summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-bus-iio11
-rw-r--r--Documentation/ABI/testing/sysfs-class-mic.txt147
-rw-r--r--Documentation/ABI/testing/sysfs-driver-sunxi-sid22
-rw-r--r--Documentation/RCU/checklist.txt4
-rw-r--r--Documentation/RCU/stallwarn.txt22
-rw-r--r--Documentation/block/blockconsole.txt94
-rwxr-xr-xDocumentation/block/blockconsole/bcon_tail82
-rwxr-xr-xDocumentation/block/blockconsole/mkblockconsole29
-rw-r--r--Documentation/devices.txt1
-rw-r--r--Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt3
-rw-r--r--Documentation/devicetree/bindings/arm/cci.txt60
-rw-r--r--Documentation/devicetree/bindings/arm/vic.txt12
-rw-r--r--Documentation/devicetree/bindings/clock/imx6q-clock.txt1
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt52
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt71
-rw-r--r--Documentation/devicetree/bindings/iio/light/gp2ap020a00f.txt21
-rw-r--r--Documentation/devicetree/bindings/leds/leds-lp55xx.txt10
-rw-r--r--Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt17
-rw-r--r--Documentation/devicetree/bindings/misc/ti,dac7512.txt20
-rw-r--r--Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt9
-rw-r--r--Documentation/devicetree/bindings/mmc/tmio_mmc.txt17
-rw-r--r--Documentation/devicetree/bindings/net/cpsw-phy-sel.txt28
-rw-r--r--Documentation/devicetree/bindings/pci/mvebu-pci.txt10
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt859
-rw-r--r--Documentation/devicetree/bindings/regulator/as3722-regulator.txt91
-rw-r--r--Documentation/devicetree/bindings/regulator/palmas-pmic.txt12
-rw-r--r--Documentation/devicetree/bindings/regulator/regulator.txt5
-rw-r--r--Documentation/devicetree/bindings/serial/qca,ar9330-uart.txt (renamed from Documentation/devicetree/bindings/tty/serial/qca,ar9330-uart.txt)0
-rw-r--r--Documentation/devicetree/bindings/sound/tlv320aic3x.txt26
-rw-r--r--Documentation/devicetree/bindings/tty/serial/renesas,sci-serial.txt53
-rw-r--r--Documentation/devicetree/bindings/video/atmel,lcdc.txt75
-rw-r--r--Documentation/driver-model/devres.txt4
-rw-r--r--Documentation/filesystems/Locking6
-rw-r--r--Documentation/filesystems/caching/netfs-api.txt73
-rw-r--r--Documentation/filesystems/vfs.txt12
-rw-r--r--Documentation/kernel-per-CPU-kthreads.txt17
-rw-r--r--Documentation/mic/mic_overview.txt49
-rw-r--r--Documentation/mic/mpssd/.gitignore1
-rw-r--r--Documentation/mic/mpssd/Makefile19
-rwxr-xr-xDocumentation/mic/mpssd/micctrl173
-rwxr-xr-xDocumentation/mic/mpssd/mpss202
-rw-r--r--Documentation/mic/mpssd/mpssd.c1701
-rw-r--r--Documentation/mic/mpssd/mpssd.h100
-rw-r--r--Documentation/mic/mpssd/sysfs.c102
-rw-r--r--Documentation/networking/netconsole.txt16
-rw-r--r--Documentation/pps/pps.txt15
-rw-r--r--Documentation/ptp/testptp.c65
-rw-r--r--Documentation/s390/s390dbf.txt10
-rw-r--r--Documentation/scheduler/sched-arch.txt5
-rw-r--r--Documentation/sound/alsa/soc/DPCM.txt380
-rw-r--r--Documentation/sound/alsa/soc/codec.txt46
-rw-r--r--Documentation/sound/alsa/soc/dapm.txt71
-rw-r--r--Documentation/sound/alsa/soc/machine.txt6
-rw-r--r--Documentation/sound/alsa/soc/platform.txt19
-rw-r--r--Documentation/virtual/kvm/cpuid.txt7
-rw-r--r--Documentation/virtual/kvm/locking.txt11
-rw-r--r--MAINTAINERS104
-rw-r--r--arch/alpha/include/asm/Kbuild1
-rw-r--r--arch/arc/include/asm/Kbuild1
-rw-r--r--arch/arm/Kconfig55
-rw-r--r--arch/arm/Kconfig.debug8
-rw-r--r--arch/arm/Makefile1
-rw-r--r--arch/arm/arm-soc-for-next-contents.txt13
-rw-r--r--arch/arm/boot/compressed/Makefile4
-rw-r--r--arch/arm/boot/compressed/head-shark.S140
-rw-r--r--arch/arm/boot/compressed/ofw-shark.c260
-rw-r--r--arch/arm/boot/dts/Makefile5
-rw-r--r--arch/arm/boot/dts/am33xx.dtsi6
-rw-r--r--arch/arm/boot/dts/armada-370-xp.dtsi3
-rw-r--r--arch/arm/boot/dts/armada-370.dtsi9
-rw-r--r--arch/arm/boot/dts/armada-xp-mv78230.dtsi1
-rw-r--r--arch/arm/boot/dts/armada-xp-mv78260.dtsi1
-rw-r--r--arch/arm/boot/dts/armada-xp-mv78460.dtsi1
-rw-r--r--arch/arm/boot/dts/armada-xp.dtsi21
-rw-r--r--arch/arm/boot/dts/at91sam9x5.dtsi6
-rw-r--r--arch/arm/boot/dts/dove-cm-a510.dts2
-rw-r--r--arch/arm/boot/dts/dove-cubox.dts2
-rw-r--r--arch/arm/boot/dts/dove-d2plug.dts2
-rw-r--r--arch/arm/boot/dts/dove-d3plug.dts103
-rw-r--r--arch/arm/boot/dts/dove-dove-db.dts2
-rw-r--r--arch/arm/boot/dts/dove.dtsi1009
-rw-r--r--arch/arm/boot/dts/imx23-evk.dts16
-rw-r--r--arch/arm/boot/dts/imx23-olinuxino.dts18
-rw-r--r--arch/arm/boot/dts/imx23-pinfunc.h333
-rw-r--r--arch/arm/boot/dts/imx23-stmp378x_devb.dts12
-rw-r--r--arch/arm/boot/dts/imx23.dtsi221
-rw-r--r--arch/arm/boot/dts/imx28-apf28.dts2
-rw-r--r--arch/arm/boot/dts/imx28-apf28dev.dts36
-rw-r--r--arch/arm/boot/dts/imx28-apx4devkit.dts60
-rw-r--r--arch/arm/boot/dts/imx28-cfa10036.dts26
-rw-r--r--arch/arm/boot/dts/imx28-cfa10037.dts18
-rw-r--r--arch/arm/boot/dts/imx28-cfa10049.dts156
-rw-r--r--arch/arm/boot/dts/imx28-cfa10055.dts80
-rw-r--r--arch/arm/boot/dts/imx28-cfa10056.dts38
-rw-r--r--arch/arm/boot/dts/imx28-cfa10057.dts66
-rw-r--r--arch/arm/boot/dts/imx28-cfa10058.dts24
-rw-r--r--arch/arm/boot/dts/imx28-evk.dts59
-rw-r--r--arch/arm/boot/dts/imx28-m28evk.dts28
-rw-r--r--arch/arm/boot/dts/imx28-pinfunc.h506
-rw-r--r--arch/arm/boot/dts/imx28-sps1.dts14
-rw-r--r--arch/arm/boot/dts/imx28-tx28.dts703
-rw-r--r--arch/arm/boot/dts/imx28.dtsi589
-rw-r--r--arch/arm/boot/dts/imx51-babbage.dts4
-rw-r--r--arch/arm/boot/dts/imx51.dtsi23
-rw-r--r--arch/arm/boot/dts/imx53-qsb.dts3
-rw-r--r--arch/arm/boot/dts/imx6q-pinfunc.h4
-rw-r--r--arch/arm/boot/dts/imx6q-sabrelite.dts103
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabreauto.dtsi5
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabresd.dtsi2
-rw-r--r--arch/arm/boot/dts/imx6qdl-wandboard.dtsi21
-rw-r--r--arch/arm/boot/dts/imx6qdl.dtsi51
-rw-r--r--arch/arm/boot/dts/imx6sl-evk.dts39
-rw-r--r--arch/arm/boot/dts/imx6sl.dtsi84
-rw-r--r--arch/arm/boot/dts/kirkwood.dtsi3
-rw-r--r--arch/arm/boot/dts/mxs-pinfunc.h31
-rw-r--r--arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts72
-rw-r--r--arch/arm/boot/dts/r8a73a4.dtsi6
-rw-r--r--arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts19
-rw-r--r--arch/arm/boot/dts/r8a7778.dtsi1
-rw-r--r--arch/arm/boot/dts/r8a7779.dtsi1
-rw-r--r--arch/arm/boot/dts/r8a7790.dtsi58
-rw-r--r--arch/arm/boot/dts/r8a7791-koelsch.dts32
-rw-r--r--arch/arm/boot/dts/r8a7791.dtsi41
-rw-r--r--arch/arm/boot/dts/s3c6400.dtsi41
-rw-r--r--arch/arm/boot/dts/s3c6410-mini6410.dts228
-rw-r--r--arch/arm/boot/dts/s3c6410-smdk6410.dts103
-rw-r--r--arch/arm/boot/dts/s3c6410.dtsi57
-rw-r--r--arch/arm/boot/dts/s3c64xx-pinctrl.dtsi687
-rw-r--r--arch/arm/boot/dts/s3c64xx.dtsi199
-rw-r--r--arch/arm/boot/dts/sh73a0.dtsi6
-rw-r--r--arch/arm/boot/dts/ste-nomadik-stn8815.dtsi12
-rw-r--r--arch/arm/boot/dts/tegra114-dalmore.dts22
-rw-r--r--arch/arm/boot/dts/vf610-cosmic.dts47
-rw-r--r--arch/arm/boot/dts/vf610-twr.dts17
-rw-r--r--arch/arm/boot/dts/vf610.dtsi12
-rw-r--r--arch/arm/common/Makefile3
-rw-r--r--arch/arm/common/bL_switcher.c606
-rw-r--r--arch/arm/common/bL_switcher_dummy_if.c71
-rw-r--r--arch/arm/common/via82c505.c83
-rw-r--r--arch/arm/configs/bockw_defconfig4
-rw-r--r--arch/arm/configs/koelsch_defconfig54
-rw-r--r--arch/arm/configs/lager_defconfig2
-rw-r--r--arch/arm/configs/marzen_defconfig2
-rw-r--r--arch/arm/configs/shark_defconfig80
-rw-r--r--arch/arm/configs/tegra_defconfig4
-rw-r--r--arch/arm/crypto/aes-armv4.S6
-rw-r--r--arch/arm/include/asm/Kbuild1
-rw-r--r--arch/arm/include/asm/bL_switcher.h17
-rw-r--r--arch/arm/include/asm/hardware/iop3xx-gpio.h75
-rw-r--r--arch/arm/include/asm/hardware/iop3xx.h12
-rw-r--r--arch/arm/include/asm/mach/pci.h4
-rw-r--r--arch/arm/include/asm/uaccess.h7
-rw-r--r--arch/arm/include/debug/vf.S26
-rw-r--r--arch/arm/kernel/entry-common.S4
-rw-r--r--arch/arm/kernel/sleep.S26
-rw-r--r--arch/arm/kernel/suspend.c8
-rw-r--r--arch/arm/lib/Makefile1
-rw-r--r--arch/arm/lib/io-shark.c13
-rw-r--r--arch/arm/mach-at91/at91rm9200_time.c2
-rw-r--r--arch/arm/mach-at91/at91sam9261_devices.c6
-rw-r--r--arch/arm/mach-at91/at91sam9263_devices.c6
-rw-r--r--arch/arm/mach-at91/at91sam926x_time.c2
-rw-r--r--arch/arm/mach-at91/at91sam9g45_devices.c6
-rw-r--r--arch/arm/mach-at91/at91sam9rl_devices.c6
-rw-r--r--arch/arm/mach-at91/at91x40_time.c2
-rw-r--r--arch/arm/mach-at91/board-sam9261ek.c10
-rw-r--r--arch/arm/mach-at91/board-sam9263ek.c6
-rw-r--r--arch/arm/mach-at91/board-sam9m10g45ek.c4
-rw-r--r--arch/arm/mach-at91/board-sam9rlek.c6
-rw-r--r--arch/arm/mach-at91/board.h4
-rw-r--r--arch/arm/mach-davinci/board-dm365-evm.c2
-rw-r--r--arch/arm/mach-davinci/include/mach/serial.h4
-rw-r--r--arch/arm/mach-dove/board-dt.c39
-rw-r--r--arch/arm/mach-ep93xx/Kconfig1
-rw-r--r--arch/arm/mach-ep93xx/core.c108
-rw-r--r--arch/arm/mach-ep93xx/include/mach/platform.h3
-rw-r--r--arch/arm/mach-exynos/common.c11
-rw-r--r--arch/arm/mach-exynos/common.h1
-rw-r--r--arch/arm/mach-exynos/cpuidle.c14
-rw-r--r--arch/arm/mach-exynos/mach-exynos4-dt.c2
-rw-r--r--arch/arm/mach-exynos/mach-exynos5-dt.c2
-rw-r--r--arch/arm/mach-imx/Kconfig2
-rw-r--r--arch/arm/mach-imx/clk-imx6q.c9
-rw-r--r--arch/arm/mach-imx/epit.c2
-rw-r--r--arch/arm/mach-imx/mach-armadillo5x0.c3
-rw-r--r--arch/arm/mach-imx/mach-imx6sl.c21
-rw-r--r--arch/arm/mach-imx/mach-mx31_3ds.c2
-rw-r--r--arch/arm/mach-imx/mach-pcm037.c3
-rw-r--r--arch/arm/mach-imx/mx31lilly-db.c3
-rw-r--r--arch/arm/mach-imx/time.c2
-rw-r--r--arch/arm/mach-integrator/pci_v3.h7
-rw-r--r--arch/arm/mach-iop32x/em7210.c2
-rw-r--r--arch/arm/mach-iop32x/glantank.c2
-rw-r--r--arch/arm/mach-iop32x/gpio-iop32x.h10
-rw-r--r--arch/arm/mach-iop32x/include/mach/gpio.h6
-rw-r--r--arch/arm/mach-iop32x/include/mach/iop32x.h1
-rw-r--r--arch/arm/mach-iop32x/iq31244.c2
-rw-r--r--arch/arm/mach-iop32x/iq80321.c2
-rw-r--r--arch/arm/mach-iop32x/n2100.c47
-rw-r--r--arch/arm/mach-iop33x/include/mach/gpio.h6
-rw-r--r--arch/arm/mach-iop33x/include/mach/iop33x.h1
-rw-r--r--arch/arm/mach-iop33x/iq80331.c7
-rw-r--r--arch/arm/mach-iop33x/iq80332.c7
-rw-r--r--arch/arm/mach-mmp/ttc_dkb.c4
-rw-r--r--arch/arm/mach-mvebu/coherency.c8
-rw-r--r--arch/arm/mach-mvebu/pmsu.c1
-rw-r--r--arch/arm/mach-mvebu/system-controller.c1
-rw-r--r--arch/arm/mach-nomadik/cpu-8815.c35
-rw-r--r--arch/arm/mach-s3c64xx/Kconfig16
-rw-r--r--arch/arm/mach-s3c64xx/Makefile3
-rw-r--r--arch/arm/mach-s3c64xx/clock.c1007
-rw-r--r--arch/arm/mach-s3c64xx/common.c33
-rw-r--r--arch/arm/mach-s3c64xx/common.h12
-rw-r--r--arch/arm/mach-s3c64xx/dma.c13
-rw-r--r--arch/arm/mach-s3c64xx/include/mach/regs-clock.h132
-rw-r--r--arch/arm/mach-s3c64xx/irq-pm.c9
-rw-r--r--arch/arm/mach-s3c64xx/mach-anw6410.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-crag6410.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-hmt.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-mini6410.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-ncp.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c85
-rw-r--r--arch/arm/mach-s3c64xx/mach-smartq.c11
-rw-r--r--arch/arm/mach-s3c64xx/mach-smdk6400.c2
-rw-r--r--arch/arm/mach-s3c64xx/mach-smdk6410.c2
-rw-r--r--arch/arm/mach-s3c64xx/pm.c21
-rw-r--r--arch/arm/mach-s3c64xx/s3c6400.c15
-rw-r--r--arch/arm/mach-s3c64xx/s3c6410.c16
-rw-r--r--arch/arm/mach-shark/Makefile10
-rw-r--r--arch/arm/mach-shark/Makefile.boot2
-rw-r--r--arch/arm/mach-shark/core.c146
-rw-r--r--arch/arm/mach-shark/dma.c23
-rw-r--r--arch/arm/mach-shark/include/mach/debug-macro.S34
-rw-r--r--arch/arm/mach-shark/include/mach/entry-macro.S36
-rw-r--r--arch/arm/mach-shark/include/mach/framebuffer.h16
-rw-r--r--arch/arm/mach-shark/include/mach/hardware.h16
-rw-r--r--arch/arm/mach-shark/include/mach/irqs.h13
-rw-r--r--arch/arm/mach-shark/include/mach/isa-dma.h13
-rw-r--r--arch/arm/mach-shark/include/mach/memory.h26
-rw-r--r--arch/arm/mach-shark/include/mach/timex.h7
-rw-r--r--arch/arm/mach-shark/include/mach/uncompress.h50
-rw-r--r--arch/arm/mach-shark/irq.c108
-rw-r--r--arch/arm/mach-shark/leds.c117
-rw-r--r--arch/arm/mach-shark/pci.c57
-rw-r--r--arch/arm/mach-shmobile/Kconfig13
-rw-r--r--arch/arm/mach-shmobile/Makefile4
-rw-r--r--arch/arm/mach-shmobile/Makefile.boot1
-rw-r--r--arch/arm/mach-shmobile/board-ape6evm-reference.c2
-rw-r--r--arch/arm/mach-shmobile/board-ape6evm.c57
-rw-r--r--arch/arm/mach-shmobile/board-armadillo800eva.c5
-rw-r--r--arch/arm/mach-shmobile/board-bockw.c370
-rw-r--r--arch/arm/mach-shmobile/board-koelsch.c44
-rw-r--r--arch/arm/mach-shmobile/board-kzm9g.c1
-rw-r--r--arch/arm/mach-shmobile/board-lager-reference.c3
-rw-r--r--arch/arm/mach-shmobile/board-lager.c112
-rw-r--r--arch/arm/mach-shmobile/board-marzen.c72
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7778.c44
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7779.c2
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7790.c12
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7791.c237
-rw-r--r--arch/arm/mach-shmobile/headsmp.S3
-rw-r--r--arch/arm/mach-shmobile/include/mach/common.h12
-rw-r--r--arch/arm/mach-shmobile/include/mach/r8a73a4.h2
-rw-r--r--arch/arm/mach-shmobile/include/mach/r8a7778.h2
-rw-r--r--arch/arm/mach-shmobile/include/mach/r8a7790.h3
-rw-r--r--arch/arm/mach-shmobile/include/mach/r8a7791.h8
-rw-r--r--arch/arm/mach-shmobile/platsmp-apmu.c195
-rw-r--r--arch/arm/mach-shmobile/platsmp-scu.c30
-rw-r--r--arch/arm/mach-shmobile/platsmp.c22
-rw-r--r--arch/arm/mach-shmobile/setup-r8a73a4.c4
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7778.c37
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7790.c26
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7791.c149
-rw-r--r--arch/arm/mach-shmobile/smp-emev2.c6
-rw-r--r--arch/arm/mach-shmobile/smp-r8a7779.c4
-rw-r--r--arch/arm/mach-shmobile/smp-r8a7790.c67
-rw-r--r--arch/arm/mach-shmobile/smp-sh73a0.c14
-rw-r--r--arch/arm/mach-tegra/Makefile1
-rw-r--r--arch/arm/mach-tegra/board-paz00.c5
-rw-r--r--arch/arm/mach-tegra/board-paz00.h25
-rw-r--r--arch/arm/mach-tegra/board.h12
-rw-r--r--arch/arm/mach-tegra/common.c115
-rw-r--r--arch/arm/mach-tegra/fuse.c66
-rw-r--r--arch/arm/mach-tegra/gpio-names.h247
-rw-r--r--arch/arm/mach-tegra/iomap.h152
-rw-r--r--arch/arm/mach-tegra/irammap.h6
-rw-r--r--arch/arm/mach-tegra/pm.c8
-rw-r--r--arch/arm/mach-tegra/pm.h3
-rw-r--r--arch/arm/mach-tegra/pmc.c50
-rw-r--r--arch/arm/mach-tegra/pmc.h5
-rw-r--r--arch/arm/mach-tegra/reset.c2
-rw-r--r--arch/arm/mach-tegra/sleep-tegra20.S5
-rw-r--r--arch/arm/mach-tegra/sleep-tegra30.S5
-rw-r--r--arch/arm/mach-tegra/tegra.c79
-rw-r--r--arch/arm/mm/mmap.c6
-rw-r--r--arch/arm/plat-iop/Makefile2
-rw-r--r--arch/arm/plat-samsung/include/plat/cpu.h4
-rw-r--r--arch/arm/plat-samsung/include/plat/uncompress.h2
-rw-r--r--arch/arm/plat-samsung/init.c12
-rw-r--r--arch/arm64/include/asm/Kbuild1
-rw-r--r--arch/arm64/include/asm/uaccess.h10
-rw-r--r--arch/arm64/mm/tlb.S2
-rw-r--r--arch/avr32/boards/atngw100/evklcd10x.c8
-rw-r--r--arch/avr32/boards/atngw100/mrmt.c4
-rw-r--r--arch/avr32/boards/atstk1000/atstk1000.h2
-rw-r--r--arch/avr32/boards/atstk1000/setup.c2
-rw-r--r--arch/avr32/boards/favr-32/setup.c2
-rw-r--r--arch/avr32/boards/hammerhead/setup.c2
-rw-r--r--arch/avr32/boards/merisc/display.c2
-rw-r--r--arch/avr32/boards/mimc200/setup.c4
-rw-r--r--arch/avr32/include/asm/Kbuild1
-rw-r--r--arch/avr32/mach-at32ap/at32ap700x.c8
-rw-r--r--arch/avr32/mach-at32ap/include/mach/board.h4
-rw-r--r--arch/blackfin/Kconfig11
-rw-r--r--arch/blackfin/include/asm/Kbuild1
-rw-r--r--arch/blackfin/include/asm/gpio.h157
-rw-r--r--arch/blackfin/include/asm/portmux.h19
-rw-r--r--arch/blackfin/kernel/Makefile3
-rw-r--r--arch/blackfin/mach-bf548/include/mach/portmux.h2
-rw-r--r--arch/blackfin/mach-bf609/include/mach/portmux.h2
-rw-r--r--arch/c6x/Kconfig4
-rw-r--r--arch/c6x/include/asm/Kbuild1
-rw-r--r--arch/cris/include/asm/Kbuild1
-rw-r--r--arch/frv/include/asm/Kbuild1
-rw-r--r--arch/h8300/Kconfig108
-rw-r--r--arch/h8300/Kconfig.cpu171
-rw-r--r--arch/h8300/Kconfig.debug68
-rw-r--r--arch/h8300/Kconfig.ide44
-rw-r--r--arch/h8300/Makefile71
-rw-r--r--arch/h8300/README38
-rw-r--r--arch/h8300/boot/Makefile22
-rw-r--r--arch/h8300/boot/compressed/Makefile37
-rw-r--r--arch/h8300/boot/compressed/head.S47
-rw-r--r--arch/h8300/boot/compressed/misc.c180
-rw-r--r--arch/h8300/boot/compressed/vmlinux.lds32
-rw-r--r--arch/h8300/boot/compressed/vmlinux.scr9
-rw-r--r--arch/h8300/defconfig42
-rw-r--r--arch/h8300/include/asm/Kbuild8
-rw-r--r--arch/h8300/include/asm/asm-offsets.h1
-rw-r--r--arch/h8300/include/asm/atomic.h146
-rw-r--r--arch/h8300/include/asm/barrier.h29
-rw-r--r--arch/h8300/include/asm/bitops.h211
-rw-r--r--arch/h8300/include/asm/bootinfo.h2
-rw-r--r--arch/h8300/include/asm/bug.h12
-rw-r--r--arch/h8300/include/asm/bugs.h16
-rw-r--r--arch/h8300/include/asm/cache.h13
-rw-r--r--arch/h8300/include/asm/cachectl.h14
-rw-r--r--arch/h8300/include/asm/cacheflush.h40
-rw-r--r--arch/h8300/include/asm/checksum.h102
-rw-r--r--arch/h8300/include/asm/cmpxchg.h60
-rw-r--r--arch/h8300/include/asm/cputime.h6
-rw-r--r--arch/h8300/include/asm/current.h25
-rw-r--r--arch/h8300/include/asm/dbg.h2
-rw-r--r--arch/h8300/include/asm/delay.h38
-rw-r--r--arch/h8300/include/asm/device.h7
-rw-r--r--arch/h8300/include/asm/div64.h1
-rw-r--r--arch/h8300/include/asm/dma.h15
-rw-r--r--arch/h8300/include/asm/elf.h101
-rw-r--r--arch/h8300/include/asm/emergency-restart.h6
-rw-r--r--arch/h8300/include/asm/fb.h12
-rw-r--r--arch/h8300/include/asm/flat.h26
-rw-r--r--arch/h8300/include/asm/fpu.h1
-rw-r--r--arch/h8300/include/asm/ftrace.h1
-rw-r--r--arch/h8300/include/asm/futex.h6
-rw-r--r--arch/h8300/include/asm/gpio-internal.h52
-rw-r--r--arch/h8300/include/asm/hardirq.h19
-rw-r--r--arch/h8300/include/asm/hw_irq.h1
-rw-r--r--arch/h8300/include/asm/io.h358
-rw-r--r--arch/h8300/include/asm/irq.h49
-rw-r--r--arch/h8300/include/asm/irq_regs.h1
-rw-r--r--arch/h8300/include/asm/irqflags.h43
-rw-r--r--arch/h8300/include/asm/kdebug.h1
-rw-r--r--arch/h8300/include/asm/kmap_types.h6
-rw-r--r--arch/h8300/include/asm/local.h6
-rw-r--r--arch/h8300/include/asm/local64.h1
-rw-r--r--arch/h8300/include/asm/mc146818rtc.h9
-rw-r--r--arch/h8300/include/asm/mmu_context.h32
-rw-r--r--arch/h8300/include/asm/mutex.h9
-rw-r--r--arch/h8300/include/asm/page.h78
-rw-r--r--arch/h8300/include/asm/page_offset.h3
-rw-r--r--arch/h8300/include/asm/param.h9
-rw-r--r--arch/h8300/include/asm/pci.h19
-rw-r--r--arch/h8300/include/asm/percpu.h6
-rw-r--r--arch/h8300/include/asm/pgalloc.h8
-rw-r--r--arch/h8300/include/asm/pgtable.h73
-rw-r--r--arch/h8300/include/asm/processor.h139
-rw-r--r--arch/h8300/include/asm/ptrace.h33
-rw-r--r--arch/h8300/include/asm/regs267x.h336
-rw-r--r--arch/h8300/include/asm/regs306x.h212
-rw-r--r--arch/h8300/include/asm/scatterlist.h6
-rw-r--r--arch/h8300/include/asm/sections.h6
-rw-r--r--arch/h8300/include/asm/segment.h49
-rw-r--r--arch/h8300/include/asm/sh_bios.h29
-rw-r--r--arch/h8300/include/asm/shm.h31
-rw-r--r--arch/h8300/include/asm/shmparam.h6
-rw-r--r--arch/h8300/include/asm/signal.h24
-rw-r--r--arch/h8300/include/asm/smp.h1
-rw-r--r--arch/h8300/include/asm/spinlock.h6
-rw-r--r--arch/h8300/include/asm/string.h44
-rw-r--r--arch/h8300/include/asm/switch_to.h50
-rw-r--r--arch/h8300/include/asm/target_time.h4
-rw-r--r--arch/h8300/include/asm/termios.h50
-rw-r--r--arch/h8300/include/asm/thread_info.h103
-rw-r--r--arch/h8300/include/asm/timer.h25
-rw-r--r--arch/h8300/include/asm/timex.h19
-rw-r--r--arch/h8300/include/asm/tlb.h8
-rw-r--r--arch/h8300/include/asm/tlbflush.h55
-rw-r--r--arch/h8300/include/asm/topology.h6
-rw-r--r--arch/h8300/include/asm/traps.h37
-rw-r--r--arch/h8300/include/asm/types.h9
-rw-r--r--arch/h8300/include/asm/uaccess.h163
-rw-r--r--arch/h8300/include/asm/ucontext.h12
-rw-r--r--arch/h8300/include/asm/unaligned.h11
-rw-r--r--arch/h8300/include/asm/unistd.h36
-rw-r--r--arch/h8300/include/asm/user.h75
-rw-r--r--arch/h8300/include/asm/virtconvert.h20
-rw-r--r--arch/h8300/include/uapi/asm/Kbuild34
-rw-r--r--arch/h8300/include/uapi/asm/auxvec.h4
-rw-r--r--arch/h8300/include/uapi/asm/bitsperlong.h1
-rw-r--r--arch/h8300/include/uapi/asm/byteorder.h6
-rw-r--r--arch/h8300/include/uapi/asm/errno.h6
-rw-r--r--arch/h8300/include/uapi/asm/fcntl.h11
-rw-r--r--arch/h8300/include/uapi/asm/ioctl.h1
-rw-r--r--arch/h8300/include/uapi/asm/ioctls.h8
-rw-r--r--arch/h8300/include/uapi/asm/ipcbuf.h1
-rw-r--r--arch/h8300/include/uapi/asm/kvm_para.h1
-rw-r--r--arch/h8300/include/uapi/asm/mman.h1
-rw-r--r--arch/h8300/include/uapi/asm/msgbuf.h31
-rw-r--r--arch/h8300/include/uapi/asm/param.h16
-rw-r--r--arch/h8300/include/uapi/asm/poll.h11
-rw-r--r--arch/h8300/include/uapi/asm/posix_types.h26
-rw-r--r--arch/h8300/include/uapi/asm/ptrace.h44
-rw-r--r--arch/h8300/include/uapi/asm/resource.h6
-rw-r--r--arch/h8300/include/uapi/asm/sembuf.h25
-rw-r--r--arch/h8300/include/uapi/asm/setup.h6
-rw-r--r--arch/h8300/include/uapi/asm/shmbuf.h42
-rw-r--r--arch/h8300/include/uapi/asm/sigcontext.h18
-rw-r--r--arch/h8300/include/uapi/asm/siginfo.h6
-rw-r--r--arch/h8300/include/uapi/asm/signal.h115
-rw-r--r--arch/h8300/include/uapi/asm/socket.h79
-rw-r--r--arch/h8300/include/uapi/asm/sockios.h13
-rw-r--r--arch/h8300/include/uapi/asm/stat.h78
-rw-r--r--arch/h8300/include/uapi/asm/statfs.h6
-rw-r--r--arch/h8300/include/uapi/asm/swab.h10
-rw-r--r--arch/h8300/include/uapi/asm/termbits.h201
-rw-r--r--arch/h8300/include/uapi/asm/termios.h44
-rw-r--r--arch/h8300/include/uapi/asm/types.h1
-rw-r--r--arch/h8300/include/uapi/asm/unistd.h330
-rw-r--r--arch/h8300/kernel/Makefile12
-rw-r--r--arch/h8300/kernel/asm-offsets.c60
-rw-r--r--arch/h8300/kernel/entry.S402
-rw-r--r--arch/h8300/kernel/gpio.c178
-rw-r--r--arch/h8300/kernel/h8300_ksyms.c100
-rw-r--r--arch/h8300/kernel/irq.c165
-rw-r--r--arch/h8300/kernel/module.c75
-rw-r--r--arch/h8300/kernel/process.c154
-rw-r--r--arch/h8300/kernel/ptrace.c168
-rw-r--r--arch/h8300/kernel/setup.c242
-rw-r--r--arch/h8300/kernel/signal.c444
-rw-r--r--arch/h8300/kernel/sys_h8300.c48
-rw-r--r--arch/h8300/kernel/syscalls.S338
-rw-r--r--arch/h8300/kernel/time.c66
-rw-r--r--arch/h8300/kernel/timer/Makefile6
-rw-r--r--arch/h8300/kernel/timer/itu.c82
-rw-r--r--arch/h8300/kernel/timer/timer16.c77
-rw-r--r--arch/h8300/kernel/timer/timer8.c102
-rw-r--r--arch/h8300/kernel/timer/tpu.c100
-rw-r--r--arch/h8300/kernel/traps.c166
-rw-r--r--arch/h8300/kernel/vmlinux.lds.S157
-rw-r--r--arch/h8300/lib/Makefile5
-rw-r--r--arch/h8300/lib/abs.S21
-rw-r--r--arch/h8300/lib/ashrdi3.c63
-rw-r--r--arch/h8300/lib/checksum.c164
-rw-r--r--arch/h8300/lib/memcpy.S84
-rw-r--r--arch/h8300/lib/memset.S61
-rw-r--r--arch/h8300/lib/romfs.S57
-rw-r--r--arch/h8300/mm/Makefile5
-rw-r--r--arch/h8300/mm/fault.c56
-rw-r--r--arch/h8300/mm/init.c155
-rw-r--r--arch/h8300/mm/kmap.c58
-rw-r--r--arch/h8300/mm/memory.c54
-rw-r--r--arch/h8300/platform/h8300h/Makefile7
-rw-r--r--arch/h8300/platform/h8300h/aki3068net/Makefile5
-rw-r--r--arch/h8300/platform/h8300h/aki3068net/crt0_ram.S110
-rw-r--r--arch/h8300/platform/h8300h/generic/Makefile5
-rw-r--r--arch/h8300/platform/h8300h/generic/crt0_ram.S107
-rw-r--r--arch/h8300/platform/h8300h/generic/crt0_rom.S122
-rw-r--r--arch/h8300/platform/h8300h/h8max/Makefile5
-rw-r--r--arch/h8300/platform/h8300h/h8max/crt0_ram.S110
-rw-r--r--arch/h8300/platform/h8300h/irq.c82
-rw-r--r--arch/h8300/platform/h8300h/ptrace_h8300h.c284
-rw-r--r--arch/h8300/platform/h8s/Makefile7
-rw-r--r--arch/h8300/platform/h8s/edosk2674/Makefile5
-rw-r--r--arch/h8300/platform/h8s/edosk2674/crt0_ram.S130
-rw-r--r--arch/h8300/platform/h8s/edosk2674/crt0_rom.S186
-rw-r--r--arch/h8300/platform/h8s/generic/Makefile5
-rw-r--r--arch/h8300/platform/h8s/generic/crt0_ram.S127
-rw-r--r--arch/h8300/platform/h8s/generic/crt0_rom.S128
-rw-r--r--arch/h8300/platform/h8s/irq.c104
-rw-r--r--arch/h8300/platform/h8s/ptrace_h8s.c84
-rw-r--r--arch/hexagon/include/asm/Kbuild1
-rw-r--r--arch/ia64/include/asm/Kbuild1
-rw-r--r--arch/ia64/kernel/acpi.c38
-rw-r--r--arch/m32r/include/asm/Kbuild1
-rw-r--r--arch/m68k/include/asm/Kbuild1
-rw-r--r--arch/m68k/include/asm/floppy.h2
-rw-r--r--arch/m68k/include/asm/sun3xflop.h2
-rw-r--r--arch/m68k/include/asm/uaccess.h7
-rw-r--r--arch/m68k/platform/68000/timers.c2
-rw-r--r--arch/m68k/platform/68360/config.c2
-rw-r--r--arch/m68k/platform/coldfire/pit.c2
-rw-r--r--arch/m68k/platform/coldfire/sltimers.c4
-rw-r--r--arch/m68k/platform/coldfire/timers.c4
-rw-r--r--arch/metag/include/asm/Kbuild1
-rw-r--r--arch/metag/include/asm/topology.h2
-rw-r--r--arch/microblaze/include/asm/Kbuild1
-rw-r--r--arch/mips/Kbuild.platforms1
-rw-r--r--arch/mips/Kconfig27
-rw-r--r--arch/mips/Kconfig.debug8
-rw-r--r--arch/mips/Makefile14
-rw-r--r--arch/mips/alchemy/devboards/db1235.c2
-rw-r--r--arch/mips/ath79/dev-common.c6
-rw-r--r--arch/mips/bcm47xx/Makefile1
-rw-r--r--arch/mips/bcm47xx/board.c309
-rw-r--r--arch/mips/bcm47xx/nvram.c20
-rw-r--r--arch/mips/bcm47xx/prom.c27
-rw-r--r--arch/mips/bcm47xx/setup.c2
-rw-r--r--arch/mips/bcm47xx/time.c23
-rw-r--r--arch/mips/boot/compressed/Makefile6
-rw-r--r--arch/mips/boot/compressed/decompress.c13
-rw-r--r--arch/mips/boot/compressed/ld.script5
-rw-r--r--arch/mips/cavium-octeon/setup.c4
-rw-r--r--arch/mips/cobalt/Makefile1
-rw-r--r--arch/mips/cobalt/console.c20
-rw-r--r--arch/mips/cobalt/setup.c3
-rw-r--r--arch/mips/configs/powertv_defconfig136
-rw-r--r--arch/mips/dec/int-handler.S8
-rw-r--r--arch/mips/dec/ioasic-irq.c43
-rw-r--r--arch/mips/dec/prom/call_o32.S2
-rw-r--r--arch/mips/dec/prom/init.c2
-rw-r--r--arch/mips/dec/prom/memory.c2
-rw-r--r--arch/mips/dec/setup.c4
-rw-r--r--arch/mips/include/asm/Kbuild1
-rw-r--r--arch/mips/include/asm/dec/ioasic.h2
-rw-r--r--arch/mips/include/asm/dec/ioasic_addrs.h2
-rw-r--r--arch/mips/include/asm/dec/kn01.h12
-rw-r--r--arch/mips/include/asm/dec/kn02ca.h2
-rw-r--r--arch/mips/include/asm/dec/prom.h2
-rw-r--r--arch/mips/include/asm/elf.h1
-rw-r--r--arch/mips/include/asm/mach-ath79/ar933x_uart_platform.h18
-rw-r--r--arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h110
-rw-r--r--arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h2
-rw-r--r--arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h12
-rw-r--r--arch/mips/include/asm/mach-dec/cpu-feature-overrides.h87
-rw-r--r--arch/mips/include/asm/mach-generic/dma-coherence.h10
-rw-r--r--arch/mips/include/asm/mach-ip27/dma-coherence.h10
-rw-r--r--arch/mips/include/asm/mach-ip32/dma-coherence.h11
-rw-r--r--arch/mips/include/asm/mach-jazz/dma-coherence.h10
-rw-r--r--arch/mips/include/asm/mach-loongson/dma-coherence.h10
-rw-r--r--arch/mips/include/asm/mach-powertv/asic.h120
-rw-r--r--arch/mips/include/asm/mach-powertv/asic_reg_map.h90
-rw-r--r--arch/mips/include/asm/mach-powertv/asic_regs.h125
-rw-r--r--arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h60
-rw-r--r--arch/mips/include/asm/mach-powertv/dma-coherence.h117
-rw-r--r--arch/mips/include/asm/mach-powertv/interrupts.h253
-rw-r--r--arch/mips/include/asm/mach-powertv/ioremap.h167
-rw-r--r--arch/mips/include/asm/mach-powertv/irq.h25
-rw-r--r--arch/mips/include/asm/mach-powertv/powertv-clock.h29
-rw-r--r--arch/mips/include/asm/mach-powertv/war.h27
-rw-r--r--arch/mips/include/asm/mmu_context.h22
-rw-r--r--arch/mips/include/asm/ptrace.h14
-rw-r--r--arch/mips/include/asm/setup.h8
-rw-r--r--arch/mips/include/asm/stackframe.h24
-rw-r--r--arch/mips/include/asm/syscall.h116
-rw-r--r--arch/mips/include/asm/thread_info.h42
-rw-r--r--arch/mips/include/asm/unistd.h7
-rw-r--r--arch/mips/include/uapi/asm/siginfo.h9
-rw-r--r--arch/mips/kernel/Makefile3
-rw-r--r--arch/mips/kernel/cpu-probe.c28
-rw-r--r--arch/mips/kernel/csrc-powertv.c151
-rw-r--r--arch/mips/kernel/early_printk_8250.c66
-rw-r--r--arch/mips/kernel/ftrace.c33
-rw-r--r--arch/mips/kernel/irq_cpu.c2
-rw-r--r--arch/mips/kernel/module.c3
-rw-r--r--arch/mips/kernel/ptrace.c199
-rw-r--r--arch/mips/kernel/scall32-o32.S846
-rw-r--r--arch/mips/kernel/scall64-64.S3
-rw-r--r--arch/mips/kernel/scall64-n32.S1
-rw-r--r--arch/mips/kernel/scall64-o32.S10
-rw-r--r--arch/mips/kernel/setup.c11
-rw-r--r--arch/mips/kernel/smp-bmips.c4
-rw-r--r--arch/mips/kernel/smp.c1
-rw-r--r--arch/mips/kernel/traps.c1
-rw-r--r--arch/mips/lantiq/irq.c2
-rw-r--r--arch/mips/lantiq/xway/sysctrl.c2
-rw-r--r--arch/mips/mm/c-r4k.c39
-rw-r--r--arch/mips/mm/dma-default.c4
-rw-r--r--arch/mips/mm/init.c5
-rw-r--r--arch/mips/mm/tlb-funcs.S2
-rw-r--r--arch/mips/mm/tlb-r4k.c37
-rw-r--r--arch/mips/mm/tlbex.c138
-rw-r--r--arch/mips/netlogic/common/smp.c2
-rw-r--r--arch/mips/pci/pci-ar71xx.c3
-rw-r--r--arch/mips/pci/pci-ar724x.c9
-rw-r--r--arch/mips/pci/pci.c50
-rw-r--r--arch/mips/powertv/Kconfig12
-rw-r--r--arch/mips/powertv/Makefile29
-rw-r--r--arch/mips/powertv/Platform7
-rw-r--r--arch/mips/powertv/asic/Makefile21
-rw-r--r--arch/mips/powertv/asic/asic-calliope.c101
-rw-r--r--arch/mips/powertv/asic/asic-cronus.c101
-rw-r--r--arch/mips/powertv/asic/asic-gaia.c96
-rw-r--r--arch/mips/powertv/asic/asic-zeus.c101
-rw-r--r--arch/mips/powertv/asic/asic_devices.c549
-rw-r--r--arch/mips/powertv/asic/asic_int.c125
-rw-r--r--arch/mips/powertv/asic/irq_asic.c115
-rw-r--r--arch/mips/powertv/asic/prealloc-calliope.c385
-rw-r--r--arch/mips/powertv/asic/prealloc-cronus.c340
-rw-r--r--arch/mips/powertv/asic/prealloc-cronuslite.c174
-rw-r--r--arch/mips/powertv/asic/prealloc-gaia.c589
-rw-r--r--arch/mips/powertv/asic/prealloc-zeus.c304
-rw-r--r--arch/mips/powertv/asic/prealloc.h70
-rw-r--r--arch/mips/powertv/init.c90
-rw-r--r--arch/mips/powertv/init.h28
-rw-r--r--arch/mips/powertv/ioremap.c136
-rw-r--r--arch/mips/powertv/memory.c353
-rw-r--r--arch/mips/powertv/pci/Makefile19
-rw-r--r--arch/mips/powertv/pci/fixup-powertv.c37
-rw-r--r--arch/mips/powertv/pci/powertv-pci.h31
-rw-r--r--arch/mips/powertv/powertv-clock.h26
-rw-r--r--arch/mips/powertv/powertv-usb.c404
-rw-r--r--arch/mips/powertv/powertv_setup.c319
-rw-r--r--arch/mips/powertv/reset.c35
-rw-r--r--arch/mips/powertv/reset.h26
-rw-r--r--arch/mips/powertv/time.c36
-rw-r--r--arch/mips/ralink/clk.c2
-rw-r--r--arch/mips/ralink/mt7620.c2
-rw-r--r--arch/mips/ralink/of.c2
-rw-r--r--arch/mips/ralink/rt305x.c2
-rw-r--r--arch/mn10300/include/asm/Kbuild1
-rw-r--r--arch/openrisc/include/asm/Kbuild1
-rw-r--r--arch/parisc/configs/generic-32bit_defconfig340
-rw-r--r--arch/parisc/configs/generic-64bit_defconfig350
-rw-r--r--arch/parisc/include/asm/Kbuild1
-rw-r--r--arch/powerpc/include/asm/Kbuild1
-rw-r--r--arch/powerpc/kernel/eeh.c3
-rw-r--r--arch/powerpc/kernel/ibmebus.c14
-rw-r--r--arch/powerpc/kernel/vio.c66
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c2
-rw-r--r--arch/s390/Kconfig1
-rw-r--r--arch/s390/Makefile14
-rw-r--r--arch/s390/include/asm/Kbuild1
-rw-r--r--arch/s390/include/asm/atomic.h186
-rw-r--r--arch/s390/include/asm/bitops.h1008
-rw-r--r--arch/s390/include/asm/debug.h5
-rw-r--r--arch/s390/include/asm/dis.h52
-rw-r--r--arch/s390/include/asm/kvm_host.h1
-rw-r--r--arch/s390/include/asm/mmu_context.h10
-rw-r--r--arch/s390/include/asm/processor.h13
-rw-r--r--arch/s390/include/asm/ptrace.h7
-rw-r--r--arch/s390/include/asm/setup.h7
-rw-r--r--arch/s390/include/asm/uaccess.h18
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/bitmap.c54
-rw-r--r--arch/s390/kernel/compat_signal.c8
-rw-r--r--arch/s390/kernel/dis.c81
-rw-r--r--arch/s390/kernel/dumpstack.c1
-rw-r--r--arch/s390/kernel/head.S2
-rw-r--r--arch/s390/kernel/ipl.c4
-rw-r--r--arch/s390/kernel/kprobes.c19
-rw-r--r--arch/s390/kernel/process.c2
-rw-r--r--arch/s390/kernel/ptrace.c4
-rw-r--r--arch/s390/kernel/runtime_instr.c2
-rw-r--r--arch/s390/kernel/setup.c59
-rw-r--r--arch/s390/kernel/signal.c12
-rw-r--r--arch/s390/kernel/smp.c6
-rw-r--r--arch/s390/kernel/vdso.c9
-rw-r--r--arch/s390/kernel/vtime.c2
-rw-r--r--arch/s390/kvm/diag.c4
-rw-r--r--arch/s390/kvm/gaccess.h21
-rw-r--r--arch/s390/kvm/intercept.c6
-rw-r--r--arch/s390/kvm/interrupt.c3
-rw-r--r--arch/s390/kvm/kvm-s390.c91
-rw-r--r--arch/s390/kvm/kvm-s390.h9
-rw-r--r--arch/s390/kvm/priv.c61
-rw-r--r--arch/s390/kvm/trace.h1
-rw-r--r--arch/s390/lib/Makefile2
-rw-r--r--arch/s390/lib/find.c77
-rw-r--r--arch/s390/lib/uaccess_mvcos.c30
-rw-r--r--arch/s390/lib/uaccess_pt.c2
-rw-r--r--arch/s390/lib/uaccess_std.c305
-rw-r--r--arch/s390/mm/fault.c9
-rw-r--r--arch/s390/mm/pgtable.c4
-rw-r--r--arch/s390/net/bpf_jit_comp.c2
-rw-r--r--arch/score/include/asm/Kbuild1
-rw-r--r--arch/sh/boards/mach-ecovec24/setup.c1
-rw-r--r--arch/sh/include/asm/Kbuild1
-rw-r--r--arch/sh/include/asm/hw_breakpoint.h12
-rw-r--r--arch/sh/include/cpu-common/cpu/ubc.h17
-rw-r--r--arch/sh/include/cpu-sh2a/cpu/ubc.h14
-rw-r--r--arch/sh/kernel/cpu/sh2a/Makefile1
-rw-r--r--arch/sh/kernel/cpu/sh2a/ubc.c154
-rw-r--r--arch/sh/kernel/hw_breakpoint.c8
-rw-r--r--arch/sparc/include/asm/Kbuild1
-rw-r--r--arch/tile/include/asm/Kbuild1
-rw-r--r--arch/um/include/asm/Kbuild1
-rw-r--r--arch/unicore32/include/asm/Kbuild1
-rw-r--r--arch/x86/Kconfig4
-rw-r--r--arch/x86/crypto/Makefile3
-rw-r--r--arch/x86/crypto/aesni-intel_glue.c2
-rw-r--r--arch/x86/crypto/camellia_aesni_avx2_glue.c2
-rw-r--r--arch/x86/crypto/camellia_aesni_avx_glue.c2
-rw-r--r--arch/x86/crypto/cast5_avx_glue.c2
-rw-r--r--arch/x86/crypto/cast6_avx_glue.c2
-rw-r--r--arch/x86/crypto/serpent_avx2_glue.c2
-rw-r--r--arch/x86/crypto/serpent_avx_glue.c2
-rw-r--r--arch/x86/crypto/serpent_sse2_glue.c2
-rw-r--r--arch/x86/crypto/sha256_ssse3_glue.c2
-rw-r--r--arch/x86/crypto/twofish_avx_glue.c2
-rw-r--r--arch/x86/include/asm/acpi.h1
-rw-r--r--arch/x86/include/asm/atomic.h29
-rw-r--r--arch/x86/include/asm/atomic64_64.h28
-rw-r--r--arch/x86/include/asm/bitops.h24
-rw-r--r--arch/x86/include/asm/calling.h50
-rw-r--r--arch/x86/include/asm/local.h28
-rw-r--r--arch/x86/include/asm/mpspec.h2
-rw-r--r--arch/x86/include/asm/preempt.h108
-rw-r--r--arch/x86/include/asm/rmwcc.h41
-rw-r--r--arch/x86/include/asm/simd.h11
-rw-r--r--arch/x86/include/asm/thread_info.h5
-rw-r--r--arch/x86/include/asm/uaccess_64.h24
-rw-r--r--arch/x86/include/asm/uv/uv.h10
-rw-r--r--arch/x86/include/asm/uv/uv_hub.h57
-rw-r--r--arch/x86/include/asm/uv/uv_mmrs.h31
-rw-r--r--arch/x86/include/uapi/asm/msr-index.h2
-rw-r--r--arch/x86/kernel/Makefile2
-rw-r--r--arch/x86/kernel/acpi/boot.c88
-rw-r--r--arch/x86/kernel/apic/apic.c8
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c70
-rw-r--r--arch/x86/kernel/asm-offsets.c1
-rw-r--r--arch/x86/kernel/cpu/common.c5
-rw-r--r--arch/x86/kernel/cpu/perf_event.h5
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel.c77
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_ds.c135
-rw-r--r--arch/x86/kernel/entry_32.S7
-rw-r--r--arch/x86/kernel/entry_64.S4
-rw-r--r--arch/x86/kernel/i386_ksyms_32.c7
-rw-r--r--arch/x86/kernel/i8259.c3
-rw-r--r--arch/x86/kernel/irq_32.c4
-rw-r--r--arch/x86/kernel/preempt.S25
-rw-r--r--arch/x86/kernel/process.c6
-rw-r--r--arch/x86/kernel/process_32.c8
-rw-r--r--arch/x86/kernel/process_64.c8
-rw-r--r--arch/x86/kernel/reboot.c7
-rw-r--r--arch/x86/kernel/smpboot.c21
-rw-r--r--arch/x86/kernel/topology.c9
-rw-r--r--arch/x86/kernel/traps.c4
-rw-r--r--arch/x86/kernel/x8664_ksyms_64.c7
-rw-r--r--arch/x86/kvm/vmx.c30
-rw-r--r--arch/x86/mm/init.c24
-rw-r--r--arch/x86/pci/fixup.c18
-rw-r--r--arch/x86/platform/olpc/olpc-xo15-sci.c9
-rw-r--r--arch/x86/platform/uv/Makefile2
-rw-r--r--arch/x86/platform/uv/uv_nmi.c666
-rw-r--r--arch/xtensa/include/asm/Kbuild1
-rw-r--r--block/partitions/Makefile1
-rw-r--r--block/partitions/blockconsole.c22
-rw-r--r--block/partitions/check.c3
-rw-r--r--block/partitions/check.h3
-rw-r--r--crypto/Kconfig23
-rw-r--r--crypto/Makefile1
-rw-r--r--crypto/ablk_helper.c (renamed from arch/x86/crypto/ablk_helper.c)9
-rw-r--r--crypto/ansi_cprng.c4
-rw-r--r--drivers/acpi/Kconfig3
-rw-r--r--drivers/acpi/acpi_ipmi.c594
-rw-r--r--drivers/acpi/acpi_memhotplug.c2
-rw-r--r--drivers/acpi/acpi_processor.c28
-rw-r--r--drivers/acpi/acpica/acdebug.h5
-rw-r--r--drivers/acpi/acpica/acevents.h6
-rw-r--r--drivers/acpi/acpica/acglobal.h18
-rw-r--r--drivers/acpi/acpica/aclocal.h8
-rw-r--r--drivers/acpi/acpica/acnamesp.h6
-rw-r--r--drivers/acpi/acpica/evgpeutil.c2
-rw-r--r--drivers/acpi/acpica/evmisc.c14
-rw-r--r--drivers/acpi/acpica/evregion.c23
-rw-r--r--drivers/acpi/acpica/evsci.c78
-rw-r--r--drivers/acpi/acpica/evxface.c139
-rw-r--r--drivers/acpi/acpica/hwxface.c26
-rw-r--r--drivers/acpi/acpica/nsaccess.c5
-rw-r--r--drivers/acpi/acpica/nsdump.c134
-rw-r--r--drivers/acpi/acpica/nsxfeval.c8
-rw-r--r--drivers/acpi/acpica/tbinstal.c12
-rw-r--r--drivers/acpi/acpica/tbprint.c12
-rw-r--r--drivers/acpi/acpica/tbxfroot.c3
-rw-r--r--drivers/acpi/acpica/utdebug.c2
-rw-r--r--drivers/acpi/acpica/utglobal.c3
-rw-r--r--drivers/acpi/apei/apei-base.c6
-rw-r--r--drivers/acpi/bus.c18
-rw-r--r--drivers/acpi/button.c9
-rw-r--r--drivers/acpi/dock.c6
-rw-r--r--drivers/acpi/ec.c49
-rw-r--r--drivers/acpi/fan.c2
-rw-r--r--drivers/acpi/numa.c4
-rw-r--r--drivers/acpi/osl.c46
-rw-r--r--drivers/acpi/pci_root.c246
-rw-r--r--drivers/acpi/processor_core.c26
-rw-r--r--drivers/acpi/processor_idle.c61
-rw-r--r--drivers/acpi/scan.c2
-rw-r--r--drivers/acpi/sysfs.c9
-rw-r--r--drivers/ata/libahci.c7
-rw-r--r--drivers/ata/pata_isapnp.c2
-rw-r--r--drivers/base/class.c29
-rw-r--r--drivers/base/core.c22
-rw-r--r--drivers/base/cpu.c24
-rw-r--r--drivers/base/firmware_class.c38
-rw-r--r--drivers/base/platform.c17
-rw-r--r--drivers/base/regmap/internal.h3
-rw-r--r--drivers/base/regmap/regmap.c103
-rw-r--r--drivers/bcma/driver_pci.c49
-rw-r--r--drivers/block/Kconfig18
-rw-r--r--drivers/block/Makefile3
-rw-r--r--drivers/block/blockconsole.c618
-rw-r--r--drivers/block/loop.c163
-rw-r--r--drivers/block/mtip32xx/mtip32xx.c500
-rw-r--r--drivers/block/mtip32xx/mtip32xx.h18
-rw-r--r--drivers/block/rsxx/core.c8
-rw-r--r--drivers/block/rsxx/dma.c111
-rw-r--r--drivers/block/rsxx/rsxx_priv.h9
-rw-r--r--drivers/block/skd_main.c5817
-rw-r--r--drivers/block/skd_s1120.h354
-rw-r--r--drivers/block/xen-blkback/blkback.c3
-rw-r--r--drivers/block/xen-blkfront.c44
-rw-r--r--drivers/bluetooth/ath3k.c2
-rw-r--r--drivers/bluetooth/btusb.c5
-rw-r--r--drivers/bluetooth/hci_vhci.c170
-rw-r--r--drivers/bus/arm-cci.c617
-rw-r--r--drivers/bus/mvebu-mbus.c6
-rw-r--r--drivers/char/hpet.c2
-rw-r--r--drivers/char/hw_random/via-rng.c2
-rw-r--r--drivers/char/misc.c8
-rw-r--r--drivers/char/random.c459
-rw-r--r--drivers/char/raw.c4
-rw-r--r--drivers/clk/samsung/Makefile2
-rw-r--r--drivers/clocksource/em_sti.c2
-rw-r--r--drivers/cpufreq/acpi-cpufreq.c4
-rw-r--r--drivers/cpufreq/cpufreq.c3
-rw-r--r--drivers/cpufreq/exynos5440-cpufreq.c2
-rw-r--r--drivers/cpufreq/pcc-cpufreq.c5
-rw-r--r--drivers/crypto/caam/caamalg.c7
-rw-r--r--drivers/crypto/caam/caamhash.c7
-rw-r--r--drivers/crypto/caam/caamrng.c7
-rw-r--r--drivers/crypto/caam/ctrl.c400
-rw-r--r--drivers/crypto/caam/desc.h17
-rw-r--r--drivers/crypto/caam/intern.h6
-rw-r--r--drivers/crypto/caam/regs.h14
-rw-r--r--drivers/crypto/caam/sg_sw_sec4.h34
-rw-r--r--drivers/crypto/dcp.c47
-rw-r--r--drivers/crypto/mv_cesa.c10
-rw-r--r--drivers/crypto/omap-aes.c4
-rw-r--r--drivers/crypto/tegra-aes.c26
-rw-r--r--drivers/dma/Kconfig1
-rw-r--r--drivers/dma/edma.c2
-rw-r--r--drivers/dma/pl330.c10
-rw-r--r--drivers/dma/tegra20-apb-dma.c2
-rw-r--r--drivers/extcon/extcon-arizona.c35
-rw-r--r--drivers/extcon/extcon-class.c7
-rw-r--r--drivers/extcon/extcon-max77693.c129
-rw-r--r--drivers/extcon/extcon-max8997.c6
-rw-r--r--drivers/gpio/Kconfig19
-rw-r--r--drivers/gpio/Makefile2
-rw-r--r--drivers/gpio/gpio-74x164.c5
-rw-r--r--drivers/gpio/gpio-arizona.c1
-rw-r--r--drivers/gpio/gpio-bcm-kona.c640
-rw-r--r--drivers/gpio/gpio-bt8xx.c2
-rw-r--r--drivers/gpio/gpio-em.c1
-rw-r--r--drivers/gpio/gpio-iop.c (renamed from arch/arm/plat-iop/gpio.c)67
-rw-r--r--drivers/gpio/gpio-mc33880.c3
-rw-r--r--drivers/gpio/gpio-palmas.c104
-rw-r--r--drivers/gpio/gpio-pca953x.c11
-rw-r--r--drivers/gpio/gpio-pcf857x.c105
-rw-r--r--drivers/gpio/gpio-rcar.c7
-rw-r--r--drivers/gpio/gpio-samsung.c34
-rw-r--r--drivers/gpio/gpiolib-acpi.c9
-rw-r--r--drivers/gpio/gpiolib.c147
-rw-r--r--drivers/gpu/drm/drm_crtc.c103
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c8
-rw-r--r--drivers/gpu/drm/drm_drv.c1
-rw-r--r--drivers/gpu/drm/drm_edid.c193
-rw-r--r--drivers/gpu/drm/drm_ioctl.c21
-rw-r--r--drivers/gpu/drm/drm_modes.c41
-rw-r--r--drivers/gpu/drm/i915/Makefile3
-rw-r--r--drivers/gpu/drm/i915/dvo.h11
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c52
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c29
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c78
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h180
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c248
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.c50
-rw-r--r--drivers/gpu/drm/i915/i915_gem_evict.c50
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c423
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c131
-rw-r--r--drivers/gpu/drm/i915/i915_gem_stolen.c2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c6
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c35
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c133
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h493
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c8
-rw-r--r--drivers/gpu/drm/i915/i915_sysfs.c68
-rw-r--r--drivers/gpu/drm/i915/i915_trace.h62
-rw-r--r--drivers/gpu/drm/i915/intel_acpi.c6
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c195
-rw-r--r--drivers/gpu/drm/i915/intel_bios.h87
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c43
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c91
-rw-r--r--drivers/gpu/drm/i915/intel_display.c1000
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c379
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h519
-rw-r--r--drivers/gpu/drm/i915/intel_dsi.c621
-rw-r--r--drivers/gpu/drm/i915/intel_dsi.h102
-rw-r--r--drivers/gpu/drm/i915/intel_dsi_cmd.c427
-rw-r--r--drivers/gpu/drm/i915/intel_dsi_cmd.h109
-rw-r--r--drivers/gpu/drm/i915/intel_dsi_pll.c317
-rw-r--r--drivers/gpu/drm/i915/intel_dvo.c11
-rw-r--r--drivers/gpu/drm/i915/intel_fb.c25
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c68
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c15
-rw-r--r--drivers/gpu/drm/i915/intel_opregion.c431
-rw-r--r--drivers/gpu/drm/i915/intel_overlay.c9
-rw-r--r--drivers/gpu/drm/i915/intel_panel.c203
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c350
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c71
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h15
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c45
-rw-r--r--drivers/gpu/drm/i915/intel_sideband.c74
-rw-r--r--drivers/gpu/drm/i915/intel_sprite.c12
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c22
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c33
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/crtc.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_acpi.c7
-rw-r--r--drivers/hid/Kconfig2
-rw-r--r--drivers/hid/hid-elo.c35
-rw-r--r--drivers/hid/hid-lenovo-tpkbd.c50
-rw-r--r--drivers/hid/hid-sony.c11
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c18
-rw-r--r--drivers/hv/channel.c50
-rw-r--r--drivers/hv/connection.c23
-rw-r--r--drivers/hv/hv_kvp.c38
-rw-r--r--drivers/hv/hv_snapshot.c6
-rw-r--r--drivers/hv/hv_util.c73
-rw-r--r--drivers/hv/hyperv_vmbus.h9
-rw-r--r--drivers/hv/vmbus_drv.c488
-rw-r--r--drivers/hwmon/acpi_power_meter.c13
-rw-r--r--drivers/hwmon/adcxx.c2
-rw-r--r--drivers/hwmon/adm1026.c6
-rw-r--r--drivers/hwmon/adt7462.c5
-rw-r--r--drivers/hwmon/applesmc.c11
-rw-r--r--drivers/hwmon/asc7621.c12
-rw-r--r--drivers/hwmon/atxp1.c3
-rw-r--r--drivers/hwmon/ds1621.c63
-rw-r--r--drivers/hwmon/f71882fg.c1
-rw-r--r--drivers/hwmon/f75375s.c4
-rw-r--r--drivers/hwmon/gpio-fan.c45
-rw-r--r--drivers/hwmon/hwmon.c185
-rw-r--r--drivers/hwmon/ina209.c46
-rw-r--r--drivers/hwmon/ina2xx.c64
-rw-r--r--drivers/hwmon/jc42.c62
-rw-r--r--drivers/hwmon/lm70.c2
-rw-r--r--drivers/hwmon/lm73.c70
-rw-r--r--drivers/hwmon/lm95234.c138
-rw-r--r--drivers/hwmon/ltc4245.c78
-rw-r--r--drivers/hwmon/ltc4261.c56
-rw-r--r--drivers/hwmon/max16065.c124
-rw-r--r--drivers/hwmon/max6642.c73
-rw-r--r--drivers/hwmon/max6697.c55
-rw-r--r--drivers/hwmon/mc13783-adc.c2
-rw-r--r--drivers/hwmon/nct6775.c141
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c22
-rw-r--r--drivers/hwmon/tmp401.c89
-rw-r--r--drivers/ide/Kconfig11
-rw-r--r--drivers/ide/Makefile2
-rw-r--r--drivers/ide/ide-h8300.c109
-rw-r--r--drivers/idle/intel_idle.c56
-rw-r--r--drivers/iio/accel/bma180.c7
-rw-r--r--drivers/iio/accel/hid-sensor-accel-3d.c7
-rw-r--r--drivers/iio/accel/st_accel_core.c30
-rw-r--r--drivers/iio/adc/Kconfig11
-rw-r--r--drivers/iio/adc/Makefile1
-rw-r--r--drivers/iio/adc/ad7266.c13
-rw-r--r--drivers/iio/adc/ad7298.c10
-rw-r--r--drivers/iio/adc/ad7476.c9
-rw-r--r--drivers/iio/adc/ad7887.c10
-rw-r--r--drivers/iio/adc/ad7923.c10
-rw-r--r--drivers/iio/adc/ad_sigma_delta.c6
-rw-r--r--drivers/iio/adc/at91_adc.c10
-rw-r--r--drivers/iio/adc/max1363.c15
-rw-r--r--drivers/iio/adc/mcp3422.c409
-rw-r--r--drivers/iio/adc/ti_am335x_adc.c223
-rw-r--r--drivers/iio/buffer_cb.c8
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_buffer.c7
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_core.c70
-rw-r--r--drivers/iio/dac/ad5064.c3
-rw-r--r--drivers/iio/dac/ad5380.c4
-rw-r--r--drivers/iio/dac/ad5446.c3
-rw-r--r--drivers/iio/dac/ad5504.c4
-rw-r--r--drivers/iio/dac/ad5624r_spi.c4
-rw-r--r--drivers/iio/dac/ad5686.c4
-rw-r--r--drivers/iio/dac/ad5755.c1
-rw-r--r--drivers/iio/dac/ad5791.c5
-rw-r--r--drivers/iio/dac/ad7303.c1
-rw-r--r--drivers/iio/dac/mcp4725.c3
-rw-r--r--drivers/iio/frequency/adf4350.c1
-rw-r--r--drivers/iio/gyro/adis16130.c2
-rw-r--r--drivers/iio/gyro/adis16260.c1
-rw-r--r--drivers/iio/gyro/adxrs450.c1
-rw-r--r--drivers/iio/gyro/hid-sensor-gyro-3d.c7
-rw-r--r--drivers/iio/gyro/itg3200_buffer.c5
-rw-r--r--drivers/iio/gyro/st_gyro_core.c30
-rw-r--r--drivers/iio/iio_core.h2
-rw-r--r--drivers/iio/imu/adis16400_buffer.c9
-rw-r--r--drivers/iio/imu/adis_buffer.c9
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c6
-rw-r--r--drivers/iio/industrialio-buffer.c60
-rw-r--r--drivers/iio/industrialio-core.c180
-rw-r--r--drivers/iio/industrialio-event.c2
-rw-r--r--drivers/iio/kfifo_buf.c5
-rw-r--r--drivers/iio/light/Kconfig32
-rw-r--r--drivers/iio/light/Makefile3
-rw-r--r--drivers/iio/light/adjd_s311.c77
-rw-r--r--drivers/iio/light/gp2ap020a00f.c1617
-rw-r--r--drivers/iio/light/hid-sensor-als.c7
-rw-r--r--drivers/iio/light/tcs3472.c367
-rw-r--r--drivers/iio/light/tsl4531.c258
-rw-r--r--drivers/iio/magnetometer/hid-sensor-magn-3d.c7
-rw-r--r--drivers/iio/magnetometer/st_magn_core.c31
-rw-r--r--drivers/iio/pressure/st_pressure.h1
-rw-r--r--drivers/iio/pressure/st_pressure_core.c268
-rw-r--r--drivers/iio/pressure/st_pressure_i2c.c1
-rw-r--r--drivers/iio/temperature/tmp006.c57
-rw-r--r--drivers/input/keyboard/pxa27x_keypad.c11
-rw-r--r--drivers/input/misc/ad714x-spi.c1
-rw-r--r--drivers/input/misc/cobalt_btns.c2
-rw-r--r--drivers/input/misc/rb532_button.c1
-rw-r--r--drivers/input/misc/uinput.c26
-rw-r--r--drivers/input/mouse/cypress_ps2.c2
-rw-r--r--drivers/input/serio/Kconfig12
-rw-r--r--drivers/input/serio/Makefile1
-rw-r--r--drivers/input/serio/hyperv-keyboard.c437
-rw-r--r--drivers/input/serio/i8042.c23
-rw-r--r--drivers/input/tablet/wacom_sys.c39
-rw-r--r--drivers/input/tablet/wacom_wac.c114
-rw-r--r--drivers/input/tablet/wacom_wac.h4
-rw-r--r--drivers/input/touchscreen/ad7877.c2
-rw-r--r--drivers/input/touchscreen/ad7879-spi.c1
-rw-r--r--drivers/input/touchscreen/cyttsp4_core.c2
-rw-r--r--drivers/input/touchscreen/htcpen.c2
-rw-r--r--drivers/input/touchscreen/ti_am335x_tsc.c12
-rw-r--r--drivers/input/touchscreen/tsc2005.c2
-rw-r--r--drivers/iommu/Makefile1
-rw-r--r--drivers/iommu/arm-smmu.c13
-rw-r--r--drivers/iommu/iommu-traces.c27
-rw-r--r--drivers/iommu/iommu.c21
-rw-r--r--drivers/iommu/tegra-gart.c25
-rw-r--r--drivers/iommu/tegra-smmu.c2
-rw-r--r--drivers/irqchip/irq-armada-370-xp.c202
-rw-r--r--drivers/irqchip/irq-gic.c108
-rw-r--r--drivers/irqchip/irq-vic.c7
-rw-r--r--drivers/leds/leds-blinkm.c3
-rw-r--r--drivers/leds/leds-dac124s085.c3
-rw-r--r--drivers/leds/leds-lp55xx-common.c3
-rw-r--r--drivers/md/bcache/Kconfig11
-rw-r--r--drivers/md/bcache/alloc.c383
-rw-r--r--drivers/md/bcache/bcache.h327
-rw-r--r--drivers/md/bcache/bset.c289
-rw-r--r--drivers/md/bcache/bset.h93
-rw-r--r--drivers/md/bcache/btree.c1385
-rw-r--r--drivers/md/bcache/btree.h195
-rw-r--r--drivers/md/bcache/closure.c25
-rw-r--r--drivers/md/bcache/closure.h110
-rw-r--r--drivers/md/bcache/debug.c170
-rw-r--r--drivers/md/bcache/debug.h50
-rw-r--r--drivers/md/bcache/journal.c290
-rw-r--r--drivers/md/bcache/journal.h49
-rw-r--r--drivers/md/bcache/movinggc.c85
-rw-r--r--drivers/md/bcache/request.c1100
-rw-r--r--drivers/md/bcache/request.h43
-rw-r--r--drivers/md/bcache/stats.c26
-rw-r--r--drivers/md/bcache/stats.h13
-rw-r--r--drivers/md/bcache/super.c190
-rw-r--r--drivers/md/bcache/sysfs.c42
-rw-r--r--drivers/md/bcache/trace.c1
-rw-r--r--drivers/md/bcache/util.c12
-rw-r--r--drivers/md/bcache/util.h15
-rw-r--r--drivers/md/bcache/writeback.c455
-rw-r--r--drivers/md/bcache/writeback.h47
-rw-r--r--drivers/md/bitmap.c4
-rw-r--r--drivers/md/md.c2
-rw-r--r--drivers/md/md.h2
-rw-r--r--drivers/media/platform/marvell-ccic/mcam-core.c14
-rw-r--r--drivers/media/usb/gspca/conex.c3
-rw-r--r--drivers/media/usb/gspca/cpia1.c4
-rw-r--r--drivers/media/usb/gspca/gspca.c48
-rw-r--r--drivers/media/usb/gspca/gspca.h10
-rw-r--r--drivers/media/usb/gspca/jeilinj.c5
-rw-r--r--drivers/media/usb/gspca/jl2005bcd.c2
-rw-r--r--drivers/media/usb/gspca/m5602/m5602_mt9m111.c2
-rw-r--r--drivers/media/usb/gspca/mars.c7
-rw-r--r--drivers/media/usb/gspca/mr97310a.c6
-rw-r--r--drivers/media/usb/gspca/nw80x.c11
-rw-r--r--drivers/media/usb/gspca/ov519.c52
-rw-r--r--drivers/media/usb/gspca/ov534.c5
-rw-r--r--drivers/media/usb/gspca/pac207.c4
-rw-r--r--drivers/media/usb/gspca/pac7311.c6
-rw-r--r--drivers/media/usb/gspca/se401.c6
-rw-r--r--drivers/media/usb/gspca/sn9c20x.c6
-rw-r--r--drivers/media/usb/gspca/sonixb.c7
-rw-r--r--drivers/media/usb/gspca/sonixj.c3
-rw-r--r--drivers/media/usb/gspca/spca1528.c3
-rw-r--r--drivers/media/usb/gspca/spca500.c3
-rw-r--r--drivers/media/usb/gspca/sq905c.c2
-rw-r--r--drivers/media/usb/gspca/sq930x.c3
-rw-r--r--drivers/media/usb/gspca/stk014.c5
-rw-r--r--drivers/media/usb/gspca/stk1135.c76
-rw-r--r--drivers/media/usb/gspca/stv06xx/stv06xx.c2
-rw-r--r--drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c2
-rw-r--r--drivers/media/usb/gspca/sunplus.c3
-rw-r--r--drivers/media/usb/gspca/topro.c13
-rw-r--r--drivers/media/usb/gspca/tv8532.c7
-rw-r--r--drivers/media/usb/gspca/vicam.c8
-rw-r--r--drivers/media/usb/gspca/w996Xcf.c28
-rw-r--r--drivers/media/usb/gspca/xirlink_cit.c46
-rw-r--r--drivers/media/usb/gspca/zc3xx.c3
-rw-r--r--drivers/media/usb/stkwebcam/stk-webcam.c7
-rw-r--r--drivers/media/v4l2-core/videobuf2-core.c16
-rw-r--r--drivers/media/v4l2-core/videobuf2-dma-sg.c149
-rw-r--r--drivers/mfd/Kconfig10
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/aat2870-core.c2
-rw-r--r--drivers/mfd/da9052-i2c.c12
-rw-r--r--drivers/mfd/ezx-pcap.c8
-rw-r--r--drivers/mfd/lpc_ich.c2
-rw-r--r--drivers/mfd/mc13xxx-core.c5
-rw-r--r--drivers/mfd/mc13xxx-i2c.c1
-rw-r--r--drivers/mfd/mc13xxx-spi.c5
-rw-r--r--drivers/mfd/rts5249.c48
-rw-r--r--drivers/mfd/rtsx_pcr.c5
-rw-r--r--drivers/mfd/sm501.c4
-rw-r--r--drivers/mfd/stw481x.c250
-rw-r--r--drivers/mfd/ti-ssp.c1
-rw-r--r--drivers/mfd/ti_am335x_tscadc.c10
-rw-r--r--drivers/mfd/timberdale.c6
-rw-r--r--drivers/mfd/tps6586x.c18
-rw-r--r--drivers/mfd/twl6040.c10
-rw-r--r--drivers/mfd/ucb1x00-core.c1
-rw-r--r--drivers/mfd/wm5110-tables.c36
-rw-r--r--drivers/mfd/wm8994-core.c78
-rw-r--r--drivers/misc/Kconfig1
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/bmp085.c2
-rw-r--r--drivers/misc/cb710/core.c2
-rw-r--r--drivers/misc/eeprom/Kconfig13
-rw-r--r--drivers/misc/eeprom/Makefile1
-rw-r--r--drivers/misc/eeprom/sunxi_sid.c158
-rw-r--r--drivers/misc/ibmasm/module.c4
-rw-r--r--drivers/misc/mei/amthif.c34
-rw-r--r--drivers/misc/mei/bus.c5
-rw-r--r--drivers/misc/mei/client.c103
-rw-r--r--drivers/misc/mei/client.h15
-rw-r--r--drivers/misc/mei/hbm.c19
-rw-r--r--drivers/misc/mei/init.c3
-rw-r--r--drivers/misc/mei/interrupt.c47
-rw-r--r--drivers/misc/mei/main.c39
-rw-r--r--drivers/misc/mei/mei_dev.h6
-rw-r--r--drivers/misc/mei/pci-me.c1
-rw-r--r--drivers/misc/mic/Kconfig39
-rw-r--r--drivers/misc/mic/Makefile6
-rw-r--r--drivers/misc/mic/card/Makefile11
-rw-r--r--drivers/misc/mic/card/mic_debugfs.c130
-rw-r--r--drivers/misc/mic/card/mic_device.c306
-rw-r--r--drivers/misc/mic/card/mic_device.h133
-rw-r--r--drivers/misc/mic/card/mic_virtio.c631
-rw-r--r--drivers/misc/mic/card/mic_virtio.h77
-rw-r--r--drivers/misc/mic/card/mic_x100.c256
-rw-r--r--drivers/misc/mic/card/mic_x100.h48
-rw-r--r--drivers/misc/mic/common/mic_device.h51
-rw-r--r--drivers/misc/mic/host/Makefile14
-rw-r--r--drivers/misc/mic/host/mic_boot.c185
-rw-r--r--drivers/misc/mic/host/mic_debugfs.c495
-rw-r--r--drivers/misc/mic/host/mic_device.h195
-rw-r--r--drivers/misc/mic/host/mic_fops.c221
-rw-r--r--drivers/misc/mic/host/mic_fops.h32
-rw-r--r--drivers/misc/mic/host/mic_intr.c628
-rw-r--r--drivers/misc/mic/host/mic_intr.h137
-rw-r--r--drivers/misc/mic/host/mic_main.c477
-rw-r--r--drivers/misc/mic/host/mic_smpt.c442
-rw-r--r--drivers/misc/mic/host/mic_smpt.h98
-rw-r--r--drivers/misc/mic/host/mic_sysfs.c466
-rw-r--r--drivers/misc/mic/host/mic_virtio.c703
-rw-r--r--drivers/misc/mic/host/mic_virtio.h138
-rw-r--r--drivers/misc/mic/host/mic_x100.c573
-rw-r--r--drivers/misc/mic/host/mic_x100.h98
-rw-r--r--drivers/misc/pti.c1
-rw-r--r--drivers/misc/ti_dac7512.c23
-rw-r--r--drivers/misc/tifm_7xx1.c3
-rw-r--r--drivers/misc/vmw_vmci/vmci_guest.c2
-rw-r--r--drivers/mmc/core/bus.c2
-rw-r--r--drivers/mmc/core/core.c25
-rw-r--r--drivers/mmc/core/mmc_ops.c73
-rw-r--r--drivers/mmc/host/atmel-mci.c21
-rw-r--r--drivers/mmc/host/dw_mmc-exynos.c294
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.c7
-rw-r--r--drivers/mmc/host/dw_mmc-socfpga.c34
-rw-r--r--drivers/mmc/host/dw_mmc.c583
-rw-r--r--drivers/mmc/host/dw_mmc.h55
-rw-r--r--drivers/mmc/host/mmci.c78
-rw-r--r--drivers/mmc/host/mmci.h4
-rw-r--r--drivers/mmc/host/mvsdio.c17
-rw-r--r--drivers/mmc/host/rtsx_pci_sdmmc.c2
-rw-r--r--drivers/mmc/host/sdhci-bcm-kona.c14
-rw-r--r--drivers/mmc/host/sdhci-bcm2835.c8
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c344
-rw-r--r--drivers/mmc/host/sdhci-esdhc.h37
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c35
-rw-r--r--drivers/mmc/host/sdhci.c12
-rw-r--r--drivers/mmc/host/sdhci.h3
-rw-r--r--drivers/mmc/host/sh_mobile_sdhi.c16
-rw-r--r--drivers/mtd/devices/m25p80.c17
-rw-r--r--drivers/mtd/devices/mtd_dataflash.c2
-rw-r--r--drivers/mtd/lpddr/lpddr_cmds.c2
-rw-r--r--drivers/mtd/nand/atmel_nand.c79
-rw-r--r--drivers/mtd/nand/denali.c2
-rw-r--r--drivers/mtd/nand/docg4.c1
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c2
-rw-r--r--drivers/mtd/nand/fsl_ifc_nand.c2
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-nand.c8
-rw-r--r--drivers/mtd/nand/lpc32xx_slc.c8
-rw-r--r--drivers/mtd/nand/nand_base.c41
-rw-r--r--drivers/mtd/nand/nand_bbt.c1
-rw-r--r--drivers/mtd/nand/nandsim.c6
-rw-r--r--drivers/mtd/onenand/omap2.c22
-rw-r--r--drivers/mtd/onenand/onenand_base.c17
-rw-r--r--drivers/net/Space.c3
-rw-r--r--drivers/net/bonding/bond_3ad.c54
-rw-r--r--drivers/net/bonding/bond_alb.c84
-rw-r--r--drivers/net/bonding/bond_alb.h4
-rw-r--r--drivers/net/bonding/bond_main.c304
-rw-r--r--drivers/net/bonding/bond_procfs.c5
-rw-r--r--drivers/net/bonding/bond_sysfs.c76
-rw-r--r--drivers/net/bonding/bonding.h100
-rw-r--r--drivers/net/can/mscan/mscan.h6
-rw-r--r--drivers/net/can/slcan.c139
-rw-r--r--drivers/net/can/softing/softing.h24
-rw-r--r--drivers/net/ethernet/8390/8390.h40
-rw-r--r--drivers/net/ethernet/8390/Kconfig7
-rw-r--r--drivers/net/ethernet/8390/Makefile1
-rw-r--r--drivers/net/ethernet/8390/ne-h8300.c684
-rw-r--r--drivers/net/ethernet/adi/bfin_mac.h2
-rw-r--r--drivers/net/ethernet/amd/7990.h12
-rw-r--r--drivers/net/ethernet/amd/declance.c19
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c.h6
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e.h12
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl2.h2
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c3
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c189
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c24
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c12
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c50
-rw-r--r--drivers/net/ethernet/broadcom/cnic_if.h4
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c81
-rw-r--r--drivers/net/ethernet/broadcom/tg3.h3
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.h43
-rw-r--r--drivers/net/ethernet/chelsio/cxgb/common.h46
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c3
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4vf/sge.c11
-rw-r--r--drivers/net/ethernet/emulex/benet/be.h24
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.h238
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h26
-rw-r--r--drivers/net/ethernet/ibm/emac/debug.h14
-rw-r--r--drivers/net/ethernet/ibm/emac/rgmii.h18
-rw-r--r--drivers/net/ethernet/ibm/emac/tah.h14
-rw-r--r--drivers/net/ethernet/ibm/emac/zmii.h18
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000.h32
-rw-r--r--drivers/net/ethernet/intel/e1000e/e1000.h45
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_82575.h16
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_hw.h6
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_i210.h38
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_mac.h2
-rw-r--r--drivers/net/ethernet/intel/igb/igb.h73
-rw-r--r--drivers/net/ethernet/intel/igbvf/igbvf.h22
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb.h22
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_hw.h25
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe.h172
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf.h34
-rw-r--r--drivers/net/ethernet/marvell/skge.c9
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h56
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic.h5
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge.h58
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_dbg.c4
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_mpi.c2
-rw-r--r--drivers/net/ethernet/sfc/ef10.c319
-rw-r--r--drivers/net/ethernet/sfc/ef10_regs.h1
-rw-r--r--drivers/net/ethernet/sfc/efx.h105
-rw-r--r--drivers/net/ethernet/sfc/ethtool.c5
-rw-r--r--drivers/net/ethernet/sfc/io.h5
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c10
-rw-r--r--drivers/net/ethernet/sfc/mcdi.h120
-rw-r--r--drivers/net/ethernet/sfc/mdio_10g.h26
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h7
-rw-r--r--drivers/net/ethernet/sfc/nic.c73
-rw-r--r--drivers/net/ethernet/sfc/nic.h256
-rw-r--r--drivers/net/ethernet/sfc/phy.h8
-rw-r--r--drivers/net/ethernet/sfc/rx.c90
-rw-r--r--drivers/net/ethernet/sfc/selftest.h15
-rw-r--r--drivers/net/ethernet/sfc/tx.c419
-rw-r--r--drivers/net/ethernet/smsc/smc9194.c24
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h12
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h17
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/mmc.h6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h10
-rw-r--r--drivers/net/ethernet/ti/Kconfig8
-rw-r--r--drivers/net/ethernet/ti/Makefile1
-rw-r--r--drivers/net/ethernet/ti/cpsw-phy-sel.c161
-rw-r--r--drivers/net/ethernet/ti/cpsw.c157
-rw-r--r--drivers/net/ethernet/ti/cpsw.h2
-rw-r--r--drivers/net/ethernet/ti/cpts.h9
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_net.h29
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_wireless.h6
-rw-r--r--drivers/net/ethernet/toshiba/spider_net.h4
-rw-r--r--drivers/net/ethernet/via/via-rhine.c9
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_emaclite.c39
-rw-r--r--drivers/net/fddi/skfp/h/smc.h28
-rw-r--r--drivers/net/irda/sir-dev.h29
-rw-r--r--drivers/net/netconsole.c2
-rw-r--r--drivers/net/phy/micrel.c24
-rw-r--r--drivers/net/slip/slip.c3
-rw-r--r--drivers/net/usb/cdc-phonet.c2
-rw-r--r--drivers/net/vmxnet3/vmxnet3_int.h4
-rw-r--r--drivers/net/wan/x25_asy.h2
-rw-r--r--drivers/net/wan/z85230.h27
-rw-r--r--drivers/net/wimax/i2400m/i2400m-usb.h27
-rw-r--r--drivers/net/wimax/i2400m/i2400m.h117
-rw-r--r--drivers/net/wireless/adm8211.c1
-rw-r--r--drivers/net/wireless/airo.c1
-rw-r--r--drivers/net/wireless/ath/ar5523/ar5523.c1
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.c291
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.h74
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c46
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c23
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.h8
-rw-r--r--drivers/net/wireless/ath/ath10k/htc.c8
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.c19
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h6
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c12
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_tx.c74
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.h19
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c22
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c327
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.h73
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c33
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h16
-rw-r--r--drivers/net/wireless/ath/ath5k/ahb.c15
-rw-r--r--drivers/net/wireless/ath/ath6kl/common.h3
-rw-r--r--drivers/net/wireless/ath/ath6kl/debug.h9
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/antenna.c36
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_calib.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_phy.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c92
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c34
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_hw.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mci.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c32
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_rtt.c58
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9485_initvals.h218
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h24
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h22
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c14
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c446
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h12
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_debug.c25
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs_pri_detector.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_4k.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_9287.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_def.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/gpio.c22
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_debug.c456
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c59
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h26
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c20
-rw-r--r--drivers/net/wireless/ath/ath9k/link.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c195
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c32
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/wmi.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c19
-rw-r--r--drivers/net/wireless/ath/wil6210/pcie_bus.c1
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c30
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd.h30
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h28
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c14
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h12
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h23
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h92
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.c2
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/aiutils.h18
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/ampdu.h22
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/antsel.h14
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/channel.h20
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h38
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/main.h110
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h219
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h371
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h91
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/pmu.h4
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/pub.h145
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/rate.h48
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/stf.h31
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h16
-rw-r--r--drivers/net/wireless/brcm80211/include/brcmu_d11.h2
-rw-r--r--drivers/net/wireless/brcm80211/include/brcmu_utils.h44
-rw-r--r--drivers/net/wireless/cw1200/cw1200_spi.c30
-rw-r--r--drivers/net/wireless/cw1200/fwio.c2
-rw-r--r--drivers/net/wireless/cw1200/hwbus.h1
-rw-r--r--drivers/net/wireless/cw1200/hwio.c15
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c2
-rw-r--r--drivers/net/wireless/ipw2x00/libipw.h87
-rw-r--r--drivers/net/wireless/iwlegacy/3945-mac.c2
-rw-r--r--drivers/net/wireless/iwlegacy/3945.h82
-rw-r--r--drivers/net/wireless/iwlegacy/4965-mac.c2
-rw-r--r--drivers/net/wireless/iwlegacy/4965.h2
-rw-r--r--drivers/net/wireless/iwlegacy/common.h66
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/agn.h2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/dev.h2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rs.h8
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.h9
-rw-r--r--drivers/net/wireless/libertas/if_spi.c2
-rw-r--r--drivers/net/wireless/mwifiex/11n_aggr.c3
-rw-r--r--drivers/net/wireless/mwifiex/11n_aggr.h2
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c5
-rw-r--r--drivers/net/wireless/mwifiex/pcie.c6
-rw-r--r--drivers/net/wireless/mwifiex/usb.c7
-rw-r--r--drivers/net/wireless/mwifiex/wmm.c3
-rw-r--r--drivers/net/wireless/mwifiex/wmm.h24
-rw-r--r--drivers/net/wireless/mwl8k.c2
-rw-r--r--drivers/net/wireless/orinoco/orinoco.h31
-rw-r--r--drivers/net/wireless/orinoco/orinoco_nortel.c2
-rw-r--r--drivers/net/wireless/orinoco/orinoco_pci.c2
-rw-r--r--drivers/net/wireless/orinoco/orinoco_plx.c2
-rw-r--r--drivers/net/wireless/orinoco/orinoco_tmd.c2
-rw-r--r--drivers/net/wireless/p54/p54pci.c1
-rw-r--r--drivers/net/wireless/p54/p54usb.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c41
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/dev.c1
-rw-r--r--drivers/net/wireless/rtlwifi/base.h1
-rw-r--r--drivers/net/wireless/rtlwifi/cam.h10
-rw-r--r--drivers/net/wireless/rtlwifi/efuse.c18
-rw-r--r--drivers/net/wireless/rtlwifi/efuse.h29
-rw-r--r--drivers/net/wireless/rtlwifi/pci.c3
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8188ee/phy.h49
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/def.h2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/phy.h57
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/reg.h20
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/rf.h13
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/mac.c187
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/rf.h13
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/hw.h7
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/phy.h47
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192de/rf.h18
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/reg.h5
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/phy.h61
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/rf.h13
-rw-r--r--drivers/net/wireless/rtlwifi/wifi.h4
-rw-r--r--drivers/net/wireless/ti/wl1251/spi.c2
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/spi.c2
-rw-r--r--drivers/parport/Kconfig2
-rw-r--r--drivers/pci/host/Kconfig2
-rw-r--r--drivers/pci/host/pci-mvebu.c121
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c9
-rw-r--r--drivers/pci/hotplug/shpchp.h2
-rw-r--r--drivers/pci/pci-acpi.c3
-rw-r--r--drivers/pci/pci-driver.c15
-rw-r--r--drivers/pci/pci-sysfs.c16
-rw-r--r--drivers/pci/pci.h2
-rw-r--r--drivers/pci/probe.c3
-rw-r--r--drivers/pcmcia/at91_cf.c11
-rw-r--r--drivers/pinctrl/Kconfig18
-rw-r--r--drivers/pinctrl/Makefile3
-rw-r--r--drivers/pinctrl/pinconf.c4
-rw-r--r--drivers/pinctrl/pinctrl-adi2-bf54x.c592
-rw-r--r--drivers/pinctrl/pinctrl-adi2-bf60x.c521
-rw-r--r--drivers/pinctrl/pinctrl-adi2.c1183
-rw-r--r--drivers/pinctrl/pinctrl-adi2.h75
-rw-r--r--drivers/pinctrl/pinctrl-tegra114.c5
-rw-r--r--drivers/platform/x86/eeepc-laptop.c8
-rw-r--r--drivers/platform/x86/fujitsu-laptop.c44
-rw-r--r--drivers/platform/x86/intel-rst.c48
-rw-r--r--drivers/platform/x86/intel-smartconnect.c27
-rw-r--r--drivers/platform/x86/intel_menlow.c8
-rw-r--r--drivers/platform/x86/sony-laptop.c28
-rw-r--r--drivers/platform/x86/topstar-laptop.c8
-rw-r--r--drivers/platform/x86/toshiba_acpi.c44
-rw-r--r--drivers/platform/x86/wmi.c30
-rw-r--r--drivers/pnp/pnpacpi/core.c11
-rw-r--r--drivers/pwm/pwm-atmel-tcb.c4
-rw-r--r--drivers/rapidio/rio-driver.c2
-rw-r--r--drivers/rapidio/rio-sysfs.c16
-rw-r--r--drivers/rapidio/rio.h2
-rw-r--r--drivers/regulator/88pm8607.c12
-rw-r--r--drivers/regulator/Kconfig26
-rw-r--r--drivers/regulator/Makefile4
-rw-r--r--drivers/regulator/aat2870-regulator.c11
-rw-r--r--drivers/regulator/ad5398.c19
-rw-r--r--drivers/regulator/anatop-regulator.c3
-rw-r--r--drivers/regulator/arizona-ldo1.c12
-rw-r--r--drivers/regulator/arizona-micsupp.c14
-rw-r--r--drivers/regulator/as3711-regulator.c22
-rw-r--r--drivers/regulator/as3722-regulator.c917
-rw-r--r--drivers/regulator/core.c328
-rw-r--r--drivers/regulator/da903x.c11
-rw-r--r--drivers/regulator/da9052-regulator.c14
-rw-r--r--drivers/regulator/da9055-regulator.c24
-rw-r--r--drivers/regulator/da9063-regulator.c4
-rw-r--r--drivers/regulator/devres.c252
-rw-r--r--drivers/regulator/fan53555.c12
-rw-r--r--drivers/regulator/fixed.c28
-rw-r--r--drivers/regulator/internal.h38
-rw-r--r--drivers/regulator/isl6271a-regulator.c24
-rw-r--r--drivers/regulator/max1586.c26
-rw-r--r--drivers/regulator/max77686.c23
-rw-r--r--drivers/regulator/max77693.c29
-rw-r--r--drivers/regulator/max8649.c14
-rw-r--r--drivers/regulator/max8660.c30
-rw-r--r--drivers/regulator/max8907-regulator.c23
-rw-r--r--drivers/regulator/max8973-regulator.c11
-rw-r--r--drivers/regulator/max8997.c39
-rw-r--r--drivers/regulator/max8998.c35
-rw-r--r--drivers/regulator/mc13783-regulator.c25
-rw-r--r--drivers/regulator/mc13892-regulator.c22
-rw-r--r--drivers/regulator/of_regulator.c6
-rw-r--r--drivers/regulator/palmas-regulator.c220
-rw-r--r--drivers/regulator/rc5t583-regulator.c22
-rw-r--r--drivers/regulator/s2mps11.c23
-rw-r--r--drivers/regulator/s5m8767.c24
-rw-r--r--drivers/regulator/stw481x-vmmc.c110
-rw-r--r--drivers/regulator/ti-abb-regulator.c79
-rw-r--r--drivers/regulator/tps51632-regulator.c11
-rw-r--r--drivers/regulator/tps62360-regulator.c17
-rw-r--r--drivers/regulator/tps65023-regulator.c22
-rw-r--r--drivers/regulator/tps6507x-regulator.c23
-rw-r--r--drivers/regulator/tps65090-regulator.c35
-rw-r--r--drivers/regulator/tps65217-regulator.c26
-rw-r--r--drivers/regulator/tps6524x-regulator.c1
-rw-r--r--drivers/regulator/tps6586x-regulator.c31
-rw-r--r--drivers/regulator/tps65910-regulator.c23
-rw-r--r--drivers/regulator/tps65912-regulator.c24
-rw-r--r--drivers/regulator/tps80031-regulator.c30
-rw-r--r--drivers/regulator/wm831x-dcdc.c118
-rw-r--r--drivers/regulator/wm831x-isink.c25
-rw-r--r--drivers/regulator/wm831x-ldo.c67
-rw-r--r--drivers/regulator/wm8350-regulator.c8
-rw-r--r--drivers/regulator/wm8400-regulator.c13
-rw-r--r--drivers/regulator/wm8994-regulator.c14
-rw-r--r--drivers/rtc/interface.c13
-rw-r--r--drivers/s390/block/scm_blk.h2
-rw-r--r--drivers/s390/char/sclp_cmd.c8
-rw-r--r--drivers/s390/char/tty3270.c2
-rw-r--r--drivers/s390/cio/airq.c19
-rw-r--r--drivers/s390/cio/eadm_sch.c2
-rw-r--r--drivers/s390/cio/qdio_debug.h8
-rw-r--r--drivers/s390/cio/qdio_main.c2
-rw-r--r--drivers/s390/crypto/zcrypt_debug.h12
-rw-r--r--drivers/s390/net/claw.h8
-rw-r--r--drivers/s390/net/ctcm_dbug.c2
-rw-r--r--drivers/s390/net/lcs.h8
-rw-r--r--drivers/s390/net/netiucv.c8
-rw-r--r--drivers/s390/net/qeth_core_main.c2
-rw-r--r--drivers/s390/scsi/zfcp_dbf.h4
-rw-r--r--drivers/scsi/bfa/bfad.c53
-rw-r--r--drivers/scsi/csiostor/csio_hw.c22
-rw-r--r--drivers/scsi/fcoe/fcoe_sysfs.c14
-rw-r--r--drivers/scsi/qla2xxx/qla_mr.c6
-rw-r--r--drivers/spi/Kconfig3
-rw-r--r--drivers/spi/spi-altera.c2
-rw-r--r--drivers/spi/spi-ath79.c2
-rw-r--r--drivers/spi/spi-atmel.c41
-rw-r--r--drivers/spi/spi-au1550.c2
-rw-r--r--drivers/spi/spi-bfin-sport.c27
-rw-r--r--drivers/spi/spi-bfin5xx.c24
-rw-r--r--drivers/spi/spi-bitbang.c12
-rw-r--r--drivers/spi/spi-butterfly.c2
-rw-r--r--drivers/spi/spi-clps711x.c2
-rw-r--r--drivers/spi/spi-davinci.c13
-rw-r--r--drivers/spi/spi-dw-mmio.c5
-rw-r--r--drivers/spi/spi-dw-pci.c1
-rw-r--r--drivers/spi/spi-efm32.c6
-rw-r--r--drivers/spi/spi-fsl-dspi.c19
-rw-r--r--drivers/spi/spi-gpio.c5
-rw-r--r--drivers/spi/spi-imx.c2
-rw-r--r--drivers/spi/spi-lm70llp.c2
-rw-r--r--drivers/spi/spi-mpc512x-psc.c4
-rw-r--r--drivers/spi/spi-nuc900.c3
-rw-r--r--drivers/spi/spi-oc-tiny.c2
-rw-r--r--drivers/spi/spi-pl022.c3
-rw-r--r--drivers/spi/spi-ppc4xx.c3
-rw-r--r--drivers/spi/spi-pxa2xx.c11
-rw-r--r--drivers/spi/spi-rspi.c183
-rw-r--r--drivers/spi/spi-s3c24xx.c4
-rw-r--r--drivers/spi/spi-s3c64xx.c35
-rw-r--r--drivers/spi/spi-sh-sci.c2
-rw-r--r--drivers/spi/spi-sirf.c2
-rw-r--r--drivers/spi/spi-tegra114.c2
-rw-r--r--drivers/spi/spi-tegra20-sflash.c2
-rw-r--r--drivers/spi/spi-tegra20-slink.c2
-rw-r--r--drivers/spi/spi-topcliff-pch.c4
-rw-r--r--drivers/spi/spi-xilinx.c2
-rw-r--r--drivers/spi/spi.c40
-rw-r--r--drivers/spi/spidev.c1
-rw-r--r--drivers/staging/android/Kconfig7
-rw-r--r--drivers/staging/android/alarm-dev.c8
-rw-r--r--drivers/staging/android/ashmem.c137
-rw-r--r--drivers/staging/android/binder.c9
-rw-r--r--drivers/staging/android/timed_output.h4
-rw-r--r--drivers/staging/bcm/InterfaceMisc.c2
-rw-r--r--drivers/staging/bcm/PHSModule.c12
-rw-r--r--drivers/staging/bcm/nvm.c12
-rw-r--r--drivers/staging/comedi/Kconfig1
-rw-r--r--drivers/staging/comedi/comedidev.h23
-rw-r--r--drivers/staging/comedi/drivers.c29
-rw-r--r--drivers/staging/comedi/drivers/8253.h9
-rw-r--r--drivers/staging/comedi/drivers/8255.c25
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c7
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c17
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c7
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_1516.c8
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_16xx.c11
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_2032.c8
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_2200.c8
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3120.c2
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3501.c8
-rw-r--r--drivers/staging/comedi/drivers/addi_apci_3xxx.c17
-rw-r--r--drivers/staging/comedi/drivers/adl_pci6208.c137
-rw-r--r--drivers/staging/comedi/drivers/adl_pci7x3x.c13
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9111.c20
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9118.c28
-rw-r--r--drivers/staging/comedi/drivers/adq12b.c32
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1710.c31
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1723.c13
-rw-r--r--drivers/staging/comedi/drivers/adv_pci_dio.c33
-rw-r--r--drivers/staging/comedi/drivers/aio_iiro_16.c4
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200_common.c33
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc263.c17
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci224.c36
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci263.c17
-rw-r--r--drivers/staging/comedi/drivers/cb_das16_cs.c21
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas.c43
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas64.c25
-rw-r--r--drivers/staging/comedi/drivers/comedi_parport.c380
-rw-r--r--drivers/staging/comedi/drivers/contec_pci_dio.c12
-rw-r--r--drivers/staging/comedi/drivers/das08.c46
-rw-r--r--drivers/staging/comedi/drivers/das08.h1
-rw-r--r--drivers/staging/comedi/drivers/das16.c44
-rw-r--r--drivers/staging/comedi/drivers/das16m1.c40
-rw-r--r--drivers/staging/comedi/drivers/das1800.c66
-rw-r--r--drivers/staging/comedi/drivers/das800.c16
-rw-r--r--drivers/staging/comedi/drivers/dmm32at.c70
-rw-r--r--drivers/staging/comedi/drivers/dt2801.c21
-rw-r--r--drivers/staging/comedi/drivers/dt2811.c8
-rw-r--r--drivers/staging/comedi/drivers/dt2817.c51
-rw-r--r--drivers/staging/comedi/drivers/dt282x.c10
-rw-r--r--drivers/staging/comedi/drivers/dt3000.c9
-rw-r--r--drivers/staging/comedi/drivers/dt9812.c9
-rw-r--r--drivers/staging/comedi/drivers/dyna_pci10xx.c20
-rw-r--r--drivers/staging/comedi/drivers/icp_multi.c14
-rw-r--r--drivers/staging/comedi/drivers/ii_pci20kc.c7
-rw-r--r--drivers/staging/comedi/drivers/me4000.c25
-rw-r--r--drivers/staging/comedi/drivers/me_daq.c9
-rw-r--r--drivers/staging/comedi/drivers/multiq3.c8
-rw-r--r--drivers/staging/comedi/drivers/ni_6527.c22
-rw-r--r--drivers/staging/comedi/drivers/ni_660x.c1
-rw-r--r--drivers/staging/comedi/drivers/ni_670x.c11
-rw-r--r--drivers/staging/comedi/drivers/ni_at_a2150.c7
-rw-r--r--drivers/staging/comedi/drivers/ni_at_ao.c8
-rw-r--r--drivers/staging/comedi/drivers/ni_atmio16d.c9
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_700.c19
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc.c33
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_common.c45
-rw-r--r--drivers/staging/comedi/drivers/ni_pcidio.c9
-rw-r--r--drivers/staging/comedi/drivers/pcl711.c704
-rw-r--r--drivers/staging/comedi/drivers/pcl726.c592
-rw-r--r--drivers/staging/comedi/drivers/pcl730.c13
-rw-r--r--drivers/staging/comedi/drivers/pcl812.c48
-rw-r--r--drivers/staging/comedi/drivers/pcl816.c13
-rw-r--r--drivers/staging/comedi/drivers/pcl818.c33
-rw-r--r--drivers/staging/comedi/drivers/pcmad.c8
-rw-r--r--drivers/staging/comedi/drivers/quatech_daqp_cs.c8
-rw-r--r--drivers/staging/comedi/drivers/rtd520.c8
-rw-r--r--drivers/staging/comedi/drivers/rti800.c8
-rw-r--r--drivers/staging/comedi/drivers/s526.c9
-rw-r--r--drivers/staging/comedi/drivers/s626.c13
-rw-r--r--drivers/staging/comedi/drivers/skel.c46
-rw-r--r--drivers/staging/comedi/drivers/ssv_dnp.c48
-rw-r--r--drivers/staging/comedi/drivers/usbdux.c6
-rw-r--r--drivers/staging/comedi/drivers/usbduxsigma.c6
-rw-r--r--drivers/staging/comedi/drivers/vmk80xx.c35
-rw-r--r--drivers/staging/crystalhd/crystalhd_hw.c8
-rw-r--r--drivers/staging/dgap/Makefile2
-rw-r--r--drivers/staging/dgap/dgap_downld.h2
-rw-r--r--drivers/staging/dgap/dgap_driver.c13
-rw-r--r--drivers/staging/dgap/dgap_driver.h5
-rw-r--r--drivers/staging/dgap/dgap_fep5.h2
-rw-r--r--drivers/staging/dgap/dgap_kcompat.h29
-rw-r--r--drivers/staging/dgap/dgap_parse.c10
-rw-r--r--drivers/staging/dgap/dgap_sysfs.c22
-rw-r--r--drivers/staging/dgap/dgap_tty.c34
-rw-r--r--drivers/staging/dgap/digi.h4
-rw-r--r--drivers/staging/dgap/downld.c4
-rw-r--r--drivers/staging/dgnc/dgnc_cls.c22
-rw-r--r--drivers/staging/dgnc/dgnc_driver.c140
-rw-r--r--drivers/staging/dgnc/dgnc_driver.h12
-rw-r--r--drivers/staging/dgnc/dgnc_kcompat.h24
-rw-r--r--drivers/staging/dgnc/dgnc_mgmt.c22
-rw-r--r--drivers/staging/dgnc/dgnc_neo.c30
-rw-r--r--drivers/staging/dgnc/dgnc_neo.h2
-rw-r--r--drivers/staging/dgnc/dgnc_sysfs.c188
-rw-r--r--drivers/staging/dgnc/dgnc_sysfs.h6
-rw-r--r--drivers/staging/dgnc/dgnc_tty.c311
-rw-r--r--drivers/staging/dgnc/dgnc_tty.h6
-rw-r--r--drivers/staging/dgnc/digi.h4
-rw-r--r--drivers/staging/dgrp/dgrp_sysfs.c30
-rw-r--r--drivers/staging/dwc2/TODO33
-rw-r--r--drivers/staging/dwc2/core.c27
-rw-r--r--drivers/staging/dwc2/core.h7
-rw-r--r--drivers/staging/dwc2/hcd.c54
-rw-r--r--drivers/staging/dwc2/hcd.h3
-rw-r--r--drivers/staging/dwc2/hcd_ddma.c13
-rw-r--r--drivers/staging/dwc2/hcd_intr.c29
-rw-r--r--drivers/staging/dwc2/hcd_queue.c203
-rw-r--r--drivers/staging/dwc2/pci.c1
-rw-r--r--drivers/staging/et131x/Module.symvers0
-rw-r--r--drivers/staging/et131x/README7
-rw-r--r--drivers/staging/et131x/et131x.c17
-rw-r--r--drivers/staging/fwserial/fwserial.c3
-rw-r--r--drivers/staging/iio/accel/lis3l02dq_ring.c6
-rw-r--r--drivers/staging/iio/accel/sca3000_core.c8
-rw-r--r--drivers/staging/iio/accel/sca3000_ring.c4
-rw-r--r--drivers/staging/iio/adc/ad7192.c15
-rw-r--r--drivers/staging/iio/adc/ad7280a.c11
-rw-r--r--drivers/staging/iio/adc/ad7291.c27
-rw-r--r--drivers/staging/iio/adc/ad7606_core.c26
-rw-r--r--drivers/staging/iio/adc/ad7606_ring.c8
-rw-r--r--drivers/staging/iio/adc/ad7780.c28
-rw-r--r--drivers/staging/iio/adc/ad7816.c59
-rw-r--r--drivers/staging/iio/adc/ad799x_core.c16
-rw-r--r--drivers/staging/iio/adc/ad799x_ring.c10
-rw-r--r--drivers/staging/iio/adc/lpc32xx_adc.c49
-rw-r--r--drivers/staging/iio/adc/mxs-lradc.c19
-rw-r--r--drivers/staging/iio/addac/adt7316.c86
-rw-r--r--drivers/staging/iio/frequency/ad5930.c16
-rw-r--r--drivers/staging/iio/frequency/ad9832.c36
-rw-r--r--drivers/staging/iio/frequency/ad9834.c33
-rw-r--r--drivers/staging/iio/frequency/ad9850.c16
-rw-r--r--drivers/staging/iio/frequency/ad9852.c17
-rw-r--r--drivers/staging/iio/frequency/ad9910.c16
-rw-r--r--drivers/staging/iio/frequency/ad9951.c17
-rw-r--r--drivers/staging/iio/iio_simple_dummy.c16
-rw-r--r--drivers/staging/iio/iio_simple_dummy_buffer.c7
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.c32
-rw-r--r--drivers/staging/iio/light/isl29018.c18
-rw-r--r--drivers/staging/iio/light/tsl2583.c48
-rw-r--r--drivers/staging/iio/light/tsl2x7x_core.c48
-rw-r--r--drivers/staging/iio/magnetometer/hmc5843.c26
-rw-r--r--drivers/staging/iio/meter/ade7753.c31
-rw-r--r--drivers/staging/iio/meter/ade7754.c31
-rw-r--r--drivers/staging/iio/meter/ade7758_core.c32
-rw-r--r--drivers/staging/iio/meter/ade7758_ring.c6
-rw-r--r--drivers/staging/iio/meter/ade7759.c30
-rw-r--r--drivers/staging/iio/meter/ade7854-i2c.c4
-rw-r--r--drivers/staging/iio/meter/ade7854-spi.c4
-rw-r--r--drivers/staging/iio/meter/ade7854.c22
-rw-r--r--drivers/staging/iio/resolver/ad2s1200.c28
-rw-r--r--drivers/staging/iio/resolver/ad2s1210.c34
-rw-r--r--drivers/staging/iio/resolver/ad2s90.c16
-rw-r--r--drivers/staging/iio/trigger/iio-trig-bfin-timer.c23
-rw-r--r--drivers/staging/iio/trigger/iio-trig-periodic-rtc.c4
-rw-r--r--drivers/staging/imx-drm/imx-drm-core.c11
-rw-r--r--drivers/staging/imx-drm/imx-ldb.c2
-rw-r--r--drivers/staging/lustre/lustre/Kconfig2
-rw-r--r--drivers/staging/lustre/lustre/libcfs/hash.c2
-rw-r--r--drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c2
-rw-r--r--drivers/staging/lustre/lustre/libcfs/prng.c4
-rw-r--r--drivers/staging/lustre/lustre/llite/dir.c2
-rw-r--r--drivers/staging/lustre/lustre/llite/file.c6
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_close.c2
-rw-r--r--drivers/staging/lustre/lustre/llite/statahead.c2
-rw-r--r--drivers/staging/lustre/lustre/lvfs/fsfilt.c12
-rw-r--r--drivers/staging/lustre/lustre/lvfs/lvfs_lib.c5
-rw-r--r--drivers/staging/lustre/lustre/lvfs/lvfs_linux.c62
-rw-r--r--drivers/staging/lustre/lustre/obdecho/echo_client.c2
-rw-r--r--drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c2
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c20
-rw-r--r--drivers/staging/netlogic/xlr_net.h2
-rw-r--r--drivers/staging/octeon-usb/cvmx-usb.c2
-rw-r--r--drivers/staging/octeon/ethernet-rx.c4
-rw-r--r--drivers/staging/octeon/ethernet-tx.c2
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon.c2
-rw-r--r--drivers/staging/quickstart/quickstart.c4
-rw-r--r--drivers/staging/rtl8187se/r8180_core.c3
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ap.c2
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_br_ext.c5
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_cmd.c2
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_efuse.c12
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ieee80211.c2
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mlme.c20
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mlme_ext.c6
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mp.c2
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_recv.c23
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_security.c2
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_sta_mgt.c7
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_wlan_util.c26
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_xmit.c7
-rw-r--r--drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c423
-rw-r--r--drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c2
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c8
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_dm.c2
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c8
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c8
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c10
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c2
-rw-r--r--drivers/staging/rtl8188eu/hal/usb_halinit.c10
-rw-r--r--drivers/staging/rtl8188eu/hal/usb_ops_linux.c96
-rw-r--r--drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h2
-rw-r--r--drivers/staging/rtl8188eu/include/Hal8188EPhyReg.h2
-rw-r--r--drivers/staging/rtl8188eu/include/HalPhyRf_8188e.h2
-rw-r--r--drivers/staging/rtl8188eu/include/odm.h4
-rw-r--r--drivers/staging/rtl8188eu/include/odm_HWConfig.h4
-rw-r--r--drivers/staging/rtl8188eu/include/odm_debug.h2
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_cmd.h2
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_led.h4
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_mlme.h12
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_mlme_ext.h2
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_mp_phy_regdef.h2
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_recv.h2
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_rf.h2
-rw-r--r--drivers/staging/rtl8188eu/include/sta_info.h2
-rw-r--r--drivers/staging/rtl8188eu/include/wifi.h2
-rw-r--r--drivers/staging/rtl8188eu/os_dep/ioctl_linux.c25
-rw-r--r--drivers/staging/rtl8188eu/os_dep/os_intfs.c2
-rw-r--r--drivers/staging/rtl8188eu/os_dep/osdep_service.c5
-rw-r--r--drivers/staging/rtl8188eu/os_dep/recv_linux.c6
-rw-r--r--drivers/staging/rtl8188eu/os_dep/usb_intf.c3
-rw-r--r--drivers/staging/rtl8192e/dot11d.h2
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c18
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.c1
-rw-r--r--drivers/staging/rtl8192e/rtllib_rx.c13
-rw-r--r--drivers/staging/rtl8192u/r8190_rtl8256.h4
-rw-r--r--drivers/staging/rtl8192u/r8192U.h4
-rw-r--r--drivers/staging/rtl8192u/r8192U_dm.c278
-rw-r--r--drivers/staging/rtl8192u/r819xU_cmdpkt.c101
-rw-r--r--drivers/staging/rtl8192u/r819xU_cmdpkt.h2
-rw-r--r--drivers/staging/rtl8192u/r819xU_firmware.c23
-rw-r--r--drivers/staging/rtl8192u/r819xU_phy.c6
-rw-r--r--drivers/staging/rtl8712/usb_intf.c16
-rw-r--r--drivers/staging/silicom/bpctl_mod.c188
-rw-r--r--drivers/staging/slicoss/slicoss.c6
-rw-r--r--drivers/staging/sm7xxfb/sm7xxfb.c1
-rw-r--r--drivers/staging/speakup/Kconfig4
-rw-r--r--drivers/staging/speakup/kobjects.c72
-rw-r--r--drivers/staging/usbip/stub_dev.c26
-rw-r--r--drivers/staging/usbip/stub_main.c4
-rw-r--r--drivers/staging/usbip/userspace/configure.ac1
-rw-r--r--drivers/staging/usbip/userspace/doc/usbip.88
-rw-r--r--drivers/staging/usbip/userspace/doc/usbipd.827
-rw-r--r--drivers/staging/usbip/userspace/src/usbip_network.c16
-rw-r--r--drivers/staging/usbip/userspace/src/usbip_network.h1
-rw-r--r--drivers/staging/usbip/userspace/src/usbipd.c69
-rw-r--r--drivers/staging/usbip/vhci_hcd.c10
-rw-r--r--drivers/staging/vt6655/bssdb.c11
-rw-r--r--drivers/staging/vt6655/device_main.c4
-rw-r--r--drivers/staging/vt6655/dpc.c7
-rw-r--r--drivers/staging/vt6655/iwctl.c6
-rw-r--r--drivers/staging/vt6655/key.c10
-rw-r--r--drivers/staging/vt6655/vntwifi.c22
-rw-r--r--drivers/staging/vt6655/wcmd.c2
-rw-r--r--drivers/staging/vt6655/wctl.c8
-rw-r--r--drivers/staging/vt6655/wmgr.c3
-rw-r--r--drivers/staging/vt6655/wpactl.c2
-rw-r--r--drivers/staging/vt6656/bssdb.c12
-rw-r--r--drivers/staging/vt6656/channel.c2
-rw-r--r--drivers/staging/vt6656/desc.h9
-rw-r--r--drivers/staging/vt6656/dpc.c13
-rw-r--r--drivers/staging/vt6656/hostap.c2
-rw-r--r--drivers/staging/vt6656/iwctl.c11
-rw-r--r--drivers/staging/vt6656/key.c10
-rw-r--r--drivers/staging/vt6656/main_usb.c3
-rw-r--r--drivers/staging/vt6656/rxtx.c209
-rw-r--r--drivers/staging/vt6656/rxtx.h38
-rw-r--r--drivers/staging/vt6656/wctl.c7
-rw-r--r--drivers/staging/vt6656/wmgr.c6
-rw-r--r--drivers/staging/vt6656/wpactl.c2
-rw-r--r--drivers/staging/winbond/mto.c7
-rw-r--r--drivers/staging/winbond/mto.h8
-rw-r--r--drivers/staging/winbond/phy_calibration.c58
-rw-r--r--drivers/staging/winbond/reg.c16
-rw-r--r--drivers/staging/winbond/wb35tx.c2
-rw-r--r--drivers/staging/wlan-ng/cfg80211.c6
-rw-r--r--drivers/staging/wlan-ng/hfa384x_usb.c90
-rw-r--r--drivers/staging/xgifb/XGI_main_26.c1
-rw-r--r--drivers/thermal/Kconfig2
-rw-r--r--drivers/thermal/x86_pkg_temp_thermal.c14
-rw-r--r--drivers/tty/hvc/hvc_dcc.c21
-rw-r--r--drivers/tty/hvc/hvc_vio.c5
-rw-r--r--drivers/tty/n_tty.c14
-rw-r--r--drivers/tty/serial/8250/8250_core.c2
-rw-r--r--drivers/tty/serial/8250/8250_dw.c34
-rw-r--r--drivers/tty/serial/8250/8250_pci.c2
-rw-r--r--drivers/tty/serial/Kconfig1
-rw-r--r--drivers/tty/serial/arc_uart.c2
-rw-r--r--drivers/tty/serial/bfin_sport_uart.c11
-rw-r--r--drivers/tty/serial/bfin_uart.c15
-rw-r--r--drivers/tty/serial/clps711x.c2
-rw-r--r--drivers/tty/serial/ifx6x60.c2
-rw-r--r--drivers/tty/serial/imx.c5
-rw-r--r--drivers/tty/serial/mfd.c3
-rw-r--r--drivers/tty/serial/mpc52xx_uart.c4
-rw-r--r--drivers/tty/serial/mpsc.c2
-rw-r--r--drivers/tty/serial/omap-serial.c10
-rw-r--r--drivers/tty/serial/pch_uart.c15
-rw-r--r--drivers/tty/serial/samsung.c22
-rw-r--r--drivers/tty/serial/samsung.h2
-rw-r--r--drivers/tty/serial/sccnxp.c1
-rw-r--r--drivers/tty/serial/serial-tegra.c4
-rw-r--r--drivers/tty/serial/serial_txx9.c2
-rw-r--r--drivers/tty/serial/sh-sci.c127
-rw-r--r--drivers/tty/serial/sirfsoc_uart.c11
-rw-r--r--drivers/tty/tty_ioctl.c3
-rw-r--r--drivers/tty/tty_port.c10
-rw-r--r--drivers/tty/vt/vt.c33
-rw-r--r--drivers/uio/uio.c16
-rw-r--r--drivers/uio/uio_aec.c1
-rw-r--r--drivers/uio/uio_cif.c1
-rw-r--r--drivers/uio/uio_mf624.c5
-rw-r--r--drivers/uio/uio_netx.c1
-rw-r--r--drivers/uio/uio_pdrv_genirq.c34
-rw-r--r--drivers/uio/uio_sercos3.c1
-rw-r--r--drivers/usb/chipidea/Kconfig2
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c7
-rw-r--r--drivers/usb/chipidea/core.c20
-rw-r--r--drivers/usb/chipidea/udc.c14
-rw-r--r--drivers/usb/core/devio.c22
-rw-r--r--drivers/usb/core/hcd-pci.c3
-rw-r--r--drivers/usb/core/hcd.c14
-rw-r--r--drivers/usb/core/hub.c18
-rw-r--r--drivers/usb/core/quirks.c37
-rw-r--r--drivers/usb/core/sysfs.c53
-rw-r--r--drivers/usb/core/usb.h1
-rw-r--r--drivers/usb/dwc3/dwc3-pci.c4
-rw-r--r--drivers/usb/early/ehci-dbgp.c4
-rw-r--r--drivers/usb/gadget/amd5536udc.c2
-rw-r--r--drivers/usb/gadget/f_fs.c60
-rw-r--r--drivers/usb/gadget/goku_udc.c1
-rw-r--r--drivers/usb/gadget/net2280.c1
-rw-r--r--drivers/usb/gadget/pch_udc.c1
-rw-r--r--drivers/usb/gadget/pxa25x_udc.c9
-rw-r--r--drivers/usb/gadget/storage_common.c4
-rw-r--r--drivers/usb/host/Kconfig62
-rw-r--r--drivers/usb/host/Makefile10
-rw-r--r--drivers/usb/host/ehci-fsl.c21
-rw-r--r--drivers/usb/host/ehci-grlib.c2
-rw-r--r--drivers/usb/host/ehci-hcd.c7
-rw-r--r--drivers/usb/host/ehci-mv.c2
-rw-r--r--drivers/usb/host/ehci-octeon.c2
-rw-r--r--drivers/usb/host/ehci-pci.c2
-rw-r--r--drivers/usb/host/ehci-pmcmsp.c2
-rw-r--r--drivers/usb/host/ehci-ppc-of.c2
-rw-r--r--drivers/usb/host/ehci-ps3.c2
-rw-r--r--drivers/usb/host/ehci-q.c5
-rw-r--r--drivers/usb/host/ehci-sched.c180
-rw-r--r--drivers/usb/host/ehci-sead3.c2
-rw-r--r--drivers/usb/host/ehci-sh.c2
-rw-r--r--drivers/usb/host/ehci-tilegx.c2
-rw-r--r--drivers/usb/host/ehci-w90x900.c89
-rw-r--r--drivers/usb/host/ehci-xilinx-of.c2
-rw-r--r--drivers/usb/host/ehci.h1
-rw-r--r--drivers/usb/host/imx21-hcd.c8
-rw-r--r--drivers/usb/host/ohci-at91.c156
-rw-r--r--drivers/usb/host/ohci-ep93xx.c72
-rw-r--r--drivers/usb/host/ohci-exynos.c167
-rw-r--r--drivers/usb/host/ohci-hcd.c171
-rw-r--r--drivers/usb/host/ohci-nxp.c123
-rw-r--r--drivers/usb/host/ohci-omap.c156
-rw-r--r--drivers/usb/host/ohci-omap3.c118
-rw-r--r--drivers/usb/host/ohci-pci.c1
-rw-r--r--drivers/usb/host/ohci-pxa27x.c240
-rw-r--r--drivers/usb/host/ohci-q.c26
-rw-r--r--drivers/usb/host/ohci-s3c2410.c136
-rw-r--r--drivers/usb/host/ohci-spear.c140
-rw-r--r--drivers/usb/host/pci-quirks.c116
-rw-r--r--drivers/usb/host/uhci-pci.c4
-rw-r--r--drivers/usb/host/uhci-q.c12
-rw-r--r--drivers/usb/host/xhci-hub.c47
-rw-r--r--drivers/usb/host/xhci-mem.c2
-rw-r--r--drivers/usb/host/xhci-pci.c2
-rw-r--r--drivers/usb/host/xhci-ring.c37
-rw-r--r--drivers/usb/host/xhci.c25
-rw-r--r--drivers/usb/host/xhci.h11
-rw-r--r--drivers/usb/misc/usbtest.c2
-rw-r--r--drivers/usb/phy/Kconfig1
-rw-r--r--drivers/usb/phy/phy-gpio-vbus-usb.c11
-rw-r--r--drivers/usb/serial/ftdi_sio.c10
-rw-r--r--drivers/usb/serial/generic.c10
-rw-r--r--drivers/usb/wusbcore/wa-hc.c14
-rw-r--r--drivers/usb/wusbcore/wa-hc.h4
-rw-r--r--drivers/usb/wusbcore/wa-xfer.c189
-rw-r--r--drivers/video/Kconfig2
-rw-r--r--drivers/video/amba-clcd.c2
-rw-r--r--drivers/video/amifb.c2
-rw-r--r--drivers/video/arkfb.c3
-rw-r--r--drivers/video/atmel_lcdfb.c347
-rw-r--r--drivers/video/aty/aty128fb.c4
-rw-r--r--drivers/video/aty/atyfb_base.c1
-rw-r--r--drivers/video/aty/radeon_base.c5
-rw-r--r--drivers/video/aty/radeon_pm.c22
-rw-r--r--drivers/video/aty/radeonfb.h1
-rw-r--r--drivers/video/au1100fb.c2
-rw-r--r--drivers/video/backlight/atmel-pwm-bl.c9
-rw-r--r--drivers/video/bw2.c2
-rw-r--r--drivers/video/carminefb.c1
-rw-r--r--drivers/video/cg14.c2
-rw-r--r--drivers/video/cg3.c2
-rw-r--r--drivers/video/cg6.c2
-rw-r--r--drivers/video/cirrusfb.c6
-rw-r--r--drivers/video/cyber2000fb.c75
-rw-r--r--drivers/video/da8xx-fb.c6
-rw-r--r--drivers/video/ep93xx-fb.c2
-rw-r--r--drivers/video/ffb.c2
-rw-r--r--drivers/video/geode/gx1fb_core.c1
-rw-r--r--drivers/video/geode/gxfb_core.c1
-rw-r--r--drivers/video/geode/lxfb_core.c1
-rw-r--r--drivers/video/grvga.c16
-rw-r--r--drivers/video/i740fb.c1
-rw-r--r--drivers/video/i810/i810_main.c1
-rw-r--r--drivers/video/imxfb.c6
-rw-r--r--drivers/video/intelfb/intelfbdrv.c2
-rw-r--r--drivers/video/jz4740_fb.c16
-rw-r--r--drivers/video/kyro/fbdev.c2
-rw-r--r--drivers/video/leo.c2
-rw-r--r--drivers/video/matrox/matroxfb_maven.c14
-rw-r--r--drivers/video/mb862xx/mb862xxfbdrv.c3
-rw-r--r--drivers/video/mbx/mbxfb.c2
-rw-r--r--drivers/video/mmp/fb/mmpfb.c34
-rw-r--r--drivers/video/mmp/hw/mmp_ctrl.c71
-rw-r--r--drivers/video/mmp/hw/mmp_ctrl.h5
-rw-r--r--drivers/video/mx3fb.c4
-rw-r--r--drivers/video/neofb.c6
-rw-r--r--drivers/video/nuc900fb.c6
-rw-r--r--drivers/video/omap/hwa742.c2
-rw-r--r--drivers/video/omap/omapfb_main.c4
-rw-r--r--drivers/video/omap2/dss/dispc.c8
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c70
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h65
-rw-r--r--drivers/video/p9100.c2
-rw-r--r--drivers/video/platinumfb.c1
-rw-r--r--drivers/video/pm2fb.c1
-rw-r--r--drivers/video/pm3fb.c1
-rw-r--r--drivers/video/pxa168fb.c6
-rw-r--r--drivers/video/pxafb.c16
-rw-r--r--drivers/video/riva/fbdev.c5
-rw-r--r--drivers/video/s1d13xxxfb.c12
-rw-r--r--drivers/video/s3c-fb.c2
-rw-r--r--drivers/video/s3c2410fb.c6
-rw-r--r--drivers/video/s3fb.c1
-rw-r--r--drivers/video/sa1100fb.c4
-rw-r--r--drivers/video/savage/savagefb_driver.c6
-rw-r--r--drivers/video/sh_mobile_hdmi.c6
-rw-r--r--drivers/video/simplefb.c4
-rw-r--r--drivers/video/sis/sis_main.c4
-rw-r--r--drivers/video/smscufx.c2
-rw-r--r--drivers/video/sunxvr1000.c2
-rw-r--r--drivers/video/tcx.c2
-rw-r--r--drivers/video/tdfxfb.c1
-rw-r--r--drivers/video/tmiofb.c10
-rw-r--r--drivers/video/tridentfb.c1
-rw-r--r--drivers/video/udlfb.c2
-rw-r--r--drivers/video/uvesafb.c19
-rw-r--r--drivers/video/vfb.c5
-rw-r--r--drivers/video/vt8623fb.c1
-rw-r--r--drivers/video/w100fb.c2
-rw-r--r--drivers/video/xilinxfb.c2
-rw-r--r--drivers/watchdog/Kconfig2
-rw-r--r--drivers/watchdog/Makefile2
-rw-r--r--drivers/watchdog/hpwdt.c6
-rw-r--r--fs/9p/cache.c6
-rw-r--r--fs/9p/cache.h12
-rw-r--r--fs/9p/vfs_addr.c12
-rw-r--r--fs/9p/vfs_file.c10
-rw-r--r--fs/9p/vfs_inode.c6
-rw-r--r--fs/9p/vfs_inode_dotl.c4
-rw-r--r--fs/Makefile2
-rw-r--r--fs/adfs/file.c4
-rw-r--r--fs/affs/file.c4
-rw-r--r--fs/afs/cell.c2
-rw-r--r--fs/afs/file.c4
-rw-r--r--fs/afs/inode.c2
-rw-r--r--fs/afs/internal.h3
-rw-r--r--fs/afs/vlocation.c3
-rw-r--r--fs/afs/volume.c2
-rw-r--r--fs/afs/write.c9
-rw-r--r--fs/aio.c136
-rw-r--r--fs/bad_inode.c14
-rw-r--r--fs/befs/linuxvfs.c61
-rw-r--r--fs/bfs/file.c4
-rw-r--r--fs/block_dev.c27
-rw-r--r--fs/btrfs/ctree.h5
-rw-r--r--fs/btrfs/file.c42
-rw-r--r--fs/btrfs/inode.c63
-rw-r--r--fs/btrfs/ioctl.c8
-rw-r--r--fs/cachefiles/interface.c2
-rw-r--r--fs/ceph/addr.c3
-rw-r--r--fs/ceph/cache.c7
-rw-r--r--fs/ceph/caps.c27
-rw-r--r--fs/ceph/dir.c11
-rw-r--r--fs/ceph/file.c273
-rw-r--r--fs/ceph/inode.c57
-rw-r--r--fs/ceph/mds_client.c53
-rw-r--r--fs/ceph/mds_client.h1
-rw-r--r--fs/ceph/super.c1
-rw-r--r--fs/ceph/super.h9
-rw-r--r--fs/cifs/cifsfs.c2
-rw-r--r--fs/cifs/cifsfs.h4
-rw-r--r--fs/cifs/cifsglob.h5
-rw-r--r--fs/cifs/cifspdu.h21
-rw-r--r--fs/cifs/cifssmb.c1
-rw-r--r--fs/cifs/file.c12
-rw-r--r--fs/cifs/fscache.c15
-rw-r--r--fs/cifs/fscache.h13
-rw-r--r--fs/cifs/inode.c45
-rw-r--r--fs/cifs/link.c7
-rw-r--r--fs/cifs/readdir.c3
-rw-r--r--fs/cifs/sess.c84
-rw-r--r--fs/dcache.c26
-rw-r--r--fs/direct-io.c223
-rw-r--r--fs/ecryptfs/dentry.c29
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h19
-rw-r--r--fs/ecryptfs/file.c15
-rw-r--r--fs/ecryptfs/inode.c16
-rw-r--r--fs/ecryptfs/main.c3
-rw-r--r--fs/exofs/file.c4
-rw-r--r--fs/ext2/file.c4
-rw-r--r--fs/ext2/inode.c8
-rw-r--r--fs/ext3/file.c4
-rw-r--r--fs/ext3/inode.c15
-rw-r--r--fs/ext4/ext4.h3
-rw-r--r--fs/ext4/file.c34
-rw-r--r--fs/ext4/indirect.c16
-rw-r--r--fs/ext4/inode.c23
-rw-r--r--fs/f2fs/checkpoint.c2
-rw-r--r--fs/f2fs/data.c4
-rw-r--r--fs/f2fs/f2fs.h4
-rw-r--r--fs/f2fs/file.c4
-rw-r--r--fs/f2fs/gc.c15
-rw-r--r--fs/f2fs/recovery.c24
-rw-r--r--fs/f2fs/segment.c4
-rw-r--r--fs/f2fs/segment.h2
-rw-r--r--fs/f2fs/super.c17
-rw-r--r--fs/f2fs/xattr.c35
-rw-r--r--fs/fat/file.c4
-rw-r--r--fs/fat/inode.c10
-rw-r--r--fs/fscache/cookie.c193
-rw-r--r--fs/fscache/fsdef.c1
-rw-r--r--fs/fscache/netfs.c1
-rw-r--r--fs/fscache/object.c7
-rw-r--r--fs/fscache/page.c59
-rw-r--r--fs/fuse/cuse.c15
-rw-r--r--fs/fuse/dir.c42
-rw-r--r--fs/fuse/file.c436
-rw-r--r--fs/fuse/fuse_i.h9
-rw-r--r--fs/fuse/inode.c2
-rw-r--r--fs/gfs2/aops.c7
-rw-r--r--fs/gfs2/file.c21
-rw-r--r--fs/gfs2/incore.h13
-rw-r--r--fs/gfs2/inode.c39
-rw-r--r--fs/gfs2/rgrp.c142
-rw-r--r--fs/hfs/inode.c11
-rw-r--r--fs/hfsplus/inode.c10
-rw-r--r--fs/hostfs/hostfs_kern.c4
-rw-r--r--fs/hpfs/file.c4
-rw-r--r--fs/internal.h4
-rw-r--r--fs/iov-iter.c411
-rw-r--r--fs/jffs2/file.c8
-rw-r--r--fs/jfs/file.c4
-rw-r--r--fs/jfs/inode.c7
-rw-r--r--fs/jfs/jfs_inode.c3
-rw-r--r--fs/libfs.c79
-rw-r--r--fs/logfs/dev_mtd.c2
-rw-r--r--fs/logfs/file.c4
-rw-r--r--fs/logfs/super.c6
-rw-r--r--fs/minix/Kconfig2
-rw-r--r--fs/minix/file.c4
-rw-r--r--fs/namespace.c22
-rw-r--r--fs/ncpfs/dir.c55
-rw-r--r--fs/ncpfs/file.c12
-rw-r--r--fs/nfs/dir.c121
-rw-r--r--fs/nfs/direct.c316
-rw-r--r--fs/nfs/file.c146
-rw-r--r--fs/nfs/fscache.c196
-rw-r--r--fs/nfs/fscache.h18
-rw-r--r--fs/nfs/inode.c6
-rw-r--r--fs/nfs/internal.h4
-rw-r--r--fs/nfs/namespace.c5
-rw-r--r--fs/nfs/nfs3proc.c8
-rw-r--r--fs/nfs/nfs4file.c10
-rw-r--r--fs/nfs/nfs4namespace.c7
-rw-r--r--fs/nfs/nfs4proc.c5
-rw-r--r--fs/nfs/proc.c8
-rw-r--r--fs/nfs/unlink.c9
-rw-r--r--fs/nfs/write.c6
-rw-r--r--fs/nfsd/nfs4recover.c12
-rw-r--r--fs/nfsd/nfs4state.c15
-rw-r--r--fs/nfsd/nfsfh.c28
-rw-r--r--fs/nfsd/nfsfh.h4
-rw-r--r--fs/nfsd/vfs.c9
-rw-r--r--fs/nilfs2/file.c4
-rw-r--r--fs/nilfs2/inode.c8
-rw-r--r--fs/ocfs2/aops.c8
-rw-r--r--fs/ocfs2/aops.h2
-rw-r--r--fs/ocfs2/file.c55
-rw-r--r--fs/ocfs2/ocfs2_trace.h6
-rw-r--r--fs/omfs/file.c4
-rw-r--r--fs/proc/self.c10
-rw-r--r--fs/ramfs/file-mmu.c4
-rw-r--r--fs/ramfs/file-nommu.c4
-rw-r--r--fs/read_write.c78
-rw-r--r--fs/reiserfs/file.c4
-rw-r--r--fs/reiserfs/inode.c7
-rw-r--r--fs/reiserfs/journal.c67
-rw-r--r--fs/romfs/mmap-nommu.c2
-rw-r--r--fs/sysfs/bin.c2
-rw-r--r--fs/sysfs/dir.c165
-rw-r--r--fs/sysfs/file.c105
-rw-r--r--fs/sysfs/group.c29
-rw-r--r--fs/sysfs/inode.c6
-rw-r--r--fs/sysfs/mount.c24
-rw-r--r--fs/sysfs/symlink.c49
-rw-r--r--fs/sysfs/sysfs.h43
-rw-r--r--fs/sysv/file.c4
-rw-r--r--fs/ubifs/dir.c41
-rw-r--r--fs/ubifs/file.c12
-rw-r--r--fs/ubifs/journal.c6
-rw-r--r--fs/ubifs/xattr.c16
-rw-r--r--fs/udf/file.c13
-rw-r--r--fs/udf/ialloc.c16
-rw-r--r--fs/udf/inode.c10
-rw-r--r--fs/udf/super.c64
-rw-r--r--fs/udf/udf_sb.h2
-rw-r--r--fs/ufs/file.c4
-rw-r--r--fs/xfs/xfs_aops.c13
-rw-r--r--fs/xfs/xfs_buf_item.c1
-rw-r--r--fs/xfs/xfs_file.c51
-rw-r--r--fs/xfs/xfs_fs.h2
-rw-r--r--fs/xfs/xfs_icache.c9
-rw-r--r--fs/xfs/xfs_log_recover.c73
-rw-r--r--include/acpi/acexcep.h8
-rw-r--r--include/acpi/acpixf.h15
-rw-r--r--include/acpi/actypes.h8
-rw-r--r--include/acpi/platform/aclinux.h2
-rw-r--r--include/acpi/processor.h3
-rw-r--r--include/asm-generic/preempt.h113
-rw-r--r--include/asm-generic/simd.h14
-rw-r--r--include/crypto/ablk_helper.h (renamed from arch/x86/include/asm/crypto/ablk_helper.h)0
-rw-r--r--include/drm/drmP.h5
-rw-r--r--include/drm/drm_crtc.h24
-rw-r--r--include/linux/acpi.h83
-rw-r--r--include/linux/aio.h17
-rw-r--r--include/linux/bcma/bcma_driver_pci.h1
-rw-r--r--include/linux/bio.h8
-rw-r--r--include/linux/blk_types.h2
-rw-r--r--include/linux/blockconsole.h7
-rw-r--r--include/linux/cgroup.h37
-rw-r--r--include/linux/clocksource.h2
-rw-r--r--include/linux/console.h1
-rw-r--r--include/linux/dcache.h1
-rw-r--r--include/linux/device.h24
-rw-r--r--include/linux/fs.h171
-rw-r--r--include/linux/fscache-cache.h50
-rw-r--r--include/linux/fscache.h113
-rw-r--r--include/linux/hardirq.h8
-rw-r--r--include/linux/hwmon-vid.h2
-rw-r--r--include/linux/hwmon.h10
-rw-r--r--include/linux/hyperv.h44
-rw-r--r--include/linux/iio/buffer.h31
-rw-r--r--include/linux/iio/common/st_sensors.h1
-rw-r--r--include/linux/iio/consumer.h2
-rw-r--r--include/linux/iio/iio.h35
-rw-r--r--include/linux/iio/sysfs.h15
-rw-r--r--include/linux/intel-iommu.h2
-rw-r--r--include/linux/iommu.h2
-rw-r--r--include/linux/irqchip/arm-gic.h5
-rw-r--r--include/linux/kernel.h11
-rw-r--r--include/linux/kobj_completion.h18
-rw-r--r--include/linux/kobject.h1
-rw-r--r--include/linux/kvm_host.h1
-rw-r--r--include/linux/mfd/arizona/registers.h2
-rw-r--r--include/linux/mfd/da9052/da9052.h20
-rw-r--r--include/linux/mfd/mc13xxx.h7
-rw-r--r--include/linux/mfd/rtsx_pci.h53
-rw-r--r--include/linux/mfd/stw481x.h56
-rw-r--r--include/linux/mfd/syscon/imx6q-iomuxc-gpr.h5
-rw-r--r--include/linux/mfd/ti_am335x_tscadc.h29
-rw-r--r--include/linux/mfd/wm8994/core.h47
-rw-r--r--include/linux/miscdevice.h1
-rw-r--r--include/linux/mmc/card.h2
-rw-r--r--include/linux/mmc/core.h1
-rw-r--r--include/linux/mmc/dw_mmc.h4
-rw-r--r--include/linux/mount.h2
-rw-r--r--include/linux/mtd/nand.h2
-rw-r--r--include/linux/netdevice.h71
-rw-r--r--include/linux/nfs_fs.h21
-rw-r--r--include/linux/of_mtd.h21
-rw-r--r--include/linux/platform_data/leds-lp55xx.h1
-rw-r--r--include/linux/platform_data/mmc-esdhc-imx.h4
-rw-r--r--include/linux/platform_data/pinctrl-adi2.h40
-rw-r--r--include/linux/platform_device.h1
-rw-r--r--include/linux/preempt.h112
-rw-r--r--include/linux/random.h1
-rw-r--r--include/linux/rculist.h23
-rw-r--r--include/linux/rcupdate.h36
-rw-r--r--include/linux/rcutiny.h17
-rw-r--r--include/linux/rcutree.h2
-rw-r--r--include/linux/regmap.h15
-rw-r--r--include/linux/regulator/driver.h9
-rw-r--r--include/linux/regulator/machine.h7
-rw-r--r--include/linux/sched.h98
-rw-r--r--include/linux/sched/sysctl.h2
-rw-r--r--include/linux/sched_clock.h2
-rw-r--r--include/linux/security.h26
-rw-r--r--include/linux/serial_sci.h6
-rw-r--r--include/linux/spi/rspi.h2
-rw-r--r--include/linux/spi/spi.h2
-rw-r--r--include/linux/sysfs.h88
-rw-r--r--include/linux/thread_info.h17
-rw-r--r--include/linux/timex.h14
-rw-r--r--include/linux/topology.h6
-rw-r--r--include/linux/tty.h1
-rw-r--r--include/linux/uaccess.h8
-rw-r--r--include/linux/usb.h2
-rw-r--r--include/linux/usb/hcd.h10
-rw-r--r--include/media/videobuf2-core.h4
-rw-r--r--include/media/videobuf2-dma-sg.h10
-rw-r--r--include/net/bluetooth/bluetooth.h17
-rw-r--r--include/net/bluetooth/hci.h10
-rw-r--r--include/net/bluetooth/hci_core.h24
-rw-r--r--include/net/bluetooth/mgmt.h3
-rw-r--r--include/net/bluetooth/rfcomm.h4
-rw-r--r--include/net/caif/caif_hsi.h2
-rw-r--r--include/net/compat.h48
-rw-r--r--include/net/dcbevent.h6
-rw-r--r--include/net/dn.h20
-rw-r--r--include/net/dn_dev.h30
-rw-r--r--include/net/dn_fib.h47
-rw-r--r--include/net/dn_neigh.h12
-rw-r--r--include/net/dn_nsp.h49
-rw-r--r--include/net/dn_route.h13
-rw-r--r--include/net/dst.h25
-rw-r--r--include/net/esp.h2
-rw-r--r--include/net/fib_rules.h17
-rw-r--r--include/net/flow.h11
-rw-r--r--include/net/flow_keys.h2
-rw-r--r--include/net/garp.h27
-rw-r--r--include/net/gen_stats.h51
-rw-r--r--include/net/genetlink.h26
-rw-r--r--include/net/icmp.h10
-rw-r--r--include/net/inet6_connection_sock.h32
-rw-r--r--include/net/inet6_hashtables.h38
-rw-r--r--include/net/inet_common.h48
-rw-r--r--include/net/inet_connection_sock.h79
-rw-r--r--include/net/inet_hashtables.h72
-rw-r--r--include/net/inet_sock.h4
-rw-r--r--include/net/inet_timewait_sock.h37
-rw-r--r--include/net/inetpeer.h12
-rw-r--r--include/net/ip.h169
-rw-r--r--include/net/ip6_fib.h53
-rw-r--r--include/net/ip6_route.h98
-rw-r--r--include/net/ip_fib.h61
-rw-r--r--include/net/ip_vs.h245
-rw-r--r--include/net/ipv6.h268
-rw-r--r--include/net/ipx.h12
-rw-r--r--include/net/irda/ircomm_tty.h14
-rw-r--r--include/net/irda/irda.h21
-rw-r--r--include/net/irda/irlap_event.h2
-rw-r--r--include/net/irda/irlap_frame.h4
-rw-r--r--include/net/iw_handler.h38
-rw-r--r--include/net/lapb.h52
-rw-r--r--include/net/llc.h50
-rw-r--r--include/net/llc_c_ac.h190
-rw-r--r--include/net/llc_c_ev.h207
-rw-r--r--include/net/llc_conn.h36
-rw-r--r--include/net/llc_if.h7
-rw-r--r--include/net/llc_pdu.h33
-rw-r--r--include/net/llc_s_ac.h20
-rw-r--r--include/net/llc_s_ev.h21
-rw-r--r--include/net/llc_sap.h22
-rw-r--r--include/net/mrp.h23
-rw-r--r--include/net/ndisc.h61
-rw-r--r--include/net/net_namespace.h28
-rw-r--r--include/net/netevent.h6
-rw-r--r--include/net/netfilter/ipv4/nf_conntrack_ipv4.h6
-rw-r--r--include/net/netfilter/ipv4/nf_defrag_ipv4.h2
-rw-r--r--include/net/netfilter/ipv6/nf_defrag_ipv6.h17
-rw-r--r--include/net/netfilter/nf_conntrack.h69
-rw-r--r--include/net/netfilter/nf_conntrack_acct.h12
-rw-r--r--include/net/netfilter/nf_conntrack_core.h69
-rw-r--r--include/net/netfilter/nf_conntrack_ecache.h22
-rw-r--r--include/net/netfilter/nf_conntrack_extend.h2
-rw-r--r--include/net/netfilter/nf_conntrack_helper.h40
-rw-r--r--include/net/netfilter/nf_conntrack_l3proto.h16
-rw-r--r--include/net/netfilter/nf_conntrack_l4proto.h32
-rw-r--r--include/net/netfilter/nf_conntrack_seqadj.h30
-rw-r--r--include/net/netfilter/nf_conntrack_synproxy.h28
-rw-r--r--include/net/netfilter/nf_conntrack_timeout.h4
-rw-r--r--include/net/netfilter/nf_conntrack_timestamp.h8
-rw-r--r--include/net/netfilter/nf_nat.h10
-rw-r--r--include/net/netfilter/nf_nat_core.h8
-rw-r--r--include/net/netfilter/nf_nat_helper.h29
-rw-r--r--include/net/netfilter/nf_nat_l3proto.h23
-rw-r--r--include/net/netfilter/nf_nat_l4proto.h30
-rw-r--r--include/net/netfilter/nf_queue.h2
-rw-r--r--include/net/netfilter/xt_rateest.h4
-rw-r--r--include/net/netlink.h63
-rw-r--r--include/net/netrom.h89
-rw-r--r--include/net/p8022.h18
-rw-r--r--include/net/ping.h4
-rw-r--r--include/net/protocol.h24
-rw-r--r--include/net/psnap.h4
-rw-r--r--include/net/raw.h6
-rw-r--r--include/net/rawv6.h3
-rw-r--r--include/net/request_sock.h14
-rw-r--r--include/net/rose.h114
-rw-r--r--include/net/route.h53
-rw-r--r--include/net/rtnetlink.h40
-rw-r--r--include/net/sch_generic.h11
-rw-r--r--include/net/scm.h10
-rw-r--r--include/net/sctp/sctp.h13
-rw-r--r--include/net/secure_seq.h28
-rw-r--r--include/net/sock.h223
-rw-r--r--include/net/stp.h4
-rw-r--r--include/net/tcp.h442
-rw-r--r--include/net/udp.h94
-rw-r--r--include/net/udplite.h6
-rw-r--r--include/net/wext.h16
-rw-r--r--include/net/wimax.h33
-rw-r--r--include/net/x25.h141
-rw-r--r--include/net/xfrm.h381
-rw-r--r--include/sound/soc-dai.h3
-rw-r--r--include/sound/soc.h95
-rw-r--r--include/trace/events/asoc.h1
-rw-r--r--include/trace/events/bcache.h47
-rw-r--r--include/trace/events/iommu.h162
-rw-r--r--include/trace/events/random.h33
-rw-r--r--include/trace/events/rcu.h80
-rw-r--r--include/trace/events/sched.h2
-rw-r--r--include/uapi/drm/drm.h37
-rw-r--r--include/uapi/drm/drm_mode.h38
-rw-r--r--include/uapi/drm/i915_drm.h8
-rw-r--r--include/uapi/linux/Kbuild2
-rw-r--r--include/uapi/linux/aio_abi.h2
-rw-r--r--include/uapi/linux/audit.h1
-rw-r--r--include/uapi/linux/bcache.h373
-rw-r--r--include/uapi/linux/elf-em.h1
-rw-r--r--include/uapi/linux/loop.h1
-rw-r--r--include/uapi/linux/mic_common.h238
-rw-r--r--include/uapi/linux/mic_ioctl.h74
-rw-r--r--include/uapi/linux/pci_regs.h3
-rw-r--r--include/uapi/linux/pkt_sched.h2
-rw-r--r--include/video/atmel_lcdc.h25
-rw-r--r--include/video/mmp_disp.h6
-rw-r--r--init/do_mounts.c2
-rw-r--r--init/main.c4
-rw-r--r--kernel/cgroup.c256
-rw-r--r--kernel/context_tracking.c2
-rw-r--r--kernel/cpu/idle.c16
-rw-r--r--kernel/events/core.c13
-rw-r--r--kernel/hung_task.c2
-rw-r--r--kernel/lockdep.c4
-rw-r--r--kernel/notifier.c2
-rw-r--r--kernel/printk/printk.c5
-rw-r--r--kernel/rcu.h7
-rw-r--r--kernel/rcupdate.c4
-rw-r--r--kernel/rcutiny.c29
-rw-r--r--kernel/rcutree.c189
-rw-r--r--kernel/rcutree.h2
-rw-r--r--kernel/rcutree_plugin.h80
-rw-r--r--kernel/sched/core.c80
-rw-r--r--kernel/sched/fair.c217
-rw-r--r--kernel/sched/sched.h4
-rw-r--r--kernel/sched/stats.h46
-rw-r--r--kernel/softirq.c16
-rw-r--r--kernel/sysctl.c5
-rw-r--r--kernel/time/clocksource.c46
-rw-r--r--kernel/time/ntp.c3
-rw-r--r--kernel/time/sched_clock.c111
-rw-r--r--kernel/timer.c8
-rw-r--r--kernel/workqueue.c41
-rw-r--r--lib/hexdump.c2
-rw-r--r--lib/kobject.c86
-rw-r--r--lib/locking-selftest.c2
-rw-r--r--lib/lzo/lzo1x_decompress_safe.c4
-rw-r--r--lib/lzo/lzodefs.h6
-rw-r--r--lib/smp_processor_id.c3
-rw-r--r--mm/filemap.c433
-rw-r--r--mm/memcontrol.c66
-rw-r--r--mm/page_io.c15
-rw-r--r--mm/percpu.c5
-rw-r--r--mm/shmem.c61
-rw-r--r--net/802/mrp.c27
-rw-r--r--net/8021q/vlan.c18
-rw-r--r--net/bluetooth/af_bluetooth.c41
-rw-r--r--net/bluetooth/hci_conn.c1
-rw-r--r--net/bluetooth/hci_core.c132
-rw-r--r--net/bluetooth/hci_event.c18
-rw-r--r--net/bluetooth/hci_sock.c204
-rw-r--r--net/bluetooth/l2cap_core.c75
-rw-r--r--net/bluetooth/l2cap_sock.c10
-rw-r--r--net/bluetooth/mgmt.c266
-rw-r--r--net/bluetooth/rfcomm/sock.c7
-rw-r--r--net/bluetooth/rfcomm/tty.c35
-rw-r--r--net/bridge/br_mdb.c2
-rw-r--r--net/bridge/br_multicast.c4
-rw-r--r--net/core/dev.c404
-rw-r--r--net/core/neighbour.c2
-rw-r--r--net/core/net-sysfs.c14
-rw-r--r--net/decnet/dn_route.c5
-rw-r--r--net/ethernet/eth.c6
-rw-r--r--net/ipv4/ip_sockglue.c2
-rw-r--r--net/ipv4/ip_vti.c67
-rw-r--r--net/ipv4/raw.c4
-rw-r--r--net/ipv4/syncookies.c53
-rw-r--r--net/ipv4/tcp_input.c84
-rw-r--r--net/ipv4/udp.c2
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c16
-rw-r--r--net/ipv4/xfrm4_policy.c1
-rw-r--r--net/ipv6/af_inet6.c48
-rw-r--r--net/ipv6/ah6.c3
-rw-r--r--net/ipv6/esp6.c3
-rw-r--r--net/ipv6/ip6_gre.c2
-rw-r--r--net/ipv6/ip6_output.c53
-rw-r--r--net/ipv6/ip6_tunnel.c2
-rw-r--r--net/ipv6/ipcomp6.c3
-rw-r--r--net/ipv6/raw.c4
-rw-r--r--net/ipv6/sit.c2
-rw-r--r--net/ipv6/syncookies.c39
-rw-r--r--net/ipv6/udp.c4
-rw-r--r--net/ipv6/xfrm6_policy.c1
-rw-r--r--net/key/af_key.c3
-rw-r--r--net/lapb/lapb_timer.c1
-rw-r--r--net/mac80211/sta_info.c4
-rw-r--r--net/sched/act_police.c4
-rw-r--r--net/sched/sch_generic.c5
-rw-r--r--net/sched/sch_htb.c17
-rw-r--r--net/sched/sch_tbf.c4
-rw-r--r--net/sunrpc/rpc_pipe.c12
-rw-r--r--net/wireless/scan.c14
-rw-r--r--net/xfrm/xfrm_replay.c54
-rw-r--r--net/xfrm/xfrm_state.c2
-rw-r--r--net/xfrm/xfrm_user.c5
-rw-r--r--security/Makefile1
-rw-r--r--security/capability.c15
-rw-r--r--security/security.c13
-rw-r--r--security/selinux/hooks.c146
-rw-r--r--security/selinux/include/objsec.h4
-rw-r--r--security/selinux/include/security.h13
-rw-r--r--security/selinux/include/xfrm.h45
-rw-r--r--security/selinux/netlabel.c6
-rw-r--r--security/selinux/netnode.c2
-rw-r--r--security/selinux/selinuxfs.c4
-rw-r--r--security/selinux/ss/ebitmap.c20
-rw-r--r--security/selinux/ss/ebitmap.h10
-rw-r--r--security/selinux/ss/mls.c22
-rw-r--r--security/selinux/ss/mls_types.h2
-rw-r--r--security/selinux/ss/policydb.c3
-rw-r--r--security/selinux/ss/services.c66
-rw-r--r--security/selinux/xfrm.c453
-rw-r--r--sound/core/compress_offload.c15
-rw-r--r--sound/firewire/amdtp.c4
-rw-r--r--sound/pci/asihpi/asihpi.c9
-rw-r--r--sound/pci/au88x0/au88x0_synth.c29
-rw-r--r--sound/pci/azt3328.c14
-rw-r--r--sound/pci/ctxfi/ctdaio.c4
-rw-r--r--sound/pci/hda/patch_ca0132.c2
-rw-r--r--sound/pci/hda/patch_hdmi.c47
-rw-r--r--sound/pci/rme9652/hdspm.c5
-rw-r--r--sound/soc/Makefile2
-rw-r--r--sound/soc/blackfin/bf6xx-i2s.c1
-rw-r--r--sound/soc/codecs/88pm860x-codec.c78
-rw-r--r--sound/soc/codecs/88pm860x-codec.h117
-rw-r--r--sound/soc/codecs/ab8500-codec.c85
-rw-r--r--sound/soc/codecs/ak4104.c11
-rw-r--r--sound/soc/codecs/ak4642.c2
-rw-r--r--sound/soc/codecs/arizona.c23
-rw-r--r--sound/soc/codecs/cq93vc.c46
-rw-r--r--sound/soc/codecs/max98088.c624
-rw-r--r--sound/soc/codecs/max98095.c470
-rw-r--r--sound/soc/codecs/max9850.c39
-rw-r--r--sound/soc/codecs/mc13783.c59
-rw-r--r--sound/soc/codecs/rt5640.c15
-rw-r--r--sound/soc/codecs/sn95031.c35
-rw-r--r--sound/soc/codecs/tlv320aic23.c84
-rw-r--r--sound/soc/codecs/tlv320aic26.c139
-rw-r--r--sound/soc/codecs/tlv320aic26.h5
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c101
-rw-r--r--sound/soc/codecs/tlv320aic3x.c233
-rw-r--r--sound/soc/codecs/twl6040.c4
-rw-r--r--sound/soc/codecs/wm8400.c95
-rw-r--r--sound/soc/davinci/davinci-evm.c64
-rw-r--r--sound/soc/fsl/fsl_spdif.c18
-rw-r--r--sound/soc/fsl/fsl_ssi.c22
-rw-r--r--sound/soc/fsl/imx-sgtl5000.c11
-rw-r--r--sound/soc/fsl/imx-spdif.c4
-rw-r--r--sound/soc/fsl/imx-wm8962.c3
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c4
-rw-r--r--sound/soc/mid-x86/mfld_machine.c10
-rw-r--r--sound/soc/mxs/mxs-saif.c12
-rw-r--r--sound/soc/mxs/mxs-sgtl5000.c20
-rw-r--r--sound/soc/omap/omap-mcpdm.c12
-rw-r--r--sound/soc/omap/omap-twl4030.c5
-rw-r--r--sound/soc/pxa/mmp-sspa.c5
-rw-r--r--sound/soc/samsung/bells.c1
-rw-r--r--sound/soc/samsung/i2s.c14
-rw-r--r--sound/soc/samsung/smdk_wm8994.c12
-rw-r--r--sound/soc/sh/rcar/adg.c11
-rw-r--r--sound/soc/sh/rcar/core.c45
-rw-r--r--sound/soc/sh/rcar/gen.c261
-rw-r--r--sound/soc/sh/rcar/rsnd.h4
-rw-r--r--sound/soc/soc-cache.c263
-rw-r--r--sound/soc/soc-core.c319
-rw-r--r--sound/soc/soc-devres.c86
-rw-r--r--sound/soc/soc-io.c26
-rw-r--r--sound/soc/soc-utils.c6
-rw-r--r--sound/soc/spear/spdif_in.c12
-rw-r--r--sound/soc/spear/spdif_out.c14
-rw-r--r--sound/usb/card.c8
-rw-r--r--sound/usb/card.h10
-rw-r--r--sound/usb/endpoint.c106
-rw-r--r--sound/usb/endpoint.h2
-rw-r--r--sound/usb/mixer.c4
-rw-r--r--sound/usb/pcm.c14
-rw-r--r--sound/usb/usbaudio.h1
-rw-r--r--tools/hv/hv_kvp_daemon.c29
-rw-r--r--tools/hv/hv_vss_daemon.c8
-rw-r--r--tools/perf/builtin-kmem.c2
-rw-r--r--tools/perf/builtin-trace.c1
-rw-r--r--tools/perf/config/Makefile2
-rw-r--r--tools/perf/util/machine.c2
-rw-r--r--tools/perf/util/probe-finder.c77
-rw-r--r--tools/perf/util/probe-finder.h3
-rw-r--r--tools/perf/util/symbol-elf.c27
-rw-r--r--tools/power/x86/turbostat/turbostat.c155
-rw-r--r--tools/testing/ktest/examples/crosstests.conf6
-rw-r--r--virt/kvm/async_pf.c5
2668 files changed, 79426 insertions, 57837 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index 39c8de0e53d0..ab1047c20495 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -811,3 +811,14 @@ Description:
Writing '1' stores the current device configuration into
on-chip EEPROM. After power-up or chip reset the device will
automatically load the saved configuration.
+
+What: /sys/.../iio:deviceX/in_intensity_red_integration_time
+What: /sys/.../iio:deviceX/in_intensity_green_integration_time
+What: /sys/.../iio:deviceX/in_intensity_blue_integration_time
+What: /sys/.../iio:deviceX/in_intensity_clear_integration_time
+What: /sys/.../iio:deviceX/in_illuminance_integration_time
+KernelVersion: 3.12
+Contact: linux-iio@vger.kernel.org
+Description:
+ This attribute is used to get/set the integration time in
+ seconds.
diff --git a/Documentation/ABI/testing/sysfs-class-mic.txt b/Documentation/ABI/testing/sysfs-class-mic.txt
new file mode 100644
index 000000000000..82cdad3b614a
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-mic.txt
@@ -0,0 +1,147 @@
+What: /sys/class/mic/
+Date: August 2013
+KernelVersion: 3.11
+Contact: Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+ The mic class directory belongs to Intel MIC devices and
+ provides information per MIC device. An Intel MIC device is a
+ PCIe form factor add-in Coprocessor card based on the Intel Many
+ Integrated Core (MIC) architecture that runs a Linux OS.
+
+What: /sys/class/mic/mic(x)
+Date: August 2013
+KernelVersion: 3.11
+Contact: Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+ The directories /sys/class/mic/mic0, /sys/class/mic/mic1 etc.,
+ represent MIC devices (0,1,..etc). Each directory has
+ information specific to that MIC device.
+
+What: /sys/class/mic/mic(x)/family
+Date: August 2013
+KernelVersion: 3.11
+Contact: Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+ Provides information about the Coprocessor family for an Intel
+ MIC device. For example - "x100"
+
+What: /sys/class/mic/mic(x)/stepping
+Date: August 2013
+KernelVersion: 3.11
+Contact: Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+ Provides information about the silicon stepping for an Intel
+ MIC device. For example - "A0" or "B0"
+
+What: /sys/class/mic/mic(x)/state
+Date: August 2013
+KernelVersion: 3.11
+Contact: Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+ When read, this entry provides the current state of an Intel
+ MIC device in the context of the card OS. Possible values that
+ will be read are:
+ "offline" - The MIC device is ready to boot the card OS.
+ "online" - The MIC device has initiated booting a card OS.
+ "shutting_down" - The card OS is shutting down.
+ "reset_failed" - The MIC device has failed to reset.
+
+ When written, this sysfs entry triggers different state change
+ operations depending upon the current state of the card OS.
+ Acceptable values are:
+ "boot" - Boot the card OS image specified by the combination
+ of firmware, ramdisk, cmdline and bootmode
+ sysfs entries.
+ "reset" - Initiates device reset.
+ "shutdown" - Initiates card OS shutdown.
+
+What: /sys/class/mic/mic(x)/shutdown_status
+Date: August 2013
+KernelVersion: 3.11
+Contact: Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+ An Intel MIC device runs a Linux OS during its operation. This
+ OS can shutdown because of various reasons. When read, this
+ entry provides the status on why the card OS was shutdown.
+ Possible values are:
+ "nop" - shutdown status is not applicable, when the card OS is
+ "online"
+ "crashed" - Shutdown because of a HW or SW crash.
+ "halted" - Shutdown because of a halt command.
+ "poweroff" - Shutdown because of a poweroff command.
+ "restart" - Shutdown because of a restart command.
+
+What: /sys/class/mic/mic(x)/cmdline
+Date: August 2013
+KernelVersion: 3.11
+Contact: Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+ An Intel MIC device runs a Linux OS during its operation. Before
+ booting this card OS, it is possible to pass kernel command line
+ options to configure various features in it, similar to
+ self-bootable machines. When read, this entry provides
+ information about the current kernel command line options set to
+ boot the card OS. This entry can be written to change the
+ existing kernel command line options. Typically, the user would
+ want to read the current command line options, append new ones
+ or modify existing ones and then write the whole kernel command
+ line back to this entry.
+
+What: /sys/class/mic/mic(x)/firmware
+Date: August 2013
+KernelVersion: 3.11
+Contact: Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+ When read, this sysfs entry provides the path name under
+ /lib/firmware/ where the firmware image to be booted on the
+ card can be found. The entry can be written to change the
+ firmware image location under /lib/firmware/.
+
+What: /sys/class/mic/mic(x)/ramdisk
+Date: August 2013
+KernelVersion: 3.11
+Contact: Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+ When read, this sysfs entry provides the path name under
+ /lib/firmware/ where the ramdisk image to be used during card
+ OS boot can be found. The entry can be written to change
+ the ramdisk image location under /lib/firmware/.
+
+What: /sys/class/mic/mic(x)/bootmode
+Date: August 2013
+KernelVersion: 3.11
+Contact: Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+ When read, this sysfs entry provides the current bootmode for
+ the card. This sysfs entry can be written with the following
+ valid strings:
+ a) linux - Boot a Linux image.
+ b) elf - Boot an elf image for flash updates.
+
+What: /sys/class/mic/mic(x)/log_buf_addr
+Date: August 2013
+KernelVersion: 3.11
+Contact: Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+ An Intel MIC device runs a Linux OS during its operation. For
+ debugging purpose and early kernel boot messages, the user can
+ access the card OS log buffer via debugfs. When read, this entry
+ provides the kernel virtual address of the buffer where the card
+ OS log buffer can be read. This entry is written by the host
+ configuration daemon to set the log buffer address. The correct
+ log buffer address to be written can be found in the System.map
+ file of the card OS.
+
+What: /sys/class/mic/mic(x)/log_buf_len
+Date: August 2013
+KernelVersion: 3.11
+Contact: Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+ An Intel MIC device runs a Linux OS during its operation. For
+ debugging purpose and early kernel boot messages, the user can
+ access the card OS log buffer via debugfs. When read, this entry
+ provides the kernel virtual address where the card OS log buffer
+ length can be read. This entry is written by host configuration
+ daemon to set the log buffer length address. The correct log
+ buffer length address to be written can be found in the
+ System.map file of the card OS.
diff --git a/Documentation/ABI/testing/sysfs-driver-sunxi-sid b/Documentation/ABI/testing/sysfs-driver-sunxi-sid
new file mode 100644
index 000000000000..ffb9536f6ecc
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-sunxi-sid
@@ -0,0 +1,22 @@
+What: /sys/devices/*/<our-device>/eeprom
+Date: August 2013
+Contact: Oliver Schinagl <oliver@schinagl.nl>
+Description: read-only access to the SID (Security-ID) on current
+ A-series SoC's from Allwinner. Currently supports A10, A10s, A13
+ and A20 CPU's. The earlier A1x series of SoCs exports 16 bytes,
+ whereas the newer A20 SoC exposes 512 bytes split into sections.
+ Besides the 16 bytes of SID, there's also an SJTAG area,
+ HDMI-HDCP key and some custom keys. Below a quick overview, for
+ details see the user manual:
+ 0x000 128 bit root-key (sun[457]i)
+ 0x010 128 bit boot-key (sun7i)
+ 0x020 64 bit security-jtag-key (sun7i)
+ 0x028 16 bit key configuration (sun7i)
+ 0x02b 16 bit custom-vendor-key (sun7i)
+ 0x02c 320 bit low general key (sun7i)
+ 0x040 32 bit read-control access (sun7i)
+ 0x064 224 bit low general key (sun7i)
+ 0x080 2304 bit HDCP-key (sun7i)
+ 0x1a0 768 bit high general key (sun7i)
+Users: any user space application which wants to read the SID on
+ Allwinner's A-series of CPU's.
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index 7703ec73a9bb..91266193b8f4 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -202,8 +202,8 @@ over a rather long period of time, but improvements are always welcome!
updater uses call_rcu_sched() or synchronize_sched(), then
the corresponding readers must disable preemption, possibly
by calling rcu_read_lock_sched() and rcu_read_unlock_sched().
- If the updater uses synchronize_srcu() or call_srcu(),
- the the corresponding readers must use srcu_read_lock() and
+ If the updater uses synchronize_srcu() or call_srcu(), then
+ the corresponding readers must use srcu_read_lock() and
srcu_read_unlock(), and with the same srcu_struct. The rules for
the expedited primitives are the same as for their non-expedited
counterparts. Mixing things up will result in confusion and
diff --git a/Documentation/RCU/stallwarn.txt b/Documentation/RCU/stallwarn.txt
index 8e9359de1d28..6f3a0057548e 100644
--- a/Documentation/RCU/stallwarn.txt
+++ b/Documentation/RCU/stallwarn.txt
@@ -12,12 +12,12 @@ CONFIG_RCU_CPU_STALL_TIMEOUT
This kernel configuration parameter defines the period of time
that RCU will wait from the beginning of a grace period until it
issues an RCU CPU stall warning. This time period is normally
- sixty seconds.
+ 21 seconds.
This configuration parameter may be changed at runtime via the
/sys/module/rcutree/parameters/rcu_cpu_stall_timeout, however
this parameter is checked only at the beginning of a cycle.
- So if you are 30 seconds into a 70-second stall, setting this
+ So if you are 10 seconds into a 40-second stall, setting this
sysfs parameter to (say) five will shorten the timeout for the
-next- stall, or the following warning for the current stall
(assuming the stall lasts long enough). It will not affect the
@@ -32,7 +32,7 @@ CONFIG_RCU_CPU_STALL_VERBOSE
also dump the stacks of any tasks that are blocking the current
RCU-preempt grace period.
-RCU_CPU_STALL_INFO
+CONFIG_RCU_CPU_STALL_INFO
This kernel configuration parameter causes the stall warning to
print out additional per-CPU diagnostic information, including
@@ -43,7 +43,8 @@ RCU_STALL_DELAY_DELTA
Although the lockdep facility is extremely useful, it does add
some overhead. Therefore, under CONFIG_PROVE_RCU, the
RCU_STALL_DELAY_DELTA macro allows five extra seconds before
- giving an RCU CPU stall warning message.
+ giving an RCU CPU stall warning message. (This is a cpp
+ macro, not a kernel configuration parameter.)
RCU_STALL_RAT_DELAY
@@ -52,7 +53,8 @@ RCU_STALL_RAT_DELAY
However, if the offending CPU does not detect its own stall in
the number of jiffies specified by RCU_STALL_RAT_DELAY, then
some other CPU will complain. This delay is normally set to
- two jiffies.
+ two jiffies. (This is a cpp macro, not a kernel configuration
+ parameter.)
When a CPU detects that it is stalling, it will print a message similar
to the following:
@@ -86,7 +88,12 @@ printing, there will be a spurious stall-warning message:
INFO: rcu_bh_state detected stalls on CPUs/tasks: { } (detected by 4, 2502 jiffies)
-This is rare, but does happen from time to time in real life.
+This is rare, but does happen from time to time in real life. It is also
+possible for a zero-jiffy stall to be flagged in this case, depending
+on how the stall warning and the grace-period initialization happen to
+interact. Please note that it is not possible to entirely eliminate this
+sort of false positive without resorting to things like stop_machine(),
+which is overkill for this sort of problem.
If the CONFIG_RCU_CPU_STALL_INFO kernel configuration parameter is set,
more information is printed with the stall-warning message, for example:
@@ -216,4 +223,5 @@ that portion of the stack which remains the same from trace to trace.
If you can reliably trigger the stall, ftrace can be quite helpful.
RCU bugs can often be debugged with the help of CONFIG_RCU_TRACE
-and with RCU's event tracing.
+and with RCU's event tracing. For information on RCU's event tracing,
+see include/trace/events/rcu.h.
diff --git a/Documentation/block/blockconsole.txt b/Documentation/block/blockconsole.txt
new file mode 100644
index 000000000000..2b45516ab29c
--- /dev/null
+++ b/Documentation/block/blockconsole.txt
@@ -0,0 +1,94 @@
+started by Jörn Engel <joern@logfs.org> 2012.03.17
+
+Blocksonsole for the impatient
+==============================
+
+1. Find an unused USB stick and prepare it for blockconsole by writing
+ the blockconsole signature to it:
+ $ ./mkblockconsole /dev/<usb_stick>
+
+2. USB stick is ready for use, replug it so that the kernel can start
+ logging to it.
+
+3. After you've done logging, read out the logs from it like this:
+ $ ./bcon_tail
+
+ This creates a file called /var/log/bcon.<UUID> which contains the
+ last 16M of the logs. Open it with a sane editor like vim which
+ can display zeroed gaps as a single line and start staring at the
+ logs.
+ For the really impatient, use:
+ $ vi `./bcon_tail`
+
+Introduction:
+=============
+
+This module logs kernel printk messages to block devices, e.g. usb
+sticks. It allows after-the-fact debugging when the main
+disk/filesystem fails and serial consoles and netconsole are
+impractical.
+
+It can currently only be used built-in. Blockconsole hooks into the
+partition scanning code and will bring up configured block devices as
+soon as possible. While this doesn't allow capture of early kernel
+panics, it does capture most of the boot process.
+
+Block device configuration:
+==================================
+
+Blockconsole has no configuration parameter. In order to use a block
+device for logging, the blockconsole header has to be written to the
+device in question. Logging to partitions is not supported.
+
+The example program mkblockconsole can be used to generate such a
+header on a device.
+
+Header format:
+==============
+
+A legal header looks like this:
+
+Linux blockconsole version 1.1
+818cf322
+00000000
+00000000
+
+It consists of a newline, the "Linux blockconsole version 1.1" string
+plus three numbers on separate lines each. Numbers are all 32bit,
+represented as 8-byte hex strings, with letters in lowercase. The
+first number is a uuid for this particular console device. Just pick
+a random number when generating the device. The second number is a
+wrap counter and unlikely to ever increment. The third is a tile
+counter, with a tile being one megabyte in size.
+
+Miscellaneous notes:
+====================
+
+Blockconsole will write a new header for every tile or once every
+megabyte. The header starts with a newline in order to ensure the
+"Linux blockconsole...' string always ends up at the beginning of a
+line if you read the blockconsole in a text editor.
+
+The blockconsole header is constructed such that opening the log
+device in a text editor, ignoring memory constraints due to large
+devices, should just work and be reasonably non-confusing to readers.
+However, the example program bcon_tail can be used to copy the last 16
+tiles of the log device to /var/log/bcon.<uuid>, which should be much
+easier to handle.
+
+The wrap counter is used by blockconsole to determine where to
+continue logging after a reboot. New logs will be written to the
+first tile that wasn't written to by the last instance of
+blockconsole. Similarly bcon_tail is doing a binary search to find
+the end of the log.
+
+Writing to the log device is strictly circular. This should give
+optimal performance and reliability on cheap devices, like usb sticks.
+
+Writing to block devices has to happen in sector granularity, while
+kernel logging happens in byte granularity. In order not to lose
+messages in important cases like kernel crashes, a timer will write
+out partial sectors if no new messages appear for a while. The
+unwritten part of the sector will be filled with spaces and a single
+newline. In a quiet system, these empty lines can make up the bulk of
+the log.
diff --git a/Documentation/block/blockconsole/bcon_tail b/Documentation/block/blockconsole/bcon_tail
new file mode 100755
index 000000000000..70926c6eeaea
--- /dev/null
+++ b/Documentation/block/blockconsole/bcon_tail
@@ -0,0 +1,82 @@
+#!/bin/bash
+
+TAIL_LEN=16
+TEMPLATE=/tmp/bcon_template
+BUF=/tmp/bcon_buf
+
+if [ $(whoami) != "root" ]; then
+ echo "You need to be root to run this."
+ exit 1
+fi
+
+if [ -z "$(which lsscsi)" ]; then
+ echo "You need to install the lsscsi package on your distro."
+ exit 1
+fi
+
+if [ -z "$(which hdparm)" ]; then
+ echo "You need to install the hdparm package on your distro."
+ exit 1
+fi
+
+end_of_log() {
+ DEV=$1
+ UUID=`head -c40 $DEV|tail -c8`
+ LOGFILE=/var/log/bcon.$UUID
+ SECTORS=`hdparm -g $DEV|grep sectors|sed 's/.*sectors = \([0-9]*\).*/\1/'`
+ #MSIZE=`expr $SECTORS / 2048`
+ dd if=$DEV iflag=direct bs=512 2>/dev/null|head -c50 > $TEMPLATE
+ #START, MIDDLE and END are in sectors
+ START=0
+ MIDDLE=$SECTORS
+ END=$SECTORS
+ while true; do
+ MIDDLE=`expr \( \( $END + $START \) / 4096 \) \* 2048`
+ if [ $MIDDLE -eq $START ]; then
+ break
+ fi
+ dd if=$DEV iflag=direct bs=512 count=1 skip=$MIDDLE 2>/dev/null|head -c50 > $BUF
+ if diff -q $BUF $TEMPLATE > /dev/null; then
+ START=$MIDDLE
+ else
+ END=$MIDDLE
+ fi
+ done
+ #switch to megabytes
+ END=`expr $END / 2048`
+ START=`expr $START / 2048`
+ if [ $START -lt $TAIL_LEN ]; then
+ START=0
+ else
+ START=`expr $START - $TAIL_LEN + 1`
+ fi
+ LEN=`expr $END - $START`
+ dd if=$DEV iflag=direct bs=1M count=$LEN skip=$START >$LOGFILE 2>/dev/null
+ echo $LOGFILE
+}
+
+# HEADER contains a newline, so the funny quoting is necessary
+HEADER='
+Linux blockconsole version 1.1'
+
+DEV="$1"
+if [ -n "$DEV" ]; then
+ if [ ! -b "$DEV" ]; then
+ echo "bcon_tail: No block device file $DEV"
+ exit 1
+ fi
+ if [ "`head -c32 $DEV`" != "$HEADER" ]; then
+ echo "bcon_tail: Invalid device file $DEV"
+ exit 1
+ fi
+ end_of_log $DEV
+ exit 0
+fi
+
+CANDIDATES=`lsscsi |sed 's|.*/dev|/dev|'`
+
+for DEV in $CANDIDATES; do
+ if [ "`head -c32 $DEV`" == "$HEADER" ]; then
+ end_of_log $DEV
+ fi
+done
diff --git a/Documentation/block/blockconsole/mkblockconsole b/Documentation/block/blockconsole/mkblockconsole
new file mode 100755
index 000000000000..c48f9957fbed
--- /dev/null
+++ b/Documentation/block/blockconsole/mkblockconsole
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# handle the case when using files for logging instead of
+# real devices (with kvm, for example)
+DD_OPTS="conv=notrunc"
+
+if [ ! $# -eq 1 ]; then
+ echo "Usage: $0 <dev>"
+ exit 1
+elif mount|fgrep -q $1; then
+ echo Device appears to be mounted - aborting
+ exit 1
+else
+ dd if=/dev/zero of=$1 bs=1M count=1 $DD_OPTS
+ # The funky formatting is actually needed!
+ UUID=`head -c4 /dev/urandom |hexdump -e '/4 "%08x"'`
+ echo > /tmp/$UUID
+ echo 'Linux blockconsole version 1.1' >> /tmp/$UUID
+ echo "$UUID" >> /tmp/$UUID
+ echo 00000000 >> /tmp/$UUID
+ echo 00000000 >> /tmp/$UUID
+ for i in `seq 452`; do echo -n " " >> /tmp/$UUID; done
+ echo >> /tmp/$UUID
+
+ dd if=/tmp/$UUID of=$1 $DD_OPTS
+ rm /tmp/$UUID
+ sync
+ exit 0
+fi
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 23721d3be3e6..80b72419ffd8 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -414,6 +414,7 @@ Your cooperation is appreciated.
200 = /dev/net/tun TAP/TUN network device
201 = /dev/button/gulpb Transmeta GULP-B buttons
202 = /dev/emd/ctl Enhanced Metadisk RAID (EMD) control
+ 203 = /dev/cuse Cuse (character device in user-space)
204 = /dev/video/em8300 EM8300 DVD decoder control
205 = /dev/video/em8300_mv EM8300 DVD decoder video
206 = /dev/video/em8300_ma EM8300 DVD decoder audio
diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
index 61df564c0d23..d74091a8a3bf 100644
--- a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
+++ b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
@@ -4,6 +4,8 @@ Marvell Armada 370 and Armada XP Interrupt Controller
Required properties:
- compatible: Should be "marvell,mpic"
- interrupt-controller: Identifies the node as an interrupt controller.
+- msi-controller: Identifies the node as an PCI Message Signaled
+ Interrupt controller.
- #interrupt-cells: The number of cells to define the interrupts. Should be 1.
The cell is the IRQ number
@@ -24,6 +26,7 @@ Example:
#address-cells = <1>;
#size-cells = <1>;
interrupt-controller;
+ msi-controller;
reg = <0xd0020a00 0x1d0>,
<0xd0021070 0x58>;
};
diff --git a/Documentation/devicetree/bindings/arm/cci.txt b/Documentation/devicetree/bindings/arm/cci.txt
index 92d36e2aa877..f28d82bbbc56 100644
--- a/Documentation/devicetree/bindings/arm/cci.txt
+++ b/Documentation/devicetree/bindings/arm/cci.txt
@@ -36,14 +36,18 @@ specific to ARM.
- reg
Usage: required
- Value type: <prop-encoded-array>
+ Value type: Integer cells. A register entry, expressed as a pair
+ of cells, containing base and size.
Definition: A standard property. Specifies base physical
address of CCI control registers common to all
interfaces.
- ranges:
Usage: required
- Value type: <prop-encoded-array>
+ Value type: Integer cells. An array of range entries, expressed
+ as a tuple of cells, containing child address,
+ parent address and the size of the region in the
+ child address space.
Definition: A standard property. Follow rules in the ePAPR for
hierarchical bus addressing. CCI interfaces
addresses refer to the parent node addressing
@@ -74,11 +78,49 @@ specific to ARM.
- reg:
Usage: required
- Value type: <prop-encoded-array>
+ Value type: Integer cells. A register entry, expressed
+ as a pair of cells, containing base and
+ size.
Definition: the base address and size of the
corresponding interface programming
registers.
+ - CCI PMU node
+
+ Parent node must be CCI interconnect node.
+
+ A CCI pmu node must contain the following properties:
+
+ - compatible
+ Usage: required
+ Value type: <string>
+ Definition: must be "arm,cci-400-pmu"
+
+ - reg:
+ Usage: required
+ Value type: Integer cells. A register entry, expressed
+ as a pair of cells, containing base and
+ size.
+ Definition: the base address and size of the
+ corresponding interface programming
+ registers.
+
+ - interrupts:
+ Usage: required
+ Value type: Integer cells. Array of interrupt specifier
+ entries, as defined in
+ ../interrupt-controller/interrupts.txt.
+ Definition: list of counter overflow interrupts, one per
+ counter. The interrupts must be specified
+ starting with the cycle counter overflow
+ interrupt, followed by counter0 overflow
+ interrupt, counter1 overflow interrupt,...
+ ,counterN overflow interrupt.
+
+ The CCI PMU has an interrupt signal for each
+ counter. The number of interrupts must be
+ equal to the number of counters.
+
* CCI interconnect bus masters
Description: masters in the device tree connected to a CCI port
@@ -144,7 +186,7 @@ Example:
#address-cells = <1>;
#size-cells = <1>;
reg = <0x0 0x2c090000 0 0x1000>;
- ranges = <0x0 0x0 0x2c090000 0x6000>;
+ ranges = <0x0 0x0 0x2c090000 0x10000>;
cci_control0: slave-if@1000 {
compatible = "arm,cci-400-ctrl-if";
@@ -163,6 +205,16 @@ Example:
interface-type = "ace";
reg = <0x5000 0x1000>;
};
+
+ pmu@9000 {
+ compatible = "arm,cci-400-pmu";
+ reg = <0x9000 0x5000>;
+ interrupts = <0 101 4>,
+ <0 102 4>,
+ <0 103 4>,
+ <0 104 4>,
+ <0 105 4>;
+ };
};
This CCI node corresponds to a CCI component whose control registers sits
diff --git a/Documentation/devicetree/bindings/arm/vic.txt b/Documentation/devicetree/bindings/arm/vic.txt
index 266716b23437..dd527216c5fb 100644
--- a/Documentation/devicetree/bindings/arm/vic.txt
+++ b/Documentation/devicetree/bindings/arm/vic.txt
@@ -18,6 +18,15 @@ Required properties:
Optional properties:
- interrupts : Interrupt source for parent controllers if the VIC is nested.
+- valid-mask : A one cell big bit mask of valid interrupt sources. Each bit
+ represents single interrupt source, starting from source 0 at LSb and ending
+ at source 31 at MSb. A bit that is set means that the source is wired and
+ clear means otherwise. If unspecified, defaults to all valid.
+- valid-wakeup-mask : A one cell big bit mask of interrupt sources that can be
+ configured as wake up source for the system. Order of bits is the same as for
+ valid-mask property. A set bit means that this interrupt source can be
+ configured as a wake up source for the system. If unspecied, defaults to all
+ interrupt sources configurable as wake up sources.
Example:
@@ -26,4 +35,7 @@ Example:
interrupt-controller;
#interrupt-cells = <1>;
reg = <0x60000 0x1000>;
+
+ valid-mask = <0xffffff7f>;
+ valid-wakeup-mask = <0x0000ff7f>;
};
diff --git a/Documentation/devicetree/bindings/clock/imx6q-clock.txt b/Documentation/devicetree/bindings/clock/imx6q-clock.txt
index 5a90a724b520..e8b1baae9ae4 100644
--- a/Documentation/devicetree/bindings/clock/imx6q-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx6q-clock.txt
@@ -215,6 +215,7 @@ clocks and IDs.
cko2 200
cko 201
vdoa 202
+ pll4_audio_div 203
Examples:
diff --git a/Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt b/Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt
new file mode 100644
index 000000000000..4a63bc96b687
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt
@@ -0,0 +1,52 @@
+Broadcom Kona Family GPIO
+=========================
+
+This GPIO driver is used in the following Broadcom SoCs:
+ BCM11130, BCM11140, BCM11351, BCM28145, BCM28155
+
+The Broadcom GPIO Controller IP can be configured prior to synthesis to
+support up to 8 banks of 32 GPIOs where each bank has its own IRQ. The
+GPIO controller only supports edge, not level, triggering of interrupts.
+
+Required properties
+-------------------
+
+- compatible: "brcm,bcm11351-gpio", "brcm,kona-gpio"
+- reg: Physical base address and length of the controller's registers.
+- interrupts: The interrupt outputs from the controller. There is one GPIO
+ interrupt per GPIO bank. The number of interrupts listed depends on the
+ number of GPIO banks on the SoC. The interrupts must be ordered by bank,
+ starting with bank 0. There is always a 1:1 mapping between banks and
+ IRQs.
+- #gpio-cells: Should be <2>. The first cell is the pin number, the second
+ cell is used to specify optional parameters:
+ - bit 0 specifies polarity (0 for normal, 1 for inverted)
+ See also "gpio-specifier" in .../devicetree/bindings/gpio/gpio.txt.
+- #interrupt-cells: Should be <2>. The first cell is the GPIO number. The
+ second cell is used to specify flags. The following subset of flags is
+ supported:
+ - trigger type (bits[1:0]):
+ 1 = low-to-high edge triggered.
+ 2 = high-to-low edge triggered.
+ 3 = low-to-high or high-to-low edge triggered
+ Valid values are 1, 2, 3
+ See also .../devicetree/bindings/interrupt-controller/interrupts.txt.
+- gpio-controller: Marks the device node as a GPIO controller.
+- interrupt-controller: Marks the device node as an interrupt controller.
+
+Example:
+ gpio: gpio@35003000 {
+ compatible = "brcm,bcm11351-gpio", "brcm,kona-gpio";
+ reg = <0x35003000 0x800>;
+ interrupts =
+ <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ gpio-controller;
+ interrupt-controller;
+ };
diff --git a/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt b/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt
new file mode 100644
index 000000000000..d63194a2c848
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt
@@ -0,0 +1,71 @@
+* PCF857x-compatible I/O expanders
+
+The PCF857x-compatible chips have "quasi-bidirectional" I/O lines that can be
+driven high by a pull-up current source or driven low to ground. This combines
+the direction and output level into a single bit per line, which can't be read
+back. We can't actually know at initialization time whether a line is configured
+(a) as output and driving the signal low/high, or (b) as input and reporting a
+low/high value, without knowing the last value written since the chip came out
+of reset (if any). The only reliable solution for setting up line direction is
+thus to do it explicitly.
+
+Required Properties:
+
+ - compatible: should be one of the following.
+ - "maxim,max7328": For the Maxim MAX7378
+ - "maxim,max7329": For the Maxim MAX7329
+ - "nxp,pca8574": For the NXP PCA8574
+ - "nxp,pca8575": For the NXP PCA8575
+ - "nxp,pca9670": For the NXP PCA9670
+ - "nxp,pca9671": For the NXP PCA9671
+ - "nxp,pca9672": For the NXP PCA9672
+ - "nxp,pca9673": For the NXP PCA9673
+ - "nxp,pca9674": For the NXP PCA9674
+ - "nxp,pca9675": For the NXP PCA9675
+ - "nxp,pcf8574": For the NXP PCF8574
+ - "nxp,pcf8574a": For the NXP PCF8574A
+ - "nxp,pcf8575": For the NXP PCF8575
+ - "ti,tca9554": For the TI TCA9554
+
+ - reg: I2C slave address.
+
+ - gpio-controller: Marks the device node as a gpio controller.
+ - #gpio-cells: Should be 2. The first cell is the GPIO number and the second
+ cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>. Only the
+ GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported.
+
+Optional Properties:
+
+ - lines-initial-states: Bitmask that specifies the initial state of each
+ line. When a bit is set to zero, the corresponding line will be initialized to
+ the input (pulled-up) state. When the bit is set to one, the line will be
+ initialized the the low-level output state. If the property is not specified
+ all lines will be initialized to the input state.
+
+ The I/O expander can detect input state changes, and thus optionally act as
+ an interrupt controller. When the expander interrupt line is connected all the
+ following properties must be set. For more information please see the
+ interrupt controller device tree bindings documentation available at
+ Documentation/devicetree/bindings/interrupt-controller/interrupts.txt.
+
+ - interrupt-controller: Identifies the node as an interrupt controller.
+ - #interrupt-cells: Number of cells to encode an interrupt source, shall be 2.
+ - interrupt-parent: phandle of the parent interrupt controller.
+ - interrupts: Interrupt specifier for the controllers interrupt.
+
+
+Please refer to gpio.txt in this directory for details of the common GPIO
+bindings used by client devices.
+
+Example: PCF8575 I/O expander node
+
+ pcf8575: gpio@20 {
+ compatible = "nxp,pcf8575";
+ reg = <0x20>;
+ interrupt-parent = <&irqpin2>;
+ interrupts = <3 0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
diff --git a/Documentation/devicetree/bindings/iio/light/gp2ap020a00f.txt b/Documentation/devicetree/bindings/iio/light/gp2ap020a00f.txt
new file mode 100644
index 000000000000..9231c82317ad
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/light/gp2ap020a00f.txt
@@ -0,0 +1,21 @@
+* Sharp GP2AP020A00F I2C Proximity/ALS sensor
+
+The proximity detector sensor requires power supply
+for its built-in led. It is also defined by this binding.
+
+Required properties:
+
+ - compatible : should be "sharp,gp2ap020a00f"
+ - reg : the I2C slave address of the light sensor
+ - interrupts : interrupt specifier for the sole interrupt generated
+ by the device
+ - vled-supply : VLED power supply, as covered in ../regulator/regulator.txt
+
+Example:
+
+gp2ap020a00f@39 {
+ compatible = "sharp,gp2ap020a00f";
+ reg = <0x39>;
+ interrupts = <2 0>;
+ vled-supply = <...>;
+};
diff --git a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt
index a61727f9a6d1..d221e75d90fa 100644
--- a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt
+++ b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt
@@ -17,12 +17,15 @@ Optional properties:
2: D1~6 with VOUT, D7~9 with VDD
3: D1~9 are connected to VOUT
-Alternatively, each child can have specific channel name
-- chan-name: Name of each channel name
+Alternatively, each child can have a specific channel name and trigger:
+- chan-name (optional): name of channel
+- linux,default-trigger (optional): see
+ Documentation/devicetree/bindings/leds/common.txt
example 1) LP5521
3 LED channels, external clock used. Channel names are 'lp5521_pri:channel0',
-'lp5521_pri:channel1' and 'lp5521_pri:channel2'
+'lp5521_pri:channel1' and 'lp5521_pri:channel2', with a heartbeat trigger
+on channel 0.
lp5521@32 {
compatible = "national,lp5521";
@@ -33,6 +36,7 @@ lp5521@32 {
chan0 {
led-cur = /bits/ 8 <0x2f>;
max-cur = /bits/ 8 <0x5f>;
+ linux,default-trigger = "heartbeat";
};
chan1 {
diff --git a/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
new file mode 100644
index 000000000000..68ba37295565
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
@@ -0,0 +1,17 @@
+Allwinner sunxi-sid
+
+Required properties:
+- compatible: "allwinner,sun4i-sid" or "allwinner,sun7i-a20-sid".
+- reg: Should contain registers location and length
+
+Example for sun4i:
+ sid@01c23800 {
+ compatible = "allwinner,sun4i-sid";
+ reg = <0x01c23800 0x10>
+ };
+
+Example for sun7i:
+ sid@01c23800 {
+ compatible = "allwinner,sun7i-a20-sid";
+ reg = <0x01c23800 0x200>
+ };
diff --git a/Documentation/devicetree/bindings/misc/ti,dac7512.txt b/Documentation/devicetree/bindings/misc/ti,dac7512.txt
new file mode 100644
index 000000000000..1db45939dac9
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/ti,dac7512.txt
@@ -0,0 +1,20 @@
+TI DAC7512 DEVICETREE BINDINGS
+
+Required properties:
+
+ - "compatible" Must be set to "ti,dac7512"
+
+Property rules described in Documentation/devicetree/bindings/spi/spi-bus.txt
+apply. In particular, "reg" and "spi-max-frequency" properties must be given.
+
+
+Example:
+
+ spi_master {
+ dac7512: dac7512@0 {
+ compatible = "ti,dac7512";
+ reg = <0>; /* CS0 */
+ spi-max-frequency = <1000000>;
+ };
+ };
+
diff --git a/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt
index cdcebea9c6f5..fdbf6863b00b 100644
--- a/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt
+++ b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt
@@ -52,6 +52,9 @@ Optional properties:
is specified and the ciu clock is specified then we'll try to set the ciu
clock to this at probe time.
+* clock-freq-min-max: Minimum and Maximum clock frequency for card output
+ clock(cclk_out). If it's not specified, max is 200MHZ and min is 400KHz by default.
+
* num-slots: specifies the number of slots supported by the controller.
The number of physical slots actually used could be equal or less than the
value specified by num-slots. If this property is not specified, the value
@@ -66,6 +69,10 @@ Optional properties:
* supports-highspeed: Enables support for high speed cards (up to 50MHz)
+* caps2-mmc-hs200-1_8v: Supports mmc HS200 SDR 1.8V mode
+
+* caps2-mmc-hs200-1_2v: Supports mmc HS200 SDR 1.2V mode
+
* broken-cd: as documented in mmc core bindings.
* vmmc-supply: The phandle to the regulator to use for vmmc. If this is
@@ -93,8 +100,10 @@ board specific portions as listed below.
dwmmc0@12200000 {
clock-frequency = <400000000>;
+ clock-freq-min-max = <400000 200000000>;
num-slots = <1>;
supports-highspeed;
+ caps2-mmc-hs200-1_8v;
broken-cd;
fifo-depth = <0x80>;
card-detect-delay = <200>;
diff --git a/Documentation/devicetree/bindings/mmc/tmio_mmc.txt b/Documentation/devicetree/bindings/mmc/tmio_mmc.txt
index df204e18e030..6a2a1160a70d 100644
--- a/Documentation/devicetree/bindings/mmc/tmio_mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/tmio_mmc.txt
@@ -9,12 +9,15 @@ compulsory and any optional properties, common to all SD/MMC drivers, as
described in mmc.txt, can be used. Additionally the following tmio_mmc-specific
optional bindings can be used.
+Required properties:
+- compatible: "renesas,sdhi-shmobile" - a generic sh-mobile SDHI unit
+ "renesas,sdhi-sh7372" - SDHI IP on SH7372 SoC
+ "renesas,sdhi-sh73a0" - SDHI IP on SH73A0 SoC
+ "renesas,sdhi-r8a73a4" - SDHI IP on R8A73A4 SoC
+ "renesas,sdhi-r8a7740" - SDHI IP on R8A7740 SoC
+ "renesas,sdhi-r8a7778" - SDHI IP on R8A7778 SoC
+ "renesas,sdhi-r8a7779" - SDHI IP on R8A7779 SoC
+ "renesas,sdhi-r8a7790" - SDHI IP on R8A7790 SoC
+
Optional properties:
- toshiba,mmc-wrprotect-disable: write-protect detection is unavailable
-
-When used with Renesas SDHI hardware, the following compatibility strings
-configure various model-specific properties:
-
-"renesas,sh7372-sdhi": (default) compatible with SH7372
-"renesas,r8a7740-sdhi": compatible with R8A7740: certain MMC/SD commands have to
- wait for the interface to become idle.
diff --git a/Documentation/devicetree/bindings/net/cpsw-phy-sel.txt b/Documentation/devicetree/bindings/net/cpsw-phy-sel.txt
new file mode 100644
index 000000000000..7ff57a119f81
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/cpsw-phy-sel.txt
@@ -0,0 +1,28 @@
+TI CPSW Phy mode Selection Device Tree Bindings
+-----------------------------------------------
+
+Required properties:
+- compatible : Should be "ti,am3352-cpsw-phy-sel"
+- reg : physical base address and size of the cpsw
+ registers map
+- reg-names : names of the register map given in "reg" node
+
+Optional properties:
+-rmii-clock-ext : If present, the driver will configure the RMII
+ interface to external clock usage
+
+Examples:
+
+ phy_sel: cpsw-phy-sel@44e10650 {
+ compatible = "ti,am3352-cpsw-phy-sel";
+ reg= <0x44e10650 0x4>;
+ reg-names = "gmii-sel";
+ };
+
+(or)
+ phy_sel: cpsw-phy-sel@44e10650 {
+ compatible = "ti,am3352-cpsw-phy-sel";
+ reg= <0x44e10650 0x4>;
+ reg-names = "gmii-sel";
+ rmii-clock-ext;
+ };
diff --git a/Documentation/devicetree/bindings/pci/mvebu-pci.txt b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
index 9556e2fedf6d..08c716b2c6b6 100644
--- a/Documentation/devicetree/bindings/pci/mvebu-pci.txt
+++ b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
@@ -5,6 +5,7 @@ Mandatory properties:
- compatible: one of the following values:
marvell,armada-370-pcie
marvell,armada-xp-pcie
+ marvell,dove-pcie
marvell,kirkwood-pcie
- #address-cells, set to <3>
- #size-cells, set to <2>
@@ -14,6 +15,8 @@ Mandatory properties:
- ranges: ranges describing the MMIO registers to control the PCIe
interfaces, and ranges describing the MBus windows needed to access
the memory and I/O regions of each PCIe interface.
+- msi-parent: Link to the hardware entity that serves as the Message
+ Signaled Interrupt controller for this PCI controller.
The ranges describing the MMIO registers have the following layout:
@@ -74,6 +77,8 @@ and the following optional properties:
- marvell,pcie-lane: the physical PCIe lane number, for ports having
multiple lanes. If this property is not found, we assume that the
value is 0.
+- reset-gpios: optional gpio to PERST#
+- reset-delay-us: delay in us to wait after reset de-assertion
Example:
@@ -86,6 +91,7 @@ pcie-controller {
#size-cells = <2>;
bus-range = <0x00 0xff>;
+ msi-parent = <&mpic>;
ranges =
<0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000 /* Port 0.0 registers */
@@ -135,6 +141,10 @@ pcie-controller {
interrupt-map = <0 0 0 0 &mpic 58>;
marvell,pcie-port = <0>;
marvell,pcie-lane = <0>;
+ /* low-active PERST# reset on GPIO 25 */
+ reset-gpios = <&gpio0 25 1>;
+ /* wait 20ms for device settle after reset deassertion */
+ reset-delay-us = <20000>;
clocks = <&gateclk 5>;
status = "disabled";
};
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
index 3077370c89af..1e70a8aff260 100644
--- a/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
@@ -59,16 +59,16 @@ Required subnode-properties:
Optional subnode-properties:
- fsl,drive-strength: Integer.
- 0: 4 mA
- 1: 8 mA
- 2: 12 mA
- 3: 16 mA
+ 0: MXS_DRIVE_4mA
+ 1: MXS_DRIVE_8mA
+ 2: MXS_DRIVE_12mA
+ 3: MXS_DRIVE_16mA
- fsl,voltage: Integer.
- 0: 1.8 V
- 1: 3.3 V
+ 0: MXS_VOLTAGE_LOW - 1.8 V
+ 1: MXS_VOLTAGE_HIGH - 3.3 V
- fsl,pull-up: Integer.
- 0: Disable the internal pull-up
- 1: Enable the internal pull-up
+ 0: MXS_PULL_DISABLE - Disable the internal pull-up
+ 1: MXS_PULL_ENABLE - Enable the internal pull-up
Note that when enabling the pull-up, the internal pad keeper gets disabled.
Also, some pins doesn't have a pull up, in that case, setting the fsl,pull-up
@@ -85,23 +85,32 @@ pinctrl@80018000 {
mmc0_8bit_pins_a: mmc0-8bit@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2000 0x2010 0x2020 0x2030
- 0x2040 0x2050 0x2060 0x2070
- 0x2080 0x2090 0x20a0>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ MX28_PAD_SSP0_DATA0__SSP0_D0
+ MX28_PAD_SSP0_DATA1__SSP0_D1
+ MX28_PAD_SSP0_DATA2__SSP0_D2
+ MX28_PAD_SSP0_DATA3__SSP0_D3
+ MX28_PAD_SSP0_DATA4__SSP0_D4
+ MX28_PAD_SSP0_DATA5__SSP0_D5
+ MX28_PAD_SSP0_DATA6__SSP0_D6
+ MX28_PAD_SSP0_DATA7__SSP0_D7
+ MX28_PAD_SSP0_CMD__SSP0_CMD
+ MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT
+ MX28_PAD_SSP0_SCK__SSP0_SCK
+ >;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
mmc_cd_cfg: mmc-cd-cfg {
- fsl,pinmux-ids = <0x2090>;
- fsl,pull-up = <0>;
+ fsl,pinmux-ids = <MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
mmc_sck_cfg: mmc-sck-cfg {
- fsl,pinmux-ids = <0x20a0>;
- fsl,drive-strength = <2>;
- fsl,pull-up = <0>;
+ fsl,pinmux-ids = <MX28_PAD_SSP0_SCK__SSP0_SCK>;
+ fsl,drive-strength = <MXS_DRIVE_12mA>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
};
@@ -112,811 +121,7 @@ adjusting the configuration for pins card-detection and clock from what group
node mmc0-8bit defines. Only the configuration properties to be adjusted need
to be listed in the config nodes.
-Valid values for i.MX28 pinmux-id:
-
-pinmux id
------- --
-MX28_PAD_GPMI_D00__GPMI_D0 0x0000
-MX28_PAD_GPMI_D01__GPMI_D1 0x0010
-MX28_PAD_GPMI_D02__GPMI_D2 0x0020
-MX28_PAD_GPMI_D03__GPMI_D3 0x0030
-MX28_PAD_GPMI_D04__GPMI_D4 0x0040
-MX28_PAD_GPMI_D05__GPMI_D5 0x0050
-MX28_PAD_GPMI_D06__GPMI_D6 0x0060
-MX28_PAD_GPMI_D07__GPMI_D7 0x0070
-MX28_PAD_GPMI_CE0N__GPMI_CE0N 0x0100
-MX28_PAD_GPMI_CE1N__GPMI_CE1N 0x0110
-MX28_PAD_GPMI_CE2N__GPMI_CE2N 0x0120
-MX28_PAD_GPMI_CE3N__GPMI_CE3N 0x0130
-MX28_PAD_GPMI_RDY0__GPMI_READY0 0x0140
-MX28_PAD_GPMI_RDY1__GPMI_READY1 0x0150
-MX28_PAD_GPMI_RDY2__GPMI_READY2 0x0160
-MX28_PAD_GPMI_RDY3__GPMI_READY3 0x0170
-MX28_PAD_GPMI_RDN__GPMI_RDN 0x0180
-MX28_PAD_GPMI_WRN__GPMI_WRN 0x0190
-MX28_PAD_GPMI_ALE__GPMI_ALE 0x01a0
-MX28_PAD_GPMI_CLE__GPMI_CLE 0x01b0
-MX28_PAD_GPMI_RESETN__GPMI_RESETN 0x01c0
-MX28_PAD_LCD_D00__LCD_D0 0x1000
-MX28_PAD_LCD_D01__LCD_D1 0x1010
-MX28_PAD_LCD_D02__LCD_D2 0x1020
-MX28_PAD_LCD_D03__LCD_D3 0x1030
-MX28_PAD_LCD_D04__LCD_D4 0x1040
-MX28_PAD_LCD_D05__LCD_D5 0x1050
-MX28_PAD_LCD_D06__LCD_D6 0x1060
-MX28_PAD_LCD_D07__LCD_D7 0x1070
-MX28_PAD_LCD_D08__LCD_D8 0x1080
-MX28_PAD_LCD_D09__LCD_D9 0x1090
-MX28_PAD_LCD_D10__LCD_D10 0x10a0
-MX28_PAD_LCD_D11__LCD_D11 0x10b0
-MX28_PAD_LCD_D12__LCD_D12 0x10c0
-MX28_PAD_LCD_D13__LCD_D13 0x10d0
-MX28_PAD_LCD_D14__LCD_D14 0x10e0
-MX28_PAD_LCD_D15__LCD_D15 0x10f0
-MX28_PAD_LCD_D16__LCD_D16 0x1100
-MX28_PAD_LCD_D17__LCD_D17 0x1110
-MX28_PAD_LCD_D18__LCD_D18 0x1120
-MX28_PAD_LCD_D19__LCD_D19 0x1130
-MX28_PAD_LCD_D20__LCD_D20 0x1140
-MX28_PAD_LCD_D21__LCD_D21 0x1150
-MX28_PAD_LCD_D22__LCD_D22 0x1160
-MX28_PAD_LCD_D23__LCD_D23 0x1170
-MX28_PAD_LCD_RD_E__LCD_RD_E 0x1180
-MX28_PAD_LCD_WR_RWN__LCD_WR_RWN 0x1190
-MX28_PAD_LCD_RS__LCD_RS 0x11a0
-MX28_PAD_LCD_CS__LCD_CS 0x11b0
-MX28_PAD_LCD_VSYNC__LCD_VSYNC 0x11c0
-MX28_PAD_LCD_HSYNC__LCD_HSYNC 0x11d0
-MX28_PAD_LCD_DOTCLK__LCD_DOTCLK 0x11e0
-MX28_PAD_LCD_ENABLE__LCD_ENABLE 0x11f0
-MX28_PAD_SSP0_DATA0__SSP0_D0 0x2000
-MX28_PAD_SSP0_DATA1__SSP0_D1 0x2010
-MX28_PAD_SSP0_DATA2__SSP0_D2 0x2020
-MX28_PAD_SSP0_DATA3__SSP0_D3 0x2030
-MX28_PAD_SSP0_DATA4__SSP0_D4 0x2040
-MX28_PAD_SSP0_DATA5__SSP0_D5 0x2050
-MX28_PAD_SSP0_DATA6__SSP0_D6 0x2060
-MX28_PAD_SSP0_DATA7__SSP0_D7 0x2070
-MX28_PAD_SSP0_CMD__SSP0_CMD 0x2080
-MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT 0x2090
-MX28_PAD_SSP0_SCK__SSP0_SCK 0x20a0
-MX28_PAD_SSP1_SCK__SSP1_SCK 0x20c0
-MX28_PAD_SSP1_CMD__SSP1_CMD 0x20d0
-MX28_PAD_SSP1_DATA0__SSP1_D0 0x20e0
-MX28_PAD_SSP1_DATA3__SSP1_D3 0x20f0
-MX28_PAD_SSP2_SCK__SSP2_SCK 0x2100
-MX28_PAD_SSP2_MOSI__SSP2_CMD 0x2110
-MX28_PAD_SSP2_MISO__SSP2_D0 0x2120
-MX28_PAD_SSP2_SS0__SSP2_D3 0x2130
-MX28_PAD_SSP2_SS1__SSP2_D4 0x2140
-MX28_PAD_SSP2_SS2__SSP2_D5 0x2150
-MX28_PAD_SSP3_SCK__SSP3_SCK 0x2180
-MX28_PAD_SSP3_MOSI__SSP3_CMD 0x2190
-MX28_PAD_SSP3_MISO__SSP3_D0 0x21a0
-MX28_PAD_SSP3_SS0__SSP3_D3 0x21b0
-MX28_PAD_AUART0_RX__AUART0_RX 0x3000
-MX28_PAD_AUART0_TX__AUART0_TX 0x3010
-MX28_PAD_AUART0_CTS__AUART0_CTS 0x3020
-MX28_PAD_AUART0_RTS__AUART0_RTS 0x3030
-MX28_PAD_AUART1_RX__AUART1_RX 0x3040
-MX28_PAD_AUART1_TX__AUART1_TX 0x3050
-MX28_PAD_AUART1_CTS__AUART1_CTS 0x3060
-MX28_PAD_AUART1_RTS__AUART1_RTS 0x3070
-MX28_PAD_AUART2_RX__AUART2_RX 0x3080
-MX28_PAD_AUART2_TX__AUART2_TX 0x3090
-MX28_PAD_AUART2_CTS__AUART2_CTS 0x30a0
-MX28_PAD_AUART2_RTS__AUART2_RTS 0x30b0
-MX28_PAD_AUART3_RX__AUART3_RX 0x30c0
-MX28_PAD_AUART3_TX__AUART3_TX 0x30d0
-MX28_PAD_AUART3_CTS__AUART3_CTS 0x30e0
-MX28_PAD_AUART3_RTS__AUART3_RTS 0x30f0
-MX28_PAD_PWM0__PWM_0 0x3100
-MX28_PAD_PWM1__PWM_1 0x3110
-MX28_PAD_PWM2__PWM_2 0x3120
-MX28_PAD_SAIF0_MCLK__SAIF0_MCLK 0x3140
-MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK 0x3150
-MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK 0x3160
-MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0 0x3170
-MX28_PAD_I2C0_SCL__I2C0_SCL 0x3180
-MX28_PAD_I2C0_SDA__I2C0_SDA 0x3190
-MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0 0x31a0
-MX28_PAD_SPDIF__SPDIF_TX 0x31b0
-MX28_PAD_PWM3__PWM_3 0x31c0
-MX28_PAD_PWM4__PWM_4 0x31d0
-MX28_PAD_LCD_RESET__LCD_RESET 0x31e0
-MX28_PAD_ENET0_MDC__ENET0_MDC 0x4000
-MX28_PAD_ENET0_MDIO__ENET0_MDIO 0x4010
-MX28_PAD_ENET0_RX_EN__ENET0_RX_EN 0x4020
-MX28_PAD_ENET0_RXD0__ENET0_RXD0 0x4030
-MX28_PAD_ENET0_RXD1__ENET0_RXD1 0x4040
-MX28_PAD_ENET0_TX_CLK__ENET0_TX_CLK 0x4050
-MX28_PAD_ENET0_TX_EN__ENET0_TX_EN 0x4060
-MX28_PAD_ENET0_TXD0__ENET0_TXD0 0x4070
-MX28_PAD_ENET0_TXD1__ENET0_TXD1 0x4080
-MX28_PAD_ENET0_RXD2__ENET0_RXD2 0x4090
-MX28_PAD_ENET0_RXD3__ENET0_RXD3 0x40a0
-MX28_PAD_ENET0_TXD2__ENET0_TXD2 0x40b0
-MX28_PAD_ENET0_TXD3__ENET0_TXD3 0x40c0
-MX28_PAD_ENET0_RX_CLK__ENET0_RX_CLK 0x40d0
-MX28_PAD_ENET0_COL__ENET0_COL 0x40e0
-MX28_PAD_ENET0_CRS__ENET0_CRS 0x40f0
-MX28_PAD_ENET_CLK__CLKCTRL_ENET 0x4100
-MX28_PAD_JTAG_RTCK__JTAG_RTCK 0x4140
-MX28_PAD_EMI_D00__EMI_DATA0 0x5000
-MX28_PAD_EMI_D01__EMI_DATA1 0x5010
-MX28_PAD_EMI_D02__EMI_DATA2 0x5020
-MX28_PAD_EMI_D03__EMI_DATA3 0x5030
-MX28_PAD_EMI_D04__EMI_DATA4 0x5040
-MX28_PAD_EMI_D05__EMI_DATA5 0x5050
-MX28_PAD_EMI_D06__EMI_DATA6 0x5060
-MX28_PAD_EMI_D07__EMI_DATA7 0x5070
-MX28_PAD_EMI_D08__EMI_DATA8 0x5080
-MX28_PAD_EMI_D09__EMI_DATA9 0x5090
-MX28_PAD_EMI_D10__EMI_DATA10 0x50a0
-MX28_PAD_EMI_D11__EMI_DATA11 0x50b0
-MX28_PAD_EMI_D12__EMI_DATA12 0x50c0
-MX28_PAD_EMI_D13__EMI_DATA13 0x50d0
-MX28_PAD_EMI_D14__EMI_DATA14 0x50e0
-MX28_PAD_EMI_D15__EMI_DATA15 0x50f0
-MX28_PAD_EMI_ODT0__EMI_ODT0 0x5100
-MX28_PAD_EMI_DQM0__EMI_DQM0 0x5110
-MX28_PAD_EMI_ODT1__EMI_ODT1 0x5120
-MX28_PAD_EMI_DQM1__EMI_DQM1 0x5130
-MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK 0x5140
-MX28_PAD_EMI_CLK__EMI_CLK 0x5150
-MX28_PAD_EMI_DQS0__EMI_DQS0 0x5160
-MX28_PAD_EMI_DQS1__EMI_DQS1 0x5170
-MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN 0x51a0
-MX28_PAD_EMI_A00__EMI_ADDR0 0x6000
-MX28_PAD_EMI_A01__EMI_ADDR1 0x6010
-MX28_PAD_EMI_A02__EMI_ADDR2 0x6020
-MX28_PAD_EMI_A03__EMI_ADDR3 0x6030
-MX28_PAD_EMI_A04__EMI_ADDR4 0x6040
-MX28_PAD_EMI_A05__EMI_ADDR5 0x6050
-MX28_PAD_EMI_A06__EMI_ADDR6 0x6060
-MX28_PAD_EMI_A07__EMI_ADDR7 0x6070
-MX28_PAD_EMI_A08__EMI_ADDR8 0x6080
-MX28_PAD_EMI_A09__EMI_ADDR9 0x6090
-MX28_PAD_EMI_A10__EMI_ADDR10 0x60a0
-MX28_PAD_EMI_A11__EMI_ADDR11 0x60b0
-MX28_PAD_EMI_A12__EMI_ADDR12 0x60c0
-MX28_PAD_EMI_A13__EMI_ADDR13 0x60d0
-MX28_PAD_EMI_A14__EMI_ADDR14 0x60e0
-MX28_PAD_EMI_BA0__EMI_BA0 0x6100
-MX28_PAD_EMI_BA1__EMI_BA1 0x6110
-MX28_PAD_EMI_BA2__EMI_BA2 0x6120
-MX28_PAD_EMI_CASN__EMI_CASN 0x6130
-MX28_PAD_EMI_RASN__EMI_RASN 0x6140
-MX28_PAD_EMI_WEN__EMI_WEN 0x6150
-MX28_PAD_EMI_CE0N__EMI_CE0N 0x6160
-MX28_PAD_EMI_CE1N__EMI_CE1N 0x6170
-MX28_PAD_EMI_CKE__EMI_CKE 0x6180
-MX28_PAD_GPMI_D00__SSP1_D0 0x0001
-MX28_PAD_GPMI_D01__SSP1_D1 0x0011
-MX28_PAD_GPMI_D02__SSP1_D2 0x0021
-MX28_PAD_GPMI_D03__SSP1_D3 0x0031
-MX28_PAD_GPMI_D04__SSP1_D4 0x0041
-MX28_PAD_GPMI_D05__SSP1_D5 0x0051
-MX28_PAD_GPMI_D06__SSP1_D6 0x0061
-MX28_PAD_GPMI_D07__SSP1_D7 0x0071
-MX28_PAD_GPMI_CE0N__SSP3_D0 0x0101
-MX28_PAD_GPMI_CE1N__SSP3_D3 0x0111
-MX28_PAD_GPMI_CE2N__CAN1_TX 0x0121
-MX28_PAD_GPMI_CE3N__CAN1_RX 0x0131
-MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT 0x0141
-MX28_PAD_GPMI_RDY1__SSP1_CMD 0x0151
-MX28_PAD_GPMI_RDY2__CAN0_TX 0x0161
-MX28_PAD_GPMI_RDY3__CAN0_RX 0x0171
-MX28_PAD_GPMI_RDN__SSP3_SCK 0x0181
-MX28_PAD_GPMI_WRN__SSP1_SCK 0x0191
-MX28_PAD_GPMI_ALE__SSP3_D1 0x01a1
-MX28_PAD_GPMI_CLE__SSP3_D2 0x01b1
-MX28_PAD_GPMI_RESETN__SSP3_CMD 0x01c1
-MX28_PAD_LCD_D03__ETM_DA8 0x1031
-MX28_PAD_LCD_D04__ETM_DA9 0x1041
-MX28_PAD_LCD_D08__ETM_DA3 0x1081
-MX28_PAD_LCD_D09__ETM_DA4 0x1091
-MX28_PAD_LCD_D20__ENET1_1588_EVENT2_OUT 0x1141
-MX28_PAD_LCD_D21__ENET1_1588_EVENT2_IN 0x1151
-MX28_PAD_LCD_D22__ENET1_1588_EVENT3_OUT 0x1161
-MX28_PAD_LCD_D23__ENET1_1588_EVENT3_IN 0x1171
-MX28_PAD_LCD_RD_E__LCD_VSYNC 0x1181
-MX28_PAD_LCD_WR_RWN__LCD_HSYNC 0x1191
-MX28_PAD_LCD_RS__LCD_DOTCLK 0x11a1
-MX28_PAD_LCD_CS__LCD_ENABLE 0x11b1
-MX28_PAD_LCD_VSYNC__SAIF1_SDATA0 0x11c1
-MX28_PAD_LCD_HSYNC__SAIF1_SDATA1 0x11d1
-MX28_PAD_LCD_DOTCLK__SAIF1_MCLK 0x11e1
-MX28_PAD_SSP0_DATA4__SSP2_D0 0x2041
-MX28_PAD_SSP0_DATA5__SSP2_D3 0x2051
-MX28_PAD_SSP0_DATA6__SSP2_CMD 0x2061
-MX28_PAD_SSP0_DATA7__SSP2_SCK 0x2071
-MX28_PAD_SSP1_SCK__SSP2_D1 0x20c1
-MX28_PAD_SSP1_CMD__SSP2_D2 0x20d1
-MX28_PAD_SSP1_DATA0__SSP2_D6 0x20e1
-MX28_PAD_SSP1_DATA3__SSP2_D7 0x20f1
-MX28_PAD_SSP2_SCK__AUART2_RX 0x2101
-MX28_PAD_SSP2_MOSI__AUART2_TX 0x2111
-MX28_PAD_SSP2_MISO__AUART3_RX 0x2121
-MX28_PAD_SSP2_SS0__AUART3_TX 0x2131
-MX28_PAD_SSP2_SS1__SSP2_D1 0x2141
-MX28_PAD_SSP2_SS2__SSP2_D2 0x2151
-MX28_PAD_SSP3_SCK__AUART4_TX 0x2181
-MX28_PAD_SSP3_MOSI__AUART4_RX 0x2191
-MX28_PAD_SSP3_MISO__AUART4_RTS 0x21a1
-MX28_PAD_SSP3_SS0__AUART4_CTS 0x21b1
-MX28_PAD_AUART0_RX__I2C0_SCL 0x3001
-MX28_PAD_AUART0_TX__I2C0_SDA 0x3011
-MX28_PAD_AUART0_CTS__AUART4_RX 0x3021
-MX28_PAD_AUART0_RTS__AUART4_TX 0x3031
-MX28_PAD_AUART1_RX__SSP2_CARD_DETECT 0x3041
-MX28_PAD_AUART1_TX__SSP3_CARD_DETECT 0x3051
-MX28_PAD_AUART1_CTS__USB0_OVERCURRENT 0x3061
-MX28_PAD_AUART1_RTS__USB0_ID 0x3071
-MX28_PAD_AUART2_RX__SSP3_D1 0x3081
-MX28_PAD_AUART2_TX__SSP3_D2 0x3091
-MX28_PAD_AUART2_CTS__I2C1_SCL 0x30a1
-MX28_PAD_AUART2_RTS__I2C1_SDA 0x30b1
-MX28_PAD_AUART3_RX__CAN0_TX 0x30c1
-MX28_PAD_AUART3_TX__CAN0_RX 0x30d1
-MX28_PAD_AUART3_CTS__CAN1_TX 0x30e1
-MX28_PAD_AUART3_RTS__CAN1_RX 0x30f1
-MX28_PAD_PWM0__I2C1_SCL 0x3101
-MX28_PAD_PWM1__I2C1_SDA 0x3111
-MX28_PAD_PWM2__USB0_ID 0x3121
-MX28_PAD_SAIF0_MCLK__PWM_3 0x3141
-MX28_PAD_SAIF0_LRCLK__PWM_4 0x3151
-MX28_PAD_SAIF0_BITCLK__PWM_5 0x3161
-MX28_PAD_SAIF0_SDATA0__PWM_6 0x3171
-MX28_PAD_I2C0_SCL__TIMROT_ROTARYA 0x3181
-MX28_PAD_I2C0_SDA__TIMROT_ROTARYB 0x3191
-MX28_PAD_SAIF1_SDATA0__PWM_7 0x31a1
-MX28_PAD_LCD_RESET__LCD_VSYNC 0x31e1
-MX28_PAD_ENET0_MDC__GPMI_CE4N 0x4001
-MX28_PAD_ENET0_MDIO__GPMI_CE5N 0x4011
-MX28_PAD_ENET0_RX_EN__GPMI_CE6N 0x4021
-MX28_PAD_ENET0_RXD0__GPMI_CE7N 0x4031
-MX28_PAD_ENET0_RXD1__GPMI_READY4 0x4041
-MX28_PAD_ENET0_TX_CLK__HSADC_TRIGGER 0x4051
-MX28_PAD_ENET0_TX_EN__GPMI_READY5 0x4061
-MX28_PAD_ENET0_TXD0__GPMI_READY6 0x4071
-MX28_PAD_ENET0_TXD1__GPMI_READY7 0x4081
-MX28_PAD_ENET0_RXD2__ENET1_RXD0 0x4091
-MX28_PAD_ENET0_RXD3__ENET1_RXD1 0x40a1
-MX28_PAD_ENET0_TXD2__ENET1_TXD0 0x40b1
-MX28_PAD_ENET0_TXD3__ENET1_TXD1 0x40c1
-MX28_PAD_ENET0_RX_CLK__ENET0_RX_ER 0x40d1
-MX28_PAD_ENET0_COL__ENET1_TX_EN 0x40e1
-MX28_PAD_ENET0_CRS__ENET1_RX_EN 0x40f1
-MX28_PAD_GPMI_CE2N__ENET0_RX_ER 0x0122
-MX28_PAD_GPMI_CE3N__SAIF1_MCLK 0x0132
-MX28_PAD_GPMI_RDY0__USB0_ID 0x0142
-MX28_PAD_GPMI_RDY2__ENET0_TX_ER 0x0162
-MX28_PAD_GPMI_RDY3__HSADC_TRIGGER 0x0172
-MX28_PAD_GPMI_ALE__SSP3_D4 0x01a2
-MX28_PAD_GPMI_CLE__SSP3_D5 0x01b2
-MX28_PAD_LCD_D00__ETM_DA0 0x1002
-MX28_PAD_LCD_D01__ETM_DA1 0x1012
-MX28_PAD_LCD_D02__ETM_DA2 0x1022
-MX28_PAD_LCD_D03__ETM_DA3 0x1032
-MX28_PAD_LCD_D04__ETM_DA4 0x1042
-MX28_PAD_LCD_D05__ETM_DA5 0x1052
-MX28_PAD_LCD_D06__ETM_DA6 0x1062
-MX28_PAD_LCD_D07__ETM_DA7 0x1072
-MX28_PAD_LCD_D08__ETM_DA8 0x1082
-MX28_PAD_LCD_D09__ETM_DA9 0x1092
-MX28_PAD_LCD_D10__ETM_DA10 0x10a2
-MX28_PAD_LCD_D11__ETM_DA11 0x10b2
-MX28_PAD_LCD_D12__ETM_DA12 0x10c2
-MX28_PAD_LCD_D13__ETM_DA13 0x10d2
-MX28_PAD_LCD_D14__ETM_DA14 0x10e2
-MX28_PAD_LCD_D15__ETM_DA15 0x10f2
-MX28_PAD_LCD_D16__ETM_DA7 0x1102
-MX28_PAD_LCD_D17__ETM_DA6 0x1112
-MX28_PAD_LCD_D18__ETM_DA5 0x1122
-MX28_PAD_LCD_D19__ETM_DA4 0x1132
-MX28_PAD_LCD_D20__ETM_DA3 0x1142
-MX28_PAD_LCD_D21__ETM_DA2 0x1152
-MX28_PAD_LCD_D22__ETM_DA1 0x1162
-MX28_PAD_LCD_D23__ETM_DA0 0x1172
-MX28_PAD_LCD_RD_E__ETM_TCTL 0x1182
-MX28_PAD_LCD_WR_RWN__ETM_TCLK 0x1192
-MX28_PAD_LCD_HSYNC__ETM_TCTL 0x11d2
-MX28_PAD_LCD_DOTCLK__ETM_TCLK 0x11e2
-MX28_PAD_SSP1_SCK__ENET0_1588_EVENT2_OUT 0x20c2
-MX28_PAD_SSP1_CMD__ENET0_1588_EVENT2_IN 0x20d2
-MX28_PAD_SSP1_DATA0__ENET0_1588_EVENT3_OUT 0x20e2
-MX28_PAD_SSP1_DATA3__ENET0_1588_EVENT3_IN 0x20f2
-MX28_PAD_SSP2_SCK__SAIF0_SDATA1 0x2102
-MX28_PAD_SSP2_MOSI__SAIF0_SDATA2 0x2112
-MX28_PAD_SSP2_MISO__SAIF1_SDATA1 0x2122
-MX28_PAD_SSP2_SS0__SAIF1_SDATA2 0x2132
-MX28_PAD_SSP2_SS1__USB1_OVERCURRENT 0x2142
-MX28_PAD_SSP2_SS2__USB0_OVERCURRENT 0x2152
-MX28_PAD_SSP3_SCK__ENET1_1588_EVENT0_OUT 0x2182
-MX28_PAD_SSP3_MOSI__ENET1_1588_EVENT0_IN 0x2192
-MX28_PAD_SSP3_MISO__ENET1_1588_EVENT1_OUT 0x21a2
-MX28_PAD_SSP3_SS0__ENET1_1588_EVENT1_IN 0x21b2
-MX28_PAD_AUART0_RX__DUART_CTS 0x3002
-MX28_PAD_AUART0_TX__DUART_RTS 0x3012
-MX28_PAD_AUART0_CTS__DUART_RX 0x3022
-MX28_PAD_AUART0_RTS__DUART_TX 0x3032
-MX28_PAD_AUART1_RX__PWM_0 0x3042
-MX28_PAD_AUART1_TX__PWM_1 0x3052
-MX28_PAD_AUART1_CTS__TIMROT_ROTARYA 0x3062
-MX28_PAD_AUART1_RTS__TIMROT_ROTARYB 0x3072
-MX28_PAD_AUART2_RX__SSP3_D4 0x3082
-MX28_PAD_AUART2_TX__SSP3_D5 0x3092
-MX28_PAD_AUART2_CTS__SAIF1_BITCLK 0x30a2
-MX28_PAD_AUART2_RTS__SAIF1_LRCLK 0x30b2
-MX28_PAD_AUART3_RX__ENET0_1588_EVENT0_OUT 0x30c2
-MX28_PAD_AUART3_TX__ENET0_1588_EVENT0_IN 0x30d2
-MX28_PAD_AUART3_CTS__ENET0_1588_EVENT1_OUT 0x30e2
-MX28_PAD_AUART3_RTS__ENET0_1588_EVENT1_IN 0x30f2
-MX28_PAD_PWM0__DUART_RX 0x3102
-MX28_PAD_PWM1__DUART_TX 0x3112
-MX28_PAD_PWM2__USB1_OVERCURRENT 0x3122
-MX28_PAD_SAIF0_MCLK__AUART4_CTS 0x3142
-MX28_PAD_SAIF0_LRCLK__AUART4_RTS 0x3152
-MX28_PAD_SAIF0_BITCLK__AUART4_RX 0x3162
-MX28_PAD_SAIF0_SDATA0__AUART4_TX 0x3172
-MX28_PAD_I2C0_SCL__DUART_RX 0x3182
-MX28_PAD_I2C0_SDA__DUART_TX 0x3192
-MX28_PAD_SAIF1_SDATA0__SAIF0_SDATA1 0x31a2
-MX28_PAD_SPDIF__ENET1_RX_ER 0x31b2
-MX28_PAD_ENET0_MDC__SAIF0_SDATA1 0x4002
-MX28_PAD_ENET0_MDIO__SAIF0_SDATA2 0x4012
-MX28_PAD_ENET0_RX_EN__SAIF1_SDATA1 0x4022
-MX28_PAD_ENET0_RXD0__SAIF1_SDATA2 0x4032
-MX28_PAD_ENET0_TX_CLK__ENET0_1588_EVENT2_OUT 0x4052
-MX28_PAD_ENET0_RXD2__ENET0_1588_EVENT0_OUT 0x4092
-MX28_PAD_ENET0_RXD3__ENET0_1588_EVENT0_IN 0x40a2
-MX28_PAD_ENET0_TXD2__ENET0_1588_EVENT1_OUT 0x40b2
-MX28_PAD_ENET0_TXD3__ENET0_1588_EVENT1_IN 0x40c2
-MX28_PAD_ENET0_RX_CLK__ENET0_1588_EVENT2_IN 0x40d2
-MX28_PAD_ENET0_COL__ENET0_1588_EVENT3_OUT 0x40e2
-MX28_PAD_ENET0_CRS__ENET0_1588_EVENT3_IN 0x40f2
-MX28_PAD_GPMI_D00__GPIO_0_0 0x0003
-MX28_PAD_GPMI_D01__GPIO_0_1 0x0013
-MX28_PAD_GPMI_D02__GPIO_0_2 0x0023
-MX28_PAD_GPMI_D03__GPIO_0_3 0x0033
-MX28_PAD_GPMI_D04__GPIO_0_4 0x0043
-MX28_PAD_GPMI_D05__GPIO_0_5 0x0053
-MX28_PAD_GPMI_D06__GPIO_0_6 0x0063
-MX28_PAD_GPMI_D07__GPIO_0_7 0x0073
-MX28_PAD_GPMI_CE0N__GPIO_0_16 0x0103
-MX28_PAD_GPMI_CE1N__GPIO_0_17 0x0113
-MX28_PAD_GPMI_CE2N__GPIO_0_18 0x0123
-MX28_PAD_GPMI_CE3N__GPIO_0_19 0x0133
-MX28_PAD_GPMI_RDY0__GPIO_0_20 0x0143
-MX28_PAD_GPMI_RDY1__GPIO_0_21 0x0153
-MX28_PAD_GPMI_RDY2__GPIO_0_22 0x0163
-MX28_PAD_GPMI_RDY3__GPIO_0_23 0x0173
-MX28_PAD_GPMI_RDN__GPIO_0_24 0x0183
-MX28_PAD_GPMI_WRN__GPIO_0_25 0x0193
-MX28_PAD_GPMI_ALE__GPIO_0_26 0x01a3
-MX28_PAD_GPMI_CLE__GPIO_0_27 0x01b3
-MX28_PAD_GPMI_RESETN__GPIO_0_28 0x01c3
-MX28_PAD_LCD_D00__GPIO_1_0 0x1003
-MX28_PAD_LCD_D01__GPIO_1_1 0x1013
-MX28_PAD_LCD_D02__GPIO_1_2 0x1023
-MX28_PAD_LCD_D03__GPIO_1_3 0x1033
-MX28_PAD_LCD_D04__GPIO_1_4 0x1043
-MX28_PAD_LCD_D05__GPIO_1_5 0x1053
-MX28_PAD_LCD_D06__GPIO_1_6 0x1063
-MX28_PAD_LCD_D07__GPIO_1_7 0x1073
-MX28_PAD_LCD_D08__GPIO_1_8 0x1083
-MX28_PAD_LCD_D09__GPIO_1_9 0x1093
-MX28_PAD_LCD_D10__GPIO_1_10 0x10a3
-MX28_PAD_LCD_D11__GPIO_1_11 0x10b3
-MX28_PAD_LCD_D12__GPIO_1_12 0x10c3
-MX28_PAD_LCD_D13__GPIO_1_13 0x10d3
-MX28_PAD_LCD_D14__GPIO_1_14 0x10e3
-MX28_PAD_LCD_D15__GPIO_1_15 0x10f3
-MX28_PAD_LCD_D16__GPIO_1_16 0x1103
-MX28_PAD_LCD_D17__GPIO_1_17 0x1113
-MX28_PAD_LCD_D18__GPIO_1_18 0x1123
-MX28_PAD_LCD_D19__GPIO_1_19 0x1133
-MX28_PAD_LCD_D20__GPIO_1_20 0x1143
-MX28_PAD_LCD_D21__GPIO_1_21 0x1153
-MX28_PAD_LCD_D22__GPIO_1_22 0x1163
-MX28_PAD_LCD_D23__GPIO_1_23 0x1173
-MX28_PAD_LCD_RD_E__GPIO_1_24 0x1183
-MX28_PAD_LCD_WR_RWN__GPIO_1_25 0x1193
-MX28_PAD_LCD_RS__GPIO_1_26 0x11a3
-MX28_PAD_LCD_CS__GPIO_1_27 0x11b3
-MX28_PAD_LCD_VSYNC__GPIO_1_28 0x11c3
-MX28_PAD_LCD_HSYNC__GPIO_1_29 0x11d3
-MX28_PAD_LCD_DOTCLK__GPIO_1_30 0x11e3
-MX28_PAD_LCD_ENABLE__GPIO_1_31 0x11f3
-MX28_PAD_SSP0_DATA0__GPIO_2_0 0x2003
-MX28_PAD_SSP0_DATA1__GPIO_2_1 0x2013
-MX28_PAD_SSP0_DATA2__GPIO_2_2 0x2023
-MX28_PAD_SSP0_DATA3__GPIO_2_3 0x2033
-MX28_PAD_SSP0_DATA4__GPIO_2_4 0x2043
-MX28_PAD_SSP0_DATA5__GPIO_2_5 0x2053
-MX28_PAD_SSP0_DATA6__GPIO_2_6 0x2063
-MX28_PAD_SSP0_DATA7__GPIO_2_7 0x2073
-MX28_PAD_SSP0_CMD__GPIO_2_8 0x2083
-MX28_PAD_SSP0_DETECT__GPIO_2_9 0x2093
-MX28_PAD_SSP0_SCK__GPIO_2_10 0x20a3
-MX28_PAD_SSP1_SCK__GPIO_2_12 0x20c3
-MX28_PAD_SSP1_CMD__GPIO_2_13 0x20d3
-MX28_PAD_SSP1_DATA0__GPIO_2_14 0x20e3
-MX28_PAD_SSP1_DATA3__GPIO_2_15 0x20f3
-MX28_PAD_SSP2_SCK__GPIO_2_16 0x2103
-MX28_PAD_SSP2_MOSI__GPIO_2_17 0x2113
-MX28_PAD_SSP2_MISO__GPIO_2_18 0x2123
-MX28_PAD_SSP2_SS0__GPIO_2_19 0x2133
-MX28_PAD_SSP2_SS1__GPIO_2_20 0x2143
-MX28_PAD_SSP2_SS2__GPIO_2_21 0x2153
-MX28_PAD_SSP3_SCK__GPIO_2_24 0x2183
-MX28_PAD_SSP3_MOSI__GPIO_2_25 0x2193
-MX28_PAD_SSP3_MISO__GPIO_2_26 0x21a3
-MX28_PAD_SSP3_SS0__GPIO_2_27 0x21b3
-MX28_PAD_AUART0_RX__GPIO_3_0 0x3003
-MX28_PAD_AUART0_TX__GPIO_3_1 0x3013
-MX28_PAD_AUART0_CTS__GPIO_3_2 0x3023
-MX28_PAD_AUART0_RTS__GPIO_3_3 0x3033
-MX28_PAD_AUART1_RX__GPIO_3_4 0x3043
-MX28_PAD_AUART1_TX__GPIO_3_5 0x3053
-MX28_PAD_AUART1_CTS__GPIO_3_6 0x3063
-MX28_PAD_AUART1_RTS__GPIO_3_7 0x3073
-MX28_PAD_AUART2_RX__GPIO_3_8 0x3083
-MX28_PAD_AUART2_TX__GPIO_3_9 0x3093
-MX28_PAD_AUART2_CTS__GPIO_3_10 0x30a3
-MX28_PAD_AUART2_RTS__GPIO_3_11 0x30b3
-MX28_PAD_AUART3_RX__GPIO_3_12 0x30c3
-MX28_PAD_AUART3_TX__GPIO_3_13 0x30d3
-MX28_PAD_AUART3_CTS__GPIO_3_14 0x30e3
-MX28_PAD_AUART3_RTS__GPIO_3_15 0x30f3
-MX28_PAD_PWM0__GPIO_3_16 0x3103
-MX28_PAD_PWM1__GPIO_3_17 0x3113
-MX28_PAD_PWM2__GPIO_3_18 0x3123
-MX28_PAD_SAIF0_MCLK__GPIO_3_20 0x3143
-MX28_PAD_SAIF0_LRCLK__GPIO_3_21 0x3153
-MX28_PAD_SAIF0_BITCLK__GPIO_3_22 0x3163
-MX28_PAD_SAIF0_SDATA0__GPIO_3_23 0x3173
-MX28_PAD_I2C0_SCL__GPIO_3_24 0x3183
-MX28_PAD_I2C0_SDA__GPIO_3_25 0x3193
-MX28_PAD_SAIF1_SDATA0__GPIO_3_26 0x31a3
-MX28_PAD_SPDIF__GPIO_3_27 0x31b3
-MX28_PAD_PWM3__GPIO_3_28 0x31c3
-MX28_PAD_PWM4__GPIO_3_29 0x31d3
-MX28_PAD_LCD_RESET__GPIO_3_30 0x31e3
-MX28_PAD_ENET0_MDC__GPIO_4_0 0x4003
-MX28_PAD_ENET0_MDIO__GPIO_4_1 0x4013
-MX28_PAD_ENET0_RX_EN__GPIO_4_2 0x4023
-MX28_PAD_ENET0_RXD0__GPIO_4_3 0x4033
-MX28_PAD_ENET0_RXD1__GPIO_4_4 0x4043
-MX28_PAD_ENET0_TX_CLK__GPIO_4_5 0x4053
-MX28_PAD_ENET0_TX_EN__GPIO_4_6 0x4063
-MX28_PAD_ENET0_TXD0__GPIO_4_7 0x4073
-MX28_PAD_ENET0_TXD1__GPIO_4_8 0x4083
-MX28_PAD_ENET0_RXD2__GPIO_4_9 0x4093
-MX28_PAD_ENET0_RXD3__GPIO_4_10 0x40a3
-MX28_PAD_ENET0_TXD2__GPIO_4_11 0x40b3
-MX28_PAD_ENET0_TXD3__GPIO_4_12 0x40c3
-MX28_PAD_ENET0_RX_CLK__GPIO_4_13 0x40d3
-MX28_PAD_ENET0_COL__GPIO_4_14 0x40e3
-MX28_PAD_ENET0_CRS__GPIO_4_15 0x40f3
-MX28_PAD_ENET_CLK__GPIO_4_16 0x4103
-MX28_PAD_JTAG_RTCK__GPIO_4_20 0x4143
-
-Valid values for i.MX23 pinmux-id:
-
-pinmux id
------- --
-MX23_PAD_GPMI_D00__GPMI_D00 0x0000
-MX23_PAD_GPMI_D01__GPMI_D01 0x0010
-MX23_PAD_GPMI_D02__GPMI_D02 0x0020
-MX23_PAD_GPMI_D03__GPMI_D03 0x0030
-MX23_PAD_GPMI_D04__GPMI_D04 0x0040
-MX23_PAD_GPMI_D05__GPMI_D05 0x0050
-MX23_PAD_GPMI_D06__GPMI_D06 0x0060
-MX23_PAD_GPMI_D07__GPMI_D07 0x0070
-MX23_PAD_GPMI_D08__GPMI_D08 0x0080
-MX23_PAD_GPMI_D09__GPMI_D09 0x0090
-MX23_PAD_GPMI_D10__GPMI_D10 0x00a0
-MX23_PAD_GPMI_D11__GPMI_D11 0x00b0
-MX23_PAD_GPMI_D12__GPMI_D12 0x00c0
-MX23_PAD_GPMI_D13__GPMI_D13 0x00d0
-MX23_PAD_GPMI_D14__GPMI_D14 0x00e0
-MX23_PAD_GPMI_D15__GPMI_D15 0x00f0
-MX23_PAD_GPMI_CLE__GPMI_CLE 0x0100
-MX23_PAD_GPMI_ALE__GPMI_ALE 0x0110
-MX23_PAD_GPMI_CE2N__GPMI_CE2N 0x0120
-MX23_PAD_GPMI_RDY0__GPMI_RDY0 0x0130
-MX23_PAD_GPMI_RDY1__GPMI_RDY1 0x0140
-MX23_PAD_GPMI_RDY2__GPMI_RDY2 0x0150
-MX23_PAD_GPMI_RDY3__GPMI_RDY3 0x0160
-MX23_PAD_GPMI_WPN__GPMI_WPN 0x0170
-MX23_PAD_GPMI_WRN__GPMI_WRN 0x0180
-MX23_PAD_GPMI_RDN__GPMI_RDN 0x0190
-MX23_PAD_AUART1_CTS__AUART1_CTS 0x01a0
-MX23_PAD_AUART1_RTS__AUART1_RTS 0x01b0
-MX23_PAD_AUART1_RX__AUART1_RX 0x01c0
-MX23_PAD_AUART1_TX__AUART1_TX 0x01d0
-MX23_PAD_I2C_SCL__I2C_SCL 0x01e0
-MX23_PAD_I2C_SDA__I2C_SDA 0x01f0
-MX23_PAD_LCD_D00__LCD_D00 0x1000
-MX23_PAD_LCD_D01__LCD_D01 0x1010
-MX23_PAD_LCD_D02__LCD_D02 0x1020
-MX23_PAD_LCD_D03__LCD_D03 0x1030
-MX23_PAD_LCD_D04__LCD_D04 0x1040
-MX23_PAD_LCD_D05__LCD_D05 0x1050
-MX23_PAD_LCD_D06__LCD_D06 0x1060
-MX23_PAD_LCD_D07__LCD_D07 0x1070
-MX23_PAD_LCD_D08__LCD_D08 0x1080
-MX23_PAD_LCD_D09__LCD_D09 0x1090
-MX23_PAD_LCD_D10__LCD_D10 0x10a0
-MX23_PAD_LCD_D11__LCD_D11 0x10b0
-MX23_PAD_LCD_D12__LCD_D12 0x10c0
-MX23_PAD_LCD_D13__LCD_D13 0x10d0
-MX23_PAD_LCD_D14__LCD_D14 0x10e0
-MX23_PAD_LCD_D15__LCD_D15 0x10f0
-MX23_PAD_LCD_D16__LCD_D16 0x1100
-MX23_PAD_LCD_D17__LCD_D17 0x1110
-MX23_PAD_LCD_RESET__LCD_RESET 0x1120
-MX23_PAD_LCD_RS__LCD_RS 0x1130
-MX23_PAD_LCD_WR__LCD_WR 0x1140
-MX23_PAD_LCD_CS__LCD_CS 0x1150
-MX23_PAD_LCD_DOTCK__LCD_DOTCK 0x1160
-MX23_PAD_LCD_ENABLE__LCD_ENABLE 0x1170
-MX23_PAD_LCD_HSYNC__LCD_HSYNC 0x1180
-MX23_PAD_LCD_VSYNC__LCD_VSYNC 0x1190
-MX23_PAD_PWM0__PWM0 0x11a0
-MX23_PAD_PWM1__PWM1 0x11b0
-MX23_PAD_PWM2__PWM2 0x11c0
-MX23_PAD_PWM3__PWM3 0x11d0
-MX23_PAD_PWM4__PWM4 0x11e0
-MX23_PAD_SSP1_CMD__SSP1_CMD 0x2000
-MX23_PAD_SSP1_DETECT__SSP1_DETECT 0x2010
-MX23_PAD_SSP1_DATA0__SSP1_DATA0 0x2020
-MX23_PAD_SSP1_DATA1__SSP1_DATA1 0x2030
-MX23_PAD_SSP1_DATA2__SSP1_DATA2 0x2040
-MX23_PAD_SSP1_DATA3__SSP1_DATA3 0x2050
-MX23_PAD_SSP1_SCK__SSP1_SCK 0x2060
-MX23_PAD_ROTARYA__ROTARYA 0x2070
-MX23_PAD_ROTARYB__ROTARYB 0x2080
-MX23_PAD_EMI_A00__EMI_A00 0x2090
-MX23_PAD_EMI_A01__EMI_A01 0x20a0
-MX23_PAD_EMI_A02__EMI_A02 0x20b0
-MX23_PAD_EMI_A03__EMI_A03 0x20c0
-MX23_PAD_EMI_A04__EMI_A04 0x20d0
-MX23_PAD_EMI_A05__EMI_A05 0x20e0
-MX23_PAD_EMI_A06__EMI_A06 0x20f0
-MX23_PAD_EMI_A07__EMI_A07 0x2100
-MX23_PAD_EMI_A08__EMI_A08 0x2110
-MX23_PAD_EMI_A09__EMI_A09 0x2120
-MX23_PAD_EMI_A10__EMI_A10 0x2130
-MX23_PAD_EMI_A11__EMI_A11 0x2140
-MX23_PAD_EMI_A12__EMI_A12 0x2150
-MX23_PAD_EMI_BA0__EMI_BA0 0x2160
-MX23_PAD_EMI_BA1__EMI_BA1 0x2170
-MX23_PAD_EMI_CASN__EMI_CASN 0x2180
-MX23_PAD_EMI_CE0N__EMI_CE0N 0x2190
-MX23_PAD_EMI_CE1N__EMI_CE1N 0x21a0
-MX23_PAD_GPMI_CE1N__GPMI_CE1N 0x21b0
-MX23_PAD_GPMI_CE0N__GPMI_CE0N 0x21c0
-MX23_PAD_EMI_CKE__EMI_CKE 0x21d0
-MX23_PAD_EMI_RASN__EMI_RASN 0x21e0
-MX23_PAD_EMI_WEN__EMI_WEN 0x21f0
-MX23_PAD_EMI_D00__EMI_D00 0x3000
-MX23_PAD_EMI_D01__EMI_D01 0x3010
-MX23_PAD_EMI_D02__EMI_D02 0x3020
-MX23_PAD_EMI_D03__EMI_D03 0x3030
-MX23_PAD_EMI_D04__EMI_D04 0x3040
-MX23_PAD_EMI_D05__EMI_D05 0x3050
-MX23_PAD_EMI_D06__EMI_D06 0x3060
-MX23_PAD_EMI_D07__EMI_D07 0x3070
-MX23_PAD_EMI_D08__EMI_D08 0x3080
-MX23_PAD_EMI_D09__EMI_D09 0x3090
-MX23_PAD_EMI_D10__EMI_D10 0x30a0
-MX23_PAD_EMI_D11__EMI_D11 0x30b0
-MX23_PAD_EMI_D12__EMI_D12 0x30c0
-MX23_PAD_EMI_D13__EMI_D13 0x30d0
-MX23_PAD_EMI_D14__EMI_D14 0x30e0
-MX23_PAD_EMI_D15__EMI_D15 0x30f0
-MX23_PAD_EMI_DQM0__EMI_DQM0 0x3100
-MX23_PAD_EMI_DQM1__EMI_DQM1 0x3110
-MX23_PAD_EMI_DQS0__EMI_DQS0 0x3120
-MX23_PAD_EMI_DQS1__EMI_DQS1 0x3130
-MX23_PAD_EMI_CLK__EMI_CLK 0x3140
-MX23_PAD_EMI_CLKN__EMI_CLKN 0x3150
-MX23_PAD_GPMI_D00__LCD_D8 0x0001
-MX23_PAD_GPMI_D01__LCD_D9 0x0011
-MX23_PAD_GPMI_D02__LCD_D10 0x0021
-MX23_PAD_GPMI_D03__LCD_D11 0x0031
-MX23_PAD_GPMI_D04__LCD_D12 0x0041
-MX23_PAD_GPMI_D05__LCD_D13 0x0051
-MX23_PAD_GPMI_D06__LCD_D14 0x0061
-MX23_PAD_GPMI_D07__LCD_D15 0x0071
-MX23_PAD_GPMI_D08__LCD_D18 0x0081
-MX23_PAD_GPMI_D09__LCD_D19 0x0091
-MX23_PAD_GPMI_D10__LCD_D20 0x00a1
-MX23_PAD_GPMI_D11__LCD_D21 0x00b1
-MX23_PAD_GPMI_D12__LCD_D22 0x00c1
-MX23_PAD_GPMI_D13__LCD_D23 0x00d1
-MX23_PAD_GPMI_D14__AUART2_RX 0x00e1
-MX23_PAD_GPMI_D15__AUART2_TX 0x00f1
-MX23_PAD_GPMI_CLE__LCD_D16 0x0101
-MX23_PAD_GPMI_ALE__LCD_D17 0x0111
-MX23_PAD_GPMI_CE2N__ATA_A2 0x0121
-MX23_PAD_AUART1_RTS__IR_CLK 0x01b1
-MX23_PAD_AUART1_RX__IR_RX 0x01c1
-MX23_PAD_AUART1_TX__IR_TX 0x01d1
-MX23_PAD_I2C_SCL__GPMI_RDY2 0x01e1
-MX23_PAD_I2C_SDA__GPMI_CE2N 0x01f1
-MX23_PAD_LCD_D00__ETM_DA8 0x1001
-MX23_PAD_LCD_D01__ETM_DA9 0x1011
-MX23_PAD_LCD_D02__ETM_DA10 0x1021
-MX23_PAD_LCD_D03__ETM_DA11 0x1031
-MX23_PAD_LCD_D04__ETM_DA12 0x1041
-MX23_PAD_LCD_D05__ETM_DA13 0x1051
-MX23_PAD_LCD_D06__ETM_DA14 0x1061
-MX23_PAD_LCD_D07__ETM_DA15 0x1071
-MX23_PAD_LCD_D08__ETM_DA0 0x1081
-MX23_PAD_LCD_D09__ETM_DA1 0x1091
-MX23_PAD_LCD_D10__ETM_DA2 0x10a1
-MX23_PAD_LCD_D11__ETM_DA3 0x10b1
-MX23_PAD_LCD_D12__ETM_DA4 0x10c1
-MX23_PAD_LCD_D13__ETM_DA5 0x10d1
-MX23_PAD_LCD_D14__ETM_DA6 0x10e1
-MX23_PAD_LCD_D15__ETM_DA7 0x10f1
-MX23_PAD_LCD_RESET__ETM_TCTL 0x1121
-MX23_PAD_LCD_RS__ETM_TCLK 0x1131
-MX23_PAD_LCD_DOTCK__GPMI_RDY3 0x1161
-MX23_PAD_LCD_ENABLE__I2C_SCL 0x1171
-MX23_PAD_LCD_HSYNC__I2C_SDA 0x1181
-MX23_PAD_LCD_VSYNC__LCD_BUSY 0x1191
-MX23_PAD_PWM0__ROTARYA 0x11a1
-MX23_PAD_PWM1__ROTARYB 0x11b1
-MX23_PAD_PWM2__GPMI_RDY3 0x11c1
-MX23_PAD_PWM3__ETM_TCTL 0x11d1
-MX23_PAD_PWM4__ETM_TCLK 0x11e1
-MX23_PAD_SSP1_DETECT__GPMI_CE3N 0x2011
-MX23_PAD_SSP1_DATA1__I2C_SCL 0x2031
-MX23_PAD_SSP1_DATA2__I2C_SDA 0x2041
-MX23_PAD_ROTARYA__AUART2_RTS 0x2071
-MX23_PAD_ROTARYB__AUART2_CTS 0x2081
-MX23_PAD_GPMI_D00__SSP2_DATA0 0x0002
-MX23_PAD_GPMI_D01__SSP2_DATA1 0x0012
-MX23_PAD_GPMI_D02__SSP2_DATA2 0x0022
-MX23_PAD_GPMI_D03__SSP2_DATA3 0x0032
-MX23_PAD_GPMI_D04__SSP2_DATA4 0x0042
-MX23_PAD_GPMI_D05__SSP2_DATA5 0x0052
-MX23_PAD_GPMI_D06__SSP2_DATA6 0x0062
-MX23_PAD_GPMI_D07__SSP2_DATA7 0x0072
-MX23_PAD_GPMI_D08__SSP1_DATA4 0x0082
-MX23_PAD_GPMI_D09__SSP1_DATA5 0x0092
-MX23_PAD_GPMI_D10__SSP1_DATA6 0x00a2
-MX23_PAD_GPMI_D11__SSP1_DATA7 0x00b2
-MX23_PAD_GPMI_D15__GPMI_CE3N 0x00f2
-MX23_PAD_GPMI_RDY0__SSP2_DETECT 0x0132
-MX23_PAD_GPMI_RDY1__SSP2_CMD 0x0142
-MX23_PAD_GPMI_WRN__SSP2_SCK 0x0182
-MX23_PAD_AUART1_CTS__SSP1_DATA4 0x01a2
-MX23_PAD_AUART1_RTS__SSP1_DATA5 0x01b2
-MX23_PAD_AUART1_RX__SSP1_DATA6 0x01c2
-MX23_PAD_AUART1_TX__SSP1_DATA7 0x01d2
-MX23_PAD_I2C_SCL__AUART1_TX 0x01e2
-MX23_PAD_I2C_SDA__AUART1_RX 0x01f2
-MX23_PAD_LCD_D08__SAIF2_SDATA0 0x1082
-MX23_PAD_LCD_D09__SAIF1_SDATA0 0x1092
-MX23_PAD_LCD_D10__SAIF_MCLK_BITCLK 0x10a2
-MX23_PAD_LCD_D11__SAIF_LRCLK 0x10b2
-MX23_PAD_LCD_D12__SAIF2_SDATA1 0x10c2
-MX23_PAD_LCD_D13__SAIF2_SDATA2 0x10d2
-MX23_PAD_LCD_D14__SAIF1_SDATA2 0x10e2
-MX23_PAD_LCD_D15__SAIF1_SDATA1 0x10f2
-MX23_PAD_LCD_D16__SAIF_ALT_BITCLK 0x1102
-MX23_PAD_LCD_RESET__GPMI_CE3N 0x1122
-MX23_PAD_PWM0__DUART_RX 0x11a2
-MX23_PAD_PWM1__DUART_TX 0x11b2
-MX23_PAD_PWM3__AUART1_CTS 0x11d2
-MX23_PAD_PWM4__AUART1_RTS 0x11e2
-MX23_PAD_SSP1_CMD__JTAG_TDO 0x2002
-MX23_PAD_SSP1_DETECT__USB_OTG_ID 0x2012
-MX23_PAD_SSP1_DATA0__JTAG_TDI 0x2022
-MX23_PAD_SSP1_DATA1__JTAG_TCLK 0x2032
-MX23_PAD_SSP1_DATA2__JTAG_RTCK 0x2042
-MX23_PAD_SSP1_DATA3__JTAG_TMS 0x2052
-MX23_PAD_SSP1_SCK__JTAG_TRST 0x2062
-MX23_PAD_ROTARYA__SPDIF 0x2072
-MX23_PAD_ROTARYB__GPMI_CE3N 0x2082
-MX23_PAD_GPMI_D00__GPIO_0_0 0x0003
-MX23_PAD_GPMI_D01__GPIO_0_1 0x0013
-MX23_PAD_GPMI_D02__GPIO_0_2 0x0023
-MX23_PAD_GPMI_D03__GPIO_0_3 0x0033
-MX23_PAD_GPMI_D04__GPIO_0_4 0x0043
-MX23_PAD_GPMI_D05__GPIO_0_5 0x0053
-MX23_PAD_GPMI_D06__GPIO_0_6 0x0063
-MX23_PAD_GPMI_D07__GPIO_0_7 0x0073
-MX23_PAD_GPMI_D08__GPIO_0_8 0x0083
-MX23_PAD_GPMI_D09__GPIO_0_9 0x0093
-MX23_PAD_GPMI_D10__GPIO_0_10 0x00a3
-MX23_PAD_GPMI_D11__GPIO_0_11 0x00b3
-MX23_PAD_GPMI_D12__GPIO_0_12 0x00c3
-MX23_PAD_GPMI_D13__GPIO_0_13 0x00d3
-MX23_PAD_GPMI_D14__GPIO_0_14 0x00e3
-MX23_PAD_GPMI_D15__GPIO_0_15 0x00f3
-MX23_PAD_GPMI_CLE__GPIO_0_16 0x0103
-MX23_PAD_GPMI_ALE__GPIO_0_17 0x0113
-MX23_PAD_GPMI_CE2N__GPIO_0_18 0x0123
-MX23_PAD_GPMI_RDY0__GPIO_0_19 0x0133
-MX23_PAD_GPMI_RDY1__GPIO_0_20 0x0143
-MX23_PAD_GPMI_RDY2__GPIO_0_21 0x0153
-MX23_PAD_GPMI_RDY3__GPIO_0_22 0x0163
-MX23_PAD_GPMI_WPN__GPIO_0_23 0x0173
-MX23_PAD_GPMI_WRN__GPIO_0_24 0x0183
-MX23_PAD_GPMI_RDN__GPIO_0_25 0x0193
-MX23_PAD_AUART1_CTS__GPIO_0_26 0x01a3
-MX23_PAD_AUART1_RTS__GPIO_0_27 0x01b3
-MX23_PAD_AUART1_RX__GPIO_0_28 0x01c3
-MX23_PAD_AUART1_TX__GPIO_0_29 0x01d3
-MX23_PAD_I2C_SCL__GPIO_0_30 0x01e3
-MX23_PAD_I2C_SDA__GPIO_0_31 0x01f3
-MX23_PAD_LCD_D00__GPIO_1_0 0x1003
-MX23_PAD_LCD_D01__GPIO_1_1 0x1013
-MX23_PAD_LCD_D02__GPIO_1_2 0x1023
-MX23_PAD_LCD_D03__GPIO_1_3 0x1033
-MX23_PAD_LCD_D04__GPIO_1_4 0x1043
-MX23_PAD_LCD_D05__GPIO_1_5 0x1053
-MX23_PAD_LCD_D06__GPIO_1_6 0x1063
-MX23_PAD_LCD_D07__GPIO_1_7 0x1073
-MX23_PAD_LCD_D08__GPIO_1_8 0x1083
-MX23_PAD_LCD_D09__GPIO_1_9 0x1093
-MX23_PAD_LCD_D10__GPIO_1_10 0x10a3
-MX23_PAD_LCD_D11__GPIO_1_11 0x10b3
-MX23_PAD_LCD_D12__GPIO_1_12 0x10c3
-MX23_PAD_LCD_D13__GPIO_1_13 0x10d3
-MX23_PAD_LCD_D14__GPIO_1_14 0x10e3
-MX23_PAD_LCD_D15__GPIO_1_15 0x10f3
-MX23_PAD_LCD_D16__GPIO_1_16 0x1103
-MX23_PAD_LCD_D17__GPIO_1_17 0x1113
-MX23_PAD_LCD_RESET__GPIO_1_18 0x1123
-MX23_PAD_LCD_RS__GPIO_1_19 0x1133
-MX23_PAD_LCD_WR__GPIO_1_20 0x1143
-MX23_PAD_LCD_CS__GPIO_1_21 0x1153
-MX23_PAD_LCD_DOTCK__GPIO_1_22 0x1163
-MX23_PAD_LCD_ENABLE__GPIO_1_23 0x1173
-MX23_PAD_LCD_HSYNC__GPIO_1_24 0x1183
-MX23_PAD_LCD_VSYNC__GPIO_1_25 0x1193
-MX23_PAD_PWM0__GPIO_1_26 0x11a3
-MX23_PAD_PWM1__GPIO_1_27 0x11b3
-MX23_PAD_PWM2__GPIO_1_28 0x11c3
-MX23_PAD_PWM3__GPIO_1_29 0x11d3
-MX23_PAD_PWM4__GPIO_1_30 0x11e3
-MX23_PAD_SSP1_CMD__GPIO_2_0 0x2003
-MX23_PAD_SSP1_DETECT__GPIO_2_1 0x2013
-MX23_PAD_SSP1_DATA0__GPIO_2_2 0x2023
-MX23_PAD_SSP1_DATA1__GPIO_2_3 0x2033
-MX23_PAD_SSP1_DATA2__GPIO_2_4 0x2043
-MX23_PAD_SSP1_DATA3__GPIO_2_5 0x2053
-MX23_PAD_SSP1_SCK__GPIO_2_6 0x2063
-MX23_PAD_ROTARYA__GPIO_2_7 0x2073
-MX23_PAD_ROTARYB__GPIO_2_8 0x2083
-MX23_PAD_EMI_A00__GPIO_2_9 0x2093
-MX23_PAD_EMI_A01__GPIO_2_10 0x20a3
-MX23_PAD_EMI_A02__GPIO_2_11 0x20b3
-MX23_PAD_EMI_A03__GPIO_2_12 0x20c3
-MX23_PAD_EMI_A04__GPIO_2_13 0x20d3
-MX23_PAD_EMI_A05__GPIO_2_14 0x20e3
-MX23_PAD_EMI_A06__GPIO_2_15 0x20f3
-MX23_PAD_EMI_A07__GPIO_2_16 0x2103
-MX23_PAD_EMI_A08__GPIO_2_17 0x2113
-MX23_PAD_EMI_A09__GPIO_2_18 0x2123
-MX23_PAD_EMI_A10__GPIO_2_19 0x2133
-MX23_PAD_EMI_A11__GPIO_2_20 0x2143
-MX23_PAD_EMI_A12__GPIO_2_21 0x2153
-MX23_PAD_EMI_BA0__GPIO_2_22 0x2163
-MX23_PAD_EMI_BA1__GPIO_2_23 0x2173
-MX23_PAD_EMI_CASN__GPIO_2_24 0x2183
-MX23_PAD_EMI_CE0N__GPIO_2_25 0x2193
-MX23_PAD_EMI_CE1N__GPIO_2_26 0x21a3
-MX23_PAD_GPMI_CE1N__GPIO_2_27 0x21b3
-MX23_PAD_GPMI_CE0N__GPIO_2_28 0x21c3
-MX23_PAD_EMI_CKE__GPIO_2_29 0x21d3
-MX23_PAD_EMI_RASN__GPIO_2_30 0x21e3
-MX23_PAD_EMI_WEN__GPIO_2_31 0x21f3
+Valid values for i.MX28/i.MX23 pinmux-id are defined in
+arch/arm/boot/dts/imx28-pinfunc.h and arch/arm/boot/dts/imx23-pinfunc.h.
+The definitions for the padconfig properties can be found in
+arch/arm/boot/dts/mxs-pinfunc.h.
diff --git a/Documentation/devicetree/bindings/regulator/as3722-regulator.txt b/Documentation/devicetree/bindings/regulator/as3722-regulator.txt
new file mode 100644
index 000000000000..caad0c8a258d
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/as3722-regulator.txt
@@ -0,0 +1,91 @@
+Regulator of AMS AS3722 PMIC.
+Name of the regulator subnode must be "regulators".
+
+Optional properties:
+--------------------
+The input supply of regulators are the optional properties on the
+regulator node. The AS3722 is having 7 DCDC step-down regulators as
+sd[0-6], 10 LDOs as ldo[0-7], ldo[9-11]. The input supply of these
+regulators are provided through following properties:
+vsup-sd2-supply: Input supply for SD2.
+vsup-sd3-supply: Input supply for SD3.
+vsup-sd4-supply: Input supply for SD4.
+vsup-sd5-supply: Input supply for SD5.
+vin-ldo0-supply: Input supply for LDO0.
+vin-ldo1-6-supply: Input supply for LDO1 and LDO6.
+vin-ldo2-5-7-supply: Input supply for LDO2, LDO5 and LDO7.
+vin-ldo3-4-supply: Input supply for LDO3 and LDO4.
+vin-ldo9-10-supply: Input supply for LDO9 and LDO10.
+vin-ldo11-supply: Input supply for LDO11.
+
+Optional nodes:
+--------------
+- regulators : Must contain a sub-node per regulator from the list below.
+ Each sub-node should contain the constraints and initialization
+ information for that regulator. See regulator.txt for a
+ description of standard properties for these sub-nodes.
+ Additional custom properties are listed below.
+ sd[0-6], ldo[0-7], ldo[9-11].
+
+ Optional sub-node properties:
+ ----------------------------
+ ams,ext-control: External control of the rail. The option of
+ this properties will tell which external input is
+ controlling this rail. Valid values are 0, 1, 2 ad 3.
+ 0: There is no external control of this rail.
+ 1: Rail is controlled by ENABLE1 input pin.
+ 2: Rail is controlled by ENABLE2 input pin.
+ 3: Rail is controlled by ENABLE3 input pin.
+ ams,enable-tracking: Enable tracking with SD1, only supported
+ by LDO3.
+
+Example:
+-------
+ ams3722: ams3722 {
+ compatible = "ams,as3722";
+ reg = <0x40>;
+ ...
+
+ regulators {
+ vsup-sd2-supply = <...>;
+ ...
+
+ sd0 {
+ regulator-name = "vdd_cpu";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-always-on;
+ ams,ext-control = <2>;
+ };
+
+ sd1 {
+ regulator-name = "vdd_core";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-always-on;
+ ams,ext-control = <1>;
+ };
+
+ sd2 {
+ regulator-name = "vddio_ddr";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-always-on;
+ };
+
+ sd4 {
+ regulator-name = "avdd-hdmi-pex";
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-always-on;
+ };
+
+ sd5 {
+ regulator-name = "vdd-1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+ ....
+ };
+ };
diff --git a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
index 875639ae0606..42e6b6bc48ff 100644
--- a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
+++ b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
@@ -26,11 +26,17 @@ Optional nodes:
For ti,palmas-pmic - smps12, smps123, smps3 depending on OTP,
smps45, smps457, smps7 depending on variant, smps6, smps[8-9],
- smps10_out2, smps10_out1, do[1-9], ldoln, ldousb.
+ smps10_out2, smps10_out1, ldo[1-9], ldoln, ldousb.
Optional sub-node properties:
ti,warm-reset - maintain voltage during warm reset(boolean)
- ti,roof-floor - control voltage selection by pin(boolean)
+ ti,roof-floor - This takes as optional argument on platform supporting
+ the rail from desired external control. If there is no argument then
+ it will be assume that it is controlled by NSLEEP pin.
+ The valid value for external pins are:
+ ENABLE1 then 1,
+ ENABLE2 then 2 or
+ NSLEEP then 3.
ti,mode-sleep - mode to adopt in pmic sleep 0 - off, 1 - auto,
2 - eco, 3 - forced pwm
ti,smps-range - OTP has the wrong range set for the hardware so override
@@ -61,7 +67,7 @@ pmic {
regulator-always-on;
regulator-boot-on;
ti,warm-reset;
- ti,roof-floor;
+ ti,roof-floor = <1>; /* ENABLE1 control */
ti,mode-sleep = <0>;
ti,smps-range = <1>;
};
diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt
index 2bd8f0978765..e2c7f1e7251a 100644
--- a/Documentation/devicetree/bindings/regulator/regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/regulator.txt
@@ -14,6 +14,11 @@ Optional properties:
- regulator-ramp-delay: ramp delay for regulator(in uV/uS)
For hardwares which support disabling ramp rate, it should be explicitly
intialised to zero (regulator-ramp-delay = <0>) for disabling ramp delay.
+- regulator-enable-ramp-delay: The time taken, in microseconds, for the supply
+ rail to reach the target voltage, plus/minus whatever tolerance the board
+ design requires. This property describes the total system ramp time
+ required due to the combination of internal ramping of the regulator itself,
+ and board design issues such as trace capacitance and load on the supply.
Deprecated properties:
- regulator-compatible: If a regulator chip contains multiple
diff --git a/Documentation/devicetree/bindings/tty/serial/qca,ar9330-uart.txt b/Documentation/devicetree/bindings/serial/qca,ar9330-uart.txt
index c5e032c85bf9..c5e032c85bf9 100644
--- a/Documentation/devicetree/bindings/tty/serial/qca,ar9330-uart.txt
+++ b/Documentation/devicetree/bindings/serial/qca,ar9330-uart.txt
diff --git a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
index 705a6b156c6c..5e6040c2c2e9 100644
--- a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
+++ b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
@@ -24,10 +24,36 @@ Optional properties:
3 - MICBIAS output is connected to AVDD,
If this node is not mentioned or if the value is incorrect, then MicBias
is powered down.
+- AVDD-supply, IOVDD-supply, DRVDD-supply, DVDD-supply : power supplies for the
+ device as covered in Documentation/devicetree/bindings/regulator/regulator.txt
+
+CODEC output pins:
+ * LLOUT
+ * RLOUT
+ * MONO_LOUT
+ * HPLOUT
+ * HPROUT
+ * HPLCOM
+ * HPRCOM
+
+CODEC input pins:
+ * MIC3L
+ * MIC3R
+ * LINE1L
+ * LINE2L
+ * LINE1R
+ * LINE2R
+
+The pins can be used in referring sound node's audio-routing property.
Example:
tlv320aic3x: tlv320aic3x@1b {
compatible = "ti,tlv320aic3x";
reg = <0x1b>;
+
+ AVDD-supply = <&regulator>;
+ IOVDD-supply = <&regulator>;
+ DRVDD-supply = <&regulator>;
+ DVDD-supply = <&regulator>;
};
diff --git a/Documentation/devicetree/bindings/tty/serial/renesas,sci-serial.txt b/Documentation/devicetree/bindings/tty/serial/renesas,sci-serial.txt
new file mode 100644
index 000000000000..6ad1adfd4577
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/renesas,sci-serial.txt
@@ -0,0 +1,53 @@
+* Renesas SH-Mobile Serial Communication Interface
+
+Required properties:
+- compatible : Should be "renesas,sci-<port type>-uart", where <port type> may be
+ SCI, SCIF, IRDA, SCIFA or SCIFB.
+- reg : Address and length of the register set for the device
+- interrupts : Should contain the following IRQs: ERI, RXI, TXI and BRI.
+- cell-index : The device id.
+- renesas,scscr : Should contain a bitfield used by the Serial Control Register.
+ b7 = SCSCR_TIE
+ b6 = SCSCR_RIE
+ b5 = SCSCR_TE
+ b4 = SCSCR_RE
+ b3 = SCSCR_REIE
+ b2 = SCSCR_TOIE
+ b1 = SCSCR_CKE1
+ b0 = SCSCR_CKE0
+- renesas,scbrr-algo-id : Algorithm ID for the Bit Rate Register
+ 1 = SCBRR_ALGO_1 ((clk + 16 * bps) / (16 * bps) - 1)
+ 2 = SCBRR_ALGO_2 ((clk + 16 * bps) / (32 * bps) - 1)
+ 3 = SCBRR_ALGO_3 (((clk * 2) + 16 * bps) / (16 * bps) - 1)
+ 4 = SCBRR_ALGO_4 (((clk * 2) + 16 * bps) / (32 * bps) - 1)
+ 5 = SCBRR_ALGO_5 (((clk * 1000 / 32) / bps) - 1)
+
+Optional properties:
+- renesas,autoconf : Set if device is capable of auto configuration
+- renesas,regtype : Overwrite the register layout. In most cases you can rely
+ on auto-probing (omit this property or set to 0) but some legacy devices
+ use a non-default register layout. Possible layouts are
+ 0 = SCIx_PROBE_REGTYPE (default)
+ 1 = SCIx_SCI_REGTYPE
+ 2 = SCIx_IRDA_REGTYPE
+ 3 = SCIx_SCIFA_REGTYPE
+ 4 = SCIx_SCIFB_REGTYPE
+ 5 = SCIx_SH2_SCIF_FIFODATA_REGTYPE
+ 6 = SCIx_SH3_SCIF_REGTYPE
+ 7 = SCIx_SH4_SCIF_REGTYPE
+ 8 = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE
+ 9 = SCIx_SH4_SCIF_FIFODATA_REGTYPE
+ 10 = SCIx_SH7705_SCIF_REGTYPE
+
+
+Example:
+ sci@0xe6c50000 {
+ compatible = "renesas,sci-SCIFA-uart";
+ interrupt-parent = <&intca>;
+ reg = <0xe6c50000 0x100>;
+ interrupts = <0x0c20>, <0x0c20>, <0x0c20>, <0x0c20>;
+ cell-index = <1>;
+ renesas,scscr = <0x30>;
+ renesas,scbrr-algo-id = <4>;
+ renesas,autoconf;
+ };
diff --git a/Documentation/devicetree/bindings/video/atmel,lcdc.txt b/Documentation/devicetree/bindings/video/atmel,lcdc.txt
new file mode 100644
index 000000000000..1ec175eddca8
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/atmel,lcdc.txt
@@ -0,0 +1,75 @@
+Atmel LCDC Framebuffer
+-----------------------------------------------------
+
+Required properties:
+- compatible :
+ "atmel,at91sam9261-lcdc" ,
+ "atmel,at91sam9263-lcdc" ,
+ "atmel,at91sam9g10-lcdc" ,
+ "atmel,at91sam9g45-lcdc" ,
+ "atmel,at91sam9g45es-lcdc" ,
+ "atmel,at91sam9rl-lcdc" ,
+ "atmel,at32ap-lcdc"
+- reg : Should contain 1 register ranges(address and length)
+- interrupts : framebuffer controller interrupt
+- display: a phandle pointing to the display node
+
+Required nodes:
+- display: a display node is required to initialize the lcd panel
+ This should be in the board dts.
+- default-mode: a videomode within the display with timing parameters
+ as specified below.
+
+Example:
+
+ fb0: fb@0x00500000 {
+ compatible = "atmel,at91sam9g45-lcdc";
+ reg = <0x00500000 0x1000>;
+ interrupts = <23 3 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fb>;
+ display = <&display0>;
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ };
+
+Atmel LCDC Display
+-----------------------------------------------------
+Required properties (as per of_videomode_helper):
+
+ - atmel,dmacon: dma controler configuration
+ - atmel,lcdcon2: lcd controler configuration
+ - atmel,guard-time: lcd guard time (Delay in frame periods)
+ - bits-per-pixel: lcd panel bit-depth.
+
+Optional properties (as per of_videomode_helper):
+ - atmel,lcdcon-backlight: enable backlight
+ - atmel,lcd-wiring-mode: lcd wiring mode "RGB" or "BRG"
+ - atmel,power-control-gpio: gpio to power on or off the LCD (as many as needed)
+
+Example:
+ display0: display {
+ bits-per-pixel = <32>;
+ atmel,lcdcon-backlight;
+ atmel,dmacon = <0x1>;
+ atmel,lcdcon2 = <0x80008002>;
+ atmel,guard-time = <9>;
+ atmel,lcd-wiring-mode = <1>;
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: timing0 {
+ clock-frequency = <9000000>;
+ hactive = <480>;
+ vactive = <272>;
+ hback-porch = <1>;
+ hfront-porch = <1>;
+ vback-porch = <40>;
+ vfront-porch = <1>;
+ hsync-len = <45>;
+ vsync-len = <1>;
+ };
+ };
+ };
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index fcb34a5697ea..5bdc8cb5fc28 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -283,6 +283,7 @@ REGULATOR
devm_regulator_get()
devm_regulator_put()
devm_regulator_bulk_get()
+ devm_regulator_register()
CLOCK
devm_clk_get()
@@ -302,3 +303,6 @@ PHY
SLAVE DMA ENGINE
devm_acpi_dma_controller_register()
+
+SPI
+ devm_spi_register_master()
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index fe7afe225381..21ef48f0778f 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -192,8 +192,8 @@ prototypes:
void (*invalidatepage) (struct page *, unsigned int, unsigned int);
int (*releasepage) (struct page *, int);
void (*freepage)(struct page *);
- int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
- loff_t offset, unsigned long nr_segs);
+ int (*direct_IO)(int, struct kiocb *, struct iov_iter *iter,
+ loff_t offset);
int (*get_xip_mem)(struct address_space *, pgoff_t, int, void **,
unsigned long *);
int (*migratepage)(struct address_space *, struct page *, struct page *);
@@ -426,7 +426,9 @@ prototypes:
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ ssize_t (*read_iter) (struct kiocb *, struct iov_iter *, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ ssize_t (*write_iter) (struct kiocb *, struct iov_iter *, loff_t);
int (*iterate) (struct file *, struct dir_context *);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
diff --git a/Documentation/filesystems/caching/netfs-api.txt b/Documentation/filesystems/caching/netfs-api.txt
index 11a0a40ce445..aed6b94160b1 100644
--- a/Documentation/filesystems/caching/netfs-api.txt
+++ b/Documentation/filesystems/caching/netfs-api.txt
@@ -29,15 +29,16 @@ This document contains the following sections:
(6) Index registration
(7) Data file registration
(8) Miscellaneous object registration
- (9) Setting the data file size
+ (9) Setting the data file size
(10) Page alloc/read/write
(11) Page uncaching
(12) Index and data file consistency
- (13) Miscellaneous cookie operations
- (14) Cookie unregistration
- (15) Index invalidation
- (16) Data file invalidation
- (17) FS-Cache specific page flags.
+ (13) Cookie enablement
+ (14) Miscellaneous cookie operations
+ (15) Cookie unregistration
+ (16) Index invalidation
+ (17) Data file invalidation
+ (18) FS-Cache specific page flags.
=============================
@@ -334,7 +335,8 @@ the path to the file:
struct fscache_cookie *
fscache_acquire_cookie(struct fscache_cookie *parent,
const struct fscache_object_def *def,
- void *netfs_data);
+ void *netfs_data,
+ bool enable);
This function creates an index entry in the index represented by parent,
filling in the index entry by calling the operations pointed to by def.
@@ -350,6 +352,10 @@ object needs to be created somewhere down the hierarchy. Furthermore, an index
may be created in several different caches independently at different times.
This is all handled transparently, and the netfs doesn't see any of it.
+A cookie will be created in the disabled state if enabled is false. A cookie
+must be enabled to do anything with it. A disabled cookie can be enabled by
+calling fscache_enable_cookie() (see below).
+
For example, with AFS, a cell would be added to the primary index. This index
entry would have a dependent inode containing a volume location index for the
volume mappings within this cell:
@@ -357,7 +363,7 @@ volume mappings within this cell:
cell->cache =
fscache_acquire_cookie(afs_cache_netfs.primary_index,
&afs_cell_cache_index_def,
- cell);
+ cell, true);
Then when a volume location was accessed, it would be entered into the cell's
index and an inode would be allocated that acts as a volume type and hash chain
@@ -366,7 +372,7 @@ combination:
vlocation->cache =
fscache_acquire_cookie(cell->cache,
&afs_vlocation_cache_index_def,
- vlocation);
+ vlocation, true);
And then a particular flavour of volume (R/O for example) could be added to
that index, creating another index for vnodes (AFS inode equivalents):
@@ -374,7 +380,7 @@ that index, creating another index for vnodes (AFS inode equivalents):
volume->cache =
fscache_acquire_cookie(vlocation->cache,
&afs_volume_cache_index_def,
- volume);
+ volume, true);
======================
@@ -388,7 +394,7 @@ the object definition should be something other than index type.
vnode->cache =
fscache_acquire_cookie(volume->cache,
&afs_vnode_cache_object_def,
- vnode);
+ vnode, true);
=================================
@@ -404,7 +410,7 @@ it would be some other type of object such as a data file.
xattr->cache =
fscache_acquire_cookie(vnode->cache,
&afs_xattr_cache_object_def,
- xattr);
+ xattr, true);
Miscellaneous objects might be used to store extended attributes or directory
entries for example.
@@ -733,6 +739,47 @@ Note that partial updates may happen automatically at other times, such as when
data blocks are added to a data file object.
+=================
+COOKIE ENABLEMENT
+=================
+
+Cookies exist in one of two states: enabled and disabled. If a cookie is
+disabled, it ignores all attempts to acquire child cookies; check, update or
+invalidate its state; allocate, read or write backing pages - though it is
+still possible to uncache pages and relinquish the cookie.
+
+The initial enablement state is set by fscache_acquire_cookie(), but the cookie
+can be enabled or disabled later. To disable a cookie, call:
+
+ void fscache_disable_cookie(struct fscache_cookie *cookie,
+ bool invalidate);
+
+If the cookie is not already disabled, this locks the cookie against other
+enable and disable ops, marks the cookie as being disabled, discards or
+invalidates any backing objects and waits for cessation of activity on any
+associated object before unlocking the cookie.
+
+All possible failures are handled internally. The caller should consider
+calling fscache_uncache_all_inode_pages() afterwards to make sure all page
+markings are cleared up.
+
+Cookies can be enabled or reenabled with:
+
+ void fscache_enable_cookie(struct fscache_cookie *cookie,
+ bool (*can_enable)(void *data),
+ void *data)
+
+If the cookie is not already enabled, this locks the cookie against other
+enable and disable ops, invokes can_enable() and, if the cookie is not an index
+cookie, will begin the procedure of acquiring backing objects.
+
+The optional can_enable() function is passed the data argument and returns a
+ruling as to whether or not enablement should actually be permitted to begin.
+
+All possible failures are handled internally. The cookie will only be marked
+as enabled if provisional backing objects are allocated.
+
+
===============================
MISCELLANEOUS COOKIE OPERATIONS
===============================
@@ -778,7 +825,7 @@ COOKIE UNREGISTRATION
To get rid of a cookie, this function should be called.
void fscache_relinquish_cookie(struct fscache_cookie *cookie,
- int retire);
+ bool retire);
If retire is non-zero, then the object will be marked for recycling, and all
copies of it will be removed from all active caches in which it is present.
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index deb48b5fd883..47fa5a3e9185 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -573,8 +573,8 @@ struct address_space_operations {
void (*invalidatepage) (struct page *, unsigned int, unsigned int);
int (*releasepage) (struct page *, int);
void (*freepage)(struct page *);
- ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
- loff_t offset, unsigned long nr_segs);
+ ssize_t (*direct_IO)(int, struct kiocb *, struct iov_iter *iter,
+ loff_t offset);
struct page* (*get_xip_page)(struct address_space *, sector_t,
int);
/* migrate the contents of a page to the specified target */
@@ -790,7 +790,9 @@ struct file_operations {
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ ssize_t (*read_iter) (struct kiocb *, struct iov_iter *, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ ssize_t (*write_iter) (struct kiocb *, struct iov_iter *, loff_t);
int (*iterate) (struct file *, struct dir_context *);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
@@ -825,10 +827,16 @@ otherwise noted.
aio_read: called by io_submit(2) and other asynchronous I/O operations
+ read_iter: aio_read replacement, called by io_submit(2) and other
+ asynchronous I/O operations
+
write: called by write(2) and related system calls
aio_write: called by io_submit(2) and other asynchronous I/O operations
+ write_iter: aio_write replacement, called by io_submit(2) and other
+ asynchronous I/O operations
+
iterate: called when the VFS needs to read the directory contents
poll: called by the VFS when a process wants to check if there is
diff --git a/Documentation/kernel-per-CPU-kthreads.txt b/Documentation/kernel-per-CPU-kthreads.txt
index 32351bfabf20..827104fb9364 100644
--- a/Documentation/kernel-per-CPU-kthreads.txt
+++ b/Documentation/kernel-per-CPU-kthreads.txt
@@ -181,12 +181,17 @@ To reduce its OS jitter, do any of the following:
make sure that this is safe on your particular system.
d. It is not possible to entirely get rid of OS jitter
from vmstat_update() on CONFIG_SMP=y systems, but you
- can decrease its frequency by writing a large value to
- /proc/sys/vm/stat_interval. The default value is HZ,
- for an interval of one second. Of course, larger values
- will make your virtual-memory statistics update more
- slowly. Of course, you can also run your workload at
- a real-time priority, thus preempting vmstat_update().
+ can decrease its frequency by writing a large value
+ to /proc/sys/vm/stat_interval. The default value is
+ HZ, for an interval of one second. Of course, larger
+ values will make your virtual-memory statistics update
+ more slowly. Of course, you can also run your workload
+ at a real-time priority, thus preempting vmstat_update(),
+ but if your workload is CPU-bound, this is a bad idea.
+ However, there is an RFC patch from Christoph Lameter
+ (based on an earlier one from Gilad Ben-Yossef) that
+ reduces or even eliminates vmstat overhead for some
+ workloads at https://lkml.org/lkml/2013/9/4/379.
e. If running on high-end powerpc servers, build with
CONFIG_PPC_RTAS_DAEMON=n. This prevents the RTAS
daemon from running on each CPU every second or so.
diff --git a/Documentation/mic/mic_overview.txt b/Documentation/mic/mic_overview.txt
new file mode 100644
index 000000000000..c4424ed1b746
--- /dev/null
+++ b/Documentation/mic/mic_overview.txt
@@ -0,0 +1,49 @@
+An Intel MIC X100 device is a PCIe form factor add-in coprocessor
+card based on the Intel Many Integrated Core (MIC) architecture
+that runs a Linux OS. It is a PCIe endpoint in a platform and therefore
+implements the three required standard address spaces i.e. configuration,
+memory and I/O. The host OS loads a device driver as is typical for
+PCIe devices. The card itself runs a bootstrap after reset that
+transfers control to the card OS downloaded from the host driver.
+The card OS as shipped by Intel is a Linux kernel with modifications
+for the X100 devices.
+
+Since it is a PCIe card, it does not have the ability to host hardware
+devices for networking, storage and console. We provide these devices
+on X100 coprocessors thus enabling a self-bootable equivalent environment
+for applications. A key benefit of our solution is that it leverages
+the standard virtio framework for network, disk and console devices,
+though in our case the virtio framework is used across a PCIe bus.
+
+Here is a block diagram of the various components described above. The
+virtio backends are situated on the host rather than the card given better
+single threaded performance for the host compared to MIC, the ability of
+the host to initiate DMA's to/from the card using the MIC DMA engine and
+the fact that the virtio block storage backend can only be on the host.
+
+ |
+ +----------+ | +----------+
+ | Card OS | | | Host OS |
+ +----------+ | +----------+
+ |
++-------+ +--------+ +------+ | +---------+ +--------+ +--------+
+| Virtio| |Virtio | |Virtio| | |Virtio | |Virtio | |Virtio |
+| Net | |Console | |Block | | |Net | |Console | |Block |
+| Driver| |Driver | |Driver| | |backend | |backend | |backend |
++-------+ +--------+ +------+ | +---------+ +--------+ +--------+
+ | | | | | | |
+ | | | |User | | |
+ | | | |------|------------|---------|-------
+ +-------------------+ |Kernel +--------------------------+
+ | | | Virtio over PCIe IOCTLs |
+ | | +--------------------------+
+ +--------------+ | |
+ |Intel MIC | | +---------------+
+ |Card Driver | | |Intel MIC |
+ +--------------+ | |Host Driver |
+ | | +---------------+
+ | | |
+ +-------------------------------------------------------------+
+ | |
+ | PCIe Bus |
+ +-------------------------------------------------------------+
diff --git a/Documentation/mic/mpssd/.gitignore b/Documentation/mic/mpssd/.gitignore
new file mode 100644
index 000000000000..8b7c72f07c92
--- /dev/null
+++ b/Documentation/mic/mpssd/.gitignore
@@ -0,0 +1 @@
+mpssd
diff --git a/Documentation/mic/mpssd/Makefile b/Documentation/mic/mpssd/Makefile
new file mode 100644
index 000000000000..eb860a7d152e
--- /dev/null
+++ b/Documentation/mic/mpssd/Makefile
@@ -0,0 +1,19 @@
+#
+# Makefile - Intel MIC User Space Tools.
+# Copyright(c) 2013, Intel Corporation.
+#
+ifdef DEBUG
+CFLAGS += $(USERWARNFLAGS) -I. -g -Wall -DDEBUG=$(DEBUG)
+else
+CFLAGS += $(USERWARNFLAGS) -I. -g -Wall
+endif
+
+mpssd: mpssd.o sysfs.o
+ $(CC) $(CFLAGS) -o $@ $^ -lpthread
+
+install:
+ install mpssd /usr/sbin/mpssd
+ install micctrl /usr/sbin/micctrl
+
+clean:
+ rm -f mpssd *.o
diff --git a/Documentation/mic/mpssd/micctrl b/Documentation/mic/mpssd/micctrl
new file mode 100755
index 000000000000..8f2629b41c5f
--- /dev/null
+++ b/Documentation/mic/mpssd/micctrl
@@ -0,0 +1,173 @@
+#!/bin/bash
+# Intel MIC Platform Software Stack (MPSS)
+#
+# Copyright(c) 2013 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.
+#
+# 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.
+#
+# The full GNU General Public License is included in this distribution in
+# the file called "COPYING".
+#
+# Intel MIC User Space Tools.
+#
+# micctrl - Controls MIC boot/start/stop.
+#
+# chkconfig: 2345 95 05
+# description: start MPSS stack processing.
+#
+### BEGIN INIT INFO
+# Provides: micctrl
+### END INIT INFO
+
+# Source function library.
+. /etc/init.d/functions
+
+sysfs="/sys/class/mic"
+
+_status()
+{
+ f=$sysfs/$1
+ echo -e $1 state: "`cat $f/state`" shutdown_status: "`cat $f/shutdown_status`"
+}
+
+status()
+{
+ if [ "`echo $1 | head -c3`" == "mic" ]; then
+ _status $1
+ return $?
+ fi
+ for f in $sysfs/*
+ do
+ _status `basename $f`
+ RETVAL=$?
+ [ $RETVAL -ne 0 ] && return $RETVAL
+ done
+ return 0
+}
+
+_reset()
+{
+ f=$sysfs/$1
+ echo reset > $f/state
+}
+
+reset()
+{
+ if [ "`echo $1 | head -c3`" == "mic" ]; then
+ _reset $1
+ return $?
+ fi
+ for f in $sysfs/*
+ do
+ _reset `basename $f`
+ RETVAL=$?
+ [ $RETVAL -ne 0 ] && return $RETVAL
+ done
+ return 0
+}
+
+_boot()
+{
+ f=$sysfs/$1
+ echo "linux" > $f/bootmode
+ echo "mic/uos.img" > $f/firmware
+ echo "mic/$1.image" > $f/ramdisk
+ echo "boot" > $f/state
+}
+
+boot()
+{
+ if [ "`echo $1 | head -c3`" == "mic" ]; then
+ _boot $1
+ return $?
+ fi
+ for f in $sysfs/*
+ do
+ _boot `basename $f`
+ RETVAL=$?
+ [ $RETVAL -ne 0 ] && return $RETVAL
+ done
+ return 0
+}
+
+_shutdown()
+{
+ f=$sysfs/$1
+ echo shutdown > $f/state
+}
+
+shutdown()
+{
+ if [ "`echo $1 | head -c3`" == "mic" ]; then
+ _shutdown $1
+ return $?
+ fi
+ for f in $sysfs/*
+ do
+ _shutdown `basename $f`
+ RETVAL=$?
+ [ $RETVAL -ne 0 ] && return $RETVAL
+ done
+ return 0
+}
+
+_wait()
+{
+ f=$sysfs/$1
+ while [ "`cat $f/state`" != "offline" -a "`cat $f/state`" != "online" ]
+ do
+ sleep 1
+ echo -e "Waiting for $1 to go offline"
+ done
+}
+
+wait()
+{
+ if [ "`echo $1 | head -c3`" == "mic" ]; then
+ _wait $1
+ return $?
+ fi
+ # Wait for the cards to go offline
+ for f in $sysfs/*
+ do
+ _wait `basename $f`
+ RETVAL=$?
+ [ $RETVAL -ne 0 ] && return $RETVAL
+ done
+ return 0
+}
+
+if [ ! -d "$sysfs" ]; then
+ echo -e $"Module unloaded "
+ exit 3
+fi
+
+case $1 in
+ -s)
+ status $2
+ ;;
+ -r)
+ reset $2
+ ;;
+ -b)
+ boot $2
+ ;;
+ -S)
+ shutdown $2
+ ;;
+ -w)
+ wait $2
+ ;;
+ *)
+ echo $"Usage: $0 {-s (status) |-r (reset) |-b (boot) |-S (shutdown) |-w (wait)}"
+ exit 2
+esac
+
+exit $?
diff --git a/Documentation/mic/mpssd/mpss b/Documentation/mic/mpssd/mpss
new file mode 100755
index 000000000000..3136c68dad0b
--- /dev/null
+++ b/Documentation/mic/mpssd/mpss
@@ -0,0 +1,202 @@
+#!/bin/bash
+# Intel MIC Platform Software Stack (MPSS)
+#
+# Copyright(c) 2013 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.
+#
+# 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.
+#
+# The full GNU General Public License is included in this distribution in
+# the file called "COPYING".
+#
+# Intel MIC User Space Tools.
+#
+# mpss Start mpssd.
+#
+# chkconfig: 2345 95 05
+# description: start MPSS stack processing.
+#
+### BEGIN INIT INFO
+# Provides: mpss
+# Required-Start:
+# Required-Stop:
+# Short-Description: MPSS stack control
+# Description: MPSS stack control
+### END INIT INFO
+
+# Source function library.
+. /etc/init.d/functions
+
+exec=/usr/sbin/mpssd
+sysfs="/sys/class/mic"
+
+start()
+{
+ [ -x $exec ] || exit 5
+
+ if [ "`ps -e | awk '{print $4}' | grep mpssd | head -1`" = "mpssd" ]; then
+ echo -e $"MPSSD already running! "
+ success
+ echo
+ return 0
+ fi
+
+ echo -e $"Starting MPSS Stack"
+ echo -e $"Loading MIC_HOST Module"
+
+ # Ensure the driver is loaded
+ if [ ! -d "$sysfs" ]; then
+ modprobe mic_host
+ RETVAL=$?
+ if [ $RETVAL -ne 0 ]; then
+ failure
+ echo
+ return $RETVAL
+ fi
+ fi
+
+ # Start the daemon
+ echo -n $"Starting MPSSD "
+ $exec
+ RETVAL=$?
+ if [ $RETVAL -ne 0 ]; then
+ failure
+ echo
+ return $RETVAL
+ fi
+ success
+ echo
+
+ sleep 5
+
+ # Boot the cards
+ micctrl -b
+
+ # Wait till ping works
+ for f in $sysfs/*
+ do
+ count=100
+ ipaddr=`cat $f/cmdline`
+ ipaddr=${ipaddr#*address,}
+ ipaddr=`echo $ipaddr | cut -d, -f1 | cut -d\; -f1`
+ while [ $count -ge 0 ]
+ do
+ echo -e "Pinging "`basename $f`" "
+ ping -c 1 $ipaddr &> /dev/null
+ RETVAL=$?
+ if [ $RETVAL -eq 0 ]; then
+ success
+ break
+ fi
+ sleep 1
+ count=`expr $count - 1`
+ done
+ [ $RETVAL -ne 0 ] && failure || success
+ echo
+ done
+ return $RETVAL
+}
+
+stop()
+{
+ echo -e $"Shutting down MPSS Stack: "
+
+ # Bail out if module is unloaded
+ if [ ! -d "$sysfs" ]; then
+ echo -n $"Module unloaded "
+ success
+ echo
+ return 0
+ fi
+
+ # Shut down the cards.
+ micctrl -S
+
+ # Wait for the cards to go offline
+ for f in $sysfs/*
+ do
+ while [ "`cat $f/state`" != "offline" ]
+ do
+ sleep 1
+ echo -e "Waiting for "`basename $f`" to go offline"
+ done
+ done
+
+ # Display the status of the cards
+ micctrl -s
+
+ # Kill MPSSD now
+ echo -n $"Killing MPSSD"
+ killall -9 mpssd 2>/dev/null
+ RETVAL=$?
+ [ $RETVAL -ne 0 ] && failure || success
+ echo
+ return $RETVAL
+}
+
+restart()
+{
+ stop
+ sleep 5
+ start
+}
+
+status()
+{
+ micctrl -s
+ if [ "`ps -e | awk '{print $4}' | grep mpssd | head -n 1`" = "mpssd" ]; then
+ echo "mpssd is running"
+ else
+ echo "mpssd is stopped"
+ fi
+ return 0
+}
+
+unload()
+{
+ if [ ! -d "$sysfs" ]; then
+ echo -n $"No MIC_HOST Module: "
+ success
+ echo
+ return
+ fi
+
+ stop
+
+ sleep 5
+ echo -n $"Removing MIC_HOST Module: "
+ modprobe -r mic_host
+ RETVAL=$?
+ [ $RETVAL -ne 0 ] && failure || success
+ echo
+ return $RETVAL
+}
+
+case $1 in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ restart)
+ restart
+ ;;
+ status)
+ status
+ ;;
+ unload)
+ unload
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|restart|status|unload}"
+ exit 2
+esac
+
+exit $?
diff --git a/Documentation/mic/mpssd/mpssd.c b/Documentation/mic/mpssd/mpssd.c
new file mode 100644
index 000000000000..8064804cdac3
--- /dev/null
+++ b/Documentation/mic/mpssd/mpssd.c
@@ -0,0 +1,1701 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC User Space Tools.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <signal.h>
+#include <poll.h>
+#include <features.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <linux/virtio_ring.h>
+#include <linux/virtio_net.h>
+#include <linux/virtio_console.h>
+#include <linux/virtio_blk.h>
+#include <linux/version.h>
+#include "mpssd.h"
+#include <linux/mic_ioctl.h>
+#include <linux/mic_common.h>
+
+static void init_mic(struct mic_info *mic);
+
+static FILE *logfp;
+static struct mic_info mic_list;
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define min_t(type, x, y) ({ \
+ type __min1 = (x); \
+ type __min2 = (y); \
+ __min1 < __min2 ? __min1 : __min2; })
+
+/* align addr on a size boundary - adjust address up/down if needed */
+#define _ALIGN_DOWN(addr, size) ((addr)&(~((size)-1)))
+#define _ALIGN_UP(addr, size) _ALIGN_DOWN(addr + size - 1, size)
+
+/* align addr on a size boundary - adjust address up if needed */
+#define _ALIGN(addr, size) _ALIGN_UP(addr, size)
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE)
+
+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
+
+#define GSO_ENABLED 1
+#define MAX_GSO_SIZE (64 * 1024)
+#define ETH_H_LEN 14
+#define MAX_NET_PKT_SIZE (_ALIGN_UP(MAX_GSO_SIZE + ETH_H_LEN, 64))
+#define MIC_DEVICE_PAGE_END 0x1000
+
+#ifndef VIRTIO_NET_HDR_F_DATA_VALID
+#define VIRTIO_NET_HDR_F_DATA_VALID 2 /* Csum is valid */
+#endif
+
+static struct {
+ struct mic_device_desc dd;
+ struct mic_vqconfig vqconfig[2];
+ __u32 host_features, guest_acknowledgements;
+ struct virtio_console_config cons_config;
+} virtcons_dev_page = {
+ .dd = {
+ .type = VIRTIO_ID_CONSOLE,
+ .num_vq = ARRAY_SIZE(virtcons_dev_page.vqconfig),
+ .feature_len = sizeof(virtcons_dev_page.host_features),
+ .config_len = sizeof(virtcons_dev_page.cons_config),
+ },
+ .vqconfig[0] = {
+ .num = htole16(MIC_VRING_ENTRIES),
+ },
+ .vqconfig[1] = {
+ .num = htole16(MIC_VRING_ENTRIES),
+ },
+};
+
+static struct {
+ struct mic_device_desc dd;
+ struct mic_vqconfig vqconfig[2];
+ __u32 host_features, guest_acknowledgements;
+ struct virtio_net_config net_config;
+} virtnet_dev_page = {
+ .dd = {
+ .type = VIRTIO_ID_NET,
+ .num_vq = ARRAY_SIZE(virtnet_dev_page.vqconfig),
+ .feature_len = sizeof(virtnet_dev_page.host_features),
+ .config_len = sizeof(virtnet_dev_page.net_config),
+ },
+ .vqconfig[0] = {
+ .num = htole16(MIC_VRING_ENTRIES),
+ },
+ .vqconfig[1] = {
+ .num = htole16(MIC_VRING_ENTRIES),
+ },
+#if GSO_ENABLED
+ .host_features = htole32(
+ 1 << VIRTIO_NET_F_CSUM |
+ 1 << VIRTIO_NET_F_GSO |
+ 1 << VIRTIO_NET_F_GUEST_TSO4 |
+ 1 << VIRTIO_NET_F_GUEST_TSO6 |
+ 1 << VIRTIO_NET_F_GUEST_ECN |
+ 1 << VIRTIO_NET_F_GUEST_UFO),
+#else
+ .host_features = 0,
+#endif
+};
+
+static const char *mic_config_dir = "/etc/sysconfig/mic";
+static const char *virtblk_backend = "VIRTBLK_BACKEND";
+static struct {
+ struct mic_device_desc dd;
+ struct mic_vqconfig vqconfig[1];
+ __u32 host_features, guest_acknowledgements;
+ struct virtio_blk_config blk_config;
+} virtblk_dev_page = {
+ .dd = {
+ .type = VIRTIO_ID_BLOCK,
+ .num_vq = ARRAY_SIZE(virtblk_dev_page.vqconfig),
+ .feature_len = sizeof(virtblk_dev_page.host_features),
+ .config_len = sizeof(virtblk_dev_page.blk_config),
+ },
+ .vqconfig[0] = {
+ .num = htole16(MIC_VRING_ENTRIES),
+ },
+ .host_features =
+ htole32(1<<VIRTIO_BLK_F_SEG_MAX),
+ .blk_config = {
+ .seg_max = htole32(MIC_VRING_ENTRIES - 2),
+ .capacity = htole64(0),
+ }
+};
+
+static char *myname;
+
+static int
+tap_configure(struct mic_info *mic, char *dev)
+{
+ pid_t pid;
+ char *ifargv[7];
+ char ipaddr[IFNAMSIZ];
+ int ret = 0;
+
+ pid = fork();
+ if (pid == 0) {
+ ifargv[0] = "ip";
+ ifargv[1] = "link";
+ ifargv[2] = "set";
+ ifargv[3] = dev;
+ ifargv[4] = "up";
+ ifargv[5] = NULL;
+ mpsslog("Configuring %s\n", dev);
+ ret = execvp("ip", ifargv);
+ if (ret < 0) {
+ mpsslog("%s execvp failed errno %s\n",
+ mic->name, strerror(errno));
+ return ret;
+ }
+ }
+ if (pid < 0) {
+ mpsslog("%s fork failed errno %s\n",
+ mic->name, strerror(errno));
+ return ret;
+ }
+
+ ret = waitpid(pid, NULL, 0);
+ if (ret < 0) {
+ mpsslog("%s waitpid failed errno %s\n",
+ mic->name, strerror(errno));
+ return ret;
+ }
+
+ snprintf(ipaddr, IFNAMSIZ, "172.31.%d.254/24", mic->id);
+
+ pid = fork();
+ if (pid == 0) {
+ ifargv[0] = "ip";
+ ifargv[1] = "addr";
+ ifargv[2] = "add";
+ ifargv[3] = ipaddr;
+ ifargv[4] = "dev";
+ ifargv[5] = dev;
+ ifargv[6] = NULL;
+ mpsslog("Configuring %s ipaddr %s\n", dev, ipaddr);
+ ret = execvp("ip", ifargv);
+ if (ret < 0) {
+ mpsslog("%s execvp failed errno %s\n",
+ mic->name, strerror(errno));
+ return ret;
+ }
+ }
+ if (pid < 0) {
+ mpsslog("%s fork failed errno %s\n",
+ mic->name, strerror(errno));
+ return ret;
+ }
+
+ ret = waitpid(pid, NULL, 0);
+ if (ret < 0) {
+ mpsslog("%s waitpid failed errno %s\n",
+ mic->name, strerror(errno));
+ return ret;
+ }
+ mpsslog("MIC name %s %s %d DONE!\n",
+ mic->name, __func__, __LINE__);
+ return 0;
+}
+
+static int tun_alloc(struct mic_info *mic, char *dev)
+{
+ struct ifreq ifr;
+ int fd, err;
+#if GSO_ENABLED
+ unsigned offload;
+#endif
+ fd = open("/dev/net/tun", O_RDWR);
+ if (fd < 0) {
+ mpsslog("Could not open /dev/net/tun %s\n", strerror(errno));
+ goto done;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
+ if (*dev)
+ strncpy(ifr.ifr_name, dev, IFNAMSIZ);
+
+ err = ioctl(fd, TUNSETIFF, (void *) &ifr);
+ if (err < 0) {
+ mpsslog("%s %s %d TUNSETIFF failed %s\n",
+ mic->name, __func__, __LINE__, strerror(errno));
+ close(fd);
+ return err;
+ }
+#if GSO_ENABLED
+ offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |
+ TUN_F_TSO_ECN | TUN_F_UFO;
+
+ err = ioctl(fd, TUNSETOFFLOAD, offload);
+ if (err < 0) {
+ mpsslog("%s %s %d TUNSETOFFLOAD failed %s\n",
+ mic->name, __func__, __LINE__, strerror(errno));
+ close(fd);
+ return err;
+ }
+#endif
+ strcpy(dev, ifr.ifr_name);
+ mpsslog("Created TAP %s\n", dev);
+done:
+ return fd;
+}
+
+#define NET_FD_VIRTIO_NET 0
+#define NET_FD_TUN 1
+#define MAX_NET_FD 2
+
+static void set_dp(struct mic_info *mic, int type, void *dp)
+{
+ switch (type) {
+ case VIRTIO_ID_CONSOLE:
+ mic->mic_console.console_dp = dp;
+ return;
+ case VIRTIO_ID_NET:
+ mic->mic_net.net_dp = dp;
+ return;
+ case VIRTIO_ID_BLOCK:
+ mic->mic_virtblk.block_dp = dp;
+ return;
+ }
+ mpsslog("%s %s %d not found\n", mic->name, __func__, type);
+ assert(0);
+}
+
+static void *get_dp(struct mic_info *mic, int type)
+{
+ switch (type) {
+ case VIRTIO_ID_CONSOLE:
+ return mic->mic_console.console_dp;
+ case VIRTIO_ID_NET:
+ return mic->mic_net.net_dp;
+ case VIRTIO_ID_BLOCK:
+ return mic->mic_virtblk.block_dp;
+ }
+ mpsslog("%s %s %d not found\n", mic->name, __func__, type);
+ assert(0);
+ return NULL;
+}
+
+static struct mic_device_desc *get_device_desc(struct mic_info *mic, int type)
+{
+ struct mic_device_desc *d;
+ int i;
+ void *dp = get_dp(mic, type);
+
+ for (i = mic_aligned_size(struct mic_bootparam); i < PAGE_SIZE;
+ i += mic_total_desc_size(d)) {
+ d = dp + i;
+
+ /* End of list */
+ if (d->type == 0)
+ break;
+
+ if (d->type == -1)
+ continue;
+
+ mpsslog("%s %s d-> type %d d %p\n",
+ mic->name, __func__, d->type, d);
+
+ if (d->type == (__u8)type)
+ return d;
+ }
+ mpsslog("%s %s %d not found\n", mic->name, __func__, type);
+ assert(0);
+ return NULL;
+}
+
+/* See comments in vhost.c for explanation of next_desc() */
+static unsigned next_desc(struct vring_desc *desc)
+{
+ unsigned int next;
+
+ if (!(le16toh(desc->flags) & VRING_DESC_F_NEXT))
+ return -1U;
+ next = le16toh(desc->next);
+ return next;
+}
+
+/* Sum up all the IOVEC length */
+static ssize_t
+sum_iovec_len(struct mic_copy_desc *copy)
+{
+ ssize_t sum = 0;
+ int i;
+
+ for (i = 0; i < copy->iovcnt; i++)
+ sum += copy->iov[i].iov_len;
+ return sum;
+}
+
+static inline void verify_out_len(struct mic_info *mic,
+ struct mic_copy_desc *copy)
+{
+ if (copy->out_len != sum_iovec_len(copy)) {
+ mpsslog("%s %s %d BUG copy->out_len 0x%x len 0x%x\n",
+ mic->name, __func__, __LINE__,
+ copy->out_len, sum_iovec_len(copy));
+ assert(copy->out_len == sum_iovec_len(copy));
+ }
+}
+
+/* Display an iovec */
+static void
+disp_iovec(struct mic_info *mic, struct mic_copy_desc *copy,
+ const char *s, int line)
+{
+ int i;
+
+ for (i = 0; i < copy->iovcnt; i++)
+ mpsslog("%s %s %d copy->iov[%d] addr %p len 0x%lx\n",
+ mic->name, s, line, i,
+ copy->iov[i].iov_base, copy->iov[i].iov_len);
+}
+
+static inline __u16 read_avail_idx(struct mic_vring *vr)
+{
+ return ACCESS_ONCE(vr->info->avail_idx);
+}
+
+static inline void txrx_prepare(int type, bool tx, struct mic_vring *vr,
+ struct mic_copy_desc *copy, ssize_t len)
+{
+ copy->vr_idx = tx ? 0 : 1;
+ copy->update_used = true;
+ if (type == VIRTIO_ID_NET)
+ copy->iov[1].iov_len = len - sizeof(struct virtio_net_hdr);
+ else
+ copy->iov[0].iov_len = len;
+}
+
+/* Central API which triggers the copies */
+static int
+mic_virtio_copy(struct mic_info *mic, int fd,
+ struct mic_vring *vr, struct mic_copy_desc *copy)
+{
+ int ret;
+
+ ret = ioctl(fd, MIC_VIRTIO_COPY_DESC, copy);
+ if (ret) {
+ mpsslog("%s %s %d errno %s ret %d\n",
+ mic->name, __func__, __LINE__,
+ strerror(errno), ret);
+ }
+ return ret;
+}
+
+/*
+ * This initialization routine requires at least one
+ * vring i.e. vr0. vr1 is optional.
+ */
+static void *
+init_vr(struct mic_info *mic, int fd, int type,
+ struct mic_vring *vr0, struct mic_vring *vr1, int num_vq)
+{
+ int vr_size;
+ char *va;
+
+ vr_size = PAGE_ALIGN(vring_size(MIC_VRING_ENTRIES,
+ MIC_VIRTIO_RING_ALIGN) + sizeof(struct _mic_vring_info));
+ va = mmap(NULL, MIC_DEVICE_PAGE_END + vr_size * num_vq,
+ PROT_READ, MAP_SHARED, fd, 0);
+ if (MAP_FAILED == va) {
+ mpsslog("%s %s %d mmap failed errno %s\n",
+ mic->name, __func__, __LINE__,
+ strerror(errno));
+ goto done;
+ }
+ set_dp(mic, type, va);
+ vr0->va = (struct mic_vring *)&va[MIC_DEVICE_PAGE_END];
+ vr0->info = vr0->va +
+ vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN);
+ vring_init(&vr0->vr,
+ MIC_VRING_ENTRIES, vr0->va, MIC_VIRTIO_RING_ALIGN);
+ mpsslog("%s %s vr0 %p vr0->info %p vr_size 0x%x vring 0x%x ",
+ __func__, mic->name, vr0->va, vr0->info, vr_size,
+ vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
+ mpsslog("magic 0x%x expected 0x%x\n",
+ vr0->info->magic, MIC_MAGIC + type);
+ assert(vr0->info->magic == MIC_MAGIC + type);
+ if (vr1) {
+ vr1->va = (struct mic_vring *)
+ &va[MIC_DEVICE_PAGE_END + vr_size];
+ vr1->info = vr1->va + vring_size(MIC_VRING_ENTRIES,
+ MIC_VIRTIO_RING_ALIGN);
+ vring_init(&vr1->vr,
+ MIC_VRING_ENTRIES, vr1->va, MIC_VIRTIO_RING_ALIGN);
+ mpsslog("%s %s vr1 %p vr1->info %p vr_size 0x%x vring 0x%x ",
+ __func__, mic->name, vr1->va, vr1->info, vr_size,
+ vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
+ mpsslog("magic 0x%x expected 0x%x\n",
+ vr1->info->magic, MIC_MAGIC + type + 1);
+ assert(vr1->info->magic == MIC_MAGIC + type + 1);
+ }
+done:
+ return va;
+}
+
+static void
+wait_for_card_driver(struct mic_info *mic, int fd, int type)
+{
+ struct pollfd pollfd;
+ int err;
+ struct mic_device_desc *desc = get_device_desc(mic, type);
+
+ pollfd.fd = fd;
+ mpsslog("%s %s Waiting .... desc-> type %d status 0x%x\n",
+ mic->name, __func__, type, desc->status);
+ while (1) {
+ pollfd.events = POLLIN;
+ pollfd.revents = 0;
+ err = poll(&pollfd, 1, -1);
+ if (err < 0) {
+ mpsslog("%s %s poll failed %s\n",
+ mic->name, __func__, strerror(errno));
+ continue;
+ }
+
+ if (pollfd.revents) {
+ mpsslog("%s %s Waiting... desc-> type %d status 0x%x\n",
+ mic->name, __func__, type, desc->status);
+ if (desc->status & VIRTIO_CONFIG_S_DRIVER_OK) {
+ mpsslog("%s %s poll.revents %d\n",
+ mic->name, __func__, pollfd.revents);
+ mpsslog("%s %s desc-> type %d status 0x%x\n",
+ mic->name, __func__, type,
+ desc->status);
+ break;
+ }
+ }
+ }
+}
+
+/* Spin till we have some descriptors */
+static void
+spin_for_descriptors(struct mic_info *mic, struct mic_vring *vr)
+{
+ __u16 avail_idx = read_avail_idx(vr);
+
+ while (avail_idx == le16toh(ACCESS_ONCE(vr->vr.avail->idx))) {
+#ifdef DEBUG
+ mpsslog("%s %s waiting for desc avail %d info_avail %d\n",
+ mic->name, __func__,
+ le16toh(vr->vr.avail->idx), vr->info->avail_idx);
+#endif
+ sched_yield();
+ }
+}
+
+static void *
+virtio_net(void *arg)
+{
+ static __u8 vnet_hdr[2][sizeof(struct virtio_net_hdr)];
+ static __u8 vnet_buf[2][MAX_NET_PKT_SIZE] __aligned(64);
+ struct iovec vnet_iov[2][2] = {
+ { { .iov_base = vnet_hdr[0], .iov_len = sizeof(vnet_hdr[0]) },
+ { .iov_base = vnet_buf[0], .iov_len = sizeof(vnet_buf[0]) } },
+ { { .iov_base = vnet_hdr[1], .iov_len = sizeof(vnet_hdr[1]) },
+ { .iov_base = vnet_buf[1], .iov_len = sizeof(vnet_buf[1]) } },
+ };
+ struct iovec *iov0 = vnet_iov[0], *iov1 = vnet_iov[1];
+ struct mic_info *mic = (struct mic_info *)arg;
+ char if_name[IFNAMSIZ];
+ struct pollfd net_poll[MAX_NET_FD];
+ struct mic_vring tx_vr, rx_vr;
+ struct mic_copy_desc copy;
+ struct mic_device_desc *desc;
+ int err;
+
+ snprintf(if_name, IFNAMSIZ, "mic%d", mic->id);
+ mic->mic_net.tap_fd = tun_alloc(mic, if_name);
+ if (mic->mic_net.tap_fd < 0)
+ goto done;
+
+ if (tap_configure(mic, if_name))
+ goto done;
+ mpsslog("MIC name %s id %d\n", mic->name, mic->id);
+
+ net_poll[NET_FD_VIRTIO_NET].fd = mic->mic_net.virtio_net_fd;
+ net_poll[NET_FD_VIRTIO_NET].events = POLLIN;
+ net_poll[NET_FD_TUN].fd = mic->mic_net.tap_fd;
+ net_poll[NET_FD_TUN].events = POLLIN;
+
+ if (MAP_FAILED == init_vr(mic, mic->mic_net.virtio_net_fd,
+ VIRTIO_ID_NET, &tx_vr, &rx_vr,
+ virtnet_dev_page.dd.num_vq)) {
+ mpsslog("%s init_vr failed %s\n",
+ mic->name, strerror(errno));
+ goto done;
+ }
+
+ copy.iovcnt = 2;
+ desc = get_device_desc(mic, VIRTIO_ID_NET);
+
+ while (1) {
+ ssize_t len;
+
+ net_poll[NET_FD_VIRTIO_NET].revents = 0;
+ net_poll[NET_FD_TUN].revents = 0;
+
+ /* Start polling for data from tap and virtio net */
+ err = poll(net_poll, 2, -1);
+ if (err < 0) {
+ mpsslog("%s poll failed %s\n",
+ __func__, strerror(errno));
+ continue;
+ }
+ if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK))
+ wait_for_card_driver(mic, mic->mic_net.virtio_net_fd,
+ VIRTIO_ID_NET);
+ /*
+ * Check if there is data to be read from TUN and write to
+ * virtio net fd if there is.
+ */
+ if (net_poll[NET_FD_TUN].revents & POLLIN) {
+ copy.iov = iov0;
+ len = readv(net_poll[NET_FD_TUN].fd,
+ copy.iov, copy.iovcnt);
+ if (len > 0) {
+ struct virtio_net_hdr *hdr
+ = (struct virtio_net_hdr *) vnet_hdr[0];
+
+ /* Disable checksums on the card since we are on
+ a reliable PCIe link */
+ hdr->flags |= VIRTIO_NET_HDR_F_DATA_VALID;
+#ifdef DEBUG
+ mpsslog("%s %s %d hdr->flags 0x%x ", mic->name,
+ __func__, __LINE__, hdr->flags);
+ mpsslog("copy.out_len %d hdr->gso_type 0x%x\n",
+ copy.out_len, hdr->gso_type);
+#endif
+#ifdef DEBUG
+ disp_iovec(mic, copy, __func__, __LINE__);
+ mpsslog("%s %s %d read from tap 0x%lx\n",
+ mic->name, __func__, __LINE__,
+ len);
+#endif
+ spin_for_descriptors(mic, &tx_vr);
+ txrx_prepare(VIRTIO_ID_NET, 1, &tx_vr, &copy,
+ len);
+
+ err = mic_virtio_copy(mic,
+ mic->mic_net.virtio_net_fd, &tx_vr,
+ &copy);
+ if (err < 0) {
+ mpsslog("%s %s %d mic_virtio_copy %s\n",
+ mic->name, __func__, __LINE__,
+ strerror(errno));
+ }
+ if (!err)
+ verify_out_len(mic, &copy);
+#ifdef DEBUG
+ disp_iovec(mic, copy, __func__, __LINE__);
+ mpsslog("%s %s %d wrote to net 0x%lx\n",
+ mic->name, __func__, __LINE__,
+ sum_iovec_len(&copy));
+#endif
+ /* Reinitialize IOV for next run */
+ iov0[1].iov_len = MAX_NET_PKT_SIZE;
+ } else if (len < 0) {
+ disp_iovec(mic, &copy, __func__, __LINE__);
+ mpsslog("%s %s %d read failed %s ", mic->name,
+ __func__, __LINE__, strerror(errno));
+ mpsslog("cnt %d sum %d\n",
+ copy.iovcnt, sum_iovec_len(&copy));
+ }
+ }
+
+ /*
+ * Check if there is data to be read from virtio net and
+ * write to TUN if there is.
+ */
+ if (net_poll[NET_FD_VIRTIO_NET].revents & POLLIN) {
+ while (rx_vr.info->avail_idx !=
+ le16toh(rx_vr.vr.avail->idx)) {
+ copy.iov = iov1;
+ txrx_prepare(VIRTIO_ID_NET, 0, &rx_vr, &copy,
+ MAX_NET_PKT_SIZE
+ + sizeof(struct virtio_net_hdr));
+
+ err = mic_virtio_copy(mic,
+ mic->mic_net.virtio_net_fd, &rx_vr,
+ &copy);
+ if (!err) {
+#ifdef DEBUG
+ struct virtio_net_hdr *hdr
+ = (struct virtio_net_hdr *)
+ vnet_hdr[1];
+
+ mpsslog("%s %s %d hdr->flags 0x%x, ",
+ mic->name, __func__, __LINE__,
+ hdr->flags);
+ mpsslog("out_len %d gso_type 0x%x\n",
+ copy.out_len,
+ hdr->gso_type);
+#endif
+ /* Set the correct output iov_len */
+ iov1[1].iov_len = copy.out_len -
+ sizeof(struct virtio_net_hdr);
+ verify_out_len(mic, &copy);
+#ifdef DEBUG
+ disp_iovec(mic, copy, __func__,
+ __LINE__);
+ mpsslog("%s %s %d ",
+ mic->name, __func__, __LINE__);
+ mpsslog("read from net 0x%lx\n",
+ sum_iovec_len(copy));
+#endif
+ len = writev(net_poll[NET_FD_TUN].fd,
+ copy.iov, copy.iovcnt);
+ if (len != sum_iovec_len(&copy)) {
+ mpsslog("Tun write failed %s ",
+ strerror(errno));
+ mpsslog("len 0x%x ", len);
+ mpsslog("read_len 0x%x\n",
+ sum_iovec_len(&copy));
+ } else {
+#ifdef DEBUG
+ disp_iovec(mic, &copy, __func__,
+ __LINE__);
+ mpsslog("%s %s %d ",
+ mic->name, __func__,
+ __LINE__);
+ mpsslog("wrote to tap 0x%lx\n",
+ len);
+#endif
+ }
+ } else {
+ mpsslog("%s %s %d mic_virtio_copy %s\n",
+ mic->name, __func__, __LINE__,
+ strerror(errno));
+ break;
+ }
+ }
+ }
+ if (net_poll[NET_FD_VIRTIO_NET].revents & POLLERR)
+ mpsslog("%s: %s: POLLERR\n", __func__, mic->name);
+ }
+done:
+ pthread_exit(NULL);
+}
+
+/* virtio_console */
+#define VIRTIO_CONSOLE_FD 0
+#define MONITOR_FD (VIRTIO_CONSOLE_FD + 1)
+#define MAX_CONSOLE_FD (MONITOR_FD + 1) /* must be the last one + 1 */
+#define MAX_BUFFER_SIZE PAGE_SIZE
+
+static void *
+virtio_console(void *arg)
+{
+ static __u8 vcons_buf[2][PAGE_SIZE];
+ struct iovec vcons_iov[2] = {
+ { .iov_base = vcons_buf[0], .iov_len = sizeof(vcons_buf[0]) },
+ { .iov_base = vcons_buf[1], .iov_len = sizeof(vcons_buf[1]) },
+ };
+ struct iovec *iov0 = &vcons_iov[0], *iov1 = &vcons_iov[1];
+ struct mic_info *mic = (struct mic_info *)arg;
+ int err;
+ struct pollfd console_poll[MAX_CONSOLE_FD];
+ int pty_fd;
+ char *pts_name;
+ ssize_t len;
+ struct mic_vring tx_vr, rx_vr;
+ struct mic_copy_desc copy;
+ struct mic_device_desc *desc;
+
+ pty_fd = posix_openpt(O_RDWR);
+ if (pty_fd < 0) {
+ mpsslog("can't open a pseudoterminal master device: %s\n",
+ strerror(errno));
+ goto _return;
+ }
+ pts_name = ptsname(pty_fd);
+ if (pts_name == NULL) {
+ mpsslog("can't get pts name\n");
+ goto _close_pty;
+ }
+ printf("%s console message goes to %s\n", mic->name, pts_name);
+ mpsslog("%s console message goes to %s\n", mic->name, pts_name);
+ err = grantpt(pty_fd);
+ if (err < 0) {
+ mpsslog("can't grant access: %s %s\n",
+ pts_name, strerror(errno));
+ goto _close_pty;
+ }
+ err = unlockpt(pty_fd);
+ if (err < 0) {
+ mpsslog("can't unlock a pseudoterminal: %s %s\n",
+ pts_name, strerror(errno));
+ goto _close_pty;
+ }
+ console_poll[MONITOR_FD].fd = pty_fd;
+ console_poll[MONITOR_FD].events = POLLIN;
+
+ console_poll[VIRTIO_CONSOLE_FD].fd = mic->mic_console.virtio_console_fd;
+ console_poll[VIRTIO_CONSOLE_FD].events = POLLIN;
+
+ if (MAP_FAILED == init_vr(mic, mic->mic_console.virtio_console_fd,
+ VIRTIO_ID_CONSOLE, &tx_vr, &rx_vr,
+ virtcons_dev_page.dd.num_vq)) {
+ mpsslog("%s init_vr failed %s\n",
+ mic->name, strerror(errno));
+ goto _close_pty;
+ }
+
+ copy.iovcnt = 1;
+ desc = get_device_desc(mic, VIRTIO_ID_CONSOLE);
+
+ for (;;) {
+ console_poll[MONITOR_FD].revents = 0;
+ console_poll[VIRTIO_CONSOLE_FD].revents = 0;
+ err = poll(console_poll, MAX_CONSOLE_FD, -1);
+ if (err < 0) {
+ mpsslog("%s %d: poll failed: %s\n", __func__, __LINE__,
+ strerror(errno));
+ continue;
+ }
+ if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK))
+ wait_for_card_driver(mic,
+ mic->mic_console.virtio_console_fd,
+ VIRTIO_ID_CONSOLE);
+
+ if (console_poll[MONITOR_FD].revents & POLLIN) {
+ copy.iov = iov0;
+ len = readv(pty_fd, copy.iov, copy.iovcnt);
+ if (len > 0) {
+#ifdef DEBUG
+ disp_iovec(mic, copy, __func__, __LINE__);
+ mpsslog("%s %s %d read from tap 0x%lx\n",
+ mic->name, __func__, __LINE__,
+ len);
+#endif
+ spin_for_descriptors(mic, &tx_vr);
+ txrx_prepare(VIRTIO_ID_CONSOLE, 1, &tx_vr,
+ &copy, len);
+
+ err = mic_virtio_copy(mic,
+ mic->mic_console.virtio_console_fd,
+ &tx_vr, &copy);
+ if (err < 0) {
+ mpsslog("%s %s %d mic_virtio_copy %s\n",
+ mic->name, __func__, __LINE__,
+ strerror(errno));
+ }
+ if (!err)
+ verify_out_len(mic, &copy);
+#ifdef DEBUG
+ disp_iovec(mic, copy, __func__, __LINE__);
+ mpsslog("%s %s %d wrote to net 0x%lx\n",
+ mic->name, __func__, __LINE__,
+ sum_iovec_len(copy));
+#endif
+ /* Reinitialize IOV for next run */
+ iov0->iov_len = PAGE_SIZE;
+ } else if (len < 0) {
+ disp_iovec(mic, &copy, __func__, __LINE__);
+ mpsslog("%s %s %d read failed %s ",
+ mic->name, __func__, __LINE__,
+ strerror(errno));
+ mpsslog("cnt %d sum %d\n",
+ copy.iovcnt, sum_iovec_len(&copy));
+ }
+ }
+
+ if (console_poll[VIRTIO_CONSOLE_FD].revents & POLLIN) {
+ while (rx_vr.info->avail_idx !=
+ le16toh(rx_vr.vr.avail->idx)) {
+ copy.iov = iov1;
+ txrx_prepare(VIRTIO_ID_CONSOLE, 0, &rx_vr,
+ &copy, PAGE_SIZE);
+
+ err = mic_virtio_copy(mic,
+ mic->mic_console.virtio_console_fd,
+ &rx_vr, &copy);
+ if (!err) {
+ /* Set the correct output iov_len */
+ iov1->iov_len = copy.out_len;
+ verify_out_len(mic, &copy);
+#ifdef DEBUG
+ disp_iovec(mic, copy, __func__,
+ __LINE__);
+ mpsslog("%s %s %d ",
+ mic->name, __func__, __LINE__);
+ mpsslog("read from net 0x%lx\n",
+ sum_iovec_len(copy));
+#endif
+ len = writev(pty_fd,
+ copy.iov, copy.iovcnt);
+ if (len != sum_iovec_len(&copy)) {
+ mpsslog("Tun write failed %s ",
+ strerror(errno));
+ mpsslog("len 0x%x ", len);
+ mpsslog("read_len 0x%x\n",
+ sum_iovec_len(&copy));
+ } else {
+#ifdef DEBUG
+ disp_iovec(mic, copy, __func__,
+ __LINE__);
+ mpsslog("%s %s %d ",
+ mic->name, __func__,
+ __LINE__);
+ mpsslog("wrote to tap 0x%lx\n",
+ len);
+#endif
+ }
+ } else {
+ mpsslog("%s %s %d mic_virtio_copy %s\n",
+ mic->name, __func__, __LINE__,
+ strerror(errno));
+ break;
+ }
+ }
+ }
+ if (console_poll[NET_FD_VIRTIO_NET].revents & POLLERR)
+ mpsslog("%s: %s: POLLERR\n", __func__, mic->name);
+ }
+_close_pty:
+ close(pty_fd);
+_return:
+ pthread_exit(NULL);
+}
+
+static void
+add_virtio_device(struct mic_info *mic, struct mic_device_desc *dd)
+{
+ char path[PATH_MAX];
+ int fd, err;
+
+ snprintf(path, PATH_MAX, "/dev/mic%d", mic->id);
+ fd = open(path, O_RDWR);
+ if (fd < 0) {
+ mpsslog("Could not open %s %s\n", path, strerror(errno));
+ return;
+ }
+
+ err = ioctl(fd, MIC_VIRTIO_ADD_DEVICE, dd);
+ if (err < 0) {
+ mpsslog("Could not add %d %s\n", dd->type, strerror(errno));
+ close(fd);
+ return;
+ }
+ switch (dd->type) {
+ case VIRTIO_ID_NET:
+ mic->mic_net.virtio_net_fd = fd;
+ mpsslog("Added VIRTIO_ID_NET for %s\n", mic->name);
+ break;
+ case VIRTIO_ID_CONSOLE:
+ mic->mic_console.virtio_console_fd = fd;
+ mpsslog("Added VIRTIO_ID_CONSOLE for %s\n", mic->name);
+ break;
+ case VIRTIO_ID_BLOCK:
+ mic->mic_virtblk.virtio_block_fd = fd;
+ mpsslog("Added VIRTIO_ID_BLOCK for %s\n", mic->name);
+ break;
+ }
+}
+
+static bool
+set_backend_file(struct mic_info *mic)
+{
+ FILE *config;
+ char buff[PATH_MAX], *line, *evv, *p;
+
+ snprintf(buff, PATH_MAX, "%s/mpssd%03d.conf", mic_config_dir, mic->id);
+ config = fopen(buff, "r");
+ if (config == NULL)
+ return false;
+ do { /* look for "virtblk_backend=XXXX" */
+ line = fgets(buff, PATH_MAX, config);
+ if (line == NULL)
+ break;
+ if (*line == '#')
+ continue;
+ p = strchr(line, '\n');
+ if (p)
+ *p = '\0';
+ } while (strncmp(line, virtblk_backend, strlen(virtblk_backend)) != 0);
+ fclose(config);
+ if (line == NULL)
+ return false;
+ evv = strchr(line, '=');
+ if (evv == NULL)
+ return false;
+ mic->mic_virtblk.backend_file = malloc(strlen(evv) + 1);
+ if (mic->mic_virtblk.backend_file == NULL) {
+ mpsslog("can't allocate memory\n", mic->name, mic->id);
+ return false;
+ }
+ strcpy(mic->mic_virtblk.backend_file, evv + 1);
+ return true;
+}
+
+#define SECTOR_SIZE 512
+static bool
+set_backend_size(struct mic_info *mic)
+{
+ mic->mic_virtblk.backend_size = lseek(mic->mic_virtblk.backend, 0,
+ SEEK_END);
+ if (mic->mic_virtblk.backend_size < 0) {
+ mpsslog("%s: can't seek: %s\n",
+ mic->name, mic->mic_virtblk.backend_file);
+ return false;
+ }
+ virtblk_dev_page.blk_config.capacity =
+ mic->mic_virtblk.backend_size / SECTOR_SIZE;
+ if ((mic->mic_virtblk.backend_size % SECTOR_SIZE) != 0)
+ virtblk_dev_page.blk_config.capacity++;
+
+ virtblk_dev_page.blk_config.capacity =
+ htole64(virtblk_dev_page.blk_config.capacity);
+
+ return true;
+}
+
+static bool
+open_backend(struct mic_info *mic)
+{
+ if (!set_backend_file(mic))
+ goto _error_exit;
+ mic->mic_virtblk.backend = open(mic->mic_virtblk.backend_file, O_RDWR);
+ if (mic->mic_virtblk.backend < 0) {
+ mpsslog("%s: can't open: %s\n", mic->name,
+ mic->mic_virtblk.backend_file);
+ goto _error_free;
+ }
+ if (!set_backend_size(mic))
+ goto _error_close;
+ mic->mic_virtblk.backend_addr = mmap(NULL,
+ mic->mic_virtblk.backend_size,
+ PROT_READ|PROT_WRITE, MAP_SHARED,
+ mic->mic_virtblk.backend, 0L);
+ if (mic->mic_virtblk.backend_addr == MAP_FAILED) {
+ mpsslog("%s: can't map: %s %s\n",
+ mic->name, mic->mic_virtblk.backend_file,
+ strerror(errno));
+ goto _error_close;
+ }
+ return true;
+
+ _error_close:
+ close(mic->mic_virtblk.backend);
+ _error_free:
+ free(mic->mic_virtblk.backend_file);
+ _error_exit:
+ return false;
+}
+
+static void
+close_backend(struct mic_info *mic)
+{
+ munmap(mic->mic_virtblk.backend_addr, mic->mic_virtblk.backend_size);
+ close(mic->mic_virtblk.backend);
+ free(mic->mic_virtblk.backend_file);
+}
+
+static bool
+start_virtblk(struct mic_info *mic, struct mic_vring *vring)
+{
+ if (((__u64)&virtblk_dev_page.blk_config % 8) != 0) {
+ mpsslog("%s: blk_config is not 8 byte aligned.\n",
+ mic->name);
+ return false;
+ }
+ add_virtio_device(mic, &virtblk_dev_page.dd);
+ if (MAP_FAILED == init_vr(mic, mic->mic_virtblk.virtio_block_fd,
+ VIRTIO_ID_BLOCK, vring, NULL, virtblk_dev_page.dd.num_vq)) {
+ mpsslog("%s init_vr failed %s\n",
+ mic->name, strerror(errno));
+ return false;
+ }
+ return true;
+}
+
+static void
+stop_virtblk(struct mic_info *mic)
+{
+ int vr_size, ret;
+
+ vr_size = PAGE_ALIGN(vring_size(MIC_VRING_ENTRIES,
+ MIC_VIRTIO_RING_ALIGN) + sizeof(struct _mic_vring_info));
+ ret = munmap(mic->mic_virtblk.block_dp,
+ MIC_DEVICE_PAGE_END + vr_size * virtblk_dev_page.dd.num_vq);
+ if (ret < 0)
+ mpsslog("%s munmap errno %d\n", mic->name, errno);
+ close(mic->mic_virtblk.virtio_block_fd);
+}
+
+static __u8
+header_error_check(struct vring_desc *desc)
+{
+ if (le32toh(desc->len) != sizeof(struct virtio_blk_outhdr)) {
+ mpsslog("%s() %d: length is not sizeof(virtio_blk_outhd)\n",
+ __func__, __LINE__);
+ return -EIO;
+ }
+ if (!(le16toh(desc->flags) & VRING_DESC_F_NEXT)) {
+ mpsslog("%s() %d: alone\n",
+ __func__, __LINE__);
+ return -EIO;
+ }
+ if (le16toh(desc->flags) & VRING_DESC_F_WRITE) {
+ mpsslog("%s() %d: not read\n",
+ __func__, __LINE__);
+ return -EIO;
+ }
+ return 0;
+}
+
+static int
+read_header(int fd, struct virtio_blk_outhdr *hdr, __u32 desc_idx)
+{
+ struct iovec iovec;
+ struct mic_copy_desc copy;
+
+ iovec.iov_len = sizeof(*hdr);
+ iovec.iov_base = hdr;
+ copy.iov = &iovec;
+ copy.iovcnt = 1;
+ copy.vr_idx = 0; /* only one vring on virtio_block */
+ copy.update_used = false; /* do not update used index */
+ return ioctl(fd, MIC_VIRTIO_COPY_DESC, &copy);
+}
+
+static int
+transfer_blocks(int fd, struct iovec *iovec, __u32 iovcnt)
+{
+ struct mic_copy_desc copy;
+
+ copy.iov = iovec;
+ copy.iovcnt = iovcnt;
+ copy.vr_idx = 0; /* only one vring on virtio_block */
+ copy.update_used = false; /* do not update used index */
+ return ioctl(fd, MIC_VIRTIO_COPY_DESC, &copy);
+}
+
+static __u8
+status_error_check(struct vring_desc *desc)
+{
+ if (le32toh(desc->len) != sizeof(__u8)) {
+ mpsslog("%s() %d: length is not sizeof(status)\n",
+ __func__, __LINE__);
+ return -EIO;
+ }
+ return 0;
+}
+
+static int
+write_status(int fd, __u8 *status)
+{
+ struct iovec iovec;
+ struct mic_copy_desc copy;
+
+ iovec.iov_base = status;
+ iovec.iov_len = sizeof(*status);
+ copy.iov = &iovec;
+ copy.iovcnt = 1;
+ copy.vr_idx = 0; /* only one vring on virtio_block */
+ copy.update_used = true; /* Update used index */
+ return ioctl(fd, MIC_VIRTIO_COPY_DESC, &copy);
+}
+
+static void *
+virtio_block(void *arg)
+{
+ struct mic_info *mic = (struct mic_info *) arg;
+ int ret;
+ struct pollfd block_poll;
+ struct mic_vring vring;
+ __u16 avail_idx;
+ __u32 desc_idx;
+ struct vring_desc *desc;
+ struct iovec *iovec, *piov;
+ __u8 status;
+ __u32 buffer_desc_idx;
+ struct virtio_blk_outhdr hdr;
+ void *fos;
+
+ for (;;) { /* forever */
+ if (!open_backend(mic)) { /* No virtblk */
+ for (mic->mic_virtblk.signaled = 0;
+ !mic->mic_virtblk.signaled;)
+ sleep(1);
+ continue;
+ }
+
+ /* backend file is specified. */
+ if (!start_virtblk(mic, &vring))
+ goto _close_backend;
+ iovec = malloc(sizeof(*iovec) *
+ le32toh(virtblk_dev_page.blk_config.seg_max));
+ if (!iovec) {
+ mpsslog("%s: can't alloc iovec: %s\n",
+ mic->name, strerror(ENOMEM));
+ goto _stop_virtblk;
+ }
+
+ block_poll.fd = mic->mic_virtblk.virtio_block_fd;
+ block_poll.events = POLLIN;
+ for (mic->mic_virtblk.signaled = 0;
+ !mic->mic_virtblk.signaled;) {
+ block_poll.revents = 0;
+ /* timeout in 1 sec to see signaled */
+ ret = poll(&block_poll, 1, 1000);
+ if (ret < 0) {
+ mpsslog("%s %d: poll failed: %s\n",
+ __func__, __LINE__,
+ strerror(errno));
+ continue;
+ }
+
+ if (!(block_poll.revents & POLLIN)) {
+#ifdef DEBUG
+ mpsslog("%s %d: block_poll.revents=0x%x\n",
+ __func__, __LINE__, block_poll.revents);
+#endif
+ continue;
+ }
+
+ /* POLLIN */
+ while (vring.info->avail_idx !=
+ le16toh(vring.vr.avail->idx)) {
+ /* read header element */
+ avail_idx =
+ vring.info->avail_idx &
+ (vring.vr.num - 1);
+ desc_idx = le16toh(
+ vring.vr.avail->ring[avail_idx]);
+ desc = &vring.vr.desc[desc_idx];
+#ifdef DEBUG
+ mpsslog("%s() %d: avail_idx=%d ",
+ __func__, __LINE__,
+ vring.info->avail_idx);
+ mpsslog("vring.vr.num=%d desc=%p\n",
+ vring.vr.num, desc);
+#endif
+ status = header_error_check(desc);
+ ret = read_header(
+ mic->mic_virtblk.virtio_block_fd,
+ &hdr, desc_idx);
+ if (ret < 0) {
+ mpsslog("%s() %d %s: ret=%d %s\n",
+ __func__, __LINE__,
+ mic->name, ret,
+ strerror(errno));
+ break;
+ }
+ /* buffer element */
+ piov = iovec;
+ status = 0;
+ fos = mic->mic_virtblk.backend_addr +
+ (hdr.sector * SECTOR_SIZE);
+ buffer_desc_idx = desc_idx =
+ next_desc(desc);
+ for (desc = &vring.vr.desc[buffer_desc_idx];
+ desc->flags & VRING_DESC_F_NEXT;
+ desc_idx = next_desc(desc),
+ desc = &vring.vr.desc[desc_idx]) {
+ piov->iov_len = desc->len;
+ piov->iov_base = fos;
+ piov++;
+ fos += desc->len;
+ }
+ /* Returning NULLs for VIRTIO_BLK_T_GET_ID. */
+ if (hdr.type & ~(VIRTIO_BLK_T_OUT |
+ VIRTIO_BLK_T_GET_ID)) {
+ /*
+ VIRTIO_BLK_T_IN - does not do
+ anything. Probably for documenting.
+ VIRTIO_BLK_T_SCSI_CMD - for
+ virtio_scsi.
+ VIRTIO_BLK_T_FLUSH - turned off in
+ config space.
+ VIRTIO_BLK_T_BARRIER - defined but not
+ used in anywhere.
+ */
+ mpsslog("%s() %d: type %x ",
+ __func__, __LINE__,
+ hdr.type);
+ mpsslog("is not supported\n");
+ status = -ENOTSUP;
+
+ } else {
+ ret = transfer_blocks(
+ mic->mic_virtblk.virtio_block_fd,
+ iovec,
+ piov - iovec);
+ if (ret < 0 &&
+ status != 0)
+ status = ret;
+ }
+ /* write status and update used pointer */
+ if (status != 0)
+ status = status_error_check(desc);
+ ret = write_status(
+ mic->mic_virtblk.virtio_block_fd,
+ &status);
+#ifdef DEBUG
+ mpsslog("%s() %d: write status=%d on desc=%p\n",
+ __func__, __LINE__,
+ status, desc);
+#endif
+ }
+ }
+ free(iovec);
+_stop_virtblk:
+ stop_virtblk(mic);
+_close_backend:
+ close_backend(mic);
+ } /* forever */
+
+ pthread_exit(NULL);
+}
+
+static void
+reset(struct mic_info *mic)
+{
+#define RESET_TIMEOUT 120
+ int i = RESET_TIMEOUT;
+ setsysfs(mic->name, "state", "reset");
+ while (i) {
+ char *state;
+ state = readsysfs(mic->name, "state");
+ if (!state)
+ goto retry;
+ mpsslog("%s: %s %d state %s\n",
+ mic->name, __func__, __LINE__, state);
+ if ((!strcmp(state, "offline"))) {
+ free(state);
+ break;
+ }
+ free(state);
+retry:
+ sleep(1);
+ i--;
+ }
+}
+
+static int
+get_mic_shutdown_status(struct mic_info *mic, char *shutdown_status)
+{
+ if (!strcmp(shutdown_status, "nop"))
+ return MIC_NOP;
+ if (!strcmp(shutdown_status, "crashed"))
+ return MIC_CRASHED;
+ if (!strcmp(shutdown_status, "halted"))
+ return MIC_HALTED;
+ if (!strcmp(shutdown_status, "poweroff"))
+ return MIC_POWER_OFF;
+ if (!strcmp(shutdown_status, "restart"))
+ return MIC_RESTART;
+ mpsslog("%s: BUG invalid status %s\n", mic->name, shutdown_status);
+ /* Invalid state */
+ assert(0);
+};
+
+static int get_mic_state(struct mic_info *mic, char *state)
+{
+ if (!strcmp(state, "offline"))
+ return MIC_OFFLINE;
+ if (!strcmp(state, "online"))
+ return MIC_ONLINE;
+ if (!strcmp(state, "shutting_down"))
+ return MIC_SHUTTING_DOWN;
+ if (!strcmp(state, "reset_failed"))
+ return MIC_RESET_FAILED;
+ mpsslog("%s: BUG invalid state %s\n", mic->name, state);
+ /* Invalid state */
+ assert(0);
+};
+
+static void mic_handle_shutdown(struct mic_info *mic)
+{
+#define SHUTDOWN_TIMEOUT 60
+ int i = SHUTDOWN_TIMEOUT, ret, stat = 0;
+ char *shutdown_status;
+ while (i) {
+ shutdown_status = readsysfs(mic->name, "shutdown_status");
+ if (!shutdown_status)
+ continue;
+ mpsslog("%s: %s %d shutdown_status %s\n",
+ mic->name, __func__, __LINE__, shutdown_status);
+ switch (get_mic_shutdown_status(mic, shutdown_status)) {
+ case MIC_RESTART:
+ mic->restart = 1;
+ case MIC_HALTED:
+ case MIC_POWER_OFF:
+ case MIC_CRASHED:
+ free(shutdown_status);
+ goto reset;
+ default:
+ break;
+ }
+ free(shutdown_status);
+ sleep(1);
+ i--;
+ }
+reset:
+ ret = kill(mic->pid, SIGTERM);
+ mpsslog("%s: %s %d kill pid %d ret %d\n",
+ mic->name, __func__, __LINE__,
+ mic->pid, ret);
+ if (!ret) {
+ ret = waitpid(mic->pid, &stat,
+ WIFSIGNALED(stat));
+ mpsslog("%s: %s %d waitpid ret %d pid %d\n",
+ mic->name, __func__, __LINE__,
+ ret, mic->pid);
+ }
+ if (ret == mic->pid)
+ reset(mic);
+}
+
+static void *
+mic_config(void *arg)
+{
+ struct mic_info *mic = (struct mic_info *)arg;
+ char *state = NULL;
+ char pathname[PATH_MAX];
+ int fd, ret;
+ struct pollfd ufds[1];
+ char value[4096];
+
+ snprintf(pathname, PATH_MAX - 1, "%s/%s/%s",
+ MICSYSFSDIR, mic->name, "state");
+
+ fd = open(pathname, O_RDONLY);
+ if (fd < 0) {
+ mpsslog("%s: opening file %s failed %s\n",
+ mic->name, pathname, strerror(errno));
+ goto error;
+ }
+
+ do {
+ ret = read(fd, value, sizeof(value));
+ if (ret < 0) {
+ mpsslog("%s: Failed to read sysfs entry '%s': %s\n",
+ mic->name, pathname, strerror(errno));
+ goto close_error1;
+ }
+retry:
+ state = readsysfs(mic->name, "state");
+ if (!state)
+ goto retry;
+ mpsslog("%s: %s %d state %s\n",
+ mic->name, __func__, __LINE__, state);
+ switch (get_mic_state(mic, state)) {
+ case MIC_SHUTTING_DOWN:
+ mic_handle_shutdown(mic);
+ goto close_error;
+ default:
+ break;
+ }
+ free(state);
+
+ ufds[0].fd = fd;
+ ufds[0].events = POLLERR | POLLPRI;
+ ret = poll(ufds, 1, -1);
+ if (ret < 0) {
+ mpsslog("%s: poll failed %s\n",
+ mic->name, strerror(errno));
+ goto close_error1;
+ }
+ } while (1);
+close_error:
+ free(state);
+close_error1:
+ close(fd);
+error:
+ init_mic(mic);
+ pthread_exit(NULL);
+}
+
+static void
+set_cmdline(struct mic_info *mic)
+{
+ char buffer[PATH_MAX];
+ int len;
+
+ len = snprintf(buffer, PATH_MAX,
+ "clocksource=tsc highres=off nohz=off ");
+ len += snprintf(buffer + len, PATH_MAX,
+ "cpufreq_on;corec6_off;pc3_off;pc6_off ");
+ len += snprintf(buffer + len, PATH_MAX,
+ "ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0",
+ mic->id);
+
+ setsysfs(mic->name, "cmdline", buffer);
+ mpsslog("%s: Command line: \"%s\"\n", mic->name, buffer);
+ snprintf(buffer, PATH_MAX, "172.31.%d.1", mic->id);
+ mpsslog("%s: IPADDR: \"%s\"\n", mic->name, buffer);
+}
+
+static void
+set_log_buf_info(struct mic_info *mic)
+{
+ int fd;
+ off_t len;
+ char system_map[] = "/lib/firmware/mic/System.map";
+ char *map, *temp, log_buf[17] = {'\0'};
+
+ fd = open(system_map, O_RDONLY);
+ if (fd < 0) {
+ mpsslog("%s: Opening System.map failed: %d\n",
+ mic->name, errno);
+ return;
+ }
+ len = lseek(fd, 0, SEEK_END);
+ if (len < 0) {
+ mpsslog("%s: Reading System.map size failed: %d\n",
+ mic->name, errno);
+ close(fd);
+ return;
+ }
+ map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (map == MAP_FAILED) {
+ mpsslog("%s: mmap of System.map failed: %d\n",
+ mic->name, errno);
+ close(fd);
+ return;
+ }
+ temp = strstr(map, "__log_buf");
+ if (!temp) {
+ mpsslog("%s: __log_buf not found: %d\n", mic->name, errno);
+ munmap(map, len);
+ close(fd);
+ return;
+ }
+ strncpy(log_buf, temp - 19, 16);
+ setsysfs(mic->name, "log_buf_addr", log_buf);
+ mpsslog("%s: log_buf_addr: %s\n", mic->name, log_buf);
+ temp = strstr(map, "log_buf_len");
+ if (!temp) {
+ mpsslog("%s: log_buf_len not found: %d\n", mic->name, errno);
+ munmap(map, len);
+ close(fd);
+ return;
+ }
+ strncpy(log_buf, temp - 19, 16);
+ setsysfs(mic->name, "log_buf_len", log_buf);
+ mpsslog("%s: log_buf_len: %s\n", mic->name, log_buf);
+ munmap(map, len);
+ close(fd);
+}
+
+static void init_mic(struct mic_info *mic);
+
+static void
+change_virtblk_backend(int x, siginfo_t *siginfo, void *p)
+{
+ struct mic_info *mic;
+
+ for (mic = mic_list.next; mic != NULL; mic = mic->next)
+ mic->mic_virtblk.signaled = 1/* true */;
+}
+
+static void
+init_mic(struct mic_info *mic)
+{
+ struct sigaction ignore = {
+ .sa_flags = 0,
+ .sa_handler = SIG_IGN
+ };
+ struct sigaction act = {
+ .sa_flags = SA_SIGINFO,
+ .sa_sigaction = change_virtblk_backend,
+ };
+ char buffer[PATH_MAX];
+ int err;
+
+ /*
+ * Currently, one virtio block device is supported for each MIC card
+ * at a time. Any user (or test) can send a SIGUSR1 to the MIC daemon.
+ * The signal informs the virtio block backend about a change in the
+ * configuration file which specifies the virtio backend file name on
+ * the host. Virtio block backend then re-reads the configuration file
+ * and switches to the new block device. This signalling mechanism may
+ * not be required once multiple virtio block devices are supported by
+ * the MIC daemon.
+ */
+ sigaction(SIGUSR1, &ignore, NULL);
+
+ mic->pid = fork();
+ switch (mic->pid) {
+ case 0:
+ set_log_buf_info(mic);
+ set_cmdline(mic);
+ add_virtio_device(mic, &virtcons_dev_page.dd);
+ add_virtio_device(mic, &virtnet_dev_page.dd);
+ err = pthread_create(&mic->mic_console.console_thread, NULL,
+ virtio_console, mic);
+ if (err)
+ mpsslog("%s virtcons pthread_create failed %s\n",
+ mic->name, strerror(err));
+ err = pthread_create(&mic->mic_net.net_thread, NULL,
+ virtio_net, mic);
+ if (err)
+ mpsslog("%s virtnet pthread_create failed %s\n",
+ mic->name, strerror(err));
+ err = pthread_create(&mic->mic_virtblk.block_thread, NULL,
+ virtio_block, mic);
+ if (err)
+ mpsslog("%s virtblk pthread_create failed %s\n",
+ mic->name, strerror(err));
+ sigemptyset(&act.sa_mask);
+ err = sigaction(SIGUSR1, &act, NULL);
+ if (err)
+ mpsslog("%s sigaction SIGUSR1 failed %s\n",
+ mic->name, strerror(errno));
+ while (1)
+ sleep(60);
+ case -1:
+ mpsslog("fork failed MIC name %s id %d errno %d\n",
+ mic->name, mic->id, errno);
+ break;
+ default:
+ if (mic->restart) {
+ snprintf(buffer, PATH_MAX, "boot");
+ setsysfs(mic->name, "state", buffer);
+ mpsslog("%s restarting mic %d\n",
+ mic->name, mic->restart);
+ mic->restart = 0;
+ }
+ pthread_create(&mic->config_thread, NULL, mic_config, mic);
+ }
+}
+
+static void
+start_daemon(void)
+{
+ struct mic_info *mic;
+
+ for (mic = mic_list.next; mic != NULL; mic = mic->next)
+ init_mic(mic);
+
+ while (1)
+ sleep(60);
+}
+
+static int
+init_mic_list(void)
+{
+ struct mic_info *mic = &mic_list;
+ struct dirent *file;
+ DIR *dp;
+ int cnt = 0;
+
+ dp = opendir(MICSYSFSDIR);
+ if (!dp)
+ return 0;
+
+ while ((file = readdir(dp)) != NULL) {
+ if (!strncmp(file->d_name, "mic", 3)) {
+ mic->next = malloc(sizeof(struct mic_info));
+ if (mic->next) {
+ mic = mic->next;
+ mic->next = NULL;
+ memset(mic, 0, sizeof(struct mic_info));
+ mic->id = atoi(&file->d_name[3]);
+ mic->name = malloc(strlen(file->d_name) + 16);
+ if (mic->name)
+ strcpy(mic->name, file->d_name);
+ mpsslog("MIC name %s id %d\n", mic->name,
+ mic->id);
+ cnt++;
+ }
+ }
+ }
+
+ closedir(dp);
+ return cnt;
+}
+
+void
+mpsslog(char *format, ...)
+{
+ va_list args;
+ char buffer[4096];
+ char ts[52], *ts1;
+ time_t t;
+
+ if (logfp == NULL)
+ return;
+
+ va_start(args, format);
+ vsprintf(buffer, format, args);
+ va_end(args);
+
+ time(&t);
+ ts1 = ctime_r(&t, ts);
+ ts1[strlen(ts1) - 1] = '\0';
+ fprintf(logfp, "%s: %s", ts1, buffer);
+
+ fflush(logfp);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int cnt;
+ pid_t pid;
+
+ myname = argv[0];
+
+ logfp = fopen(LOGFILE_NAME, "a+");
+ if (!logfp) {
+ fprintf(stderr, "cannot open logfile '%s'\n", LOGFILE_NAME);
+ exit(1);
+ }
+ pid = fork();
+ switch (pid) {
+ case 0:
+ break;
+ case -1:
+ exit(2);
+ default:
+ exit(0);
+ }
+
+ mpsslog("MIC Daemon start\n");
+
+ cnt = init_mic_list();
+ if (cnt == 0) {
+ mpsslog("MIC module not loaded\n");
+ exit(3);
+ }
+ mpsslog("MIC found %d devices\n", cnt);
+
+ start_daemon();
+
+ exit(0);
+}
diff --git a/Documentation/mic/mpssd/mpssd.h b/Documentation/mic/mpssd/mpssd.h
new file mode 100644
index 000000000000..b6dee38ca5b1
--- /dev/null
+++ b/Documentation/mic/mpssd/mpssd.h
@@ -0,0 +1,100 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC User Space Tools.
+ */
+#ifndef _MPSSD_H_
+#define _MPSSD_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <libgen.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/dir.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/utsname.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <signal.h>
+#include <limits.h>
+#include <syslog.h>
+#include <getopt.h>
+#include <net/if.h>
+#include <linux/if_tun.h>
+#include <linux/if_tun.h>
+#include <linux/virtio_ids.h>
+
+#define MICSYSFSDIR "/sys/class/mic"
+#define LOGFILE_NAME "/var/log/mpssd"
+#define PAGE_SIZE 4096
+
+struct mic_console_info {
+ pthread_t console_thread;
+ int virtio_console_fd;
+ void *console_dp;
+};
+
+struct mic_net_info {
+ pthread_t net_thread;
+ int virtio_net_fd;
+ int tap_fd;
+ void *net_dp;
+};
+
+struct mic_virtblk_info {
+ pthread_t block_thread;
+ int virtio_block_fd;
+ void *block_dp;
+ volatile sig_atomic_t signaled;
+ char *backend_file;
+ int backend;
+ void *backend_addr;
+ long backend_size;
+};
+
+struct mic_info {
+ int id;
+ char *name;
+ pthread_t config_thread;
+ pid_t pid;
+ struct mic_console_info mic_console;
+ struct mic_net_info mic_net;
+ struct mic_virtblk_info mic_virtblk;
+ int restart;
+ struct mic_info *next;
+};
+
+void mpsslog(char *format, ...);
+char *readsysfs(char *dir, char *entry);
+int setsysfs(char *dir, char *entry, char *value);
+#endif
diff --git a/Documentation/mic/mpssd/sysfs.c b/Documentation/mic/mpssd/sysfs.c
new file mode 100644
index 000000000000..11de72b63386
--- /dev/null
+++ b/Documentation/mic/mpssd/sysfs.c
@@ -0,0 +1,102 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC User Space Tools.
+ */
+
+#include "mpssd.h"
+
+#define PAGE_SIZE 4096
+
+char *
+readsysfs(char *dir, char *entry)
+{
+ char filename[PATH_MAX];
+ char value[PAGE_SIZE];
+ char *string = NULL;
+ int fd;
+ int len;
+
+ if (dir == NULL)
+ snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry);
+ else
+ snprintf(filename, PATH_MAX,
+ "%s/%s/%s", MICSYSFSDIR, dir, entry);
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ mpsslog("Failed to open sysfs entry '%s': %s\n",
+ filename, strerror(errno));
+ return NULL;
+ }
+
+ len = read(fd, value, sizeof(value));
+ if (len < 0) {
+ mpsslog("Failed to read sysfs entry '%s': %s\n",
+ filename, strerror(errno));
+ goto readsys_ret;
+ }
+ if (len == 0)
+ goto readsys_ret;
+
+ value[len - 1] = '\0';
+
+ string = malloc(strlen(value) + 1);
+ if (string)
+ strcpy(string, value);
+
+readsys_ret:
+ close(fd);
+ return string;
+}
+
+int
+setsysfs(char *dir, char *entry, char *value)
+{
+ char filename[PATH_MAX];
+ char *oldvalue;
+ int fd, ret = 0;
+
+ if (dir == NULL)
+ snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry);
+ else
+ snprintf(filename, PATH_MAX, "%s/%s/%s",
+ MICSYSFSDIR, dir, entry);
+
+ oldvalue = readsysfs(dir, entry);
+
+ fd = open(filename, O_RDWR);
+ if (fd < 0) {
+ ret = errno;
+ mpsslog("Failed to open sysfs entry '%s': %s\n",
+ filename, strerror(errno));
+ goto done;
+ }
+
+ if (!oldvalue || strcmp(value, oldvalue)) {
+ if (write(fd, value, strlen(value)) < 0) {
+ ret = errno;
+ mpsslog("Failed to write new sysfs entry '%s': %s\n",
+ filename, strerror(errno));
+ }
+ }
+ close(fd);
+done:
+ if (oldvalue)
+ free(oldvalue);
+ return ret;
+}
diff --git a/Documentation/networking/netconsole.txt b/Documentation/networking/netconsole.txt
index a5d574a9ae09..0af2e040584e 100644
--- a/Documentation/networking/netconsole.txt
+++ b/Documentation/networking/netconsole.txt
@@ -59,9 +59,7 @@ address.
The remote host has several options to receive the kernel messages,
for example:
-1) syslogd
-
-2) netcat
+1) netcat
On distributions using a BSD-based netcat version (e.g. Fedora,
openSUSE and Ubuntu) the listening port must be specified without
@@ -70,10 +68,20 @@ for example:
'nc -u -l -p <port>' / 'nc -u -l <port>' or
'netcat -u -l -p <port>' / 'netcat -u -l <port>'
-3) socat
+2) socat
'socat udp-recv:<port> -'
+3) cancd
+
+ A daemon written specifically for netconsole that is good at capturing
+ output from many machines. Using netcat for several machines either
+ interleaves output from all machines or requires the use of per-machine
+ ports.
+
+ https://git.kernel.org/cgit/linux/kernel/git/joern/cancd.git/
+ https://oss.oracle.com/projects/cancd/
+
Dynamic reconfiguration:
========================
diff --git a/Documentation/pps/pps.txt b/Documentation/pps/pps.txt
index d35dcdd82ff6..c03b1be5eb15 100644
--- a/Documentation/pps/pps.txt
+++ b/Documentation/pps/pps.txt
@@ -66,6 +66,21 @@ In LinuxPPS the PPS sources are simply char devices usually mapped
into files /dev/pps0, /dev/pps1, etc..
+PPS with USB to serial devices
+------------------------------
+
+It is possible to grab the PPS from an USB to serial device. However,
+you should take into account the latencies and jitter introduced by
+the USB stack. Users has reported clock instability around +-1ms when
+synchronized with PPS through USB. This isn't suited for time server
+synchronization.
+
+If your device doesn't report PPS, you can check that the feature is
+supported by its driver. Most of the time, you only need to add a call
+to usb_serial_handle_dcd_change after checking the DCD status (see
+ch341 and pl2303 examples).
+
+
Coding example
--------------
diff --git a/Documentation/ptp/testptp.c b/Documentation/ptp/testptp.c
index f59ded066108..a74d0a84d329 100644
--- a/Documentation/ptp/testptp.c
+++ b/Documentation/ptp/testptp.c
@@ -100,6 +100,11 @@ static long ppb_to_scaled_ppm(int ppb)
return (long) (ppb * 65.536);
}
+static int64_t pctns(struct ptp_clock_time *t)
+{
+ return t->sec * 1000000000LL + t->nsec;
+}
+
static void usage(char *progname)
{
fprintf(stderr,
@@ -112,6 +117,8 @@ static void usage(char *progname)
" -f val adjust the ptp clock frequency by 'val' ppb\n"
" -g get the ptp clock time\n"
" -h prints this message\n"
+ " -k val measure the time offset between system and phc clock\n"
+ " for 'val' times (Maximum 25)\n"
" -p val enable output with a period of 'val' nanoseconds\n"
" -P val enable or disable (val=1|0) the system clock PPS\n"
" -s set the ptp clock time from the system time\n"
@@ -133,8 +140,12 @@ int main(int argc, char *argv[])
struct itimerspec timeout;
struct sigevent sigevent;
+ struct ptp_clock_time *pct;
+ struct ptp_sys_offset *sysoff;
+
+
char *progname;
- int c, cnt, fd;
+ int i, c, cnt, fd;
char *device = DEVICE;
clockid_t clkid;
@@ -144,14 +155,19 @@ int main(int argc, char *argv[])
int extts = 0;
int gettime = 0;
int oneshot = 0;
+ int pct_offset = 0;
+ int n_samples = 0;
int periodic = 0;
int perout = -1;
int pps = -1;
int settime = 0;
+ int64_t t1, t2, tp;
+ int64_t interval, offset;
+
progname = strrchr(argv[0], '/');
progname = progname ? 1+progname : argv[0];
- while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghp:P:sSt:v"))) {
+ while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghk:p:P:sSt:v"))) {
switch (c) {
case 'a':
oneshot = atoi(optarg);
@@ -174,6 +190,10 @@ int main(int argc, char *argv[])
case 'g':
gettime = 1;
break;
+ case 'k':
+ pct_offset = 1;
+ n_samples = atoi(optarg);
+ break;
case 'p':
perout = atoi(optarg);
break;
@@ -376,6 +396,47 @@ int main(int argc, char *argv[])
}
}
+ if (pct_offset) {
+ if (n_samples <= 0 || n_samples > 25) {
+ puts("n_samples should be between 1 and 25");
+ usage(progname);
+ return -1;
+ }
+
+ sysoff = calloc(1, sizeof(*sysoff));
+ if (!sysoff) {
+ perror("calloc");
+ return -1;
+ }
+ sysoff->n_samples = n_samples;
+
+ if (ioctl(fd, PTP_SYS_OFFSET, sysoff))
+ perror("PTP_SYS_OFFSET");
+ else
+ puts("system and phc clock time offset request okay");
+
+ pct = &sysoff->ts[0];
+ for (i = 0; i < sysoff->n_samples; i++) {
+ t1 = pctns(pct+2*i);
+ tp = pctns(pct+2*i+1);
+ t2 = pctns(pct+2*i+2);
+ interval = t2 - t1;
+ offset = (t2 + t1) / 2 - tp;
+
+ printf("system time: %ld.%ld\n",
+ (pct+2*i)->sec, (pct+2*i)->nsec);
+ printf("phc time: %ld.%ld\n",
+ (pct+2*i+1)->sec, (pct+2*i+1)->nsec);
+ printf("system time: %ld.%ld\n",
+ (pct+2*i+2)->sec, (pct+2*i+2)->nsec);
+ printf("system/phc clock time offset is %ld ns\n"
+ "system clock time delay is %ld ns\n",
+ offset, interval);
+ }
+
+ free(sysoff);
+ }
+
close(fd);
return 0;
}
diff --git a/Documentation/s390/s390dbf.txt b/Documentation/s390/s390dbf.txt
index fcaf0b4efba2..3da163383c93 100644
--- a/Documentation/s390/s390dbf.txt
+++ b/Documentation/s390/s390dbf.txt
@@ -158,6 +158,16 @@ Return Value: none
Description: Sets new actual debug level if new_level is valid.
---------------------------------------------------------------------------
+bool debug_level_enabled (debug_info_t * id, int level);
+
+Parameter: id: handle for debug log
+ level: debug level
+
+Return Value: True if level is less or equal to the current debug level.
+
+Description: Returns true if debug events for the specified level would be
+ logged. Otherwise returns false.
+---------------------------------------------------------------------------
void debug_stop_all(void);
Parameter: none
diff --git a/Documentation/scheduler/sched-arch.txt b/Documentation/scheduler/sched-arch.txt
index b1b8587b86f0..9290de703450 100644
--- a/Documentation/scheduler/sched-arch.txt
+++ b/Documentation/scheduler/sched-arch.txt
@@ -65,11 +65,6 @@ Possible arch/ problems
Possible arch problems I found (and either tried to fix or didn't):
-h8300 - Is such sleeping racy vs interrupts? (See #4a).
- The H8/300 manual I found indicates yes, however disabling IRQs
- over the sleep mean only NMIs can wake it up, so can't fix easily
- without doing spin waiting.
-
ia64 - is safe_halt call racy vs interrupts? (does it sleep?) (See #4a)
sh64 - Is sleeping racy vs interrupts? (See #4a)
diff --git a/Documentation/sound/alsa/soc/DPCM.txt b/Documentation/sound/alsa/soc/DPCM.txt
new file mode 100644
index 000000000000..aa8546f2d144
--- /dev/null
+++ b/Documentation/sound/alsa/soc/DPCM.txt
@@ -0,0 +1,380 @@
+Dynamic PCM
+===========
+
+1. Description
+==============
+
+Dynamic PCM allows an ALSA PCM device to digitally route its PCM audio to
+various digital endpoints during the PCM stream runtime. e.g. PCM0 can route
+digital audio to I2S DAI0, I2S DAI1 or PDM DAI2. This is useful for on SoC DSP
+drivers that expose several ALSA PCMs and can route to multiple DAIs.
+
+The DPCM runtime routing is determined by the ALSA mixer settings in the same
+way as the analog signal is routed in an ASoC codec driver. DPCM uses a DAPM
+graph representing the DSP internal audio paths and uses the mixer settings to
+determine the patch used by each ALSA PCM.
+
+DPCM re-uses all the existing component codec, platform and DAI drivers without
+any modifications.
+
+
+Phone Audio System with SoC based DSP
+-------------------------------------
+
+Consider the following phone audio subsystem. This will be used in this
+document for all examples :-
+
+| Front End PCMs | SoC DSP | Back End DAIs | Audio devices |
+
+ *************
+PCM0 <------------> * * <----DAI0-----> Codec Headset
+ * *
+PCM1 <------------> * * <----DAI1-----> Codec Speakers
+ * DSP *
+PCM2 <------------> * * <----DAI2-----> MODEM
+ * *
+PCM3 <------------> * * <----DAI3-----> BT
+ * *
+ * * <----DAI4-----> DMIC
+ * *
+ * * <----DAI5-----> FM
+ *************
+
+This diagram shows a simple smart phone audio subsystem. It supports Bluetooth,
+FM digital radio, Speakers, Headset Jack, digital microphones and cellular
+modem. This sound card exposes 4 DSP front end (FE) ALSA PCM devices and
+supports 6 back end (BE) DAIs. Each FE PCM can digitally route audio data to any
+of the BE DAIs. The FE PCM devices can also route audio to more than 1 BE DAI.
+
+
+
+Example - DPCM Switching playback from DAI0 to DAI1
+---------------------------------------------------
+
+Audio is being played to the Headset. After a while the user removes the headset
+and audio continues playing on the speakers.
+
+Playback on PCM0 to Headset would look like :-
+
+ *************
+PCM0 <============> * * <====DAI0=====> Codec Headset
+ * *
+PCM1 <------------> * * <----DAI1-----> Codec Speakers
+ * DSP *
+PCM2 <------------> * * <----DAI2-----> MODEM
+ * *
+PCM3 <------------> * * <----DAI3-----> BT
+ * *
+ * * <----DAI4-----> DMIC
+ * *
+ * * <----DAI5-----> FM
+ *************
+
+The headset is removed from the jack by user so the speakers must now be used :-
+
+ *************
+PCM0 <============> * * <----DAI0-----> Codec Headset
+ * *
+PCM1 <------------> * * <====DAI1=====> Codec Speakers
+ * DSP *
+PCM2 <------------> * * <----DAI2-----> MODEM
+ * *
+PCM3 <------------> * * <----DAI3-----> BT
+ * *
+ * * <----DAI4-----> DMIC
+ * *
+ * * <----DAI5-----> FM
+ *************
+
+The audio driver processes this as follows :-
+
+ 1) Machine driver receives Jack removal event.
+
+ 2) Machine driver OR audio HAL disables the Headset path.
+
+ 3) DPCM runs the PCM trigger(stop), hw_free(), shutdown() operations on DAI0
+ for headset since the path is now disabled.
+
+ 4) Machine driver or audio HAL enables the speaker path.
+
+ 5) DPCM runs the PCM ops for startup(), hw_params(), prepapre() and
+ trigger(start) for DAI1 Speakers since the path is enabled.
+
+In this example, the machine driver or userspace audio HAL can alter the routing
+and then DPCM will take care of managing the DAI PCM operations to either bring
+the link up or down. Audio playback does not stop during this transition.
+
+
+
+DPCM machine driver
+===================
+
+The DPCM enabled ASoC machine driver is similar to normal machine drivers
+except that we also have to :-
+
+ 1) Define the FE and BE DAI links.
+
+ 2) Define any FE/BE PCM operations.
+
+ 3) Define widget graph connections.
+
+
+1 FE and BE DAI links
+---------------------
+
+| Front End PCMs | SoC DSP | Back End DAIs | Audio devices |
+
+ *************
+PCM0 <------------> * * <----DAI0-----> Codec Headset
+ * *
+PCM1 <------------> * * <----DAI1-----> Codec Speakers
+ * DSP *
+PCM2 <------------> * * <----DAI2-----> MODEM
+ * *
+PCM3 <------------> * * <----DAI3-----> BT
+ * *
+ * * <----DAI4-----> DMIC
+ * *
+ * * <----DAI5-----> FM
+ *************
+
+For the example above we have to define 4 FE DAI links and 6 BE DAI links. The
+FE DAI links are defined as follows :-
+
+static struct snd_soc_dai_link machine_dais[] = {
+ {
+ .name = "PCM0 System",
+ .stream_name = "System Playback",
+ .cpu_dai_name = "System Pin",
+ .platform_name = "dsp-audio",
+ .codec_name = "snd-soc-dummy",
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+ .dpcm_playback = 1,
+ },
+ .....< other FE and BE DAI links here >
+};
+
+This FE DAI link is pretty similar to a regular DAI link except that we also
+set the DAI link to a DPCM FE with the "dynamic = 1". The supported FE stream
+directions should also be set with the "dpcm_playback" and "dpcm_capture"
+flags. There is also an option to specify the ordering of the trigger call for
+each FE. This allows the ASoC core to trigger the DSP before or after the other
+components (as some DSPs have strong requirements for the ordering DAI/DSP
+start and stop sequences).
+
+The FE DAI above sets the codec and code DAIs to dummy devices since the BE is
+dynamic and will change depending on runtime config.
+
+The BE DAIs are configured as follows :-
+
+static struct snd_soc_dai_link machine_dais[] = {
+ .....< FE DAI links here >
+ {
+ .name = "Codec Headset",
+ .cpu_dai_name = "ssp-dai.0",
+ .platform_name = "snd-soc-dummy",
+ .no_pcm = 1,
+ .codec_name = "rt5640.0-001c",
+ .codec_dai_name = "rt5640-aif1",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .be_hw_params_fixup = hswult_ssp0_fixup,
+ .ops = &haswell_ops,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ },
+ .....< other BE DAI links here >
+};
+
+This BE DAI link connects DAI0 to the codec (in this case RT5460 AIF1). It sets
+the "no_pcm" flag to mark it has a BE and sets flags for supported stream
+directions using "dpcm_playback" and "dpcm_capture" above.
+
+The BE has also flags set for ignoreing suspend and PM down time. This allows
+the BE to work in a hostless mode where the host CPU is not transferring data
+like a BT phone call :-
+
+ *************
+PCM0 <------------> * * <----DAI0-----> Codec Headset
+ * *
+PCM1 <------------> * * <----DAI1-----> Codec Speakers
+ * DSP *
+PCM2 <------------> * * <====DAI2=====> MODEM
+ * *
+PCM3 <------------> * * <====DAI3=====> BT
+ * *
+ * * <----DAI4-----> DMIC
+ * *
+ * * <----DAI5-----> FM
+ *************
+
+This allows the host CPU to sleep whilst the DSP, MODEM DAI and the BT DAI are
+still in operation.
+
+A BE DAI link can also set the codec to a dummy device if the code is a device
+that is managed externally.
+
+Likewise a BE DAI can also set a dummy cpu DAI if the CPU DAI is managed by the
+DSP firmware.
+
+
+2 FE/BE PCM operations
+----------------------
+
+The BE above also exports some PCM operations and a "fixup" callback. The fixup
+callback is used by the machine driver to (re)configure the DAI based upon the
+FE hw params. i.e. the DSP may perform SRC or ASRC from the FE to BE.
+
+e.g. DSP converts all FE hw params to run at fixed rate of 48k, 16bit, stereo for
+DAI0. This means all FE hw_params have to be fixed in the machine driver for
+DAI0 so that the DAI is running at desired configuration regardless of the FE
+configuration.
+
+static int dai0_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ /* The DSP will covert the FE rate to 48k, stereo */
+ rate->min = rate->max = 48000;
+ channels->min = channels->max = 2;
+
+ /* set DAI0 to 16 bit */
+ snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
+ SNDRV_PCM_HW_PARAM_FIRST_MASK],
+ SNDRV_PCM_FORMAT_S16_LE);
+ return 0;
+}
+
+The other PCM operation are the same as for regular DAI links. Use as necessary.
+
+
+3 Widget graph connections
+--------------------------
+
+The BE DAI links will normally be connected to the graph at initialisation time
+by the ASoC DAPM core. However, if the BE codec or BE DAI is a dummy then this
+has to be set explicitly in the driver :-
+
+/* BE for codec Headset - DAI0 is dummy and managed by DSP FW */
+{"DAI0 CODEC IN", NULL, "AIF1 Capture"},
+{"AIF1 Playback", NULL, "DAI0 CODEC OUT"},
+
+
+Writing a DPCM DSP driver
+=========================
+
+The DPCM DSP driver looks much like a standard platform class ASoC driver
+combined with elements from a codec class driver. A DSP platform driver must
+implement :-
+
+ 1) Front End PCM DAIs - i.e. struct snd_soc_dai_driver.
+
+ 2) DAPM graph showing DSP audio routing from FE DAIs to BEs.
+
+ 3) DAPM widgets from DSP graph.
+
+ 4) Mixers for gains, routing, etc.
+
+ 5) DMA configuration.
+
+ 6) BE AIF widgets.
+
+Items 6 is important for routing the audio outside of the DSP. AIF need to be
+defined for each BE and each stream direction. e.g for BE DAI0 above we would
+have :-
+
+SND_SOC_DAPM_AIF_IN("DAI0 RX", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("DAI0 TX", NULL, 0, SND_SOC_NOPM, 0, 0),
+
+The BE AIF are used to connect the DSP graph to the graphs for the other
+component drivers (e.g. codec graph).
+
+
+Hostless PCM streams
+====================
+
+A hostless PCM stream is a stream that is not routed through the host CPU. An
+example of this would be a phone call from handset to modem.
+
+
+ *************
+PCM0 <------------> * * <----DAI0-----> Codec Headset
+ * *
+PCM1 <------------> * * <====DAI1=====> Codec Speakers/Mic
+ * DSP *
+PCM2 <------------> * * <====DAI2=====> MODEM
+ * *
+PCM3 <------------> * * <----DAI3-----> BT
+ * *
+ * * <----DAI4-----> DMIC
+ * *
+ * * <----DAI5-----> FM
+ *************
+
+In this case the PCM data is routed via the DSP. The host CPU in this use case
+is only used for control and can sleep during the runtime of the stream.
+
+The host can control the hostless link either by :-
+
+ 1) Configuring the link as a CODEC <-> CODEC style link. In this case the link
+ is enabled or disabled by the state of the DAPM graph. This usually means
+ there is a mixer control that can be used to connect or disconnect the path
+ between both DAIs.
+
+ 2) Hostless FE. This FE has a virtual connection to the BE DAI links on the DAPM
+ graph. Control is then carried out by the FE as regualar PCM operations.
+ This method gives more control over the DAI links, but requires much more
+ userspace code to control the link. Its recommended to use CODEC<->CODEC
+ unless your HW needs more fine grained sequencing of the PCM ops.
+
+
+CODEC <-> CODEC link
+--------------------
+
+This DAI link is enabled when DAPM detects a valid path within the DAPM graph.
+The machine driver sets some additional parameters to the DAI link i.e.
+
+static const struct snd_soc_pcm_stream dai_params = {
+ .formats = SNDRV_PCM_FMTBIT_S32_LE,
+ .rate_min = 8000,
+ .rate_max = 8000,
+ .channels_min = 2,
+ .channels_max = 2,
+};
+
+static struct snd_soc_dai_link dais[] = {
+ < ... more DAI links above ... >
+ {
+ .name = "MODEM",
+ .stream_name = "MODEM",
+ .cpu_dai_name = "dai2",
+ .codec_dai_name = "modem-aif1",
+ .codec_name = "modem",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFM,
+ .params = &dai_params,
+ }
+ < ... more DAI links here ... >
+
+These parameters are used to configure the DAI hw_params() when DAPM detects a
+valid path and then calls the PCM operations to start the link. DAPM will also
+call the appropriate PCM operations to disable the DAI when the path is no
+longer valid.
+
+
+Hostless FE
+-----------
+
+The DAI link(s) are enabled by a FE that does not read or write any PCM data.
+This means creating a new FE that is connected with a virtual path to both
+DAI links. The DAI links will be started when the FE PCM is started and stopped
+when the FE PCM is stopped. Note that the FE PCM cannot read or write data in
+this configuration.
+
+
diff --git a/Documentation/sound/alsa/soc/codec.txt b/Documentation/sound/alsa/soc/codec.txt
index bce23a4a7875..db5f9c9ae149 100644
--- a/Documentation/sound/alsa/soc/codec.txt
+++ b/Documentation/sound/alsa/soc/codec.txt
@@ -1,22 +1,23 @@
-ASoC Codec Driver
-=================
+ASoC Codec Class Driver
+=======================
-The codec driver is generic and hardware independent code that configures the
-codec to provide audio capture and playback. It should contain no code that is
-specific to the target platform or machine. All platform and machine specific
-code should be added to the platform and machine drivers respectively.
+The codec class driver is generic and hardware independent code that configures
+the codec, FM, MODEM, BT or external DSP to provide audio capture and playback.
+It should contain no code that is specific to the target platform or machine.
+All platform and machine specific code should be added to the platform and
+machine drivers respectively.
-Each codec driver *must* provide the following features:-
+Each codec class driver *must* provide the following features:-
1) Codec DAI and PCM configuration
- 2) Codec control IO - using I2C, 3 Wire(SPI) or both APIs
+ 2) Codec control IO - using RegMap API
3) Mixers and audio controls
4) Codec audio operations
+ 5) DAPM description.
+ 6) DAPM event handler.
Optionally, codec drivers can also provide:-
- 5) DAPM description.
- 6) DAPM event handler.
7) DAC Digital mute control.
Its probably best to use this guide in conjunction with the existing codec
@@ -64,26 +65,9 @@ struct snd_soc_dai_driver wm8731_dai = {
2 - Codec control IO
--------------------
The codec can usually be controlled via an I2C or SPI style interface
-(AC97 combines control with data in the DAI). The codec drivers provide
-functions to read and write the codec registers along with supplying a
-register cache:-
-
- /* IO control data and register cache */
- void *control_data; /* codec control (i2c/3wire) data */
- void *reg_cache;
-
-Codec read/write should do any data formatting and call the hardware
-read write below to perform the IO. These functions are called by the
-core and ALSA when performing DAPM or changing the mixer:-
-
- unsigned int (*read)(struct snd_soc_codec *, unsigned int);
- int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
-
-Codec hardware IO functions - usually points to either the I2C, SPI or AC97
-read/write:-
-
- hw_write_t hw_write;
- hw_read_t hw_read;
+(AC97 combines control with data in the DAI). The codec driver should use the
+Regmap API for all codec IO. Please see include/linux/regmap.h and existing
+codec drivers for example regmap usage.
3 - Mixers and audio controls
@@ -127,7 +111,7 @@ Defines a stereo enumerated control
4 - Codec Audio Operations
--------------------------
-The codec driver also supports the following ALSA operations:-
+The codec driver also supports the following ALSA PCM operations:-
/* SoC audio ops */
struct snd_soc_ops {
diff --git a/Documentation/sound/alsa/soc/dapm.txt b/Documentation/sound/alsa/soc/dapm.txt
index 05bf5a0eee41..7dfd88ce31ac 100644
--- a/Documentation/sound/alsa/soc/dapm.txt
+++ b/Documentation/sound/alsa/soc/dapm.txt
@@ -21,7 +21,7 @@ level power systems.
There are 4 power domains within DAPM
- 1. Codec domain - VREF, VMID (core codec and audio power)
+ 1. Codec bias domain - VREF, VMID (core codec and audio power)
Usually controlled at codec probe/remove and suspend/resume, although
can be set at stream time if power is not needed for sidetone, etc.
@@ -63,14 +63,22 @@ Audio DAPM widgets fall into a number of types:-
o Line - Line Input/Output (and optional Jack)
o Speaker - Speaker
o Supply - Power or clock supply widget used by other widgets.
+ o Regulator - External regulator that supplies power to audio components.
+ o Clock - External clock that supplies clock to audio componnents.
+ o AIF IN - Audio Interface Input (with TDM slot mask).
+ o AIF OUT - Audio Interface Output (with TDM slot mask).
+ o Siggen - Signal Generator.
+ o DAI IN - Digital Audio Interface Input.
+ o DAI OUT - Digital Audio Interface Output.
+ o DAI Link - DAI Link between two DAI structures */
o Pre - Special PRE widget (exec before all others)
o Post - Special POST widget (exec after all others)
(Widgets are defined in include/sound/soc-dapm.h)
-Widgets are usually added in the codec driver and the machine driver. There are
-convenience macros defined in soc-dapm.h that can be used to quickly build a
-list of widgets of the codecs and machines DAPM widgets.
+Widgets can be added to the sound card by any of the component driver types.
+There are convenience macros defined in soc-dapm.h that can be used to quickly
+build a list of widgets of the codecs and machines DAPM widgets.
Most widgets have a name, register, shift and invert. Some widgets have extra
parameters for stream name and kcontrols.
@@ -80,11 +88,13 @@ parameters for stream name and kcontrols.
-------------------------
Stream Widgets relate to the stream power domain and only consist of ADCs
-(analog to digital converters) and DACs (digital to analog converters).
+(analog to digital converters), DACs (digital to analog converters),
+AIF IN and AIF OUT.
Stream widgets have the following format:-
SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert),
+SND_SOC_DAPM_AIF_IN(name, stream, slot, reg, shift, invert)
NOTE: the stream name must match the corresponding stream name in your codec
snd_soc_codec_dai.
@@ -94,6 +104,11 @@ e.g. stream widgets for HiFi playback and capture
SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1),
SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),
+e.g. stream widgets for AIF
+
+SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+
2.2 Path Domain Widgets
-----------------------
@@ -121,12 +136,14 @@ If you dont want the mixer elements prefixed with the name of the mixer widget,
you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same
as for SND_SOC_DAPM_MIXER.
-2.3 Platform/Machine domain Widgets
------------------------------------
+
+2.3 Machine domain Widgets
+--------------------------
Machine widgets are different from codec widgets in that they don't have a
codec register bit associated with them. A machine widget is assigned to each
-machine audio component (non codec) that can be independently powered. e.g.
+machine audio component (non codec or DSP) that can be independently
+powered. e.g.
o Speaker Amp
o Microphone Bias
@@ -146,12 +163,12 @@ static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event)
SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
-2.4 Codec Domain
-----------------
+2.4 Codec (BIAS) Domain
+-----------------------
-The codec power domain has no widgets and is handled by the codecs DAPM event
-handler. This handler is called when the codec powerstate is changed wrt to any
-stream event or by kernel PM events.
+The codec bias power domain has no widgets and is handled by the codecs DAPM
+event handler. This handler is called when the codec powerstate is changed wrt
+to any stream event or by kernel PM events.
2.5 Virtual Widgets
@@ -169,15 +186,16 @@ After all the widgets have been defined, they can then be added to the DAPM
subsystem individually with a call to snd_soc_dapm_new_control().
-3. Codec Widget Interconnections
-================================
+3. Codec/DSP Widget Interconnections
+====================================
-Widgets are connected to each other within the codec and machine by audio paths
-(called interconnections). Each interconnection must be defined in order to
-create a map of all audio paths between widgets.
+Widgets are connected to each other within the codec, platform and machine by
+audio paths (called interconnections). Each interconnection must be defined in
+order to create a map of all audio paths between widgets.
-This is easiest with a diagram of the codec (and schematic of the machine audio
-system), as it requires joining widgets together via their audio signal paths.
+This is easiest with a diagram of the codec or DSP (and schematic of the machine
+audio system), as it requires joining widgets together via their audio signal
+paths.
e.g., from the WM8731 output mixer (wm8731.c)
@@ -247,16 +265,9 @@ machine and includes the codec. e.g.
o Mic Jack
o Codec Pins
-When a codec pin is NC it can be marked as not used with a call to
-
-snd_soc_dapm_set_endpoint(codec, "Widget Name", 0);
-
-The last argument is 0 for inactive and 1 for active. This way the pin and its
-input widget will never be powered up and consume power.
-
-This also applies to machine widgets. e.g. if a headphone is connected to a
-jack then the jack can be marked active. If the headphone is removed, then
-the headphone jack can be marked inactive.
+Endpoints are added to the DAPM graph so that their usage can be determined in
+order to save power. e.g. NC codecs pins will be switched OFF, unconnected
+jacks can also be switched OFF.
5 DAPM Widget Events
diff --git a/Documentation/sound/alsa/soc/machine.txt b/Documentation/sound/alsa/soc/machine.txt
index d50c14df3411..74056dba52be 100644
--- a/Documentation/sound/alsa/soc/machine.txt
+++ b/Documentation/sound/alsa/soc/machine.txt
@@ -1,8 +1,10 @@
ASoC Machine Driver
===================
-The ASoC machine (or board) driver is the code that glues together the platform
-and codec drivers.
+The ASoC machine (or board) driver is the code that glues together all the
+component drivers (e.g. codecs, platforms and DAIs). It also describes the
+relationships between each componnent which include audio paths, GPIOs,
+interrupts, clocking, jacks and voltage regulators.
The machine driver can contain codec and platform specific code. It registers
the audio subsystem with the kernel as a platform device and is represented by
diff --git a/Documentation/sound/alsa/soc/platform.txt b/Documentation/sound/alsa/soc/platform.txt
index d57efad37e0a..3a08a2c9150c 100644
--- a/Documentation/sound/alsa/soc/platform.txt
+++ b/Documentation/sound/alsa/soc/platform.txt
@@ -1,9 +1,9 @@
ASoC Platform Driver
====================
-An ASoC platform driver can be divided into audio DMA and SoC DAI configuration
-and control. The platform drivers only target the SoC CPU and must have no board
-specific code.
+An ASoC platform driver class can be divided into audio DMA drivers, SoC DAI
+drivers and DSP drivers. The platform drivers only target the SoC CPU and must
+have no board specific code.
Audio DMA
=========
@@ -64,3 +64,16 @@ Each SoC DAI driver must provide the following features:-
5) Suspend and resume (optional)
Please see codec.txt for a description of items 1 - 4.
+
+
+SoC DSP Drivers
+===============
+
+Each SoC DSP driver usually supplies the following features :-
+
+ 1) DAPM graph
+ 2) Mixer controls
+ 3) DMA IO to/from DSP buffers (if applicable)
+ 4) Definition of DSP front end (FE) PCM devices.
+
+Please see DPCM.txt for a description of item 4.
diff --git a/Documentation/virtual/kvm/cpuid.txt b/Documentation/virtual/kvm/cpuid.txt
index 22ff659bc0fb..3c65feb83010 100644
--- a/Documentation/virtual/kvm/cpuid.txt
+++ b/Documentation/virtual/kvm/cpuid.txt
@@ -43,6 +43,13 @@ KVM_FEATURE_CLOCKSOURCE2 || 3 || kvmclock available at msrs
KVM_FEATURE_ASYNC_PF || 4 || async pf can be enabled by
|| || writing to msr 0x4b564d02
------------------------------------------------------------------------------
+KVM_FEATURE_STEAL_TIME || 5 || steal time can be enabled by
+ || || writing to msr 0x4b564d03.
+------------------------------------------------------------------------------
+KVM_FEATURE_PV_EOI || 6 || paravirtualized end of interrupt
+ || || handler can be enabled by writing
+ || || to msr 0x4b564d04.
+------------------------------------------------------------------------------
KVM_FEATURE_PV_UNHALT || 7 || guest checks this feature bit
|| || before enabling paravirtualized
|| || spinlock support.
diff --git a/Documentation/virtual/kvm/locking.txt b/Documentation/virtual/kvm/locking.txt
index 41b7ac9884b5..a9f366e73c8e 100644
--- a/Documentation/virtual/kvm/locking.txt
+++ b/Documentation/virtual/kvm/locking.txt
@@ -151,3 +151,14 @@ Type: spinlock_t
Arch: any
Protects: -shadow page/shadow tlb entry
Comment: it is a spinlock since it is used in mmu notifier.
+
+Name: kvm->srcu
+Type: srcu lock
+Arch: any
+Protects: - kvm->memslots
+ - kvm->buses
+Comment: The srcu read lock must be held while accessing memslots (e.g.
+ when using gfn_to_* functions) and while accessing in-kernel
+ MMIO/PIO address->device structure mapping (kvm->buses).
+ The srcu index can be stored in kvm_vcpu->srcu_idx per vcpu
+ if it is needed by multiple functions.
diff --git a/MAINTAINERS b/MAINTAINERS
index 9b1f81055160..0e04ce184837 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1142,11 +1142,6 @@ F: drivers/net/ethernet/i825xx/ether1*
F: drivers/net/ethernet/seeq/ether3*
F: drivers/scsi/arm/
-ARM/SHARK MACHINE SUPPORT
-M: Alexander Schulz <alex@shark-linux.de>
-W: http://www.shark-linux.de/shark.html
-S: Maintained
-
ARM/SAMSUNG ARM ARCHITECTURES
M: Ben Dooks <ben-linux@fluff.org>
M: Kukjin Kim <kgene.kim@samsung.com>
@@ -2640,6 +2635,18 @@ F: include/linux/device-mapper.h
F: include/linux/dm-*.h
F: include/uapi/linux/dm-*.h
+DIGI NEO AND CLASSIC PCI PRODUCTS
+M: Lidza Louina <lidza.louina@gmail.com>
+L: driverdev-devel@linuxdriverproject.org
+S: Maintained
+F: drivers/staging/dgnc/
+
+DIGI EPCA PCI PRODUCTS
+M: Lidza Louina <lidza.louina@gmail.com>
+L: driverdev-devel@linuxdriverproject.org
+S: Maintained
+F: drivers/staging/dgap/
+
DIOLAN U2C-12 I2C DRIVER
M: Guenter Roeck <linux@roeck-us.net>
L: linux-i2c@vger.kernel.org
@@ -2803,7 +2810,7 @@ M: Terje Bergström <tbergstrom@nvidia.com>
L: dri-devel@lists.freedesktop.org
L: linux-tegra@vger.kernel.org
T: git git://anongit.freedesktop.org/tegra/linux.git
-S: Maintained
+S: Supported
F: drivers/gpu/host1x/
F: include/uapi/drm/tegra_drm.h
F: Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
@@ -4196,7 +4203,7 @@ S: Maintained
F: drivers/media/rc/iguanair.c
IIO SUBSYSTEM AND DRIVERS
-M: Jonathan Cameron <jic23@cam.ac.uk>
+M: Jonathan Cameron <jic23@kernel.org>
L: linux-iio@vger.kernel.org
S: Maintained
F: drivers/iio/
@@ -4458,6 +4465,13 @@ L: linux-serial@vger.kernel.org
S: Maintained
F: drivers/tty/serial/ioc3_serial.c
+IOMMU DRIVERS
+M: Joerg Roedel <joro@8bytes.org>
+L: iommu@lists.linux-foundation.org
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
+S: Maintained
+F: drivers/iommu/
+
IP MASQUERADING
M: Juanjo Ciarlante <jjciarla@raiz.uncu.edu.ar>
S: Maintained
@@ -7391,9 +7405,10 @@ SELINUX SECURITY MODULE
M: Stephen Smalley <sds@tycho.nsa.gov>
M: James Morris <james.l.morris@oracle.com>
M: Eric Paris <eparis@parisplace.org>
+M: Paul Moore <paul@paul-moore.com>
L: selinux@tycho.nsa.gov (subscribers-only, general discussion)
W: http://selinuxproject.org
-T: git git://git.infradead.org/users/eparis/selinux.git
+T: git git://git.infradead.org/users/pcmoore/selinux
S: Supported
F: include/linux/selinux*
F: security/selinux/
@@ -7948,7 +7963,7 @@ S: Maintained
F: drivers/staging/media/go7007/
STAGING - INDUSTRIAL IO
-M: Jonathan Cameron <jic23@cam.ac.uk>
+M: Jonathan Cameron <jic23@kernel.org>
L: linux-iio@vger.kernel.org
S: Odd Fixes
F: drivers/staging/iio/
@@ -8263,14 +8278,72 @@ L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/rc/ttusbir.c
-TEGRA SUPPORT
+TEGRA ARCHITECTURE SUPPORT
M: Stephen Warren <swarren@wwwdotorg.org>
+M: Thierry Reding <thierry.reding@gmail.com>
L: linux-tegra@vger.kernel.org
Q: http://patchwork.ozlabs.org/project/linux-tegra/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git
S: Supported
N: [^a-z]tegra
+TEGRA ASOC DRIVER
+M: Stephen Warren <swarren@wwwdotorg.org>
+S: Supported
+F: sound/soc/tegra/
+
+TEGRA CLOCK DRIVER
+M: Peter De Schrijver <pdeschrijver@nvidia.com>
+M: Prashant Gaikwad <pgaikwad@nvidia.com>
+S: Supported
+F: drivers/clk/tegra/
+
+TEGRA DMA DRIVER
+M: Laxman Dewangan <ldewangan@nvidia.com>
+S: Supported
+F: drivers/dma/tegra20-apb-dma.c
+
+TEGRA GPIO DRIVER
+M: Stephen Warren <swarren@wwwdotorg.org>
+S: Supported
+F: drivers/gpio/gpio-tegra.c
+
+TEGRA I2C DRIVER
+M: Laxman Dewangan <ldewangan@nvidia.com>
+S: Supported
+F: drivers/i2c/busses/i2c-tegra.c
+
+TEGRA IOMMU DRIVERS
+M: Hiroshi Doyu <hdoyu@nvidia.com>
+S: Supported
+F: drivers/iommu/tegra*
+
+TEGRA KBC DRIVER
+M: Rakesh Iyer <riyer@nvidia.com>
+M: Laxman Dewangan <ldewangan@nvidia.com>
+S: Supported
+F: drivers/input/keyboard/tegra-kbc.c
+
+TEGRA PINCTRL DRIVER
+M: Stephen Warren <swarren@wwwdotorg.org>
+S: Supported
+F: drivers/pinctrl/pinctrl-tegra*
+
+TEGRA PWM DRIVER
+M: Thierry Reding <thierry.reding@gmail.com>
+S: Supported
+F: drivers/pwm/pwm-tegra.c
+
+TEGRA SERIAL DRIVER
+M: Laxman Dewangan <ldewangan@nvidia.com>
+S: Supported
+F: drivers/tty/serial/serial-tegra.c
+
+TEGRA SPI DRIVER
+M: Laxman Dewangan <ldewangan@nvidia.com>
+S: Supported
+F: drivers/spi/spi-tegra*
+
TEHUTI ETHERNET DRIVER
M: Andy Gospodarek <andy@greyhouse.net>
L: netdev@vger.kernel.org
@@ -8571,14 +8644,6 @@ S: Maintained
F: arch/m68k/*/*_no.*
F: arch/m68k/include/asm/*_no.*
-UCLINUX FOR RENESAS H8/300 (H8300)
-M: Yoshinori Sato <ysato@users.sourceforge.jp>
-W: http://uclinux-h8.sourceforge.jp/
-S: Supported
-F: arch/h8300/
-F: drivers/ide/ide-h8300.c
-F: drivers/net/ethernet/8390/ne-h8300.c
-
UDF FILESYSTEM
M: Jan Kara <jack@suse.cz>
S: Maintained
@@ -8725,9 +8790,8 @@ F: Documentation/hid/hiddev.txt
F: drivers/hid/usbhid/
USB/IP DRIVERS
-M: Matt Mooney <mfm@muteddisk.com>
L: linux-usb@vger.kernel.org
-S: Maintained
+S: Orphan
F: drivers/staging/usbip/
USB ISP116X DRIVER
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index a6e85f448c1c..f01fb505ad52 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -3,3 +3,4 @@ generic-y += clkdev.h
generic-y += exec.h
generic-y += trace_clock.h
+generic-y += preempt.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index d8dd660898b9..5943f7f9d325 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += ucontext.h
generic-y += user.h
generic-y += vga.h
generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 3f7714d8d2d2..b766dadd321b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -457,7 +457,7 @@ config ARCH_IOP32X
depends on MMU
select ARCH_REQUIRE_GPIOLIB
select CPU_XSCALE
- select NEED_MACH_GPIO_H
+ select GPIO_IOP
select NEED_RET_TO_USER
select PCI
select PLAT_IOP
@@ -470,7 +470,7 @@ config ARCH_IOP33X
depends on MMU
select ARCH_REQUIRE_GPIOLIB
select CPU_XSCALE
- select NEED_MACH_GPIO_H
+ select GPIO_IOP
select NEED_RET_TO_USER
select PCI
select PLAT_IOP
@@ -727,6 +727,7 @@ config ARCH_S3C64XX
select ARM_VIC
select CLKDEV_LOOKUP
select CLKSRC_SAMSUNG_PWM
+ select COMMON_CLK
select CPU_V6
select GENERIC_CLOCKEVENTS
select GPIO_SAMSUNG
@@ -740,7 +741,6 @@ config ARCH_S3C64XX
select S3C_DEV_NAND
select S3C_GPIO_TRACK
select SAMSUNG_ATAGS
- select SAMSUNG_CLKSRC
select SAMSUNG_GPIOLIB_4BIT
select SAMSUNG_WDT_RESET
select USB_ARCH_HAS_OHCI
@@ -824,20 +824,6 @@ config ARCH_EXYNOS
help
Support for SAMSUNG's EXYNOS SoCs (EXYNOS4/5)
-config ARCH_SHARK
- bool "Shark"
- select ARCH_USES_GETTIMEOFFSET
- select CPU_SA110
- select ISA
- select ISA_DMA
- select NEED_MACH_MEMORY_H
- select PCI
- select VIRT_TO_BUS
- select ZONE_DMA
- help
- Support for the StrongARM based Digital DNARD machine, also known
- as "Shark" (<http://www.shark-linux.de/shark.html>).
-
config ARCH_DAVINCI
bool "TI DaVinci"
select ARCH_HAS_HOLES_MEMORYMODEL
@@ -1431,12 +1417,6 @@ config PCI_NANOENGINE
config PCI_SYSCALL
def_bool PCI
-# Select the host bridge type
-config PCI_HOST_VIA82C505
- bool
- depends on PCI && ARCH_SHARK
- default y
-
config PCI_HOST_ITE8152
bool
depends on PCI && MACH_ARMCORE
@@ -1549,6 +1529,32 @@ config MCPM
for (multi-)cluster based systems, such as big.LITTLE based
systems.
+config BIG_LITTLE
+ bool "big.LITTLE support (Experimental)"
+ depends on CPU_V7 && SMP
+ select MCPM
+ help
+ This option enables support selections for the big.LITTLE
+ system architecture.
+
+config BL_SWITCHER
+ bool "big.LITTLE switcher support"
+ depends on BIG_LITTLE && MCPM && HOTPLUG_CPU
+ select CPU_PM
+ select ARM_CPU_SUSPEND
+ help
+ The big.LITTLE "switcher" provides the core functionality to
+ transparently handle transition between a cluster of A15's
+ and a cluster of A7's in a big.LITTLE system.
+
+config BL_SWITCHER_DUMMY_IF
+ tristate "Simple big.LITTLE switcher user interface"
+ depends on BL_SWITCHER && DEBUG_KERNEL
+ help
+ This is a simple and dummy char dev interface to control
+ the big.LITTLE switcher core code. It is meant for
+ debugging purposes only.
+
choice
prompt "Memory split"
default VMSPLIT_3G
@@ -2217,8 +2223,7 @@ config NEON
config KERNEL_MODE_NEON
bool "Support for NEON in kernel mode"
- default n
- depends on NEON
+ depends on NEON && AEABI
help
Say Y to include support for NEON in kernel mode.
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 9762c84b4198..d597c6b8488b 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -386,6 +386,13 @@ choice
when u-boot hands over to the kernel, the system
silently crashes, with no serial output at all.
+ config DEBUG_VF_UART
+ bool "Vybrid UART"
+ depends on SOC_VF610
+ help
+ Say Y here if you want kernel low-level debugging support
+ on Vybrid based platforms.
+
config DEBUG_NOMADIK_UART
bool "Kernel low-level debugging messages via NOMADIK UART"
depends on ARCH_NOMADIK
@@ -906,6 +913,7 @@ config DEBUG_LL_INCLUDE
default "debug/tegra.S" if DEBUG_TEGRA_UART
default "debug/ux500.S" if DEBUG_UX500_UART
default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT
+ default "debug/vf.S" if DEBUG_VF_UART
default "debug/vt8500.S" if DEBUG_VT8500_UART0
default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
default "mach/debug-macro.S"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index a37a50f575a2..92a90fefddec 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -188,7 +188,6 @@ machine-$(CONFIG_ARCH_S5P64X0) += s5p64x0
machine-$(CONFIG_ARCH_S5PC100) += s5pc100
machine-$(CONFIG_ARCH_S5PV210) += s5pv210
machine-$(CONFIG_ARCH_SA1100) += sa1100
-machine-$(CONFIG_ARCH_SHARK) += shark
machine-$(CONFIG_ARCH_SHMOBILE) += shmobile
machine-$(CONFIG_ARCH_SHMOBILE_MULTI) += shmobile
machine-$(CONFIG_ARCH_SIRF) += prima2
diff --git a/arch/arm/arm-soc-for-next-contents.txt b/arch/arm/arm-soc-for-next-contents.txt
new file mode 100644
index 000000000000..4ea3784854a9
--- /dev/null
+++ b/arch/arm/arm-soc-for-next-contents.txt
@@ -0,0 +1,13 @@
+
+
+next/cleanup
+ shark/removal
+ git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git tags/del-shark-for-v3.13
+
+next/soc
+ samsung/s3c64xx-clk
+ http://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git tags/samsung-clk-s3c64xx
+
+next/dt
+ samsung/s3c64xx-dt
+ http://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git tags/samsung-dt-s3c64xx
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 7ac1610252ba..e7190bb5998e 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -44,10 +44,6 @@ ifeq ($(CONFIG_ARCH_ACORN),y)
OBJS += ll_char_wr.o font.o
endif
-ifeq ($(CONFIG_ARCH_SHARK),y)
-OBJS += head-shark.o ofw-shark.o
-endif
-
ifeq ($(CONFIG_ARCH_SA1100),y)
OBJS += head-sa1100.o
endif
diff --git a/arch/arm/boot/compressed/head-shark.S b/arch/arm/boot/compressed/head-shark.S
deleted file mode 100644
index 92b56897ed64..000000000000
--- a/arch/arm/boot/compressed/head-shark.S
+++ /dev/null
@@ -1,140 +0,0 @@
-/* The head-file for the Shark
- * by Alexander Schulz
- *
- * Does the following:
- * - get the memory layout from firmware. This can only be done as long as the mmu
- * is still on.
- * - switch the mmu off, so we have physical addresses
- * - copy the kernel to 0x08508000. This is done to have a fixed address where the
- * C-parts (misc.c) are executed. This address must be known at compile-time,
- * but the load-address of the kernel depends on how much memory is installed.
- * - Jump to this location.
- * - Set r8 with 0, r7 with the architecture ID for head.S
- */
-
-#include <linux/linkage.h>
-
-#include <asm/assembler.h>
-
- .section ".start", "ax"
-
- .arch armv4
- b __beginning
-
-__ofw_data: .long 0 @ the number of memory blocks
- .space 128 @ (startaddr,size) ...
- .space 128 @ bootargs
- .align
-
-__beginning: mov r4, r0 @ save the entry to the firmware
-
- mov r0, #0xC0 @ disable irq and fiq
- mov r1, r0
- mrs r3, cpsr
- bic r2, r3, r0
- eor r2, r2, r1
- msr cpsr_c, r2
-
- mov r0, r4 @ get the Memory layout from firmware
- adr r1, __ofw_data
- add r2, r1, #4
- mov lr, pc
- b ofw_init
- mov r1, #0
-
- adr r2, __mmu_off @ calculate physical address
- sub r2, r2, #0xf0000000 @ openprom maps us at f000 virt, 0e50 phys
- adr r0, __ofw_data
- ldr r0, [r0, #4]
- add r2, r2, r0
- add r2, r2, #0x00500000
-
- mrc p15, 0, r3, c1, c0
- bic r3, r3, #0xC @ Write Buffer and DCache
- bic r3, r3, #0x1000 @ ICache
- mcr p15, 0, r3, c1, c0 @ disabled
-
- mov r0, #0
- mcr p15, 0, r0, c7, c7 @ flush I,D caches on v4
- mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
- mcr p15, 0, r0, c8, c7 @ flush I,D TLBs on v4
-
- bic r3, r3, #0x1 @ MMU
- mcr p15, 0, r3, c1, c0 @ disabled
-
- mov pc, r2
-
-__copy_target: .long 0x08507FFC
-__copy_end: .long 0x08607FFC
-
- .word _start
- .word __bss_start
-
- .align
-__temp_stack: .space 128
-
-__mmu_off:
- adr r0, __ofw_data @ read the 1. entry of the memory map
- ldr r0, [r0, #4]
- orr r0, r0, #0x00600000
- sub r0, r0, #4
-
- ldr r1, __copy_end
- ldr r3, __copy_target
-
-/* r0 = 0x0e600000 (current end of kernelcode)
- * r3 = 0x08508000 (where it should begin)
- * r1 = 0x08608000 (end of copying area, 1MB)
- * The kernel is compressed, so 1 MB should be enough.
- * copy the kernel to the beginning of physical memory
- * We start from the highest address, so we can copy
- * from 0x08500000 to 0x08508000 if we have only 8MB
- */
-
-/* As we get more 2.6-kernels it gets more and more
- * uncomfortable to be bound to kernel images of 1MB only.
- * So we add a loop here, to be able to copy some more.
- * Alexander Schulz 2005-07-17
- */
-
- mov r4, #3 @ How many megabytes to copy
-
-
-__MoveCode: sub r4, r4, #1
-
-__Copy: ldr r2, [r0], #-4
- str r2, [r1], #-4
- teq r1, r3
- bne __Copy
-
- /* The firmware maps us in blocks of 1 MB, the next block is
- _below_ the last one. So our decrementing source pointer
- ist right here, but the destination pointer must be increased
- by 2 MB */
- add r1, r1, #0x00200000
- add r3, r3, #0x00100000
-
- teq r4, #0
- bne __MoveCode
-
-
- /* and jump to it */
- adr r2, __go_on @ where we want to jump
- adr r0, __ofw_data @ read the 1. entry of the memory map
- ldr r0, [r0, #4]
- sub r2, r2, r0 @ we are mapped add 0e50 now, sub that (-0e00)
- sub r2, r2, #0x00500000 @ -0050
- ldr r0, __copy_target @ and add 0850 8000 instead
- add r0, r0, #4
- add r2, r2, r0
- mov pc, r2 @ and jump there
-
-__go_on:
- adr sp, __temp_stack
- add sp, sp, #128
- adr r0, __ofw_data
- mov lr, pc
- b create_params
-
- mov r8, #0
- mov r7, #15
diff --git a/arch/arm/boot/compressed/ofw-shark.c b/arch/arm/boot/compressed/ofw-shark.c
deleted file mode 100644
index 465c54b6b128..000000000000
--- a/arch/arm/boot/compressed/ofw-shark.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * linux/arch/arm/boot/compressed/ofw-shark.c
- *
- * by Alexander Schulz
- *
- * This file is used to get some basic information
- * about the memory layout of the shark we are running
- * on. Memory is usually divided in blocks a 8 MB.
- * And bootargs are copied from OpenFirmware.
- */
-
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <asm/setup.h>
-#include <asm/page.h>
-
-
-asmlinkage void
-create_params (unsigned long *buffer)
-{
- /* Is there a better address? Also change in mach-shark/core.c */
- struct tag *tag = (struct tag *) 0x08003000;
- int j,i,m,k,nr_banks,size;
- unsigned char *c;
-
- k = 0;
-
- /* Head of the taglist */
- tag->hdr.tag = ATAG_CORE;
- tag->hdr.size = tag_size(tag_core);
- tag->u.core.flags = 1;
- tag->u.core.pagesize = PAGE_SIZE;
- tag->u.core.rootdev = 0;
-
- /* Build up one tagged block for each memory region */
- size=0;
- nr_banks=(unsigned int) buffer[0];
- for (j=0;j<nr_banks;j++){
- /* search the lowest address and put it into the next entry */
- /* not a fast sort algorithm, but there are at most 8 entries */
- /* and this is used only once anyway */
- m=0xffffffff;
- for (i=0;i<(unsigned int) buffer[0];i++){
- if (buffer[2*i+1]<m) {
- m=buffer[2*i+1];
- k=i;
- }
- }
-
- tag = tag_next(tag);
- tag->hdr.tag = ATAG_MEM;
- tag->hdr.size = tag_size(tag_mem32);
- tag->u.mem.size = buffer[2*k+2];
- tag->u.mem.start = buffer[2*k+1];
-
- size += buffer[2*k+2];
-
- buffer[2*k+1]=0xffffffff; /* mark as copied */
- }
-
- /* The command line */
- tag = tag_next(tag);
- tag->hdr.tag = ATAG_CMDLINE;
-
- c=(unsigned char *)(&buffer[34]);
- j=0;
- while (*c) tag->u.cmdline.cmdline[j++]=*c++;
-
- tag->u.cmdline.cmdline[j]=0;
- tag->hdr.size = (j + 7 + sizeof(struct tag_header)) >> 2;
-
- /* Hardware revision */
- tag = tag_next(tag);
- tag->hdr.tag = ATAG_REVISION;
- tag->hdr.size = tag_size(tag_revision);
- tag->u.revision.rev = ((unsigned char) buffer[33])-'0';
-
- /* End of the taglist */
- tag = tag_next(tag);
- tag->hdr.tag = 0;
- tag->hdr.size = 0;
-}
-
-
-typedef int (*ofw_handle_t)(void *);
-
-/* Everything below is called with a wrong MMU setting.
- * This means: no string constants, no initialization of
- * arrays, no global variables! This is ugly but I didn't
- * want to write this in assembler :-)
- */
-
-int
-of_decode_int(const unsigned char *p)
-{
- unsigned int i = *p++ << 8;
- i = (i + *p++) << 8;
- i = (i + *p++) << 8;
- return (i + *p);
-}
-
-int
-OF_finddevice(ofw_handle_t openfirmware, char *name)
-{
- unsigned int args[8];
- char service[12];
-
- service[0]='f';
- service[1]='i';
- service[2]='n';
- service[3]='d';
- service[4]='d';
- service[5]='e';
- service[6]='v';
- service[7]='i';
- service[8]='c';
- service[9]='e';
- service[10]='\0';
-
- args[0]=(unsigned int)service;
- args[1]=1;
- args[2]=1;
- args[3]=(unsigned int)name;
-
- if (openfirmware(args) == -1)
- return -1;
- return args[4];
-}
-
-int
-OF_getproplen(ofw_handle_t openfirmware, int handle, char *prop)
-{
- unsigned int args[8];
- char service[12];
-
- service[0]='g';
- service[1]='e';
- service[2]='t';
- service[3]='p';
- service[4]='r';
- service[5]='o';
- service[6]='p';
- service[7]='l';
- service[8]='e';
- service[9]='n';
- service[10]='\0';
-
- args[0] = (unsigned int)service;
- args[1] = 2;
- args[2] = 1;
- args[3] = (unsigned int)handle;
- args[4] = (unsigned int)prop;
-
- if (openfirmware(args) == -1)
- return -1;
- return args[5];
-}
-
-int
-OF_getprop(ofw_handle_t openfirmware, int handle, char *prop, void *buf, unsigned int buflen)
-{
- unsigned int args[8];
- char service[8];
-
- service[0]='g';
- service[1]='e';
- service[2]='t';
- service[3]='p';
- service[4]='r';
- service[5]='o';
- service[6]='p';
- service[7]='\0';
-
- args[0] = (unsigned int)service;
- args[1] = 4;
- args[2] = 1;
- args[3] = (unsigned int)handle;
- args[4] = (unsigned int)prop;
- args[5] = (unsigned int)buf;
- args[6] = buflen;
-
- if (openfirmware(args) == -1)
- return -1;
- return args[7];
-}
-
-asmlinkage void ofw_init(ofw_handle_t o, int *nomr, int *pointer)
-{
- int phandle,i,mem_len,buffer[32];
- char temp[15];
-
- temp[0]='/';
- temp[1]='m';
- temp[2]='e';
- temp[3]='m';
- temp[4]='o';
- temp[5]='r';
- temp[6]='y';
- temp[7]='\0';
-
- phandle=OF_finddevice(o,temp);
-
- temp[0]='r';
- temp[1]='e';
- temp[2]='g';
- temp[3]='\0';
-
- mem_len = OF_getproplen(o,phandle, temp);
- OF_getprop(o,phandle, temp, buffer, mem_len);
- *nomr=mem_len >> 3;
-
- for (i=0; i<=mem_len/4; i++) pointer[i]=of_decode_int((const unsigned char *)&buffer[i]);
-
- temp[0]='/';
- temp[1]='c';
- temp[2]='h';
- temp[3]='o';
- temp[4]='s';
- temp[5]='e';
- temp[6]='n';
- temp[7]='\0';
-
- phandle=OF_finddevice(o,temp);
-
- temp[0]='b';
- temp[1]='o';
- temp[2]='o';
- temp[3]='t';
- temp[4]='a';
- temp[5]='r';
- temp[6]='g';
- temp[7]='s';
- temp[8]='\0';
-
- mem_len = OF_getproplen(o,phandle, temp);
- OF_getprop(o,phandle, temp, buffer, mem_len);
- if (mem_len > 128) mem_len=128;
- for (i=0; i<=mem_len/4; i++) pointer[i+33]=buffer[i];
- pointer[i+33]=0;
-
- temp[0]='/';
- temp[1]='\0';
- phandle=OF_finddevice(o,temp);
- temp[0]='b';
- temp[1]='a';
- temp[2]='n';
- temp[3]='n';
- temp[4]='e';
- temp[5]='r';
- temp[6]='-';
- temp[7]='n';
- temp[8]='a';
- temp[9]='m';
- temp[10]='e';
- temp[11]='\0';
- mem_len = OF_getproplen(o,phandle, temp);
- OF_getprop(o,phandle, temp, buffer, mem_len);
- * ((unsigned char *) &pointer[32]) = ((unsigned char *) buffer)[mem_len-2];
-}
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index e95af3f5433b..cf7588965779 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -49,6 +49,7 @@ dtb-$(CONFIG_ARCH_DAVINCI) += da850-enbw-cmc.dtb \
dtb-$(CONFIG_ARCH_DOVE) += dove-cm-a510.dtb \
dove-cubox.dtb \
dove-d2plug.dtb \
+ dove-d3plug.dtb \
dove-dove-db.dtb
dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
exynos4210-smdkv310.dtb \
@@ -142,6 +143,7 @@ dtb-$(CONFIG_ARCH_MXC) += \
imx6q-sbc6x.dtb \
imx6q-wandboard.dtb \
imx6sl-evk.dtb \
+ vf610-cosmic.dtb \
vf610-twr.dtb
dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \
imx23-olinuxino.dtb \
@@ -195,6 +197,8 @@ dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
ste-ccu8540.dtb \
ste-ccu9540.dtb
dtb-$(CONFIG_ARCH_S3C24XX) += s3c2416-smdk2416.dtb
+dtb-$(CONFIG_ARCH_S3C64XX) += s3c6410-mini6410.dtb \
+ s3c6410-smdk6410.dtb
dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \
emev2-kzm9d-reference.dtb \
r8a7740-armadillo800eva.dtb \
@@ -203,6 +207,7 @@ dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \
r8a7740-armadillo800eva-reference.dtb \
r8a7779-marzen.dtb \
r8a7779-marzen-reference.dtb \
+ r8a7791-koelsch.dtb \
r8a7790-lager.dtb \
r8a7790-lager-reference.dtb \
sh73a0-kzm9g.dtb \
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index f9c5da9c7fe1..d76ae24c9745 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -594,6 +594,12 @@
/* Filled in by U-Boot */
mac-address = [ 00 00 00 00 00 00 ];
};
+
+ phy_sel: cpsw-phy-sel@44e10650 {
+ compatible = "ti,am3352-cpsw-phy-sel";
+ reg= <0x44e10650 0x4>;
+ reg-names = "gmii-sel";
+ };
};
ocmcram: ocmcram@40300000 {
diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
index 1de2dae0fdae..534e1be80df2 100644
--- a/arch/arm/boot/dts/armada-370-xp.dtsi
+++ b/arch/arm/boot/dts/armada-370-xp.dtsi
@@ -113,6 +113,7 @@
#interrupt-cells = <1>;
#size-cells = <1>;
interrupt-controller;
+ msi-controller;
};
coherency-fabric@20200 {
@@ -176,7 +177,6 @@
i2c0: i2c@11000 {
compatible = "marvell,mv64xxx-i2c";
- reg = <0x11000 0x20>;
#address-cells = <1>;
#size-cells = <0>;
interrupts = <31>;
@@ -187,7 +187,6 @@
i2c1: i2c@11100 {
compatible = "marvell,mv64xxx-i2c";
- reg = <0x11100 0x20>;
#address-cells = <1>;
#size-cells = <0>;
interrupts = <32>;
diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi
index e134d7a90c9a..7a4b82e71aaf 100644
--- a/arch/arm/boot/dts/armada-370.dtsi
+++ b/arch/arm/boot/dts/armada-370.dtsi
@@ -44,6 +44,7 @@
#address-cells = <3>;
#size-cells = <2>;
+ msi-parent = <&mpic>;
bus-range = <0x00 0xff>;
ranges =
@@ -218,6 +219,14 @@
};
};
+ i2c0: i2c@11000 {
+ reg = <0x11000 0x20>;
+ };
+
+ i2c1: i2c@11100 {
+ reg = <0x11100 0x20>;
+ };
+
usb@50000 {
clocks = <&coreclk 0>;
};
diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
index 0358a33cba48..3f5e6121c730 100644
--- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
@@ -57,6 +57,7 @@
#address-cells = <3>;
#size-cells = <2>;
+ msi-parent = <&mpic>;
bus-range = <0x00 0xff>;
ranges =
diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
index 0e82c5062243..3e9fd1353f89 100644
--- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
@@ -58,6 +58,7 @@
#address-cells = <3>;
#size-cells = <2>;
+ msi-parent = <&mpic>;
bus-range = <0x00 0xff>;
ranges =
diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
index e82c1b80af17..31ba6d8fbadf 100644
--- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
@@ -74,6 +74,7 @@
#address-cells = <3>;
#size-cells = <2>;
+ msi-parent = <&mpic>;
bus-range = <0x00 0xff>;
ranges =
diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi
index def125c0eeaa..281c6447e872 100644
--- a/arch/arm/boot/dts/armada-xp.dtsi
+++ b/arch/arm/boot/dts/armada-xp.dtsi
@@ -70,6 +70,8 @@
timer@20300 {
compatible = "marvell,armada-xp-timer";
+ clocks = <&coreclk 2>, <&refclk>;
+ clock-names = "nbclk", "fixed";
};
coreclk: mvebu-sar@18230 {
@@ -145,6 +147,16 @@
};
};
+ i2c0: i2c@11000 {
+ compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
+ reg = <0x11000 0x100>;
+ };
+
+ i2c1: i2c@11100 {
+ compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
+ reg = <0x11100 0x100>;
+ };
+
usb@50000 {
clocks = <&gateclk 18>;
};
@@ -169,4 +181,13 @@
};
};
};
+
+ clocks {
+ /* 25 MHz reference crystal */
+ refclk: oscillator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <25000000>;
+ };
+ };
};
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index cf78ac0b04b1..e74dc15efa9d 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -190,12 +190,12 @@
AT91_PIOA 8 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* PA8 periph A */
};
- pinctrl_uart2_rts: uart2_rts-0 {
+ pinctrl_usart2_rts: usart2_rts-0 {
atmel,pins =
<AT91_PIOB 0 AT91_PERIPH_B AT91_PINCTRL_NONE>; /* PB0 periph B */
};
- pinctrl_uart2_cts: uart2_cts-0 {
+ pinctrl_usart2_cts: usart2_cts-0 {
atmel,pins =
<AT91_PIOB 1 AT91_PERIPH_B AT91_PINCTRL_NONE>; /* PB1 periph B */
};
@@ -556,6 +556,7 @@
interrupts = <12 IRQ_TYPE_LEVEL_HIGH 0>;
dmas = <&dma0 1 AT91_DMA_CFG_PER_ID(0)>;
dma-names = "rxtx";
+ pinctrl-names = "default";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
@@ -567,6 +568,7 @@
interrupts = <26 IRQ_TYPE_LEVEL_HIGH 0>;
dmas = <&dma1 1 AT91_DMA_CFG_PER_ID(0)>;
dma-names = "rxtx";
+ pinctrl-names = "default";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
diff --git a/arch/arm/boot/dts/dove-cm-a510.dts b/arch/arm/boot/dts/dove-cm-a510.dts
index 61a8062e56de..50c0d6904497 100644
--- a/arch/arm/boot/dts/dove-cm-a510.dts
+++ b/arch/arm/boot/dts/dove-cm-a510.dts
@@ -1,6 +1,6 @@
/dts-v1/;
-/include/ "dove.dtsi"
+#include "dove.dtsi"
/ {
model = "Compulab CM-A510";
diff --git a/arch/arm/boot/dts/dove-cubox.dts b/arch/arm/boot/dts/dove-cubox.dts
index 022646ef4b38..4af59b6dce0f 100644
--- a/arch/arm/boot/dts/dove-cubox.dts
+++ b/arch/arm/boot/dts/dove-cubox.dts
@@ -1,6 +1,6 @@
/dts-v1/;
-/include/ "dove.dtsi"
+#include "dove.dtsi"
/ {
model = "SolidRun CuBox";
diff --git a/arch/arm/boot/dts/dove-d2plug.dts b/arch/arm/boot/dts/dove-d2plug.dts
index e2222ce94f2f..c11d3636c8e5 100644
--- a/arch/arm/boot/dts/dove-d2plug.dts
+++ b/arch/arm/boot/dts/dove-d2plug.dts
@@ -1,6 +1,6 @@
/dts-v1/;
-/include/ "dove.dtsi"
+#include "dove.dtsi"
/ {
model = "Globalscale D2Plug";
diff --git a/arch/arm/boot/dts/dove-d3plug.dts b/arch/arm/boot/dts/dove-d3plug.dts
new file mode 100644
index 000000000000..f5f59bb5a534
--- /dev/null
+++ b/arch/arm/boot/dts/dove-d3plug.dts
@@ -0,0 +1,103 @@
+/dts-v1/;
+
+#include "dove.dtsi"
+
+/ {
+ model = "Globalscale D3Plug";
+ compatible = "globalscale,d3plug", "marvell,dove";
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x40000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200n8 earlyprintk root=/dev/mmcblk0p2 rw rootwait";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-0 = <&pmx_gpio_0 &pmx_gpio_1 &pmx_gpio_2>;
+ pinctrl-names = "default";
+
+ wlan-act {
+ label = "wlan-act";
+ gpios = <&gpio0 0 1>;
+ };
+
+ wlan-ap {
+ label = "wlan-ap";
+ gpios = <&gpio0 1 1>;
+ };
+
+ status {
+ label = "status";
+ gpios = <&gpio0 2 1>;
+ };
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb_power: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "USB Power";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-boot-on;
+ gpio = <&gpio0 8 0>;
+ pinctrl-0 = <&pmx_gpio_8>;
+ pinctrl-names = "default";
+ };
+ };
+};
+
+&uart0 { status = "okay"; };
+&sata0 { status = "okay"; };
+&i2c0 { status = "okay"; };
+
+/* Samsung M8G2F eMMC */
+&sdio0 {
+ status = "okay";
+ non-removable;
+ bus-width = <4>;
+};
+
+/* Marvell SD8787 WLAN/BT */
+&sdio1 {
+ status = "okay";
+ non-removable;
+};
+
+&spi0 {
+ status = "okay";
+
+ /* spi0.0: 2M Flash Macronix MX25L1605D */
+ spi-flash@0 {
+ compatible = "st,m25l1605d";
+ spi-max-frequency = <86000000>;
+ reg = <0>;
+ };
+};
+
+&pcie {
+ status = "okay";
+ /* Fresco Logic USB3.0 xHCI controller */
+ pcie-port@0 {
+ status = "okay";
+ reset-gpios = <&gpio0 26 1>;
+ reset-delay-us = <20000>;
+ pinctrl-0 = <&pmx_camera_gpio>;
+ pinctrl-names = "default";
+ };
+ /* Mini-PCIe slot */
+ pcie-port@1 {
+ status = "okay";
+ reset-gpios = <&gpio0 25 1>;
+ };
+};
diff --git a/arch/arm/boot/dts/dove-dove-db.dts b/arch/arm/boot/dts/dove-dove-db.dts
index e5a920beab45..bb725dca3a10 100644
--- a/arch/arm/boot/dts/dove-dove-db.dts
+++ b/arch/arm/boot/dts/dove-dove-db.dts
@@ -1,6 +1,6 @@
/dts-v1/;
-/include/ "dove.dtsi"
+#include "dove.dtsi"
/ {
model = "Marvell DB-MV88AP510-BP Development Board";
diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi
index cc279166646f..499abadf86f0 100644
--- a/arch/arm/boot/dts/dove.dtsi
+++ b/arch/arm/boot/dts/dove.dtsi
@@ -1,8 +1,11 @@
/include/ "skeleton.dtsi"
+#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
+
/ {
compatible = "marvell,dove";
model = "Marvell Armada 88AP510 SoC";
+ interrupt-parent = <&intc>;
aliases {
gpio0 = &gpio0;
@@ -27,482 +30,548 @@
marvell,tauros2-cache-features = <0>;
};
- soc@f1000000 {
- compatible = "simple-bus";
- #address-cells = <1>;
+ mbus {
+ compatible = "marvell,dove-mbus", "marvell,mbus", "simple-bus";
+ #address-cells = <2>;
#size-cells = <1>;
- interrupt-parent = <&intc>;
-
- ranges = <0xc8000000 0xc8000000 0x0100000 /* CESA SRAM 1M */
- 0xe0000000 0xe0000000 0x8000000 /* PCIe0 Mem 128M */
- 0xe8000000 0xe8000000 0x8000000 /* PCIe1 Mem 128M */
- 0xf0000000 0xf0000000 0x0100000 /* ScratchPad 1M */
- 0x00000000 0xf1000000 0x1000000 /* SB/NB regs 16M */
- 0xf2000000 0xf2000000 0x0100000 /* PCIe0 I/O 1M */
- 0xf2100000 0xf2100000 0x0100000 /* PCIe0 I/O 1M */
- 0xf8000000 0xf8000000 0x8000000>; /* BootROM 128M */
-
- timer: timer@20300 {
- compatible = "marvell,orion-timer";
- reg = <0x20300 0x20>;
- interrupt-parent = <&bridge_intc>;
- interrupts = <1>, <2>;
- clocks = <&core_clk 0>;
- };
-
- intc: main-interrupt-ctrl@20200 {
- compatible = "marvell,orion-intc";
- interrupt-controller;
- #interrupt-cells = <1>;
- reg = <0x20200 0x10>, <0x20210 0x10>;
- };
-
- bridge_intc: bridge-interrupt-ctrl@20110 {
- compatible = "marvell,orion-bridge-intc";
- interrupt-controller;
- #interrupt-cells = <1>;
- reg = <0x20110 0x8>;
- interrupts = <0>;
- marvell,#interrupts = <5>;
- };
-
- core_clk: core-clocks@d0214 {
- compatible = "marvell,dove-core-clock";
- reg = <0xd0214 0x4>;
- #clock-cells = <1>;
- };
-
- gate_clk: clock-gating-ctrl@d0038 {
- compatible = "marvell,dove-gating-clock";
- reg = <0xd0038 0x4>;
- clocks = <&core_clk 0>;
- #clock-cells = <1>;
- };
-
- thermal: thermal-diode@d001c {
- compatible = "marvell,dove-thermal";
- reg = <0xd001c 0x0c>, <0xd005c 0x08>;
- };
-
- uart0: serial@12000 {
- compatible = "ns16550a";
- reg = <0x12000 0x100>;
- reg-shift = <2>;
- interrupts = <7>;
- clocks = <&core_clk 0>;
+ controller = <&mbusc>;
+ pcie-mem-aperture = <0xe0000000 0x10000000>; /* 256M MEM space */
+ pcie-io-aperture = <0xf2000000 0x00200000>; /* 2M I/O space */
+
+ ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x0100000 /* MBUS regs 1M */
+ MBUS_ID(0xf0, 0x02) 0 0xf1800000 0x1000000 /* AXI regs 16M */
+ MBUS_ID(0x01, 0xfd) 0 0xf8000000 0x8000000 /* BootROM 128M */
+ MBUS_ID(0x03, 0x01) 0 0xc8000000 0x0100000 /* CESA SRAM 1M */
+ MBUS_ID(0x0d, 0x00) 0 0xf0000000 0x0100000>; /* PMU SRAM 1M */
+
+ pcie: pcie-controller {
+ compatible = "marvell,dove-pcie";
status = "disabled";
- };
-
- uart1: serial@12100 {
- compatible = "ns16550a";
- reg = <0x12100 0x100>;
- reg-shift = <2>;
- interrupts = <8>;
- clocks = <&core_clk 0>;
- pinctrl-0 = <&pmx_uart1>;
- pinctrl-names = "default";
- status = "disabled";
- };
-
- uart2: serial@12200 {
- compatible = "ns16550a";
- reg = <0x12000 0x100>;
- reg-shift = <2>;
- interrupts = <9>;
- clocks = <&core_clk 0>;
- status = "disabled";
- };
-
- uart3: serial@12300 {
- compatible = "ns16550a";
- reg = <0x12100 0x100>;
- reg-shift = <2>;
- interrupts = <10>;
- clocks = <&core_clk 0>;
- status = "disabled";
- };
-
- gpio0: gpio-ctrl@d0400 {
- compatible = "marvell,orion-gpio";
- #gpio-cells = <2>;
- gpio-controller;
- reg = <0xd0400 0x20>;
- ngpios = <32>;
- interrupt-controller;
- #interrupt-cells = <2>;
- interrupts = <12>, <13>, <14>, <60>;
- };
-
- gpio1: gpio-ctrl@d0420 {
- compatible = "marvell,orion-gpio";
- #gpio-cells = <2>;
- gpio-controller;
- reg = <0xd0420 0x20>;
- ngpios = <32>;
- interrupt-controller;
- #interrupt-cells = <2>;
- interrupts = <61>;
- };
-
- gpio2: gpio-ctrl@e8400 {
- compatible = "marvell,orion-gpio";
- #gpio-cells = <2>;
- gpio-controller;
- reg = <0xe8400 0x0c>;
- ngpios = <8>;
- };
-
- pinctrl: pin-ctrl@d0200 {
- compatible = "marvell,dove-pinctrl";
- reg = <0xd0200 0x10>;
- clocks = <&gate_clk 22>;
-
- pmx_gpio_0: pmx-gpio-0 {
- marvell,pins = "mpp0";
- marvell,function = "gpio";
- };
-
- pmx_gpio_1: pmx-gpio-1 {
- marvell,pins = "mpp1";
- marvell,function = "gpio";
- };
-
- pmx_gpio_2: pmx-gpio-2 {
- marvell,pins = "mpp2";
- marvell,function = "gpio";
- };
-
- pmx_gpio_3: pmx-gpio-3 {
- marvell,pins = "mpp3";
- marvell,function = "gpio";
- };
-
- pmx_gpio_4: pmx-gpio-4 {
- marvell,pins = "mpp4";
- marvell,function = "gpio";
- };
-
- pmx_gpio_5: pmx-gpio-5 {
- marvell,pins = "mpp5";
- marvell,function = "gpio";
- };
-
- pmx_gpio_6: pmx-gpio-6 {
- marvell,pins = "mpp6";
- marvell,function = "gpio";
- };
-
- pmx_gpio_7: pmx-gpio-7 {
- marvell,pins = "mpp7";
- marvell,function = "gpio";
- };
-
- pmx_gpio_8: pmx-gpio-8 {
- marvell,pins = "mpp8";
- marvell,function = "gpio";
- };
-
- pmx_gpio_9: pmx-gpio-9 {
- marvell,pins = "mpp9";
- marvell,function = "gpio";
- };
-
- pmx_gpio_10: pmx-gpio-10 {
- marvell,pins = "mpp10";
- marvell,function = "gpio";
- };
-
- pmx_gpio_11: pmx-gpio-11 {
- marvell,pins = "mpp11";
- marvell,function = "gpio";
- };
-
- pmx_gpio_12: pmx-gpio-12 {
- marvell,pins = "mpp12";
- marvell,function = "gpio";
- };
-
- pmx_gpio_13: pmx-gpio-13 {
- marvell,pins = "mpp13";
- marvell,function = "gpio";
- };
-
- pmx_gpio_14: pmx-gpio-14 {
- marvell,pins = "mpp14";
- marvell,function = "gpio";
- };
-
- pmx_gpio_15: pmx-gpio-15 {
- marvell,pins = "mpp15";
- marvell,function = "gpio";
- };
-
- pmx_gpio_16: pmx-gpio-16 {
- marvell,pins = "mpp16";
- marvell,function = "gpio";
- };
-
- pmx_gpio_17: pmx-gpio-17 {
- marvell,pins = "mpp17";
- marvell,function = "gpio";
- };
-
- pmx_gpio_18: pmx-gpio-18 {
- marvell,pins = "mpp18";
- marvell,function = "gpio";
- };
-
- pmx_gpio_19: pmx-gpio-19 {
- marvell,pins = "mpp19";
- marvell,function = "gpio";
- };
-
- pmx_gpio_20: pmx-gpio-20 {
- marvell,pins = "mpp20";
- marvell,function = "gpio";
- };
-
- pmx_gpio_21: pmx-gpio-21 {
- marvell,pins = "mpp21";
- marvell,function = "gpio";
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ msi-parent = <&intc>;
+ bus-range = <0x00 0xff>;
+
+ ranges = <0x82000000 0x0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x2000
+ 0x82000000 0x0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x2000
+ 0x82000000 0x1 0x0 MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 Mem */
+ 0x81000000 0x1 0x0 MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 I/O */
+ 0x82000000 0x2 0x0 MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 Mem */
+ 0x81000000 0x2 0x0 MBUS_ID(0x08, 0xe0) 0 1 0>; /* Port 1.0 I/O */
+
+ pcie-port@0 {
+ device_type = "pci";
+ status = "disabled";
+ assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+ reg = <0x0800 0 0 0 0>;
+ clocks = <&gate_clk 4>;
+ marvell,pcie-port = <0>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+ 0x81000000 0 0 0x81000000 0x1 0 1 0>;
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &intc 16>;
+ };
+
+ pcie-port@1 {
+ device_type = "pci";
+ status = "disabled";
+ assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
+ reg = <0x1000 0 0 0 0>;
+ clocks = <&gate_clk 5>;
+ marvell,pcie-port = <1>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+ 0x81000000 0 0 0x81000000 0x2 0 1 0>;
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &intc 18>;
};
-
- pmx_camera: pmx-camera {
- marvell,pins = "mpp_camera";
- marvell,function = "camera";
- };
-
- pmx_camera_gpio: pmx-camera-gpio {
- marvell,pins = "mpp_camera";
- marvell,function = "gpio";
- };
-
- pmx_sdio0: pmx-sdio0 {
- marvell,pins = "mpp_sdio0";
- marvell,function = "sdio0";
- };
-
- pmx_sdio0_gpio: pmx-sdio0-gpio {
- marvell,pins = "mpp_sdio0";
- marvell,function = "gpio";
- };
-
- pmx_sdio1: pmx-sdio1 {
- marvell,pins = "mpp_sdio1";
- marvell,function = "sdio1";
- };
-
- pmx_sdio1_gpio: pmx-sdio1-gpio {
- marvell,pins = "mpp_sdio1";
- marvell,function = "gpio";
- };
-
- pmx_audio1_gpio: pmx-audio1-gpio {
- marvell,pins = "mpp_audio1";
- marvell,function = "gpio";
- };
-
- pmx_spi0: pmx-spi0 {
- marvell,pins = "mpp_spi0";
- marvell,function = "spi0";
- };
-
- pmx_spi0_gpio: pmx-spi0-gpio {
- marvell,pins = "mpp_spi0";
- marvell,function = "gpio";
- };
-
- pmx_uart1: pmx-uart1 {
- marvell,pins = "mpp_uart1";
- marvell,function = "uart1";
- };
-
- pmx_uart1_gpio: pmx-uart1-gpio {
- marvell,pins = "mpp_uart1";
- marvell,function = "gpio";
- };
-
- pmx_nand: pmx-nand {
- marvell,pins = "mpp_nand";
- marvell,function = "nand";
- };
-
- pmx_nand_gpo: pmx-nand-gpo {
- marvell,pins = "mpp_nand";
- marvell,function = "gpo";
- };
- };
-
- spi0: spi-ctrl@10600 {
- compatible = "marvell,orion-spi";
- #address-cells = <1>;
- #size-cells = <0>;
- cell-index = <0>;
- interrupts = <6>;
- reg = <0x10600 0x28>;
- clocks = <&core_clk 0>;
- pinctrl-0 = <&pmx_spi0>;
- pinctrl-names = "default";
- status = "disabled";
};
- spi1: spi-ctrl@14600 {
- compatible = "marvell,orion-spi";
+ internal-regs {
+ compatible = "simple-bus";
#address-cells = <1>;
- #size-cells = <0>;
- cell-index = <1>;
- interrupts = <5>;
- reg = <0x14600 0x28>;
- clocks = <&core_clk 0>;
- status = "disabled";
- };
-
- i2c0: i2c-ctrl@11000 {
- compatible = "marvell,mv64xxx-i2c";
- reg = <0x11000 0x20>;
- #address-cells = <1>;
- #size-cells = <0>;
- interrupts = <11>;
- clock-frequency = <400000>;
- timeout-ms = <1000>;
- clocks = <&core_clk 0>;
- status = "disabled";
- };
-
- ehci0: usb-host@50000 {
- compatible = "marvell,orion-ehci";
- reg = <0x50000 0x1000>;
- interrupts = <24>;
- clocks = <&gate_clk 0>;
- status = "okay";
- };
-
- ehci1: usb-host@51000 {
- compatible = "marvell,orion-ehci";
- reg = <0x51000 0x1000>;
- interrupts = <25>;
- clocks = <&gate_clk 1>;
- status = "okay";
- };
-
- sdio0: sdio-host@92000 {
- compatible = "marvell,dove-sdhci";
- reg = <0x92000 0x100>;
- interrupts = <35>, <37>;
- clocks = <&gate_clk 8>;
- pinctrl-0 = <&pmx_sdio0>;
- pinctrl-names = "default";
- status = "disabled";
- };
-
- sdio1: sdio-host@90000 {
- compatible = "marvell,dove-sdhci";
- reg = <0x90000 0x100>;
- interrupts = <36>, <38>;
- clocks = <&gate_clk 9>;
- pinctrl-0 = <&pmx_sdio1>;
- pinctrl-names = "default";
- status = "disabled";
- };
-
- sata0: sata-host@a0000 {
- compatible = "marvell,orion-sata";
- reg = <0xa0000 0x2400>;
- interrupts = <62>;
- clocks = <&gate_clk 3>;
- nr-ports = <1>;
- status = "disabled";
- };
-
- rtc: real-time-clock@d8500 {
- compatible = "marvell,orion-rtc";
- reg = <0xd8500 0x20>;
- };
-
- crypto: crypto-engine@30000 {
- compatible = "marvell,orion-crypto";
- reg = <0x30000 0x10000>,
- <0xc8000000 0x800>;
- reg-names = "regs", "sram";
- interrupts = <31>;
- clocks = <&gate_clk 15>;
- status = "okay";
- };
-
- xor0: dma-engine@60800 {
- compatible = "marvell,orion-xor";
- reg = <0x60800 0x100
- 0x60a00 0x100>;
- clocks = <&gate_clk 23>;
- status = "okay";
-
- channel0 {
- interrupts = <39>;
- dmacap,memcpy;
- dmacap,xor;
- };
-
- channel1 {
- interrupts = <40>;
- dmacap,memset;
- dmacap,memcpy;
- dmacap,xor;
- };
- };
-
- xor1: dma-engine@60900 {
- compatible = "marvell,orion-xor";
- reg = <0x60900 0x100
- 0x60b00 0x100>;
- clocks = <&gate_clk 24>;
- status = "okay";
-
- channel0 {
- interrupts = <42>;
- dmacap,memcpy;
- dmacap,xor;
- };
-
- channel1 {
- interrupts = <43>;
- dmacap,memset;
- dmacap,memcpy;
- dmacap,xor;
- };
- };
-
- mdio: mdio-bus@72004 {
- compatible = "marvell,orion-mdio";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x72004 0x84>;
- interrupts = <30>;
- clocks = <&gate_clk 2>;
- status = "disabled";
-
- ethphy: ethernet-phy {
- device-type = "ethernet-phy";
- /* set phy address in board file */
- };
- };
-
- eth: ethernet-controller@72000 {
- compatible = "marvell,orion-eth";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x72000 0x4000>;
- clocks = <&gate_clk 2>;
- marvell,tx-checksum-limit = <1600>;
- status = "disabled";
-
- ethernet-port@0 {
- device_type = "network";
- compatible = "marvell,orion-eth-port";
- reg = <0>;
- interrupts = <29>;
- /* overwrite MAC address in bootloader */
- local-mac-address = [00 00 00 00 00 00];
- phy-handle = <&ethphy>;
+ #size-cells = <1>;
+ ranges = <0x00000000 MBUS_ID(0xf0, 0x01) 0 0x0100000 /* MBUS regs 1M */
+ 0x00800000 MBUS_ID(0xf0, 0x02) 0 0x1000000 /* AXI regs 16M */
+ 0xffffe000 MBUS_ID(0x03, 0x01) 0 0x0000800 /* CESA SRAM 2k */
+ 0xfffff000 MBUS_ID(0x0d, 0x00) 0 0x0000800>; /* PMU SRAM 2k */
+
+ mbusc: mbus-ctrl@20000 {
+ compatible = "marvell,mbus-controller";
+ reg = <0x20000 0x80>, <0x800100 0x8>;
+ };
+
+ timer: timer@20300 {
+ compatible = "marvell,orion-timer";
+ reg = <0x20300 0x20>;
+ interrupt-parent = <&bridge_intc>;
+ interrupts = <1>, <2>;
+ clocks = <&core_clk 0>;
+ };
+
+ intc: main-interrupt-ctrl@20200 {
+ compatible = "marvell,orion-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x20200 0x10>, <0x20210 0x10>;
+ };
+
+ bridge_intc: bridge-interrupt-ctrl@20110 {
+ compatible = "marvell,orion-bridge-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x20110 0x8>;
+ interrupts = <0>;
+ marvell,#interrupts = <5>;
+ };
+
+ core_clk: core-clocks@d0214 {
+ compatible = "marvell,dove-core-clock";
+ reg = <0xd0214 0x4>;
+ #clock-cells = <1>;
+ };
+
+ gate_clk: clock-gating-ctrl@d0038 {
+ compatible = "marvell,dove-gating-clock";
+ reg = <0xd0038 0x4>;
+ clocks = <&core_clk 0>;
+ #clock-cells = <1>;
+ };
+
+ thermal: thermal-diode@d001c {
+ compatible = "marvell,dove-thermal";
+ reg = <0xd001c 0x0c>, <0xd005c 0x08>;
+ };
+
+ uart0: serial@12000 {
+ compatible = "ns16550a";
+ reg = <0x12000 0x100>;
+ reg-shift = <2>;
+ interrupts = <7>;
+ clocks = <&core_clk 0>;
+ status = "disabled";
+ };
+
+ uart1: serial@12100 {
+ compatible = "ns16550a";
+ reg = <0x12100 0x100>;
+ reg-shift = <2>;
+ interrupts = <8>;
+ clocks = <&core_clk 0>;
+ pinctrl-0 = <&pmx_uart1>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ uart2: serial@12200 {
+ compatible = "ns16550a";
+ reg = <0x12000 0x100>;
+ reg-shift = <2>;
+ interrupts = <9>;
+ clocks = <&core_clk 0>;
+ status = "disabled";
+ };
+
+ uart3: serial@12300 {
+ compatible = "ns16550a";
+ reg = <0x12100 0x100>;
+ reg-shift = <2>;
+ interrupts = <10>;
+ clocks = <&core_clk 0>;
+ status = "disabled";
+ };
+
+ gpio0: gpio-ctrl@d0400 {
+ compatible = "marvell,orion-gpio";
+ #gpio-cells = <2>;
+ gpio-controller;
+ reg = <0xd0400 0x20>;
+ ngpios = <32>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <12>, <13>, <14>, <60>;
+ };
+
+ gpio1: gpio-ctrl@d0420 {
+ compatible = "marvell,orion-gpio";
+ #gpio-cells = <2>;
+ gpio-controller;
+ reg = <0xd0420 0x20>;
+ ngpios = <32>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <61>;
+ };
+
+ gpio2: gpio-ctrl@e8400 {
+ compatible = "marvell,orion-gpio";
+ #gpio-cells = <2>;
+ gpio-controller;
+ reg = <0xe8400 0x0c>;
+ ngpios = <8>;
+ };
+
+ pinctrl: pin-ctrl@d0200 {
+ compatible = "marvell,dove-pinctrl";
+ reg = <0xd0200 0x10>;
+ clocks = <&gate_clk 22>;
+
+ pmx_gpio_0: pmx-gpio-0 {
+ marvell,pins = "mpp0";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_1: pmx-gpio-1 {
+ marvell,pins = "mpp1";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_2: pmx-gpio-2 {
+ marvell,pins = "mpp2";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_3: pmx-gpio-3 {
+ marvell,pins = "mpp3";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_4: pmx-gpio-4 {
+ marvell,pins = "mpp4";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_5: pmx-gpio-5 {
+ marvell,pins = "mpp5";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_6: pmx-gpio-6 {
+ marvell,pins = "mpp6";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_7: pmx-gpio-7 {
+ marvell,pins = "mpp7";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_8: pmx-gpio-8 {
+ marvell,pins = "mpp8";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_9: pmx-gpio-9 {
+ marvell,pins = "mpp9";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_10: pmx-gpio-10 {
+ marvell,pins = "mpp10";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_11: pmx-gpio-11 {
+ marvell,pins = "mpp11";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_12: pmx-gpio-12 {
+ marvell,pins = "mpp12";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_13: pmx-gpio-13 {
+ marvell,pins = "mpp13";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_14: pmx-gpio-14 {
+ marvell,pins = "mpp14";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_15: pmx-gpio-15 {
+ marvell,pins = "mpp15";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_16: pmx-gpio-16 {
+ marvell,pins = "mpp16";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_17: pmx-gpio-17 {
+ marvell,pins = "mpp17";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_18: pmx-gpio-18 {
+ marvell,pins = "mpp18";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_19: pmx-gpio-19 {
+ marvell,pins = "mpp19";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_20: pmx-gpio-20 {
+ marvell,pins = "mpp20";
+ marvell,function = "gpio";
+ };
+
+ pmx_gpio_21: pmx-gpio-21 {
+ marvell,pins = "mpp21";
+ marvell,function = "gpio";
+ };
+
+ pmx_camera: pmx-camera {
+ marvell,pins = "mpp_camera";
+ marvell,function = "camera";
+ };
+
+ pmx_camera_gpio: pmx-camera-gpio {
+ marvell,pins = "mpp_camera";
+ marvell,function = "gpio";
+ };
+
+ pmx_sdio0: pmx-sdio0 {
+ marvell,pins = "mpp_sdio0";
+ marvell,function = "sdio0";
+ };
+
+ pmx_sdio0_gpio: pmx-sdio0-gpio {
+ marvell,pins = "mpp_sdio0";
+ marvell,function = "gpio";
+ };
+
+ pmx_sdio1: pmx-sdio1 {
+ marvell,pins = "mpp_sdio1";
+ marvell,function = "sdio1";
+ };
+
+ pmx_sdio1_gpio: pmx-sdio1-gpio {
+ marvell,pins = "mpp_sdio1";
+ marvell,function = "gpio";
+ };
+
+ pmx_audio1_gpio: pmx-audio1-gpio {
+ marvell,pins = "mpp_audio1";
+ marvell,function = "gpio";
+ };
+
+ pmx_spi0: pmx-spi0 {
+ marvell,pins = "mpp_spi0";
+ marvell,function = "spi0";
+ };
+
+ pmx_spi0_gpio: pmx-spi0-gpio {
+ marvell,pins = "mpp_spi0";
+ marvell,function = "gpio";
+ };
+
+ pmx_uart1: pmx-uart1 {
+ marvell,pins = "mpp_uart1";
+ marvell,function = "uart1";
+ };
+
+ pmx_uart1_gpio: pmx-uart1-gpio {
+ marvell,pins = "mpp_uart1";
+ marvell,function = "gpio";
+ };
+
+ pmx_nand: pmx-nand {
+ marvell,pins = "mpp_nand";
+ marvell,function = "nand";
+ };
+
+ pmx_nand_gpo: pmx-nand-gpo {
+ marvell,pins = "mpp_nand";
+ marvell,function = "gpo";
+ };
+ };
+
+ spi0: spi-ctrl@10600 {
+ compatible = "marvell,orion-spi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ interrupts = <6>;
+ reg = <0x10600 0x28>;
+ clocks = <&core_clk 0>;
+ pinctrl-0 = <&pmx_spi0>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ spi1: spi-ctrl@14600 {
+ compatible = "marvell,orion-spi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <1>;
+ interrupts = <5>;
+ reg = <0x14600 0x28>;
+ clocks = <&core_clk 0>;
+ status = "disabled";
+ };
+
+ i2c0: i2c-ctrl@11000 {
+ compatible = "marvell,mv64xxx-i2c";
+ reg = <0x11000 0x20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <11>;
+ clock-frequency = <400000>;
+ timeout-ms = <1000>;
+ clocks = <&core_clk 0>;
+ status = "disabled";
+ };
+
+ ehci0: usb-host@50000 {
+ compatible = "marvell,orion-ehci";
+ reg = <0x50000 0x1000>;
+ interrupts = <24>;
+ clocks = <&gate_clk 0>;
+ status = "okay";
+ };
+
+ ehci1: usb-host@51000 {
+ compatible = "marvell,orion-ehci";
+ reg = <0x51000 0x1000>;
+ interrupts = <25>;
+ clocks = <&gate_clk 1>;
+ status = "okay";
+ };
+
+ sdio0: sdio-host@92000 {
+ compatible = "marvell,dove-sdhci";
+ reg = <0x92000 0x100>;
+ interrupts = <35>, <37>;
+ clocks = <&gate_clk 8>;
+ pinctrl-0 = <&pmx_sdio0>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ sdio1: sdio-host@90000 {
+ compatible = "marvell,dove-sdhci";
+ reg = <0x90000 0x100>;
+ interrupts = <36>, <38>;
+ clocks = <&gate_clk 9>;
+ pinctrl-0 = <&pmx_sdio1>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ sata0: sata-host@a0000 {
+ compatible = "marvell,orion-sata";
+ reg = <0xa0000 0x2400>;
+ interrupts = <62>;
+ clocks = <&gate_clk 3>;
+ nr-ports = <1>;
+ status = "disabled";
+ };
+
+ rtc: real-time-clock@d8500 {
+ compatible = "marvell,orion-rtc";
+ reg = <0xd8500 0x20>;
+ };
+
+ crypto: crypto-engine@30000 {
+ compatible = "marvell,orion-crypto";
+ reg = <0x30000 0x10000>,
+ <0xffffe000 0x800>;
+ reg-names = "regs", "sram";
+ interrupts = <31>;
+ clocks = <&gate_clk 15>;
+ status = "okay";
+ };
+
+ xor0: dma-engine@60800 {
+ compatible = "marvell,orion-xor";
+ reg = <0x60800 0x100
+ 0x60a00 0x100>;
+ clocks = <&gate_clk 23>;
+ status = "okay";
+
+ channel0 {
+ interrupts = <39>;
+ dmacap,memcpy;
+ dmacap,xor;
+ };
+
+ channel1 {
+ interrupts = <40>;
+ dmacap,memcpy;
+ dmacap,xor;
+ };
+ };
+
+ xor1: dma-engine@60900 {
+ compatible = "marvell,orion-xor";
+ reg = <0x60900 0x100
+ 0x60b00 0x100>;
+ clocks = <&gate_clk 24>;
+ status = "okay";
+
+ channel0 {
+ interrupts = <42>;
+ dmacap,memcpy;
+ dmacap,xor;
+ };
+
+ channel1 {
+ interrupts = <43>;
+ dmacap,memcpy;
+ dmacap,xor;
+ };
+ };
+
+ mdio: mdio-bus@72004 {
+ compatible = "marvell,orion-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x72004 0x84>;
+ interrupts = <30>;
+ clocks = <&gate_clk 2>;
+ status = "disabled";
+
+ ethphy: ethernet-phy {
+ device-type = "ethernet-phy";
+ /* set phy address in board file */
+ };
+ };
+
+ eth: ethernet-ctrl@72000 {
+ compatible = "marvell,orion-eth";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x72000 0x4000>;
+ clocks = <&gate_clk 2>;
+ marvell,tx-checksum-limit = <1600>;
+ status = "disabled";
+
+ ethernet-port@0 {
+ device_type = "network";
+ compatible = "marvell,orion-eth-port";
+ reg = <0>;
+ interrupts = <29>;
+ /* overwrite MAC address in bootloader */
+ local-mac-address = [00 00 00 00 00 00];
+ phy-handle = <&ethphy>;
+ };
};
};
};
diff --git a/arch/arm/boot/dts/imx23-evk.dts b/arch/arm/boot/dts/imx23-evk.dts
index 185c7c01102a..1f026adefd45 100644
--- a/arch/arm/boot/dts/imx23-evk.dts
+++ b/arch/arm/boot/dts/imx23-evk.dts
@@ -10,7 +10,7 @@
*/
/dts-v1/;
-/include/ "imx23.dtsi"
+#include "imx23.dtsi"
/ {
model = "Freescale i.MX23 Evaluation Kit";
@@ -45,14 +45,14 @@
hog_pins_a: hog@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1123 /* MX23_PAD_LCD_RESET__GPIO_1_18 */
- 0x11d3 /* MX23_PAD_PWM3__GPIO_1_29 */
- 0x11e3 /* MX23_PAD_PWM4__GPIO_1_30 */
- 0x2010 /* MX23_PAD_SSP1_DETECT__SSP1_DETECT */
+ MX23_PAD_LCD_RESET__GPIO_1_18
+ MX23_PAD_PWM3__GPIO_1_29
+ MX23_PAD_PWM4__GPIO_1_30
+ MX23_PAD_SSP1_DETECT__SSP1_DETECT
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
};
diff --git a/arch/arm/boot/dts/imx23-olinuxino.dts b/arch/arm/boot/dts/imx23-olinuxino.dts
index fc766ae12e24..526bfdbd87f9 100644
--- a/arch/arm/boot/dts/imx23-olinuxino.dts
+++ b/arch/arm/boot/dts/imx23-olinuxino.dts
@@ -12,7 +12,7 @@
*/
/dts-v1/;
-/include/ "imx23.dtsi"
+#include "imx23.dtsi"
/ {
model = "i.MX23 Olinuxino Low Cost Board";
@@ -40,21 +40,21 @@
hog_pins_a: hog@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x0113 /* MX23_PAD_GPMI_ALE__GPIO_0_17 */
+ MX23_PAD_GPMI_ALE__GPIO_0_17
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
led_pin_gpio2_1: led_gpio2_1@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2013 /* MX23_PAD_SSP1_DETECT__GPIO_2_1 */
+ MX23_PAD_SSP1_DETECT__GPIO_2_1
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
};
diff --git a/arch/arm/boot/dts/imx23-pinfunc.h b/arch/arm/boot/dts/imx23-pinfunc.h
new file mode 100644
index 000000000000..5c0f32ca3a93
--- /dev/null
+++ b/arch/arm/boot/dts/imx23-pinfunc.h
@@ -0,0 +1,333 @@
+/*
+ * Header providing constants for i.MX23 pinctrl bindings.
+ *
+ * Copyright (C) 2013 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __DT_BINDINGS_MX23_PINCTRL_H__
+#define __DT_BINDINGS_MX23_PINCTRL_H__
+
+#include "mxs-pinfunc.h"
+
+#define MX23_PAD_GPMI_D00__GPMI_D00 0x0000
+#define MX23_PAD_GPMI_D01__GPMI_D01 0x0010
+#define MX23_PAD_GPMI_D02__GPMI_D02 0x0020
+#define MX23_PAD_GPMI_D03__GPMI_D03 0x0030
+#define MX23_PAD_GPMI_D04__GPMI_D04 0x0040
+#define MX23_PAD_GPMI_D05__GPMI_D05 0x0050
+#define MX23_PAD_GPMI_D06__GPMI_D06 0x0060
+#define MX23_PAD_GPMI_D07__GPMI_D07 0x0070
+#define MX23_PAD_GPMI_D08__GPMI_D08 0x0080
+#define MX23_PAD_GPMI_D09__GPMI_D09 0x0090
+#define MX23_PAD_GPMI_D10__GPMI_D10 0x00a0
+#define MX23_PAD_GPMI_D11__GPMI_D11 0x00b0
+#define MX23_PAD_GPMI_D12__GPMI_D12 0x00c0
+#define MX23_PAD_GPMI_D13__GPMI_D13 0x00d0
+#define MX23_PAD_GPMI_D14__GPMI_D14 0x00e0
+#define MX23_PAD_GPMI_D15__GPMI_D15 0x00f0
+#define MX23_PAD_GPMI_CLE__GPMI_CLE 0x0100
+#define MX23_PAD_GPMI_ALE__GPMI_ALE 0x0110
+#define MX23_PAD_GPMI_CE2N__GPMI_CE2N 0x0120
+#define MX23_PAD_GPMI_RDY0__GPMI_RDY0 0x0130
+#define MX23_PAD_GPMI_RDY1__GPMI_RDY1 0x0140
+#define MX23_PAD_GPMI_RDY2__GPMI_RDY2 0x0150
+#define MX23_PAD_GPMI_RDY3__GPMI_RDY3 0x0160
+#define MX23_PAD_GPMI_WPN__GPMI_WPN 0x0170
+#define MX23_PAD_GPMI_WRN__GPMI_WRN 0x0180
+#define MX23_PAD_GPMI_RDN__GPMI_RDN 0x0190
+#define MX23_PAD_AUART1_CTS__AUART1_CTS 0x01a0
+#define MX23_PAD_AUART1_RTS__AUART1_RTS 0x01b0
+#define MX23_PAD_AUART1_RX__AUART1_RX 0x01c0
+#define MX23_PAD_AUART1_TX__AUART1_TX 0x01d0
+#define MX23_PAD_I2C_SCL__I2C_SCL 0x01e0
+#define MX23_PAD_I2C_SDA__I2C_SDA 0x01f0
+#define MX23_PAD_LCD_D00__LCD_D00 0x1000
+#define MX23_PAD_LCD_D01__LCD_D01 0x1010
+#define MX23_PAD_LCD_D02__LCD_D02 0x1020
+#define MX23_PAD_LCD_D03__LCD_D03 0x1030
+#define MX23_PAD_LCD_D04__LCD_D04 0x1040
+#define MX23_PAD_LCD_D05__LCD_D05 0x1050
+#define MX23_PAD_LCD_D06__LCD_D06 0x1060
+#define MX23_PAD_LCD_D07__LCD_D07 0x1070
+#define MX23_PAD_LCD_D08__LCD_D08 0x1080
+#define MX23_PAD_LCD_D09__LCD_D09 0x1090
+#define MX23_PAD_LCD_D10__LCD_D10 0x10a0
+#define MX23_PAD_LCD_D11__LCD_D11 0x10b0
+#define MX23_PAD_LCD_D12__LCD_D12 0x10c0
+#define MX23_PAD_LCD_D13__LCD_D13 0x10d0
+#define MX23_PAD_LCD_D14__LCD_D14 0x10e0
+#define MX23_PAD_LCD_D15__LCD_D15 0x10f0
+#define MX23_PAD_LCD_D16__LCD_D16 0x1100
+#define MX23_PAD_LCD_D17__LCD_D17 0x1110
+#define MX23_PAD_LCD_RESET__LCD_RESET 0x1120
+#define MX23_PAD_LCD_RS__LCD_RS 0x1130
+#define MX23_PAD_LCD_WR__LCD_WR 0x1140
+#define MX23_PAD_LCD_CS__LCD_CS 0x1150
+#define MX23_PAD_LCD_DOTCK__LCD_DOTCK 0x1160
+#define MX23_PAD_LCD_ENABLE__LCD_ENABLE 0x1170
+#define MX23_PAD_LCD_HSYNC__LCD_HSYNC 0x1180
+#define MX23_PAD_LCD_VSYNC__LCD_VSYNC 0x1190
+#define MX23_PAD_PWM0__PWM0 0x11a0
+#define MX23_PAD_PWM1__PWM1 0x11b0
+#define MX23_PAD_PWM2__PWM2 0x11c0
+#define MX23_PAD_PWM3__PWM3 0x11d0
+#define MX23_PAD_PWM4__PWM4 0x11e0
+#define MX23_PAD_SSP1_CMD__SSP1_CMD 0x2000
+#define MX23_PAD_SSP1_DETECT__SSP1_DETECT 0x2010
+#define MX23_PAD_SSP1_DATA0__SSP1_DATA0 0x2020
+#define MX23_PAD_SSP1_DATA1__SSP1_DATA1 0x2030
+#define MX23_PAD_SSP1_DATA2__SSP1_DATA2 0x2040
+#define MX23_PAD_SSP1_DATA3__SSP1_DATA3 0x2050
+#define MX23_PAD_SSP1_SCK__SSP1_SCK 0x2060
+#define MX23_PAD_ROTARYA__ROTARYA 0x2070
+#define MX23_PAD_ROTARYB__ROTARYB 0x2080
+#define MX23_PAD_EMI_A00__EMI_A00 0x2090
+#define MX23_PAD_EMI_A01__EMI_A01 0x20a0
+#define MX23_PAD_EMI_A02__EMI_A02 0x20b0
+#define MX23_PAD_EMI_A03__EMI_A03 0x20c0
+#define MX23_PAD_EMI_A04__EMI_A04 0x20d0
+#define MX23_PAD_EMI_A05__EMI_A05 0x20e0
+#define MX23_PAD_EMI_A06__EMI_A06 0x20f0
+#define MX23_PAD_EMI_A07__EMI_A07 0x2100
+#define MX23_PAD_EMI_A08__EMI_A08 0x2110
+#define MX23_PAD_EMI_A09__EMI_A09 0x2120
+#define MX23_PAD_EMI_A10__EMI_A10 0x2130
+#define MX23_PAD_EMI_A11__EMI_A11 0x2140
+#define MX23_PAD_EMI_A12__EMI_A12 0x2150
+#define MX23_PAD_EMI_BA0__EMI_BA0 0x2160
+#define MX23_PAD_EMI_BA1__EMI_BA1 0x2170
+#define MX23_PAD_EMI_CASN__EMI_CASN 0x2180
+#define MX23_PAD_EMI_CE0N__EMI_CE0N 0x2190
+#define MX23_PAD_EMI_CE1N__EMI_CE1N 0x21a0
+#define MX23_PAD_GPMI_CE1N__GPMI_CE1N 0x21b0
+#define MX23_PAD_GPMI_CE0N__GPMI_CE0N 0x21c0
+#define MX23_PAD_EMI_CKE__EMI_CKE 0x21d0
+#define MX23_PAD_EMI_RASN__EMI_RASN 0x21e0
+#define MX23_PAD_EMI_WEN__EMI_WEN 0x21f0
+#define MX23_PAD_EMI_D00__EMI_D00 0x3000
+#define MX23_PAD_EMI_D01__EMI_D01 0x3010
+#define MX23_PAD_EMI_D02__EMI_D02 0x3020
+#define MX23_PAD_EMI_D03__EMI_D03 0x3030
+#define MX23_PAD_EMI_D04__EMI_D04 0x3040
+#define MX23_PAD_EMI_D05__EMI_D05 0x3050
+#define MX23_PAD_EMI_D06__EMI_D06 0x3060
+#define MX23_PAD_EMI_D07__EMI_D07 0x3070
+#define MX23_PAD_EMI_D08__EMI_D08 0x3080
+#define MX23_PAD_EMI_D09__EMI_D09 0x3090
+#define MX23_PAD_EMI_D10__EMI_D10 0x30a0
+#define MX23_PAD_EMI_D11__EMI_D11 0x30b0
+#define MX23_PAD_EMI_D12__EMI_D12 0x30c0
+#define MX23_PAD_EMI_D13__EMI_D13 0x30d0
+#define MX23_PAD_EMI_D14__EMI_D14 0x30e0
+#define MX23_PAD_EMI_D15__EMI_D15 0x30f0
+#define MX23_PAD_EMI_DQM0__EMI_DQM0 0x3100
+#define MX23_PAD_EMI_DQM1__EMI_DQM1 0x3110
+#define MX23_PAD_EMI_DQS0__EMI_DQS0 0x3120
+#define MX23_PAD_EMI_DQS1__EMI_DQS1 0x3130
+#define MX23_PAD_EMI_CLK__EMI_CLK 0x3140
+#define MX23_PAD_EMI_CLKN__EMI_CLKN 0x3150
+#define MX23_PAD_GPMI_D00__LCD_D8 0x0001
+#define MX23_PAD_GPMI_D01__LCD_D9 0x0011
+#define MX23_PAD_GPMI_D02__LCD_D10 0x0021
+#define MX23_PAD_GPMI_D03__LCD_D11 0x0031
+#define MX23_PAD_GPMI_D04__LCD_D12 0x0041
+#define MX23_PAD_GPMI_D05__LCD_D13 0x0051
+#define MX23_PAD_GPMI_D06__LCD_D14 0x0061
+#define MX23_PAD_GPMI_D07__LCD_D15 0x0071
+#define MX23_PAD_GPMI_D08__LCD_D18 0x0081
+#define MX23_PAD_GPMI_D09__LCD_D19 0x0091
+#define MX23_PAD_GPMI_D10__LCD_D20 0x00a1
+#define MX23_PAD_GPMI_D11__LCD_D21 0x00b1
+#define MX23_PAD_GPMI_D12__LCD_D22 0x00c1
+#define MX23_PAD_GPMI_D13__LCD_D23 0x00d1
+#define MX23_PAD_GPMI_D14__AUART2_RX 0x00e1
+#define MX23_PAD_GPMI_D15__AUART2_TX 0x00f1
+#define MX23_PAD_GPMI_CLE__LCD_D16 0x0101
+#define MX23_PAD_GPMI_ALE__LCD_D17 0x0111
+#define MX23_PAD_GPMI_CE2N__ATA_A2 0x0121
+#define MX23_PAD_AUART1_RTS__IR_CLK 0x01b1
+#define MX23_PAD_AUART1_RX__IR_RX 0x01c1
+#define MX23_PAD_AUART1_TX__IR_TX 0x01d1
+#define MX23_PAD_I2C_SCL__GPMI_RDY2 0x01e1
+#define MX23_PAD_I2C_SDA__GPMI_CE2N 0x01f1
+#define MX23_PAD_LCD_D00__ETM_DA8 0x1001
+#define MX23_PAD_LCD_D01__ETM_DA9 0x1011
+#define MX23_PAD_LCD_D02__ETM_DA10 0x1021
+#define MX23_PAD_LCD_D03__ETM_DA11 0x1031
+#define MX23_PAD_LCD_D04__ETM_DA12 0x1041
+#define MX23_PAD_LCD_D05__ETM_DA13 0x1051
+#define MX23_PAD_LCD_D06__ETM_DA14 0x1061
+#define MX23_PAD_LCD_D07__ETM_DA15 0x1071
+#define MX23_PAD_LCD_D08__ETM_DA0 0x1081
+#define MX23_PAD_LCD_D09__ETM_DA1 0x1091
+#define MX23_PAD_LCD_D10__ETM_DA2 0x10a1
+#define MX23_PAD_LCD_D11__ETM_DA3 0x10b1
+#define MX23_PAD_LCD_D12__ETM_DA4 0x10c1
+#define MX23_PAD_LCD_D13__ETM_DA5 0x10d1
+#define MX23_PAD_LCD_D14__ETM_DA6 0x10e1
+#define MX23_PAD_LCD_D15__ETM_DA7 0x10f1
+#define MX23_PAD_LCD_RESET__ETM_TCTL 0x1121
+#define MX23_PAD_LCD_RS__ETM_TCLK 0x1131
+#define MX23_PAD_LCD_DOTCK__GPMI_RDY3 0x1161
+#define MX23_PAD_LCD_ENABLE__I2C_SCL 0x1171
+#define MX23_PAD_LCD_HSYNC__I2C_SDA 0x1181
+#define MX23_PAD_LCD_VSYNC__LCD_BUSY 0x1191
+#define MX23_PAD_PWM0__ROTARYA 0x11a1
+#define MX23_PAD_PWM1__ROTARYB 0x11b1
+#define MX23_PAD_PWM2__GPMI_RDY3 0x11c1
+#define MX23_PAD_PWM3__ETM_TCTL 0x11d1
+#define MX23_PAD_PWM4__ETM_TCLK 0x11e1
+#define MX23_PAD_SSP1_DETECT__GPMI_CE3N 0x2011
+#define MX23_PAD_SSP1_DATA1__I2C_SCL 0x2031
+#define MX23_PAD_SSP1_DATA2__I2C_SDA 0x2041
+#define MX23_PAD_ROTARYA__AUART2_RTS 0x2071
+#define MX23_PAD_ROTARYB__AUART2_CTS 0x2081
+#define MX23_PAD_GPMI_D00__SSP2_DATA0 0x0002
+#define MX23_PAD_GPMI_D01__SSP2_DATA1 0x0012
+#define MX23_PAD_GPMI_D02__SSP2_DATA2 0x0022
+#define MX23_PAD_GPMI_D03__SSP2_DATA3 0x0032
+#define MX23_PAD_GPMI_D04__SSP2_DATA4 0x0042
+#define MX23_PAD_GPMI_D05__SSP2_DATA5 0x0052
+#define MX23_PAD_GPMI_D06__SSP2_DATA6 0x0062
+#define MX23_PAD_GPMI_D07__SSP2_DATA7 0x0072
+#define MX23_PAD_GPMI_D08__SSP1_DATA4 0x0082
+#define MX23_PAD_GPMI_D09__SSP1_DATA5 0x0092
+#define MX23_PAD_GPMI_D10__SSP1_DATA6 0x00a2
+#define MX23_PAD_GPMI_D11__SSP1_DATA7 0x00b2
+#define MX23_PAD_GPMI_D15__GPMI_CE3N 0x00f2
+#define MX23_PAD_GPMI_RDY0__SSP2_DETECT 0x0132
+#define MX23_PAD_GPMI_RDY1__SSP2_CMD 0x0142
+#define MX23_PAD_GPMI_WRN__SSP2_SCK 0x0182
+#define MX23_PAD_AUART1_CTS__SSP1_DATA4 0x01a2
+#define MX23_PAD_AUART1_RTS__SSP1_DATA5 0x01b2
+#define MX23_PAD_AUART1_RX__SSP1_DATA6 0x01c2
+#define MX23_PAD_AUART1_TX__SSP1_DATA7 0x01d2
+#define MX23_PAD_I2C_SCL__AUART1_TX 0x01e2
+#define MX23_PAD_I2C_SDA__AUART1_RX 0x01f2
+#define MX23_PAD_LCD_D08__SAIF2_SDATA0 0x1082
+#define MX23_PAD_LCD_D09__SAIF1_SDATA0 0x1092
+#define MX23_PAD_LCD_D10__SAIF_MCLK_BITCLK 0x10a2
+#define MX23_PAD_LCD_D11__SAIF_LRCLK 0x10b2
+#define MX23_PAD_LCD_D12__SAIF2_SDATA1 0x10c2
+#define MX23_PAD_LCD_D13__SAIF2_SDATA2 0x10d2
+#define MX23_PAD_LCD_D14__SAIF1_SDATA2 0x10e2
+#define MX23_PAD_LCD_D15__SAIF1_SDATA1 0x10f2
+#define MX23_PAD_LCD_D16__SAIF_ALT_BITCLK 0x1102
+#define MX23_PAD_LCD_RESET__GPMI_CE3N 0x1122
+#define MX23_PAD_PWM0__DUART_RX 0x11a2
+#define MX23_PAD_PWM1__DUART_TX 0x11b2
+#define MX23_PAD_PWM3__AUART1_CTS 0x11d2
+#define MX23_PAD_PWM4__AUART1_RTS 0x11e2
+#define MX23_PAD_SSP1_CMD__JTAG_TDO 0x2002
+#define MX23_PAD_SSP1_DETECT__USB_OTG_ID 0x2012
+#define MX23_PAD_SSP1_DATA0__JTAG_TDI 0x2022
+#define MX23_PAD_SSP1_DATA1__JTAG_TCLK 0x2032
+#define MX23_PAD_SSP1_DATA2__JTAG_RTCK 0x2042
+#define MX23_PAD_SSP1_DATA3__JTAG_TMS 0x2052
+#define MX23_PAD_SSP1_SCK__JTAG_TRST 0x2062
+#define MX23_PAD_ROTARYA__SPDIF 0x2072
+#define MX23_PAD_ROTARYB__GPMI_CE3N 0x2082
+#define MX23_PAD_GPMI_D00__GPIO_0_0 0x0003
+#define MX23_PAD_GPMI_D01__GPIO_0_1 0x0013
+#define MX23_PAD_GPMI_D02__GPIO_0_2 0x0023
+#define MX23_PAD_GPMI_D03__GPIO_0_3 0x0033
+#define MX23_PAD_GPMI_D04__GPIO_0_4 0x0043
+#define MX23_PAD_GPMI_D05__GPIO_0_5 0x0053
+#define MX23_PAD_GPMI_D06__GPIO_0_6 0x0063
+#define MX23_PAD_GPMI_D07__GPIO_0_7 0x0073
+#define MX23_PAD_GPMI_D08__GPIO_0_8 0x0083
+#define MX23_PAD_GPMI_D09__GPIO_0_9 0x0093
+#define MX23_PAD_GPMI_D10__GPIO_0_10 0x00a3
+#define MX23_PAD_GPMI_D11__GPIO_0_11 0x00b3
+#define MX23_PAD_GPMI_D12__GPIO_0_12 0x00c3
+#define MX23_PAD_GPMI_D13__GPIO_0_13 0x00d3
+#define MX23_PAD_GPMI_D14__GPIO_0_14 0x00e3
+#define MX23_PAD_GPMI_D15__GPIO_0_15 0x00f3
+#define MX23_PAD_GPMI_CLE__GPIO_0_16 0x0103
+#define MX23_PAD_GPMI_ALE__GPIO_0_17 0x0113
+#define MX23_PAD_GPMI_CE2N__GPIO_0_18 0x0123
+#define MX23_PAD_GPMI_RDY0__GPIO_0_19 0x0133
+#define MX23_PAD_GPMI_RDY1__GPIO_0_20 0x0143
+#define MX23_PAD_GPMI_RDY2__GPIO_0_21 0x0153
+#define MX23_PAD_GPMI_RDY3__GPIO_0_22 0x0163
+#define MX23_PAD_GPMI_WPN__GPIO_0_23 0x0173
+#define MX23_PAD_GPMI_WRN__GPIO_0_24 0x0183
+#define MX23_PAD_GPMI_RDN__GPIO_0_25 0x0193
+#define MX23_PAD_AUART1_CTS__GPIO_0_26 0x01a3
+#define MX23_PAD_AUART1_RTS__GPIO_0_27 0x01b3
+#define MX23_PAD_AUART1_RX__GPIO_0_28 0x01c3
+#define MX23_PAD_AUART1_TX__GPIO_0_29 0x01d3
+#define MX23_PAD_I2C_SCL__GPIO_0_30 0x01e3
+#define MX23_PAD_I2C_SDA__GPIO_0_31 0x01f3
+#define MX23_PAD_LCD_D00__GPIO_1_0 0x1003
+#define MX23_PAD_LCD_D01__GPIO_1_1 0x1013
+#define MX23_PAD_LCD_D02__GPIO_1_2 0x1023
+#define MX23_PAD_LCD_D03__GPIO_1_3 0x1033
+#define MX23_PAD_LCD_D04__GPIO_1_4 0x1043
+#define MX23_PAD_LCD_D05__GPIO_1_5 0x1053
+#define MX23_PAD_LCD_D06__GPIO_1_6 0x1063
+#define MX23_PAD_LCD_D07__GPIO_1_7 0x1073
+#define MX23_PAD_LCD_D08__GPIO_1_8 0x1083
+#define MX23_PAD_LCD_D09__GPIO_1_9 0x1093
+#define MX23_PAD_LCD_D10__GPIO_1_10 0x10a3
+#define MX23_PAD_LCD_D11__GPIO_1_11 0x10b3
+#define MX23_PAD_LCD_D12__GPIO_1_12 0x10c3
+#define MX23_PAD_LCD_D13__GPIO_1_13 0x10d3
+#define MX23_PAD_LCD_D14__GPIO_1_14 0x10e3
+#define MX23_PAD_LCD_D15__GPIO_1_15 0x10f3
+#define MX23_PAD_LCD_D16__GPIO_1_16 0x1103
+#define MX23_PAD_LCD_D17__GPIO_1_17 0x1113
+#define MX23_PAD_LCD_RESET__GPIO_1_18 0x1123
+#define MX23_PAD_LCD_RS__GPIO_1_19 0x1133
+#define MX23_PAD_LCD_WR__GPIO_1_20 0x1143
+#define MX23_PAD_LCD_CS__GPIO_1_21 0x1153
+#define MX23_PAD_LCD_DOTCK__GPIO_1_22 0x1163
+#define MX23_PAD_LCD_ENABLE__GPIO_1_23 0x1173
+#define MX23_PAD_LCD_HSYNC__GPIO_1_24 0x1183
+#define MX23_PAD_LCD_VSYNC__GPIO_1_25 0x1193
+#define MX23_PAD_PWM0__GPIO_1_26 0x11a3
+#define MX23_PAD_PWM1__GPIO_1_27 0x11b3
+#define MX23_PAD_PWM2__GPIO_1_28 0x11c3
+#define MX23_PAD_PWM3__GPIO_1_29 0x11d3
+#define MX23_PAD_PWM4__GPIO_1_30 0x11e3
+#define MX23_PAD_SSP1_CMD__GPIO_2_0 0x2003
+#define MX23_PAD_SSP1_DETECT__GPIO_2_1 0x2013
+#define MX23_PAD_SSP1_DATA0__GPIO_2_2 0x2023
+#define MX23_PAD_SSP1_DATA1__GPIO_2_3 0x2033
+#define MX23_PAD_SSP1_DATA2__GPIO_2_4 0x2043
+#define MX23_PAD_SSP1_DATA3__GPIO_2_5 0x2053
+#define MX23_PAD_SSP1_SCK__GPIO_2_6 0x2063
+#define MX23_PAD_ROTARYA__GPIO_2_7 0x2073
+#define MX23_PAD_ROTARYB__GPIO_2_8 0x2083
+#define MX23_PAD_EMI_A00__GPIO_2_9 0x2093
+#define MX23_PAD_EMI_A01__GPIO_2_10 0x20a3
+#define MX23_PAD_EMI_A02__GPIO_2_11 0x20b3
+#define MX23_PAD_EMI_A03__GPIO_2_12 0x20c3
+#define MX23_PAD_EMI_A04__GPIO_2_13 0x20d3
+#define MX23_PAD_EMI_A05__GPIO_2_14 0x20e3
+#define MX23_PAD_EMI_A06__GPIO_2_15 0x20f3
+#define MX23_PAD_EMI_A07__GPIO_2_16 0x2103
+#define MX23_PAD_EMI_A08__GPIO_2_17 0x2113
+#define MX23_PAD_EMI_A09__GPIO_2_18 0x2123
+#define MX23_PAD_EMI_A10__GPIO_2_19 0x2133
+#define MX23_PAD_EMI_A11__GPIO_2_20 0x2143
+#define MX23_PAD_EMI_A12__GPIO_2_21 0x2153
+#define MX23_PAD_EMI_BA0__GPIO_2_22 0x2163
+#define MX23_PAD_EMI_BA1__GPIO_2_23 0x2173
+#define MX23_PAD_EMI_CASN__GPIO_2_24 0x2183
+#define MX23_PAD_EMI_CE0N__GPIO_2_25 0x2193
+#define MX23_PAD_EMI_CE1N__GPIO_2_26 0x21a3
+#define MX23_PAD_GPMI_CE1N__GPIO_2_27 0x21b3
+#define MX23_PAD_GPMI_CE0N__GPIO_2_28 0x21c3
+#define MX23_PAD_EMI_CKE__GPIO_2_29 0x21d3
+#define MX23_PAD_EMI_RASN__GPIO_2_30 0x21e3
+#define MX23_PAD_EMI_WEN__GPIO_2_31 0x21f3
+
+#endif /* __DT_BINDINGS_MX23_PINCTRL_H__ */
diff --git a/arch/arm/boot/dts/imx23-stmp378x_devb.dts b/arch/arm/boot/dts/imx23-stmp378x_devb.dts
index 85c3864b6a56..cb64e2b191ea 100644
--- a/arch/arm/boot/dts/imx23-stmp378x_devb.dts
+++ b/arch/arm/boot/dts/imx23-stmp378x_devb.dts
@@ -10,7 +10,7 @@
*/
/dts-v1/;
-/include/ "imx23.dtsi"
+#include "imx23.dtsi"
/ {
model = "Freescale STMP378x Development Board";
@@ -39,12 +39,12 @@
hog_pins_a: hog@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x11d3 /* MX23_PAD_PWM3__GPIO_1_29 */
- 0x11e3 /* MX23_PAD_PWM4__GPIO_1_30 */
+ MX23_PAD_PWM3__GPIO_1_29
+ MX23_PAD_PWM4__GPIO_1_30
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
};
};
diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi
index 28b5ce289662..87faa6e8b6e7 100644
--- a/arch/arm/boot/dts/imx23.dtsi
+++ b/arch/arm/boot/dts/imx23.dtsi
@@ -9,7 +9,8 @@
* http://www.gnu.org/copyleft/gpl.html
*/
-/include/ "skeleton.dtsi"
+#include "skeleton.dtsi"
+#include "imx23-pinfunc.h"
/ {
interrupt-parent = <&icoll>;
@@ -137,174 +138,174 @@
duart_pins_a: duart@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x11a2 /* MX23_PAD_PWM0__DUART_RX */
- 0x11b2 /* MX23_PAD_PWM1__DUART_TX */
+ MX23_PAD_PWM0__DUART_RX
+ MX23_PAD_PWM1__DUART_TX
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
auart0_pins_a: auart0@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x01c0 /* MX23_PAD_AUART1_RX__AUART1_RX */
- 0x01d0 /* MX23_PAD_AUART1_TX__AUART1_TX */
- 0x01a0 /* MX23_PAD_AUART1_CTS__AUART1_CTS */
- 0x01b0 /* MX23_PAD_AUART1_RTS__AUART1_RTS */
+ MX23_PAD_AUART1_RX__AUART1_RX
+ MX23_PAD_AUART1_TX__AUART1_TX
+ MX23_PAD_AUART1_CTS__AUART1_CTS
+ MX23_PAD_AUART1_RTS__AUART1_RTS
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
auart0_2pins_a: auart0-2pins@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x01e2 /* MX23_PAD_I2C_SCL__AUART1_TX */
- 0x01f2 /* MX23_PAD_I2C_SDA__AUART1_RX */
+ MX23_PAD_I2C_SCL__AUART1_TX
+ MX23_PAD_I2C_SDA__AUART1_RX
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
gpmi_pins_a: gpmi-nand@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x0000 /* MX23_PAD_GPMI_D00__GPMI_D00 */
- 0x0010 /* MX23_PAD_GPMI_D01__GPMI_D01 */
- 0x0020 /* MX23_PAD_GPMI_D02__GPMI_D02 */
- 0x0030 /* MX23_PAD_GPMI_D03__GPMI_D03 */
- 0x0040 /* MX23_PAD_GPMI_D04__GPMI_D04 */
- 0x0050 /* MX23_PAD_GPMI_D05__GPMI_D05 */
- 0x0060 /* MX23_PAD_GPMI_D06__GPMI_D06 */
- 0x0070 /* MX23_PAD_GPMI_D07__GPMI_D07 */
- 0x0100 /* MX23_PAD_GPMI_CLE__GPMI_CLE */
- 0x0110 /* MX23_PAD_GPMI_ALE__GPMI_ALE */
- 0x0130 /* MX23_PAD_GPMI_RDY0__GPMI_RDY0 */
- 0x0140 /* MX23_PAD_GPMI_RDY1__GPMI_RDY1 */
- 0x0170 /* MX23_PAD_GPMI_WPN__GPMI_WPN */
- 0x0180 /* MX23_PAD_GPMI_WRN__GPMI_WRN */
- 0x0190 /* MX23_PAD_GPMI_RDN__GPMI_RDN */
- 0x21b0 /* MX23_PAD_GPMI_CE1N__GPMI_CE1N */
- 0x21c0 /* MX23_PAD_GPMI_CE0N__GPMI_CE0N */
+ MX23_PAD_GPMI_D00__GPMI_D00
+ MX23_PAD_GPMI_D01__GPMI_D01
+ MX23_PAD_GPMI_D02__GPMI_D02
+ MX23_PAD_GPMI_D03__GPMI_D03
+ MX23_PAD_GPMI_D04__GPMI_D04
+ MX23_PAD_GPMI_D05__GPMI_D05
+ MX23_PAD_GPMI_D06__GPMI_D06
+ MX23_PAD_GPMI_D07__GPMI_D07
+ MX23_PAD_GPMI_CLE__GPMI_CLE
+ MX23_PAD_GPMI_ALE__GPMI_ALE
+ MX23_PAD_GPMI_RDY0__GPMI_RDY0
+ MX23_PAD_GPMI_RDY1__GPMI_RDY1
+ MX23_PAD_GPMI_WPN__GPMI_WPN
+ MX23_PAD_GPMI_WRN__GPMI_WRN
+ MX23_PAD_GPMI_RDN__GPMI_RDN
+ MX23_PAD_GPMI_CE1N__GPMI_CE1N
+ MX23_PAD_GPMI_CE0N__GPMI_CE0N
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
gpmi_pins_fixup: gpmi-pins-fixup {
fsl,pinmux-ids = <
- 0x0170 /* MX23_PAD_GPMI_WPN__GPMI_WPN */
- 0x0180 /* MX23_PAD_GPMI_WRN__GPMI_WRN */
- 0x0190 /* MX23_PAD_GPMI_RDN__GPMI_RDN */
+ MX23_PAD_GPMI_WPN__GPMI_WPN
+ MX23_PAD_GPMI_WRN__GPMI_WRN
+ MX23_PAD_GPMI_RDN__GPMI_RDN
>;
- fsl,drive-strength = <2>;
+ fsl,drive-strength = <MXS_DRIVE_12mA>;
};
mmc0_4bit_pins_a: mmc0-4bit@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2020 /* MX23_PAD_SSP1_DATA0__SSP1_DATA0 */
- 0x2030 /* MX23_PAD_SSP1_DATA1__SSP1_DATA1 */
- 0x2040 /* MX23_PAD_SSP1_DATA2__SSP1_DATA2 */
- 0x2050 /* MX23_PAD_SSP1_DATA3__SSP1_DATA3 */
- 0x2000 /* MX23_PAD_SSP1_CMD__SSP1_CMD */
- 0x2060 /* MX23_PAD_SSP1_SCK__SSP1_SCK */
+ MX23_PAD_SSP1_DATA0__SSP1_DATA0
+ MX23_PAD_SSP1_DATA1__SSP1_DATA1
+ MX23_PAD_SSP1_DATA2__SSP1_DATA2
+ MX23_PAD_SSP1_DATA3__SSP1_DATA3
+ MX23_PAD_SSP1_CMD__SSP1_CMD
+ MX23_PAD_SSP1_SCK__SSP1_SCK
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
mmc0_8bit_pins_a: mmc0-8bit@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2020 /* MX23_PAD_SSP1_DATA0__SSP1_DATA0 */
- 0x2030 /* MX23_PAD_SSP1_DATA1__SSP1_DATA1 */
- 0x2040 /* MX23_PAD_SSP1_DATA2__SSP1_DATA2 */
- 0x2050 /* MX23_PAD_SSP1_DATA3__SSP1_DATA3 */
- 0x0082 /* MX23_PAD_GPMI_D08__SSP1_DATA4 */
- 0x0092 /* MX23_PAD_GPMI_D09__SSP1_DATA5 */
- 0x00a2 /* MX23_PAD_GPMI_D10__SSP1_DATA6 */
- 0x00b2 /* MX23_PAD_GPMI_D11__SSP1_DATA7 */
- 0x2000 /* MX23_PAD_SSP1_CMD__SSP1_CMD */
- 0x2010 /* MX23_PAD_SSP1_DETECT__SSP1_DETECT */
- 0x2060 /* MX23_PAD_SSP1_SCK__SSP1_SCK */
+ MX23_PAD_SSP1_DATA0__SSP1_DATA0
+ MX23_PAD_SSP1_DATA1__SSP1_DATA1
+ MX23_PAD_SSP1_DATA2__SSP1_DATA2
+ MX23_PAD_SSP1_DATA3__SSP1_DATA3
+ MX23_PAD_GPMI_D08__SSP1_DATA4
+ MX23_PAD_GPMI_D09__SSP1_DATA5
+ MX23_PAD_GPMI_D10__SSP1_DATA6
+ MX23_PAD_GPMI_D11__SSP1_DATA7
+ MX23_PAD_SSP1_CMD__SSP1_CMD
+ MX23_PAD_SSP1_DETECT__SSP1_DETECT
+ MX23_PAD_SSP1_SCK__SSP1_SCK
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
mmc0_pins_fixup: mmc0-pins-fixup {
fsl,pinmux-ids = <
- 0x2010 /* MX23_PAD_SSP1_DETECT__SSP1_DETECT */
- 0x2060 /* MX23_PAD_SSP1_SCK__SSP1_SCK */
+ MX23_PAD_SSP1_DETECT__SSP1_DETECT
+ MX23_PAD_SSP1_SCK__SSP1_SCK
>;
- fsl,pull-up = <0>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
pwm2_pins_a: pwm2@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x11c0 /* MX23_PAD_PWM2__PWM2 */
+ MX23_PAD_PWM2__PWM2
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
lcdif_24bit_pins_a: lcdif-24bit@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1000 /* MX23_PAD_LCD_D00__LCD_D0 */
- 0x1010 /* MX23_PAD_LCD_D01__LCD_D1 */
- 0x1020 /* MX23_PAD_LCD_D02__LCD_D2 */
- 0x1030 /* MX23_PAD_LCD_D03__LCD_D3 */
- 0x1040 /* MX23_PAD_LCD_D04__LCD_D4 */
- 0x1050 /* MX23_PAD_LCD_D05__LCD_D5 */
- 0x1060 /* MX23_PAD_LCD_D06__LCD_D6 */
- 0x1070 /* MX23_PAD_LCD_D07__LCD_D7 */
- 0x1080 /* MX23_PAD_LCD_D08__LCD_D8 */
- 0x1090 /* MX23_PAD_LCD_D09__LCD_D9 */
- 0x10a0 /* MX23_PAD_LCD_D10__LCD_D10 */
- 0x10b0 /* MX23_PAD_LCD_D11__LCD_D11 */
- 0x10c0 /* MX23_PAD_LCD_D12__LCD_D12 */
- 0x10d0 /* MX23_PAD_LCD_D13__LCD_D13 */
- 0x10e0 /* MX23_PAD_LCD_D14__LCD_D14 */
- 0x10f0 /* MX23_PAD_LCD_D15__LCD_D15 */
- 0x1100 /* MX23_PAD_LCD_D16__LCD_D16 */
- 0x1110 /* MX23_PAD_LCD_D17__LCD_D17 */
- 0x0081 /* MX23_PAD_GPMI_D08__LCD_D18 */
- 0x0091 /* MX23_PAD_GPMI_D09__LCD_D19 */
- 0x00a1 /* MX23_PAD_GPMI_D10__LCD_D20 */
- 0x00b1 /* MX23_PAD_GPMI_D11__LCD_D21 */
- 0x00c1 /* MX23_PAD_GPMI_D12__LCD_D22 */
- 0x00d1 /* MX23_PAD_GPMI_D13__LCD_D23 */
- 0x1160 /* MX23_PAD_LCD_DOTCK__LCD_DOTCK */
- 0x1170 /* MX23_PAD_LCD_ENABLE__LCD_ENABLE */
- 0x1180 /* MX23_PAD_LCD_HSYNC__LCD_HSYNC */
- 0x1190 /* MX23_PAD_LCD_VSYNC__LCD_VSYNC */
+ MX23_PAD_LCD_D00__LCD_D00
+ MX23_PAD_LCD_D01__LCD_D01
+ MX23_PAD_LCD_D02__LCD_D02
+ MX23_PAD_LCD_D03__LCD_D03
+ MX23_PAD_LCD_D04__LCD_D04
+ MX23_PAD_LCD_D05__LCD_D05
+ MX23_PAD_LCD_D06__LCD_D06
+ MX23_PAD_LCD_D07__LCD_D07
+ MX23_PAD_LCD_D08__LCD_D08
+ MX23_PAD_LCD_D09__LCD_D09
+ MX23_PAD_LCD_D10__LCD_D10
+ MX23_PAD_LCD_D11__LCD_D11
+ MX23_PAD_LCD_D12__LCD_D12
+ MX23_PAD_LCD_D13__LCD_D13
+ MX23_PAD_LCD_D14__LCD_D14
+ MX23_PAD_LCD_D15__LCD_D15
+ MX23_PAD_LCD_D16__LCD_D16
+ MX23_PAD_LCD_D17__LCD_D17
+ MX23_PAD_GPMI_D08__LCD_D18
+ MX23_PAD_GPMI_D09__LCD_D19
+ MX23_PAD_GPMI_D10__LCD_D20
+ MX23_PAD_GPMI_D11__LCD_D21
+ MX23_PAD_GPMI_D12__LCD_D22
+ MX23_PAD_GPMI_D13__LCD_D23
+ MX23_PAD_LCD_DOTCK__LCD_DOTCK
+ MX23_PAD_LCD_ENABLE__LCD_ENABLE
+ MX23_PAD_LCD_HSYNC__LCD_HSYNC
+ MX23_PAD_LCD_VSYNC__LCD_VSYNC
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
spi2_pins_a: spi2@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x0182 /* MX23_PAD_GPMI_WRN__SSP2_SCK */
- 0x0142 /* MX23_PAD_GPMI_RDY1__SSP2_CMD */
- 0x0002 /* MX23_PAD_GPMI_D00__SSP2_DATA0 */
- 0x0032 /* MX23_PAD_GPMI_D03__SSP2_DATA3 */
+ MX23_PAD_GPMI_WRN__SSP2_SCK
+ MX23_PAD_GPMI_RDY1__SSP2_CMD
+ MX23_PAD_GPMI_D00__SSP2_DATA0
+ MX23_PAD_GPMI_D03__SSP2_DATA3
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
};
diff --git a/arch/arm/boot/dts/imx28-apf28.dts b/arch/arm/boot/dts/imx28-apf28.dts
index 7eb075876c4c..7198fe3798c6 100644
--- a/arch/arm/boot/dts/imx28-apf28.dts
+++ b/arch/arm/boot/dts/imx28-apf28.dts
@@ -10,7 +10,7 @@
*/
/dts-v1/;
-/include/ "imx28.dtsi"
+#include "imx28.dtsi"
/ {
model = "Armadeus Systems APF28 module";
diff --git a/arch/arm/boot/dts/imx28-apf28dev.dts b/arch/arm/boot/dts/imx28-apf28dev.dts
index b602494c152b..e2efd8d89c4f 100644
--- a/arch/arm/boot/dts/imx28-apf28dev.dts
+++ b/arch/arm/boot/dts/imx28-apf28dev.dts
@@ -10,7 +10,7 @@
*/
/* APF28Dev is a docking board for the APF28 SOM */
-/include/ "imx28-apf28.dts"
+#include "imx28-apf28.dts"
/ {
model = "Armadeus Systems APF28Dev docking/development board";
@@ -41,30 +41,30 @@
hog_pins_apf28dev: hog@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1103 /* MX28_PAD_LCD_D16__GPIO_1_16 */
- 0x1113 /* MX28_PAD_LCD_D17__GPIO_1_17 */
- 0x1123 /* MX28_PAD_LCD_D18__GPIO_1_18 */
- 0x1133 /* MX28_PAD_LCD_D19__GPIO_1_19 */
- 0x1143 /* MX28_PAD_LCD_D20__GPIO_1_20 */
- 0x1153 /* MX28_PAD_LCD_D21__GPIO_1_21 */
- 0x1163 /* MX28_PAD_LCD_D22__GPIO_1_22 */
+ MX28_PAD_LCD_D16__GPIO_1_16
+ MX28_PAD_LCD_D17__GPIO_1_17
+ MX28_PAD_LCD_D18__GPIO_1_18
+ MX28_PAD_LCD_D19__GPIO_1_19
+ MX28_PAD_LCD_D20__GPIO_1_20
+ MX28_PAD_LCD_D21__GPIO_1_21
+ MX28_PAD_LCD_D22__GPIO_1_22
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
lcdif_pins_apf28dev: lcdif-apf28dev@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
- 0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
- 0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
- 0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+ MX28_PAD_LCD_RD_E__LCD_VSYNC
+ MX28_PAD_LCD_WR_RWN__LCD_HSYNC
+ MX28_PAD_LCD_RS__LCD_DOTCLK
+ MX28_PAD_LCD_CS__LCD_ENABLE
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
};
diff --git a/arch/arm/boot/dts/imx28-apx4devkit.dts b/arch/arm/boot/dts/imx28-apx4devkit.dts
index 0e7fed47bd8d..6f254ca816cb 100644
--- a/arch/arm/boot/dts/imx28-apx4devkit.dts
+++ b/arch/arm/boot/dts/imx28-apx4devkit.dts
@@ -1,5 +1,5 @@
/dts-v1/;
-/include/ "imx28.dtsi"
+#include "imx28.dtsi"
/ {
model = "Bluegiga APX4 Development Kit";
@@ -40,53 +40,53 @@
hog_pins_a: hog@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x0113 /* MX28_PAD_GPMI_CE1N__GPIO_0_17 */
- 0x0153 /* MX28_PAD_GPMI_RDY1__GPIO_0_21 */
- 0x2123 /* MX28_PAD_SSP2_MISO__GPIO_2_18 */
- 0x2131 /* MX28_PAD_SSP2_SS0__GPIO_2_19 */
- 0x31c3 /* MX28_PAD_PWM3__GPIO_3_28 */
- 0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
- 0x4143 /* MX28_PAD_JTAG_RTCK__GPIO_4_20 */
+ MX28_PAD_GPMI_CE1N__GPIO_0_17
+ MX28_PAD_GPMI_RDY1__GPIO_0_21
+ MX28_PAD_SSP2_MISO__GPIO_2_18
+ MX28_PAD_SSP2_SS0__AUART3_TX /* was: 0x2131 - MX28_PAD_SSP2_SS0__GPIO_2_19 */
+ MX28_PAD_PWM3__GPIO_3_28
+ MX28_PAD_LCD_RESET__GPIO_3_30
+ MX28_PAD_JTAG_RTCK__GPIO_4_20
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
lcdif_pins_apx4: lcdif-apx4@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
- 0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
- 0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
- 0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+ MX28_PAD_LCD_RD_E__LCD_VSYNC
+ MX28_PAD_LCD_WR_RWN__LCD_HSYNC
+ MX28_PAD_LCD_RS__LCD_DOTCLK
+ MX28_PAD_LCD_CS__LCD_ENABLE
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
mmc2_4bit_pins_apx4: mmc2-4bit-apx4@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2041 /* MX28_PAD_SSP0_DATA4__SSP2_D0 */
- 0x2051 /* MX28_PAD_SSP0_DATA5__SSP2_D3 */
- 0x2061 /* MX28_PAD_SSP0_DATA6__SSP2_CMD */
- 0x2071 /* MX28_PAD_SSP0_DATA7__SSP2_SCK */
- 0x2141 /* MX28_PAD_SSP2_SS1__SSP2_D1 */
- 0x2151 /* MX28_PAD_SSP2_SS2__SSP2_D2 */
+ MX28_PAD_SSP0_DATA4__SSP2_D0
+ MX28_PAD_SSP0_DATA5__SSP2_D3
+ MX28_PAD_SSP0_DATA6__SSP2_CMD
+ MX28_PAD_SSP0_DATA7__SSP2_SCK
+ MX28_PAD_SSP2_SS1__SSP2_D1
+ MX28_PAD_SSP2_SS2__SSP2_D2
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
mmc2_sck_cfg_apx4: mmc2-sck-cfg-apx4 {
fsl,pinmux-ids = <
- 0x2071 /* MX28_PAD_SSP0_DATA7__SSP2_SCK */
+ MX28_PAD_SSP0_DATA7__SSP2_SCK
>;
- fsl,drive-strength = <2>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_12mA>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
};
diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
index 1ec8c94bbac9..cabb6171a19d 100644
--- a/arch/arm/boot/dts/imx28-cfa10036.dts
+++ b/arch/arm/boot/dts/imx28-cfa10036.dts
@@ -10,7 +10,7 @@
*/
/dts-v1/;
-/include/ "imx28.dtsi"
+#include "imx28.dtsi"
/ {
model = "Crystalfontz CFA-10036 Board";
@@ -26,31 +26,31 @@
ssd1306_cfa10036: ssd1306-10036@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2073 /* MX28_PAD_SSP0_D7__GPIO_2_7 */
+ MX28_PAD_SSP0_DATA7__GPIO_2_7
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
led_pins_cfa10036: leds-10036@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x3043 /* MX28_PAD_AUART1_RX__GPIO_3_4 */
+ MX28_PAD_AUART1_RX__GPIO_3_4
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
usb0_otg_cfa10036: otg-10036@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x0142 /* MX28_PAD_GPMI_READY0__USB0_ID */
+ MX28_PAD_GPMI_RDY0__USB0_ID
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
};
diff --git a/arch/arm/boot/dts/imx28-cfa10037.dts b/arch/arm/boot/dts/imx28-cfa10037.dts
index 182b99fe35f3..f93e9a700e52 100644
--- a/arch/arm/boot/dts/imx28-cfa10037.dts
+++ b/arch/arm/boot/dts/imx28-cfa10037.dts
@@ -13,7 +13,7 @@
* The CFA-10049 is an expansion board for the CFA-10036 module, thus we
* need to include the CFA-10036 DTS.
*/
-/include/ "imx28-cfa10036.dts"
+#include "imx28-cfa10036.dts"
/ {
model = "Crystalfontz CFA-10037 Board";
@@ -25,21 +25,21 @@
usb_pins_cfa10037: usb-10037@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x0073 /* MX28_PAD_GPMI_D7__GPIO_0_7 */
+ MX28_PAD_GPMI_D07__GPIO_0_7
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
mac0_pins_cfa10037: mac0-10037@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2153 /* MX28_PAD_SSP2_D5__GPIO_2_21 */
+ MX28_PAD_SSP2_SS2__GPIO_2_21
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
};
};
diff --git a/arch/arm/boot/dts/imx28-cfa10049.dts b/arch/arm/boot/dts/imx28-cfa10049.dts
index 06e4cfaf7dd2..7087b4bf6a8f 100644
--- a/arch/arm/boot/dts/imx28-cfa10049.dts
+++ b/arch/arm/boot/dts/imx28-cfa10049.dts
@@ -13,7 +13,7 @@
* The CFA-10049 is an expansion board for the CFA-10036 module, thus we
* need to include the CFA-10036 DTS.
*/
-/include/ "imx28-cfa10036.dts"
+#include "imx28-cfa10036.dts"
/ {
model = "Crystalfontz CFA-10049 Board";
@@ -25,150 +25,150 @@
usb_pins_cfa10049: usb-10049@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x0073 /* MX28_PAD_GPMI_D7__GPIO_0_7 */
+ MX28_PAD_GPMI_D07__GPIO_0_7
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
i2cmux_pins_cfa10049: i2cmux-10049@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1163 /* MX28_PAD_LCD_D22__GPIO_1_22 */
- 0x1173 /* MX28_PAD_LCD_D22__GPIO_1_23 */
+ MX28_PAD_LCD_D22__GPIO_1_22
+ MX28_PAD_LCD_D23__GPIO_1_23
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
mac0_pins_cfa10049: mac0-10049@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2153 /* MX28_PAD_SSP2_D5__GPIO_2_21 */
+ MX28_PAD_SSP2_SS2__GPIO_2_21
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
pca_pins_cfa10049: pca-10049@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2133 /* MX28_PAD_SSP2_D3__GPIO_2_19 */
+ MX28_PAD_SSP2_SS0__GPIO_2_19
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
rotary_pins_cfa10049: rotary-10049@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x3183 /* MX28_PAD_I2C0_SCL__GPIO_3_24 */
- 0x3193 /* MX28_PAD_I2C0_SDA__GPIO_3_25 */
+ MX28_PAD_I2C0_SCL__GPIO_3_24
+ MX28_PAD_I2C0_SDA__GPIO_3_25
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
rotary_btn_pins_cfa10049: rotary-btn-10049@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x31a3 /* MX28_PAD_SAIF_SDATA0__GPIO_3_26 */
+ MX28_PAD_SAIF1_SDATA0__GPIO_3_26
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
spi2_pins_cfa10049: spi2-cfa10049@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2103 /* MX28_PAD_SSP2_SCK__GPIO_2_16 */
- 0x2113 /* MX28_PAD_SSP2_CMD__GPIO_2_17 */
- 0x2123 /* MX28_PAD_SSP2_D0__GPIO_2_18 */
- 0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
+ MX28_PAD_SSP2_SCK__GPIO_2_16
+ MX28_PAD_SSP2_MOSI__GPIO_2_17
+ MX28_PAD_SSP2_MISO__GPIO_2_18
+ MX28_PAD_AUART1_TX__GPIO_3_5
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
spi3_pins_cfa10049: spi3-cfa10049@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x0183 /* MX28_PAD_GPMI_RDN__GPIO_0_24 */
- 0x01c3 /* MX28_PAD_GPMI_RESETN__GPIO_0_28 */
- 0x0113 /* MX28_PAD_GPMI_CE1N__GPIO_0_17 */
- 0x01a3 /* MX28_PAD_GPMI_ALE__GPIO_0_26 */
- 0x01b3 /* MX28_PAD_GPMI_CLE__GPIO_0_27 */
+ MX28_PAD_GPMI_RDN__GPIO_0_24
+ MX28_PAD_GPMI_RESETN__GPIO_0_28
+ MX28_PAD_GPMI_CE1N__GPIO_0_17
+ MX28_PAD_GPMI_ALE__GPIO_0_26
+ MX28_PAD_GPMI_CLE__GPIO_0_27
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
lcdif_18bit_pins_cfa10049: lcdif-18bit@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1000 /* MX28_PAD_LCD_D00__LCD_D0 */
- 0x1010 /* MX28_PAD_LCD_D01__LCD_D1 */
- 0x1020 /* MX28_PAD_LCD_D02__LCD_D2 */
- 0x1030 /* MX28_PAD_LCD_D03__LCD_D3 */
- 0x1040 /* MX28_PAD_LCD_D04__LCD_D4 */
- 0x1050 /* MX28_PAD_LCD_D05__LCD_D5 */
- 0x1060 /* MX28_PAD_LCD_D06__LCD_D6 */
- 0x1070 /* MX28_PAD_LCD_D07__LCD_D7 */
- 0x1080 /* MX28_PAD_LCD_D08__LCD_D8 */
- 0x1090 /* MX28_PAD_LCD_D09__LCD_D9 */
- 0x10a0 /* MX28_PAD_LCD_D10__LCD_D10 */
- 0x10b0 /* MX28_PAD_LCD_D11__LCD_D11 */
- 0x10c0 /* MX28_PAD_LCD_D12__LCD_D12 */
- 0x10d0 /* MX28_PAD_LCD_D13__LCD_D13 */
- 0x10e0 /* MX28_PAD_LCD_D14__LCD_D14 */
- 0x10f0 /* MX28_PAD_LCD_D15__LCD_D15 */
- 0x1100 /* MX28_PAD_LCD_D16__LCD_D16 */
- 0x1110 /* MX28_PAD_LCD_D17__LCD_D17 */
+ MX28_PAD_LCD_D00__LCD_D0
+ MX28_PAD_LCD_D01__LCD_D1
+ MX28_PAD_LCD_D02__LCD_D2
+ MX28_PAD_LCD_D03__LCD_D3
+ MX28_PAD_LCD_D04__LCD_D4
+ MX28_PAD_LCD_D05__LCD_D5
+ MX28_PAD_LCD_D06__LCD_D6
+ MX28_PAD_LCD_D07__LCD_D7
+ MX28_PAD_LCD_D08__LCD_D8
+ MX28_PAD_LCD_D09__LCD_D9
+ MX28_PAD_LCD_D10__LCD_D10
+ MX28_PAD_LCD_D11__LCD_D11
+ MX28_PAD_LCD_D12__LCD_D12
+ MX28_PAD_LCD_D13__LCD_D13
+ MX28_PAD_LCD_D14__LCD_D14
+ MX28_PAD_LCD_D15__LCD_D15
+ MX28_PAD_LCD_D16__LCD_D16
+ MX28_PAD_LCD_D17__LCD_D17
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
lcdif_pins_cfa10049: lcdif-evk@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
- 0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
- 0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
- 0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+ MX28_PAD_LCD_RD_E__LCD_VSYNC
+ MX28_PAD_LCD_WR_RWN__LCD_HSYNC
+ MX28_PAD_LCD_RS__LCD_DOTCLK
+ MX28_PAD_LCD_CS__LCD_ENABLE
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
lcdif_pins_cfa10049_pullup: lcdif-10049-pullup@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
+ MX28_PAD_LCD_RESET__GPIO_3_30
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
w1_gpio_pins: w1-gpio@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1153 /* MX28_PAD_LCD_D21__GPIO_1_21 */
+ MX28_PAD_LCD_D21__GPIO_1_21
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>; /* 0 will enable the keeper */
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>; /* 0 will enable the keeper */
};
};
diff --git a/arch/arm/boot/dts/imx28-cfa10055.dts b/arch/arm/boot/dts/imx28-cfa10055.dts
index 171bcbe1ec4b..c3900e7ba331 100644
--- a/arch/arm/boot/dts/imx28-cfa10055.dts
+++ b/arch/arm/boot/dts/imx28-cfa10055.dts
@@ -14,7 +14,7 @@
* The CFA-10055 is an expansion board for the CFA-10036 module and
* CFA-10037, thus we need to include the CFA-10037 DTS.
*/
-/include/ "imx28-cfa10037.dts"
+#include "imx28-cfa10037.dts"
/ {
model = "Crystalfontz CFA-10055 Board";
@@ -26,64 +26,64 @@
spi2_pins_cfa10055: spi2-cfa10055@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2103 /* MX28_PAD_SSP2_SCK__GPIO_2_16 */
- 0x2113 /* MX28_PAD_SSP2_CMD__GPIO_2_17 */
- 0x2123 /* MX28_PAD_SSP2_D0__GPIO_2_18 */
- 0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
+ MX28_PAD_SSP2_SCK__GPIO_2_16
+ MX28_PAD_SSP2_MOSI__GPIO_2_17
+ MX28_PAD_SSP2_MISO__GPIO_2_18
+ MX28_PAD_AUART1_TX__GPIO_3_5
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
lcdif_18bit_pins_cfa10055: lcdif-18bit@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1000 /* MX28_PAD_LCD_D00__LCD_D0 */
- 0x1010 /* MX28_PAD_LCD_D01__LCD_D1 */
- 0x1020 /* MX28_PAD_LCD_D02__LCD_D2 */
- 0x1030 /* MX28_PAD_LCD_D03__LCD_D3 */
- 0x1040 /* MX28_PAD_LCD_D04__LCD_D4 */
- 0x1050 /* MX28_PAD_LCD_D05__LCD_D5 */
- 0x1060 /* MX28_PAD_LCD_D06__LCD_D6 */
- 0x1070 /* MX28_PAD_LCD_D07__LCD_D7 */
- 0x1080 /* MX28_PAD_LCD_D08__LCD_D8 */
- 0x1090 /* MX28_PAD_LCD_D09__LCD_D9 */
- 0x10a0 /* MX28_PAD_LCD_D10__LCD_D10 */
- 0x10b0 /* MX28_PAD_LCD_D11__LCD_D11 */
- 0x10c0 /* MX28_PAD_LCD_D12__LCD_D12 */
- 0x10d0 /* MX28_PAD_LCD_D13__LCD_D13 */
- 0x10e0 /* MX28_PAD_LCD_D14__LCD_D14 */
- 0x10f0 /* MX28_PAD_LCD_D15__LCD_D15 */
- 0x1100 /* MX28_PAD_LCD_D16__LCD_D16 */
- 0x1110 /* MX28_PAD_LCD_D17__LCD_D17 */
+ MX28_PAD_LCD_D00__LCD_D0
+ MX28_PAD_LCD_D01__LCD_D1
+ MX28_PAD_LCD_D02__LCD_D2
+ MX28_PAD_LCD_D03__LCD_D3
+ MX28_PAD_LCD_D04__LCD_D4
+ MX28_PAD_LCD_D05__LCD_D5
+ MX28_PAD_LCD_D06__LCD_D6
+ MX28_PAD_LCD_D07__LCD_D7
+ MX28_PAD_LCD_D08__LCD_D8
+ MX28_PAD_LCD_D09__LCD_D9
+ MX28_PAD_LCD_D10__LCD_D10
+ MX28_PAD_LCD_D11__LCD_D11
+ MX28_PAD_LCD_D12__LCD_D12
+ MX28_PAD_LCD_D13__LCD_D13
+ MX28_PAD_LCD_D14__LCD_D14
+ MX28_PAD_LCD_D15__LCD_D15
+ MX28_PAD_LCD_D16__LCD_D16
+ MX28_PAD_LCD_D17__LCD_D17
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
lcdif_pins_cfa10055: lcdif-evk@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
- 0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
- 0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
- 0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+ MX28_PAD_LCD_RD_E__LCD_VSYNC
+ MX28_PAD_LCD_WR_RWN__LCD_HSYNC
+ MX28_PAD_LCD_RS__LCD_DOTCLK
+ MX28_PAD_LCD_CS__LCD_ENABLE
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
lcdif_pins_cfa10055_pullup: lcdif-10055-pullup@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
+ MX28_PAD_LCD_RESET__GPIO_3_30
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
};
diff --git a/arch/arm/boot/dts/imx28-cfa10056.dts b/arch/arm/boot/dts/imx28-cfa10056.dts
index b45dd0e4ee57..cef959a97219 100644
--- a/arch/arm/boot/dts/imx28-cfa10056.dts
+++ b/arch/arm/boot/dts/imx28-cfa10056.dts
@@ -13,7 +13,7 @@
* The CFA-10055 is an expansion board for the CFA-10036 module and
* CFA-10037, thus we need to include the CFA-10037 DTS.
*/
-/include/ "imx28-cfa10037.dts"
+#include "imx28-cfa10037.dts"
/ {
model = "Crystalfontz CFA-10056 Board";
@@ -25,37 +25,37 @@
spi2_pins_cfa10056: spi2-cfa10056@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2103 /* MX28_PAD_SSP2_SCK__GPIO_2_16 */
- 0x2113 /* MX28_PAD_SSP2_CMD__GPIO_2_17 */
- 0x2123 /* MX28_PAD_SSP2_D0__GPIO_2_18 */
- 0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
+ MX28_PAD_SSP2_SCK__GPIO_2_16
+ MX28_PAD_SSP2_MOSI__GPIO_2_17
+ MX28_PAD_SSP2_MISO__GPIO_2_18
+ MX28_PAD_AUART1_TX__GPIO_3_5
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
lcdif_pins_cfa10056: lcdif-10056@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
- 0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
- 0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
- 0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+ MX28_PAD_LCD_RD_E__LCD_VSYNC
+ MX28_PAD_LCD_WR_RWN__LCD_HSYNC
+ MX28_PAD_LCD_RS__LCD_DOTCLK
+ MX28_PAD_LCD_CS__LCD_ENABLE
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
lcdif_pins_cfa10056_pullup: lcdif-10056-pullup@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
+ MX28_PAD_LCD_RESET__GPIO_3_30
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
};
diff --git a/arch/arm/boot/dts/imx28-cfa10057.dts b/arch/arm/boot/dts/imx28-cfa10057.dts
index 0333c0532f28..3c1312885ae0 100644
--- a/arch/arm/boot/dts/imx28-cfa10057.dts
+++ b/arch/arm/boot/dts/imx28-cfa10057.dts
@@ -14,7 +14,7 @@
* The CFA-10057 is an expansion board for the CFA-10036 module, thus we
* need to include the CFA-10036 DTS.
*/
-/include/ "imx28-cfa10036.dts"
+#include "imx28-cfa10036.dts"
/ {
model = "Crystalfontz CFA-10057 Board";
@@ -26,51 +26,51 @@
usb_pins_cfa10057: usb-10057@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x0073 /* MX28_PAD_GPMI_D7__GPIO_0_7 */
+ MX28_PAD_GPMI_D07__GPIO_0_7
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
lcdif_18bit_pins_cfa10057: lcdif-18bit@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1000 /* MX28_PAD_LCD_D00__LCD_D0 */
- 0x1010 /* MX28_PAD_LCD_D01__LCD_D1 */
- 0x1020 /* MX28_PAD_LCD_D02__LCD_D2 */
- 0x1030 /* MX28_PAD_LCD_D03__LCD_D3 */
- 0x1040 /* MX28_PAD_LCD_D04__LCD_D4 */
- 0x1050 /* MX28_PAD_LCD_D05__LCD_D5 */
- 0x1060 /* MX28_PAD_LCD_D06__LCD_D6 */
- 0x1070 /* MX28_PAD_LCD_D07__LCD_D7 */
- 0x1080 /* MX28_PAD_LCD_D08__LCD_D8 */
- 0x1090 /* MX28_PAD_LCD_D09__LCD_D9 */
- 0x10a0 /* MX28_PAD_LCD_D10__LCD_D10 */
- 0x10b0 /* MX28_PAD_LCD_D11__LCD_D11 */
- 0x10c0 /* MX28_PAD_LCD_D12__LCD_D12 */
- 0x10d0 /* MX28_PAD_LCD_D13__LCD_D13 */
- 0x10e0 /* MX28_PAD_LCD_D14__LCD_D14 */
- 0x10f0 /* MX28_PAD_LCD_D15__LCD_D15 */
- 0x1100 /* MX28_PAD_LCD_D16__LCD_D16 */
- 0x1110 /* MX28_PAD_LCD_D17__LCD_D17 */
+ MX28_PAD_LCD_D00__LCD_D0
+ MX28_PAD_LCD_D01__LCD_D1
+ MX28_PAD_LCD_D02__LCD_D2
+ MX28_PAD_LCD_D03__LCD_D3
+ MX28_PAD_LCD_D04__LCD_D4
+ MX28_PAD_LCD_D05__LCD_D5
+ MX28_PAD_LCD_D06__LCD_D6
+ MX28_PAD_LCD_D07__LCD_D7
+ MX28_PAD_LCD_D08__LCD_D8
+ MX28_PAD_LCD_D09__LCD_D9
+ MX28_PAD_LCD_D10__LCD_D10
+ MX28_PAD_LCD_D11__LCD_D11
+ MX28_PAD_LCD_D12__LCD_D12
+ MX28_PAD_LCD_D13__LCD_D13
+ MX28_PAD_LCD_D14__LCD_D14
+ MX28_PAD_LCD_D15__LCD_D15
+ MX28_PAD_LCD_D16__LCD_D16
+ MX28_PAD_LCD_D17__LCD_D17
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
lcdif_pins_cfa10057: lcdif-evk@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
- 0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
- 0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
- 0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+ MX28_PAD_LCD_RD_E__LCD_VSYNC
+ MX28_PAD_LCD_WR_RWN__LCD_HSYNC
+ MX28_PAD_LCD_RS__LCD_DOTCLK
+ MX28_PAD_LCD_CS__LCD_ENABLE
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
};
diff --git a/arch/arm/boot/dts/imx28-cfa10058.dts b/arch/arm/boot/dts/imx28-cfa10058.dts
index 64c64c55a82a..2469d34df0ae 100644
--- a/arch/arm/boot/dts/imx28-cfa10058.dts
+++ b/arch/arm/boot/dts/imx28-cfa10058.dts
@@ -14,7 +14,7 @@
* The CFA-10058 is an expansion board for the CFA-10036 module, thus we
* need to include the CFA-10036 DTS.
*/
-/include/ "imx28-cfa10036.dts"
+#include "imx28-cfa10036.dts"
/ {
model = "Crystalfontz CFA-10058 Board";
@@ -26,24 +26,24 @@
usb_pins_cfa10058: usb-10058@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x0073 /* MX28_PAD_GPMI_D7__GPIO_0_7 */
+ MX28_PAD_GPMI_D07__GPIO_0_7
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
lcdif_pins_cfa10058: lcdif-10058@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
- 0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
- 0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
- 0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+ MX28_PAD_LCD_RD_E__LCD_VSYNC
+ MX28_PAD_LCD_WR_RWN__LCD_HSYNC
+ MX28_PAD_LCD_RS__LCD_DOTCLK
+ MX28_PAD_LCD_CS__LCD_ENABLE
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
};
diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts
index 15715d921d14..1f63845b8ce0 100644
--- a/arch/arm/boot/dts/imx28-evk.dts
+++ b/arch/arm/boot/dts/imx28-evk.dts
@@ -10,7 +10,7 @@
*/
/dts-v1/;
-/include/ "imx28.dtsi"
+#include "imx28.dtsi"
/ {
model = "Freescale i.MX28 Evaluation Kit";
@@ -70,52 +70,52 @@
hog_pins_a: hog@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x20d3 /* MX28_PAD_SSP1_CMD__GPIO_2_13 */
- 0x20f3 /* MX28_PAD_SSP1_DATA3__GPIO_2_15 */
- 0x40d3 /* MX28_PAD_ENET0_RX_CLK__GPIO_4_13 */
- 0x20c3 /* MX28_PAD_SSP1_SCK__GPIO_2_12 */
- 0x31c3 /* MX28_PAD_PWM3__GPIO_3_28 */
- 0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
- 0x3083 /* MX28_PAD_AUART2_RX__GPIO_3_8 */
- 0x3093 /* MX28_PAD_AUART2_TX__GPIO_3_9 */
+ MX28_PAD_SSP1_CMD__GPIO_2_13
+ MX28_PAD_SSP1_DATA3__GPIO_2_15
+ MX28_PAD_ENET0_RX_CLK__GPIO_4_13
+ MX28_PAD_SSP1_SCK__GPIO_2_12
+ MX28_PAD_PWM3__GPIO_3_28
+ MX28_PAD_LCD_RESET__GPIO_3_30
+ MX28_PAD_AUART2_RX__GPIO_3_8
+ MX28_PAD_AUART2_TX__GPIO_3_9
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
led_pin_gpio3_5: led_gpio3_5@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
+ MX28_PAD_AUART1_TX__GPIO_3_5
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
gpmi_pins_evk: gpmi-nand-evk@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x0110 /* MX28_PAD_GPMI_CE1N__GPMI_CE1N */
- 0x0150 /* MX28_PAD_GPMI_RDY1__GPMI_READY1 */
+ MX28_PAD_GPMI_CE1N__GPMI_CE1N
+ MX28_PAD_GPMI_RDY1__GPMI_READY1
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
lcdif_pins_evk: lcdif-evk@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
- 0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
- 0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
- 0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+ MX28_PAD_LCD_RD_E__LCD_VSYNC
+ MX28_PAD_LCD_WR_RWN__LCD_HSYNC
+ MX28_PAD_LCD_RS__LCD_DOTCLK
+ MX28_PAD_LCD_CS__LCD_ENABLE
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
};
@@ -182,6 +182,7 @@
};
lradc@80050000 {
+ fsl,lradc-touchscreen-wires = <4>;
status = "okay";
};
@@ -242,6 +243,8 @@
ahb@80080000 {
usb0: usb@80080000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb0_id_pins_a>;
vbus-supply = <&reg_usb0_vbus>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx28-m28evk.dts b/arch/arm/boot/dts/imx28-m28evk.dts
index 0d322a2bebaf..8e2477fbe1d7 100644
--- a/arch/arm/boot/dts/imx28-m28evk.dts
+++ b/arch/arm/boot/dts/imx28-m28evk.dts
@@ -10,7 +10,7 @@
*/
/dts-v1/;
-/include/ "imx28.dtsi"
+#include "imx28.dtsi"
/ {
model = "DENX M28EVK";
@@ -92,26 +92,26 @@
hog_pins_a: hog@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x31c3 /* MX28_PAD_PWM3__GPIO_3_28 */
- 0x30a3 /* MX28_PAD_AUART2_CTS__GPIO_3_10 */
- 0x30b3 /* MX28_PAD_AUART2_RTS__GPIO_3_11 */
- 0x30c3 /* MX28_PAD_AUART3_RX__GPIO_3_12 */
- 0x30d3 /* MX28_PAD_AUART3_TX__GPIO_3_13 */
+ MX28_PAD_PWM3__GPIO_3_28
+ MX28_PAD_AUART2_CTS__GPIO_3_10
+ MX28_PAD_AUART2_RTS__GPIO_3_11
+ MX28_PAD_AUART3_RX__GPIO_3_12
+ MX28_PAD_AUART3_TX__GPIO_3_13
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
lcdif_pins_m28: lcdif-m28@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x11e0 /* MX28_PAD_LCD_DOTCLK__LCD_DOTCLK */
- 0x11f0 /* MX28_PAD_LCD_ENABLE__LCD_ENABLE */
+ MX28_PAD_LCD_DOTCLK__LCD_DOTCLK
+ MX28_PAD_LCD_ENABLE__LCD_ENABLE
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
};
diff --git a/arch/arm/boot/dts/imx28-pinfunc.h b/arch/arm/boot/dts/imx28-pinfunc.h
new file mode 100644
index 000000000000..e11f69ba0fe4
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-pinfunc.h
@@ -0,0 +1,506 @@
+/*
+ * Header providing constants for i.MX28 pinctrl bindings.
+ *
+ * Copyright (C) 2013 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __DT_BINDINGS_MX28_PINCTRL_H__
+#define __DT_BINDINGS_MX28_PINCTRL_H__
+
+#include "mxs-pinfunc.h"
+
+#define MX28_PAD_GPMI_D00__GPMI_D0 0x0000
+#define MX28_PAD_GPMI_D01__GPMI_D1 0x0010
+#define MX28_PAD_GPMI_D02__GPMI_D2 0x0020
+#define MX28_PAD_GPMI_D03__GPMI_D3 0x0030
+#define MX28_PAD_GPMI_D04__GPMI_D4 0x0040
+#define MX28_PAD_GPMI_D05__GPMI_D5 0x0050
+#define MX28_PAD_GPMI_D06__GPMI_D6 0x0060
+#define MX28_PAD_GPMI_D07__GPMI_D7 0x0070
+#define MX28_PAD_GPMI_CE0N__GPMI_CE0N 0x0100
+#define MX28_PAD_GPMI_CE1N__GPMI_CE1N 0x0110
+#define MX28_PAD_GPMI_CE2N__GPMI_CE2N 0x0120
+#define MX28_PAD_GPMI_CE3N__GPMI_CE3N 0x0130
+#define MX28_PAD_GPMI_RDY0__GPMI_READY0 0x0140
+#define MX28_PAD_GPMI_RDY1__GPMI_READY1 0x0150
+#define MX28_PAD_GPMI_RDY2__GPMI_READY2 0x0160
+#define MX28_PAD_GPMI_RDY3__GPMI_READY3 0x0170
+#define MX28_PAD_GPMI_RDN__GPMI_RDN 0x0180
+#define MX28_PAD_GPMI_WRN__GPMI_WRN 0x0190
+#define MX28_PAD_GPMI_ALE__GPMI_ALE 0x01a0
+#define MX28_PAD_GPMI_CLE__GPMI_CLE 0x01b0
+#define MX28_PAD_GPMI_RESETN__GPMI_RESETN 0x01c0
+#define MX28_PAD_LCD_D00__LCD_D0 0x1000
+#define MX28_PAD_LCD_D01__LCD_D1 0x1010
+#define MX28_PAD_LCD_D02__LCD_D2 0x1020
+#define MX28_PAD_LCD_D03__LCD_D3 0x1030
+#define MX28_PAD_LCD_D04__LCD_D4 0x1040
+#define MX28_PAD_LCD_D05__LCD_D5 0x1050
+#define MX28_PAD_LCD_D06__LCD_D6 0x1060
+#define MX28_PAD_LCD_D07__LCD_D7 0x1070
+#define MX28_PAD_LCD_D08__LCD_D8 0x1080
+#define MX28_PAD_LCD_D09__LCD_D9 0x1090
+#define MX28_PAD_LCD_D10__LCD_D10 0x10a0
+#define MX28_PAD_LCD_D11__LCD_D11 0x10b0
+#define MX28_PAD_LCD_D12__LCD_D12 0x10c0
+#define MX28_PAD_LCD_D13__LCD_D13 0x10d0
+#define MX28_PAD_LCD_D14__LCD_D14 0x10e0
+#define MX28_PAD_LCD_D15__LCD_D15 0x10f0
+#define MX28_PAD_LCD_D16__LCD_D16 0x1100
+#define MX28_PAD_LCD_D17__LCD_D17 0x1110
+#define MX28_PAD_LCD_D18__LCD_D18 0x1120
+#define MX28_PAD_LCD_D19__LCD_D19 0x1130
+#define MX28_PAD_LCD_D20__LCD_D20 0x1140
+#define MX28_PAD_LCD_D21__LCD_D21 0x1150
+#define MX28_PAD_LCD_D22__LCD_D22 0x1160
+#define MX28_PAD_LCD_D23__LCD_D23 0x1170
+#define MX28_PAD_LCD_RD_E__LCD_RD_E 0x1180
+#define MX28_PAD_LCD_WR_RWN__LCD_WR_RWN 0x1190
+#define MX28_PAD_LCD_RS__LCD_RS 0x11a0
+#define MX28_PAD_LCD_CS__LCD_CS 0x11b0
+#define MX28_PAD_LCD_VSYNC__LCD_VSYNC 0x11c0
+#define MX28_PAD_LCD_HSYNC__LCD_HSYNC 0x11d0
+#define MX28_PAD_LCD_DOTCLK__LCD_DOTCLK 0x11e0
+#define MX28_PAD_LCD_ENABLE__LCD_ENABLE 0x11f0
+#define MX28_PAD_SSP0_DATA0__SSP0_D0 0x2000
+#define MX28_PAD_SSP0_DATA1__SSP0_D1 0x2010
+#define MX28_PAD_SSP0_DATA2__SSP0_D2 0x2020
+#define MX28_PAD_SSP0_DATA3__SSP0_D3 0x2030
+#define MX28_PAD_SSP0_DATA4__SSP0_D4 0x2040
+#define MX28_PAD_SSP0_DATA5__SSP0_D5 0x2050
+#define MX28_PAD_SSP0_DATA6__SSP0_D6 0x2060
+#define MX28_PAD_SSP0_DATA7__SSP0_D7 0x2070
+#define MX28_PAD_SSP0_CMD__SSP0_CMD 0x2080
+#define MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT 0x2090
+#define MX28_PAD_SSP0_SCK__SSP0_SCK 0x20a0
+#define MX28_PAD_SSP1_SCK__SSP1_SCK 0x20c0
+#define MX28_PAD_SSP1_CMD__SSP1_CMD 0x20d0
+#define MX28_PAD_SSP1_DATA0__SSP1_D0 0x20e0
+#define MX28_PAD_SSP1_DATA3__SSP1_D3 0x20f0
+#define MX28_PAD_SSP2_SCK__SSP2_SCK 0x2100
+#define MX28_PAD_SSP2_MOSI__SSP2_CMD 0x2110
+#define MX28_PAD_SSP2_MISO__SSP2_D0 0x2120
+#define MX28_PAD_SSP2_SS0__SSP2_D3 0x2130
+#define MX28_PAD_SSP2_SS1__SSP2_D4 0x2140
+#define MX28_PAD_SSP2_SS2__SSP2_D5 0x2150
+#define MX28_PAD_SSP3_SCK__SSP3_SCK 0x2180
+#define MX28_PAD_SSP3_MOSI__SSP3_CMD 0x2190
+#define MX28_PAD_SSP3_MISO__SSP3_D0 0x21a0
+#define MX28_PAD_SSP3_SS0__SSP3_D3 0x21b0
+#define MX28_PAD_AUART0_RX__AUART0_RX 0x3000
+#define MX28_PAD_AUART0_TX__AUART0_TX 0x3010
+#define MX28_PAD_AUART0_CTS__AUART0_CTS 0x3020
+#define MX28_PAD_AUART0_RTS__AUART0_RTS 0x3030
+#define MX28_PAD_AUART1_RX__AUART1_RX 0x3040
+#define MX28_PAD_AUART1_TX__AUART1_TX 0x3050
+#define MX28_PAD_AUART1_CTS__AUART1_CTS 0x3060
+#define MX28_PAD_AUART1_RTS__AUART1_RTS 0x3070
+#define MX28_PAD_AUART2_RX__AUART2_RX 0x3080
+#define MX28_PAD_AUART2_TX__AUART2_TX 0x3090
+#define MX28_PAD_AUART2_CTS__AUART2_CTS 0x30a0
+#define MX28_PAD_AUART2_RTS__AUART2_RTS 0x30b0
+#define MX28_PAD_AUART3_RX__AUART3_RX 0x30c0
+#define MX28_PAD_AUART3_TX__AUART3_TX 0x30d0
+#define MX28_PAD_AUART3_CTS__AUART3_CTS 0x30e0
+#define MX28_PAD_AUART3_RTS__AUART3_RTS 0x30f0
+#define MX28_PAD_PWM0__PWM_0 0x3100
+#define MX28_PAD_PWM1__PWM_1 0x3110
+#define MX28_PAD_PWM2__PWM_2 0x3120
+#define MX28_PAD_SAIF0_MCLK__SAIF0_MCLK 0x3140
+#define MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK 0x3150
+#define MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK 0x3160
+#define MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0 0x3170
+#define MX28_PAD_I2C0_SCL__I2C0_SCL 0x3180
+#define MX28_PAD_I2C0_SDA__I2C0_SDA 0x3190
+#define MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0 0x31a0
+#define MX28_PAD_SPDIF__SPDIF_TX 0x31b0
+#define MX28_PAD_PWM3__PWM_3 0x31c0
+#define MX28_PAD_PWM4__PWM_4 0x31d0
+#define MX28_PAD_LCD_RESET__LCD_RESET 0x31e0
+#define MX28_PAD_ENET0_MDC__ENET0_MDC 0x4000
+#define MX28_PAD_ENET0_MDIO__ENET0_MDIO 0x4010
+#define MX28_PAD_ENET0_RX_EN__ENET0_RX_EN 0x4020
+#define MX28_PAD_ENET0_RXD0__ENET0_RXD0 0x4030
+#define MX28_PAD_ENET0_RXD1__ENET0_RXD1 0x4040
+#define MX28_PAD_ENET0_TX_CLK__ENET0_TX_CLK 0x4050
+#define MX28_PAD_ENET0_TX_EN__ENET0_TX_EN 0x4060
+#define MX28_PAD_ENET0_TXD0__ENET0_TXD0 0x4070
+#define MX28_PAD_ENET0_TXD1__ENET0_TXD1 0x4080
+#define MX28_PAD_ENET0_RXD2__ENET0_RXD2 0x4090
+#define MX28_PAD_ENET0_RXD3__ENET0_RXD3 0x40a0
+#define MX28_PAD_ENET0_TXD2__ENET0_TXD2 0x40b0
+#define MX28_PAD_ENET0_TXD3__ENET0_TXD3 0x40c0
+#define MX28_PAD_ENET0_RX_CLK__ENET0_RX_CLK 0x40d0
+#define MX28_PAD_ENET0_COL__ENET0_COL 0x40e0
+#define MX28_PAD_ENET0_CRS__ENET0_CRS 0x40f0
+#define MX28_PAD_ENET_CLK__CLKCTRL_ENET 0x4100
+#define MX28_PAD_JTAG_RTCK__JTAG_RTCK 0x4140
+#define MX28_PAD_EMI_D00__EMI_DATA0 0x5000
+#define MX28_PAD_EMI_D01__EMI_DATA1 0x5010
+#define MX28_PAD_EMI_D02__EMI_DATA2 0x5020
+#define MX28_PAD_EMI_D03__EMI_DATA3 0x5030
+#define MX28_PAD_EMI_D04__EMI_DATA4 0x5040
+#define MX28_PAD_EMI_D05__EMI_DATA5 0x5050
+#define MX28_PAD_EMI_D06__EMI_DATA6 0x5060
+#define MX28_PAD_EMI_D07__EMI_DATA7 0x5070
+#define MX28_PAD_EMI_D08__EMI_DATA8 0x5080
+#define MX28_PAD_EMI_D09__EMI_DATA9 0x5090
+#define MX28_PAD_EMI_D10__EMI_DATA10 0x50a0
+#define MX28_PAD_EMI_D11__EMI_DATA11 0x50b0
+#define MX28_PAD_EMI_D12__EMI_DATA12 0x50c0
+#define MX28_PAD_EMI_D13__EMI_DATA13 0x50d0
+#define MX28_PAD_EMI_D14__EMI_DATA14 0x50e0
+#define MX28_PAD_EMI_D15__EMI_DATA15 0x50f0
+#define MX28_PAD_EMI_ODT0__EMI_ODT0 0x5100
+#define MX28_PAD_EMI_DQM0__EMI_DQM0 0x5110
+#define MX28_PAD_EMI_ODT1__EMI_ODT1 0x5120
+#define MX28_PAD_EMI_DQM1__EMI_DQM1 0x5130
+#define MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK 0x5140
+#define MX28_PAD_EMI_CLK__EMI_CLK 0x5150
+#define MX28_PAD_EMI_DQS0__EMI_DQS0 0x5160
+#define MX28_PAD_EMI_DQS1__EMI_DQS1 0x5170
+#define MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN 0x51a0
+#define MX28_PAD_EMI_A00__EMI_ADDR0 0x6000
+#define MX28_PAD_EMI_A01__EMI_ADDR1 0x6010
+#define MX28_PAD_EMI_A02__EMI_ADDR2 0x6020
+#define MX28_PAD_EMI_A03__EMI_ADDR3 0x6030
+#define MX28_PAD_EMI_A04__EMI_ADDR4 0x6040
+#define MX28_PAD_EMI_A05__EMI_ADDR5 0x6050
+#define MX28_PAD_EMI_A06__EMI_ADDR6 0x6060
+#define MX28_PAD_EMI_A07__EMI_ADDR7 0x6070
+#define MX28_PAD_EMI_A08__EMI_ADDR8 0x6080
+#define MX28_PAD_EMI_A09__EMI_ADDR9 0x6090
+#define MX28_PAD_EMI_A10__EMI_ADDR10 0x60a0
+#define MX28_PAD_EMI_A11__EMI_ADDR11 0x60b0
+#define MX28_PAD_EMI_A12__EMI_ADDR12 0x60c0
+#define MX28_PAD_EMI_A13__EMI_ADDR13 0x60d0
+#define MX28_PAD_EMI_A14__EMI_ADDR14 0x60e0
+#define MX28_PAD_EMI_BA0__EMI_BA0 0x6100
+#define MX28_PAD_EMI_BA1__EMI_BA1 0x6110
+#define MX28_PAD_EMI_BA2__EMI_BA2 0x6120
+#define MX28_PAD_EMI_CASN__EMI_CASN 0x6130
+#define MX28_PAD_EMI_RASN__EMI_RASN 0x6140
+#define MX28_PAD_EMI_WEN__EMI_WEN 0x6150
+#define MX28_PAD_EMI_CE0N__EMI_CE0N 0x6160
+#define MX28_PAD_EMI_CE1N__EMI_CE1N 0x6170
+#define MX28_PAD_EMI_CKE__EMI_CKE 0x6180
+#define MX28_PAD_GPMI_D00__SSP1_D0 0x0001
+#define MX28_PAD_GPMI_D01__SSP1_D1 0x0011
+#define MX28_PAD_GPMI_D02__SSP1_D2 0x0021
+#define MX28_PAD_GPMI_D03__SSP1_D3 0x0031
+#define MX28_PAD_GPMI_D04__SSP1_D4 0x0041
+#define MX28_PAD_GPMI_D05__SSP1_D5 0x0051
+#define MX28_PAD_GPMI_D06__SSP1_D6 0x0061
+#define MX28_PAD_GPMI_D07__SSP1_D7 0x0071
+#define MX28_PAD_GPMI_CE0N__SSP3_D0 0x0101
+#define MX28_PAD_GPMI_CE1N__SSP3_D3 0x0111
+#define MX28_PAD_GPMI_CE2N__CAN1_TX 0x0121
+#define MX28_PAD_GPMI_CE3N__CAN1_RX 0x0131
+#define MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT 0x0141
+#define MX28_PAD_GPMI_RDY1__SSP1_CMD 0x0151
+#define MX28_PAD_GPMI_RDY2__CAN0_TX 0x0161
+#define MX28_PAD_GPMI_RDY3__CAN0_RX 0x0171
+#define MX28_PAD_GPMI_RDN__SSP3_SCK 0x0181
+#define MX28_PAD_GPMI_WRN__SSP1_SCK 0x0191
+#define MX28_PAD_GPMI_ALE__SSP3_D1 0x01a1
+#define MX28_PAD_GPMI_CLE__SSP3_D2 0x01b1
+#define MX28_PAD_GPMI_RESETN__SSP3_CMD 0x01c1
+#define MX28_PAD_LCD_D03__ETM_DA8 0x1031
+#define MX28_PAD_LCD_D04__ETM_DA9 0x1041
+#define MX28_PAD_LCD_D08__ETM_DA3 0x1081
+#define MX28_PAD_LCD_D09__ETM_DA4 0x1091
+#define MX28_PAD_LCD_D20__ENET1_1588_EVENT2_OUT 0x1141
+#define MX28_PAD_LCD_D21__ENET1_1588_EVENT2_IN 0x1151
+#define MX28_PAD_LCD_D22__ENET1_1588_EVENT3_OUT 0x1161
+#define MX28_PAD_LCD_D23__ENET1_1588_EVENT3_IN 0x1171
+#define MX28_PAD_LCD_RD_E__LCD_VSYNC 0x1181
+#define MX28_PAD_LCD_WR_RWN__LCD_HSYNC 0x1191
+#define MX28_PAD_LCD_RS__LCD_DOTCLK 0x11a1
+#define MX28_PAD_LCD_CS__LCD_ENABLE 0x11b1
+#define MX28_PAD_LCD_VSYNC__SAIF1_SDATA0 0x11c1
+#define MX28_PAD_LCD_HSYNC__SAIF1_SDATA1 0x11d1
+#define MX28_PAD_LCD_DOTCLK__SAIF1_MCLK 0x11e1
+#define MX28_PAD_SSP0_DATA4__SSP2_D0 0x2041
+#define MX28_PAD_SSP0_DATA5__SSP2_D3 0x2051
+#define MX28_PAD_SSP0_DATA6__SSP2_CMD 0x2061
+#define MX28_PAD_SSP0_DATA7__SSP2_SCK 0x2071
+#define MX28_PAD_SSP1_SCK__SSP2_D1 0x20c1
+#define MX28_PAD_SSP1_CMD__SSP2_D2 0x20d1
+#define MX28_PAD_SSP1_DATA0__SSP2_D6 0x20e1
+#define MX28_PAD_SSP1_DATA3__SSP2_D7 0x20f1
+#define MX28_PAD_SSP2_SCK__AUART2_RX 0x2101
+#define MX28_PAD_SSP2_MOSI__AUART2_TX 0x2111
+#define MX28_PAD_SSP2_MISO__AUART3_RX 0x2121
+#define MX28_PAD_SSP2_SS0__AUART3_TX 0x2131
+#define MX28_PAD_SSP2_SS1__SSP2_D1 0x2141
+#define MX28_PAD_SSP2_SS2__SSP2_D2 0x2151
+#define MX28_PAD_SSP3_SCK__AUART4_TX 0x2181
+#define MX28_PAD_SSP3_MOSI__AUART4_RX 0x2191
+#define MX28_PAD_SSP3_MISO__AUART4_RTS 0x21a1
+#define MX28_PAD_SSP3_SS0__AUART4_CTS 0x21b1
+#define MX28_PAD_AUART0_RX__I2C0_SCL 0x3001
+#define MX28_PAD_AUART0_TX__I2C0_SDA 0x3011
+#define MX28_PAD_AUART0_CTS__AUART4_RX 0x3021
+#define MX28_PAD_AUART0_RTS__AUART4_TX 0x3031
+#define MX28_PAD_AUART1_RX__SSP2_CARD_DETECT 0x3041
+#define MX28_PAD_AUART1_TX__SSP3_CARD_DETECT 0x3051
+#define MX28_PAD_AUART1_CTS__USB0_OVERCURRENT 0x3061
+#define MX28_PAD_AUART1_RTS__USB0_ID 0x3071
+#define MX28_PAD_AUART2_RX__SSP3_D1 0x3081
+#define MX28_PAD_AUART2_TX__SSP3_D2 0x3091
+#define MX28_PAD_AUART2_CTS__I2C1_SCL 0x30a1
+#define MX28_PAD_AUART2_RTS__I2C1_SDA 0x30b1
+#define MX28_PAD_AUART3_RX__CAN0_TX 0x30c1
+#define MX28_PAD_AUART3_TX__CAN0_RX 0x30d1
+#define MX28_PAD_AUART3_CTS__CAN1_TX 0x30e1
+#define MX28_PAD_AUART3_RTS__CAN1_RX 0x30f1
+#define MX28_PAD_PWM0__I2C1_SCL 0x3101
+#define MX28_PAD_PWM1__I2C1_SDA 0x3111
+#define MX28_PAD_PWM2__USB0_ID 0x3121
+#define MX28_PAD_SAIF0_MCLK__PWM_3 0x3141
+#define MX28_PAD_SAIF0_LRCLK__PWM_4 0x3151
+#define MX28_PAD_SAIF0_BITCLK__PWM_5 0x3161
+#define MX28_PAD_SAIF0_SDATA0__PWM_6 0x3171
+#define MX28_PAD_I2C0_SCL__TIMROT_ROTARYA 0x3181
+#define MX28_PAD_I2C0_SDA__TIMROT_ROTARYB 0x3191
+#define MX28_PAD_SAIF1_SDATA0__PWM_7 0x31a1
+#define MX28_PAD_LCD_RESET__LCD_VSYNC 0x31e1
+#define MX28_PAD_ENET0_MDC__GPMI_CE4N 0x4001
+#define MX28_PAD_ENET0_MDIO__GPMI_CE5N 0x4011
+#define MX28_PAD_ENET0_RX_EN__GPMI_CE6N 0x4021
+#define MX28_PAD_ENET0_RXD0__GPMI_CE7N 0x4031
+#define MX28_PAD_ENET0_RXD1__GPMI_READY4 0x4041
+#define MX28_PAD_ENET0_TX_CLK__HSADC_TRIGGER 0x4051
+#define MX28_PAD_ENET0_TX_EN__GPMI_READY5 0x4061
+#define MX28_PAD_ENET0_TXD0__GPMI_READY6 0x4071
+#define MX28_PAD_ENET0_TXD1__GPMI_READY7 0x4081
+#define MX28_PAD_ENET0_RXD2__ENET1_RXD0 0x4091
+#define MX28_PAD_ENET0_RXD3__ENET1_RXD1 0x40a1
+#define MX28_PAD_ENET0_TXD2__ENET1_TXD0 0x40b1
+#define MX28_PAD_ENET0_TXD3__ENET1_TXD1 0x40c1
+#define MX28_PAD_ENET0_RX_CLK__ENET0_RX_ER 0x40d1
+#define MX28_PAD_ENET0_COL__ENET1_TX_EN 0x40e1
+#define MX28_PAD_ENET0_CRS__ENET1_RX_EN 0x40f1
+#define MX28_PAD_GPMI_CE2N__ENET0_RX_ER 0x0122
+#define MX28_PAD_GPMI_CE3N__SAIF1_MCLK 0x0132
+#define MX28_PAD_GPMI_RDY0__USB0_ID 0x0142
+#define MX28_PAD_GPMI_RDY2__ENET0_TX_ER 0x0162
+#define MX28_PAD_GPMI_RDY3__HSADC_TRIGGER 0x0172
+#define MX28_PAD_GPMI_ALE__SSP3_D4 0x01a2
+#define MX28_PAD_GPMI_CLE__SSP3_D5 0x01b2
+#define MX28_PAD_LCD_D00__ETM_DA0 0x1002
+#define MX28_PAD_LCD_D01__ETM_DA1 0x1012
+#define MX28_PAD_LCD_D02__ETM_DA2 0x1022
+#define MX28_PAD_LCD_D03__ETM_DA3 0x1032
+#define MX28_PAD_LCD_D04__ETM_DA4 0x1042
+#define MX28_PAD_LCD_D05__ETM_DA5 0x1052
+#define MX28_PAD_LCD_D06__ETM_DA6 0x1062
+#define MX28_PAD_LCD_D07__ETM_DA7 0x1072
+#define MX28_PAD_LCD_D08__ETM_DA8 0x1082
+#define MX28_PAD_LCD_D09__ETM_DA9 0x1092
+#define MX28_PAD_LCD_D10__ETM_DA10 0x10a2
+#define MX28_PAD_LCD_D11__ETM_DA11 0x10b2
+#define MX28_PAD_LCD_D12__ETM_DA12 0x10c2
+#define MX28_PAD_LCD_D13__ETM_DA13 0x10d2
+#define MX28_PAD_LCD_D14__ETM_DA14 0x10e2
+#define MX28_PAD_LCD_D15__ETM_DA15 0x10f2
+#define MX28_PAD_LCD_D16__ETM_DA7 0x1102
+#define MX28_PAD_LCD_D17__ETM_DA6 0x1112
+#define MX28_PAD_LCD_D18__ETM_DA5 0x1122
+#define MX28_PAD_LCD_D19__ETM_DA4 0x1132
+#define MX28_PAD_LCD_D20__ETM_DA3 0x1142
+#define MX28_PAD_LCD_D21__ETM_DA2 0x1152
+#define MX28_PAD_LCD_D22__ETM_DA1 0x1162
+#define MX28_PAD_LCD_D23__ETM_DA0 0x1172
+#define MX28_PAD_LCD_RD_E__ETM_TCTL 0x1182
+#define MX28_PAD_LCD_WR_RWN__ETM_TCLK 0x1192
+#define MX28_PAD_LCD_HSYNC__ETM_TCTL 0x11d2
+#define MX28_PAD_LCD_DOTCLK__ETM_TCLK 0x11e2
+#define MX28_PAD_SSP1_SCK__ENET0_1588_EVENT2_OUT 0x20c2
+#define MX28_PAD_SSP1_CMD__ENET0_1588_EVENT2_IN 0x20d2
+#define MX28_PAD_SSP1_DATA0__ENET0_1588_EVENT3_OUT 0x20e2
+#define MX28_PAD_SSP1_DATA3__ENET0_1588_EVENT3_IN 0x20f2
+#define MX28_PAD_SSP2_SCK__SAIF0_SDATA1 0x2102
+#define MX28_PAD_SSP2_MOSI__SAIF0_SDATA2 0x2112
+#define MX28_PAD_SSP2_MISO__SAIF1_SDATA1 0x2122
+#define MX28_PAD_SSP2_SS0__SAIF1_SDATA2 0x2132
+#define MX28_PAD_SSP2_SS1__USB1_OVERCURRENT 0x2142
+#define MX28_PAD_SSP2_SS2__USB0_OVERCURRENT 0x2152
+#define MX28_PAD_SSP3_SCK__ENET1_1588_EVENT0_OUT 0x2182
+#define MX28_PAD_SSP3_MOSI__ENET1_1588_EVENT0_IN 0x2192
+#define MX28_PAD_SSP3_MISO__ENET1_1588_EVENT1_OUT 0x21a2
+#define MX28_PAD_SSP3_SS0__ENET1_1588_EVENT1_IN 0x21b2
+#define MX28_PAD_AUART0_RX__DUART_CTS 0x3002
+#define MX28_PAD_AUART0_TX__DUART_RTS 0x3012
+#define MX28_PAD_AUART0_CTS__DUART_RX 0x3022
+#define MX28_PAD_AUART0_RTS__DUART_TX 0x3032
+#define MX28_PAD_AUART1_RX__PWM_0 0x3042
+#define MX28_PAD_AUART1_TX__PWM_1 0x3052
+#define MX28_PAD_AUART1_CTS__TIMROT_ROTARYA 0x3062
+#define MX28_PAD_AUART1_RTS__TIMROT_ROTARYB 0x3072
+#define MX28_PAD_AUART2_RX__SSP3_D4 0x3082
+#define MX28_PAD_AUART2_TX__SSP3_D5 0x3092
+#define MX28_PAD_AUART2_CTS__SAIF1_BITCLK 0x30a2
+#define MX28_PAD_AUART2_RTS__SAIF1_LRCLK 0x30b2
+#define MX28_PAD_AUART3_RX__ENET0_1588_EVENT0_OUT 0x30c2
+#define MX28_PAD_AUART3_TX__ENET0_1588_EVENT0_IN 0x30d2
+#define MX28_PAD_AUART3_CTS__ENET0_1588_EVENT1_OUT 0x30e2
+#define MX28_PAD_AUART3_RTS__ENET0_1588_EVENT1_IN 0x30f2
+#define MX28_PAD_PWM0__DUART_RX 0x3102
+#define MX28_PAD_PWM1__DUART_TX 0x3112
+#define MX28_PAD_PWM2__USB1_OVERCURRENT 0x3122
+#define MX28_PAD_SAIF0_MCLK__AUART4_CTS 0x3142
+#define MX28_PAD_SAIF0_LRCLK__AUART4_RTS 0x3152
+#define MX28_PAD_SAIF0_BITCLK__AUART4_RX 0x3162
+#define MX28_PAD_SAIF0_SDATA0__AUART4_TX 0x3172
+#define MX28_PAD_I2C0_SCL__DUART_RX 0x3182
+#define MX28_PAD_I2C0_SDA__DUART_TX 0x3192
+#define MX28_PAD_SAIF1_SDATA0__SAIF0_SDATA1 0x31a2
+#define MX28_PAD_SPDIF__ENET1_RX_ER 0x31b2
+#define MX28_PAD_ENET0_MDC__SAIF0_SDATA1 0x4002
+#define MX28_PAD_ENET0_MDIO__SAIF0_SDATA2 0x4012
+#define MX28_PAD_ENET0_RX_EN__SAIF1_SDATA1 0x4022
+#define MX28_PAD_ENET0_RXD0__SAIF1_SDATA2 0x4032
+#define MX28_PAD_ENET0_TX_CLK__ENET0_1588_EVENT2_OUT 0x4052
+#define MX28_PAD_ENET0_RXD2__ENET0_1588_EVENT0_OUT 0x4092
+#define MX28_PAD_ENET0_RXD3__ENET0_1588_EVENT0_IN 0x40a2
+#define MX28_PAD_ENET0_TXD2__ENET0_1588_EVENT1_OUT 0x40b2
+#define MX28_PAD_ENET0_TXD3__ENET0_1588_EVENT1_IN 0x40c2
+#define MX28_PAD_ENET0_RX_CLK__ENET0_1588_EVENT2_IN 0x40d2
+#define MX28_PAD_ENET0_COL__ENET0_1588_EVENT3_OUT 0x40e2
+#define MX28_PAD_ENET0_CRS__ENET0_1588_EVENT3_IN 0x40f2
+#define MX28_PAD_GPMI_D00__GPIO_0_0 0x0003
+#define MX28_PAD_GPMI_D01__GPIO_0_1 0x0013
+#define MX28_PAD_GPMI_D02__GPIO_0_2 0x0023
+#define MX28_PAD_GPMI_D03__GPIO_0_3 0x0033
+#define MX28_PAD_GPMI_D04__GPIO_0_4 0x0043
+#define MX28_PAD_GPMI_D05__GPIO_0_5 0x0053
+#define MX28_PAD_GPMI_D06__GPIO_0_6 0x0063
+#define MX28_PAD_GPMI_D07__GPIO_0_7 0x0073
+#define MX28_PAD_GPMI_CE0N__GPIO_0_16 0x0103
+#define MX28_PAD_GPMI_CE1N__GPIO_0_17 0x0113
+#define MX28_PAD_GPMI_CE2N__GPIO_0_18 0x0123
+#define MX28_PAD_GPMI_CE3N__GPIO_0_19 0x0133
+#define MX28_PAD_GPMI_RDY0__GPIO_0_20 0x0143
+#define MX28_PAD_GPMI_RDY1__GPIO_0_21 0x0153
+#define MX28_PAD_GPMI_RDY2__GPIO_0_22 0x0163
+#define MX28_PAD_GPMI_RDY3__GPIO_0_23 0x0173
+#define MX28_PAD_GPMI_RDN__GPIO_0_24 0x0183
+#define MX28_PAD_GPMI_WRN__GPIO_0_25 0x0193
+#define MX28_PAD_GPMI_ALE__GPIO_0_26 0x01a3
+#define MX28_PAD_GPMI_CLE__GPIO_0_27 0x01b3
+#define MX28_PAD_GPMI_RESETN__GPIO_0_28 0x01c3
+#define MX28_PAD_LCD_D00__GPIO_1_0 0x1003
+#define MX28_PAD_LCD_D01__GPIO_1_1 0x1013
+#define MX28_PAD_LCD_D02__GPIO_1_2 0x1023
+#define MX28_PAD_LCD_D03__GPIO_1_3 0x1033
+#define MX28_PAD_LCD_D04__GPIO_1_4 0x1043
+#define MX28_PAD_LCD_D05__GPIO_1_5 0x1053
+#define MX28_PAD_LCD_D06__GPIO_1_6 0x1063
+#define MX28_PAD_LCD_D07__GPIO_1_7 0x1073
+#define MX28_PAD_LCD_D08__GPIO_1_8 0x1083
+#define MX28_PAD_LCD_D09__GPIO_1_9 0x1093
+#define MX28_PAD_LCD_D10__GPIO_1_10 0x10a3
+#define MX28_PAD_LCD_D11__GPIO_1_11 0x10b3
+#define MX28_PAD_LCD_D12__GPIO_1_12 0x10c3
+#define MX28_PAD_LCD_D13__GPIO_1_13 0x10d3
+#define MX28_PAD_LCD_D14__GPIO_1_14 0x10e3
+#define MX28_PAD_LCD_D15__GPIO_1_15 0x10f3
+#define MX28_PAD_LCD_D16__GPIO_1_16 0x1103
+#define MX28_PAD_LCD_D17__GPIO_1_17 0x1113
+#define MX28_PAD_LCD_D18__GPIO_1_18 0x1123
+#define MX28_PAD_LCD_D19__GPIO_1_19 0x1133
+#define MX28_PAD_LCD_D20__GPIO_1_20 0x1143
+#define MX28_PAD_LCD_D21__GPIO_1_21 0x1153
+#define MX28_PAD_LCD_D22__GPIO_1_22 0x1163
+#define MX28_PAD_LCD_D23__GPIO_1_23 0x1173
+#define MX28_PAD_LCD_RD_E__GPIO_1_24 0x1183
+#define MX28_PAD_LCD_WR_RWN__GPIO_1_25 0x1193
+#define MX28_PAD_LCD_RS__GPIO_1_26 0x11a3
+#define MX28_PAD_LCD_CS__GPIO_1_27 0x11b3
+#define MX28_PAD_LCD_VSYNC__GPIO_1_28 0x11c3
+#define MX28_PAD_LCD_HSYNC__GPIO_1_29 0x11d3
+#define MX28_PAD_LCD_DOTCLK__GPIO_1_30 0x11e3
+#define MX28_PAD_LCD_ENABLE__GPIO_1_31 0x11f3
+#define MX28_PAD_SSP0_DATA0__GPIO_2_0 0x2003
+#define MX28_PAD_SSP0_DATA1__GPIO_2_1 0x2013
+#define MX28_PAD_SSP0_DATA2__GPIO_2_2 0x2023
+#define MX28_PAD_SSP0_DATA3__GPIO_2_3 0x2033
+#define MX28_PAD_SSP0_DATA4__GPIO_2_4 0x2043
+#define MX28_PAD_SSP0_DATA5__GPIO_2_5 0x2053
+#define MX28_PAD_SSP0_DATA6__GPIO_2_6 0x2063
+#define MX28_PAD_SSP0_DATA7__GPIO_2_7 0x2073
+#define MX28_PAD_SSP0_CMD__GPIO_2_8 0x2083
+#define MX28_PAD_SSP0_DETECT__GPIO_2_9 0x2093
+#define MX28_PAD_SSP0_SCK__GPIO_2_10 0x20a3
+#define MX28_PAD_SSP1_SCK__GPIO_2_12 0x20c3
+#define MX28_PAD_SSP1_CMD__GPIO_2_13 0x20d3
+#define MX28_PAD_SSP1_DATA0__GPIO_2_14 0x20e3
+#define MX28_PAD_SSP1_DATA3__GPIO_2_15 0x20f3
+#define MX28_PAD_SSP2_SCK__GPIO_2_16 0x2103
+#define MX28_PAD_SSP2_MOSI__GPIO_2_17 0x2113
+#define MX28_PAD_SSP2_MISO__GPIO_2_18 0x2123
+#define MX28_PAD_SSP2_SS0__GPIO_2_19 0x2133
+#define MX28_PAD_SSP2_SS1__GPIO_2_20 0x2143
+#define MX28_PAD_SSP2_SS2__GPIO_2_21 0x2153
+#define MX28_PAD_SSP3_SCK__GPIO_2_24 0x2183
+#define MX28_PAD_SSP3_MOSI__GPIO_2_25 0x2193
+#define MX28_PAD_SSP3_MISO__GPIO_2_26 0x21a3
+#define MX28_PAD_SSP3_SS0__GPIO_2_27 0x21b3
+#define MX28_PAD_AUART0_RX__GPIO_3_0 0x3003
+#define MX28_PAD_AUART0_TX__GPIO_3_1 0x3013
+#define MX28_PAD_AUART0_CTS__GPIO_3_2 0x3023
+#define MX28_PAD_AUART0_RTS__GPIO_3_3 0x3033
+#define MX28_PAD_AUART1_RX__GPIO_3_4 0x3043
+#define MX28_PAD_AUART1_TX__GPIO_3_5 0x3053
+#define MX28_PAD_AUART1_CTS__GPIO_3_6 0x3063
+#define MX28_PAD_AUART1_RTS__GPIO_3_7 0x3073
+#define MX28_PAD_AUART2_RX__GPIO_3_8 0x3083
+#define MX28_PAD_AUART2_TX__GPIO_3_9 0x3093
+#define MX28_PAD_AUART2_CTS__GPIO_3_10 0x30a3
+#define MX28_PAD_AUART2_RTS__GPIO_3_11 0x30b3
+#define MX28_PAD_AUART3_RX__GPIO_3_12 0x30c3
+#define MX28_PAD_AUART3_TX__GPIO_3_13 0x30d3
+#define MX28_PAD_AUART3_CTS__GPIO_3_14 0x30e3
+#define MX28_PAD_AUART3_RTS__GPIO_3_15 0x30f3
+#define MX28_PAD_PWM0__GPIO_3_16 0x3103
+#define MX28_PAD_PWM1__GPIO_3_17 0x3113
+#define MX28_PAD_PWM2__GPIO_3_18 0x3123
+#define MX28_PAD_SAIF0_MCLK__GPIO_3_20 0x3143
+#define MX28_PAD_SAIF0_LRCLK__GPIO_3_21 0x3153
+#define MX28_PAD_SAIF0_BITCLK__GPIO_3_22 0x3163
+#define MX28_PAD_SAIF0_SDATA0__GPIO_3_23 0x3173
+#define MX28_PAD_I2C0_SCL__GPIO_3_24 0x3183
+#define MX28_PAD_I2C0_SDA__GPIO_3_25 0x3193
+#define MX28_PAD_SAIF1_SDATA0__GPIO_3_26 0x31a3
+#define MX28_PAD_SPDIF__GPIO_3_27 0x31b3
+#define MX28_PAD_PWM3__GPIO_3_28 0x31c3
+#define MX28_PAD_PWM4__GPIO_3_29 0x31d3
+#define MX28_PAD_LCD_RESET__GPIO_3_30 0x31e3
+#define MX28_PAD_ENET0_MDC__GPIO_4_0 0x4003
+#define MX28_PAD_ENET0_MDIO__GPIO_4_1 0x4013
+#define MX28_PAD_ENET0_RX_EN__GPIO_4_2 0x4023
+#define MX28_PAD_ENET0_RXD0__GPIO_4_3 0x4033
+#define MX28_PAD_ENET0_RXD1__GPIO_4_4 0x4043
+#define MX28_PAD_ENET0_TX_CLK__GPIO_4_5 0x4053
+#define MX28_PAD_ENET0_TX_EN__GPIO_4_6 0x4063
+#define MX28_PAD_ENET0_TXD0__GPIO_4_7 0x4073
+#define MX28_PAD_ENET0_TXD1__GPIO_4_8 0x4083
+#define MX28_PAD_ENET0_RXD2__GPIO_4_9 0x4093
+#define MX28_PAD_ENET0_RXD3__GPIO_4_10 0x40a3
+#define MX28_PAD_ENET0_TXD2__GPIO_4_11 0x40b3
+#define MX28_PAD_ENET0_TXD3__GPIO_4_12 0x40c3
+#define MX28_PAD_ENET0_RX_CLK__GPIO_4_13 0x40d3
+#define MX28_PAD_ENET0_COL__GPIO_4_14 0x40e3
+#define MX28_PAD_ENET0_CRS__GPIO_4_15 0x40f3
+#define MX28_PAD_ENET_CLK__GPIO_4_16 0x4103
+#define MX28_PAD_JTAG_RTCK__GPIO_4_20 0x4143
+
+#endif /* __DT_BINDINGS_MX28_PINCTRL_H__ */
diff --git a/arch/arm/boot/dts/imx28-sps1.dts b/arch/arm/boot/dts/imx28-sps1.dts
index 6c6a5442800a..4870f07bf56a 100644
--- a/arch/arm/boot/dts/imx28-sps1.dts
+++ b/arch/arm/boot/dts/imx28-sps1.dts
@@ -10,7 +10,7 @@
*/
/dts-v1/;
-/include/ "imx28.dtsi"
+#include "imx28.dtsi"
/ {
model = "SchulerControl GmbH, SC SPS 1";
@@ -29,13 +29,13 @@
hog_pins_a: hog-gpios@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x0003 /* MX28_PAD_GPMI_D00__GPIO_0_0 */
- 0x0033 /* MX28_PAD_GPMI_D03__GPIO_0_3 */
- 0x0063 /* MX28_PAD_GPMI_D06__GPIO_0_6 */
+ MX28_PAD_GPMI_D00__GPIO_0_0
+ MX28_PAD_GPMI_D03__GPIO_0_3
+ MX28_PAD_GPMI_D06__GPIO_0_6
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
};
diff --git a/arch/arm/boot/dts/imx28-tx28.dts b/arch/arm/boot/dts/imx28-tx28.dts
index 37be532f0055..be5a0550d58c 100644
--- a/arch/arm/boot/dts/imx28-tx28.dts
+++ b/arch/arm/boot/dts/imx28-tx28.dts
@@ -1,106 +1,139 @@
+/*
+ * Copyright 2012 Shawn Guo <shawn.guo@linaro.org>
+ * Copyright 2013 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
/dts-v1/;
-/include/ "imx28.dtsi"
+#include "imx28.dtsi"
+#include <dt-bindings/gpio/gpio.h>
/ {
model = "Ka-Ro electronics TX28 module";
compatible = "karo,tx28", "fsl,imx28";
+ aliases {
+ can0 = &can0;
+ can1 = &can1;
+ display = &display;
+ ds1339 = &ds1339;
+ gpio5 = &gpio5;
+ lcdif = &lcdif;
+ lcdif_23bit_pins = &tx28_lcdif_23bit_pins;
+ lcdif_24bit_pins = &lcdif_24bit_pins_a;
+ stk5led = &user_led;
+ usbotg = &usb0;
+ };
+
memory {
- reg = <0x40000000 0x08000000>;
- };
-
- apb@80000000 {
- apbh@80000000 {
- ssp0: ssp@80010000 {
- compatible = "fsl,imx28-mmc";
- pinctrl-names = "default";
- pinctrl-0 = <&mmc0_4bit_pins_a
- &mmc0_cd_cfg
- &mmc0_sck_cfg>;
- bus-width = <4>;
- status = "okay";
- };
+ reg = <0 0>; /* will be filled in by U-Boot */
+ };
- pinctrl@80018000 {
- pinctrl-names = "default";
- pinctrl-0 = <&hog_pins_a>;
-
- hog_pins_a: hog@0 {
- reg = <0>;
- fsl,pinmux-ids = <
- 0x40a3 /* MX28_PAD_ENET0_RXD3__GPIO_4_10 */
- >;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
- };
-
- mac0_pins_gpio: mac0-gpio-mode@0 {
- reg = <0>;
- fsl,pinmux-ids = <
- 0x4003 /* MX28_PAD_ENET0_MDC__GPIO_4_0 */
- 0x4013 /* MX28_PAD_ENET0_MDIO__GPIO_4_1 */
- 0x4023 /* MX28_PAD_ENET0_RX_EN__GPIO_4_2 */
- 0x4033 /* MX28_PAD_ENET0_RXD0__GPIO_4_3 */
- 0x4043 /* MX28_PAD_ENET0_RXD1__GPIO_4_4 */
- 0x4063 /* MX28_PAD_ENET0_TX_EN__GPIO_4_6 */
- 0x4073 /* MX28_PAD_ENET0_TXD0__GPIO_4_7 */
- 0x4083 /* MX28_PAD_ENET0_TXD1__GPIO_4_8 */
- 0x4103 /* MX28_PAD_ENET_CLK__GPIO_4_16 */
- >;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
- };
- };
+ onewire {
+ compatible = "w1-gpio";
+ gpios = <&gpio2 7 0>;
+ status = "disabled";
+ };
+
+ regulators {
+ compatible = "simple-bus";
+
+ reg_usb0_vbus: usb0_vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb0_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio0 18 0>;
+ enable-active-high;
};
- apbx@80040000 {
- i2c0: i2c@80058000 {
- pinctrl-names = "default";
- pinctrl-0 = <&i2c0_pins_a>;
- status = "okay";
+ reg_usb1_vbus: usb1_vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio3 27 0>;
+ enable-active-high;
+ };
- ds1339: rtc@68 {
- compatible = "mxim,ds1339";
- reg = <0x68>;
- };
- };
+ reg_2p5v: 2p5v {
+ compatible = "regulator-fixed";
+ regulator-name = "2P5V";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-always-on;
+ };
- pwm: pwm@80064000 {
- pinctrl-names = "default";
- pinctrl-0 = <&pwm0_pins_a>;
- status = "okay";
- };
+ reg_3p3v: 3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
- duart: serial@80074000 {
- pinctrl-names = "default";
- pinctrl-0 = <&duart_4pins_a>;
- status = "okay";
- };
+ reg_can_xcvr: can-xcvr {
+ compatible = "regulator-fixed";
+ regulator-name = "CAN XCVR";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 0 0>;
+ enable-active-low;
+ pinctrl-names = "default";
+ pinctrl-0 = <&tx28_flexcan_xcvr_pins>;
+ };
- auart1: serial@8006c000 {
- pinctrl-names = "default";
- pinctrl-0 = <&auart1_pins_a>;
- status = "okay";
- };
+ reg_lcd: lcd-power {
+ compatible = "regulator-fixed";
+ regulator-name = "LCD POWER";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 31 0>;
+ enable-active-high;
+ };
+
+ reg_lcd_reset: lcd-reset {
+ compatible = "regulator-fixed";
+ regulator-name = "LCD RESET";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio3 30 0>;
+ startup-delay-us = <300000>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-boot-on;
};
};
- ahb@80080000 {
- mac0: ethernet@800f0000 {
- phy-mode = "rmii";
- pinctrl-names = "default", "gpio_mode";
- pinctrl-0 = <&mac0_pins_a>;
- pinctrl-1 = <&mac0_pins_gpio>;
- status = "okay";
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ mclk: clock@0 {
+ compatible = "fixed-clock";
+ reg = <0>;
+ #clock-cells = <0>;
+ clock-frequency = <27000000>;
};
};
+ sound {
+ compatible = "fsl,imx28-tx28-sgtl5000",
+ "fsl,mxs-audio-sgtl5000";
+ model = "imx28-tx28-sgtl5000";
+ saif-controllers = <&saif0 &saif1>;
+ audio-codec = <&sgtl5000>;
+ };
+
leds {
compatible = "gpio-leds";
- user {
+ user_led: user {
label = "Heartbeat";
gpios = <&gpio4 10 0>;
linux,default-trigger = "heartbeat";
@@ -109,8 +142,512 @@
backlight {
compatible = "pwm-backlight";
- pwms = <&pwm 0 5000000>;
- brightness-levels = <0 4 8 16 32 64 128 255>;
- default-brightness-level = <6>;
+ pwms = <&pwm 0 500000>;
+ /*
+ * a silly way to create a 1:1 relationship between the
+ * PWM value and the actual duty cycle
+ */
+ brightness-levels = < 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 32 33 34 35 36 37 38 39
+ 40 41 42 43 44 45 46 47 48 49
+ 50 51 52 53 54 55 56 57 58 59
+ 60 61 62 63 64 65 66 67 68 69
+ 70 71 72 73 74 75 76 77 78 79
+ 80 81 82 83 84 85 86 87 88 89
+ 90 91 92 93 94 95 96 97 98 99
+ 100>;
+ default-brightness-level = <50>;
+ };
+
+ matrix_keypad: matrix-keypad@0 {
+ compatible = "gpio-matrix-keypad";
+ col-gpios = <
+ &gpio5 0 0
+ &gpio5 1 0
+ &gpio5 2 0
+ &gpio5 3 0
+ >;
+ row-gpios = <
+ &gpio5 4 0
+ &gpio5 5 0
+ &gpio5 6 0
+ &gpio5 7 0
+ >;
+ /* sample keymap */
+ linux,keymap = <
+ 0x00000074 /* row 0, col 0, KEY_POWER */
+ 0x00010052 /* row 0, col 1, KEY_KP0 */
+ 0x0002004f /* row 0, col 2, KEY_KP1 */
+ 0x00030050 /* row 0, col 3, KEY_KP2 */
+ 0x01000051 /* row 1, col 0, KEY_KP3 */
+ 0x0101004b /* row 1, col 1, KEY_KP4 */
+ 0x0102004c /* row 1, col 2, KEY_KP5 */
+ 0x0103004d /* row 1, col 3, KEY_KP6 */
+ 0x02000047 /* row 2, col 0, KEY_KP7 */
+ 0x02010048 /* row 2, col 1, KEY_KP8 */
+ 0x02020049 /* row 2, col 2, KEY_KP9 */
+ >;
+ gpio-activelow;
+ linux,wakeup;
+ debounce-delay-ms = <100>;
+ col-scan-delay-us = <5000>;
+ linux,no-autorepeat;
+ };
+};
+
+/* 2nd TX-Std UART - (A)UART1 */
+&auart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&auart1_pins_a>;
+ status = "okay";
+};
+
+/* 3rd TX-Std UART - (A)UART3 */
+&auart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&auart3_pins_a>;
+ status = "okay";
+};
+
+&can0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&can0_pins_a>;
+ xceiver-supply = <&reg_can_xcvr>;
+ status = "okay";
+};
+
+&can1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&can1_pins_a>;
+ xceiver-supply = <&reg_can_xcvr>;
+ status = "okay";
+};
+
+&digctl {
+ status = "okay";
+};
+
+/* 1st TX-Std UART - (D)UART */
+&duart {
+ pinctrl-names = "default";
+ pinctrl-0 = <&duart_4pins_a>;
+ status = "okay";
+};
+
+&gpmi {
+ pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg>;
+ nand-on-flash-bbt;
+ status = "okay";
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ clock-frequency = <400000>;
+ status = "okay";
+
+ sgtl5000: sgtl5000@0a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ VDDA-supply = <&reg_2p5v>;
+ VDDIO-supply = <&reg_3p3v>;
+ clocks = <&mclk>;
+ };
+
+ gpio5: pca953x@20 {
+ compatible = "nxp,pca9554";
+ reg = <0x20>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&tx28_pca9554_pins>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <28 0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ polytouch: edt-ft5x06@38 {
+ compatible = "edt,edt-ft5x06";
+ reg = <0x38>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&tx28_edt_ft5x06_pins>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <5 0>;
+ reset-gpios = <&gpio2 6 1>;
+ wake-gpios = <&gpio4 9 0>;
+ };
+
+ touchscreen: tsc2007@48 {
+ compatible = "ti,tsc2007";
+ reg = <0x48>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&tx28_tsc2007_pins>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <20 0>;
+ pendown-gpio = <&gpio3 20 1>;
+ ti,x-plate-ohms = /bits/ 16 <660>;
+ };
+
+ ds1339: rtc@68 {
+ compatible = "mxim,ds1339";
+ reg = <0x68>;
+ };
+};
+
+&lcdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcdif_24bit_pins_a &lcdif_sync_pins_a &tx28_lcdif_ctrl_pins>;
+ lcd-supply = <&reg_lcd>;
+ display = <&display>;
+ status = "okay";
+
+ display: display@0 {
+ bits-per-pixel = <32>;
+ bus-width = <24>;
+ display-timings {
+ native-mode = <&timing5>;
+ timing0: timing0 {
+ panel-name = "VGA";
+ clock-frequency = <25175000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <48>;
+ hsync-len = <96>;
+ hfront-porch = <16>;
+ vback-porch = <33>;
+ vsync-len = <2>;
+ vfront-porch = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+
+ timing1: timing1 {
+ panel-name = "ETV570";
+ clock-frequency = <25175000>;
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <114>;
+ hsync-len = <30>;
+ hfront-porch = <16>;
+ vback-porch = <32>;
+ vsync-len = <3>;
+ vfront-porch = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+
+ timing2: timing2 {
+ panel-name = "ET0350";
+ clock-frequency = <6500000>;
+ hactive = <320>;
+ vactive = <240>;
+ hback-porch = <34>;
+ hsync-len = <34>;
+ hfront-porch = <20>;
+ vback-porch = <15>;
+ vsync-len = <3>;
+ vfront-porch = <4>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+
+ timing3: timing3 {
+ panel-name = "ET0430";
+ clock-frequency = <9000000>;
+ hactive = <480>;
+ vactive = <272>;
+ hback-porch = <2>;
+ hsync-len = <41>;
+ hfront-porch = <2>;
+ vback-porch = <2>;
+ vsync-len = <10>;
+ vfront-porch = <2>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+
+ timing4: timing4 {
+ panel-name = "ET0500", "ET0700";
+ clock-frequency = <33260000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <88>;
+ hsync-len = <128>;
+ hfront-porch = <40>;
+ vback-porch = <33>;
+ vsync-len = <2>;
+ vfront-porch = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+
+ timing5: timing5 {
+ panel-name = "ETQ570";
+ clock-frequency = <6400000>;
+ hactive = <320>;
+ vactive = <240>;
+ hback-porch = <38>;
+ hsync-len = <30>;
+ hfront-porch = <30>;
+ vback-porch = <16>;
+ vsync-len = <3>;
+ vfront-porch = <4>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+ };
+ };
+};
+
+&lradc {
+ fsl,lradc-touchscreen-wires = <4>;
+ status = "okay";
+};
+
+&mac0 {
+ phy-mode = "rmii";
+ pinctrl-names = "default", "gpio_mode";
+ pinctrl-0 = <&mac0_pins_a>;
+ pinctrl-1 = <&tx28_mac0_pins_gpio>;
+ status = "okay";
+};
+
+&mac1 {
+ phy-mode = "rmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mac1_pins_a>;
+ /* not enabled by default */
+};
+
+&mxs_rtc {
+ status = "okay";
+};
+
+&ocotp {
+ status = "okay";
+};
+
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0_pins_a>;
+ status = "okay";
+};
+
+&pinctrl {
+ pinctrl-names = "default";
+ pinctrl-0 = <&hog_pins_a>;
+
+ hog_pins_a: hog@0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ MX28_PAD_ENET0_RXD3__GPIO_4_10 /* module LED */
+ >;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
+ };
+
+ tx28_edt_ft5x06_pins: tx28-edt-ft5x06-pins {
+ fsl,pinmux-ids = <
+ MX28_PAD_SSP0_DATA6__GPIO_2_6 /* RESET */
+ MX28_PAD_SSP0_DATA5__GPIO_2_5 /* IRQ */
+ MX28_PAD_ENET0_RXD2__GPIO_4_9 /* WAKE */
+ >;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
+ };
+
+ tx28_flexcan_xcvr_pins: tx28-flexcan-xcvr-pins {
+ fsl,pinmux-ids = <
+ MX28_PAD_LCD_D00__GPIO_1_0
+ >;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
+ };
+
+ tx28_lcdif_23bit_pins: tx28-lcdif-23bit {
+ fsl,pinmux-ids = <
+ /* LCD_D00 may be used as Flexcan Transceiver Enable on STK5-V5 */
+ MX28_PAD_LCD_D01__LCD_D1
+ MX28_PAD_LCD_D02__LCD_D2
+ MX28_PAD_LCD_D03__LCD_D3
+ MX28_PAD_LCD_D04__LCD_D4
+ MX28_PAD_LCD_D05__LCD_D5
+ MX28_PAD_LCD_D06__LCD_D6
+ MX28_PAD_LCD_D07__LCD_D7
+ MX28_PAD_LCD_D08__LCD_D8
+ MX28_PAD_LCD_D09__LCD_D9
+ MX28_PAD_LCD_D10__LCD_D10
+ MX28_PAD_LCD_D11__LCD_D11
+ MX28_PAD_LCD_D12__LCD_D12
+ MX28_PAD_LCD_D13__LCD_D13
+ MX28_PAD_LCD_D14__LCD_D14
+ MX28_PAD_LCD_D15__LCD_D15
+ MX28_PAD_LCD_D16__LCD_D16
+ MX28_PAD_LCD_D17__LCD_D17
+ MX28_PAD_LCD_D18__LCD_D18
+ MX28_PAD_LCD_D19__LCD_D19
+ MX28_PAD_LCD_D20__LCD_D20
+ MX28_PAD_LCD_D21__LCD_D21
+ MX28_PAD_LCD_D22__LCD_D22
+ MX28_PAD_LCD_D23__LCD_D23
+ >;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
+ };
+
+ tx28_lcdif_ctrl_pins: tx28-lcdif-ctrl {
+ fsl,pinmux-ids = <
+ MX28_PAD_LCD_ENABLE__GPIO_1_31 /* Enable */
+ MX28_PAD_LCD_RESET__GPIO_3_30 /* Reset */
+ >;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
+ };
+
+ tx28_mac0_pins_gpio: tx28-mac0-gpio-pins {
+ fsl,pinmux-ids = <
+ MX28_PAD_ENET0_MDC__GPIO_4_0
+ MX28_PAD_ENET0_MDIO__GPIO_4_1
+ MX28_PAD_ENET0_RX_EN__GPIO_4_2
+ MX28_PAD_ENET0_RXD0__GPIO_4_3
+ MX28_PAD_ENET0_RXD1__GPIO_4_4
+ MX28_PAD_ENET0_TX_EN__GPIO_4_6
+ MX28_PAD_ENET0_TXD0__GPIO_4_7
+ MX28_PAD_ENET0_TXD1__GPIO_4_8
+ MX28_PAD_ENET_CLK__GPIO_4_16
+ >;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
+ };
+
+ tx28_pca9554_pins: tx28-pca9554-pins {
+ fsl,pinmux-ids = <
+ MX28_PAD_PWM3__GPIO_3_28
+ >;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
+ };
+
+ tx28_tsc2007_pins: tx28-tsc2007-pins {
+ fsl,pinmux-ids = <
+ MX28_PAD_SAIF0_MCLK__GPIO_3_20 /* TSC2007 IRQ */
+ >;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
+ };
+
+
+ tx28_usbphy0_pins: tx28-usbphy0-pins {
+ fsl,pinmux-ids = <
+ MX28_PAD_GPMI_CE2N__GPIO_0_18 /* USBOTG_VBUSEN */
+ MX28_PAD_GPMI_CE3N__GPIO_0_19 /* USBOTH_OC */
+ >;
+ fsl,drive-strength = <MXS_DRIVE_12mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
+ };
+
+ tx28_usbphy1_pins: tx28-usbphy1-pins {
+ fsl,pinmux-ids = <
+ MX28_PAD_SPDIF__GPIO_3_27 /* USBH_VBUSEN */
+ MX28_PAD_JTAG_RTCK__GPIO_4_20 /* USBH_OC */
+ >;
+ fsl,drive-strength = <MXS_DRIVE_12mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
+ };
+};
+
+&saif0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&saif0_pins_b>;
+ fsl,saif-master;
+ status = "okay";
+};
+
+&saif1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&saif1_pins_a>;
+ status = "okay";
+};
+
+&ssp0 {
+ compatible = "fsl,imx28-mmc";
+ pinctrl-names = "default", "special";
+ pinctrl-0 = <&mmc0_4bit_pins_a
+ &mmc0_cd_cfg
+ &mmc0_sck_cfg>;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&ssp3 {
+ compatible = "fsl,imx28-spi";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi3_pins_a>;
+ clock-frequency = <57600000>;
+ status = "okay";
+
+ spidev0: spi@0 {
+ compatible = "spidev";
+ reg = <0>;
+ spi-max-frequency = <57600000>;
+ };
+
+ spidev1: spi@1 {
+ compatible = "spidev";
+ reg = <1>;
+ spi-max-frequency = <57600000>;
};
};
+
+&usb0 {
+ vbus-supply = <&reg_usb0_vbus>;
+ disable-over-current;
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usb1 {
+ vbus-supply = <&reg_usb1_vbus>;
+ disable-over-current;
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usbphy0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&tx28_usbphy0_pins>;
+ phy_type = "utmi";
+ status = "okay";
+};
+
+&usbphy1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&tx28_usbphy1_pins>;
+ phy_type = "utmi";
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index 7363fded95ee..918d419772dd 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -9,7 +9,8 @@
* http://www.gnu.org/copyleft/gpl.html
*/
-/include/ "skeleton.dtsi"
+#include "skeleton.dtsi"
+#include "imx28-pinfunc.h"
/ {
interrupt-parent = <&icoll>;
@@ -207,538 +208,548 @@
duart_pins_a: duart@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x3102 /* MX28_PAD_PWM0__DUART_RX */
- 0x3112 /* MX28_PAD_PWM1__DUART_TX */
+ MX28_PAD_PWM0__DUART_RX
+ MX28_PAD_PWM1__DUART_TX
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
duart_pins_b: duart@1 {
reg = <1>;
fsl,pinmux-ids = <
- 0x3022 /* MX28_PAD_AUART0_CTS__DUART_RX */
- 0x3032 /* MX28_PAD_AUART0_RTS__DUART_TX */
+ MX28_PAD_AUART0_CTS__DUART_RX
+ MX28_PAD_AUART0_RTS__DUART_TX
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
duart_4pins_a: duart-4pins@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x3022 /* MX28_PAD_AUART0_CTS__DUART_RX */
- 0x3032 /* MX28_PAD_AUART0_RTS__DUART_TX */
- 0x3002 /* MX28_PAD_AUART0_RX__DUART_CTS */
- 0x3012 /* MX28_PAD_AUART0_TX__DUART_RTS */
+ MX28_PAD_AUART0_CTS__DUART_RX
+ MX28_PAD_AUART0_RTS__DUART_TX
+ MX28_PAD_AUART0_RX__DUART_CTS
+ MX28_PAD_AUART0_TX__DUART_RTS
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
gpmi_pins_a: gpmi-nand@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x0000 /* MX28_PAD_GPMI_D00__GPMI_D0 */
- 0x0010 /* MX28_PAD_GPMI_D01__GPMI_D1 */
- 0x0020 /* MX28_PAD_GPMI_D02__GPMI_D2 */
- 0x0030 /* MX28_PAD_GPMI_D03__GPMI_D3 */
- 0x0040 /* MX28_PAD_GPMI_D04__GPMI_D4 */
- 0x0050 /* MX28_PAD_GPMI_D05__GPMI_D5 */
- 0x0060 /* MX28_PAD_GPMI_D06__GPMI_D6 */
- 0x0070 /* MX28_PAD_GPMI_D07__GPMI_D7 */
- 0x0100 /* MX28_PAD_GPMI_CE0N__GPMI_CE0N */
- 0x0140 /* MX28_PAD_GPMI_RDY0__GPMI_READY0 */
- 0x0180 /* MX28_PAD_GPMI_RDN__GPMI_RDN */
- 0x0190 /* MX28_PAD_GPMI_WRN__GPMI_WRN */
- 0x01a0 /* MX28_PAD_GPMI_ALE__GPMI_ALE */
- 0x01b0 /* MX28_PAD_GPMI_CLE__GPMI_CLE */
- 0x01c0 /* MX28_PAD_GPMI_RESETN__GPMI_RESETN */
+ MX28_PAD_GPMI_D00__GPMI_D0
+ MX28_PAD_GPMI_D01__GPMI_D1
+ MX28_PAD_GPMI_D02__GPMI_D2
+ MX28_PAD_GPMI_D03__GPMI_D3
+ MX28_PAD_GPMI_D04__GPMI_D4
+ MX28_PAD_GPMI_D05__GPMI_D5
+ MX28_PAD_GPMI_D06__GPMI_D6
+ MX28_PAD_GPMI_D07__GPMI_D7
+ MX28_PAD_GPMI_CE0N__GPMI_CE0N
+ MX28_PAD_GPMI_RDY0__GPMI_READY0
+ MX28_PAD_GPMI_RDN__GPMI_RDN
+ MX28_PAD_GPMI_WRN__GPMI_WRN
+ MX28_PAD_GPMI_ALE__GPMI_ALE
+ MX28_PAD_GPMI_CLE__GPMI_CLE
+ MX28_PAD_GPMI_RESETN__GPMI_RESETN
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
gpmi_status_cfg: gpmi-status-cfg {
fsl,pinmux-ids = <
- 0x0180 /* MX28_PAD_GPMI_RDN__GPMI_RDN */
- 0x0190 /* MX28_PAD_GPMI_WRN__GPMI_WRN */
- 0x01c0 /* MX28_PAD_GPMI_RESETN__GPMI_RESETN */
+ MX28_PAD_GPMI_RDN__GPMI_RDN
+ MX28_PAD_GPMI_WRN__GPMI_WRN
+ MX28_PAD_GPMI_RESETN__GPMI_RESETN
>;
- fsl,drive-strength = <2>;
+ fsl,drive-strength = <MXS_DRIVE_12mA>;
};
auart0_pins_a: auart0@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x3000 /* MX28_PAD_AUART0_RX__AUART0_RX */
- 0x3010 /* MX28_PAD_AUART0_TX__AUART0_TX */
- 0x3020 /* MX28_PAD_AUART0_CTS__AUART0_CTS */
- 0x3030 /* MX28_PAD_AUART0_RTS__AUART0_RTS */
+ MX28_PAD_AUART0_RX__AUART0_RX
+ MX28_PAD_AUART0_TX__AUART0_TX
+ MX28_PAD_AUART0_CTS__AUART0_CTS
+ MX28_PAD_AUART0_RTS__AUART0_RTS
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
auart0_2pins_a: auart0-2pins@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x3000 /* MX28_PAD_AUART0_RX__AUART0_RX */
- 0x3010 /* MX28_PAD_AUART0_TX__AUART0_TX */
+ MX28_PAD_AUART0_RX__AUART0_RX
+ MX28_PAD_AUART0_TX__AUART0_TX
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
auart1_pins_a: auart1@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x3040 /* MX28_PAD_AUART1_RX__AUART1_RX */
- 0x3050 /* MX28_PAD_AUART1_TX__AUART1_TX */
- 0x3060 /* MX28_PAD_AUART1_CTS__AUART1_CTS */
- 0x3070 /* MX28_PAD_AUART1_RTS__AUART1_RTS */
+ MX28_PAD_AUART1_RX__AUART1_RX
+ MX28_PAD_AUART1_TX__AUART1_TX
+ MX28_PAD_AUART1_CTS__AUART1_CTS
+ MX28_PAD_AUART1_RTS__AUART1_RTS
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
auart1_2pins_a: auart1-2pins@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x3040 /* MX28_PAD_AUART1_RX__AUART1_RX */
- 0x3050 /* MX28_PAD_AUART1_TX__AUART1_TX */
+ MX28_PAD_AUART1_RX__AUART1_RX
+ MX28_PAD_AUART1_TX__AUART1_TX
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
auart2_2pins_a: auart2-2pins@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2101 /* MX28_PAD_SSP2_SCK__AUART2_RX */
- 0x2111 /* MX28_PAD_SSP2_MOSI__AUART2_TX */
+ MX28_PAD_SSP2_SCK__AUART2_RX
+ MX28_PAD_SSP2_MOSI__AUART2_TX
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
auart2_2pins_b: auart2-2pins@1 {
reg = <1>;
fsl,pinmux-ids = <
- 0x3080 /* MX28_PAD_AUART2_RX__AUART2_RX */
- 0x3090 /* MX28_PAD_AUART2_TX__AUART2_TX */
+ MX28_PAD_AUART2_RX__AUART2_RX
+ MX28_PAD_AUART2_TX__AUART2_TX
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
auart3_pins_a: auart3@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x30c0 /* MX28_PAD_AUART3_RX__AUART3_RX */
- 0x30d0 /* MX28_PAD_AUART3_TX__AUART3_TX */
- 0x30e0 /* MX28_PAD_AUART3_CTS__AUART3_CTS */
- 0x30f0 /* MX28_PAD_AUART3_RTS__AUART3_RTS */
+ MX28_PAD_AUART3_RX__AUART3_RX
+ MX28_PAD_AUART3_TX__AUART3_TX
+ MX28_PAD_AUART3_CTS__AUART3_CTS
+ MX28_PAD_AUART3_RTS__AUART3_RTS
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
auart3_2pins_a: auart3-2pins@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2121 /* MX28_PAD_SSP2_MISO__AUART3_RX */
- 0x2131 /* MX28_PAD_SSP2_SS0__AUART3_TX */
+ MX28_PAD_SSP2_MISO__AUART3_RX
+ MX28_PAD_SSP2_SS0__AUART3_TX
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
auart3_2pins_b: auart3-2pins@1 {
reg = <1>;
fsl,pinmux-ids = <
- 0x30c0 /* MX28_PAD_AUART3_RX__AUART3_RX */
- 0x30d0 /* MX28_PAD_AUART3_TX__AUART3_TX */
+ MX28_PAD_AUART3_RX__AUART3_RX
+ MX28_PAD_AUART3_TX__AUART3_TX
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
auart4_2pins_a: auart4@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2181 /* MX28_PAD_SSP3_SCK__AUART4_TX */
- 0x2191 /* MX28_PAD_SSP3_MOSI__AUART4_RX */
+ MX28_PAD_SSP3_SCK__AUART4_TX
+ MX28_PAD_SSP3_MOSI__AUART4_RX
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
mac0_pins_a: mac0@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x4000 /* MX28_PAD_ENET0_MDC__ENET0_MDC */
- 0x4010 /* MX28_PAD_ENET0_MDIO__ENET0_MDIO */
- 0x4020 /* MX28_PAD_ENET0_RX_EN__ENET0_RX_EN */
- 0x4030 /* MX28_PAD_ENET0_RXD0__ENET0_RXD0 */
- 0x4040 /* MX28_PAD_ENET0_RXD1__ENET0_RXD1 */
- 0x4060 /* MX28_PAD_ENET0_TX_EN__ENET0_TX_EN */
- 0x4070 /* MX28_PAD_ENET0_TXD0__ENET0_TXD0 */
- 0x4080 /* MX28_PAD_ENET0_TXD1__ENET0_TXD1 */
- 0x4100 /* MX28_PAD_ENET_CLK__CLKCTRL_ENET */
+ MX28_PAD_ENET0_MDC__ENET0_MDC
+ MX28_PAD_ENET0_MDIO__ENET0_MDIO
+ MX28_PAD_ENET0_RX_EN__ENET0_RX_EN
+ MX28_PAD_ENET0_RXD0__ENET0_RXD0
+ MX28_PAD_ENET0_RXD1__ENET0_RXD1
+ MX28_PAD_ENET0_TX_EN__ENET0_TX_EN
+ MX28_PAD_ENET0_TXD0__ENET0_TXD0
+ MX28_PAD_ENET0_TXD1__ENET0_TXD1
+ MX28_PAD_ENET_CLK__CLKCTRL_ENET
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
mac1_pins_a: mac1@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x40f1 /* MX28_PAD_ENET0_CRS__ENET1_RX_EN */
- 0x4091 /* MX28_PAD_ENET0_RXD2__ENET1_RXD0 */
- 0x40a1 /* MX28_PAD_ENET0_RXD3__ENET1_RXD1 */
- 0x40e1 /* MX28_PAD_ENET0_COL__ENET1_TX_EN */
- 0x40b1 /* MX28_PAD_ENET0_TXD2__ENET1_TXD0 */
- 0x40c1 /* MX28_PAD_ENET0_TXD3__ENET1_TXD1 */
+ MX28_PAD_ENET0_CRS__ENET1_RX_EN
+ MX28_PAD_ENET0_RXD2__ENET1_RXD0
+ MX28_PAD_ENET0_RXD3__ENET1_RXD1
+ MX28_PAD_ENET0_COL__ENET1_TX_EN
+ MX28_PAD_ENET0_TXD2__ENET1_TXD0
+ MX28_PAD_ENET0_TXD3__ENET1_TXD1
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
mmc0_8bit_pins_a: mmc0-8bit@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2000 /* MX28_PAD_SSP0_DATA0__SSP0_D0 */
- 0x2010 /* MX28_PAD_SSP0_DATA1__SSP0_D1 */
- 0x2020 /* MX28_PAD_SSP0_DATA2__SSP0_D2 */
- 0x2030 /* MX28_PAD_SSP0_DATA3__SSP0_D3 */
- 0x2040 /* MX28_PAD_SSP0_DATA4__SSP0_D4 */
- 0x2050 /* MX28_PAD_SSP0_DATA5__SSP0_D5 */
- 0x2060 /* MX28_PAD_SSP0_DATA6__SSP0_D6 */
- 0x2070 /* MX28_PAD_SSP0_DATA7__SSP0_D7 */
- 0x2080 /* MX28_PAD_SSP0_CMD__SSP0_CMD */
- 0x2090 /* MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT */
- 0x20a0 /* MX28_PAD_SSP0_SCK__SSP0_SCK */
+ MX28_PAD_SSP0_DATA0__SSP0_D0
+ MX28_PAD_SSP0_DATA1__SSP0_D1
+ MX28_PAD_SSP0_DATA2__SSP0_D2
+ MX28_PAD_SSP0_DATA3__SSP0_D3
+ MX28_PAD_SSP0_DATA4__SSP0_D4
+ MX28_PAD_SSP0_DATA5__SSP0_D5
+ MX28_PAD_SSP0_DATA6__SSP0_D6
+ MX28_PAD_SSP0_DATA7__SSP0_D7
+ MX28_PAD_SSP0_CMD__SSP0_CMD
+ MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT
+ MX28_PAD_SSP0_SCK__SSP0_SCK
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
mmc0_4bit_pins_a: mmc0-4bit@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2000 /* MX28_PAD_SSP0_DATA0__SSP0_D0 */
- 0x2010 /* MX28_PAD_SSP0_DATA1__SSP0_D1 */
- 0x2020 /* MX28_PAD_SSP0_DATA2__SSP0_D2 */
- 0x2030 /* MX28_PAD_SSP0_DATA3__SSP0_D3 */
- 0x2080 /* MX28_PAD_SSP0_CMD__SSP0_CMD */
- 0x2090 /* MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT */
- 0x20a0 /* MX28_PAD_SSP0_SCK__SSP0_SCK */
+ MX28_PAD_SSP0_DATA0__SSP0_D0
+ MX28_PAD_SSP0_DATA1__SSP0_D1
+ MX28_PAD_SSP0_DATA2__SSP0_D2
+ MX28_PAD_SSP0_DATA3__SSP0_D3
+ MX28_PAD_SSP0_CMD__SSP0_CMD
+ MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT
+ MX28_PAD_SSP0_SCK__SSP0_SCK
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
mmc0_cd_cfg: mmc0-cd-cfg {
fsl,pinmux-ids = <
- 0x2090 /* MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT */
+ MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT
>;
- fsl,pull-up = <0>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
mmc0_sck_cfg: mmc0-sck-cfg {
fsl,pinmux-ids = <
- 0x20a0 /* MX28_PAD_SSP0_SCK__SSP0_SCK */
+ MX28_PAD_SSP0_SCK__SSP0_SCK
>;
- fsl,drive-strength = <2>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_12mA>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
i2c0_pins_a: i2c0@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x3180 /* MX28_PAD_I2C0_SCL__I2C0_SCL */
- 0x3190 /* MX28_PAD_I2C0_SDA__I2C0_SDA */
+ MX28_PAD_I2C0_SCL__I2C0_SCL
+ MX28_PAD_I2C0_SDA__I2C0_SDA
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
i2c0_pins_b: i2c0@1 {
reg = <1>;
fsl,pinmux-ids = <
- 0x3001 /* MX28_PAD_AUART0_RX__I2C0_SCL */
- 0x3011 /* MX28_PAD_AUART0_TX__I2C0_SDA */
+ MX28_PAD_AUART0_RX__I2C0_SCL
+ MX28_PAD_AUART0_TX__I2C0_SDA
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
i2c1_pins_a: i2c1@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x3101 /* MX28_PAD_PWM0__I2C1_SCL */
- 0x3111 /* MX28_PAD_PWM1__I2C1_SDA */
+ MX28_PAD_PWM0__I2C1_SCL
+ MX28_PAD_PWM1__I2C1_SDA
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
saif0_pins_a: saif0@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x3140 /* MX28_PAD_SAIF0_MCLK__SAIF0_MCLK */
- 0x3150 /* MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK */
- 0x3160 /* MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK */
- 0x3170 /* MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0 */
+ MX28_PAD_SAIF0_MCLK__SAIF0_MCLK
+ MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK
+ MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK
+ MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0
>;
- fsl,drive-strength = <2>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_12mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
saif0_pins_b: saif0@1 {
reg = <1>;
fsl,pinmux-ids = <
- 0x3150 /* MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK */
- 0x3160 /* MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK */
- 0x3170 /* MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0 */
+ MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK
+ MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK
+ MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0
>;
- fsl,drive-strength = <2>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_12mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
saif1_pins_a: saif1@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x31a0 /* MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0 */
+ MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0
>;
- fsl,drive-strength = <2>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_12mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
pwm0_pins_a: pwm0@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x3100 /* MX28_PAD_PWM0__PWM_0 */
+ MX28_PAD_PWM0__PWM_0
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
pwm2_pins_a: pwm2@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x3120 /* MX28_PAD_PWM2__PWM_2 */
+ MX28_PAD_PWM2__PWM_2
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
pwm3_pins_a: pwm3@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x31c0 /* MX28_PAD_PWM3__PWM_3 */
+ MX28_PAD_PWM3__PWM_3
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
pwm3_pins_b: pwm3@1 {
reg = <1>;
fsl,pinmux-ids = <
- 0x3141 /* MX28_PAD_SAIF0_MCLK__PWM3 */
+ MX28_PAD_SAIF0_MCLK__PWM_3
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
pwm4_pins_a: pwm4@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x31d0 /* MX28_PAD_PWM4__PWM_4 */
+ MX28_PAD_PWM4__PWM_4
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
lcdif_24bit_pins_a: lcdif-24bit@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1000 /* MX28_PAD_LCD_D00__LCD_D0 */
- 0x1010 /* MX28_PAD_LCD_D01__LCD_D1 */
- 0x1020 /* MX28_PAD_LCD_D02__LCD_D2 */
- 0x1030 /* MX28_PAD_LCD_D03__LCD_D3 */
- 0x1040 /* MX28_PAD_LCD_D04__LCD_D4 */
- 0x1050 /* MX28_PAD_LCD_D05__LCD_D5 */
- 0x1060 /* MX28_PAD_LCD_D06__LCD_D6 */
- 0x1070 /* MX28_PAD_LCD_D07__LCD_D7 */
- 0x1080 /* MX28_PAD_LCD_D08__LCD_D8 */
- 0x1090 /* MX28_PAD_LCD_D09__LCD_D9 */
- 0x10a0 /* MX28_PAD_LCD_D10__LCD_D10 */
- 0x10b0 /* MX28_PAD_LCD_D11__LCD_D11 */
- 0x10c0 /* MX28_PAD_LCD_D12__LCD_D12 */
- 0x10d0 /* MX28_PAD_LCD_D13__LCD_D13 */
- 0x10e0 /* MX28_PAD_LCD_D14__LCD_D14 */
- 0x10f0 /* MX28_PAD_LCD_D15__LCD_D15 */
- 0x1100 /* MX28_PAD_LCD_D16__LCD_D16 */
- 0x1110 /* MX28_PAD_LCD_D17__LCD_D17 */
- 0x1120 /* MX28_PAD_LCD_D18__LCD_D18 */
- 0x1130 /* MX28_PAD_LCD_D19__LCD_D19 */
- 0x1140 /* MX28_PAD_LCD_D20__LCD_D20 */
- 0x1150 /* MX28_PAD_LCD_D21__LCD_D21 */
- 0x1160 /* MX28_PAD_LCD_D22__LCD_D22 */
- 0x1170 /* MX28_PAD_LCD_D23__LCD_D23 */
+ MX28_PAD_LCD_D00__LCD_D0
+ MX28_PAD_LCD_D01__LCD_D1
+ MX28_PAD_LCD_D02__LCD_D2
+ MX28_PAD_LCD_D03__LCD_D3
+ MX28_PAD_LCD_D04__LCD_D4
+ MX28_PAD_LCD_D05__LCD_D5
+ MX28_PAD_LCD_D06__LCD_D6
+ MX28_PAD_LCD_D07__LCD_D7
+ MX28_PAD_LCD_D08__LCD_D8
+ MX28_PAD_LCD_D09__LCD_D9
+ MX28_PAD_LCD_D10__LCD_D10
+ MX28_PAD_LCD_D11__LCD_D11
+ MX28_PAD_LCD_D12__LCD_D12
+ MX28_PAD_LCD_D13__LCD_D13
+ MX28_PAD_LCD_D14__LCD_D14
+ MX28_PAD_LCD_D15__LCD_D15
+ MX28_PAD_LCD_D16__LCD_D16
+ MX28_PAD_LCD_D17__LCD_D17
+ MX28_PAD_LCD_D18__LCD_D18
+ MX28_PAD_LCD_D19__LCD_D19
+ MX28_PAD_LCD_D20__LCD_D20
+ MX28_PAD_LCD_D21__LCD_D21
+ MX28_PAD_LCD_D22__LCD_D22
+ MX28_PAD_LCD_D23__LCD_D23
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
lcdif_16bit_pins_a: lcdif-16bit@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x1000 /* MX28_PAD_LCD_D00__LCD_D0 */
- 0x1010 /* MX28_PAD_LCD_D01__LCD_D1 */
- 0x1020 /* MX28_PAD_LCD_D02__LCD_D2 */
- 0x1030 /* MX28_PAD_LCD_D03__LCD_D3 */
- 0x1040 /* MX28_PAD_LCD_D04__LCD_D4 */
- 0x1050 /* MX28_PAD_LCD_D05__LCD_D5 */
- 0x1060 /* MX28_PAD_LCD_D06__LCD_D6 */
- 0x1070 /* MX28_PAD_LCD_D07__LCD_D7 */
- 0x1080 /* MX28_PAD_LCD_D08__LCD_D8 */
- 0x1090 /* MX28_PAD_LCD_D09__LCD_D9 */
- 0x10a0 /* MX28_PAD_LCD_D10__LCD_D10 */
- 0x10b0 /* MX28_PAD_LCD_D11__LCD_D11 */
- 0x10c0 /* MX28_PAD_LCD_D12__LCD_D12 */
- 0x10d0 /* MX28_PAD_LCD_D13__LCD_D13 */
- 0x10e0 /* MX28_PAD_LCD_D14__LCD_D14 */
- 0x10f0 /* MX28_PAD_LCD_D15__LCD_D15 */
+ MX28_PAD_LCD_D00__LCD_D0
+ MX28_PAD_LCD_D01__LCD_D1
+ MX28_PAD_LCD_D02__LCD_D2
+ MX28_PAD_LCD_D03__LCD_D3
+ MX28_PAD_LCD_D04__LCD_D4
+ MX28_PAD_LCD_D05__LCD_D5
+ MX28_PAD_LCD_D06__LCD_D6
+ MX28_PAD_LCD_D07__LCD_D7
+ MX28_PAD_LCD_D08__LCD_D8
+ MX28_PAD_LCD_D09__LCD_D9
+ MX28_PAD_LCD_D10__LCD_D10
+ MX28_PAD_LCD_D11__LCD_D11
+ MX28_PAD_LCD_D12__LCD_D12
+ MX28_PAD_LCD_D13__LCD_D13
+ MX28_PAD_LCD_D14__LCD_D14
+ MX28_PAD_LCD_D15__LCD_D15
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
lcdif_sync_pins_a: lcdif-sync@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
- 0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
- 0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
- 0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
+ MX28_PAD_LCD_RS__LCD_DOTCLK
+ MX28_PAD_LCD_CS__LCD_ENABLE
+ MX28_PAD_LCD_RD_E__LCD_VSYNC
+ MX28_PAD_LCD_WR_RWN__LCD_HSYNC
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
can0_pins_a: can0@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x0161 /* MX28_PAD_GPMI_RDY2__CAN0_TX */
- 0x0171 /* MX28_PAD_GPMI_RDY3__CAN0_RX */
+ MX28_PAD_GPMI_RDY2__CAN0_TX
+ MX28_PAD_GPMI_RDY3__CAN0_RX
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
can1_pins_a: can1@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x0121 /* MX28_PAD_GPMI_CE2N__CAN1_TX */
- 0x0131 /* MX28_PAD_GPMI_CE3N__CAN1_RX */
+ MX28_PAD_GPMI_CE2N__CAN1_TX
+ MX28_PAD_GPMI_CE3N__CAN1_RX
>;
- fsl,drive-strength = <0>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_4mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
spi2_pins_a: spi2@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2100 /* MX28_PAD_SSP2_SCK__SSP2_SCK */
- 0x2110 /* MX28_PAD_SSP2_MOSI__SSP2_CMD */
- 0x2120 /* MX28_PAD_SSP2_MISO__SSP2_D0 */
- 0x2130 /* MX28_PAD_SSP2_SS0__SSP2_D3 */
+ MX28_PAD_SSP2_SCK__SSP2_SCK
+ MX28_PAD_SSP2_MOSI__SSP2_CMD
+ MX28_PAD_SSP2_MISO__SSP2_D0
+ MX28_PAD_SSP2_SS0__SSP2_D3
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <1>;
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
spi3_pins_a: spi3@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x3082 /* MX28_PAD_AUART2_RX__SSP3_D4 */
- 0x3092 /* MX28_PAD_AUART2_TX__SSP3_D5 */
- 0x2180 /* MX28_PAD_SSP3_SCK__SSP3_SCK */
- 0x2190 /* MX28_PAD_SSP3_MOSI__SSP3_CMD */
- 0x21A0 /* MX28_PAD_SSP3_MISO__SSP3_D0 */
- 0x21B0 /* MX28_PAD_SSP3_SS0__SSP3_D3 */
+ MX28_PAD_AUART2_RX__SSP3_D4
+ MX28_PAD_AUART2_TX__SSP3_D5
+ MX28_PAD_SSP3_SCK__SSP3_SCK
+ MX28_PAD_SSP3_MOSI__SSP3_CMD
+ MX28_PAD_SSP3_MISO__SSP3_D0
+ MX28_PAD_SSP3_SS0__SSP3_D3
>;
- fsl,drive-strength = <1>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_8mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
usbphy0_pins_a: usbphy0@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2152 /* MX28_PAD_SSP2_SS2__USB0_OVERCURRENT */
+ MX28_PAD_SSP2_SS2__USB0_OVERCURRENT
>;
- fsl,drive-strength = <2>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_12mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
usbphy0_pins_b: usbphy0@1 {
reg = <1>;
fsl,pinmux-ids = <
- 0x3061 /* MX28_PAD_AUART1_CTS__USB0_OVERCURRENT */
+ MX28_PAD_AUART1_CTS__USB0_OVERCURRENT
>;
- fsl,drive-strength = <2>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_12mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
};
usbphy1_pins_a: usbphy1@0 {
reg = <0>;
fsl,pinmux-ids = <
- 0x2142 /* MX28_PAD_SSP2_SS1__USB1_OVERCURRENT */
+ MX28_PAD_SSP2_SS1__USB1_OVERCURRENT
>;
- fsl,drive-strength = <2>;
- fsl,voltage = <1>;
- fsl,pull-up = <0>;
+ fsl,drive-strength = <MXS_DRIVE_12mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_DISABLE>;
+ };
+
+ usb0_id_pins_a: usb0id@0 {
+ reg = <0>;
+ fsl,pinmux-ids = <
+ MX28_PAD_AUART1_RTS__USB0_ID
+ >;
+ fsl,drive-strength = <MXS_DRIVE_12mA>;
+ fsl,voltage = <MXS_VOLTAGE_HIGH>;
+ fsl,pull-up = <MXS_PULL_ENABLE>;
};
};
diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
index 1d337d99ecd5..f13f33906dde 100644
--- a/arch/arm/boot/dts/imx51-babbage.dts
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -95,7 +95,7 @@
&uart3 {
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart3_1>;
+ pinctrl-0 = <&pinctrl_uart3_1 &pinctrl_uart3_rtscts_1>;
fsl,uart-has-rtscts;
status = "okay";
};
@@ -252,7 +252,7 @@
&uart1 {
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart1_1>;
+ pinctrl-0 = <&pinctrl_uart1_1 &pinctrl_uart1_rtscts_1>;
fsl,uart-has-rtscts;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
index 54cee6517902..f4dcff3a9969 100644
--- a/arch/arm/boot/dts/imx51.dtsi
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -86,6 +86,11 @@
interrupt-parent = <&tzic>;
ranges;
+ iram: iram@1ffe0000 {
+ compatible = "mmio-sram";
+ reg = <0x1ffe0000 0x20000>;
+ };
+
ipu: ipu@40000000 {
#crtc-cells = <1>;
compatible = "fsl,imx51-ipu";
@@ -374,6 +379,14 @@
clocks = <&clks 107>;
};
+ owire: owire@83fa4000 {
+ compatible = "fsl,imx51-owire", "fsl,imx21-owire";
+ reg = <0x83fa4000 0x4000>;
+ interrupts = <88>;
+ clocks = <&clks 159>;
+ status = "disabled";
+ };
+
ecspi2: ecspi@83fac000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -747,6 +760,11 @@
fsl,pins = <
MX51_PAD_UART1_RXD__UART1_RXD 0x1c5
MX51_PAD_UART1_TXD__UART1_TXD 0x1c5
+ >;
+ };
+
+ pinctrl_uart1_rtscts_1: uart1rtscts-1 {
+ fsl,pins = <
MX51_PAD_UART1_RTS__UART1_RTS 0x1c5
MX51_PAD_UART1_CTS__UART1_CTS 0x1c5
>;
@@ -767,6 +785,11 @@
fsl,pins = <
MX51_PAD_EIM_D25__UART3_RXD 0x1c5
MX51_PAD_EIM_D26__UART3_TXD 0x1c5
+ >;
+ };
+
+ pinctrl_uart3_rtscts_1: uart3rtscts-1 {
+ fsl,pins = <
MX51_PAD_EIM_D27__UART3_RTS 0x1c5
MX51_PAD_EIM_D24__UART3_CTS 0x1c5
>;
diff --git a/arch/arm/boot/dts/imx53-qsb.dts b/arch/arm/boot/dts/imx53-qsb.dts
index e97ddae09d74..94597c3c2eb6 100644
--- a/arch/arm/boot/dts/imx53-qsb.dts
+++ b/arch/arm/boot/dts/imx53-qsb.dts
@@ -318,5 +318,6 @@
};
&usbotg {
- status = "okay";
+ dr_mode = "peripheral";
+ status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6q-pinfunc.h b/arch/arm/boot/dts/imx6q-pinfunc.h
index 9bbe82bdee41..97ed0816a6e0 100644
--- a/arch/arm/boot/dts/imx6q-pinfunc.h
+++ b/arch/arm/boot/dts/imx6q-pinfunc.h
@@ -536,7 +536,7 @@
#define MX6QDL_PAD_ENET_REF_CLK__ESAI_RX_FS 0x1d4 0x4e8 0x85c 0x2 0x0
#define MX6QDL_PAD_ENET_REF_CLK__GPIO1_IO23 0x1d4 0x4e8 0x000 0x5 0x0
#define MX6QDL_PAD_ENET_REF_CLK__SPDIF_SR_CLK 0x1d4 0x4e8 0x000 0x6 0x0
-#define MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x1d8 0x4ec 0x000 0x0 0x0
+#define MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x1d8 0x4ec 0x004 0x0 0xff0d0100
#define MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER 0x1d8 0x4ec 0x000 0x1 0x0
#define MX6QDL_PAD_ENET_RX_ER__ESAI_RX_HF_CLK 0x1d8 0x4ec 0x864 0x2 0x0
#define MX6QDL_PAD_ENET_RX_ER__SPDIF_IN 0x1d8 0x4ec 0x914 0x3 0x1
@@ -654,7 +654,7 @@
#define MX6QDL_PAD_GPIO_1__ESAI_RX_CLK 0x224 0x5f4 0x86c 0x0 0x1
#define MX6QDL_PAD_GPIO_1__WDOG2_B 0x224 0x5f4 0x000 0x1 0x0
#define MX6QDL_PAD_GPIO_1__KEY_ROW5 0x224 0x5f4 0x8f4 0x2 0x0
-#define MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x224 0x5f4 0x000 0x3 0x0
+#define MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x224 0x5f4 0x004 0x3 0xff0d0101
#define MX6QDL_PAD_GPIO_1__PWM2_OUT 0x224 0x5f4 0x000 0x4 0x0
#define MX6QDL_PAD_GPIO_1__GPIO1_IO01 0x224 0x5f4 0x000 0x5 0x0
#define MX6QDL_PAD_GPIO_1__SD1_CD_B 0x224 0x5f4 0x000 0x6 0x0
diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts
index 3530280f5150..e1c1777a80d5 100644
--- a/arch/arm/boot/dts/imx6q-sabrelite.dts
+++ b/arch/arm/boot/dts/imx6q-sabrelite.dts
@@ -65,8 +65,10 @@
};
};
-&sata {
+&audmux {
status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_audmux_1>;
};
&ecspi1 {
@@ -83,11 +85,29 @@
};
};
-&ssi1 {
- fsl,mode = "i2s-slave";
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet_1>;
+ phy-mode = "rgmii";
+ phy-reset-gpios = <&gpio3 23 0>;
status = "okay";
};
+&i2c1 {
+ status = "okay";
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1_1>;
+
+ codec: sgtl5000@0a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ clocks = <&clks 201>;
+ VDDA-supply = <&reg_2p5v>;
+ VDDIO-supply = <&reg_3p3v>;
+ };
+};
+
&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
@@ -108,23 +128,55 @@
};
};
-&usbotg {
- vbus-supply = <&reg_usb_otg_vbus>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_usbotg_1>;
- disable-over-current;
+&ldb {
+ status = "okay";
+
+ lvds-channel@0 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <18>;
+ status = "okay";
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: hsd100pxn1 {
+ clock-frequency = <65000000>;
+ hactive = <1024>;
+ vactive = <768>;
+ hback-porch = <220>;
+ hfront-porch = <40>;
+ vback-porch = <21>;
+ vfront-porch = <7>;
+ hsync-len = <60>;
+ vsync-len = <10>;
+ };
+ };
+ };
+};
+
+&sata {
+ status = "okay";
+};
+
+&ssi1 {
+ fsl,mode = "i2s-slave";
status = "okay";
};
+&uart2 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2_1>;
+};
+
&usbh1 {
status = "okay";
};
-&fec {
+&usbotg {
+ vbus-supply = <&reg_usb_otg_vbus>;
pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_enet_1>;
- phy-mode = "rgmii";
- phy-reset-gpios = <&gpio3 23 0>;
+ pinctrl-0 = <&pinctrl_usbotg_1>;
+ disable-over-current;
status = "okay";
};
@@ -145,30 +197,3 @@
vmmc-supply = <&reg_3p3v>;
status = "okay";
};
-
-&audmux {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_audmux_1>;
-};
-
-&uart2 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart2_1>;
-};
-
-&i2c1 {
- status = "okay";
- clock-frequency = <100000>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_i2c1_1>;
-
- codec: sgtl5000@0a {
- compatible = "fsl,sgtl5000";
- reg = <0x0a>;
- clocks = <&clks 201>;
- VDDA-supply = <&reg_2p5v>;
- VDDIO-supply = <&reg_3p3v>;
- };
-};
diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index 1cbbc5160d27..ff6f1e8f2dd9 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -54,6 +54,7 @@
fsl,pins = <
MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x80000000
MX6QDL_PAD_SD2_DAT2__GPIO1_IO13 0x80000000
+ MX6QDL_PAD_GPIO_18__SD3_VSELECT 0x17059
>;
};
};
@@ -74,8 +75,10 @@
};
&usdhc3 {
- pinctrl-names = "default";
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc3_1>;
+ pinctrl-1 = <&pinctrl_usdhc3_1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc3_1_200mhz>;
cd-gpios = <&gpio6 15 0>;
wp-gpios = <&gpio1 13 0>;
status = "okay";
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index 39eafc222a2e..64e454bcc4a3 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -229,6 +229,7 @@
&usdhc2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc2_1>;
+ bus-width = <8>;
cd-gpios = <&gpio2 2 0>;
wp-gpios = <&gpio2 3 0>;
status = "okay";
@@ -237,6 +238,7 @@
&usdhc3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc3_1>;
+ bus-width = <8>;
cd-gpios = <&gpio2 0 0>;
wp-gpios = <&gpio2 1 0>;
status = "okay";
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
index a55113e65bcb..df42d3ccb70e 100644
--- a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
@@ -43,6 +43,13 @@
mux-int-port = <1>;
mux-ext-port = <3>;
};
+
+ sound-spdif {
+ compatible = "fsl,imx-audio-spdif";
+ model = "imx-spdif";
+ spdif-controller = <&spdif>;
+ spdif-out;
+ };
};
&audmux {
@@ -93,6 +100,12 @@
status = "okay";
};
+&spdif {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spdif_3>;
+ status = "okay";
+};
+
&ssi1 {
fsl,mode = "i2s-slave";
status = "okay";
@@ -115,6 +128,14 @@
status = "okay";
};
+&usbotg {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg_1>;
+ disable-over-current;
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
&usdhc1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc1_2>;
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index ccd55c2fdb67..ef51342be314 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -136,8 +136,23 @@
ranges;
spdif: spdif@02004000 {
+ compatible = "fsl,imx35-spdif";
reg = <0x02004000 0x4000>;
interrupts = <0 52 0x04>;
+ dmas = <&sdma 14 18 0>,
+ <&sdma 15 18 0>;
+ dma-names = "rx", "tx";
+ clocks = <&clks 197>, <&clks 3>,
+ <&clks 197>, <&clks 107>,
+ <&clks 0>, <&clks 118>,
+ <&clks 62>, <&clks 139>,
+ <&clks 0>;
+ clock-names = "core", "rxtx0",
+ "rxtx1", "rxtx2",
+ "rxtx3", "rxtx4",
+ "rxtx5", "rxtx6",
+ "rxtx7";
+ status = "disabled";
};
ecspi1: ecspi@02008000 {
@@ -1010,6 +1025,12 @@
MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x1b0b0
>;
};
+
+ pinctrl_spdif_3: spdifgrp-3 {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_RXD0__SPDIF_OUT 0x1b0b0
+ >;
+ };
};
uart1 {
@@ -1184,6 +1205,36 @@
>;
};
+ pinctrl_usdhc3_1_100mhz: usdhc3grp-1-100mhz { /* 100Mhz */
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170b9
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170b9
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170b9
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170b9
+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170b9
+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170b9
+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170b9
+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc3_1_200mhz: usdhc3grp-1-200mhz { /* 200Mhz */
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170f9
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170f9
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170f9
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170f9
+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170f9
+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170f9
+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170f9
+ >;
+ };
+
pinctrl_usdhc3_2: usdhc3grp-2 {
fsl,pins = <
MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index 2886a590823d..36ea01e308d3 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -17,6 +17,28 @@
memory {
reg = <0x80000000 0x40000000>;
};
+
+ regulators {
+ compatible = "simple-bus";
+
+ reg_usb_otg1_vbus: usb_otg1_vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_otg1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio4 0 0>;
+ enable-active-high;
+ };
+
+ reg_usb_otg2_vbus: usb_otg2_vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_otg2_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio4 2 0>;
+ enable-active-high;
+ };
+ };
};
&fec {
@@ -38,6 +60,8 @@
MX6SL_PAD_SD2_DAT7__GPIO5_IO00 0x17059
MX6SL_PAD_SD2_DAT6__GPIO4_IO29 0x17059
MX6SL_PAD_REF_CLK_32K__GPIO3_IO22 0x17059
+ MX6SL_PAD_KEY_COL4__GPIO4_IO00 0x80000000
+ MX6SL_PAD_KEY_COL5__GPIO4_IO02 0x80000000
>;
};
};
@@ -49,6 +73,21 @@
status = "okay";
};
+&usbotg1 {
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg1_1>;
+ disable-over-current;
+ status = "okay";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usb_otg2_vbus>;
+ dr_mode = "host";
+ disable-over-current;
+ status = "okay";
+};
+
&usdhc1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc1_1>;
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index c46651e4d966..f295290d29fc 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -13,16 +13,20 @@
/ {
aliases {
- serial0 = &uart1;
- serial1 = &uart2;
- serial2 = &uart3;
- serial3 = &uart4;
- serial4 = &uart5;
gpio0 = &gpio1;
gpio1 = &gpio2;
gpio2 = &gpio3;
gpio3 = &gpio4;
gpio4 = &gpio5;
+ serial0 = &uart1;
+ serial1 = &uart2;
+ serial2 = &uart3;
+ serial3 = &uart4;
+ serial4 = &uart5;
+ spi0 = &ecspi1;
+ spi1 = &ecspi2;
+ spi2 = &ecspi3;
+ spi3 = &ecspi4;
};
cpus {
@@ -528,6 +532,11 @@
interrupts = <0 89 0x04>;
};
+ gpr: iomuxc-gpr@020e0000 {
+ compatible = "fsl,imx6sl-iomuxc-gpr", "syscon";
+ reg = <0x020e0000 0x38>;
+ };
+
iomuxc: iomuxc@020e0000 {
compatible = "fsl,imx6sl-iomuxc";
reg = <0x020e0000 0x4000>;
@@ -557,6 +566,64 @@
};
};
+ usbotg1 {
+ pinctrl_usbotg1_1: usbotg1grp-1 {
+ fsl,pins = <
+ MX6SL_PAD_EPDC_PWRCOM__USB_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_usbotg1_2: usbotg1grp-2 {
+ fsl,pins = <
+ MX6SL_PAD_FEC_RXD0__USB_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_usbotg1_3: usbotg1grp-3 {
+ fsl,pins = <
+ MX6SL_PAD_LCD_DAT1__USB_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_usbotg1_4: usbotg1grp-4 {
+ fsl,pins = <
+ MX6SL_PAD_REF_CLK_32K__USB_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_usbotg1_5: usbotg1grp-5 {
+ fsl,pins = <
+ MX6SL_PAD_SD3_DAT0__USB_OTG1_ID 0x17059
+ >;
+ };
+ };
+
+ usbotg2 {
+ pinctrl_usbotg2_1: usbotg2grp-1 {
+ fsl,pins = <
+ MX6SL_PAD_ECSPI1_SCLK__USB_OTG2_OC 0x17059
+ >;
+ };
+
+ pinctrl_usbotg2_2: usbotg2grp-2 {
+ fsl,pins = <
+ MX6SL_PAD_ECSPI2_SCLK__USB_OTG2_OC 0x17059
+ >;
+ };
+
+ pinctrl_usbotg2_3: usbotg2grp-3 {
+ fsl,pins = <
+ MX6SL_PAD_KEY_ROW5__USB_OTG2_OC 0x17059
+ >;
+ };
+
+ pinctrl_usbotg2_4: usbotg2grp-4 {
+ fsl,pins = <
+ MX6SL_PAD_SD3_DAT2__USB_OTG2_OC 0x17059
+ >;
+ };
+ };
+
usdhc1 {
pinctrl_usdhc1_1: usdhc1grp-1 {
fsl,pins = <
@@ -619,7 +686,8 @@
<&clks IMX6SL_CLK_SDMA>;
clock-names = "ipg", "ahb";
#dma-cells = <3>;
- fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6sl.bin";
+ /* imx6sl reuses imx6q sdma firmware */
+ fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q.bin";
};
pxp: pxp@020f0000 {
@@ -663,7 +731,7 @@
usbotg2: usb@02184200 {
compatible = "fsl,imx6sl-usb", "fsl,imx27-usb";
reg = <0x02184200 0x200>;
- interrupts = <0 40 0x04>;
+ interrupts = <0 42 0x04>;
clocks = <&clks IMX6SL_CLK_USBOH3>;
fsl,usbphy = <&usbphy2>;
fsl,usbmisc = <&usbmisc 1>;
@@ -673,7 +741,7 @@
usbh: usb@02184400 {
compatible = "fsl,imx6sl-usb", "fsl,imx27-usb";
reg = <0x02184400 0x200>;
- interrupts = <0 42 0x04>;
+ interrupts = <0 40 0x04>;
clocks = <&clks IMX6SL_CLK_USBOH3>;
fsl,usbmisc = <&usbmisc 2>;
status = "disabled";
diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi
index cf7aeaf89e9c..1335b2e1bed4 100644
--- a/arch/arm/boot/dts/kirkwood.dtsi
+++ b/arch/arm/boot/dts/kirkwood.dtsi
@@ -13,6 +13,7 @@
cpu@0 {
device_type = "cpu";
compatible = "marvell,feroceon";
+ reg = <0>;
clocks = <&core_clk 1>, <&core_clk 3>, <&gate_clk 11>;
clock-names = "cpu_clk", "ddrclk", "powersave";
};
@@ -167,7 +168,7 @@
xor@60900 {
compatible = "marvell,orion-xor";
reg = <0x60900 0x100
- 0xd0B00 0x100>;
+ 0x60B00 0x100>;
status = "okay";
clocks = <&gate_clk 16>;
diff --git a/arch/arm/boot/dts/mxs-pinfunc.h b/arch/arm/boot/dts/mxs-pinfunc.h
new file mode 100644
index 000000000000..c6da987b20cb
--- /dev/null
+++ b/arch/arm/boot/dts/mxs-pinfunc.h
@@ -0,0 +1,31 @@
+/*
+ * Header providing constants for i.MX28 pinctrl bindings.
+ *
+ * Copyright (C) 2013 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __DT_BINDINGS_MXS_PINCTRL_H__
+#define __DT_BINDINGS_MXS_PINCTRL_H__
+
+/* fsl,drive-strength property */
+#define MXS_DRIVE_4mA 0
+#define MXS_DRIVE_8mA 1
+#define MXS_DRIVE_12mA 2
+#define MXS_DRIVE_16mA 3
+
+/* fsl,voltage property */
+#define MXS_VOLTAGE_LOW 0
+#define MXS_VOLTAGE_HIGH 1
+
+/* fsl,pull-up property */
+#define MXS_PULL_DISABLE 0
+#define MXS_PULL_ENABLE 1
+
+#endif /* __DT_BINDINGS_MXS_PINCTRL_H__ */
diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts b/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts
index f444624eb097..2b49b05ae2f4 100644
--- a/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts
+++ b/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts
@@ -10,6 +10,7 @@
/dts-v1/;
/include/ "r8a73a4.dtsi"
+#include <dt-bindings/gpio/gpio.h>
/ {
model = "APE6EVM";
@@ -24,6 +25,34 @@
reg = <0 0x40000000 0 0x40000000>;
};
+ vcc_mmc0: regulator@0 {
+ compatible = "regulator-fixed";
+ regulator-name = "MMC0 Vcc";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-always-on;
+ };
+
+ vcc_sdhi0: regulator@1 {
+ compatible = "regulator-fixed";
+
+ regulator-name = "SDHI0 Vcc";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&pfc 76 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ /* Common 3.3V rail, used by several devices on APE6EVM */
+ ape6evm_fixed_3v3: regulator@2 {
+ compatible = "regulator-fixed";
+ regulator-name = "3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
lbsc {
compatible = "simple-bus";
#address-cells = <1>;
@@ -62,4 +91,47 @@
renesas,groups = "scifa0_data";
renesas,function = "scifa0";
};
+
+ mmc0_pins: mmcif {
+ renesas,groups = "mmc0_data8", "mmc0_ctrl";
+ renesas,function = "mmc0";
+ };
+
+ sdhi0_pins: sdhi0 {
+ renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd";
+ renesas,function = "sdhi0";
+ };
+
+ sdhi1_pins: sdhi1 {
+ renesas,groups = "sdhi1_data4", "sdhi1_ctrl";
+ renesas,function = "sdhi1";
+ };
+};
+
+&mmcif0 {
+ vmmc-supply = <&vcc_mmc0>;
+ bus-width = <8>;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins>;
+ status = "okay";
+};
+
+&sdhi0 {
+ vmmc-supply = <&vcc_sdhi0>;
+ bus-width = <4>;
+ toshiba,mmc-wrprotect-disable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhi0_pins>;
+ status = "okay";
+};
+
+&sdhi1 {
+ vmmc-supply = <&ape6evm_fixed_3v3>;
+ bus-width = <4>;
+ broken-cd;
+ toshiba,mmc-wrprotect-disable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhi1_pins>;
+ status = "okay";
};
diff --git a/arch/arm/boot/dts/r8a73a4.dtsi b/arch/arm/boot/dts/r8a73a4.dtsi
index 6c26caa880f2..658fcc537576 100644
--- a/arch/arm/boot/dts/r8a73a4.dtsi
+++ b/arch/arm/boot/dts/r8a73a4.dtsi
@@ -193,7 +193,7 @@
};
sdhi0: sdhi@ee100000 {
- compatible = "renesas,r8a73a4-sdhi";
+ compatible = "renesas,sdhi-r8a73a4";
reg = <0 0xee100000 0 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 165 4>;
@@ -202,7 +202,7 @@
};
sdhi1: sdhi@ee120000 {
- compatible = "renesas,r8a73a4-sdhi";
+ compatible = "renesas,sdhi-r8a73a4";
reg = <0 0xee120000 0 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 166 4>;
@@ -211,7 +211,7 @@
};
sdhi2: sdhi@ee140000 {
- compatible = "renesas,r8a73a4-sdhi";
+ compatible = "renesas,sdhi-r8a73a4";
reg = <0 0xee140000 0 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 167 4>;
diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts b/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts
index c638e4ab91b8..801442bdaa18 100644
--- a/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts
+++ b/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts
@@ -11,6 +11,7 @@
/dts-v1/;
/include/ "r8a7740.dtsi"
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pwm/pwm.h>
/ {
model = "armadillo 800 eva reference";
@@ -49,6 +50,15 @@
gpios = <&pfc 177 GPIO_ACTIVE_HIGH>;
};
};
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&tpu 2 33333 PWM_POLARITY_INVERTED>;
+ brightness-levels = <0 1 2 4 8 16 32 64 128 255>;
+ default-brightness-level = <9>;
+ pinctrl-0 = <&backlight_pins>;
+ pinctrl-names = "default";
+ };
};
&i2c0 {
@@ -76,4 +86,13 @@
renesas,groups = "intc_irq10";
renesas,function = "intc";
};
+
+ backlight_pins: backlight {
+ renesas,groups = "tpu0_to2_1";
+ renesas,function = "tpu0";
+ };
+};
+
+&tpu {
+ status = "okay";
};
diff --git a/arch/arm/boot/dts/r8a7778.dtsi b/arch/arm/boot/dts/r8a7778.dtsi
index 45ac404ab6d8..3577aba82583 100644
--- a/arch/arm/boot/dts/r8a7778.dtsi
+++ b/arch/arm/boot/dts/r8a7778.dtsi
@@ -96,6 +96,5 @@
pfc: pfc@fffc0000 {
compatible = "renesas,pfc-r8a7778";
reg = <0xfffc000 0x118>;
- #gpio-range-cells = <3>;
};
};
diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi
index 23a62447359c..ebbe507fcbfa 100644
--- a/arch/arm/boot/dts/r8a7779.dtsi
+++ b/arch/arm/boot/dts/r8a7779.dtsi
@@ -188,7 +188,6 @@
pfc: pfc@fffc0000 {
compatible = "renesas,pfc-r8a7779";
reg = <0xfffc0000 0x23c>;
- #gpio-range-cells = <3>;
};
thermal@ffc48000 {
diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 3b879e7c697c..28fc18c9601b 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -24,6 +24,55 @@
reg = <0>;
clock-frequency = <1300000000>;
};
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <1>;
+ clock-frequency = <1300000000>;
+ };
+
+ cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <2>;
+ clock-frequency = <1300000000>;
+ };
+
+ cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <3>;
+ clock-frequency = <1300000000>;
+ };
+
+ cpu4: cpu@4 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x100>;
+ clock-frequency = <780000000>;
+ };
+
+ cpu5: cpu@5 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x101>;
+ clock-frequency = <780000000>;
+ };
+
+ cpu6: cpu@6 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x102>;
+ clock-frequency = <780000000>;
+ };
+
+ cpu7: cpu@7 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0x103>;
+ clock-frequency = <780000000>;
+ };
};
gic: interrupt-controller@f1001000 {
@@ -148,11 +197,10 @@
pfc: pfc@e6060000 {
compatible = "renesas,pfc-r8a7790";
reg = <0 0xe6060000 0 0x250>;
- #gpio-range-cells = <3>;
};
sdhi0: sdhi@ee100000 {
- compatible = "renesas,r8a7790-sdhi";
+ compatible = "renesas,sdhi-r8a7790";
reg = <0 0xee100000 0 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 165 4>;
@@ -161,7 +209,7 @@
};
sdhi1: sdhi@ee120000 {
- compatible = "renesas,r8a7790-sdhi";
+ compatible = "renesas,sdhi-r8a7790";
reg = <0 0xee120000 0 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 166 4>;
@@ -170,7 +218,7 @@
};
sdhi2: sdhi@ee140000 {
- compatible = "renesas,r8a7790-sdhi";
+ compatible = "renesas,sdhi-r8a7790";
reg = <0 0xee140000 0 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 167 4>;
@@ -179,7 +227,7 @@
};
sdhi3: sdhi@ee160000 {
- compatible = "renesas,r8a7790-sdhi";
+ compatible = "renesas,sdhi-r8a7790";
reg = <0 0xee160000 0 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 168 4>;
diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts
new file mode 100644
index 000000000000..1ce5250ec278
--- /dev/null
+++ b/arch/arm/boot/dts/r8a7791-koelsch.dts
@@ -0,0 +1,32 @@
+/*
+ * Device Tree Source for the Koelsch board
+ *
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/dts-v1/;
+/include/ "r8a7791.dtsi"
+
+/ {
+ model = "Koelsch";
+ compatible = "renesas,koelsch", "renesas,r8a7791";
+
+ chosen {
+ bootargs = "console=ttySC6,115200 ignore_loglevel rw root=/dev/nfs ip=dhcp";
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0 0x40000000 0 0x80000000>;
+ };
+
+ lbsc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+};
diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
new file mode 100644
index 000000000000..bbed43bd9be9
--- /dev/null
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -0,0 +1,41 @@
+/*
+ * Device Tree Source for the r8a7791 SoC
+ *
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/ {
+ compatible = "renesas,r8a7791";
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <0>;
+ clock-frequency = <1300000000>;
+ };
+ };
+
+ gic: interrupt-controller@f1001000 {
+ compatible = "arm,cortex-a15-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0 0xf1001000 0 0x1000>,
+ <0 0xf1002000 0 0x1000>,
+ <0 0xf1004000 0 0x2000>,
+ <0 0xf1006000 0 0x2000>;
+ interrupts = <1 9 0xf04>;
+ };
+};
diff --git a/arch/arm/boot/dts/s3c6400.dtsi b/arch/arm/boot/dts/s3c6400.dtsi
new file mode 100644
index 000000000000..a7d1c8ec150d
--- /dev/null
+++ b/arch/arm/boot/dts/s3c6400.dtsi
@@ -0,0 +1,41 @@
+/*
+ * Samsung's S3C6400 SoC device tree source
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * Samsung's S3C6400 SoC device nodes are listed in this file. S3C6400
+ * based board files can include this file and provide values for board specfic
+ * bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * S3C6400 SoC. As device tree coverage for S3C6400 increases, additional
+ * nodes can be added to this file.
+ *
+ * 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 "s3c64xx.dtsi"
+
+/ {
+ compatible = "samsung,s3c6400";
+};
+
+&vic0 {
+ valid-mask = <0xfffffe1f>;
+ valid-wakeup-mask = <0x00200004>;
+};
+
+&vic1 {
+ valid-mask = <0xffffffff>;
+ valid-wakeup-mask = <0x53020000>;
+};
+
+&soc {
+ clocks: clock-controller@7e00f000 {
+ compatible = "samsung,s3c6400-clock";
+ reg = <0x7e00f000 0x1000>;
+ #clock-cells = <1>;
+ };
+};
diff --git a/arch/arm/boot/dts/s3c6410-mini6410.dts b/arch/arm/boot/dts/s3c6410-mini6410.dts
new file mode 100644
index 000000000000..57e00f9bce99
--- /dev/null
+++ b/arch/arm/boot/dts/s3c6410-mini6410.dts
@@ -0,0 +1,228 @@
+/*
+ * Samsung's S3C6410 based Mini6410 board device tree source
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * Device tree source file for FriendlyARM Mini6410 board which is based on
+ * Samsung's S3C6410 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include "s3c6410.dtsi"
+
+/ {
+ model = "FriendlyARM Mini6410 board based on S3C6410";
+ compatible = "friendlyarm,mini6410", "samsung,s3c6410";
+
+ memory {
+ reg = <0x50000000 0x10000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttySAC0,115200n8 earlyprintk rootwait root=/dev/mmcblk0p1";
+ };
+
+ clocks {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fin_pll: oscillator@0 {
+ compatible = "fixed-clock";
+ reg = <0>;
+ clock-frequency = <12000000>;
+ clock-output-names = "fin_pll";
+ #clock-cells = <0>;
+ };
+
+ xusbxti: oscillator@1 {
+ compatible = "fixed-clock";
+ reg = <1>;
+ clock-output-names = "xusbxti";
+ clock-frequency = <48000000>;
+ #clock-cells = <0>;
+ };
+ };
+
+ srom-cs1@18000000 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x18000000 0x8000000>;
+ ranges;
+
+ ethernet@18000000 {
+ compatible = "davicom,dm9000";
+ reg = <0x18000000 0x2 0x18000004 0x2>;
+ interrupt-parent = <&gpn>;
+ interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
+ davicom,no-eeprom;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_keys>;
+ autorepeat;
+
+ button-k1 {
+ label = "K1";
+ gpios = <&gpn 0 GPIO_ACTIVE_LOW>;
+ linux,code = <2>;
+ debounce-interval = <20>;
+ };
+
+ button-k2 {
+ label = "K2";
+ gpios = <&gpn 1 GPIO_ACTIVE_LOW>;
+ linux,code = <3>;
+ debounce-interval = <20>;
+ };
+
+ button-k3 {
+ label = "K3";
+ gpios = <&gpn 2 GPIO_ACTIVE_LOW>;
+ linux,code = <4>;
+ debounce-interval = <20>;
+ };
+
+ button-k4 {
+ label = "K4";
+ gpios = <&gpn 3 GPIO_ACTIVE_LOW>;
+ linux,code = <5>;
+ debounce-interval = <20>;
+ };
+
+ button-k5 {
+ label = "K5";
+ gpios = <&gpn 4 GPIO_ACTIVE_LOW>;
+ linux,code = <6>;
+ debounce-interval = <20>;
+ };
+
+ button-k6 {
+ label = "K6";
+ gpios = <&gpn 5 GPIO_ACTIVE_LOW>;
+ linux,code = <7>;
+ debounce-interval = <20>;
+ };
+
+ button-k7 {
+ label = "K7";
+ gpios = <&gpl 11 GPIO_ACTIVE_LOW>;
+ linux,code = <8>;
+ debounce-interval = <20>;
+ };
+
+ button-k8 {
+ label = "K8";
+ gpios = <&gpl 12 GPIO_ACTIVE_LOW>;
+ linux,code = <9>;
+ debounce-interval = <20>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_leds>;
+
+ led-1 {
+ label = "LED1";
+ gpios = <&gpk 4 GPIO_ACTIVE_LOW>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ led-2 {
+ label = "LED2";
+ gpios = <&gpk 5 GPIO_ACTIVE_LOW>;
+ linux,default-trigger = "mmc0";
+ };
+
+ led-3 {
+ label = "LED3";
+ gpios = <&gpk 6 GPIO_ACTIVE_LOW>;
+ };
+
+ led-4 {
+ label = "LED4";
+ gpios = <&gpk 7 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ buzzer {
+ compatible = "pwm-beeper";
+ pwms = <&pwm 0 1000000 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0_out>;
+ };
+};
+
+&sdhci0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sd0_clk>, <&sd0_cmd>, <&sd0_cd>, <&sd0_bus4>;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_data>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_data>, <&uart1_fctl>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_data>;
+ status = "okay";
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3_data>;
+ status = "okay";
+};
+
+&pwm {
+ status = "okay";
+};
+
+&pinctrl0 {
+ gpio_leds: gpio-leds {
+ samsung,pins = "gpk-4", "gpk-5", "gpk-6", "gpk-7";
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ gpio_keys: gpio-keys {
+ samsung,pins = "gpn-0", "gpn-1", "gpn-2", "gpn-3",
+ "gpn-4", "gpn-5", "gpl-11", "gpl-12";
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_bus>;
+ status = "okay";
+
+ eeprom@50 {
+ compatible = "atmel,24c08";
+ reg = <0x50>;
+ pagesize = <16>;
+ };
+};
diff --git a/arch/arm/boot/dts/s3c6410-smdk6410.dts b/arch/arm/boot/dts/s3c6410-smdk6410.dts
new file mode 100644
index 000000000000..ecf35ec466f7
--- /dev/null
+++ b/arch/arm/boot/dts/s3c6410-smdk6410.dts
@@ -0,0 +1,103 @@
+/*
+ * Samsung S3C6410 based SMDK6410 board device tree source.
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * Device tree source file for SAMSUNG SMDK6410 board which is based on
+ * Samsung's S3C6410 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include "s3c6410.dtsi"
+
+/ {
+ model = "SAMSUNG SMDK6410 board based on S3C6410";
+ compatible = "samsung,mini6410", "samsung,s3c6410";
+
+ memory {
+ reg = <0x50000000 0x8000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttySAC0,115200n8 earlyprintk rootwait root=/dev/mmcblk0p1";
+ };
+
+ clocks {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fin_pll: oscillator@0 {
+ compatible = "fixed-clock";
+ reg = <0>;
+ clock-frequency = <12000000>;
+ clock-output-names = "fin_pll";
+ #clock-cells = <0>;
+ };
+
+ xusbxti: oscillator@1 {
+ compatible = "fixed-clock";
+ reg = <1>;
+ clock-output-names = "xusbxti";
+ clock-frequency = <48000000>;
+ #clock-cells = <0>;
+ };
+ };
+
+ srom-cs1@18000000 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x18000000 0x8000000>;
+ ranges;
+
+ ethernet@18000000 {
+ compatible = "smsc,lan9115";
+ reg = <0x18000000 0x10000>;
+ interrupt-parent = <&gpn>;
+ interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
+ phy-mode = "mii";
+ reg-io-width = <4>;
+ smsc,force-internal-phy;
+ };
+ };
+};
+
+&sdhci0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sd0_clk>, <&sd0_cmd>, <&sd0_cd>, <&sd0_bus4>;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_data>, <&uart0_fctl>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_data>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_data>;
+ status = "okay";
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3_data>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/s3c6410.dtsi b/arch/arm/boot/dts/s3c6410.dtsi
new file mode 100644
index 000000000000..eb4226b3407c
--- /dev/null
+++ b/arch/arm/boot/dts/s3c6410.dtsi
@@ -0,0 +1,57 @@
+/*
+ * Samsung's S3C6410 SoC device tree source
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * Samsung's S3C6410 SoC device nodes are listed in this file. S3C6410
+ * based board files can include this file and provide values for board specfic
+ * bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * S3C6410 SoC. As device tree coverage for S3C6410 increases, additional
+ * nodes can be added to this file.
+ *
+ * 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 "s3c64xx.dtsi"
+
+/ {
+ compatible = "samsung,s3c6410";
+
+ aliases {
+ i2c1 = &i2c1;
+ };
+};
+
+&vic0 {
+ valid-mask = <0xffffff7f>;
+ valid-wakeup-mask = <0x00200004>;
+};
+
+&vic1 {
+ valid-mask = <0xffffffff>;
+ valid-wakeup-mask = <0x53020000>;
+};
+
+&soc {
+ clocks: clock-controller@7e00f000 {
+ compatible = "samsung,s3c6410-clock";
+ reg = <0x7e00f000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ i2c1: i2c@7f00f000 {
+ compatible = "samsung,s3c2440-i2c";
+ reg = <0x7f00f000 0x1000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <5>;
+ clock-names = "i2c";
+ clocks = <&clocks PCLK_IIC1>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+};
diff --git a/arch/arm/boot/dts/s3c64xx-pinctrl.dtsi b/arch/arm/boot/dts/s3c64xx-pinctrl.dtsi
new file mode 100644
index 000000000000..b1197d8b04de
--- /dev/null
+++ b/arch/arm/boot/dts/s3c64xx-pinctrl.dtsi
@@ -0,0 +1,687 @@
+/*
+ * Samsung's S3C64xx SoC series common device tree source
+ * - pin control-related definitions
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * Samsung's S3C64xx SoCs pin banks, pin-mux and pin-config options are
+ * listed as device tree nodes in this file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define PIN_PULL_NONE 0
+#define PIN_PULL_DOWN 1
+#define PIN_PULL_UP 2
+
+&pinctrl0 {
+ /*
+ * Pin banks
+ */
+
+ gpa: gpa {
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpb: gpb {
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpc: gpc {
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpd: gpd {
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpe: gpe {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpf: gpf {
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpg: gpg {
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gph: gph {
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpi: gpi {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpj: gpj {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpk: gpk {
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpl: gpl {
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpm: gpm {
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpn: gpn {
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpo: gpo {
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpp: gpp {
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpq: gpq {
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ /*
+ * Pin groups
+ */
+
+ uart0_data: uart0-data {
+ samsung,pins = "gpa-0", "gpa-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ uart0_fctl: uart0-fctl {
+ samsung,pins = "gpa-2", "gpa-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ uart1_data: uart1-data {
+ samsung,pins = "gpa-4", "gpa-5";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ uart1_fctl: uart1-fctl {
+ samsung,pins = "gpa-6", "gpa-7";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ uart2_data: uart2-data {
+ samsung,pins = "gpb-0", "gpb-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ uart3_data: uart3-data {
+ samsung,pins = "gpb-2", "gpb-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ ext_dma_0: ext-dma-0 {
+ samsung,pins = "gpb-0", "gpb-1";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ ext_dma_1: ext-dma-1 {
+ samsung,pins = "gpb-2", "gpb-3";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ irda_data_0: irda-data-0 {
+ samsung,pins = "gpb-0", "gpb-1";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ irda_data_1: irda-data-1 {
+ samsung,pins = "gpb-2", "gpb-3";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ irda_sdbw: irda-sdbw {
+ samsung,pins = "gpb-4";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ i2c0_bus: i2c0-bus {
+ samsung,pins = "gpb-5", "gpb-6";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_UP>;
+ };
+
+ i2c1_bus: i2c1-bus {
+ /* S3C6410-only */
+ samsung,pins = "gpb-2", "gpb-3";
+ samsung,pin-function = <6>;
+ samsung,pin-pud = <PIN_PULL_UP>;
+ };
+
+ spi0_bus: spi0-bus {
+ samsung,pins = "gpc-0", "gpc-1", "gpc-2";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_UP>;
+ };
+
+ spi0_cs: spi0-cs {
+ samsung,pins = "gpc-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ spi1_bus: spi1-bus {
+ samsung,pins = "gpc-4", "gpc-5", "gpc-6";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_UP>;
+ };
+
+ spi1_cs: spi1-cs {
+ samsung,pins = "gpc-7";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ sd0_cmd: sd0-cmd {
+ samsung,pins = "gpg-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ sd0_clk: sd0-clk {
+ samsung,pins = "gpg-0";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ sd0_bus1: sd0-bus1 {
+ samsung,pins = "gpg-2";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ sd0_bus4: sd0-bus4 {
+ samsung,pins = "gpg-2", "gpg-3", "gpg-4", "gpg-5";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ sd0_cd: sd0-cd {
+ samsung,pins = "gpg-6";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_UP>;
+ };
+
+ sd1_cmd: sd1-cmd {
+ samsung,pins = "gph-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ sd1_clk: sd1-clk {
+ samsung,pins = "gph-0";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ sd1_bus1: sd1-bus1 {
+ samsung,pins = "gph-2";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ sd1_bus4: sd1-bus4 {
+ samsung,pins = "gph-2", "gph-3", "gph-4", "gph-5";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ sd1_bus8: sd1-bus8 {
+ samsung,pins = "gph-2", "gph-3", "gph-4", "gph-5",
+ "gph-6", "gph-7", "gph-8", "gph-9";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ sd1_cd: sd1-cd {
+ samsung,pins = "gpg-6";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_UP>;
+ };
+
+ sd2_cmd: sd2-cmd {
+ samsung,pins = "gpc-4";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ sd2_clk: sd2-clk {
+ samsung,pins = "gpc-5";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ sd2_bus1: sd2-bus1 {
+ samsung,pins = "gph-6";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ sd2_bus4: sd2-bus4 {
+ samsung,pins = "gph-6", "gph-7", "gph-8", "gph-9";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ i2s0_bus: i2s0-bus {
+ samsung,pins = "gpd-0", "gpd-2", "gpd-3", "gpd-4";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ i2s0_cdclk: i2s0-cdclk {
+ samsung,pins = "gpd-1";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ i2s1_bus: i2s1-bus {
+ samsung,pins = "gpe-0", "gpe-2", "gpe-3", "gpe-4";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ i2s1_cdclk: i2s1-cdclk {
+ samsung,pins = "gpe-1";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ i2s2_bus: i2s2-bus {
+ /* S3C6410-only */
+ samsung,pins = "gpc-4", "gpc-5", "gpc-6", "gph-6",
+ "gph-8", "gph-9";
+ samsung,pin-function = <5>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ i2s2_cdclk: i2s2-cdclk {
+ /* S3C6410-only */
+ samsung,pins = "gph-7";
+ samsung,pin-function = <5>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ pcm0_bus: pcm0-bus {
+ samsung,pins = "gpd-0", "gpd-2", "gpd-3", "gpd-4";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ pcm0_extclk: pcm0-extclk {
+ samsung,pins = "gpd-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ pcm1_bus: pcm1-bus {
+ samsung,pins = "gpe-0", "gpe-2", "gpe-3", "gpe-4";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ pcm1_extclk: pcm1-extclk {
+ samsung,pins = "gpe-1";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ ac97_bus_0: ac97-bus-0 {
+ samsung,pins = "gpd-0", "gpd-1", "gpd-2", "gpd-3", "gpd-4";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ ac97_bus_1: ac97-bus-1 {
+ samsung,pins = "gpe-0", "gpe-1", "gpe-2", "gpe-3", "gpe-4";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ cam_port: cam-port {
+ samsung,pins = "gpf-0", "gpf-1", "gpf-2", "gpf-4",
+ "gpf-5", "gpf-6", "gpf-7", "gpf-8",
+ "gpf-9", "gpf-10", "gpf-11", "gpf-12";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ cam_rst: cam-rst {
+ samsung,pins = "gpf-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ cam_field: cam-field {
+ /* S3C6410-only */
+ samsung,pins = "gpb-4";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ pwm_extclk: pwm-extclk {
+ samsung,pins = "gpf-13";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ pwm0_out: pwm0-out {
+ samsung,pins = "gpf-14";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ pwm1_out: pwm1-out {
+ samsung,pins = "gpf-15";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ clkout0: clkout-0 {
+ samsung,pins = "gpf-14";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_col0_0: keypad-col0-0 {
+ samsung,pins = "gph-0";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_col1_0: keypad-col1-0 {
+ samsung,pins = "gph-1";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_col2_0: keypad-col2-0 {
+ samsung,pins = "gph-2";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_col3_0: keypad-col3-0 {
+ samsung,pins = "gph-3";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_col4_0: keypad-col4-0 {
+ samsung,pins = "gph-4";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_col5_0: keypad-col5-0 {
+ samsung,pins = "gph-5";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_col6_0: keypad-col6-0 {
+ samsung,pins = "gph-6";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_col7_0: keypad-col7-0 {
+ samsung,pins = "gph-7";
+ samsung,pin-function = <4>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_col0_1: keypad-col0-1 {
+ samsung,pins = "gpl-0";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_col1_1: keypad-col1-1 {
+ samsung,pins = "gpl-1";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_col2_1: keypad-col2-1 {
+ samsung,pins = "gpl-2";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_col3_1: keypad-col3-1 {
+ samsung,pins = "gpl-3";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_col4_1: keypad-col4-1 {
+ samsung,pins = "gpl-4";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_col5_1: keypad-col5-1 {
+ samsung,pins = "gpl-5";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_col6_1: keypad-col6-1 {
+ samsung,pins = "gpl-6";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_col7_1: keypad-col7-1 {
+ samsung,pins = "gpl-7";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_row0_0: keypad-row0-0 {
+ samsung,pins = "gpk-8";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_row1_0: keypad-row1-0 {
+ samsung,pins = "gpk-9";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_row2_0: keypad-row2-0 {
+ samsung,pins = "gpk-10";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_row3_0: keypad-row3-0 {
+ samsung,pins = "gpk-11";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_row4_0: keypad-row4-0 {
+ samsung,pins = "gpk-12";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_row5_0: keypad-row5-0 {
+ samsung,pins = "gpk-13";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_row6_0: keypad-row6-0 {
+ samsung,pins = "gpk-14";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_row7_0: keypad-row7-0 {
+ samsung,pins = "gpk-15";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_row0_1: keypad-row0-1 {
+ samsung,pins = "gpn-0";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_row1_1: keypad-row1-1 {
+ samsung,pins = "gpn-1";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_row2_1: keypad-row2-1 {
+ samsung,pins = "gpn-2";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_row3_1: keypad-row3-1 {
+ samsung,pins = "gpn-3";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_row4_1: keypad-row4-1 {
+ samsung,pins = "gpn-4";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_row5_1: keypad-row5-1 {
+ samsung,pins = "gpn-5";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_row6_1: keypad-row6-1 {
+ samsung,pins = "gpn-6";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ keypad_row7_1: keypad-row7-1 {
+ samsung,pins = "gpn-7";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ lcd_ctrl: lcd-ctrl {
+ samsung,pins = "gpj-8", "gpj-9", "gpj-10", "gpj-11";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ lcd_data16: lcd-data-width16 {
+ samsung,pins = "gpi-3", "gpi-4", "gpi-5", "gpi-6",
+ "gpi-7", "gpi-10", "gpi-11", "gpi-12",
+ "gpi-13", "gpi-14", "gpi-15", "gpj-3",
+ "gpj-4", "gpj-5", "gpj-6", "gpj-7";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ lcd_data18: lcd-data-width18 {
+ samsung,pins = "gpi-2", "gpi-3", "gpi-4", "gpi-5",
+ "gpi-6", "gpi-7", "gpi-10", "gpi-11",
+ "gpi-12", "gpi-13", "gpi-14", "gpi-15",
+ "gpj-2", "gpj-3", "gpj-4", "gpj-5",
+ "gpj-6", "gpj-7";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ lcd_data24: lcd-data-width24 {
+ samsung,pins = "gpi-0", "gpi-1", "gpi-2", "gpi-3",
+ "gpi-4", "gpi-5", "gpi-6", "gpi-7",
+ "gpi-8", "gpi-9", "gpi-10", "gpi-11",
+ "gpi-12", "gpi-13", "gpi-14", "gpi-15",
+ "gpj-0", "gpj-1", "gpj-2", "gpj-3",
+ "gpj-4", "gpj-5", "gpj-6", "gpj-7";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+
+ hsi_bus: hsi-bus {
+ samsung,pins = "gpk-0", "gpk-1", "gpk-2", "gpk-3",
+ "gpk-4", "gpk-5", "gpk-6", "gpk-7";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <PIN_PULL_NONE>;
+ };
+};
diff --git a/arch/arm/boot/dts/s3c64xx.dtsi b/arch/arm/boot/dts/s3c64xx.dtsi
new file mode 100644
index 000000000000..4e3be4d3493d
--- /dev/null
+++ b/arch/arm/boot/dts/s3c64xx.dtsi
@@ -0,0 +1,199 @@
+/*
+ * Samsung's S3C64xx SoC series common device tree source
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * Samsung's S3C64xx SoC series device nodes are listed in this file.
+ * Particular SoCs from S3C64xx series can include this file and provide
+ * values for SoCs specfic bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * S3C64xx SoCs. As device tree coverage for S3C64xx increases, additional
+ * nodes can be added to this file.
+ *
+ * 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 "skeleton.dtsi"
+#include <dt-bindings/clock/samsung,s3c64xx-clock.h>
+
+/ {
+ aliases {
+ i2c0 = &i2c0;
+ pinctrl0 = &pinctrl0;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,arm1176jzf-s", "arm,arm1176";
+ reg = <0x0>;
+ };
+ };
+
+ soc: soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ vic0: interrupt-controller@71200000 {
+ compatible = "arm,pl192-vic";
+ interrupt-controller;
+ reg = <0x71200000 0x1000>;
+ #interrupt-cells = <1>;
+ };
+
+ vic1: interrupt-controller@71300000 {
+ compatible = "arm,pl192-vic";
+ interrupt-controller;
+ reg = <0x71300000 0x1000>;
+ #interrupt-cells = <1>;
+ };
+
+ sdhci0: sdhci@7c200000 {
+ compatible = "samsung,s3c6410-sdhci";
+ reg = <0x7c200000 0x100>;
+ interrupt-parent = <&vic1>;
+ interrupts = <24>;
+ clock-names = "hsmmc", "mmc_busclk.0", "mmc_busclk.2";
+ clocks = <&clocks HCLK_HSMMC0>, <&clocks HCLK_HSMMC0>,
+ <&clocks SCLK_MMC0>;
+ status = "disabled";
+ };
+
+ sdhci1: sdhci@7c300000 {
+ compatible = "samsung,s3c6410-sdhci";
+ reg = <0x7c300000 0x100>;
+ interrupt-parent = <&vic1>;
+ interrupts = <25>;
+ clock-names = "hsmmc", "mmc_busclk.0", "mmc_busclk.2";
+ clocks = <&clocks HCLK_HSMMC1>, <&clocks HCLK_HSMMC1>,
+ <&clocks SCLK_MMC1>;
+ status = "disabled";
+ };
+
+ sdhci2: sdhci@7c400000 {
+ compatible = "samsung,s3c6410-sdhci";
+ reg = <0x7c400000 0x100>;
+ interrupt-parent = <&vic1>;
+ interrupts = <17>;
+ clock-names = "hsmmc", "mmc_busclk.0", "mmc_busclk.2";
+ clocks = <&clocks HCLK_HSMMC2>, <&clocks HCLK_HSMMC2>,
+ <&clocks SCLK_MMC2>;
+ status = "disabled";
+ };
+
+ watchdog: watchdog@7e004000 {
+ compatible = "samsung,s3c2410-wdt";
+ reg = <0x7e004000 0x1000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <26>;
+ clock-names = "watchdog";
+ clocks = <&clocks PCLK_WDT>;
+ status = "disabled";
+ };
+
+ i2c0: i2c@7f004000 {
+ compatible = "samsung,s3c2440-i2c";
+ reg = <0x7f004000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <18>;
+ clock-names = "i2c";
+ clocks = <&clocks PCLK_IIC0>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ uart0: serial@7f005000 {
+ compatible = "samsung,s3c6400-uart";
+ reg = <0x7f005000 0x100>;
+ interrupt-parent = <&vic1>;
+ interrupts = <5>;
+ clock-names = "uart", "clk_uart_baud2",
+ "clk_uart_baud3";
+ clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>,
+ <&clocks SCLK_UART>;
+ status = "disabled";
+ };
+
+ uart1: serial@7f005400 {
+ compatible = "samsung,s3c6400-uart";
+ reg = <0x7f005400 0x100>;
+ interrupt-parent = <&vic1>;
+ interrupts = <6>;
+ clock-names = "uart", "clk_uart_baud2",
+ "clk_uart_baud3";
+ clocks = <&clocks PCLK_UART1>, <&clocks PCLK_UART1>,
+ <&clocks SCLK_UART>;
+ status = "disabled";
+ };
+
+ uart2: serial@7f005800 {
+ compatible = "samsung,s3c6400-uart";
+ reg = <0x7f005800 0x100>;
+ interrupt-parent = <&vic1>;
+ interrupts = <7>;
+ clock-names = "uart", "clk_uart_baud2",
+ "clk_uart_baud3";
+ clocks = <&clocks PCLK_UART2>, <&clocks PCLK_UART2>,
+ <&clocks SCLK_UART>;
+ status = "disabled";
+ };
+
+ uart3: serial@7f005c00 {
+ compatible = "samsung,s3c6400-uart";
+ reg = <0x7f005c00 0x100>;
+ interrupt-parent = <&vic1>;
+ interrupts = <8>;
+ clock-names = "uart", "clk_uart_baud2",
+ "clk_uart_baud3";
+ clocks = <&clocks PCLK_UART3>, <&clocks PCLK_UART3>,
+ <&clocks SCLK_UART>;
+ status = "disabled";
+ };
+
+ pwm: pwm@7f006000 {
+ compatible = "samsung,s3c6400-pwm";
+ reg = <0x7f006000 0x1000>;
+ interrupt-parent = <&vic0>;
+ interrupts = <23>, <24>, <25>, <27>, <28>;
+ clock-names = "timers";
+ clocks = <&clocks PCLK_PWM>;
+ samsung,pwm-outputs = <0>, <1>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ pinctrl0: pinctrl@7f008000 {
+ compatible = "samsung,s3c64xx-pinctrl";
+ reg = <0x7f008000 0x1000>;
+ interrupt-parent = <&vic1>;
+ interrupts = <21>;
+
+ pctrl_int_map: pinctrl-interrupt-map {
+ interrupt-map = <0 &vic0 0>,
+ <1 &vic0 1>,
+ <2 &vic1 0>,
+ <3 &vic1 1>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+
+ wakeup-interrupt-controller {
+ compatible = "samsung,s3c64xx-wakeup-eint";
+ interrupts = <0>, <1>, <2>, <3>;
+ interrupt-parent = <&pctrl_int_map>;
+ };
+ };
+ };
+};
+
+#include "s3c64xx-pinctrl.dtsi"
diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi
index ba59a5875a10..3955c7606a6f 100644
--- a/arch/arm/boot/dts/sh73a0.dtsi
+++ b/arch/arm/boot/dts/sh73a0.dtsi
@@ -196,7 +196,7 @@
};
sdhi0: sdhi@ee100000 {
- compatible = "renesas,r8a7740-sdhi";
+ compatible = "renesas,sdhi-r8a7740";
reg = <0xee100000 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 83 4
@@ -208,7 +208,7 @@
/* SDHI1 and SDHI2 have no CD pins, no need for CD IRQ */
sdhi1: sdhi@ee120000 {
- compatible = "renesas,r8a7740-sdhi";
+ compatible = "renesas,sdhi-r8a7740";
reg = <0xee120000 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 88 4
@@ -219,7 +219,7 @@
};
sdhi2: sdhi@ee140000 {
- compatible = "renesas,r8a7740-sdhi";
+ compatible = "renesas,sdhi-r8a7740";
reg = <0xee140000 0x100>;
interrupt-parent = <&gic>;
interrupts = <0 104 4
diff --git a/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi b/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
index 9169d3025f39..79425e3836ce 100644
--- a/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
+++ b/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
@@ -653,6 +653,7 @@
reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
clocks = <&hclksmc>;
status = "okay";
+ timings = /bits/ 8 <0 0 0 0x10 0x0a 0>;
partition@0 {
label = "X-Loader(NAND)";
@@ -707,8 +708,14 @@
pinctrl-0 = <&i2c0_default_mux>, <&i2c0_default_mode>;
stw4811@2d {
- compatible = "st,stw4811";
- reg = <0x2d>;
+ compatible = "st,stw4811";
+ reg = <0x2d>;
+ vmmc_regulator: vmmc {
+ compatible = "st,stw481x-vmmc";
+ regulator-name = "VMMC";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
};
};
@@ -839,6 +846,7 @@
cd-inverted;
pinctrl-names = "default";
pinctrl-0 = <&mmcsd_default_mux>, <&mmcsd_default_mode>;
+ vmmc-supply = <&vmmc_regulator>;
};
};
};
diff --git a/arch/arm/boot/dts/tegra114-dalmore.dts b/arch/arm/boot/dts/tegra114-dalmore.dts
index 60230288884b..871aff5e2b87 100644
--- a/arch/arm/boot/dts/tegra114-dalmore.dts
+++ b/arch/arm/boot/dts/tegra114-dalmore.dts
@@ -1,5 +1,6 @@
/dts-v1/;
+#include <dt-bindings/input/input.h>
#include "tegra114.dtsi"
/ {
@@ -1011,6 +1012,19 @@
interrupt-parent = <&palmas>;
interrupts = <8 0>;
};
+
+ pinmux {
+ compatible = "ti,tps65913-pinctrl";
+ pinctrl-names = "default";
+ pinctrl-0 = <&palmas_default>;
+
+ palmas_default: pinmux {
+ pin_gpio6 {
+ pins = "gpio6";
+ function = "gpio";
+ };
+ };
+ };
};
};
@@ -1081,26 +1095,26 @@
home {
label = "Home";
gpios = <&gpio TEGRA_GPIO(I, 5) GPIO_ACTIVE_LOW>;
- linux,code = <102>; /* KEY_HOME */
+ linux,code = <KEY_HOME>;
};
power {
label = "Power";
gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>;
- linux,code = <116>; /* KEY_POWER */
+ linux,code = <KEY_POWER>;
gpio-key,wakeup;
};
volume_down {
label = "Volume Down";
gpios = <&gpio TEGRA_GPIO(R, 1) GPIO_ACTIVE_LOW>;
- linux,code = <114>; /* KEY_VOLUMEDOWN */
+ linux,code = <KEY_VOLUMEDOWN>;
};
volume_up {
label = "Volume Up";
gpios = <&gpio TEGRA_GPIO(R, 2) GPIO_ACTIVE_LOW>;
- linux,code = <115>; /* KEY_VOLUMEUP */
+ linux,code = <KEY_VOLUMEUP>;
};
};
diff --git a/arch/arm/boot/dts/vf610-cosmic.dts b/arch/arm/boot/dts/vf610-cosmic.dts
new file mode 100644
index 000000000000..c42e4f938dcd
--- /dev/null
+++ b/arch/arm/boot/dts/vf610-cosmic.dts
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ * Copyright 2013 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+/dts-v1/;
+#include "vf610.dtsi"
+
+/ {
+ model = "PHYTEC Cosmic/Cosmic+ Board";
+ compatible = "phytec,vf610-cosmic", "fsl,vf610";
+
+ chosen {
+ bootargs = "console=ttyLP1,115200";
+ };
+
+ memory {
+ reg = <0x80000000 0x10000000>;
+ };
+
+ clocks {
+ enet_ext {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <50000000>;
+ };
+ };
+
+};
+
+&fec1 {
+ phy-mode = "rmii";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1_1>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1_1>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/vf610-twr.dts b/arch/arm/boot/dts/vf610-twr.dts
index 1a58678b93fa..c8047ca16501 100644
--- a/arch/arm/boot/dts/vf610-twr.dts
+++ b/arch/arm/boot/dts/vf610-twr.dts
@@ -36,6 +36,23 @@
};
+&dspi0 {
+ bus-num = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_dspi0_1>;
+ status = "okay";
+
+ sflash: at26df081a@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "atmel,at26df081a";
+ spi-max-frequency = <16000000>;
+ spi-cpol;
+ spi-cpha;
+ reg = <0>;
+ };
+};
+
&fec0 {
phy-mode = "rmii";
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi
index 67d929cf9804..d31ce1b4a7b0 100644
--- a/arch/arm/boot/dts/vf610.dtsi
+++ b/arch/arm/boot/dts/vf610.dtsi
@@ -123,6 +123,18 @@
status = "disabled";
};
+ dspi0: dspi0@4002c000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,vf610-dspi";
+ reg = <0x4002c000 0x1000>;
+ interrupts = <0 67 0x04>;
+ clocks = <&clks VF610_CLK_DSPI0>;
+ clock-names = "dspi";
+ spi-num-chipselects = <5>;
+ status = "disabled";
+ };
+
sai2: sai@40031000 {
compatible = "fsl,vf610-sai";
reg = <0x40031000 0x1000>;
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 8c60f473e976..4bdc41622c36 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -6,7 +6,6 @@ obj-y += firmware.o
obj-$(CONFIG_ICST) += icst.o
obj-$(CONFIG_SA1111) += sa1111.o
-obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o
obj-$(CONFIG_DMABOUNCE) += dmabounce.o
obj-$(CONFIG_SHARP_LOCOMO) += locomo.o
obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o
@@ -17,3 +16,5 @@ obj-$(CONFIG_MCPM) += mcpm_head.o mcpm_entry.o mcpm_platsmp.o vlock.o
AFLAGS_mcpm_head.o := -march=armv7-a
AFLAGS_vlock.o := -march=armv7-a
obj-$(CONFIG_TI_PRIV_EDMA) += edma.o
+obj-$(CONFIG_BL_SWITCHER) += bL_switcher.o
+obj-$(CONFIG_BL_SWITCHER_DUMMY_IF) += bL_switcher_dummy_if.o
diff --git a/arch/arm/common/bL_switcher.c b/arch/arm/common/bL_switcher.c
new file mode 100644
index 000000000000..335ff76d4c5a
--- /dev/null
+++ b/arch/arm/common/bL_switcher.c
@@ -0,0 +1,606 @@
+/*
+ * arch/arm/common/bL_switcher.c -- big.LITTLE cluster switcher core driver
+ *
+ * Created by: Nicolas Pitre, March 2012
+ * Copyright: (C) 2012-2013 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/cpu_pm.h>
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+#include <linux/clockchips.h>
+#include <linux/hrtimer.h>
+#include <linux/tick.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include <linux/irqchip/arm-gic.h>
+#include <linux/moduleparam.h>
+
+#include <asm/smp_plat.h>
+#include <asm/suspend.h>
+#include <asm/mcpm.h>
+#include <asm/bL_switcher.h>
+
+
+/*
+ * Use our own MPIDR accessors as the generic ones in asm/cputype.h have
+ * __attribute_const__ and we don't want the compiler to assume any
+ * constness here as the value _does_ change along some code paths.
+ */
+
+static int read_mpidr(void)
+{
+ unsigned int id;
+ asm volatile ("mrc p15, 0, %0, c0, c0, 5" : "=r" (id));
+ return id & MPIDR_HWID_BITMASK;
+}
+
+/*
+ * bL switcher core code.
+ */
+
+static void bL_do_switch(void *_unused)
+{
+ unsigned ib_mpidr, ib_cpu, ib_cluster;
+
+ pr_debug("%s\n", __func__);
+
+ ib_mpidr = cpu_logical_map(smp_processor_id());
+ ib_cpu = MPIDR_AFFINITY_LEVEL(ib_mpidr, 0);
+ ib_cluster = MPIDR_AFFINITY_LEVEL(ib_mpidr, 1);
+
+ /*
+ * Our state has been saved at this point. Let's release our
+ * inbound CPU.
+ */
+ mcpm_set_entry_vector(ib_cpu, ib_cluster, cpu_resume);
+ sev();
+
+ /*
+ * From this point, we must assume that our counterpart CPU might
+ * have taken over in its parallel world already, as if execution
+ * just returned from cpu_suspend(). It is therefore important to
+ * be very careful not to make any change the other guy is not
+ * expecting. This is why we need stack isolation.
+ *
+ * Fancy under cover tasks could be performed here. For now
+ * we have none.
+ */
+
+ /* Let's put ourself down. */
+ mcpm_cpu_power_down();
+
+ /* should never get here */
+ BUG();
+}
+
+/*
+ * Stack isolation. To ensure 'current' remains valid, we just use another
+ * piece of our thread's stack space which should be fairly lightly used.
+ * The selected area starts just above the thread_info structure located
+ * at the very bottom of the stack, aligned to a cache line, and indexed
+ * with the cluster number.
+ */
+#define STACK_SIZE 512
+extern void call_with_stack(void (*fn)(void *), void *arg, void *sp);
+static int bL_switchpoint(unsigned long _arg)
+{
+ unsigned int mpidr = read_mpidr();
+ unsigned int clusterid = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+ void *stack = current_thread_info() + 1;
+ stack = PTR_ALIGN(stack, L1_CACHE_BYTES);
+ stack += clusterid * STACK_SIZE + STACK_SIZE;
+ call_with_stack(bL_do_switch, (void *)_arg, stack);
+ BUG();
+}
+
+/*
+ * Generic switcher interface
+ */
+
+static unsigned int bL_gic_id[MAX_CPUS_PER_CLUSTER][MAX_NR_CLUSTERS];
+static int bL_switcher_cpu_pairing[NR_CPUS];
+
+/*
+ * bL_switch_to - Switch to a specific cluster for the current CPU
+ * @new_cluster_id: the ID of the cluster to switch to.
+ *
+ * This function must be called on the CPU to be switched.
+ * Returns 0 on success, else a negative status code.
+ */
+static int bL_switch_to(unsigned int new_cluster_id)
+{
+ unsigned int mpidr, this_cpu, that_cpu;
+ unsigned int ob_mpidr, ob_cpu, ob_cluster, ib_mpidr, ib_cpu, ib_cluster;
+ struct tick_device *tdev;
+ enum clock_event_mode tdev_mode;
+ int ret;
+
+ this_cpu = smp_processor_id();
+ ob_mpidr = read_mpidr();
+ ob_cpu = MPIDR_AFFINITY_LEVEL(ob_mpidr, 0);
+ ob_cluster = MPIDR_AFFINITY_LEVEL(ob_mpidr, 1);
+ BUG_ON(cpu_logical_map(this_cpu) != ob_mpidr);
+
+ if (new_cluster_id == ob_cluster)
+ return 0;
+
+ that_cpu = bL_switcher_cpu_pairing[this_cpu];
+ ib_mpidr = cpu_logical_map(that_cpu);
+ ib_cpu = MPIDR_AFFINITY_LEVEL(ib_mpidr, 0);
+ ib_cluster = MPIDR_AFFINITY_LEVEL(ib_mpidr, 1);
+
+ pr_debug("before switch: CPU %d MPIDR %#x -> %#x\n",
+ this_cpu, ob_mpidr, ib_mpidr);
+
+ /* Close the gate for our entry vectors */
+ mcpm_set_entry_vector(ob_cpu, ob_cluster, NULL);
+ mcpm_set_entry_vector(ib_cpu, ib_cluster, NULL);
+
+ /*
+ * Let's wake up the inbound CPU now in case it requires some delay
+ * to come online, but leave it gated in our entry vector code.
+ */
+ ret = mcpm_cpu_power_up(ib_cpu, ib_cluster);
+ if (ret) {
+ pr_err("%s: mcpm_cpu_power_up() returned %d\n", __func__, ret);
+ return ret;
+ }
+
+ /*
+ * From this point we are entering the switch critical zone
+ * and can't take any interrupts anymore.
+ */
+ local_irq_disable();
+ local_fiq_disable();
+
+ /* redirect GIC's SGIs to our counterpart */
+ gic_migrate_target(bL_gic_id[ib_cpu][ib_cluster]);
+
+ /*
+ * Raise a SGI on the inbound CPU to make sure it doesn't stall
+ * in a possible WFI, such as in mcpm_power_down().
+ */
+ arch_send_wakeup_ipi_mask(cpumask_of(this_cpu));
+
+ tdev = tick_get_device(this_cpu);
+ if (tdev && !cpumask_equal(tdev->evtdev->cpumask, cpumask_of(this_cpu)))
+ tdev = NULL;
+ if (tdev) {
+ tdev_mode = tdev->evtdev->mode;
+ clockevents_set_mode(tdev->evtdev, CLOCK_EVT_MODE_SHUTDOWN);
+ }
+
+ ret = cpu_pm_enter();
+
+ /* we can not tolerate errors at this point */
+ if (ret)
+ panic("%s: cpu_pm_enter() returned %d\n", __func__, ret);
+
+ /* Swap the physical CPUs in the logical map for this logical CPU. */
+ cpu_logical_map(this_cpu) = ib_mpidr;
+ cpu_logical_map(that_cpu) = ob_mpidr;
+
+ /* Let's do the actual CPU switch. */
+ ret = cpu_suspend(0, bL_switchpoint);
+ if (ret > 0)
+ panic("%s: cpu_suspend() returned %d\n", __func__, ret);
+
+ /* We are executing on the inbound CPU at this point */
+ mpidr = read_mpidr();
+ pr_debug("after switch: CPU %d MPIDR %#x\n", this_cpu, mpidr);
+ BUG_ON(mpidr != ib_mpidr);
+
+ mcpm_cpu_powered_up();
+
+ ret = cpu_pm_exit();
+
+ if (tdev) {
+ clockevents_set_mode(tdev->evtdev, tdev_mode);
+ clockevents_program_event(tdev->evtdev,
+ tdev->evtdev->next_event, 1);
+ }
+
+ local_fiq_enable();
+ local_irq_enable();
+
+ if (ret)
+ pr_err("%s exiting with error %d\n", __func__, ret);
+ return ret;
+}
+
+struct bL_thread {
+ struct task_struct *task;
+ wait_queue_head_t wq;
+ int wanted_cluster;
+ struct completion started;
+};
+
+static struct bL_thread bL_threads[NR_CPUS];
+
+static int bL_switcher_thread(void *arg)
+{
+ struct bL_thread *t = arg;
+ struct sched_param param = { .sched_priority = 1 };
+ int cluster;
+
+ sched_setscheduler_nocheck(current, SCHED_FIFO, &param);
+ complete(&t->started);
+
+ do {
+ if (signal_pending(current))
+ flush_signals(current);
+ wait_event_interruptible(t->wq,
+ t->wanted_cluster != -1 ||
+ kthread_should_stop());
+ cluster = xchg(&t->wanted_cluster, -1);
+ if (cluster != -1)
+ bL_switch_to(cluster);
+ } while (!kthread_should_stop());
+
+ return 0;
+}
+
+static struct task_struct *bL_switcher_thread_create(int cpu, void *arg)
+{
+ struct task_struct *task;
+
+ task = kthread_create_on_node(bL_switcher_thread, arg,
+ cpu_to_node(cpu), "kswitcher_%d", cpu);
+ if (!IS_ERR(task)) {
+ kthread_bind(task, cpu);
+ wake_up_process(task);
+ } else
+ pr_err("%s failed for CPU %d\n", __func__, cpu);
+ return task;
+}
+
+/*
+ * bL_switch_request - Switch to a specific cluster for the given CPU
+ *
+ * @cpu: the CPU to switch
+ * @new_cluster_id: the ID of the cluster to switch to.
+ *
+ * This function causes a cluster switch on the given CPU by waking up
+ * the appropriate switcher thread. This function may or may not return
+ * before the switch has occurred.
+ */
+int bL_switch_request(unsigned int cpu, unsigned int new_cluster_id)
+{
+ struct bL_thread *t;
+
+ if (cpu >= ARRAY_SIZE(bL_threads)) {
+ pr_err("%s: cpu %d out of bounds\n", __func__, cpu);
+ return -EINVAL;
+ }
+
+ t = &bL_threads[cpu];
+ if (IS_ERR(t->task))
+ return PTR_ERR(t->task);
+ if (!t->task)
+ return -ESRCH;
+
+ t->wanted_cluster = new_cluster_id;
+ wake_up(&t->wq);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(bL_switch_request);
+
+/*
+ * Activation and configuration code.
+ */
+
+static unsigned int bL_switcher_active;
+static unsigned int bL_switcher_cpu_original_cluster[NR_CPUS];
+static cpumask_t bL_switcher_removed_logical_cpus;
+
+static void bL_switcher_restore_cpus(void)
+{
+ int i;
+
+ for_each_cpu(i, &bL_switcher_removed_logical_cpus)
+ cpu_up(i);
+}
+
+static int bL_switcher_halve_cpus(void)
+{
+ int i, j, cluster_0, gic_id, ret;
+ unsigned int cpu, cluster, mask;
+ cpumask_t available_cpus;
+
+ /* First pass to validate what we have */
+ mask = 0;
+ for_each_online_cpu(i) {
+ cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(i), 0);
+ cluster = MPIDR_AFFINITY_LEVEL(cpu_logical_map(i), 1);
+ if (cluster >= 2) {
+ pr_err("%s: only dual cluster systems are supported\n", __func__);
+ return -EINVAL;
+ }
+ if (WARN_ON(cpu >= MAX_CPUS_PER_CLUSTER))
+ return -EINVAL;
+ mask |= (1 << cluster);
+ }
+ if (mask != 3) {
+ pr_err("%s: no CPU pairing possible\n", __func__);
+ return -EINVAL;
+ }
+
+ /*
+ * Now let's do the pairing. We match each CPU with another CPU
+ * from a different cluster. To get a uniform scheduling behavior
+ * without fiddling with CPU topology and compute capacity data,
+ * we'll use logical CPUs initially belonging to the same cluster.
+ */
+ memset(bL_switcher_cpu_pairing, -1, sizeof(bL_switcher_cpu_pairing));
+ cpumask_copy(&available_cpus, cpu_online_mask);
+ cluster_0 = -1;
+ for_each_cpu(i, &available_cpus) {
+ int match = -1;
+ cluster = MPIDR_AFFINITY_LEVEL(cpu_logical_map(i), 1);
+ if (cluster_0 == -1)
+ cluster_0 = cluster;
+ if (cluster != cluster_0)
+ continue;
+ cpumask_clear_cpu(i, &available_cpus);
+ for_each_cpu(j, &available_cpus) {
+ cluster = MPIDR_AFFINITY_LEVEL(cpu_logical_map(j), 1);
+ /*
+ * Let's remember the last match to create "odd"
+ * pairings on purpose in order for other code not
+ * to assume any relation between physical and
+ * logical CPU numbers.
+ */
+ if (cluster != cluster_0)
+ match = j;
+ }
+ if (match != -1) {
+ bL_switcher_cpu_pairing[i] = match;
+ cpumask_clear_cpu(match, &available_cpus);
+ pr_info("CPU%d paired with CPU%d\n", i, match);
+ }
+ }
+
+ /*
+ * Now we disable the unwanted CPUs i.e. everything that has no
+ * pairing information (that includes the pairing counterparts).
+ */
+ cpumask_clear(&bL_switcher_removed_logical_cpus);
+ for_each_online_cpu(i) {
+ cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(i), 0);
+ cluster = MPIDR_AFFINITY_LEVEL(cpu_logical_map(i), 1);
+
+ /* Let's take note of the GIC ID for this CPU */
+ gic_id = gic_get_cpu_id(i);
+ if (gic_id < 0) {
+ pr_err("%s: bad GIC ID for CPU %d\n", __func__, i);
+ bL_switcher_restore_cpus();
+ return -EINVAL;
+ }
+ bL_gic_id[cpu][cluster] = gic_id;
+ pr_info("GIC ID for CPU %u cluster %u is %u\n",
+ cpu, cluster, gic_id);
+
+ if (bL_switcher_cpu_pairing[i] != -1) {
+ bL_switcher_cpu_original_cluster[i] = cluster;
+ continue;
+ }
+
+ ret = cpu_down(i);
+ if (ret) {
+ bL_switcher_restore_cpus();
+ return ret;
+ }
+ cpumask_set_cpu(i, &bL_switcher_removed_logical_cpus);
+ }
+
+ return 0;
+}
+
+static int bL_switcher_enable(void)
+{
+ int cpu, ret;
+
+ cpu_hotplug_driver_lock();
+ if (bL_switcher_active) {
+ cpu_hotplug_driver_unlock();
+ return 0;
+ }
+
+ pr_info("big.LITTLE switcher initializing\n");
+
+ ret = bL_switcher_halve_cpus();
+ if (ret) {
+ cpu_hotplug_driver_unlock();
+ return ret;
+ }
+
+ for_each_online_cpu(cpu) {
+ struct bL_thread *t = &bL_threads[cpu];
+ init_waitqueue_head(&t->wq);
+ init_completion(&t->started);
+ t->wanted_cluster = -1;
+ t->task = bL_switcher_thread_create(cpu, t);
+ }
+
+ bL_switcher_active = 1;
+ cpu_hotplug_driver_unlock();
+
+ pr_info("big.LITTLE switcher initialized\n");
+ return 0;
+}
+
+#ifdef CONFIG_SYSFS
+
+static void bL_switcher_disable(void)
+{
+ unsigned int cpu, cluster;
+ struct bL_thread *t;
+ struct task_struct *task;
+
+ cpu_hotplug_driver_lock();
+ if (!bL_switcher_active) {
+ cpu_hotplug_driver_unlock();
+ return;
+ }
+ bL_switcher_active = 0;
+
+ /*
+ * To deactivate the switcher, we must shut down the switcher
+ * threads to prevent any other requests from being accepted.
+ * Then, if the final cluster for given logical CPU is not the
+ * same as the original one, we'll recreate a switcher thread
+ * just for the purpose of switching the CPU back without any
+ * possibility for interference from external requests.
+ */
+ for_each_online_cpu(cpu) {
+ t = &bL_threads[cpu];
+ task = t->task;
+ t->task = NULL;
+ if (!task || IS_ERR(task))
+ continue;
+ kthread_stop(task);
+ /* no more switch may happen on this CPU at this point */
+ cluster = MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 1);
+ if (cluster == bL_switcher_cpu_original_cluster[cpu])
+ continue;
+ init_completion(&t->started);
+ t->wanted_cluster = bL_switcher_cpu_original_cluster[cpu];
+ task = bL_switcher_thread_create(cpu, t);
+ if (!IS_ERR(task)) {
+ wait_for_completion(&t->started);
+ kthread_stop(task);
+ cluster = MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 1);
+ if (cluster == bL_switcher_cpu_original_cluster[cpu])
+ continue;
+ }
+ /* If execution gets here, we're in trouble. */
+ pr_crit("%s: unable to restore original cluster for CPU %d\n",
+ __func__, cpu);
+ pr_crit("%s: CPU %d can't be restored\n",
+ __func__, bL_switcher_cpu_pairing[cpu]);
+ cpumask_clear_cpu(bL_switcher_cpu_pairing[cpu],
+ &bL_switcher_removed_logical_cpus);
+ }
+
+ bL_switcher_restore_cpus();
+ cpu_hotplug_driver_unlock();
+}
+
+static ssize_t bL_switcher_active_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", bL_switcher_active);
+}
+
+static ssize_t bL_switcher_active_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ int ret;
+
+ switch (buf[0]) {
+ case '0':
+ bL_switcher_disable();
+ ret = 0;
+ break;
+ case '1':
+ ret = bL_switcher_enable();
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return (ret >= 0) ? count : ret;
+}
+
+static struct kobj_attribute bL_switcher_active_attr =
+ __ATTR(active, 0644, bL_switcher_active_show, bL_switcher_active_store);
+
+static struct attribute *bL_switcher_attrs[] = {
+ &bL_switcher_active_attr.attr,
+ NULL,
+};
+
+static struct attribute_group bL_switcher_attr_group = {
+ .attrs = bL_switcher_attrs,
+};
+
+static struct kobject *bL_switcher_kobj;
+
+static int __init bL_switcher_sysfs_init(void)
+{
+ int ret;
+
+ bL_switcher_kobj = kobject_create_and_add("bL_switcher", kernel_kobj);
+ if (!bL_switcher_kobj)
+ return -ENOMEM;
+ ret = sysfs_create_group(bL_switcher_kobj, &bL_switcher_attr_group);
+ if (ret)
+ kobject_put(bL_switcher_kobj);
+ return ret;
+}
+
+#endif /* CONFIG_SYSFS */
+
+/*
+ * Veto any CPU hotplug operation on those CPUs we've removed
+ * while the switcher is active.
+ * We're just not ready to deal with that given the trickery involved.
+ */
+static int bL_switcher_hotplug_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ if (bL_switcher_active) {
+ int pairing = bL_switcher_cpu_pairing[(unsigned long)hcpu];
+ switch (action & 0xf) {
+ case CPU_UP_PREPARE:
+ case CPU_DOWN_PREPARE:
+ if (pairing == -1)
+ return NOTIFY_BAD;
+ }
+ }
+ return NOTIFY_DONE;
+}
+
+static bool no_bL_switcher;
+core_param(no_bL_switcher, no_bL_switcher, bool, 0644);
+
+static int __init bL_switcher_init(void)
+{
+ int ret;
+
+ if (MAX_NR_CLUSTERS != 2) {
+ pr_err("%s: only dual cluster systems are supported\n", __func__);
+ return -EINVAL;
+ }
+
+ cpu_notifier(bL_switcher_hotplug_callback, 0);
+
+ if (!no_bL_switcher) {
+ ret = bL_switcher_enable();
+ if (ret)
+ return ret;
+ }
+
+#ifdef CONFIG_SYSFS
+ ret = bL_switcher_sysfs_init();
+ if (ret)
+ pr_err("%s: unable to create sysfs entry\n", __func__);
+#endif
+
+ return 0;
+}
+
+late_initcall(bL_switcher_init);
diff --git a/arch/arm/common/bL_switcher_dummy_if.c b/arch/arm/common/bL_switcher_dummy_if.c
new file mode 100644
index 000000000000..3f47f1203c6b
--- /dev/null
+++ b/arch/arm/common/bL_switcher_dummy_if.c
@@ -0,0 +1,71 @@
+/*
+ * arch/arm/common/bL_switcher_dummy_if.c -- b.L switcher dummy interface
+ *
+ * Created by: Nicolas Pitre, November 2012
+ * Copyright: (C) 2012-2013 Linaro Limited
+ *
+ * Dummy interface to user space for debugging purpose only.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+#include <asm/bL_switcher.h>
+
+static ssize_t bL_switcher_write(struct file *file, const char __user *buf,
+ size_t len, loff_t *pos)
+{
+ unsigned char val[3];
+ unsigned int cpu, cluster;
+ int ret;
+
+ pr_debug("%s\n", __func__);
+
+ if (len < 3)
+ return -EINVAL;
+
+ if (copy_from_user(val, buf, 3))
+ return -EFAULT;
+
+ /* format: <cpu#>,<cluster#> */
+ if (val[0] < '0' || val[0] > '9' ||
+ val[1] != ',' ||
+ val[2] < '0' || val[2] > '1')
+ return -EINVAL;
+
+ cpu = val[0] - '0';
+ cluster = val[2] - '0';
+ ret = bL_switch_request(cpu, cluster);
+
+ return ret ? : len;
+}
+
+static const struct file_operations bL_switcher_fops = {
+ .write = bL_switcher_write,
+ .owner = THIS_MODULE,
+};
+
+static struct miscdevice bL_switcher_device = {
+ MISC_DYNAMIC_MINOR,
+ "b.L_switcher",
+ &bL_switcher_fops
+};
+
+static int __init bL_switcher_dummy_if_init(void)
+{
+ return misc_register(&bL_switcher_device);
+}
+
+static void __exit bL_switcher_dummy_if_exit(void)
+{
+ misc_deregister(&bL_switcher_device);
+}
+
+module_init(bL_switcher_dummy_if_init);
+module_exit(bL_switcher_dummy_if_exit);
diff --git a/arch/arm/common/via82c505.c b/arch/arm/common/via82c505.c
deleted file mode 100644
index 6cb362e56d29..000000000000
--- a/arch/arm/common/via82c505.c
+++ /dev/null
@@ -1,83 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-
-
-#include <asm/mach/pci.h>
-
-#define MAX_SLOTS 7
-
-#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
-
-static int
-via82c505_read_config(struct pci_bus *bus, unsigned int devfn, int where,
- int size, u32 *value)
-{
- outl(CONFIG_CMD(bus,devfn,where),0xCF8);
- switch (size) {
- case 1:
- *value=inb(0xCFC + (where&3));
- break;
- case 2:
- *value=inw(0xCFC + (where&2));
- break;
- case 4:
- *value=inl(0xCFC);
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-via82c505_write_config(struct pci_bus *bus, unsigned int devfn, int where,
- int size, u32 value)
-{
- outl(CONFIG_CMD(bus,devfn,where),0xCF8);
- switch (size) {
- case 1:
- outb(value, 0xCFC + (where&3));
- break;
- case 2:
- outw(value, 0xCFC + (where&2));
- break;
- case 4:
- outl(value, 0xCFC);
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops via82c505_ops = {
- .read = via82c505_read_config,
- .write = via82c505_write_config,
-};
-
-void __init via82c505_preinit(void)
-{
- printk(KERN_DEBUG "PCI: VIA 82c505\n");
- if (!request_region(0xA8,2,"via config")) {
- printk(KERN_WARNING"VIA 82c505: Unable to request region 0xA8\n");
- return;
- }
- if (!request_region(0xCF8,8,"pci config")) {
- printk(KERN_WARNING"VIA 82c505: Unable to request region 0xCF8\n");
- release_region(0xA8, 2);
- return;
- }
-
- /* Enable compatible Mode */
- outb(0x96,0xA8);
- outb(0x18,0xA9);
- outb(0x93,0xA8);
- outb(0xd0,0xA9);
-
-}
-
-int __init via82c505_setup(int nr, struct pci_sys_data *sys)
-{
- return (nr == 0);
-}
diff --git a/arch/arm/configs/bockw_defconfig b/arch/arm/configs/bockw_defconfig
index e7e94948d194..b38cd107f82d 100644
--- a/arch/arm/configs/bockw_defconfig
+++ b/arch/arm/configs/bockw_defconfig
@@ -91,6 +91,10 @@ CONFIG_VIDEO_RCAR_VIN=y
CONFIG_VIDEO_ML86V7667=y
CONFIG_SPI=y
CONFIG_SPI_SH_HSPI=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_RCAR=y
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_EHCI_HCD=y
diff --git a/arch/arm/configs/koelsch_defconfig b/arch/arm/configs/koelsch_defconfig
new file mode 100644
index 000000000000..825c16dee8a0
--- /dev/null
+++ b/arch/arm/configs/koelsch_defconfig
@@ -0,0 +1,54 @@
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+CONFIG_SLAB=y
+# CONFIG_BLOCK is not set
+CONFIG_ARCH_SHMOBILE=y
+CONFIG_ARCH_R8A7791=y
+CONFIG_MACH_KOELSCH=y
+# CONFIG_SWP_EMULATE is not set
+CONFIG_CPU_BPREDICT_DISABLE=y
+CONFIG_PL310_ERRATA_588369=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_NR_CPUS=8
+CONFIG_AEABI=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_KEXEC=y
+CONFIG_AUTO_ZRELADDR=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=20
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+# CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_RCAR_THERMAL=y
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_ARM_UNWIND is not set
diff --git a/arch/arm/configs/lager_defconfig b/arch/arm/configs/lager_defconfig
index e777ef22b801..35bff5e0d57a 100644
--- a/arch/arm/configs/lager_defconfig
+++ b/arch/arm/configs/lager_defconfig
@@ -89,6 +89,8 @@ CONFIG_THERMAL=y
CONFIG_RCAR_THERMAL=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_DRM=y
+CONFIG_DRM_RCAR_DU=y
# CONFIG_USB_SUPPORT is not set
CONFIG_MMC=y
CONFIG_MMC_SDHI=y
diff --git a/arch/arm/configs/marzen_defconfig b/arch/arm/configs/marzen_defconfig
index 000e9205b2b9..5cc6360340b1 100644
--- a/arch/arm/configs/marzen_defconfig
+++ b/arch/arm/configs/marzen_defconfig
@@ -92,6 +92,8 @@ CONFIG_SOC_CAMERA=y
CONFIG_VIDEO_RCAR_VIN=y
# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
CONFIG_VIDEO_ADV7180=y
+CONFIG_DRM=y
+CONFIG_DRM_RCAR_DU=y
CONFIG_USB=y
CONFIG_USB_RCAR_PHY=y
CONFIG_MMC=y
diff --git a/arch/arm/configs/shark_defconfig b/arch/arm/configs/shark_defconfig
deleted file mode 100644
index e319b2c56f11..000000000000
--- a/arch/arm/configs/shark_defconfig
+++ /dev/null
@@ -1,80 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_SHARK=y
-CONFIG_LEDS=y
-CONFIG_LEDS_TIMER=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_STANDALONE is not set
-# CONFIG_FIRMWARE_IN_KERNEL is not set
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=m
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
-CONFIG_CHR_DEV_ST=m
-CONFIG_BLK_DEV_SR=m
-CONFIG_CHR_DEV_SG=m
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_NET_PCI=y
-CONFIG_CS89x0=y
-# CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_PRINTER=m
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FB_CYBER2000=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-CONFIG_SOUND=m
-CONFIG_SOUND_PRIME=m
-CONFIG_SOUND_OSS=m
-CONFIG_SOUND_SB=m
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_CMOS=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFSD=m
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index ea042e80e54d..ec4f6e7713c1 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -41,9 +41,11 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_KEXEC=y
CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
CONFIG_CPU_IDLE=y
CONFIG_VFP=y
+CONFIG_NEON=y
CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -129,6 +131,7 @@ CONFIG_SPI=y
CONFIG_SPI_TEGRA114=y
CONFIG_SPI_TEGRA20_SFLASH=y
CONFIG_SPI_TEGRA20_SLINK=y
+CONFIG_PINCTRL_PALMAS=y
CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_GPIO_PALMAS=y
CONFIG_GPIO_TPS6586X=y
@@ -223,6 +226,7 @@ CONFIG_KEYBOARD_NVEC=y
CONFIG_SERIO_NVEC_PS2=y
CONFIG_NVEC_POWER=y
CONFIG_NVEC_PAZ00=y
+CONFIG_COMMON_CLK_DEBUG=y
CONFIG_TEGRA_IOMMU_GART=y
CONFIG_TEGRA_IOMMU_SMMU=y
CONFIG_MEMORY=y
diff --git a/arch/arm/crypto/aes-armv4.S b/arch/arm/crypto/aes-armv4.S
index 19d6cd6f29f9..3a14ea8fe97e 100644
--- a/arch/arm/crypto/aes-armv4.S
+++ b/arch/arm/crypto/aes-armv4.S
@@ -148,7 +148,7 @@ AES_Te:
@ const AES_KEY *key) {
.align 5
ENTRY(AES_encrypt)
- sub r3,pc,#8 @ AES_encrypt
+ adr r3,AES_encrypt
stmdb sp!,{r1,r4-r12,lr}
mov r12,r0 @ inp
mov r11,r2
@@ -381,7 +381,7 @@ _armv4_AES_encrypt:
.align 5
ENTRY(private_AES_set_encrypt_key)
_armv4_AES_set_encrypt_key:
- sub r3,pc,#8 @ AES_set_encrypt_key
+ adr r3,_armv4_AES_set_encrypt_key
teq r0,#0
moveq r0,#-1
beq .Labrt
@@ -843,7 +843,7 @@ AES_Td:
@ const AES_KEY *key) {
.align 5
ENTRY(AES_decrypt)
- sub r3,pc,#8 @ AES_decrypt
+ adr r3,AES_decrypt
stmdb sp!,{r1,r4-r12,lr}
mov r12,r0 @ inp
mov r11,r2
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index d3db39860b9c..4e6838d4ddf6 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -33,3 +33,4 @@ generic-y += timex.h
generic-y += trace_clock.h
generic-y += types.h
generic-y += unaligned.h
+generic-y += preempt.h
diff --git a/arch/arm/include/asm/bL_switcher.h b/arch/arm/include/asm/bL_switcher.h
new file mode 100644
index 000000000000..e0c0bba70bbf
--- /dev/null
+++ b/arch/arm/include/asm/bL_switcher.h
@@ -0,0 +1,17 @@
+/*
+ * arch/arm/include/asm/bL_switcher.h
+ *
+ * Created by: Nicolas Pitre, April 2012
+ * Copyright: (C) 2012-2013 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef ASM_BL_SWITCHER_H
+#define ASM_BL_SWITCHER_H
+
+int bL_switch_request(unsigned int cpu, unsigned int new_cluster_id);
+
+#endif
diff --git a/arch/arm/include/asm/hardware/iop3xx-gpio.h b/arch/arm/include/asm/hardware/iop3xx-gpio.h
deleted file mode 100644
index 9eda7dc92ad8..000000000000
--- a/arch/arm/include/asm/hardware/iop3xx-gpio.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * arch/arm/include/asm/hardware/iop3xx-gpio.h
- *
- * IOP3xx GPIO wrappers
- *
- * Copyright (c) 2008 Arnaud Patard <arnaud.patard@rtp-net.org>
- * Based on IXP4XX gpio.h file
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#ifndef __ASM_ARM_HARDWARE_IOP3XX_GPIO_H
-#define __ASM_ARM_HARDWARE_IOP3XX_GPIO_H
-
-#include <mach/hardware.h>
-#include <asm-generic/gpio.h>
-
-#define __ARM_GPIOLIB_COMPLEX
-
-#define IOP3XX_N_GPIOS 8
-
-static inline int gpio_get_value(unsigned gpio)
-{
- if (gpio > IOP3XX_N_GPIOS)
- return __gpio_get_value(gpio);
-
- return gpio_line_get(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
- if (gpio > IOP3XX_N_GPIOS) {
- __gpio_set_value(gpio, value);
- return;
- }
- gpio_line_set(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned gpio)
-{
- if (gpio < IOP3XX_N_GPIOS)
- return 0;
- else
- return __gpio_cansleep(gpio);
-}
-
-/*
- * The GPIOs are not generating any interrupt
- * Note : manuals are not clear about this
- */
-static inline int gpio_to_irq(int gpio)
-{
- return -EINVAL;
-}
-
-static inline int irq_to_gpio(int gpio)
-{
- return -EINVAL;
-}
-
-#endif
-
diff --git a/arch/arm/include/asm/hardware/iop3xx.h b/arch/arm/include/asm/hardware/iop3xx.h
index 423744bf18eb..2594a95ff19a 100644
--- a/arch/arm/include/asm/hardware/iop3xx.h
+++ b/arch/arm/include/asm/hardware/iop3xx.h
@@ -18,16 +18,9 @@
/*
* IOP3XX GPIO handling
*/
-#define GPIO_IN 0
-#define GPIO_OUT 1
-#define GPIO_LOW 0
-#define GPIO_HIGH 1
#define IOP3XX_GPIO_LINE(x) (x)
#ifndef __ASSEMBLY__
-extern void gpio_line_config(int line, int direction);
-extern int gpio_line_get(int line);
-extern void gpio_line_set(int line, int value);
extern int init_atu;
extern int iop3xx_get_init_atu(void);
#endif
@@ -168,11 +161,6 @@ extern int iop3xx_get_init_atu(void);
/* PERCR0 DOESN'T EXIST - index from 1! */
#define IOP3XX_PERCR0 (volatile u32 *)IOP3XX_REG_ADDR(0x0710)
-/* General Purpose I/O */
-#define IOP3XX_GPOE (volatile u32 *)IOP3XX_GPIO_REG(0x0000)
-#define IOP3XX_GPID (volatile u32 *)IOP3XX_GPIO_REG(0x0004)
-#define IOP3XX_GPOD (volatile u32 *)IOP3XX_GPIO_REG(0x0008)
-
/* Timers */
#define IOP3XX_TU_TMR0 (volatile u32 *)IOP3XX_TIMER_REG(0x0000)
#define IOP3XX_TU_TMR1 (volatile u32 *)IOP3XX_TIMER_REG(0x0004)
diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index 454d642a4070..7fc42784becb 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -106,8 +106,4 @@ extern int dc21285_setup(int nr, struct pci_sys_data *);
extern void dc21285_preinit(void);
extern void dc21285_postinit(void);
-extern struct pci_ops via82c505_ops;
-extern int via82c505_setup(int nr, struct pci_sys_data *);
-extern void via82c505_init(void *sysdata);
-
#endif /* __ASM_MACH_PCI_H */
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 7e1f76027f66..72abdc541f38 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -19,6 +19,13 @@
#include <asm/unified.h>
#include <asm/compiler.h>
+#if __LINUX_ARM_ARCH__ < 6
+#include <asm-generic/uaccess-unaligned.h>
+#else
+#define __get_user_unaligned __get_user
+#define __put_user_unaligned __put_user
+#endif
+
#define VERIFY_READ 0
#define VERIFY_WRITE 1
diff --git a/arch/arm/include/debug/vf.S b/arch/arm/include/debug/vf.S
new file mode 100644
index 000000000000..ba12cc44b2cb
--- /dev/null
+++ b/arch/arm/include/debug/vf.S
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ *
+ */
+
+ .macro addruart, rp, rv, tmp
+ ldr \rp, =0x40028000 @ physical
+ ldr \rv, =0xfe028000 @ virtual
+ .endm
+
+ .macro senduart, rd, rx
+ strb \rd, [\rx, #0x7] @ Data Register
+ .endm
+
+ .macro busyuart, rd, rx
+1001: ldrb \rd, [\rx, #0x4] @ Status Register 1
+ tst \rd, #1 << 6 @ TC
+ beq 1001b @ wait until transmit done
+ .endm
+
+ .macro waituart,rd,rx
+ .endm
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 74ad15d1a065..bc6bd9683ba4 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -442,10 +442,10 @@ local_restart:
ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
add r1, sp, #S_OFF
- cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE)
+2: cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE)
eor r0, scno, #__NR_SYSCALL_BASE @ put OS number back
bcs arm_syscall
-2: mov why, #0 @ no longer a real syscall
+ mov why, #0 @ no longer a real syscall
b sys_ni_syscall @ not private func
#if defined(CONFIG_OABI_COMPAT) || !defined(CONFIG_AEABI)
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index db1536b8b30b..622460201911 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -55,6 +55,7 @@
* specific registers and some other data for resume.
* r0 = suspend function arg0
* r1 = suspend function
+ * r2 = MPIDR value the resuming CPU will use
*/
ENTRY(__cpu_suspend)
stmfd sp!, {r4 - r11, lr}
@@ -67,23 +68,18 @@ ENTRY(__cpu_suspend)
mov r5, sp @ current virtual SP
add r4, r4, #12 @ Space for pgd, virt sp, phys resume fn
sub sp, sp, r4 @ allocate CPU state on stack
- stmfd sp!, {r0, r1} @ save suspend func arg and pointer
- add r0, sp, #8 @ save pointer to save block
- mov r1, r4 @ size of save block
- mov r2, r5 @ virtual SP
ldr r3, =sleep_save_sp
+ stmfd sp!, {r0, r1} @ save suspend func arg and pointer
ldr r3, [r3, #SLEEP_SAVE_SP_VIRT]
- ALT_SMP(mrc p15, 0, r9, c0, c0, 5)
- ALT_UP_B(1f)
- ldr r8, =mpidr_hash
- /*
- * This ldmia relies on the memory layout of the mpidr_hash
- * struct mpidr_hash.
- */
- ldmia r8, {r4-r7} @ r4 = mpidr mask (r5,r6,r7) = l[0,1,2] shifts
- compute_mpidr_hash lr, r5, r6, r7, r9, r4
- add r3, r3, lr, lsl #2
-1:
+ ALT_SMP(ldr r0, =mpidr_hash)
+ ALT_UP_B(1f)
+ /* This ldmia relies on the memory layout of the mpidr_hash struct */
+ ldmia r0, {r1, r6-r8} @ r1 = mpidr mask (r6,r7,r8) = l[0,1,2] shifts
+ compute_mpidr_hash r0, r6, r7, r8, r2, r1
+ add r3, r3, r0, lsl #2
+1: mov r2, r5 @ virtual SP
+ mov r1, r4 @ size of save block
+ add r0, sp, #8 @ pointer to save block
bl __cpu_suspend_save
adr lr, BSYM(cpu_suspend_abort)
ldmfd sp!, {r0, pc} @ call suspend fn
diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c
index 41cf3cbf756d..2835d35234ca 100644
--- a/arch/arm/kernel/suspend.c
+++ b/arch/arm/kernel/suspend.c
@@ -10,7 +10,7 @@
#include <asm/suspend.h>
#include <asm/tlbflush.h>
-extern int __cpu_suspend(unsigned long, int (*)(unsigned long));
+extern int __cpu_suspend(unsigned long, int (*)(unsigned long), u32 cpuid);
extern void cpu_resume_mmu(void);
#ifdef CONFIG_MMU
@@ -21,6 +21,7 @@ extern void cpu_resume_mmu(void);
int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
{
struct mm_struct *mm = current->active_mm;
+ u32 __mpidr = cpu_logical_map(smp_processor_id());
int ret;
if (!idmap_pgd)
@@ -32,7 +33,7 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
* resume (indicated by a zero return code), we need to switch
* back to the correct page tables.
*/
- ret = __cpu_suspend(arg, fn);
+ ret = __cpu_suspend(arg, fn, __mpidr);
if (ret == 0) {
cpu_switch_mm(mm->pgd, mm);
local_flush_bp_all();
@@ -44,7 +45,8 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
#else
int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
{
- return __cpu_suspend(arg, fn);
+ u32 __mpidr = cpu_logical_map(smp_processor_id());
+ return __cpu_suspend(arg, fn, __mpidr);
}
#define idmap_pgd NULL
#endif
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index bd454b09133e..47d7338561de 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -41,7 +41,6 @@ else
endif
lib-$(CONFIG_ARCH_RPC) += ecard.o io-acorn.o floppydma.o
-lib-$(CONFIG_ARCH_SHARK) += io-shark.o
$(obj)/csumpartialcopy.o: $(obj)/csumpartialcopygeneric.S
$(obj)/csumpartialcopyuser.o: $(obj)/csumpartialcopygeneric.S
diff --git a/arch/arm/lib/io-shark.c b/arch/arm/lib/io-shark.c
deleted file mode 100644
index 824253948f51..000000000000
--- a/arch/arm/lib/io-shark.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * linux/arch/arm/lib/io-shark.c
- *
- * by Alexander Schulz
- *
- * derived from:
- * linux/arch/arm/lib/io-ebsa.S
- * Copyright (C) 1995, 1996 Russell King
- *
- * 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.
- */
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index 180b3024bec3..f607deb40f4d 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -93,7 +93,7 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
static struct irqaction at91rm9200_timer_irq = {
.name = "at91_tick",
- .flags = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .flags = IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
.handler = at91rm9200_timer_interrupt,
.irq = NR_IRQS_LEGACY + AT91_ID_SYS,
};
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 629ea5fc95cf..b2a34740146a 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -465,7 +465,7 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
static u64 lcdc_dmamask = DMA_BIT_MASK(32);
-static struct atmel_lcdfb_info lcdc_data;
+static struct atmel_lcdfb_pdata lcdc_data;
static struct resource lcdc_resources[] = {
[0] = {
@@ -498,7 +498,7 @@ static struct platform_device at91_lcdc_device = {
.num_resources = ARRAY_SIZE(lcdc_resources),
};
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
+void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data)
{
if (!data) {
return;
@@ -559,7 +559,7 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
platform_device_register(&at91_lcdc_device);
}
#else
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
+void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) {}
#endif
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 858c8aac2daf..4aeadddbc181 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -832,7 +832,7 @@ void __init at91_add_device_can(struct at91_can_data *data) {}
#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
static u64 lcdc_dmamask = DMA_BIT_MASK(32);
-static struct atmel_lcdfb_info lcdc_data;
+static struct atmel_lcdfb_pdata lcdc_data;
static struct resource lcdc_resources[] = {
[0] = {
@@ -859,7 +859,7 @@ static struct platform_device at91_lcdc_device = {
.num_resources = ARRAY_SIZE(lcdc_resources),
};
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
+void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data)
{
if (!data)
return;
@@ -891,7 +891,7 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
platform_device_register(&at91_lcdc_device);
}
#else
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
+void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) {}
#endif
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
index 3a4bc2e1a65e..bb392320a0dd 100644
--- a/arch/arm/mach-at91/at91sam926x_time.c
+++ b/arch/arm/mach-at91/at91sam926x_time.c
@@ -171,7 +171,7 @@ static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
static struct irqaction at91sam926x_pit_irq = {
.name = "at91_tick",
- .flags = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .flags = IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
.handler = at91sam926x_pit_interrupt,
.irq = NR_IRQS_LEGACY + AT91_ID_SYS,
};
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index acb703e13331..cb36fa872d30 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -965,7 +965,7 @@ void __init at91_add_device_isi(struct isi_platform_data *data,
#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
static u64 lcdc_dmamask = DMA_BIT_MASK(32);
-static struct atmel_lcdfb_info lcdc_data;
+static struct atmel_lcdfb_pdata lcdc_data;
static struct resource lcdc_resources[] = {
[0] = {
@@ -991,7 +991,7 @@ static struct platform_device at91_lcdc_device = {
.num_resources = ARRAY_SIZE(lcdc_resources),
};
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
+void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data)
{
if (!data)
return;
@@ -1037,7 +1037,7 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
platform_device_register(&at91_lcdc_device);
}
#else
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
+void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) {}
#endif
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 352468f265a9..a698bdab2cce 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -498,7 +498,7 @@ void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
static u64 lcdc_dmamask = DMA_BIT_MASK(32);
-static struct atmel_lcdfb_info lcdc_data;
+static struct atmel_lcdfb_pdata lcdc_data;
static struct resource lcdc_resources[] = {
[0] = {
@@ -525,7 +525,7 @@ static struct platform_device at91_lcdc_device = {
.num_resources = ARRAY_SIZE(lcdc_resources),
};
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
+void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data)
{
if (!data) {
return;
@@ -557,7 +557,7 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
platform_device_register(&at91_lcdc_device);
}
#else
-void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
+void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data) {}
#endif
diff --git a/arch/arm/mach-at91/at91x40_time.c b/arch/arm/mach-at91/at91x40_time.c
index 2919eba41ff4..c0e637adf65d 100644
--- a/arch/arm/mach-at91/at91x40_time.c
+++ b/arch/arm/mach-at91/at91x40_time.c
@@ -57,7 +57,7 @@ static irqreturn_t at91x40_timer_interrupt(int irq, void *dev_id)
static struct irqaction at91x40_timer_irq = {
.name = "at91_tick",
- .flags = IRQF_DISABLED | IRQF_TIMER,
+ .flags = IRQF_TIMER,
.handler = at91x40_timer_interrupt
};
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index d3437624ca4e..473546b9408b 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -389,7 +389,7 @@ static struct fb_monspecs at91fb_default_stn_monspecs = {
| ATMEL_LCDC_IFWIDTH_4 \
| ATMEL_LCDC_SCANMOD_SINGLE)
-static void at91_lcdc_stn_power_control(int on)
+static void at91_lcdc_stn_power_control(struct atmel_lcdfb_pdata *pdata, int on)
{
/* backlight */
if (on) { /* power up */
@@ -401,7 +401,7 @@ static void at91_lcdc_stn_power_control(int on)
}
}
-static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = {
.default_bpp = 1,
.default_dmacon = ATMEL_LCDC_DMAEN,
.default_lcdcon2 = AT91SAM9261_DEFAULT_STN_LCDCON2,
@@ -445,7 +445,7 @@ static struct fb_monspecs at91fb_default_tft_monspecs = {
| ATMEL_LCDC_DISTYPE_TFT \
| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
-static void at91_lcdc_tft_power_control(int on)
+static void at91_lcdc_tft_power_control(struct atmel_lcdfb_pdata *pdata, int on)
{
if (on)
at91_set_gpio_value(AT91_PIN_PA12, 0); /* power up */
@@ -453,7 +453,7 @@ static void at91_lcdc_tft_power_control(int on)
at91_set_gpio_value(AT91_PIN_PA12, 1); /* power down */
}
-static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = {
.lcdcon_is_backlight = true,
.default_bpp = 16,
.default_dmacon = ATMEL_LCDC_DMAEN,
@@ -465,7 +465,7 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
#endif
#else
-static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data;
#endif
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index 3284df05df14..8b4942cbb6d9 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -275,13 +275,13 @@ static struct fb_monspecs at91fb_default_monspecs = {
| ATMEL_LCDC_DISTYPE_TFT \
| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
-static void at91_lcdc_power_control(int on)
+static void at91_lcdc_power_control(struct atmel_lcdfb_pdata *pdata, int on)
{
at91_set_gpio_value(AT91_PIN_PA30, on);
}
/* Driver datas */
-static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = {
.lcdcon_is_backlight = true,
.default_bpp = 16,
.default_dmacon = ATMEL_LCDC_DMAEN,
@@ -292,7 +292,7 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
};
#else
-static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data;
#endif
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index 2a94896a1375..ef39078c8ce2 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -284,7 +284,7 @@ static struct fb_monspecs at91fb_default_monspecs = {
| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
/* Driver datas */
-static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = {
.lcdcon_is_backlight = true,
.default_bpp = 32,
.default_dmacon = ATMEL_LCDC_DMAEN,
@@ -295,7 +295,7 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
};
#else
-static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data;
#endif
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index aa265dcf2128..604eecf6cd70 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -170,7 +170,7 @@ static struct fb_monspecs at91fb_default_monspecs = {
| ATMEL_LCDC_DISTYPE_TFT \
| ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
-static void at91_lcdc_power_control(int on)
+static void at91_lcdc_power_control(struct atmel_lcdfb_pdata *pdata, int on)
{
if (on)
at91_set_gpio_value(AT91_PIN_PC1, 0); /* power up */
@@ -179,7 +179,7 @@ static void at91_lcdc_power_control(int on)
}
/* Driver datas */
-static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data = {
.lcdcon_is_backlight = true,
.default_bpp = 16,
.default_dmacon = ATMEL_LCDC_DMAEN,
@@ -191,7 +191,7 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
};
#else
-static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+static struct atmel_lcdfb_pdata __initdata ek_lcdc_data;
#endif
diff --git a/arch/arm/mach-at91/board.h b/arch/arm/mach-at91/board.h
index 4a234fb2ab3b..6c08b341167d 100644
--- a/arch/arm/mach-at91/board.h
+++ b/arch/arm/mach-at91/board.h
@@ -107,8 +107,8 @@ extern void __init at91_add_device_pwm(u32 mask);
extern void __init at91_add_device_ssc(unsigned id, unsigned pins);
/* LCD Controller */
-struct atmel_lcdfb_info;
-extern void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data);
+struct atmel_lcdfb_pdata;
+extern void __init at91_add_device_lcdc(struct atmel_lcdfb_pdata *data);
/* AC97 */
extern void __init at91_add_device_ac97(struct ac97c_platform_data *data);
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index 92b7f770615a..4078ba93776b 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -176,7 +176,7 @@ static struct at24_platform_data eeprom_info = {
.context = (void *)0x7f00,
};
-static struct snd_platform_data dm365_evm_snd_data = {
+static struct snd_platform_data dm365_evm_snd_data __maybe_unused = {
.asp_chan_q = EVENTQ_3,
};
diff --git a/arch/arm/mach-davinci/include/mach/serial.h b/arch/arm/mach-davinci/include/mach/serial.h
index 52b8571b2e70..ce402cd21fa0 100644
--- a/arch/arm/mach-davinci/include/mach/serial.h
+++ b/arch/arm/mach-davinci/include/mach/serial.h
@@ -15,8 +15,6 @@
#include <mach/hardware.h>
-#include <linux/platform_device.h>
-
#define DAVINCI_UART0_BASE (IO_PHYS + 0x20000)
#define DAVINCI_UART1_BASE (IO_PHYS + 0x20400)
#define DAVINCI_UART2_BASE (IO_PHYS + 0x20800)
@@ -39,6 +37,8 @@
#define UART_DM646X_SCR_TX_WATERMARK 0x08
#ifndef __ASSEMBLY__
+#include <linux/platform_device.h>
+
extern int davinci_serial_init(struct platform_device *);
#endif
diff --git a/arch/arm/mach-dove/board-dt.c b/arch/arm/mach-dove/board-dt.c
index 49f72a848423..9a116d796323 100644
--- a/arch/arm/mach-dove/board-dt.c
+++ b/arch/arm/mach-dove/board-dt.c
@@ -23,41 +23,12 @@
#include <plat/irq.h>
#include "common.h"
-/*
- * There are still devices that doesn't even know about DT,
- * get clock gates here and add a clock lookup.
- */
-static void __init dove_legacy_clk_init(void)
-{
- struct device_node *np = of_find_compatible_node(NULL, NULL,
- "marvell,dove-gating-clock");
- struct of_phandle_args clkspec;
-
- clkspec.np = np;
- clkspec.args_count = 1;
-
- clkspec.args[0] = CLOCK_GATING_BIT_PCIE0;
- orion_clkdev_add("0", "pcie",
- of_clk_get_from_provider(&clkspec));
-
- clkspec.args[0] = CLOCK_GATING_BIT_PCIE1;
- orion_clkdev_add("1", "pcie",
- of_clk_get_from_provider(&clkspec));
-}
-
static void __init dove_dt_time_init(void)
{
of_clk_init(NULL);
clocksource_of_init();
}
-static void __init dove_dt_init_early(void)
-{
- mvebu_mbus_init("marvell,dove-mbus",
- BRIDGE_WINS_BASE, BRIDGE_WINS_SZ,
- DOVE_MC_WINS_BASE, DOVE_MC_WINS_SZ);
-}
-
static void __init dove_dt_init(void)
{
pr_info("Dove 88AP510 SoC\n");
@@ -65,14 +36,7 @@ static void __init dove_dt_init(void)
#ifdef CONFIG_CACHE_TAUROS2
tauros2_init(0);
#endif
- dove_setup_cpu_wins();
-
- /* Setup clocks for legacy devices */
- dove_legacy_clk_init();
-
- /* Internal devices not ported to DT yet */
- dove_pcie_init(1, 1);
-
+ BUG_ON(mvebu_mbus_dt_init());
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
@@ -83,7 +47,6 @@ static const char * const dove_dt_board_compat[] = {
DT_MACHINE_START(DOVE_DT, "Marvell Dove (Flattened Device Tree)")
.map_io = dove_map_io,
- .init_early = dove_dt_init_early,
.init_time = dove_dt_time_init,
.init_machine = dove_dt_init,
.restart = dove_restart,
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
index 93e54fd4e3d5..bec570ae6494 100644
--- a/arch/arm/mach-ep93xx/Kconfig
+++ b/arch/arm/mach-ep93xx/Kconfig
@@ -5,6 +5,7 @@ menu "Cirrus EP93xx Implementation Options"
config EP93XX_SOC_COMMON
bool
default y
+ select SOC_BUS
select LEDS_GPIO_REGISTER
config CRUNCH
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 3f12b885c083..4c0a1fccefd9 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -21,6 +21,7 @@
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
+#include <linux/sys_soc.h>
#include <linux/timex.h>
#include <linux/irq.h>
#include <linux/io.h>
@@ -43,6 +44,7 @@
#include <linux/platform_data/spi-ep93xx.h>
#include <mach/gpio-ep93xx.h>
+#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>
@@ -896,8 +898,108 @@ void ep93xx_ide_release_gpio(struct platform_device *pdev)
}
EXPORT_SYMBOL(ep93xx_ide_release_gpio);
-void __init ep93xx_init_devices(void)
+/*************************************************************************
+ * EP93xx Security peripheral
+ *************************************************************************/
+
+/*
+ * The Maverick Key is 256 bits of micro fuses blown at the factory during
+ * manufacturing to uniquely identify a part.
+ *
+ * See: http://arm.cirrus.com/forum/viewtopic.php?t=486&highlight=maverick+key
+ */
+#define EP93XX_SECURITY_REG(x) (EP93XX_SECURITY_BASE + (x))
+#define EP93XX_SECURITY_SECFLG EP93XX_SECURITY_REG(0x2400)
+#define EP93XX_SECURITY_FUSEFLG EP93XX_SECURITY_REG(0x2410)
+#define EP93XX_SECURITY_UNIQID EP93XX_SECURITY_REG(0x2440)
+#define EP93XX_SECURITY_UNIQCHK EP93XX_SECURITY_REG(0x2450)
+#define EP93XX_SECURITY_UNIQVAL EP93XX_SECURITY_REG(0x2460)
+#define EP93XX_SECURITY_SECID1 EP93XX_SECURITY_REG(0x2500)
+#define EP93XX_SECURITY_SECID2 EP93XX_SECURITY_REG(0x2504)
+#define EP93XX_SECURITY_SECCHK1 EP93XX_SECURITY_REG(0x2520)
+#define EP93XX_SECURITY_SECCHK2 EP93XX_SECURITY_REG(0x2524)
+#define EP93XX_SECURITY_UNIQID2 EP93XX_SECURITY_REG(0x2700)
+#define EP93XX_SECURITY_UNIQID3 EP93XX_SECURITY_REG(0x2704)
+#define EP93XX_SECURITY_UNIQID4 EP93XX_SECURITY_REG(0x2708)
+#define EP93XX_SECURITY_UNIQID5 EP93XX_SECURITY_REG(0x270c)
+
+static char ep93xx_soc_id[33];
+
+static const char __init *ep93xx_get_soc_id(void)
{
+ unsigned int id, id2, id3, id4, id5;
+
+ if (__raw_readl(EP93XX_SECURITY_UNIQVAL) != 1)
+ return "bad Hamming code";
+
+ id = __raw_readl(EP93XX_SECURITY_UNIQID);
+ id2 = __raw_readl(EP93XX_SECURITY_UNIQID2);
+ id3 = __raw_readl(EP93XX_SECURITY_UNIQID3);
+ id4 = __raw_readl(EP93XX_SECURITY_UNIQID4);
+ id5 = __raw_readl(EP93XX_SECURITY_UNIQID5);
+
+ if (id != id2)
+ return "invalid";
+
+ snprintf(ep93xx_soc_id, sizeof(ep93xx_soc_id),
+ "%08x%08x%08x%08x", id2, id3, id4, id5);
+
+ return ep93xx_soc_id;
+}
+
+static const char __init *ep93xx_get_soc_rev(void)
+{
+ int rev = ep93xx_chip_revision();
+
+ switch (rev) {
+ case EP93XX_CHIP_REV_D0:
+ return "D0";
+ case EP93XX_CHIP_REV_D1:
+ return "D1";
+ case EP93XX_CHIP_REV_E0:
+ return "E0";
+ case EP93XX_CHIP_REV_E1:
+ return "E1";
+ case EP93XX_CHIP_REV_E2:
+ return "E2";
+ default:
+ return "unknown";
+ }
+}
+
+static const char __init *ep93xx_get_machine_name(void)
+{
+ return kasprintf(GFP_KERNEL,"%s", machine_desc->name);
+}
+
+static struct device __init *ep93xx_init_soc(void)
+{
+ struct soc_device_attribute *soc_dev_attr;
+ struct soc_device *soc_dev;
+
+ soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+ if (!soc_dev_attr)
+ return NULL;
+
+ soc_dev_attr->machine = ep93xx_get_machine_name();
+ soc_dev_attr->family = "Cirrus Logic EP93xx";
+ soc_dev_attr->revision = ep93xx_get_soc_rev();
+ soc_dev_attr->soc_id = ep93xx_get_soc_id();
+
+ soc_dev = soc_device_register(soc_dev_attr);
+ if (IS_ERR(soc_dev)) {
+ kfree(soc_dev_attr->machine);
+ kfree(soc_dev_attr);
+ return NULL;
+ }
+
+ return soc_device_to_device(soc_dev);
+}
+
+struct device __init *ep93xx_init_devices(void)
+{
+ struct device *parent;
+
/* Disallow access to MaverickCrunch initially */
ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA);
@@ -908,6 +1010,8 @@ void __init ep93xx_init_devices(void)
EP93XX_SYSCON_DEVCFG_GONIDE |
EP93XX_SYSCON_DEVCFG_HONIDE);
+ parent = ep93xx_init_soc();
+
/* Get the GPIO working early, other devices need it */
platform_device_register(&ep93xx_gpio_device);
@@ -920,6 +1024,8 @@ void __init ep93xx_init_devices(void)
platform_device_register(&ep93xx_wdt_device);
gpio_led_register_device(-1, &ep93xx_led_data);
+
+ return parent;
}
void ep93xx_restart(enum reboot_mode mode, const char *cmd)
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
index e256e0baec2e..4c0bbd97f741 100644
--- a/arch/arm/mach-ep93xx/include/mach/platform.h
+++ b/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -6,6 +6,7 @@
#include <linux/reboot.h>
+struct device;
struct i2c_gpio_platform_data;
struct i2c_board_info;
struct spi_board_info;
@@ -54,7 +55,7 @@ void ep93xx_register_ide(void);
int ep93xx_ide_acquire_gpio(struct platform_device *pdev);
void ep93xx_ide_release_gpio(struct platform_device *pdev);
-void ep93xx_init_devices(void);
+struct device *ep93xx_init_devices(void);
extern void ep93xx_timer_init(void);
void ep93xx_restart(enum reboot_mode, const char *);
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index ba95e5db2501..c17407b16d7c 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -30,6 +30,7 @@
#include <linux/clk-provider.h>
#include <linux/irqchip/arm-gic.h>
#include <linux/irqchip/chained_irq.h>
+#include <linux/platform_device.h>
#include <asm/proc-fns.h>
#include <asm/exception.h>
@@ -294,6 +295,16 @@ void exynos5_restart(enum reboot_mode mode, const char *cmd)
__raw_writel(val, addr);
}
+static struct platform_device exynos_cpuidle = {
+ .name = "exynos_cpuidle",
+ .id = -1,
+};
+
+void __init exynos_cpuidle_init(void)
+{
+ platform_device_register(&exynos_cpuidle);
+}
+
void __init exynos_init_late(void)
{
if (of_machine_is_compatible("samsung,exynos5440"))
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 8646a141ae46..b2ac1885d381 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -22,6 +22,7 @@ struct map_desc;
void exynos_init_io(void);
void exynos4_restart(enum reboot_mode mode, const char *cmd);
void exynos5_restart(enum reboot_mode mode, const char *cmd);
+void exynos_cpuidle_init(void);
void exynos_init_late(void);
void exynos_firmware_init(void);
diff --git a/arch/arm/mach-exynos/cpuidle.c b/arch/arm/mach-exynos/cpuidle.c
index ac139226d63c..1bde6ad07d93 100644
--- a/arch/arm/mach-exynos/cpuidle.c
+++ b/arch/arm/mach-exynos/cpuidle.c
@@ -15,6 +15,7 @@
#include <linux/io.h>
#include <linux/export.h>
#include <linux/time.h>
+#include <linux/platform_device.h>
#include <asm/proc-fns.h>
#include <asm/smp_scu.h>
@@ -192,7 +193,7 @@ static void __init exynos5_core_down_clk(void)
__raw_writel(tmp, EXYNOS5_PWR_CTRL2);
}
-static int __init exynos4_init_cpuidle(void)
+static int __init exynos_cpuidle_probe(struct platform_device *pdev)
{
int cpu_id, ret;
struct cpuidle_device *device;
@@ -226,4 +227,13 @@ static int __init exynos4_init_cpuidle(void)
return 0;
}
-device_initcall(exynos4_init_cpuidle);
+
+static struct platform_driver exynos_cpuidle_driver = {
+ .probe = exynos_cpuidle_probe,
+ .driver = {
+ .name = "exynos_cpuidle",
+ .owner = THIS_MODULE,
+ },
+};
+
+module_platform_driver(exynos_cpuidle_driver);
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index 0099c6c13bba..53a3dc37a730 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -25,6 +25,8 @@
static void __init exynos4_dt_machine_init(void)
{
+ exynos_cpuidle_init();
+
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c
index f874b773ca13..c9f7dd1cdc8f 100644
--- a/arch/arm/mach-exynos/mach-exynos5-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos5-dt.c
@@ -47,6 +47,8 @@ static void __init exynos5_dt_machine_init(void)
}
}
+ exynos_cpuidle_init();
+
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 29a8af6922a8..9f67338ac2ee 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -24,7 +24,7 @@ config MXC_IRQ_PRIOR
help
Select this if you want to use prioritized IRQ handling.
This feature prevents higher priority ISR to be interrupted
- by lower priority IRQ even IRQF_DISABLED flag is not set.
+ by lower priority IRQ.
This may be useful in embedded applications, where are strong
requirements for timing.
Say N here, unless you have a specialized requirement.
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 9181a241d3a8..913ad85ad621 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -182,7 +182,7 @@ static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "pll2_bus", };
static const char *periph_sels[] = { "periph_pre", "periph_clk2", };
static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", };
static const char *axi_sels[] = { "periph", "pll2_pfd2_396m", "periph", "pll3_pfd1_540m", };
-static const char *audio_sels[] = { "pll4_post_div", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", };
+static const char *audio_sels[] = { "pll4_audio_div", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", };
static const char *gpu_axi_sels[] = { "axi", "ahb", };
static const char *gpu2d_core_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", };
static const char *gpu3d_core_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", };
@@ -196,7 +196,7 @@ static const char *ipu2_di0_sels[] = { "ipu2_di0_pre", "dummy", "dummy", "ldb_di
static const char *ipu2_di1_sels[] = { "ipu2_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
static const char *hsi_tx_sels[] = { "pll3_120m", "pll2_pfd2_396m", };
static const char *pcie_axi_sels[] = { "axi", "ahb", };
-static const char *ssi_sels[] = { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_post_div", };
+static const char *ssi_sels[] = { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_audio_div", };
static const char *usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
static const char *enfc_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", };
static const char *emi_sels[] = { "pll2_pfd2_396m", "pll3_usb_otg", "axi", "pll2_pfd0_352m", };
@@ -205,7 +205,7 @@ static const char *vdo_axi_sels[] = { "axi", "ahb", };
static const char *vpu_axi_sels[] = { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m", };
static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div",
"dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0",
- "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_post_div", };
+ "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_audio_div", };
static const char *cko2_sels[] = {
"mmdc_ch0_axi", "mmdc_ch1_axi", "usdhc4", "usdhc1",
"gpu2d_axi", "dummy", "ecspi_root", "gpu3d_axi",
@@ -251,7 +251,7 @@ enum mx6q_clks {
ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5,
sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate,
usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow,
- spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, clk_max
+ spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, pll4_audio_div, clk_max
};
static struct clk *clk[clk_max];
@@ -359,6 +359,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[twd] = imx_clk_fixed_factor("twd", "arm", 1, 2);
clk[pll4_post_div] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
+ clk[pll4_audio_div] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
clk[pll5_post_div] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
clk[pll5_video_div] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
diff --git a/arch/arm/mach-imx/epit.c b/arch/arm/mach-imx/epit.c
index e02de188ae83..074b1a81ba76 100644
--- a/arch/arm/mach-imx/epit.c
+++ b/arch/arm/mach-imx/epit.c
@@ -171,7 +171,7 @@ static irqreturn_t epit_timer_interrupt(int irq, void *dev_id)
static struct irqaction epit_timer_irq = {
.name = "i.MX EPIT Timer Tick",
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .flags = IRQF_TIMER | IRQF_IRQPOLL,
.handler = epit_timer_interrupt,
};
diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c
index 368a6e3f5926..58b864a3fc20 100644
--- a/arch/arm/mach-imx/mach-armadillo5x0.c
+++ b/arch/arm/mach-imx/mach-armadillo5x0.c
@@ -404,8 +404,7 @@ static int armadillo5x0_sdhc1_init(struct device *dev,
/* When supported the trigger type have to be BOTH */
ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK)),
- detect_irq,
- IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+ detect_irq, IRQF_TRIGGER_FALLING,
"sdhc-detect", data);
if (ret)
diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
index 0d75dc54f715..892b6298dda2 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -11,16 +11,37 @@
#include <linux/irqchip.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/regmap.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include "common.h"
+static void __init imx6sl_fec_init(void)
+{
+ struct regmap *gpr;
+
+ /* set FEC clock from internal PLL clock source */
+ gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sl-iomuxc-gpr");
+ if (!IS_ERR(gpr)) {
+ regmap_update_bits(gpr, IOMUXC_GPR1,
+ IMX6SL_GPR1_FEC_CLOCK_MUX2_SEL_MASK, 0);
+ regmap_update_bits(gpr, IOMUXC_GPR1,
+ IMX6SL_GPR1_FEC_CLOCK_MUX1_SEL_MASK, 0);
+ } else {
+ pr_err("failed to find fsl,imx6sl-iomux-gpr regmap\n");
+ }
+}
+
static void __init imx6sl_init_machine(void)
{
mxc_arch_reset_init_dt();
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+ imx6sl_fec_init();
}
static void __init imx6sl_init_irq(void)
diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c
index 1ed916175d41..50044a21b388 100644
--- a/arch/arm/mach-imx/mach-mx31_3ds.c
+++ b/arch/arm/mach-imx/mach-mx31_3ds.c
@@ -311,7 +311,7 @@ static int mx31_3ds_sdhc1_init(struct device *dev,
}
ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)),
- detect_irq, IRQF_DISABLED |
+ detect_irq,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
"sdhc1-detect", data);
if (ret) {
diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c
index bc0261e99d39..45303bd62902 100644
--- a/arch/arm/mach-imx/mach-pcm037.c
+++ b/arch/arm/mach-imx/mach-pcm037.c
@@ -371,8 +371,7 @@ static int pcm970_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
#endif
ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_SCK6)), detect_irq,
- IRQF_DISABLED | IRQF_TRIGGER_FALLING,
- "sdhc-detect", data);
+ IRQF_TRIGGER_FALLING, "sdhc-detect", data);
if (ret)
goto err_gpio_free_2;
diff --git a/arch/arm/mach-imx/mx31lilly-db.c b/arch/arm/mach-imx/mx31lilly-db.c
index d4361b80c5fb..649fe49ce85e 100644
--- a/arch/arm/mach-imx/mx31lilly-db.c
+++ b/arch/arm/mach-imx/mx31lilly-db.c
@@ -130,8 +130,7 @@ static int mxc_mmc1_init(struct device *dev,
gpio_direction_input(gpio_wp);
ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)),
- detect_irq,
- IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+ detect_irq, IRQF_TRIGGER_FALLING,
"MMC detect", data);
if (ret)
goto exit_free_wp;
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index cd46529e9eaa..9b6638aadeaa 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -250,7 +250,7 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
static struct irqaction mxc_timer_irq = {
.name = "i.MX Timer Tick",
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .flags = IRQF_TIMER | IRQF_IRQPOLL,
.handler = mxc_timer_interrupt,
};
diff --git a/arch/arm/mach-integrator/pci_v3.h b/arch/arm/mach-integrator/pci_v3.h
index 755fd29fed4a..06a9e2e7d007 100644
--- a/arch/arm/mach-integrator/pci_v3.h
+++ b/arch/arm/mach-integrator/pci_v3.h
@@ -1,2 +1,9 @@
/* Simple oneliner include to the PCIv3 early init */
+#ifdef CONFIG_PCI
extern int pci_v3_early_init(void);
+#else
+static inline int pci_v3_early_init(void)
+{
+ return 0;
+}
+#endif
diff --git a/arch/arm/mach-iop32x/em7210.c b/arch/arm/mach-iop32x/em7210.c
index 31fbb6c61b25..177cd073a83b 100644
--- a/arch/arm/mach-iop32x/em7210.c
+++ b/arch/arm/mach-iop32x/em7210.c
@@ -32,6 +32,7 @@
#include <asm/mach/time.h>
#include <asm/mach-types.h>
#include <mach/time.h>
+#include "gpio-iop32x.h"
static void __init em7210_timer_init(void)
{
@@ -183,6 +184,7 @@ void em7210_power_off(void)
static void __init em7210_init_machine(void)
{
+ register_iop32x_gpio();
platform_device_register(&em7210_serial_device);
platform_device_register(&iop3xx_i2c0_device);
platform_device_register(&iop3xx_i2c1_device);
diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c
index ac304705fe68..547b2342d61a 100644
--- a/arch/arm/mach-iop32x/glantank.c
+++ b/arch/arm/mach-iop32x/glantank.c
@@ -34,6 +34,7 @@
#include <asm/mach-types.h>
#include <asm/page.h>
#include <mach/time.h>
+#include "gpio-iop32x.h"
/*
* GLAN Tank timer tick configuration.
@@ -187,6 +188,7 @@ static void glantank_power_off(void)
static void __init glantank_init_machine(void)
{
+ register_iop32x_gpio();
platform_device_register(&iop3xx_i2c0_device);
platform_device_register(&iop3xx_i2c1_device);
platform_device_register(&glantank_flash_device);
diff --git a/arch/arm/mach-iop32x/gpio-iop32x.h b/arch/arm/mach-iop32x/gpio-iop32x.h
new file mode 100644
index 000000000000..3c7309c02029
--- /dev/null
+++ b/arch/arm/mach-iop32x/gpio-iop32x.h
@@ -0,0 +1,10 @@
+static struct resource iop32x_gpio_res[] = {
+ DEFINE_RES_MEM((IOP3XX_PERIPHERAL_PHYS_BASE + 0x07c4), 0x10),
+};
+
+static inline void register_iop32x_gpio(void)
+{
+ platform_device_register_simple("gpio-iop", 0,
+ iop32x_gpio_res,
+ ARRAY_SIZE(iop32x_gpio_res));
+}
diff --git a/arch/arm/mach-iop32x/include/mach/gpio.h b/arch/arm/mach-iop32x/include/mach/gpio.h
deleted file mode 100644
index 708f4ec9db1d..000000000000
--- a/arch/arm/mach-iop32x/include/mach/gpio.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_ARCH_IOP32X_GPIO_H
-#define __ASM_ARCH_IOP32X_GPIO_H
-
-#include <asm/hardware/iop3xx-gpio.h>
-
-#endif
diff --git a/arch/arm/mach-iop32x/include/mach/iop32x.h b/arch/arm/mach-iop32x/include/mach/iop32x.h
index 941f363aca56..56ec864ec313 100644
--- a/arch/arm/mach-iop32x/include/mach/iop32x.h
+++ b/arch/arm/mach-iop32x/include/mach/iop32x.h
@@ -19,7 +19,6 @@
* Peripherals that are shared between the iop32x and iop33x but
* located at different addresses.
*/
-#define IOP3XX_GPIO_REG(reg) (IOP3XX_PERIPHERAL_VIRT_BASE + 0x07c4 + (reg))
#define IOP3XX_TIMER_REG(reg) (IOP3XX_PERIPHERAL_VIRT_BASE + 0x07e0 + (reg))
#include <asm/hardware/iop3xx.h>
diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
index f2cd2966212d..0e1392b20d18 100644
--- a/arch/arm/mach-iop32x/iq31244.c
+++ b/arch/arm/mach-iop32x/iq31244.c
@@ -37,6 +37,7 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <mach/time.h>
+#include "gpio-iop32x.h"
/*
* Until March of 2007 iq31244 platforms and ep80219 platforms shared the
@@ -283,6 +284,7 @@ void ep80219_power_off(void)
static void __init iq31244_init_machine(void)
{
+ register_iop32x_gpio();
platform_device_register(&iop3xx_i2c0_device);
platform_device_register(&iop3xx_i2c1_device);
platform_device_register(&iq31244_flash_device);
diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c
index 015435de90dd..66782ff1f46a 100644
--- a/arch/arm/mach-iop32x/iq80321.c
+++ b/arch/arm/mach-iop32x/iq80321.c
@@ -33,6 +33,7 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <mach/time.h>
+#include "gpio-iop32x.h"
/*
* IQ80321 timer tick configuration.
@@ -170,6 +171,7 @@ static struct platform_device iq80321_serial_device = {
static void __init iq80321_init_machine(void)
{
+ register_iop32x_gpio();
platform_device_register(&iop3xx_i2c0_device);
platform_device_register(&iop3xx_i2c1_device);
platform_device_register(&iq80321_flash_device);
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index 069144300b77..c1cd80ecc219 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -30,6 +30,7 @@
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/io.h>
+#include <linux/gpio.h>
#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
@@ -40,6 +41,7 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <mach/time.h>
+#include "gpio-iop32x.h"
/*
* N2100 timer tick configuration.
@@ -288,8 +290,14 @@ static void n2100_power_off(void)
static void n2100_restart(enum reboot_mode mode, const char *cmd)
{
- gpio_line_set(N2100_HARDWARE_RESET, GPIO_LOW);
- gpio_line_config(N2100_HARDWARE_RESET, GPIO_OUT);
+ int ret;
+
+ ret = gpio_direction_output(N2100_HARDWARE_RESET, 0);
+ if (ret) {
+ pr_crit("could not drive reset GPIO low\n");
+ return;
+ }
+ /* Wait for reset to happen */
while (1)
;
}
@@ -299,7 +307,7 @@ static struct timer_list power_button_poll_timer;
static void power_button_poll(unsigned long dummy)
{
- if (gpio_line_get(N2100_POWER_BUTTON) == 0) {
+ if (gpio_get_value(N2100_POWER_BUTTON) == 0) {
ctrl_alt_del();
return;
}
@@ -308,9 +316,37 @@ static void power_button_poll(unsigned long dummy)
add_timer(&power_button_poll_timer);
}
+static int __init n2100_request_gpios(void)
+{
+ int ret;
+
+ if (!machine_is_n2100())
+ return 0;
+
+ ret = gpio_request(N2100_HARDWARE_RESET, "reset");
+ if (ret)
+ pr_err("could not request reset GPIO\n");
+
+ ret = gpio_request(N2100_POWER_BUTTON, "power");
+ if (ret)
+ pr_err("could not request power GPIO\n");
+ else {
+ ret = gpio_direction_input(N2100_POWER_BUTTON);
+ if (ret)
+ pr_err("could not set power GPIO as input\n");
+ }
+ /* Set up power button poll timer */
+ init_timer(&power_button_poll_timer);
+ power_button_poll_timer.function = power_button_poll;
+ power_button_poll_timer.expires = jiffies + (HZ / 10);
+ add_timer(&power_button_poll_timer);
+ return 0;
+}
+device_initcall(n2100_request_gpios);
static void __init n2100_init_machine(void)
{
+ register_iop32x_gpio();
platform_device_register(&iop3xx_i2c0_device);
platform_device_register(&n2100_flash_device);
platform_device_register(&n2100_serial_device);
@@ -321,11 +357,6 @@ static void __init n2100_init_machine(void)
ARRAY_SIZE(n2100_i2c_devices));
pm_power_off = n2100_power_off;
-
- init_timer(&power_button_poll_timer);
- power_button_poll_timer.function = power_button_poll;
- power_button_poll_timer.expires = jiffies + (HZ / 10);
- add_timer(&power_button_poll_timer);
}
MACHINE_START(N2100, "Thecus N2100")
diff --git a/arch/arm/mach-iop33x/include/mach/gpio.h b/arch/arm/mach-iop33x/include/mach/gpio.h
deleted file mode 100644
index ddd55bba9bb9..000000000000
--- a/arch/arm/mach-iop33x/include/mach/gpio.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_ARCH_IOP33X_GPIO_H
-#define __ASM_ARCH_IOP33X_GPIO_H
-
-#include <asm/hardware/iop3xx-gpio.h>
-
-#endif
diff --git a/arch/arm/mach-iop33x/include/mach/iop33x.h b/arch/arm/mach-iop33x/include/mach/iop33x.h
index a89c0a234bff..c95122653094 100644
--- a/arch/arm/mach-iop33x/include/mach/iop33x.h
+++ b/arch/arm/mach-iop33x/include/mach/iop33x.h
@@ -18,7 +18,6 @@
* Peripherals that are shared between the iop32x and iop33x but
* located at different addresses.
*/
-#define IOP3XX_GPIO_REG(reg) (IOP3XX_PERIPHERAL_VIRT_BASE + 0x1780 + (reg))
#define IOP3XX_TIMER_REG(reg) (IOP3XX_PERIPHERAL_VIRT_BASE + 0x07d0 + (reg))
#include <asm/hardware/iop3xx.h>
diff --git a/arch/arm/mach-iop33x/iq80331.c b/arch/arm/mach-iop33x/iq80331.c
index c43304a10fa7..e2cb65cfbe23 100644
--- a/arch/arm/mach-iop33x/iq80331.c
+++ b/arch/arm/mach-iop33x/iq80331.c
@@ -122,8 +122,15 @@ static struct platform_device iq80331_flash_device = {
.resource = &iq80331_flash_resource,
};
+static struct resource iq80331_gpio_res[] = {
+ DEFINE_RES_MEM((IOP3XX_PERIPHERAL_PHYS_BASE + 0x1780), 0x10),
+};
+
static void __init iq80331_init_machine(void)
{
+ platform_device_register_simple("gpio-iop", 0,
+ iq80331_gpio_res,
+ ARRAY_SIZE(iq80331_gpio_res));
platform_device_register(&iop3xx_i2c0_device);
platform_device_register(&iop3xx_i2c1_device);
platform_device_register(&iop33x_uart0_device);
diff --git a/arch/arm/mach-iop33x/iq80332.c b/arch/arm/mach-iop33x/iq80332.c
index 8192987e78e5..0b6269d94f89 100644
--- a/arch/arm/mach-iop33x/iq80332.c
+++ b/arch/arm/mach-iop33x/iq80332.c
@@ -122,8 +122,15 @@ static struct platform_device iq80332_flash_device = {
.resource = &iq80332_flash_resource,
};
+static struct resource iq80332_gpio_res[] = {
+ DEFINE_RES_MEM((IOP3XX_PERIPHERAL_PHYS_BASE + 0x1780), 0x10),
+};
+
static void __init iq80332_init_machine(void)
{
+ platform_device_register_simple("gpio-iop", 0,
+ iq80332_gpio_res,
+ ARRAY_SIZE(iq80332_gpio_res));
platform_device_register(&iop3xx_i2c0_device);
platform_device_register(&iop3xx_i2c1_device);
platform_device_register(&iop33x_uart0_device);
diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c
index 702232996c8c..cfadd974f5ce 100644
--- a/arch/arm/mach-mmp/ttc_dkb.c
+++ b/arch/arm/mach-mmp/ttc_dkb.c
@@ -191,7 +191,6 @@ static struct pxa3xx_nand_platform_data dkb_nand_info = {
#define SCLK_SOURCE_SELECT(x) (x << 30) /* 0x0 ~ 0x3 */
/* link config */
#define CFG_DUMBMODE(mode) (mode << 28) /* 0x0 ~ 0x6*/
-#define CFG_GRA_SWAPRB(x) (x << 0) /* 1: rbswap enabled */
static struct mmp_mach_path_config dkb_disp_config[] = {
[0] = {
.name = "mmp-parallel",
@@ -199,8 +198,7 @@ static struct mmp_mach_path_config dkb_disp_config[] = {
.output_type = PATH_OUT_PARALLEL,
.path_config = CFG_IOPADMODE(0x1)
| SCLK_SOURCE_SELECT(0x1),
- .link_config = CFG_DUMBMODE(0x2)
- | CFG_GRA_SWAPRB(0x1),
+ .link_config = CFG_DUMBMODE(0x2),
},
};
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
index 4c24303ec481..58adf2fd9cfc 100644
--- a/arch/arm/mach-mvebu/coherency.c
+++ b/arch/arm/mach-mvebu/coherency.c
@@ -140,6 +140,7 @@ int __init coherency_init(void)
coherency_base = of_iomap(np, 0);
coherency_cpu_base = of_iomap(np, 1);
set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0);
+ of_node_put(np);
}
return 0;
@@ -147,9 +148,14 @@ int __init coherency_init(void)
static int __init coherency_late_init(void)
{
- if (of_find_matching_node(NULL, of_coherency_table))
+ struct device_node *np;
+
+ np = of_find_matching_node(NULL, of_coherency_table);
+ if (np) {
bus_register_notifier(&platform_bus_type,
&mvebu_hwcc_platform_nb);
+ of_node_put(np);
+ }
return 0;
}
diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c
index 3cc4bef6401c..27fc4f049474 100644
--- a/arch/arm/mach-mvebu/pmsu.c
+++ b/arch/arm/mach-mvebu/pmsu.c
@@ -67,6 +67,7 @@ int __init armada_370_xp_pmsu_init(void)
pr_info("Initializing Power Management Service Unit\n");
pmsu_mp_base = of_iomap(np, 0);
pmsu_reset_base = of_iomap(np, 1);
+ of_node_put(np);
}
return 0;
diff --git a/arch/arm/mach-mvebu/system-controller.c b/arch/arm/mach-mvebu/system-controller.c
index f875124ff4f9..5175083cdb34 100644
--- a/arch/arm/mach-mvebu/system-controller.c
+++ b/arch/arm/mach-mvebu/system-controller.c
@@ -98,6 +98,7 @@ static int __init mvebu_system_controller_init(void)
BUG_ON(!match);
system_controller_base = of_iomap(np, 0);
mvebu_sc = (struct mvebu_system_controller *)match->data;
+ of_node_put(np);
}
return 0;
diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c
index 13e0df9c11ce..c6c156e5570e 100644
--- a/arch/arm/mach-nomadik/cpu-8815.c
+++ b/arch/arm/mach-nomadik/cpu-8815.c
@@ -31,9 +31,7 @@
#include <linux/of_gpio.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
-#include <linux/mtd/fsmc.h>
#include <linux/gpio.h>
-#include <linux/amba/mmci.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -146,17 +144,6 @@ static void __init cpu8815_timer_init_of(void)
clocksource_of_init();
}
-static struct fsmc_nand_timings cpu8815_nand_timings = {
- .thiz = 0,
- .thold = 0x10,
- .twait = 0x0A,
- .tset = 0,
-};
-
-static struct fsmc_nand_platform_data cpu8815_nand_data = {
- .nand_timings = &cpu8815_nand_timings,
-};
-
/*
* The SMSC911x IRQ is connected to a GPIO pin, but the driver expects
* to simply request an IRQ passed as a resource. So the GPIO pin needs
@@ -190,15 +177,6 @@ static int __init cpu8815_eth_init(void)
device_initcall(cpu8815_eth_init);
/*
- * TODO:
- * cannot be set from device tree, convert to a proper DT
- * binding.
- */
-static struct mmci_platform_data mmcsd_plat_data = {
- .ocr_mask = MMC_VDD_29_30,
-};
-
-/*
* This GPIO pin turns on a line that is used to detect card insertion
* on this board.
*/
@@ -232,24 +210,13 @@ static int __init cpu8815_mmcsd_init(void)
}
device_initcall(cpu8815_mmcsd_init);
-
-/* These are mostly to get the right device names for the clock lookups */
-static struct of_dev_auxdata cpu8815_auxdata_lookup[] __initdata = {
- OF_DEV_AUXDATA("stericsson,fsmc-nand", NOMADIK_FSMC_BASE,
- NULL, &cpu8815_nand_data),
- OF_DEV_AUXDATA("arm,primecell", NOMADIK_SDI_BASE,
- NULL, &mmcsd_plat_data),
- { /* sentinel */ },
-};
-
static void __init cpu8815_init_of(void)
{
#ifdef CONFIG_CACHE_L2X0
/* At full speed latency must be >=2, so 0x249 in low bits */
l2x0_of_init(0x00730249, 0xfe000fff);
#endif
- of_platform_populate(NULL, of_default_bus_match_table,
- cpu8815_auxdata_lookup, NULL);
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
static const char * cpu8815_board_compat[] = {
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
index 041da5172423..bd14e3a37128 100644
--- a/arch/arm/mach-s3c64xx/Kconfig
+++ b/arch/arm/mach-s3c64xx/Kconfig
@@ -306,3 +306,19 @@ config MACH_WLF_CRAGG_6410
select SAMSUNG_GPIO_EXTRA128
help
Machine support for the Wolfson Cragganmore S3C6410 variant.
+
+config MACH_S3C64XX_DT
+ bool "Samsung S3C6400/S3C6410 machine using Device Tree"
+ select CLKSRC_OF
+ select CPU_S3C6400
+ select CPU_S3C6410
+ select PINCTRL
+ select PINCTRL_S3C64XX
+ select USE_OF
+ help
+ Machine support for Samsung S3C6400/S3C6410 machines with Device Tree
+ enabled.
+ Select this if a fdt blob is available for your S3C64XX SoC based
+ board.
+ Note: This is under development and not all peripherals can be
+ supported with this machine file.
diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile
index 31d0c9101272..6faedcffce04 100644
--- a/arch/arm/mach-s3c64xx/Makefile
+++ b/arch/arm/mach-s3c64xx/Makefile
@@ -12,7 +12,7 @@ obj- :=
# Core
-obj-y += common.o clock.o
+obj-y += common.o
# Core support
@@ -57,3 +57,4 @@ obj-$(CONFIG_MACH_SMARTQ7) += mach-smartq7.o
obj-$(CONFIG_MACH_SMDK6400) += mach-smdk6400.o
obj-$(CONFIG_MACH_SMDK6410) += mach-smdk6410.o
obj-$(CONFIG_MACH_WLF_CRAGG_6410) += mach-crag6410.o mach-crag6410-module.o
+obj-$(CONFIG_MACH_S3C64XX_DT) += mach-s3c64xx-dt.o
diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c
deleted file mode 100644
index c1bcc4a6d3a8..000000000000
--- a/arch/arm/mach-s3c64xx/clock.c
+++ /dev/null
@@ -1,1007 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/clock.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- * http://armlinux.simtec.co.uk/
- *
- * S3C64XX Base clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-
-#include <mach/regs-clock.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/pll.h>
-
-#include "regs-sys.h"
-
-/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
- * ext_xtal_mux for want of an actual name from the manual.
-*/
-
-static struct clk clk_ext_xtal_mux = {
- .name = "ext_xtal",
-};
-
-#define clk_fin_apll clk_ext_xtal_mux
-#define clk_fin_mpll clk_ext_xtal_mux
-#define clk_fin_epll clk_ext_xtal_mux
-
-#define clk_fout_mpll clk_mpll
-#define clk_fout_epll clk_epll
-
-struct clk clk_h2 = {
- .name = "hclk2",
- .rate = 0,
-};
-
-struct clk clk_27m = {
- .name = "clk_27m",
- .rate = 27000000,
-};
-
-static int clk_48m_ctrl(struct clk *clk, int enable)
-{
- unsigned long flags;
- u32 val;
-
- /* can't rely on clock lock, this register has other usages */
- local_irq_save(flags);
-
- val = __raw_readl(S3C64XX_OTHERS);
- if (enable)
- val |= S3C64XX_OTHERS_USBMASK;
- else
- val &= ~S3C64XX_OTHERS_USBMASK;
-
- __raw_writel(val, S3C64XX_OTHERS);
- local_irq_restore(flags);
-
- return 0;
-}
-
-struct clk clk_48m = {
- .name = "clk_48m",
- .rate = 48000000,
- .enable = clk_48m_ctrl,
-};
-
-struct clk clk_xusbxti = {
- .name = "xusbxti",
- .rate = 48000000,
-};
-
-static int inline s3c64xx_gate(void __iomem *reg,
- struct clk *clk,
- int enable)
-{
- unsigned int ctrlbit = clk->ctrlbit;
- u32 con;
-
- con = __raw_readl(reg);
-
- if (enable)
- con |= ctrlbit;
- else
- con &= ~ctrlbit;
-
- __raw_writel(con, reg);
- return 0;
-}
-
-static int s3c64xx_pclk_ctrl(struct clk *clk, int enable)
-{
- return s3c64xx_gate(S3C_PCLK_GATE, clk, enable);
-}
-
-static int s3c64xx_hclk_ctrl(struct clk *clk, int enable)
-{
- return s3c64xx_gate(S3C_HCLK_GATE, clk, enable);
-}
-
-int s3c64xx_sclk_ctrl(struct clk *clk, int enable)
-{
- return s3c64xx_gate(S3C_SCLK_GATE, clk, enable);
-}
-
-static struct clk init_clocks_off[] = {
- {
- .name = "nand",
- .parent = &clk_h,
- }, {
- .name = "rtc",
- .parent = &clk_p,
- .enable = s3c64xx_pclk_ctrl,
- .ctrlbit = S3C_CLKCON_PCLK_RTC,
- }, {
- .name = "adc",
- .parent = &clk_p,
- .enable = s3c64xx_pclk_ctrl,
- .ctrlbit = S3C_CLKCON_PCLK_TSADC,
- }, {
- .name = "i2c",
- .devname = "s3c2440-i2c.0",
- .parent = &clk_p,
- .enable = s3c64xx_pclk_ctrl,
- .ctrlbit = S3C_CLKCON_PCLK_IIC,
- }, {
- .name = "i2c",
- .devname = "s3c2440-i2c.1",
- .parent = &clk_p,
- .enable = s3c64xx_pclk_ctrl,
- .ctrlbit = S3C6410_CLKCON_PCLK_I2C1,
- }, {
- .name = "keypad",
- .parent = &clk_p,
- .enable = s3c64xx_pclk_ctrl,
- .ctrlbit = S3C_CLKCON_PCLK_KEYPAD,
- }, {
- .name = "spi",
- .devname = "s3c6410-spi.0",
- .parent = &clk_p,
- .enable = s3c64xx_pclk_ctrl,
- .ctrlbit = S3C_CLKCON_PCLK_SPI0,
- }, {
- .name = "spi",
- .devname = "s3c6410-spi.1",
- .parent = &clk_p,
- .enable = s3c64xx_pclk_ctrl,
- .ctrlbit = S3C_CLKCON_PCLK_SPI1,
- }, {
- .name = "48m",
- .devname = "s3c-sdhci.0",
- .parent = &clk_48m,
- .enable = s3c64xx_sclk_ctrl,
- .ctrlbit = S3C_CLKCON_SCLK_MMC0_48,
- }, {
- .name = "48m",
- .devname = "s3c-sdhci.1",
- .parent = &clk_48m,
- .enable = s3c64xx_sclk_ctrl,
- .ctrlbit = S3C_CLKCON_SCLK_MMC1_48,
- }, {
- .name = "48m",
- .devname = "s3c-sdhci.2",
- .parent = &clk_48m,
- .enable = s3c64xx_sclk_ctrl,
- .ctrlbit = S3C_CLKCON_SCLK_MMC2_48,
- }, {
- .name = "ac97",
- .parent = &clk_p,
- .ctrlbit = S3C_CLKCON_PCLK_AC97,
- }, {
- .name = "cfcon",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_IHOST,
- }, {
- .name = "dma0",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_DMA0,
- }, {
- .name = "dma1",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_DMA1,
- }, {
- .name = "3dse",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_3DSE,
- }, {
- .name = "hclk_secur",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_SECUR,
- }, {
- .name = "sdma1",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_SDMA1,
- }, {
- .name = "sdma0",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_SDMA0,
- }, {
- .name = "hclk_jpeg",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_JPEG,
- }, {
- .name = "camif",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_CAMIF,
- }, {
- .name = "hclk_scaler",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_SCALER,
- }, {
- .name = "2d",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_2D,
- }, {
- .name = "tv",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_TV,
- }, {
- .name = "post0",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_POST0,
- }, {
- .name = "rot",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_ROT,
- }, {
- .name = "hclk_mfc",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_MFC,
- }, {
- .name = "pclk_mfc",
- .parent = &clk_p,
- .enable = s3c64xx_pclk_ctrl,
- .ctrlbit = S3C_CLKCON_PCLK_MFC,
- }, {
- .name = "dac27",
- .enable = s3c64xx_sclk_ctrl,
- .ctrlbit = S3C_CLKCON_SCLK_DAC27,
- }, {
- .name = "tv27",
- .enable = s3c64xx_sclk_ctrl,
- .ctrlbit = S3C_CLKCON_SCLK_TV27,
- }, {
- .name = "scaler27",
- .enable = s3c64xx_sclk_ctrl,
- .ctrlbit = S3C_CLKCON_SCLK_SCALER27,
- }, {
- .name = "sclk_scaler",
- .enable = s3c64xx_sclk_ctrl,
- .ctrlbit = S3C_CLKCON_SCLK_SCALER,
- }, {
- .name = "post0_27",
- .enable = s3c64xx_sclk_ctrl,
- .ctrlbit = S3C_CLKCON_SCLK_POST0_27,
- }, {
- .name = "secur",
- .enable = s3c64xx_sclk_ctrl,
- .ctrlbit = S3C_CLKCON_SCLK_SECUR,
- }, {
- .name = "sclk_mfc",
- .enable = s3c64xx_sclk_ctrl,
- .ctrlbit = S3C_CLKCON_SCLK_MFC,
- }, {
- .name = "sclk_jpeg",
- .enable = s3c64xx_sclk_ctrl,
- .ctrlbit = S3C_CLKCON_SCLK_JPEG,
- },
-};
-
-static struct clk clk_48m_spi0 = {
- .name = "spi_48m",
- .devname = "s3c6410-spi.0",
- .parent = &clk_48m,
- .enable = s3c64xx_sclk_ctrl,
- .ctrlbit = S3C_CLKCON_SCLK_SPI0_48,
-};
-
-static struct clk clk_48m_spi1 = {
- .name = "spi_48m",
- .devname = "s3c6410-spi.1",
- .parent = &clk_48m,
- .enable = s3c64xx_sclk_ctrl,
- .ctrlbit = S3C_CLKCON_SCLK_SPI1_48,
-};
-
-static struct clk clk_i2s0 = {
- .name = "iis",
- .devname = "samsung-i2s.0",
- .parent = &clk_p,
- .enable = s3c64xx_pclk_ctrl,
- .ctrlbit = S3C_CLKCON_PCLK_IIS0,
-};
-
-static struct clk clk_i2s1 = {
- .name = "iis",
- .devname = "samsung-i2s.1",
- .parent = &clk_p,
- .enable = s3c64xx_pclk_ctrl,
- .ctrlbit = S3C_CLKCON_PCLK_IIS1,
-};
-
-#ifdef CONFIG_CPU_S3C6410
-static struct clk clk_i2s2 = {
- .name = "iis",
- .devname = "samsung-i2s.2",
- .parent = &clk_p,
- .enable = s3c64xx_pclk_ctrl,
- .ctrlbit = S3C6410_CLKCON_PCLK_IIS2,
-};
-#endif
-
-static struct clk init_clocks[] = {
- {
- .name = "lcd",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_LCD,
- }, {
- .name = "gpio",
- .parent = &clk_p,
- .enable = s3c64xx_pclk_ctrl,
- .ctrlbit = S3C_CLKCON_PCLK_GPIO,
- }, {
- .name = "usb-host",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_UHOST,
- }, {
- .name = "otg",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_USB,
- }, {
- .name = "timers",
- .parent = &clk_p,
- .enable = s3c64xx_pclk_ctrl,
- .ctrlbit = S3C_CLKCON_PCLK_PWM,
- }, {
- .name = "uart",
- .devname = "s3c6400-uart.0",
- .parent = &clk_p,
- .enable = s3c64xx_pclk_ctrl,
- .ctrlbit = S3C_CLKCON_PCLK_UART0,
- }, {
- .name = "uart",
- .devname = "s3c6400-uart.1",
- .parent = &clk_p,
- .enable = s3c64xx_pclk_ctrl,
- .ctrlbit = S3C_CLKCON_PCLK_UART1,
- }, {
- .name = "uart",
- .devname = "s3c6400-uart.2",
- .parent = &clk_p,
- .enable = s3c64xx_pclk_ctrl,
- .ctrlbit = S3C_CLKCON_PCLK_UART2,
- }, {
- .name = "uart",
- .devname = "s3c6400-uart.3",
- .parent = &clk_p,
- .enable = s3c64xx_pclk_ctrl,
- .ctrlbit = S3C_CLKCON_PCLK_UART3,
- }, {
- .name = "watchdog",
- .parent = &clk_p,
- .ctrlbit = S3C_CLKCON_PCLK_WDT,
- },
-};
-
-static struct clk clk_hsmmc0 = {
- .name = "hsmmc",
- .devname = "s3c-sdhci.0",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_HSMMC0,
-};
-
-static struct clk clk_hsmmc1 = {
- .name = "hsmmc",
- .devname = "s3c-sdhci.1",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_HSMMC1,
-};
-
-static struct clk clk_hsmmc2 = {
- .name = "hsmmc",
- .devname = "s3c-sdhci.2",
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_HSMMC2,
-};
-
-static struct clk clk_fout_apll = {
- .name = "fout_apll",
-};
-
-static struct clk *clk_src_apll_list[] = {
- [0] = &clk_fin_apll,
- [1] = &clk_fout_apll,
-};
-
-static struct clksrc_sources clk_src_apll = {
- .sources = clk_src_apll_list,
- .nr_sources = ARRAY_SIZE(clk_src_apll_list),
-};
-
-static struct clksrc_clk clk_mout_apll = {
- .clk = {
- .name = "mout_apll",
- },
- .reg_src = { .reg = S3C_CLK_SRC, .shift = 0, .size = 1 },
- .sources = &clk_src_apll,
-};
-
-static struct clk *clk_src_epll_list[] = {
- [0] = &clk_fin_epll,
- [1] = &clk_fout_epll,
-};
-
-static struct clksrc_sources clk_src_epll = {
- .sources = clk_src_epll_list,
- .nr_sources = ARRAY_SIZE(clk_src_epll_list),
-};
-
-static struct clksrc_clk clk_mout_epll = {
- .clk = {
- .name = "mout_epll",
- },
- .reg_src = { .reg = S3C_CLK_SRC, .shift = 2, .size = 1 },
- .sources = &clk_src_epll,
-};
-
-static struct clk *clk_src_mpll_list[] = {
- [0] = &clk_fin_mpll,
- [1] = &clk_fout_mpll,
-};
-
-static struct clksrc_sources clk_src_mpll = {
- .sources = clk_src_mpll_list,
- .nr_sources = ARRAY_SIZE(clk_src_mpll_list),
-};
-
-static struct clksrc_clk clk_mout_mpll = {
- .clk = {
- .name = "mout_mpll",
- },
- .reg_src = { .reg = S3C_CLK_SRC, .shift = 1, .size = 1 },
- .sources = &clk_src_mpll,
-};
-
-static unsigned int armclk_mask;
-
-static unsigned long s3c64xx_clk_arm_get_rate(struct clk *clk)
-{
- unsigned long rate = clk_get_rate(clk->parent);
- u32 clkdiv;
-
- /* divisor mask starts at bit0, so no need to shift */
- clkdiv = __raw_readl(S3C_CLK_DIV0) & armclk_mask;
-
- return rate / (clkdiv + 1);
-}
-
-static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk,
- unsigned long rate)
-{
- unsigned long parent = clk_get_rate(clk->parent);
- u32 div;
-
- if (parent < rate)
- return parent;
-
- div = (parent / rate) - 1;
- if (div > armclk_mask)
- div = armclk_mask;
-
- return parent / (div + 1);
-}
-
-static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
-{
- unsigned long parent = clk_get_rate(clk->parent);
- u32 div;
- u32 val;
-
- if (rate < parent / (armclk_mask + 1))
- return -EINVAL;
-
- rate = clk_round_rate(clk, rate);
- div = clk_get_rate(clk->parent) / rate;
-
- val = __raw_readl(S3C_CLK_DIV0);
- val &= ~armclk_mask;
- val |= (div - 1);
- __raw_writel(val, S3C_CLK_DIV0);
-
- return 0;
-
-}
-
-static struct clk clk_arm = {
- .name = "armclk",
- .parent = &clk_mout_apll.clk,
- .ops = &(struct clk_ops) {
- .get_rate = s3c64xx_clk_arm_get_rate,
- .set_rate = s3c64xx_clk_arm_set_rate,
- .round_rate = s3c64xx_clk_arm_round_rate,
- },
-};
-
-static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk)
-{
- unsigned long rate = clk_get_rate(clk->parent);
-
- printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
-
- if (__raw_readl(S3C_CLK_DIV0) & S3C6400_CLKDIV0_MPLL_MASK)
- rate /= 2;
-
- return rate;
-}
-
-static struct clk_ops clk_dout_ops = {
- .get_rate = s3c64xx_clk_doutmpll_get_rate,
-};
-
-static struct clk clk_dout_mpll = {
- .name = "dout_mpll",
- .parent = &clk_mout_mpll.clk,
- .ops = &clk_dout_ops,
-};
-
-static struct clk *clkset_spi_mmc_list[] = {
- &clk_mout_epll.clk,
- &clk_dout_mpll,
- &clk_fin_epll,
- &clk_27m,
-};
-
-static struct clksrc_sources clkset_spi_mmc = {
- .sources = clkset_spi_mmc_list,
- .nr_sources = ARRAY_SIZE(clkset_spi_mmc_list),
-};
-
-static struct clk *clkset_irda_list[] = {
- &clk_mout_epll.clk,
- &clk_dout_mpll,
- NULL,
- &clk_27m,
-};
-
-static struct clksrc_sources clkset_irda = {
- .sources = clkset_irda_list,
- .nr_sources = ARRAY_SIZE(clkset_irda_list),
-};
-
-static struct clk *clkset_uart_list[] = {
- &clk_mout_epll.clk,
- &clk_dout_mpll,
- NULL,
- NULL
-};
-
-static struct clksrc_sources clkset_uart = {
- .sources = clkset_uart_list,
- .nr_sources = ARRAY_SIZE(clkset_uart_list),
-};
-
-static struct clk *clkset_uhost_list[] = {
- &clk_48m,
- &clk_mout_epll.clk,
- &clk_dout_mpll,
- &clk_fin_epll,
-};
-
-static struct clksrc_sources clkset_uhost = {
- .sources = clkset_uhost_list,
- .nr_sources = ARRAY_SIZE(clkset_uhost_list),
-};
-
-/* The peripheral clocks are all controlled via clocksource followed
- * by an optional divider and gate stage. We currently roll this into
- * one clock which hides the intermediate clock from the mux.
- *
- * Note, the JPEG clock can only be an even divider...
- *
- * The scaler and LCD clocks depend on the S3C64XX version, and also
- * have a common parent divisor so are not included here.
- */
-
-/* clocks that feed other parts of the clock source tree */
-
-static struct clk clk_iis_cd0 = {
- .name = "iis_cdclk0",
-};
-
-static struct clk clk_iis_cd1 = {
- .name = "iis_cdclk1",
-};
-
-static struct clk clk_iisv4_cd = {
- .name = "iis_cdclk_v4",
-};
-
-static struct clk clk_pcm_cd = {
- .name = "pcm_cdclk",
-};
-
-static struct clk *clkset_audio0_list[] = {
- [0] = &clk_mout_epll.clk,
- [1] = &clk_dout_mpll,
- [2] = &clk_fin_epll,
- [3] = &clk_iis_cd0,
- [4] = &clk_pcm_cd,
-};
-
-static struct clksrc_sources clkset_audio0 = {
- .sources = clkset_audio0_list,
- .nr_sources = ARRAY_SIZE(clkset_audio0_list),
-};
-
-static struct clk *clkset_audio1_list[] = {
- [0] = &clk_mout_epll.clk,
- [1] = &clk_dout_mpll,
- [2] = &clk_fin_epll,
- [3] = &clk_iis_cd1,
- [4] = &clk_pcm_cd,
-};
-
-static struct clksrc_sources clkset_audio1 = {
- .sources = clkset_audio1_list,
- .nr_sources = ARRAY_SIZE(clkset_audio1_list),
-};
-
-#ifdef CONFIG_CPU_S3C6410
-static struct clk *clkset_audio2_list[] = {
- [0] = &clk_mout_epll.clk,
- [1] = &clk_dout_mpll,
- [2] = &clk_fin_epll,
- [3] = &clk_iisv4_cd,
- [4] = &clk_pcm_cd,
-};
-
-static struct clksrc_sources clkset_audio2 = {
- .sources = clkset_audio2_list,
- .nr_sources = ARRAY_SIZE(clkset_audio2_list),
-};
-#endif
-
-static struct clksrc_clk clksrcs[] = {
- {
- .clk = {
- .name = "usb-bus-host",
- .ctrlbit = S3C_CLKCON_SCLK_UHOST,
- .enable = s3c64xx_sclk_ctrl,
- },
- .reg_src = { .reg = S3C_CLK_SRC, .shift = 5, .size = 2 },
- .reg_div = { .reg = S3C_CLK_DIV1, .shift = 20, .size = 4 },
- .sources = &clkset_uhost,
- }, {
- .clk = {
- .name = "irda-bus",
- .ctrlbit = S3C_CLKCON_SCLK_IRDA,
- .enable = s3c64xx_sclk_ctrl,
- },
- .reg_src = { .reg = S3C_CLK_SRC, .shift = 24, .size = 2 },
- .reg_div = { .reg = S3C_CLK_DIV2, .shift = 20, .size = 4 },
- .sources = &clkset_irda,
- }, {
- .clk = {
- .name = "camera",
- .ctrlbit = S3C_CLKCON_SCLK_CAM,
- .enable = s3c64xx_sclk_ctrl,
- .parent = &clk_h2,
- },
- .reg_div = { .reg = S3C_CLK_DIV0, .shift = 20, .size = 4 },
- },
-};
-
-/* Where does UCLK0 come from? */
-static struct clksrc_clk clk_sclk_uclk = {
- .clk = {
- .name = "uclk1",
- .ctrlbit = S3C_CLKCON_SCLK_UART,
- .enable = s3c64xx_sclk_ctrl,
- },
- .reg_src = { .reg = S3C_CLK_SRC, .shift = 13, .size = 1 },
- .reg_div = { .reg = S3C_CLK_DIV2, .shift = 16, .size = 4 },
- .sources = &clkset_uart,
-};
-
-static struct clksrc_clk clk_sclk_mmc0 = {
- .clk = {
- .name = "mmc_bus",
- .devname = "s3c-sdhci.0",
- .ctrlbit = S3C_CLKCON_SCLK_MMC0,
- .enable = s3c64xx_sclk_ctrl,
- },
- .reg_src = { .reg = S3C_CLK_SRC, .shift = 18, .size = 2 },
- .reg_div = { .reg = S3C_CLK_DIV1, .shift = 0, .size = 4 },
- .sources = &clkset_spi_mmc,
-};
-
-static struct clksrc_clk clk_sclk_mmc1 = {
- .clk = {
- .name = "mmc_bus",
- .devname = "s3c-sdhci.1",
- .ctrlbit = S3C_CLKCON_SCLK_MMC1,
- .enable = s3c64xx_sclk_ctrl,
- },
- .reg_src = { .reg = S3C_CLK_SRC, .shift = 20, .size = 2 },
- .reg_div = { .reg = S3C_CLK_DIV1, .shift = 4, .size = 4 },
- .sources = &clkset_spi_mmc,
-};
-
-static struct clksrc_clk clk_sclk_mmc2 = {
- .clk = {
- .name = "mmc_bus",
- .devname = "s3c-sdhci.2",
- .ctrlbit = S3C_CLKCON_SCLK_MMC2,
- .enable = s3c64xx_sclk_ctrl,
- },
- .reg_src = { .reg = S3C_CLK_SRC, .shift = 22, .size = 2 },
- .reg_div = { .reg = S3C_CLK_DIV1, .shift = 8, .size = 4 },
- .sources = &clkset_spi_mmc,
-};
-
-static struct clksrc_clk clk_sclk_spi0 = {
- .clk = {
- .name = "spi-bus",
- .devname = "s3c6410-spi.0",
- .ctrlbit = S3C_CLKCON_SCLK_SPI0,
- .enable = s3c64xx_sclk_ctrl,
- },
- .reg_src = { .reg = S3C_CLK_SRC, .shift = 14, .size = 2 },
- .reg_div = { .reg = S3C_CLK_DIV2, .shift = 0, .size = 4 },
- .sources = &clkset_spi_mmc,
-};
-
-static struct clksrc_clk clk_sclk_spi1 = {
- .clk = {
- .name = "spi-bus",
- .devname = "s3c6410-spi.1",
- .ctrlbit = S3C_CLKCON_SCLK_SPI1,
- .enable = s3c64xx_sclk_ctrl,
- },
- .reg_src = { .reg = S3C_CLK_SRC, .shift = 16, .size = 2 },
- .reg_div = { .reg = S3C_CLK_DIV2, .shift = 4, .size = 4 },
- .sources = &clkset_spi_mmc,
-};
-
-static struct clksrc_clk clk_audio_bus0 = {
- .clk = {
- .name = "audio-bus",
- .devname = "samsung-i2s.0",
- .ctrlbit = S3C_CLKCON_SCLK_AUDIO0,
- .enable = s3c64xx_sclk_ctrl,
- },
- .reg_src = { .reg = S3C_CLK_SRC, .shift = 7, .size = 3 },
- .reg_div = { .reg = S3C_CLK_DIV2, .shift = 8, .size = 4 },
- .sources = &clkset_audio0,
-};
-
-static struct clksrc_clk clk_audio_bus1 = {
- .clk = {
- .name = "audio-bus",
- .devname = "samsung-i2s.1",
- .ctrlbit = S3C_CLKCON_SCLK_AUDIO1,
- .enable = s3c64xx_sclk_ctrl,
- },
- .reg_src = { .reg = S3C_CLK_SRC, .shift = 10, .size = 3 },
- .reg_div = { .reg = S3C_CLK_DIV2, .shift = 12, .size = 4 },
- .sources = &clkset_audio1,
-};
-
-#ifdef CONFIG_CPU_S3C6410
-static struct clksrc_clk clk_audio_bus2 = {
- .clk = {
- .name = "audio-bus",
- .devname = "samsung-i2s.2",
- .ctrlbit = S3C6410_CLKCON_SCLK_AUDIO2,
- .enable = s3c64xx_sclk_ctrl,
- },
- .reg_src = { .reg = S3C6410_CLK_SRC2, .shift = 0, .size = 3 },
- .reg_div = { .reg = S3C_CLK_DIV2, .shift = 24, .size = 4 },
- .sources = &clkset_audio2,
-};
-#endif
-/* Clock initialisation code */
-
-static struct clksrc_clk *init_parents[] = {
- &clk_mout_apll,
- &clk_mout_epll,
- &clk_mout_mpll,
-};
-
-static struct clksrc_clk *clksrc_cdev[] = {
- &clk_sclk_uclk,
- &clk_sclk_mmc0,
- &clk_sclk_mmc1,
- &clk_sclk_mmc2,
- &clk_sclk_spi0,
- &clk_sclk_spi1,
- &clk_audio_bus0,
- &clk_audio_bus1,
-};
-
-static struct clk *clk_cdev[] = {
- &clk_hsmmc0,
- &clk_hsmmc1,
- &clk_hsmmc2,
- &clk_48m_spi0,
- &clk_48m_spi1,
- &clk_i2s0,
- &clk_i2s1,
-};
-
-static struct clk_lookup s3c64xx_clk_lookup[] = {
- CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
- CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk),
- CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &clk_hsmmc0),
- CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &clk_hsmmc1),
- CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.0", &clk_hsmmc2),
- CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
- CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
- CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
- CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
- CLKDEV_INIT("s3c6410-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
- CLKDEV_INIT("s3c6410-spi.0", "spi_busclk2", &clk_48m_spi0),
- CLKDEV_INIT("s3c6410-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
- CLKDEV_INIT("s3c6410-spi.1", "spi_busclk2", &clk_48m_spi1),
- CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &clk_i2s0),
- CLKDEV_INIT("samsung-i2s.0", "i2s_opclk1", &clk_audio_bus0.clk),
- CLKDEV_INIT("samsung-i2s.1", "i2s_opclk0", &clk_i2s1),
- CLKDEV_INIT("samsung-i2s.1", "i2s_opclk1", &clk_audio_bus1.clk),
-#ifdef CONFIG_CPU_S3C6410
- CLKDEV_INIT("samsung-i2s.2", "i2s_opclk0", &clk_i2s2),
- CLKDEV_INIT("samsung-i2s.2", "i2s_opclk1", &clk_audio_bus2.clk),
-#endif
-};
-
-#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
-
-void __init_or_cpufreq s3c64xx_setup_clocks(void)
-{
- struct clk *xtal_clk;
- unsigned long xtal;
- unsigned long fclk;
- unsigned long hclk;
- unsigned long hclk2;
- unsigned long pclk;
- unsigned long epll;
- unsigned long apll;
- unsigned long mpll;
- unsigned int ptr;
- u32 clkdiv0;
-
- printk(KERN_DEBUG "%s: registering clocks\n", __func__);
-
- clkdiv0 = __raw_readl(S3C_CLK_DIV0);
- printk(KERN_DEBUG "%s: clkdiv0 = %08x\n", __func__, clkdiv0);
-
- xtal_clk = clk_get(NULL, "xtal");
- BUG_ON(IS_ERR(xtal_clk));
-
- xtal = clk_get_rate(xtal_clk);
- clk_put(xtal_clk);
-
- printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
-
- /* For now assume the mux always selects the crystal */
- clk_ext_xtal_mux.parent = xtal_clk;
-
- epll = s3c_get_pll6553x(xtal, __raw_readl(S3C_EPLL_CON0),
- __raw_readl(S3C_EPLL_CON1));
- mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON));
- apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON));
-
- fclk = mpll;
-
- printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n",
- apll, mpll, epll);
-
- if(__raw_readl(S3C64XX_OTHERS) & S3C64XX_OTHERS_SYNCMUXSEL)
- /* Synchronous mode */
- hclk2 = apll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
- else
- /* Asynchronous mode */
- hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
-
- hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK);
- pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK);
-
- printk(KERN_INFO "S3C64XX: HCLK2=%ld, HCLK=%ld, PCLK=%ld\n",
- hclk2, hclk, pclk);
-
- clk_fout_mpll.rate = mpll;
- clk_fout_epll.rate = epll;
- clk_fout_apll.rate = apll;
-
- clk_h2.rate = hclk2;
- clk_h.rate = hclk;
- clk_p.rate = pclk;
- clk_f.rate = fclk;
-
- for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
- s3c_set_clksrc(init_parents[ptr], true);
-
- for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
- s3c_set_clksrc(&clksrcs[ptr], true);
-}
-
-static struct clk *clks1[] __initdata = {
- &clk_ext_xtal_mux,
- &clk_iis_cd0,
- &clk_iis_cd1,
- &clk_iisv4_cd,
- &clk_pcm_cd,
- &clk_mout_epll.clk,
- &clk_mout_mpll.clk,
- &clk_dout_mpll,
- &clk_arm,
-};
-
-static struct clk *clks[] __initdata = {
- &clk_ext,
- &clk_epll,
- &clk_27m,
- &clk_48m,
- &clk_h2,
- &clk_xusbxti,
-};
-
-/**
- * s3c64xx_register_clocks - register clocks for s3c6400 and s3c6410
- * @xtal: The rate for the clock crystal feeding the PLLs.
- * @armclk_divlimit: Divisor mask for ARMCLK.
- *
- * Register the clocks for the S3C6400 and S3C6410 SoC range, such
- * as ARMCLK as well as the necessary parent clocks.
- *
- * This call does not setup the clocks, which is left to the
- * s3c64xx_setup_clocks() call which may be needed by the cpufreq
- * or resume code to re-set the clocks if the bootloader has changed
- * them.
- */
-void __init s3c64xx_register_clocks(unsigned long xtal,
- unsigned armclk_divlimit)
-{
- unsigned int cnt;
-
- armclk_mask = armclk_divlimit;
-
- s3c24xx_register_baseclocks(xtal);
- s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-
- s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
-
- s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
- s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-
- s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
- for (cnt = 0; cnt < ARRAY_SIZE(clk_cdev); cnt++)
- s3c_disable_clocks(clk_cdev[cnt], 1);
-
- s3c24xx_register_clocks(clks1, ARRAY_SIZE(clks1));
- s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
- for (cnt = 0; cnt < ARRAY_SIZE(clksrc_cdev); cnt++)
- s3c_register_clksrc(clksrc_cdev[cnt], 1);
- clkdev_add_table(s3c64xx_clk_lookup, ARRAY_SIZE(s3c64xx_clk_lookup));
-}
diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c
index 73d79cf5e141..7a3ce4c39e5f 100644
--- a/arch/arm/mach-s3c64xx/common.c
+++ b/arch/arm/mach-s3c64xx/common.c
@@ -14,9 +14,14 @@
* published by the Free Software Foundation.
*/
+/*
+ * NOTE: Code in this file is not used when booting with Device Tree support.
+ */
+
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/clk-provider.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/serial_core.h>
@@ -38,7 +43,6 @@
#include <mach/regs-gpio.h>
#include <plat/cpu.h>
-#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/pm.h>
#include <plat/gpio-cfg.h>
@@ -50,6 +54,19 @@
#include "common.h"
+/* External clock frequency */
+static unsigned long xtal_f = 12000000, xusbxti_f = 48000000;
+
+void __init s3c64xx_set_xtal_freq(unsigned long freq)
+{
+ xtal_f = freq;
+}
+
+void __init s3c64xx_set_xusbxti_freq(unsigned long freq)
+{
+ xusbxti_f = freq;
+}
+
/* uart registration process */
static void __init s3c64xx_init_uarts(struct s3c2410_uartcfg *cfg, int no)
@@ -67,7 +84,6 @@ static struct cpu_table cpu_ids[] __initdata = {
.idcode = S3C6400_CPU_ID,
.idmask = S3C64XX_CPU_MASK,
.map_io = s3c6400_map_io,
- .init_clocks = s3c6400_init_clocks,
.init_uarts = s3c64xx_init_uarts,
.init = s3c6400_init,
.name = name_s3c6400,
@@ -75,7 +91,6 @@ static struct cpu_table cpu_ids[] __initdata = {
.idcode = S3C6410_CPU_ID,
.idmask = S3C64XX_CPU_MASK,
.map_io = s3c6410_map_io,
- .init_clocks = s3c6410_init_clocks,
.init_uarts = s3c64xx_init_uarts,
.init = s3c6410_init,
.name = name_s3c6410,
@@ -192,6 +207,10 @@ void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
static __init int s3c64xx_dev_init(void)
{
+ /* Not applicable when using DT. */
+ if (of_have_populated_dt())
+ return 0;
+
subsys_system_register(&s3c64xx_subsys, NULL);
return device_register(&s3c64xx_dev);
}
@@ -213,8 +232,10 @@ void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
{
/*
* FIXME: there is no better place to put this at the moment
- * (samsung_wdt_reset_init needs clocks)
+ * (s3c64xx_clk_init needs ioremap and must happen before init_time
+ * samsung_wdt_reset_init needs clocks)
*/
+ s3c64xx_clk_init(NULL, xtal_f, xusbxti_f, soc_is_s3c6400(), S3C_VA_SYS);
samsung_wdt_reset_init(S3C_VA_WATCHDOG);
printk(KERN_DEBUG "%s: initialising interrupts\n", __func__);
@@ -391,6 +412,10 @@ static int __init s3c64xx_init_irq_eint(void)
{
int irq;
+ /* On DT-enabled systems EINTs are handled by pinctrl-s3c64xx driver. */
+ if (of_have_populated_dt())
+ return -ENODEV;
+
for (irq = IRQ_EINT(0); irq <= IRQ_EINT(27); irq++) {
irq_set_chip_and_handler(irq, &s3c_irq_eint, handle_level_irq);
irq_set_chip_data(irq, (void *)eint_irq_to_bit(irq));
diff --git a/arch/arm/mach-s3c64xx/common.h b/arch/arm/mach-s3c64xx/common.h
index e8f990b37665..bd3bd562011e 100644
--- a/arch/arm/mach-s3c64xx/common.h
+++ b/arch/arm/mach-s3c64xx/common.h
@@ -22,21 +22,21 @@
void s3c64xx_init_irq(u32 vic0, u32 vic1);
void s3c64xx_init_io(struct map_desc *mach_desc, int size);
-void s3c64xx_register_clocks(unsigned long xtal, unsigned armclk_limit);
-void s3c64xx_setup_clocks(void);
-
void s3c64xx_restart(enum reboot_mode mode, const char *cmd);
void s3c64xx_init_late(void);
+void s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
+ unsigned long xusbxti_f, bool is_s3c6400, void __iomem *reg_base);
+void s3c64xx_set_xtal_freq(unsigned long freq);
+void s3c64xx_set_xusbxti_freq(unsigned long freq);
+
#ifdef CONFIG_CPU_S3C6400
extern int s3c6400_init(void);
extern void s3c6400_init_irq(void);
extern void s3c6400_map_io(void);
-extern void s3c6400_init_clocks(int xtal);
#else
-#define s3c6400_init_clocks NULL
#define s3c6400_map_io NULL
#define s3c6400_init NULL
#endif
@@ -46,10 +46,8 @@ extern void s3c6400_init_clocks(int xtal);
extern int s3c6410_init(void);
extern void s3c6410_init_irq(void);
extern void s3c6410_map_io(void);
-extern void s3c6410_init_clocks(int xtal);
#else
-#define s3c6410_init_clocks NULL
#define s3c6410_map_io NULL
#define s3c6410_init NULL
#endif
diff --git a/arch/arm/mach-s3c64xx/dma.c b/arch/arm/mach-s3c64xx/dma.c
index 759846c28d12..7e22c2113816 100644
--- a/arch/arm/mach-s3c64xx/dma.c
+++ b/arch/arm/mach-s3c64xx/dma.c
@@ -12,6 +12,10 @@
* published by the Free Software Foundation.
*/
+/*
+ * NOTE: Code in this file is not used when booting with Device Tree support.
+ */
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
@@ -24,6 +28,7 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/amba/pl080.h>
+#include <linux/of.h>
#include <mach/dma.h>
#include <mach/map.h>
@@ -677,7 +682,7 @@ static int s3c64xx_dma_init1(int chno, enum dma_ch chbase,
goto err_map;
}
- clk_enable(dmac->clk);
+ clk_prepare_enable(dmac->clk);
dmac->regs = regs;
dmac->chanbase = chbase;
@@ -711,7 +716,7 @@ static int s3c64xx_dma_init1(int chno, enum dma_ch chbase,
return 0;
err_clk:
- clk_disable(dmac->clk);
+ clk_disable_unprepare(dmac->clk);
clk_put(dmac->clk);
err_map:
iounmap(regs);
@@ -726,6 +731,10 @@ static int __init s3c64xx_dma_init(void)
{
int ret;
+ /* This driver is not supported when booting with device tree. */
+ if (of_have_populated_dt())
+ return -ENODEV;
+
printk(KERN_INFO "%s: Registering DMA channels\n", __func__);
dma_pool = dma_pool_create("DMA-LLI", NULL, sizeof(struct pl080s_lli), 16, 0);
diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-clock.h b/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
index 05332b998ec0..4f44aac77092 100644
--- a/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
+++ b/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
@@ -15,145 +15,21 @@
#ifndef __PLAT_REGS_CLOCK_H
#define __PLAT_REGS_CLOCK_H __FILE__
+/*
+ * FIXME: Remove remaining definitions
+ */
+
#define S3C_CLKREG(x) (S3C_VA_SYS + (x))
-#define S3C_APLL_LOCK S3C_CLKREG(0x00)
-#define S3C_MPLL_LOCK S3C_CLKREG(0x04)
-#define S3C_EPLL_LOCK S3C_CLKREG(0x08)
-#define S3C_APLL_CON S3C_CLKREG(0x0C)
-#define S3C_MPLL_CON S3C_CLKREG(0x10)
-#define S3C_EPLL_CON0 S3C_CLKREG(0x14)
-#define S3C_EPLL_CON1 S3C_CLKREG(0x18)
-#define S3C_CLK_SRC S3C_CLKREG(0x1C)
-#define S3C_CLK_DIV0 S3C_CLKREG(0x20)
-#define S3C_CLK_DIV1 S3C_CLKREG(0x24)
-#define S3C_CLK_DIV2 S3C_CLKREG(0x28)
-#define S3C_CLK_OUT S3C_CLKREG(0x2C)
-#define S3C_HCLK_GATE S3C_CLKREG(0x30)
#define S3C_PCLK_GATE S3C_CLKREG(0x34)
-#define S3C_SCLK_GATE S3C_CLKREG(0x38)
-#define S3C_MEM0_GATE S3C_CLKREG(0x3C)
#define S3C6410_CLK_SRC2 S3C_CLKREG(0x10C)
#define S3C_MEM_SYS_CFG S3C_CLKREG(0x120)
-/* CLKDIV0 */
-#define S3C6400_CLKDIV0_PCLK_MASK (0xf << 12)
-#define S3C6400_CLKDIV0_PCLK_SHIFT (12)
-#define S3C6400_CLKDIV0_HCLK2_MASK (0x7 << 9)
-#define S3C6400_CLKDIV0_HCLK2_SHIFT (9)
-#define S3C6400_CLKDIV0_HCLK_MASK (0x1 << 8)
-#define S3C6400_CLKDIV0_HCLK_SHIFT (8)
-#define S3C6400_CLKDIV0_MPLL_MASK (0x1 << 4)
-#define S3C6400_CLKDIV0_MPLL_SHIFT (4)
-
-#define S3C6400_CLKDIV0_ARM_MASK (0x7 << 0)
-#define S3C6410_CLKDIV0_ARM_MASK (0xf << 0)
-#define S3C6400_CLKDIV0_ARM_SHIFT (0)
-
-/* HCLK GATE Registers */
-#define S3C_CLKCON_HCLK_3DSE (1<<31)
-#define S3C_CLKCON_HCLK_UHOST (1<<29)
-#define S3C_CLKCON_HCLK_SECUR (1<<28)
-#define S3C_CLKCON_HCLK_SDMA1 (1<<27)
-#define S3C_CLKCON_HCLK_SDMA0 (1<<26)
-#define S3C_CLKCON_HCLK_IROM (1<<25)
-#define S3C_CLKCON_HCLK_DDR1 (1<<24)
-#define S3C_CLKCON_HCLK_DDR0 (1<<23)
-#define S3C_CLKCON_HCLK_MEM1 (1<<22)
-#define S3C_CLKCON_HCLK_MEM0 (1<<21)
-#define S3C_CLKCON_HCLK_USB (1<<20)
-#define S3C_CLKCON_HCLK_HSMMC2 (1<<19)
-#define S3C_CLKCON_HCLK_HSMMC1 (1<<18)
-#define S3C_CLKCON_HCLK_HSMMC0 (1<<17)
-#define S3C_CLKCON_HCLK_MDP (1<<16)
-#define S3C_CLKCON_HCLK_DHOST (1<<15)
-#define S3C_CLKCON_HCLK_IHOST (1<<14)
-#define S3C_CLKCON_HCLK_DMA1 (1<<13)
-#define S3C_CLKCON_HCLK_DMA0 (1<<12)
-#define S3C_CLKCON_HCLK_JPEG (1<<11)
-#define S3C_CLKCON_HCLK_CAMIF (1<<10)
-#define S3C_CLKCON_HCLK_SCALER (1<<9)
-#define S3C_CLKCON_HCLK_2D (1<<8)
-#define S3C_CLKCON_HCLK_TV (1<<7)
-#define S3C_CLKCON_HCLK_POST0 (1<<5)
-#define S3C_CLKCON_HCLK_ROT (1<<4)
-#define S3C_CLKCON_HCLK_LCD (1<<3)
-#define S3C_CLKCON_HCLK_TZIC (1<<2)
-#define S3C_CLKCON_HCLK_INTC (1<<1)
-#define S3C_CLKCON_HCLK_MFC (1<<0)
-
/* PCLK GATE Registers */
-#define S3C6410_CLKCON_PCLK_I2C1 (1<<27)
-#define S3C6410_CLKCON_PCLK_IIS2 (1<<26)
-#define S3C_CLKCON_PCLK_SKEY (1<<24)
-#define S3C_CLKCON_PCLK_CHIPID (1<<23)
-#define S3C_CLKCON_PCLK_SPI1 (1<<22)
-#define S3C_CLKCON_PCLK_SPI0 (1<<21)
-#define S3C_CLKCON_PCLK_HSIRX (1<<20)
-#define S3C_CLKCON_PCLK_HSITX (1<<19)
-#define S3C_CLKCON_PCLK_GPIO (1<<18)
-#define S3C_CLKCON_PCLK_IIC (1<<17)
-#define S3C_CLKCON_PCLK_IIS1 (1<<16)
-#define S3C_CLKCON_PCLK_IIS0 (1<<15)
-#define S3C_CLKCON_PCLK_AC97 (1<<14)
-#define S3C_CLKCON_PCLK_TZPC (1<<13)
-#define S3C_CLKCON_PCLK_TSADC (1<<12)
-#define S3C_CLKCON_PCLK_KEYPAD (1<<11)
-#define S3C_CLKCON_PCLK_IRDA (1<<10)
-#define S3C_CLKCON_PCLK_PCM1 (1<<9)
-#define S3C_CLKCON_PCLK_PCM0 (1<<8)
-#define S3C_CLKCON_PCLK_PWM (1<<7)
-#define S3C_CLKCON_PCLK_RTC (1<<6)
-#define S3C_CLKCON_PCLK_WDT (1<<5)
#define S3C_CLKCON_PCLK_UART3 (1<<4)
#define S3C_CLKCON_PCLK_UART2 (1<<3)
#define S3C_CLKCON_PCLK_UART1 (1<<2)
#define S3C_CLKCON_PCLK_UART0 (1<<1)
-#define S3C_CLKCON_PCLK_MFC (1<<0)
-
-/* SCLK GATE Registers */
-#define S3C_CLKCON_SCLK_UHOST (1<<30)
-#define S3C_CLKCON_SCLK_MMC2_48 (1<<29)
-#define S3C_CLKCON_SCLK_MMC1_48 (1<<28)
-#define S3C_CLKCON_SCLK_MMC0_48 (1<<27)
-#define S3C_CLKCON_SCLK_MMC2 (1<<26)
-#define S3C_CLKCON_SCLK_MMC1 (1<<25)
-#define S3C_CLKCON_SCLK_MMC0 (1<<24)
-#define S3C_CLKCON_SCLK_SPI1_48 (1<<23)
-#define S3C_CLKCON_SCLK_SPI0_48 (1<<22)
-#define S3C_CLKCON_SCLK_SPI1 (1<<21)
-#define S3C_CLKCON_SCLK_SPI0 (1<<20)
-#define S3C_CLKCON_SCLK_DAC27 (1<<19)
-#define S3C_CLKCON_SCLK_TV27 (1<<18)
-#define S3C_CLKCON_SCLK_SCALER27 (1<<17)
-#define S3C_CLKCON_SCLK_SCALER (1<<16)
-#define S3C_CLKCON_SCLK_LCD27 (1<<15)
-#define S3C_CLKCON_SCLK_LCD (1<<14)
-#define S3C6400_CLKCON_SCLK_POST1_27 (1<<13)
-#define S3C6410_CLKCON_FIMC (1<<13)
-#define S3C_CLKCON_SCLK_POST0_27 (1<<12)
-#define S3C6400_CLKCON_SCLK_POST1 (1<<11)
-#define S3C6410_CLKCON_SCLK_AUDIO2 (1<<11)
-#define S3C_CLKCON_SCLK_POST0 (1<<10)
-#define S3C_CLKCON_SCLK_AUDIO1 (1<<9)
-#define S3C_CLKCON_SCLK_AUDIO0 (1<<8)
-#define S3C_CLKCON_SCLK_SECUR (1<<7)
-#define S3C_CLKCON_SCLK_IRDA (1<<6)
-#define S3C_CLKCON_SCLK_UART (1<<5)
-#define S3C_CLKCON_SCLK_ONENAND (1<<4)
-#define S3C_CLKCON_SCLK_MFC (1<<3)
-#define S3C_CLKCON_SCLK_CAM (1<<2)
-#define S3C_CLKCON_SCLK_JPEG (1<<1)
-
-/* CLKSRC */
-
-#define S3C6400_CLKSRC_APLL_MOUT (1 << 0)
-#define S3C6400_CLKSRC_MPLL_MOUT (1 << 1)
-#define S3C6400_CLKSRC_EPLL_MOUT (1 << 2)
-#define S3C6400_CLKSRC_APLL_MOUT_SHIFT (0)
-#define S3C6400_CLKSRC_MPLL_MOUT_SHIFT (1)
-#define S3C6400_CLKSRC_EPLL_MOUT_SHIFT (2)
-#define S3C6400_CLKSRC_MFC (1 << 4)
/* MEM_SYS_CFG */
#define MEM_SYS_CFG_INDEP_CF 0x4000
diff --git a/arch/arm/mach-s3c64xx/irq-pm.c b/arch/arm/mach-s3c64xx/irq-pm.c
index c3da1b68d03e..1649c0d1c1b8 100644
--- a/arch/arm/mach-s3c64xx/irq-pm.c
+++ b/arch/arm/mach-s3c64xx/irq-pm.c
@@ -12,12 +12,17 @@
* published by the Free Software Foundation.
*/
+/*
+ * NOTE: Code in this file is not used when booting with Device Tree support.
+ */
+
#include <linux/kernel.h>
#include <linux/syscore_ops.h>
#include <linux/interrupt.h>
#include <linux/serial_core.h>
#include <linux/irq.h>
#include <linux/io.h>
+#include <linux/of.h>
#include <mach/map.h>
@@ -101,6 +106,10 @@ static struct syscore_ops s3c64xx_irq_syscore_ops = {
static __init int s3c64xx_syscore_init(void)
{
+ /* Appropriate drivers (pinctrl, uart) handle this when using DT. */
+ if (of_have_populated_dt())
+ return 0;
+
register_syscore_ops(&s3c64xx_irq_syscore_ops);
return 0;
diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c
index 35e3f54574ef..d266dd5f7060 100644
--- a/arch/arm/mach-s3c64xx/mach-anw6410.c
+++ b/arch/arm/mach-s3c64xx/mach-anw6410.c
@@ -207,7 +207,7 @@ static struct platform_device *anw6410_devices[] __initdata = {
static void __init anw6410_map_io(void)
{
s3c64xx_init_io(anw6410_iodesc, ARRAY_SIZE(anw6410_iodesc));
- s3c24xx_init_clocks(12000000);
+ s3c64xx_set_xtal_freq(12000000);
s3c24xx_init_uarts(anw6410_uartcfgs, ARRAY_SIZE(anw6410_uartcfgs));
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index eb8e5a1aca42..1a911df9e451 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -743,7 +743,7 @@ static struct s3c2410_platform_i2c i2c1_pdata = {
static void __init crag6410_map_io(void)
{
s3c64xx_init_io(NULL, 0);
- s3c24xx_init_clocks(12000000);
+ s3c64xx_set_xtal_freq(12000000);
s3c24xx_init_uarts(crag6410_uartcfgs, ARRAY_SIZE(crag6410_uartcfgs));
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c
index f39569e0f2e6..e8064044ef79 100644
--- a/arch/arm/mach-s3c64xx/mach-hmt.c
+++ b/arch/arm/mach-s3c64xx/mach-hmt.c
@@ -247,7 +247,7 @@ static struct platform_device *hmt_devices[] __initdata = {
static void __init hmt_map_io(void)
{
s3c64xx_init_io(hmt_iodesc, ARRAY_SIZE(hmt_iodesc));
- s3c24xx_init_clocks(12000000);
+ s3c64xx_set_xtal_freq(12000000);
s3c24xx_init_uarts(hmt_uartcfgs, ARRAY_SIZE(hmt_uartcfgs));
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
}
diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c
index fc043e3ecdf8..58d46a3d7b78 100644
--- a/arch/arm/mach-s3c64xx/mach-mini6410.c
+++ b/arch/arm/mach-s3c64xx/mach-mini6410.c
@@ -231,7 +231,7 @@ static void __init mini6410_map_io(void)
u32 tmp;
s3c64xx_init_io(NULL, 0);
- s3c24xx_init_clocks(12000000);
+ s3c64xx_set_xtal_freq(12000000);
s3c24xx_init_uarts(mini6410_uartcfgs, ARRAY_SIZE(mini6410_uartcfgs));
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
diff --git a/arch/arm/mach-s3c64xx/mach-ncp.c b/arch/arm/mach-s3c64xx/mach-ncp.c
index 7e2c3908f1f8..2067b0bf55b4 100644
--- a/arch/arm/mach-s3c64xx/mach-ncp.c
+++ b/arch/arm/mach-s3c64xx/mach-ncp.c
@@ -86,7 +86,7 @@ static struct map_desc ncp_iodesc[] __initdata = {};
static void __init ncp_map_io(void)
{
s3c64xx_init_io(ncp_iodesc, ARRAY_SIZE(ncp_iodesc));
- s3c24xx_init_clocks(12000000);
+ s3c64xx_set_xtal_freq(12000000);
s3c24xx_init_uarts(ncp_uartcfgs, ARRAY_SIZE(ncp_uartcfgs));
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
}
diff --git a/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c b/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c
new file mode 100644
index 000000000000..7eb9a10fc1af
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c
@@ -0,0 +1,85 @@
+/*
+ * Samsung's S3C64XX flattened device tree enabled machine
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@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.
+*/
+
+#include <linux/clk-provider.h>
+#include <linux/irqchip.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/system_misc.h>
+
+#include <plat/cpu.h>
+#include <plat/watchdog-reset.h>
+
+#include <mach/map.h>
+
+#include "common.h"
+
+/*
+ * IO mapping for shared system controller IP.
+ *
+ * FIXME: Make remaining drivers use dynamic mapping.
+ */
+static struct map_desc s3c64xx_dt_iodesc[] __initdata = {
+ {
+ .virtual = (unsigned long)S3C_VA_SYS,
+ .pfn = __phys_to_pfn(S3C64XX_PA_SYSCON),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ },
+};
+
+static void __init s3c64xx_dt_map_io(void)
+{
+ debug_ll_io_init();
+ iotable_init(s3c64xx_dt_iodesc, ARRAY_SIZE(s3c64xx_dt_iodesc));
+
+ s3c64xx_init_cpu();
+
+ if (!soc_is_s3c64xx())
+ panic("SoC is not S3C64xx!");
+}
+
+static void __init s3c64xx_dt_init_irq(void)
+{
+ of_clk_init(NULL);
+ samsung_wdt_reset_of_init();
+ irqchip_init();
+};
+
+static void __init s3c64xx_dt_init_machine(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static void s3c64xx_dt_restart(enum reboot_mode mode, const char *cmd)
+{
+ if (mode != REBOOT_SOFT)
+ samsung_wdt_reset();
+
+ /* if all else fails, or mode was for soft, jump to 0 */
+ soft_restart(0);
+}
+
+static char const *s3c64xx_dt_compat[] __initdata = {
+ "samsung,s3c6400",
+ "samsung,s3c6410",
+ NULL
+};
+
+DT_MACHINE_START(S3C6400_DT, "Samsung S3C64xx (Flattened Device Tree)")
+ /* Maintainer: Tomasz Figa <tomasz.figa@gmail.com> */
+ .dt_compat = s3c64xx_dt_compat,
+ .map_io = s3c64xx_dt_map_io,
+ .init_irq = s3c64xx_dt_init_irq,
+ .init_machine = s3c64xx_dt_init_machine,
+ .restart = s3c64xx_dt_restart,
+MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c
index 86d980b448fd..0f47237be3b2 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq.c
@@ -337,13 +337,6 @@ err:
return ret;
}
-static int __init smartq_usb_otg_init(void)
-{
- clk_xusbxti.rate = 12000000;
-
- return 0;
-}
-
static int __init smartq_wifi_init(void)
{
int ret;
@@ -377,7 +370,8 @@ static struct map_desc smartq_iodesc[] __initdata = {};
void __init smartq_map_io(void)
{
s3c64xx_init_io(smartq_iodesc, ARRAY_SIZE(smartq_iodesc));
- s3c24xx_init_clocks(12000000);
+ s3c64xx_set_xtal_freq(12000000);
+ s3c64xx_set_xusbxti_freq(12000000);
s3c24xx_init_uarts(smartq_uartcfgs, ARRAY_SIZE(smartq_uartcfgs));
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
@@ -399,7 +393,6 @@ void __init smartq_machine_init(void)
WARN_ON(smartq_lcd_setup_gpio());
WARN_ON(smartq_power_off_init());
WARN_ON(smartq_usb_host_init());
- WARN_ON(smartq_usb_otg_init());
WARN_ON(smartq_wifi_init());
platform_add_devices(smartq_devices, ARRAY_SIZE(smartq_devices));
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6400.c b/arch/arm/mach-s3c64xx/mach-smdk6400.c
index d70c0843aea2..27381cfcabbe 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6400.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6400.c
@@ -65,7 +65,7 @@ static struct map_desc smdk6400_iodesc[] = {};
static void __init smdk6400_map_io(void)
{
s3c64xx_init_io(smdk6400_iodesc, ARRAY_SIZE(smdk6400_iodesc));
- s3c24xx_init_clocks(12000000);
+ s3c64xx_set_xtal_freq(12000000);
s3c24xx_init_uarts(smdk6400_uartcfgs, ARRAY_SIZE(smdk6400_uartcfgs));
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
}
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index d90b450c5645..2a7b32ca5c96 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -634,7 +634,7 @@ static void __init smdk6410_map_io(void)
u32 tmp;
s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc));
- s3c24xx_init_clocks(12000000);
+ s3c64xx_set_xtal_freq(12000000);
s3c24xx_init_uarts(smdk6410_uartcfgs, ARRAY_SIZE(smdk6410_uartcfgs));
samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
diff --git a/arch/arm/mach-s3c64xx/pm.c b/arch/arm/mach-s3c64xx/pm.c
index 6a1f91fea678..8cdb824a3b43 100644
--- a/arch/arm/mach-s3c64xx/pm.c
+++ b/arch/arm/mach-s3c64xx/pm.c
@@ -194,29 +194,8 @@ void s3c_pm_debug_smdkled(u32 set, u32 clear)
#endif
static struct sleep_save core_save[] = {
- SAVE_ITEM(S3C_APLL_LOCK),
- SAVE_ITEM(S3C_MPLL_LOCK),
- SAVE_ITEM(S3C_EPLL_LOCK),
- SAVE_ITEM(S3C_CLK_SRC),
- SAVE_ITEM(S3C_CLK_DIV0),
- SAVE_ITEM(S3C_CLK_DIV1),
- SAVE_ITEM(S3C_CLK_DIV2),
- SAVE_ITEM(S3C_CLK_OUT),
- SAVE_ITEM(S3C_HCLK_GATE),
- SAVE_ITEM(S3C_PCLK_GATE),
- SAVE_ITEM(S3C_SCLK_GATE),
- SAVE_ITEM(S3C_MEM0_GATE),
-
- SAVE_ITEM(S3C_EPLL_CON1),
- SAVE_ITEM(S3C_EPLL_CON0),
-
SAVE_ITEM(S3C64XX_MEM0DRVCON),
SAVE_ITEM(S3C64XX_MEM1DRVCON),
-
-#ifndef CONFIG_CPU_FREQ
- SAVE_ITEM(S3C_APLL_CON),
- SAVE_ITEM(S3C_MPLL_CON),
-#endif
};
static struct sleep_save misc_save[] = {
diff --git a/arch/arm/mach-s3c64xx/s3c6400.c b/arch/arm/mach-s3c64xx/s3c6400.c
index 4869714c6f1b..3db0c98222f7 100644
--- a/arch/arm/mach-s3c64xx/s3c6400.c
+++ b/arch/arm/mach-s3c64xx/s3c6400.c
@@ -9,6 +9,10 @@
* published by the Free Software Foundation.
*/
+/*
+ * NOTE: Code in this file is not used when booting with Device Tree support.
+ */
+
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
@@ -20,6 +24,7 @@
#include <linux/device.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
+#include <linux/of.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -58,12 +63,6 @@ void __init s3c6400_map_io(void)
s3c64xx_onenand1_setname("s3c6400-onenand");
}
-void __init s3c6400_init_clocks(int xtal)
-{
- s3c64xx_register_clocks(xtal, S3C6400_CLKDIV0_ARM_MASK);
- s3c64xx_setup_clocks();
-}
-
void __init s3c6400_init_irq(void)
{
/* VIC0 does not have IRQS 5..7,
@@ -82,6 +81,10 @@ static struct device s3c6400_dev = {
static int __init s3c6400_core_init(void)
{
+ /* Not applicable when using DT. */
+ if (of_have_populated_dt())
+ return 0;
+
return subsys_system_register(&s3c6400_subsys, NULL);
}
diff --git a/arch/arm/mach-s3c64xx/s3c6410.c b/arch/arm/mach-s3c64xx/s3c6410.c
index 31c29fdf1800..72b2278953a8 100644
--- a/arch/arm/mach-s3c64xx/s3c6410.c
+++ b/arch/arm/mach-s3c64xx/s3c6410.c
@@ -10,6 +10,10 @@
* published by the Free Software Foundation.
*/
+/*
+ * NOTE: Code in this file is not used when booting with Device Tree support.
+ */
+
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
@@ -21,6 +25,7 @@
#include <linux/device.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
+#include <linux/of.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -62,13 +67,6 @@ void __init s3c6410_map_io(void)
s3c_cfcon_setname("s3c64xx-pata");
}
-void __init s3c6410_init_clocks(int xtal)
-{
- printk(KERN_DEBUG "%s: initialising clocks\n", __func__);
- s3c64xx_register_clocks(xtal, S3C6410_CLKDIV0_ARM_MASK);
- s3c64xx_setup_clocks();
-}
-
void __init s3c6410_init_irq(void)
{
/* VIC0 is missing IRQ7, VIC1 is fully populated. */
@@ -86,6 +84,10 @@ static struct device s3c6410_dev = {
static int __init s3c6410_core_init(void)
{
+ /* Not applicable when using DT. */
+ if (of_have_populated_dt())
+ return 0;
+
return subsys_system_register(&s3c6410_subsys, NULL);
}
diff --git a/arch/arm/mach-shark/Makefile b/arch/arm/mach-shark/Makefile
deleted file mode 100644
index 29657183c452..000000000000
--- a/arch/arm/mach-shark/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y := core.o dma.o irq.o pci.o leds.o
-obj-m :=
-obj-n :=
-obj- :=
diff --git a/arch/arm/mach-shark/Makefile.boot b/arch/arm/mach-shark/Makefile.boot
deleted file mode 100644
index e40e24e4ca34..000000000000
--- a/arch/arm/mach-shark/Makefile.boot
+++ /dev/null
@@ -1,2 +0,0 @@
- zreladdr-y += 0x08008000
-
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
deleted file mode 100644
index 1d32c5e8eab6..000000000000
--- a/arch/arm/mach-shark/core.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * linux/arch/arm/mach-shark/arch.c
- *
- * Architecture specific stuff.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/sched.h>
-#include <linux/serial_8250.h>
-#include <linux/io.h>
-#include <linux/cpu.h>
-#include <linux/reboot.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/param.h>
-#include <asm/system_misc.h>
-
-#include <asm/mach/map.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#define ROMCARD_SIZE 0x08000000
-#define ROMCARD_START 0x10000000
-
-static void shark_restart(enum reboot_mode mode, const char *cmd)
-{
- short temp;
- /* Reset the Machine via pc[3] of the sequoia chipset */
- outw(0x09,0x24);
- temp=inw(0x26);
- temp = temp | (1<<3) | (1<<10);
- outw(0x09,0x24);
- outw(temp,0x26);
-}
-
-static struct plat_serial8250_port serial_platform_data[] = {
- {
- .iobase = 0x3f8,
- .irq = 4,
- .uartclk = 1843200,
- .regshift = 0,
- .iotype = UPIO_PORT,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- },
- {
- .iobase = 0x2f8,
- .irq = 3,
- .uartclk = 1843200,
- .regshift = 0,
- .iotype = UPIO_PORT,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- },
- { },
-};
-
-static struct platform_device serial_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev = {
- .platform_data = serial_platform_data,
- },
-};
-
-static struct resource rtc_resources[] = {
- [0] = {
- .start = 0x70,
- .end = 0x73,
- .flags = IORESOURCE_IO,
- },
- [1] = {
- .start = IRQ_ISA_RTC_ALARM,
- .end = IRQ_ISA_RTC_ALARM,
- .flags = IORESOURCE_IRQ,
- }
-};
-
-static struct platform_device rtc_device = {
- .name = "rtc_cmos",
- .id = -1,
- .resource = rtc_resources,
- .num_resources = ARRAY_SIZE(rtc_resources),
-};
-
-static int __init shark_init(void)
-{
- int ret;
-
- if (machine_is_shark())
- {
- ret = platform_device_register(&rtc_device);
- if (ret) printk(KERN_ERR "Unable to register RTC device: %d\n", ret);
- ret = platform_device_register(&serial_device);
- if (ret) printk(KERN_ERR "Unable to register Serial device: %d\n", ret);
- }
- return 0;
-}
-
-arch_initcall(shark_init);
-
-extern void shark_init_irq(void);
-
-#define IRQ_TIMER 0
-#define HZ_TIME ((1193180 + HZ/2) / HZ)
-
-static irqreturn_t
-shark_timer_interrupt(int irq, void *dev_id)
-{
- timer_tick();
- return IRQ_HANDLED;
-}
-
-static struct irqaction shark_timer_irq = {
- .name = "Shark Timer Tick",
- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
- .handler = shark_timer_interrupt,
-};
-
-/*
- * Set up timer interrupt, and return the current time in seconds.
- */
-static void __init shark_timer_init(void)
-{
- outb(0x34, 0x43); /* binary, mode 0, LSB/MSB, Ch 0 */
- outb(HZ_TIME & 0xff, 0x40); /* LSB of count */
- outb(HZ_TIME >> 8, 0x40);
-
- setup_irq(IRQ_TIMER, &shark_timer_irq);
-}
-
-static void shark_init_early(void)
-{
- cpu_idle_poll_ctrl(true);
-}
-
-MACHINE_START(SHARK, "Shark")
- /* Maintainer: Alexander Schulz */
- .atag_offset = 0x3000,
- .init_early = shark_init_early,
- .init_irq = shark_init_irq,
- .init_time = shark_timer_init,
- .dma_zone_size = SZ_4M,
- .restart = shark_restart,
-MACHINE_END
diff --git a/arch/arm/mach-shark/dma.c b/arch/arm/mach-shark/dma.c
deleted file mode 100644
index 10b5b8b3272a..000000000000
--- a/arch/arm/mach-shark/dma.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-shark/dma.c
- *
- * by Alexander Schulz
- *
- * derived from:
- * arch/arm/kernel/dma-ebsa285.c
- * Copyright (C) 1998 Phil Blundell
- */
-
-#include <linux/init.h>
-
-#include <asm/dma.h>
-#include <asm/mach/dma.h>
-
-static int __init shark_dma_init(void)
-{
-#ifdef CONFIG_ISA_DMA
- isa_init_dma();
-#endif
- return 0;
-}
-core_initcall(shark_dma_init);
diff --git a/arch/arm/mach-shark/include/mach/debug-macro.S b/arch/arm/mach-shark/include/mach/debug-macro.S
deleted file mode 100644
index d129119a3f69..000000000000
--- a/arch/arm/mach-shark/include/mach/debug-macro.S
+++ /dev/null
@@ -1,34 +0,0 @@
-/* arch/arm/mach-shark/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- * Copyright (C) 1994-1999 Russell King
- * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * 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.
- *
-*/
-
- .macro addruart, rp, rv, tmp
- mov \rp, #0x3f8
- orr \rv, \rp, #0xfe000000
- orr \rv, \rv, #0x00e00000
- orr \rp, \rp, #0x40000000
- .endm
-
- .macro senduart,rd,rx
- strb \rd, [\rx]
- .endm
-
- .macro waituart,rd,rx
- .endm
-
- .macro busyuart,rd,rx
- mov \rd, #0
-1001: add \rd, \rd, #1
- teq \rd, #0x10000
- bne 1001b
- .endm
-
diff --git a/arch/arm/mach-shark/include/mach/entry-macro.S b/arch/arm/mach-shark/include/mach/entry-macro.S
deleted file mode 100644
index c9e49f049532..000000000000
--- a/arch/arm/mach-shark/include/mach/entry-macro.S
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * arch/arm/mach-shark/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for Shark platform
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
- .macro get_irqnr_preamble, base, tmp
- mov \base, #0xfe000000
- orr \base, \base, #0x00e00000
- .endm
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-
- mov \irqstat, #0x0C
- strb \irqstat, [\base, #0x20] @outb(0x0C, 0x20) /* Poll command */
- ldrb \irqnr, [\base, #0x20] @irq = inb(0x20) & 7
- and \irqstat, \irqnr, #0x80
- teq \irqstat, #0
- beq 43f
- and \irqnr, \irqnr, #7
- teq \irqnr, #2
- bne 44f
-43: mov \irqstat, #0x0C
- strb \irqstat, [\base, #0xa0] @outb(0x0C, 0xA0) /* Poll command */
- ldrb \irqnr, [\base, #0xa0] @irq = (inb(0xA0) & 7) + 8
- and \irqstat, \irqnr, #0x80
- teq \irqstat, #0
- beq 44f
- and \irqnr, \irqnr, #7
- add \irqnr, \irqnr, #8
-44: teq \irqstat, #0
- .endm
-
diff --git a/arch/arm/mach-shark/include/mach/framebuffer.h b/arch/arm/mach-shark/include/mach/framebuffer.h
deleted file mode 100644
index 84a5bf6e5ba3..000000000000
--- a/arch/arm/mach-shark/include/mach/framebuffer.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * arch/arm/mach-shark/include/mach/framebuffer.h
- *
- * by Alexander Schulz
- *
- */
-
-#ifndef __ASM_ARCH_FRAMEBUFFER_H
-#define __ASM_ARCH_FRAMEBUFFER_H
-
-/* defines for the Framebuffer */
-#define FB_START 0x06000000
-#define FB_SIZE 0x01000000
-
-#endif
-
diff --git a/arch/arm/mach-shark/include/mach/hardware.h b/arch/arm/mach-shark/include/mach/hardware.h
deleted file mode 100644
index 663f952a8ab3..000000000000
--- a/arch/arm/mach-shark/include/mach/hardware.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * arch/arm/mach-shark/include/mach/hardware.h
- *
- * by Alexander Schulz
- *
- * derived from:
- * arch/arm/mach-ebsa110/include/mach/hardware.h
- * Copyright (C) 1996-1999 Russell King.
- */
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#define UNCACHEABLE_ADDR 0xdf010000
-
-#endif
-
diff --git a/arch/arm/mach-shark/include/mach/irqs.h b/arch/arm/mach-shark/include/mach/irqs.h
deleted file mode 100644
index c8e8a4e1f61a..000000000000
--- a/arch/arm/mach-shark/include/mach/irqs.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * arch/arm/mach-shark/include/mach/irqs.h
- *
- * by Alexander Schulz
- */
-
-#define NR_IRQS 16
-
-#define IRQ_ISA_KEYBOARD 1
-#define IRQ_ISA_RTC_ALARM 8
-#define I8042_KBD_IRQ 1
-#define I8042_AUX_IRQ 12
-#define IRQ_HARDDISK 14
diff --git a/arch/arm/mach-shark/include/mach/isa-dma.h b/arch/arm/mach-shark/include/mach/isa-dma.h
deleted file mode 100644
index 96c43b8f8dda..000000000000
--- a/arch/arm/mach-shark/include/mach/isa-dma.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * arch/arm/mach-shark/include/mach/isa-dma.h
- *
- * by Alexander Schulz
- */
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#define MAX_DMA_CHANNELS 8
-#define DMA_ISA_CASCADE 4
-
-#endif /* _ASM_ARCH_DMA_H */
-
diff --git a/arch/arm/mach-shark/include/mach/memory.h b/arch/arm/mach-shark/include/mach/memory.h
deleted file mode 100644
index 1cf8d6962617..000000000000
--- a/arch/arm/mach-shark/include/mach/memory.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * arch/arm/mach-shark/include/mach/memory.h
- *
- * by Alexander Schulz
- *
- * derived from:
- * arch/arm/mach-ebsa110/include/mach/memory.h
- * Copyright (c) 1996-1999 Russell King.
- */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#include <asm/sizes.h>
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET UL(0x08000000)
-
-/*
- * Cache flushing area
- */
-#define FLUSH_BASE_PHYS 0x80000000
-#define FLUSH_BASE 0xdf000000
-
-#endif
diff --git a/arch/arm/mach-shark/include/mach/timex.h b/arch/arm/mach-shark/include/mach/timex.h
deleted file mode 100644
index bb6eeaebed86..000000000000
--- a/arch/arm/mach-shark/include/mach/timex.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * arch/arm/mach-shark/include/mach/timex.h
- *
- * by Alexander Schulz
- */
-
-#define CLOCK_TICK_RATE 1193180
diff --git a/arch/arm/mach-shark/include/mach/uncompress.h b/arch/arm/mach-shark/include/mach/uncompress.h
deleted file mode 100644
index a168435aecc9..000000000000
--- a/arch/arm/mach-shark/include/mach/uncompress.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * arch/arm/mach-shark/include/mach/uncompress.h
- * by Alexander Schulz
- *
- * derived from:
- * arch/arm/mach-footbridge/include/mach/uncompress.h
- * Copyright (C) 1996,1997,1998 Russell King
- */
-
-#define SERIAL_BASE ((volatile unsigned char *)0x400003f8)
-
-static inline void putc(int c)
-{
- volatile int t;
-
- SERIAL_BASE[0] = c;
- t=0x10000;
- while (t--);
-}
-
-static inline void flush(void)
-{
-}
-
-#ifdef DEBUG
-static void putn(unsigned long z)
-{
- int i;
- char x;
-
- putc('0');
- putc('x');
- for (i=0;i<8;i++) {
- x='0'+((z>>((7-i)*4))&0xf);
- if (x>'9') x=x-'0'+'A'-10;
- putc(x);
- }
-}
-
-static void putr()
-{
- putc('\n');
- putc('\r');
-}
-#endif
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
diff --git a/arch/arm/mach-shark/irq.c b/arch/arm/mach-shark/irq.c
deleted file mode 100644
index 5dce13e429f3..000000000000
--- a/arch/arm/mach-shark/irq.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * linux/arch/arm/mach-shark/irq.c
- *
- * by Alexander Schulz
- *
- * derived from linux/arch/ppc/kernel/i8259.c and:
- * arch/arm/mach-ebsa110/include/mach/irq.h
- * Copyright (C) 1996-1998 Russell King
- */
-
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-
-/*
- * 8259A PIC functions to handle ISA devices:
- */
-
-/*
- * This contains the irq mask for both 8259A irq controllers,
- * Let through the cascade-interrupt no. 2 (ff-(1<<2)==fb)
- */
-static unsigned char cached_irq_mask[2] = { 0xfb, 0xff };
-
-/*
- * These have to be protected by the irq controller spinlock
- * before being called.
- */
-static void shark_disable_8259A_irq(struct irq_data *d)
-{
- unsigned int mask;
- if (d->irq<8) {
- mask = 1 << d->irq;
- cached_irq_mask[0] |= mask;
- outb(cached_irq_mask[1],0xA1);
- } else {
- mask = 1 << (d->irq-8);
- cached_irq_mask[1] |= mask;
- outb(cached_irq_mask[0],0x21);
- }
-}
-
-static void shark_enable_8259A_irq(struct irq_data *d)
-{
- unsigned int mask;
- if (d->irq<8) {
- mask = ~(1 << d->irq);
- cached_irq_mask[0] &= mask;
- outb(cached_irq_mask[0],0x21);
- } else {
- mask = ~(1 << (d->irq-8));
- cached_irq_mask[1] &= mask;
- outb(cached_irq_mask[1],0xA1);
- }
-}
-
-static void shark_ack_8259A_irq(struct irq_data *d){}
-
-static irqreturn_t bogus_int(int irq, void *dev_id)
-{
- printk("Got interrupt %i!\n",irq);
- return IRQ_NONE;
-}
-
-static struct irqaction cascade;
-
-static struct irq_chip fb_chip = {
- .name = "XT-PIC",
- .irq_ack = shark_ack_8259A_irq,
- .irq_mask = shark_disable_8259A_irq,
- .irq_unmask = shark_enable_8259A_irq,
-};
-
-void __init shark_init_irq(void)
-{
- int irq;
-
- for (irq = 0; irq < NR_IRQS; irq++) {
- irq_set_chip_and_handler(irq, &fb_chip, handle_edge_irq);
- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
- }
-
- /* init master interrupt controller */
- outb(0x11, 0x20); /* Start init sequence, edge triggered (level: 0x19)*/
- outb(0x00, 0x21); /* Vector base */
- outb(0x04, 0x21); /* Cascade (slave) on IRQ2 */
- outb(0x03, 0x21); /* Select 8086 mode , auto eoi*/
- outb(0x0A, 0x20);
- /* init slave interrupt controller */
- outb(0x11, 0xA0); /* Start init sequence, edge triggered */
- outb(0x08, 0xA1); /* Vector base */
- outb(0x02, 0xA1); /* Cascade (slave) on IRQ2 */
- outb(0x03, 0xA1); /* Select 8086 mode, auto eoi */
- outb(0x0A, 0xA0);
- outb(cached_irq_mask[1],0xA1);
- outb(cached_irq_mask[0],0x21);
- //request_region(0x20,0x2,"pic1");
- //request_region(0xA0,0x2,"pic2");
-
- cascade.handler = bogus_int;
- cascade.name = "cascade";
- setup_irq(2,&cascade);
-}
-
diff --git a/arch/arm/mach-shark/leds.c b/arch/arm/mach-shark/leds.c
deleted file mode 100644
index 081c778a10ac..000000000000
--- a/arch/arm/mach-shark/leds.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * DIGITAL Shark LED control routines.
- *
- * Driver for the 3 user LEDs found on the Shark
- * Based on Versatile and RealView machine LED code
- *
- * License terms: GNU General Public License (GPL) version 2
- * Author: Bryan Wu <bryan.wu@canonical.com>
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/leds.h>
-
-#include <asm/mach-types.h>
-
-#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
-struct shark_led {
- struct led_classdev cdev;
- u8 mask;
-};
-
-/*
- * The triggers lines up below will only be used if the
- * LED triggers are compiled in.
- */
-static const struct {
- const char *name;
- const char *trigger;
-} shark_leds[] = {
- { "shark:amber0", "default-on", }, /* Bit 5 */
- { "shark:green", "heartbeat", }, /* Bit 6 */
- { "shark:amber1", "cpu0" }, /* Bit 7 */
-};
-
-static u16 led_reg_read(void)
-{
- outw(0x09, 0x24);
- return inw(0x26);
-}
-
-static void led_reg_write(u16 value)
-{
- outw(0x09, 0x24);
- outw(value, 0x26);
-}
-
-static void shark_led_set(struct led_classdev *cdev,
- enum led_brightness b)
-{
- struct shark_led *led = container_of(cdev,
- struct shark_led, cdev);
- u16 reg = led_reg_read();
-
- if (b != LED_OFF)
- reg |= led->mask;
- else
- reg &= ~led->mask;
-
- led_reg_write(reg);
-}
-
-static enum led_brightness shark_led_get(struct led_classdev *cdev)
-{
- struct shark_led *led = container_of(cdev,
- struct shark_led, cdev);
- u16 reg = led_reg_read();
-
- return (reg & led->mask) ? LED_FULL : LED_OFF;
-}
-
-static int __init shark_leds_init(void)
-{
- int i;
- u16 reg;
-
- if (!machine_is_shark())
- return -ENODEV;
-
- for (i = 0; i < ARRAY_SIZE(shark_leds); i++) {
- struct shark_led *led;
-
- led = kzalloc(sizeof(*led), GFP_KERNEL);
- if (!led)
- break;
-
- led->cdev.name = shark_leds[i].name;
- led->cdev.brightness_set = shark_led_set;
- led->cdev.brightness_get = shark_led_get;
- led->cdev.default_trigger = shark_leds[i].trigger;
-
- /* Count in 5 bits offset */
- led->mask = BIT(i + 5);
-
- if (led_classdev_register(NULL, &led->cdev) < 0) {
- kfree(led);
- break;
- }
- }
-
- /* Make LEDs independent of power-state */
- request_region(0x24, 4, "led_reg");
- reg = led_reg_read();
- reg |= 1 << 10;
- led_reg_write(reg);
-
- return 0;
-}
-
-/*
- * Since we may have triggers on any subsystem, defer registration
- * until after subsystem_init.
- */
-fs_initcall(shark_leds_init);
-#endif
diff --git a/arch/arm/mach-shark/pci.c b/arch/arm/mach-shark/pci.c
deleted file mode 100644
index 6d91a914c1dd..000000000000
--- a/arch/arm/mach-shark/pci.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * linux/arch/arm/mach-shark/pci.c
- *
- * PCI bios-type initialisation for PCI machines
- *
- * Bits taken from various places.
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <video/vga.h>
-
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-
-#define IO_START 0x40000000
-
-static int __init shark_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- if (dev->bus->number == 0)
- if (dev->devfn == 0)
- return 255;
- else
- return 11;
- else
- return 255;
-}
-
-extern void __init via82c505_preinit(void);
-
-static struct hw_pci shark_pci __initdata = {
- .setup = via82c505_setup,
- .map_irq = shark_map_irq,
- .nr_controllers = 1,
- .ops = &via82c505_ops,
- .preinit = via82c505_preinit,
-};
-
-static int __init shark_pci_init(void)
-{
- if (!machine_is_shark())
- return -ENODEV;
-
- pcibios_min_io = 0x6000;
- pcibios_min_mem = 0x50000000;
- vga_base = 0xe8000000;
-
- pci_ioremap_io(0, IO_START);
-
- pci_common_init(&shark_pci);
-
- return 0;
-}
-
-subsys_initcall(shark_pci_init);
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 1f94c310c477..eda285794961 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -101,6 +101,12 @@ config ARCH_R8A7790
select SH_CLK_CPG
select RENESAS_IRQC
+config ARCH_R8A7791
+ bool "R-Car M2 (R8A77910)"
+ select ARM_GIC
+ select CPU_V7
+ select SH_CLK_CPG
+
config ARCH_EMEV2
bool "Emma Mobile EV2"
select ARCH_WANT_OPTIONAL_GPIOLIB
@@ -162,6 +168,8 @@ config MACH_BOCKW
select RENESAS_INTC_IRQPIN
select REGULATOR_FIXED_VOLTAGE if REGULATOR
select USE_OF
+ select SND_SOC_AK4554 if SND_SIMPLE_CARD
+ select SND_SOC_AK4642 if SND_SIMPLE_CARD
config MACH_BOCKW_REFERENCE
bool "BOCK-W - Reference Device Tree Implementation"
@@ -213,6 +221,11 @@ config MACH_LAGER_REFERENCE
This is intended to aid developers
+config MACH_KOELSCH
+ bool "Koelsch board"
+ depends on ARCH_R8A7791
+ select USE_OF
+
config MACH_KZM9D
bool "KZM9D board"
depends on ARCH_EMEV2
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index 2705bfa8c113..f8f699212984 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_ARCH_R8A7740) += setup-r8a7740.o
obj-$(CONFIG_ARCH_R8A7778) += setup-r8a7778.o
obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o
obj-$(CONFIG_ARCH_R8A7790) += setup-r8a7790.o
+obj-$(CONFIG_ARCH_R8A7791) += setup-r8a7791.o
obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o
# Clock objects
@@ -27,6 +28,7 @@ obj-$(CONFIG_ARCH_R8A7740) += clock-r8a7740.o
obj-$(CONFIG_ARCH_R8A7778) += clock-r8a7778.o
obj-$(CONFIG_ARCH_R8A7779) += clock-r8a7779.o
obj-$(CONFIG_ARCH_R8A7790) += clock-r8a7790.o
+obj-$(CONFIG_ARCH_R8A7791) += clock-r8a7791.o
obj-$(CONFIG_ARCH_EMEV2) += clock-emev2.o
endif
@@ -34,6 +36,7 @@ endif
smp-y := platsmp.o headsmp.o
smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-scu.o platsmp-scu.o
smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o headsmp-scu.o platsmp-scu.o
+smp-$(CONFIG_ARCH_R8A7790) += smp-r8a7790.o platsmp-apmu.o
smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o
# IRQ objects
@@ -59,6 +62,7 @@ obj-$(CONFIG_MACH_LAGER) += board-lager.o
obj-$(CONFIG_MACH_LAGER_REFERENCE) += board-lager-reference.o
obj-$(CONFIG_MACH_ARMADILLO800EVA) += board-armadillo800eva.o
obj-$(CONFIG_MACH_ARMADILLO800EVA_REFERENCE) += board-armadillo800eva-reference.o
+obj-$(CONFIG_MACH_KOELSCH) += board-koelsch.o
obj-$(CONFIG_MACH_KZM9D) += board-kzm9d.o
obj-$(CONFIG_MACH_KZM9D_REFERENCE) += board-kzm9d-reference.o
obj-$(CONFIG_MACH_KZM9G) += board-kzm9g.o
diff --git a/arch/arm/mach-shmobile/Makefile.boot b/arch/arm/mach-shmobile/Makefile.boot
index 6a504fe7d86c..60e29e6c1126 100644
--- a/arch/arm/mach-shmobile/Makefile.boot
+++ b/arch/arm/mach-shmobile/Makefile.boot
@@ -6,6 +6,7 @@ loadaddr-$(CONFIG_MACH_ARMADILLO800EVA) += 0x40008000
loadaddr-$(CONFIG_MACH_ARMADILLO800EVA_REFERENCE) += 0x40008000
loadaddr-$(CONFIG_MACH_BOCKW) += 0x60008000
loadaddr-$(CONFIG_MACH_BOCKW_REFERENCE) += 0x60008000
+loadaddr-$(CONFIG_MACH_KOELSCH) += 0x40008000
loadaddr-$(CONFIG_MACH_KZM9D) += 0x40008000
loadaddr-$(CONFIG_MACH_KZM9D_REFERENCE) += 0x40008000
loadaddr-$(CONFIG_MACH_KZM9G) += 0x41008000
diff --git a/arch/arm/mach-shmobile/board-ape6evm-reference.c b/arch/arm/mach-shmobile/board-ape6evm-reference.c
index a23fa714f7ac..3276afcf3cc9 100644
--- a/arch/arm/mach-shmobile/board-ape6evm-reference.c
+++ b/arch/arm/mach-shmobile/board-ape6evm-reference.c
@@ -57,7 +57,7 @@ static const char *ape6evm_boards_compat_dt[] __initdata = {
};
DT_MACHINE_START(APE6EVM_DT, "ape6evm")
- .init_early = r8a73a4_init_delay,
+ .init_early = r8a73a4_init_early,
.init_machine = ape6evm_add_standard_devices,
.dt_compat = ape6evm_boards_compat_dt,
MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-ape6evm.c b/arch/arm/mach-shmobile/board-ape6evm.c
index 24b87eea9da3..7627385f516e 100644
--- a/arch/arm/mach-shmobile/board-ape6evm.c
+++ b/arch/arm/mach-shmobile/board-ape6evm.c
@@ -113,22 +113,56 @@ static const struct smsc911x_platform_config lan9220_data __initconst = {
};
/*
- * On APE6EVM power is supplied to MMCIF by a tps80032 regulator. For now we
- * model a VDD supply to MMCIF, using a fixed 3.3V regulator. Also use the
- * static power supply for SDHI0 and SDHI1, whereas SDHI0's VccQ is also
- * supplied by the same tps80032 regulator and thus can also be adjusted
- * dynamically.
+ * MMC0 power supplies:
+ * Both Vcc and VccQ to eMMC on APE6EVM are supplied by a tps80032 voltage
+ * regulator. Until support for it is added to this file we simulate the
+ * Vcc supply by a fixed always-on regulator
*/
-static struct regulator_consumer_supply fixed3v3_power_consumers[] =
+static struct regulator_consumer_supply vcc_mmc0_consumers[] =
{
REGULATOR_SUPPLY("vmmc", "sh_mmcif.0"),
+};
+
+/*
+ * SDHI0 power supplies:
+ * Vcc to SDHI0 on APE6EVM is supplied by a GPIO-switchable regulator. VccQ is
+ * provided by the same tps80032 regulator as both MMC0 voltages - see comment
+ * above
+ */
+static struct regulator_consumer_supply vcc_sdhi0_consumers[] =
+{
REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
+};
+
+static struct regulator_init_data vcc_sdhi0_init_data = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(vcc_sdhi0_consumers),
+ .consumer_supplies = vcc_sdhi0_consumers,
+};
+
+static const struct fixed_voltage_config vcc_sdhi0_info __initconst = {
+ .supply_name = "SDHI0 Vcc",
+ .microvolts = 3300000,
+ .gpio = 76,
+ .enable_high = 1,
+ .init_data = &vcc_sdhi0_init_data,
+};
+
+/*
+ * SDHI1 power supplies:
+ * Vcc and VccQ to SDHI1 on APE6EVM are both fixed at 3.3V
+ */
+static struct regulator_consumer_supply vcc_sdhi1_consumers[] =
+{
REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"),
};
/* MMCIF */
static const struct sh_mmcif_plat_data mmcif0_pdata __initconst = {
.caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
+ .ccs_unsupported = true,
};
static const struct resource mmcif0_resources[] __initconst = {
@@ -215,14 +249,19 @@ static void __init ape6evm_add_standard_devices(void)
platform_device_register_resndata(&platform_bus, "smsc911x", -1,
lan9220_res, ARRAY_SIZE(lan9220_res),
&lan9220_data, sizeof(lan9220_data));
- regulator_register_always_on(1, "fixed-3.3V", fixed3v3_power_consumers,
- ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
+
+ regulator_register_always_on(1, "MMC0 Vcc", vcc_mmc0_consumers,
+ ARRAY_SIZE(vcc_mmc0_consumers), 2800000);
platform_device_register_resndata(&platform_bus, "sh_mmcif", 0,
mmcif0_resources, ARRAY_SIZE(mmcif0_resources),
&mmcif0_pdata, sizeof(mmcif0_pdata));
+ platform_device_register_data(&platform_bus, "reg-fixed-voltage", 2,
+ &vcc_sdhi0_info, sizeof(vcc_sdhi0_info));
platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 0,
sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
&sdhi0_pdata, sizeof(sdhi0_pdata));
+ regulator_register_always_on(3, "SDHI1 Vcc", vcc_sdhi1_consumers,
+ ARRAY_SIZE(vcc_sdhi1_consumers), 3300000);
platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 1,
sdhi1_resources, ARRAY_SIZE(sdhi1_resources),
&sdhi1_pdata, sizeof(sdhi1_pdata));
@@ -240,7 +279,7 @@ static const char *ape6evm_boards_compat_dt[] __initdata = {
};
DT_MACHINE_START(APE6EVM_DT, "ape6evm")
- .init_early = r8a73a4_init_delay,
+ .init_early = r8a73a4_init_early,
.init_machine = ape6evm_add_standard_devices,
.dt_compat = ape6evm_boards_compat_dt,
MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index 5bd1479d3deb..8bc8e4c58847 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -823,6 +823,7 @@ static struct sh_mmcif_plat_data sh_mmcif_plat = {
.caps = MMC_CAP_4_BIT_DATA |
MMC_CAP_8_BIT_DATA |
MMC_CAP_NONREMOVABLE,
+ .ccs_unsupported = true,
.slave_id_tx = SHDMA_SLAVE_MMCIF_TX,
.slave_id_rx = SHDMA_SLAVE_MMCIF_RX,
};
@@ -1108,9 +1109,9 @@ static const struct pinctrl_map eva_pinctrl_map[] = {
PIN_MAP_MUX_GROUP_DEFAULT("asoc-simple-card.1", "pfc-r8a7740",
"fsib_mclk_in", "fsib"),
/* GETHER */
- PIN_MAP_MUX_GROUP_DEFAULT("sh-eth", "pfc-r8a7740",
+ PIN_MAP_MUX_GROUP_DEFAULT("r8a7740-gether", "pfc-r8a7740",
"gether_mii", "gether"),
- PIN_MAP_MUX_GROUP_DEFAULT("sh-eth", "pfc-r8a7740",
+ PIN_MAP_MUX_GROUP_DEFAULT("r8a7740-gether", "pfc-r8a7740",
"gether_int", "gether"),
/* HDMI */
PIN_MAP_MUX_GROUP_DEFAULT("sh-mobile-hdmi", "pfc-r8a7740",
diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c
index 6b9faf3908f7..330e84c14f8e 100644
--- a/arch/arm/mach-shmobile/board-bockw.c
+++ b/arch/arm/mach-shmobile/board-bockw.c
@@ -32,11 +32,19 @@
#include <linux/smsc911x.h>
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
+#include <linux/usb/renesas_usbhs.h>
#include <media/soc_camera.h>
#include <mach/common.h>
#include <mach/irqs.h>
#include <mach/r8a7778.h>
#include <asm/mach/arch.h>
+#include <sound/rcar_snd.h>
+#include <sound/simple_card.h>
+
+#define FPGA 0x18200000
+#define IRQ0MR 0x30
+#define COMCTLR 0x101c
+static void __iomem *fpga;
/*
* CN9(Upper side) SCIF/RCAN selection
@@ -63,6 +71,45 @@
* SW19 (MMC) 1 pin
*/
+/*
+ * SSI settings
+ *
+ * SW45: 1-4 side (SSI5 out, ROUT/LOUT CN19 Mid)
+ * SW46: 1101 (SSI6 Recorde)
+ * SW47: 1110 (SSI5 Playback)
+ * SW48: 11 (Recorde power)
+ * SW49: 1 (SSI slave mode)
+ * SW50: 1111 (SSI7, SSI8)
+ * SW51: 1111 (SSI3, SSI4)
+ * SW54: 1pin (ak4554 FPGA control)
+ * SW55: 1 (CLKB is 24.5760MHz)
+ * SW60: 1pin (ak4554 FPGA control)
+ * SW61: 3pin (use X11 clock)
+ * SW78: 3-6 (ak4642 connects I2C0)
+ *
+ * You can use sound as
+ *
+ * hw0: CN19: SSI56-AK4643
+ * hw1: CN21: SSI3-AK4554(playback)
+ * hw2: CN21: SSI4-AK4554(capture)
+ * hw3: CN20: SSI7-AK4554(playback)
+ * hw4: CN20: SSI8-AK4554(capture)
+ *
+ * this command is required when playback on hw0.
+ *
+ * # amixer set "LINEOUT Mixer DACL" on
+ */
+
+/*
+ * USB
+ *
+ * USB1 (CN29) can be Host/Function
+ *
+ * Host Func
+ * SW98 1 2
+ * SW99 1 3
+ */
+
/* Dummy supplies, where voltage doesn't matter */
static struct regulator_consumer_supply dummy_supplies[] = {
REGULATOR_SUPPLY("vddvario", "smsc911x"),
@@ -81,13 +128,71 @@ static struct resource smsc911x_resources[] __initdata = {
DEFINE_RES_IRQ(irq_pin(0)), /* IRQ 0 */
};
+#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC)
+/*
+ * When USB1 is Func
+ */
+static int usbhsf_get_id(struct platform_device *pdev)
+{
+ return USBHS_GADGET;
+}
+
+#define SUSPMODE 0x102
+static int usbhsf_power_ctrl(struct platform_device *pdev,
+ void __iomem *base, int enable)
+{
+ enable = !!enable;
+
+ r8a7778_usb_phy_power(enable);
+
+ iowrite16(enable << 14, base + SUSPMODE);
+
+ return 0;
+}
+
+static struct resource usbhsf_resources[] __initdata = {
+ DEFINE_RES_MEM(0xffe60000, 0x110),
+ DEFINE_RES_IRQ(gic_iid(0x4f)),
+};
+
+static struct renesas_usbhs_platform_info usbhs_info __initdata = {
+ .platform_callback = {
+ .get_id = usbhsf_get_id,
+ .power_ctrl = usbhsf_power_ctrl,
+ },
+ .driver_param = {
+ .buswait_bwait = 4,
+ },
+};
+
+#define USB_PHY_SETTING {.port1_func = 1, .ovc_pin[1].active_high = 1,}
+#define USB1_DEVICE "renesas_usbhs"
+#define ADD_USB_FUNC_DEVICE_IF_POSSIBLE() \
+ platform_device_register_resndata( \
+ &platform_bus, "renesas_usbhs", -1, \
+ usbhsf_resources, \
+ ARRAY_SIZE(usbhsf_resources), \
+ &usbhs_info, sizeof(struct renesas_usbhs_platform_info))
+
+#else
+/*
+ * When USB1 is Host
+ */
+#define USB_PHY_SETTING { }
+#define USB1_DEVICE "ehci-platform"
+#define ADD_USB_FUNC_DEVICE_IF_POSSIBLE()
+
+#endif
+
/* USB */
static struct resource usb_phy_resources[] __initdata = {
DEFINE_RES_MEM(0xffe70800, 0x100),
DEFINE_RES_MEM(0xffe76000, 0x100),
};
-static struct rcar_phy_platform_data usb_phy_platform_data __initdata;
+static struct rcar_phy_platform_data usb_phy_platform_data __initdata =
+ USB_PHY_SETTING;
+
/* SDHI */
static struct sh_mobile_sdhi_info sdhi0_info __initdata = {
@@ -118,7 +223,9 @@ static struct sh_eth_plat_data ether_platform_data __initdata = {
static struct i2c_board_info i2c0_devices[] = {
{
I2C_BOARD_INFO("rx8581", 0x51),
- },
+ }, {
+ I2C_BOARD_INFO("ak4643", 0x12),
+ }
};
/* HSPI*/
@@ -181,7 +288,213 @@ static struct soc_camera_link iclink##idx##_ml86v7667 __initdata = { \
BOCKW_CAMERA(0);
BOCKW_CAMERA(1);
+/* Sound */
+static struct resource rsnd_resources[] __initdata = {
+ [RSND_GEN1_SRU] = DEFINE_RES_MEM(0xffd90000, 0x1000),
+ [RSND_GEN1_SSI] = DEFINE_RES_MEM(0xffd91000, 0x1240),
+ [RSND_GEN1_ADG] = DEFINE_RES_MEM(0xfffe0000, 0x24),
+};
+
+static struct rsnd_ssi_platform_info rsnd_ssi[] = {
+ RSND_SSI_UNUSED, /* SSI 0 */
+ RSND_SSI_UNUSED, /* SSI 1 */
+ RSND_SSI_UNUSED, /* SSI 2 */
+ RSND_SSI_SET(1, 0, gic_iid(0x85), RSND_SSI_PLAY),
+ RSND_SSI_SET(2, 0, gic_iid(0x85), RSND_SSI_CLK_PIN_SHARE | RSND_SSI_CLK_FROM_ADG),
+ RSND_SSI_SET(0, 0, gic_iid(0x86), RSND_SSI_PLAY),
+ RSND_SSI_SET(0, 0, gic_iid(0x86), 0),
+ RSND_SSI_SET(3, 0, gic_iid(0x86), RSND_SSI_PLAY),
+ RSND_SSI_SET(4, 0, gic_iid(0x86), RSND_SSI_CLK_PIN_SHARE | RSND_SSI_CLK_FROM_ADG),
+};
+
+static struct rsnd_scu_platform_info rsnd_scu[9] = {
+ /* no member at this point */
+};
+
+enum {
+ AK4554_34 = 0,
+ AK4643_56,
+ AK4554_78,
+ SOUND_MAX,
+};
+
+static int rsnd_codec_power(int id, int enable)
+{
+ static int sound_user[SOUND_MAX] = {0, 0, 0};
+ int *usr = NULL;
+ u32 bit;
+
+ switch (id) {
+ case 3:
+ case 4:
+ usr = sound_user + AK4554_34;
+ bit = (1 << 10);
+ break;
+ case 5:
+ case 6:
+ usr = sound_user + AK4643_56;
+ bit = (1 << 6);
+ break;
+ case 7:
+ case 8:
+ usr = sound_user + AK4554_78;
+ bit = (1 << 7);
+ break;
+ }
+
+ if (!usr)
+ return -EIO;
+
+ if (enable) {
+ if (*usr == 0) {
+ u32 val = ioread16(fpga + COMCTLR);
+ val &= ~bit;
+ iowrite16(val, fpga + COMCTLR);
+ }
+
+ (*usr)++;
+ } else {
+ if (*usr == 0)
+ return 0;
+
+ (*usr)--;
+
+ if (*usr == 0) {
+ u32 val = ioread16(fpga + COMCTLR);
+ val |= bit;
+ iowrite16(val, fpga + COMCTLR);
+ }
+ }
+
+ return 0;
+}
+
+static int rsnd_start(int id)
+{
+ return rsnd_codec_power(id, 1);
+}
+
+static int rsnd_stop(int id)
+{
+ return rsnd_codec_power(id, 0);
+}
+
+static struct rcar_snd_info rsnd_info = {
+ .flags = RSND_GEN1,
+ .ssi_info = rsnd_ssi,
+ .ssi_info_nr = ARRAY_SIZE(rsnd_ssi),
+ .scu_info = rsnd_scu,
+ .scu_info_nr = ARRAY_SIZE(rsnd_scu),
+ .start = rsnd_start,
+ .stop = rsnd_stop,
+};
+
+static struct asoc_simple_card_info rsnd_card_info[] = {
+ /* SSI5, SSI6 */
+ {
+ .name = "AK4643",
+ .card = "SSI56-AK4643",
+ .codec = "ak4642-codec.0-0012",
+ .platform = "rcar_sound",
+ .daifmt = SND_SOC_DAIFMT_LEFT_J,
+ .cpu_dai = {
+ .name = "rsnd-dai.0",
+ .fmt = SND_SOC_DAIFMT_CBS_CFS,
+ },
+ .codec_dai = {
+ .name = "ak4642-hifi",
+ .fmt = SND_SOC_DAIFMT_CBM_CFM,
+ .sysclk = 11289600,
+ },
+ },
+ /* SSI3 */
+ {
+ .name = "AK4554",
+ .card = "SSI3-AK4554(playback)",
+ .codec = "ak4554-adc-dac.0",
+ .platform = "rcar_sound",
+ .cpu_dai = {
+ .name = "rsnd-dai.1",
+ .fmt = SND_SOC_DAIFMT_CBM_CFM |
+ SND_SOC_DAIFMT_RIGHT_J,
+ },
+ .codec_dai = {
+ .name = "ak4554-hifi",
+ },
+ },
+ /* SSI4 */
+ {
+ .name = "AK4554",
+ .card = "SSI4-AK4554(capture)",
+ .codec = "ak4554-adc-dac.0",
+ .platform = "rcar_sound",
+ .cpu_dai = {
+ .name = "rsnd-dai.2",
+ .fmt = SND_SOC_DAIFMT_CBM_CFM |
+ SND_SOC_DAIFMT_LEFT_J,
+ },
+ .codec_dai = {
+ .name = "ak4554-hifi",
+ },
+ },
+ /* SSI7 */
+ {
+ .name = "AK4554",
+ .card = "SSI7-AK4554(playback)",
+ .codec = "ak4554-adc-dac.1",
+ .platform = "rcar_sound",
+ .cpu_dai = {
+ .name = "rsnd-dai.3",
+ .fmt = SND_SOC_DAIFMT_CBM_CFM |
+ SND_SOC_DAIFMT_RIGHT_J,
+ },
+ .codec_dai = {
+ .name = "ak4554-hifi",
+ },
+ },
+ /* SSI8 */
+ {
+ .name = "AK4554",
+ .card = "SSI8-AK4554(capture)",
+ .codec = "ak4554-adc-dac.1",
+ .platform = "rcar_sound",
+ .cpu_dai = {
+ .name = "rsnd-dai.4",
+ .fmt = SND_SOC_DAIFMT_CBM_CFM |
+ SND_SOC_DAIFMT_LEFT_J,
+ },
+ .codec_dai = {
+ .name = "ak4554-hifi",
+ },
+ }
+};
+
static const struct pinctrl_map bockw_pinctrl_map[] = {
+ /* AUDIO */
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "audio_clk_a", "audio_clk"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "audio_clk_b", "audio_clk"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi34_ctrl", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi3_data", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi4_data", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi5_ctrl", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi5_data", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi6_ctrl", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi6_data", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi78_ctrl", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi7_data", "ssi"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+ "ssi8_data", "ssi"),
/* Ether */
PIN_MAP_MUX_GROUP_DEFAULT("r8a777x-ether", "pfc-r8a7778",
"ether_rmii", "ether"),
@@ -201,7 +514,7 @@ static const struct pinctrl_map bockw_pinctrl_map[] = {
/* USB */
PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform", "pfc-r8a7778",
"usb0", "usb0"),
- PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform", "pfc-r8a7778",
+ PIN_MAP_MUX_GROUP_DEFAULT(USB1_DEVICE, "pfc-r8a7778",
"usb1", "usb1"),
/* SDHI0 */
PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778",
@@ -224,13 +537,13 @@ static const struct pinctrl_map bockw_pinctrl_map[] = {
"vin1_data8", "vin1"),
};
-#define FPGA 0x18200000
-#define IRQ0MR 0x30
#define PFC 0xfffc0000
#define PUPR4 0x110
static void __init bockw_init(void)
{
void __iomem *base;
+ struct clk *clk;
+ int i;
r8a7778_clock_init();
r8a7778_init_irq_extpin(1);
@@ -269,8 +582,8 @@ static void __init bockw_init(void)
/* for SMSC */
- base = ioremap_nocache(FPGA, SZ_1M);
- if (base) {
+ fpga = ioremap_nocache(FPGA, SZ_1M);
+ if (fpga) {
/*
* CAUTION
*
@@ -278,10 +591,9 @@ static void __init bockw_init(void)
* it should be cared in the future
* Now, it is assuming IRQ0 was used only from SMSC.
*/
- u16 val = ioread16(base + IRQ0MR);
+ u16 val = ioread16(fpga + IRQ0MR);
val &= ~(1 << 4); /* enable SMSC911x */
- iowrite16(val, base + IRQ0MR);
- iounmap(base);
+ iowrite16(val, fpga + IRQ0MR);
regulator_register_fixed(0, dummy_supplies,
ARRAY_SIZE(dummy_supplies));
@@ -308,6 +620,42 @@ static void __init bockw_init(void)
sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
&sdhi0_info, sizeof(struct sh_mobile_sdhi_info));
}
+
+ /* for Audio */
+ clk = clk_get(NULL, "audio_clk_b");
+ clk_set_rate(clk, 24576000);
+ clk_put(clk);
+ rsnd_codec_power(5, 1); /* enable ak4642 */
+
+ platform_device_register_simple(
+ "ak4554-adc-dac", 0, NULL, 0);
+
+ platform_device_register_simple(
+ "ak4554-adc-dac", 1, NULL, 0);
+
+ platform_device_register_resndata(
+ &platform_bus, "rcar_sound", -1,
+ rsnd_resources, ARRAY_SIZE(rsnd_resources),
+ &rsnd_info, sizeof(rsnd_info));
+
+ for (i = 0; i < ARRAY_SIZE(rsnd_card_info); i++) {
+ struct platform_device_info cardinfo = {
+ .parent = &platform_bus,
+ .name = "asoc-simple-card",
+ .id = i,
+ .data = &rsnd_card_info[i],
+ .size_data = sizeof(struct asoc_simple_card_info),
+ .dma_mask = ~0,
+ };
+
+ platform_device_register_full(&cardinfo);
+ }
+}
+
+static void __init bockw_init_late(void)
+{
+ r8a7778_init_late();
+ ADD_USB_FUNC_DEVICE_IF_POSSIBLE();
}
static const char *bockw_boards_compat_dt[] __initdata = {
@@ -320,5 +668,5 @@ DT_MACHINE_START(BOCKW_DT, "bockw")
.init_irq = r8a7778_init_irq_dt,
.init_machine = bockw_init,
.dt_compat = bockw_boards_compat_dt,
- .init_late = r8a7778_init_late,
+ .init_late = bockw_init_late,
MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-koelsch.c b/arch/arm/mach-shmobile/board-koelsch.c
new file mode 100644
index 000000000000..cc2d5e82b59a
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-koelsch.c
@@ -0,0 +1,44 @@
+/*
+ * Koelsch board support
+ *
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * 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 of the License.
+ *
+ * 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/kernel.h>
+#include <linux/platform_device.h>
+#include <mach/common.h>
+#include <mach/r8a7791.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static void __init koelsch_add_standard_devices(void)
+{
+ r8a7791_clock_init();
+ r8a7791_add_dt_devices();
+}
+
+static const char * const koelsch_boards_compat_dt[] __initconst = {
+ "renesas,koelsch",
+ NULL,
+};
+
+DT_MACHINE_START(KOELSCH_DT, "koelsch")
+ .init_early = r8a7791_init_early,
+ .init_machine = koelsch_add_standard_devices,
+ .dt_compat = koelsch_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
index f1994968d303..fe689b7fdc9e 100644
--- a/arch/arm/mach-shmobile/board-kzm9g.c
+++ b/arch/arm/mach-shmobile/board-kzm9g.c
@@ -366,6 +366,7 @@ static struct resource sh_mmcif_resources[] = {
static struct sh_mmcif_plat_data sh_mmcif_platdata = {
.ocr = MMC_VDD_165_195,
.caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
+ .ccs_unsupported = true,
.slave_id_tx = SHDMA_SLAVE_MMCIF_TX,
.slave_id_rx = SHDMA_SLAVE_MMCIF_RX,
};
diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c
index 9c316a1b2e32..d39a91b3ba48 100644
--- a/arch/arm/mach-shmobile/board-lager-reference.c
+++ b/arch/arm/mach-shmobile/board-lager-reference.c
@@ -38,7 +38,8 @@ static const char *lager_boards_compat_dt[] __initdata = {
};
DT_MACHINE_START(LAGER_DT, "lager")
- .init_early = r8a7790_init_delay,
+ .smp = smp_ops(r8a7790_smp_ops),
+ .init_early = r8a7790_init_early,
.init_machine = lager_add_standard_devices,
.init_time = r8a7790_timer_init,
.dt_compat = lager_boards_compat_dt,
diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c
index ffb6f0ac7606..77d9dae58184 100644
--- a/arch/arm/mach-shmobile/board-lager.c
+++ b/arch/arm/mach-shmobile/board-lager.c
@@ -28,7 +28,9 @@
#include <linux/mmc/sh_mmcif.h>
#include <linux/pinctrl/machine.h>
#include <linux/platform_data/gpio-rcar.h>
+#include <linux/platform_data/rcar-du.h>
#include <linux/platform_device.h>
+#include <linux/phy.h>
#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
#include <linux/sh_eth.h>
@@ -38,6 +40,62 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+/* DU */
+static struct rcar_du_encoder_data lager_du_encoders[] = {
+ {
+ .type = RCAR_DU_ENCODER_VGA,
+ .output = RCAR_DU_OUTPUT_DPAD0,
+ }, {
+ .type = RCAR_DU_ENCODER_NONE,
+ .output = RCAR_DU_OUTPUT_LVDS1,
+ .connector.lvds.panel = {
+ .width_mm = 210,
+ .height_mm = 158,
+ .mode = {
+ .clock = 65000,
+ .hdisplay = 1024,
+ .hsync_start = 1048,
+ .hsync_end = 1184,
+ .htotal = 1344,
+ .vdisplay = 768,
+ .vsync_start = 771,
+ .vsync_end = 777,
+ .vtotal = 806,
+ .flags = 0,
+ },
+ },
+ },
+};
+
+static const struct rcar_du_platform_data lager_du_pdata __initconst = {
+ .encoders = lager_du_encoders,
+ .num_encoders = ARRAY_SIZE(lager_du_encoders),
+};
+
+static const struct resource du_resources[] __initconst = {
+ DEFINE_RES_MEM(0xfeb00000, 0x70000),
+ DEFINE_RES_MEM_NAMED(0xfeb90000, 0x1c, "lvds.0"),
+ DEFINE_RES_MEM_NAMED(0xfeb94000, 0x1c, "lvds.1"),
+ DEFINE_RES_IRQ(gic_spi(256)),
+ DEFINE_RES_IRQ(gic_spi(268)),
+ DEFINE_RES_IRQ(gic_spi(269)),
+};
+
+static void __init lager_add_du_device(void)
+{
+ struct platform_device_info info = {
+ .name = "rcar-du-r8a7790",
+ .id = -1,
+ .res = du_resources,
+ .num_res = ARRAY_SIZE(du_resources),
+ .data = &lager_du_pdata,
+ .size_data = sizeof(lager_du_pdata),
+ .dma_mask = DMA_BIT_MASK(32),
+ };
+
+ platform_device_register_full(&info);
+}
+
/* LEDS */
static struct gpio_led lager_leds[] = {
{
@@ -55,7 +113,7 @@ static struct gpio_led lager_leds[] = {
},
};
-static __initdata struct gpio_led_platform_data lager_leds_pdata = {
+static const struct gpio_led_platform_data lager_leds_pdata __initconst = {
.leds = lager_leds,
.num_leds = ARRAY_SIZE(lager_leds),
};
@@ -71,7 +129,7 @@ static struct gpio_keys_button gpio_buttons[] = {
GPIO_KEY(KEY_1, RCAR_GP_PIN(1, 14), "SW2-pin1"),
};
-static __initdata struct gpio_keys_platform_data lager_keys_pdata = {
+static const struct gpio_keys_platform_data lager_keys_pdata __initconst = {
.buttons = gpio_buttons,
.nbuttons = ARRAY_SIZE(gpio_buttons),
};
@@ -83,29 +141,38 @@ static struct regulator_consumer_supply fixed3v3_power_consumers[] =
};
/* MMCIF */
-static struct sh_mmcif_plat_data mmcif1_pdata __initdata = {
+static const struct sh_mmcif_plat_data mmcif1_pdata __initconst = {
.caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
+ .clk_ctrl2_present = true,
+ .ccs_unsupported = true,
};
-static struct resource mmcif1_resources[] __initdata = {
+static const struct resource mmcif1_resources[] __initconst = {
DEFINE_RES_MEM_NAMED(0xee220000, 0x80, "MMCIF1"),
DEFINE_RES_IRQ(gic_spi(170)),
};
/* Ether */
-static struct sh_eth_plat_data ether_pdata __initdata = {
+static const struct sh_eth_plat_data ether_pdata __initconst = {
.phy = 0x1,
.edmac_endian = EDMAC_LITTLE_ENDIAN,
.phy_interface = PHY_INTERFACE_MODE_RMII,
.ether_link_active_low = 1,
};
-static struct resource ether_resources[] __initdata = {
+static const struct resource ether_resources[] __initconst = {
DEFINE_RES_MEM(0xee700000, 0x400),
DEFINE_RES_IRQ(gic_spi(162)),
};
static const struct pinctrl_map lager_pinctrl_map[] = {
+ /* DU (CN10: ARGB0, CN13: LVDS) */
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790",
+ "du_rgb666", "du"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790",
+ "du_sync_1", "du"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790",
+ "du_clk_out_0", "du"),
/* SCIF0 (CN19: DEBUG SERIAL0) */
PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.6", "pfc-r8a7790",
"scif0_data", "scif0"),
@@ -153,16 +220,43 @@ static void __init lager_add_standard_devices(void)
ether_resources,
ARRAY_SIZE(ether_resources),
&ether_pdata, sizeof(ether_pdata));
+
+ lager_add_du_device();
+}
+
+/*
+ * Ether LEDs on the Lager board are named LINK and ACTIVE which corresponds
+ * to non-default 01 setting of the Micrel KSZ8041 PHY control register 1 bits
+ * 14-15. We have to set them back to 01 from the default 00 value each time
+ * the PHY is reset. It's also important because the PHY's LED0 signal is
+ * connected to SoC's ETH_LINK signal and in the PHY's default mode it will
+ * bounce on and off after each packet, which we apparently want to avoid.
+ */
+static int lager_ksz8041_fixup(struct phy_device *phydev)
+{
+ u16 phyctrl1 = phy_read(phydev, 0x1e);
+
+ phyctrl1 &= ~0xc000;
+ phyctrl1 |= 0x4000;
+ return phy_write(phydev, 0x1e, phyctrl1);
+}
+
+static void __init lager_init(void)
+{
+ lager_add_standard_devices();
+
+ phy_register_fixup_for_id("r8a7790-ether-ff:01", lager_ksz8041_fixup);
}
-static const char *lager_boards_compat_dt[] __initdata = {
+static const char * const lager_boards_compat_dt[] __initconst = {
"renesas,lager",
NULL,
};
DT_MACHINE_START(LAGER_DT, "lager")
- .init_early = r8a7790_init_delay,
+ .smp = smp_ops(r8a7790_smp_ops),
+ .init_early = r8a7790_init_early,
.init_time = r8a7790_timer_init,
- .init_machine = lager_add_standard_devices,
+ .init_machine = lager_init,
.dt_compat = lager_boards_compat_dt,
MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
index 3f5044fda4e3..434b213cc738 100644
--- a/arch/arm/mach-shmobile/board-marzen.c
+++ b/arch/arm/mach-shmobile/board-marzen.c
@@ -30,6 +30,7 @@
#include <linux/dma-mapping.h>
#include <linux/pinctrl/machine.h>
#include <linux/platform_data/gpio-rcar.h>
+#include <linux/platform_data/rcar-du.h>
#include <linux/platform_data/usb-rcar-phy.h>
#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
@@ -169,6 +170,63 @@ static struct platform_device hspi_device = {
.num_resources = ARRAY_SIZE(hspi_resources),
};
+/*
+ * DU
+ *
+ * The panel only specifies the [hv]display and [hv]total values. The position
+ * and width of the sync pulses don't matter, they're copied from VESA timings.
+ */
+static struct rcar_du_encoder_data du_encoders[] = {
+ {
+ .type = RCAR_DU_ENCODER_VGA,
+ .output = RCAR_DU_OUTPUT_DPAD0,
+ }, {
+ .type = RCAR_DU_ENCODER_LVDS,
+ .output = RCAR_DU_OUTPUT_DPAD1,
+ .connector.lvds.panel = {
+ .width_mm = 210,
+ .height_mm = 158,
+ .mode = {
+ .clock = 65000,
+ .hdisplay = 1024,
+ .hsync_start = 1048,
+ .hsync_end = 1184,
+ .htotal = 1344,
+ .vdisplay = 768,
+ .vsync_start = 771,
+ .vsync_end = 777,
+ .vtotal = 806,
+ .flags = 0,
+ },
+ },
+ },
+};
+
+static const struct rcar_du_platform_data du_pdata __initconst = {
+ .encoders = du_encoders,
+ .num_encoders = ARRAY_SIZE(du_encoders),
+};
+
+static const struct resource du_resources[] __initconst = {
+ DEFINE_RES_MEM(0xfff80000, 0x40000),
+ DEFINE_RES_IRQ(gic_iid(0x3f)),
+};
+
+static void __init marzen_add_du_device(void)
+{
+ struct platform_device_info info = {
+ .name = "rcar-du-r8a7779",
+ .id = -1,
+ .res = du_resources,
+ .num_res = ARRAY_SIZE(du_resources),
+ .data = &du_pdata,
+ .size_data = sizeof(du_pdata),
+ .dma_mask = DMA_BIT_MASK(32),
+ };
+
+ platform_device_register_full(&info);
+}
+
/* LEDS */
static struct gpio_led marzen_leds[] = {
{
@@ -237,6 +295,19 @@ static struct platform_device *marzen_devices[] __initdata = {
};
static const struct pinctrl_map marzen_pinctrl_map[] = {
+ /* DU (CN10: ARGB0, CN13: LVDS) */
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+ "du0_rgb888", "du0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+ "du0_sync_1", "du0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+ "du0_clk_out_0", "du0"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+ "du1_rgb666", "du1"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+ "du1_sync_1", "du1"),
+ PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+ "du1_clk_out", "du1"),
/* HSPI0 */
PIN_MAP_MUX_GROUP_DEFAULT("sh-hspi.0", "pfc-r8a7779",
"hspi0", "hspi0"),
@@ -297,6 +368,7 @@ static void __init marzen_init(void)
r8a7779_add_vin_device(1, &vin_platform_data);
r8a7779_add_vin_device(3, &vin_platform_data);
platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
+ marzen_add_du_device();
}
static const char *marzen_boards_compat_dt[] __initdata = {
diff --git a/arch/arm/mach-shmobile/clock-r8a7778.c b/arch/arm/mach-shmobile/clock-r8a7778.c
index c4bf2d8fb111..fb6af83858e3 100644
--- a/arch/arm/mach-shmobile/clock-r8a7778.c
+++ b/arch/arm/mach-shmobile/clock-r8a7778.c
@@ -69,6 +69,15 @@ static struct clk extal_clk = {
.mapping = &cpg_mapping,
};
+static struct clk audio_clk_a = {
+};
+
+static struct clk audio_clk_b = {
+};
+
+static struct clk audio_clk_c = {
+};
+
/*
* clock ratio of these clock will be updated
* on r8a7778_clock_init()
@@ -100,18 +109,23 @@ static struct clk *main_clks[] = {
&p_clk,
&g_clk,
&z_clk,
+ &audio_clk_a,
+ &audio_clk_b,
+ &audio_clk_c,
};
enum {
MSTP331,
MSTP323, MSTP322, MSTP321,
+ MSTP311, MSTP310,
+ MSTP309, MSTP308, MSTP307,
MSTP114,
MSTP110, MSTP109,
MSTP100,
MSTP030,
MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
- MSTP016, MSTP015,
- MSTP007,
+ MSTP016, MSTP015, MSTP012, MSTP011, MSTP010,
+ MSTP009, MSTP008, MSTP007,
MSTP_NR };
static struct clk mstp_clks[MSTP_NR] = {
@@ -119,6 +133,11 @@ static struct clk mstp_clks[MSTP_NR] = {
[MSTP323] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 23, 0), /* SDHI0 */
[MSTP322] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 22, 0), /* SDHI1 */
[MSTP321] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 21, 0), /* SDHI2 */
+ [MSTP311] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 11, 0), /* SSI4 */
+ [MSTP310] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 10, 0), /* SSI5 */
+ [MSTP309] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 9, 0), /* SSI6 */
+ [MSTP308] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 8, 0), /* SSI7 */
+ [MSTP307] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 7, 0), /* SSI8 */
[MSTP114] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 14, 0), /* Ether */
[MSTP110] = SH_CLK_MSTP32(&s_clk, MSTPCR1, 10, 0), /* VIN0 */
[MSTP109] = SH_CLK_MSTP32(&s_clk, MSTPCR1, 9, 0), /* VIN1 */
@@ -135,11 +154,20 @@ static struct clk mstp_clks[MSTP_NR] = {
[MSTP021] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 21, 0), /* SCIF5 */
[MSTP016] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 16, 0), /* TMU0 */
[MSTP015] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 15, 0), /* TMU1 */
+ [MSTP012] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 12, 0), /* SSI0 */
+ [MSTP011] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 11, 0), /* SSI1 */
+ [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 */
};
static struct clk_lookup lookups[] = {
/* main */
+ CLKDEV_CON_ID("audio_clk_a", &audio_clk_a),
+ CLKDEV_CON_ID("audio_clk_b", &audio_clk_b),
+ CLKDEV_CON_ID("audio_clk_c", &audio_clk_c),
+ CLKDEV_CON_ID("audio_clk_internal", &s1_clk),
CLKDEV_CON_ID("shyway_clk", &s_clk),
CLKDEV_CON_ID("peripheral_clk", &p_clk),
@@ -153,6 +181,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("r8a7778-vin.1", &mstp_clks[MSTP109]), /* VIN1 */
CLKDEV_DEV_ID("ehci-platform", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */
CLKDEV_DEV_ID("ohci-platform", &mstp_clks[MSTP100]), /* USB OHCI port0/1 */
+ CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP100]), /* USB FUNC */
CLKDEV_DEV_ID("i2c-rcar.0", &mstp_clks[MSTP030]), /* I2C0 */
CLKDEV_DEV_ID("i2c-rcar.1", &mstp_clks[MSTP029]), /* I2C1 */
CLKDEV_DEV_ID("i2c-rcar.2", &mstp_clks[MSTP028]), /* I2C2 */
@@ -168,6 +197,17 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh-hspi.0", &mstp_clks[MSTP007]), /* HSPI0 */
CLKDEV_DEV_ID("sh-hspi.1", &mstp_clks[MSTP007]), /* HSPI1 */
CLKDEV_DEV_ID("sh-hspi.2", &mstp_clks[MSTP007]), /* HSPI2 */
+ CLKDEV_DEV_ID("rcar_sound", &mstp_clks[MSTP008]), /* SRU */
+
+ CLKDEV_ICK_ID("ssi.0", "rcar_sound", &mstp_clks[MSTP012]),
+ CLKDEV_ICK_ID("ssi.1", "rcar_sound", &mstp_clks[MSTP011]),
+ CLKDEV_ICK_ID("ssi.2", "rcar_sound", &mstp_clks[MSTP010]),
+ CLKDEV_ICK_ID("ssi.3", "rcar_sound", &mstp_clks[MSTP009]),
+ CLKDEV_ICK_ID("ssi.4", "rcar_sound", &mstp_clks[MSTP311]),
+ CLKDEV_ICK_ID("ssi.5", "rcar_sound", &mstp_clks[MSTP310]),
+ CLKDEV_ICK_ID("ssi.6", "rcar_sound", &mstp_clks[MSTP309]),
+ CLKDEV_ICK_ID("ssi.7", "rcar_sound", &mstp_clks[MSTP308]),
+ CLKDEV_ICK_ID("ssi.8", "rcar_sound", &mstp_clks[MSTP307]),
};
void __init r8a7778_clock_init(void)
diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c
index bd6ad922eb7e..1f7080fab0a5 100644
--- a/arch/arm/mach-shmobile/clock-r8a7779.c
+++ b/arch/arm/mach-shmobile/clock-r8a7779.c
@@ -200,7 +200,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP320]), /* SDHI3 */
- CLKDEV_DEV_ID("rcar-du.0", &mstp_clks[MSTP103]), /* DU */
+ CLKDEV_DEV_ID("rcar-du-r8a7779", &mstp_clks[MSTP103]), /* DU */
};
void __init r8a7779_clock_init(void)
diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c
index fc36d3db0b4d..d99b87bc76ea 100644
--- a/arch/arm/mach-shmobile/clock-r8a7790.c
+++ b/arch/arm/mach-shmobile/clock-r8a7790.c
@@ -182,7 +182,7 @@ static struct clk div6_clks[DIV6_NR] = {
/* MSTP */
enum {
MSTP813,
- MSTP721, MSTP720,
+ MSTP726, MSTP725, MSTP724, MSTP723, MSTP722, MSTP721, MSTP720,
MSTP717, MSTP716,
MSTP522,
MSTP315, MSTP314, MSTP313, MSTP312, MSTP311, MSTP305, MSTP304,
@@ -193,6 +193,11 @@ enum {
static struct clk mstp_clks[MSTP_NR] = {
[MSTP813] = SH_CLK_MSTP32(&p_clk, SMSTPCR8, 13, 0), /* Ether */
+ [MSTP726] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 26, 0), /* LVDS0 */
+ [MSTP725] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 25, 0), /* LVDS1 */
+ [MSTP724] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 24, 0), /* DU0 */
+ [MSTP723] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 23, 0), /* DU1 */
+ [MSTP722] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 22, 0), /* DU2 */
[MSTP721] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 21, 0), /* SCIF0 */
[MSTP720] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 20, 0), /* SCIF1 */
[MSTP717] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 17, 0), /* HSCIF0 */
@@ -251,6 +256,11 @@ static struct clk_lookup lookups[] = {
CLKDEV_CON_ID("ssprs", &div6_clks[DIV6_SSPRS]),
/* MSTP */
+ CLKDEV_ICK_ID("lvds.0", "rcar-du-r8a7790", &mstp_clks[MSTP726]),
+ CLKDEV_ICK_ID("lvds.1", "rcar-du-r8a7790", &mstp_clks[MSTP725]),
+ CLKDEV_ICK_ID("du.0", "rcar-du-r8a7790", &mstp_clks[MSTP724]),
+ CLKDEV_ICK_ID("du.1", "rcar-du-r8a7790", &mstp_clks[MSTP723]),
+ CLKDEV_ICK_ID("du.2", "rcar-du-r8a7790", &mstp_clks[MSTP722]),
CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]),
CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP206]),
diff --git a/arch/arm/mach-shmobile/clock-r8a7791.c b/arch/arm/mach-shmobile/clock-r8a7791.c
new file mode 100644
index 000000000000..c9a26f16ce5b
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock-r8a7791.c
@@ -0,0 +1,237 @@
+/*
+ * r8a7791 clock framework support
+ *
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * 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 of the License.
+ *
+ * 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/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/sh_clk.h>
+#include <linux/clkdev.h>
+#include <mach/clock.h>
+#include <mach/common.h>
+
+/*
+ * MD EXTAL PLL0 PLL1 PLL3
+ * 14 13 19 (MHz) *1 *1
+ *---------------------------------------------------
+ * 0 0 0 15 x 1 x172/2 x208/2 x106
+ * 0 0 1 15 x 1 x172/2 x208/2 x88
+ * 0 1 0 20 x 1 x130/2 x156/2 x80
+ * 0 1 1 20 x 1 x130/2 x156/2 x66
+ * 1 0 0 26 / 2 x200/2 x240/2 x122
+ * 1 0 1 26 / 2 x200/2 x240/2 x102
+ * 1 1 0 30 / 2 x172/2 x208/2 x106
+ * 1 1 1 30 / 2 x172/2 x208/2 x88
+ *
+ * *1 : Table 7.6 indicates VCO ouput (PLLx = VCO/2)
+ * see "p1 / 2" on R8A7791_CLOCK_ROOT() below
+ */
+
+#define MD(nr) (1 << nr)
+
+#define CPG_BASE 0xe6150000
+#define CPG_LEN 0x1000
+
+#define SMSTPCR0 0xE6150130
+#define SMSTPCR1 0xE6150134
+#define SMSTPCR2 0xe6150138
+#define SMSTPCR3 0xE615013C
+#define SMSTPCR5 0xE6150144
+#define SMSTPCR7 0xe615014c
+#define SMSTPCR8 0xE6150990
+#define SMSTPCR9 0xE6150994
+#define SMSTPCR10 0xE6150998
+#define SMSTPCR11 0xE615099C
+
+#define MODEMR 0xE6160060
+#define SDCKCR 0xE6150074
+#define SD2CKCR 0xE6150078
+#define SD3CKCR 0xE615007C
+#define MMC0CKCR 0xE6150240
+#define MMC1CKCR 0xE6150244
+#define SSPCKCR 0xE6150248
+#define SSPRSCKCR 0xE615024C
+
+static struct clk_mapping cpg_mapping = {
+ .phys = CPG_BASE,
+ .len = CPG_LEN,
+};
+
+static struct clk extal_clk = {
+ /* .rate will be updated on r8a7791_clock_init() */
+ .mapping = &cpg_mapping,
+};
+
+static struct sh_clk_ops followparent_clk_ops = {
+ .recalc = followparent_recalc,
+};
+
+static struct clk main_clk = {
+ /* .parent will be set r8a73a4_clock_init */
+ .ops = &followparent_clk_ops,
+};
+
+/*
+ * clock ratio of these clock will be updated
+ * on r8a7791_clock_init()
+ */
+SH_FIXED_RATIO_CLK_SET(pll1_clk, main_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(pll3_clk, main_clk, 1, 1);
+
+/* fixed ratio clock */
+SH_FIXED_RATIO_CLK_SET(extal_div2_clk, extal_clk, 1, 2);
+SH_FIXED_RATIO_CLK_SET(cp_clk, extal_clk, 1, 2);
+
+SH_FIXED_RATIO_CLK_SET(pll1_div2_clk, pll1_clk, 1, 2);
+SH_FIXED_RATIO_CLK_SET(hp_clk, pll1_clk, 1, 12);
+SH_FIXED_RATIO_CLK_SET(p_clk, pll1_clk, 1, 24);
+SH_FIXED_RATIO_CLK_SET(rclk_clk, pll1_clk, 1, (48 * 1024));
+SH_FIXED_RATIO_CLK_SET(mp_clk, pll1_div2_clk, 1, 15);
+
+static struct clk *main_clks[] = {
+ &extal_clk,
+ &extal_div2_clk,
+ &main_clk,
+ &pll1_clk,
+ &pll1_div2_clk,
+ &pll3_clk,
+ &hp_clk,
+ &p_clk,
+ &rclk_clk,
+ &mp_clk,
+ &cp_clk,
+};
+
+/* MSTP */
+enum {
+ MSTP721, MSTP720,
+ MSTP719, MSTP718, MSTP715, MSTP714,
+ MSTP216, MSTP207, MSTP206,
+ MSTP204, MSTP203, MSTP202, MSTP1105, MSTP1106, MSTP1107,
+ MSTP124,
+ MSTP_NR
+};
+
+static struct clk mstp_clks[MSTP_NR] = {
+ [MSTP721] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 21, 0), /* SCIF0 */
+ [MSTP720] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 20, 0), /* SCIF1 */
+ [MSTP719] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 19, 0), /* SCIF2 */
+ [MSTP718] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 18, 0), /* SCIF3 */
+ [MSTP715] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 15, 0), /* SCIF4 */
+ [MSTP714] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 14, 0), /* SCIF5 */
+ [MSTP216] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 16, 0), /* SCIFB2 */
+ [MSTP207] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 7, 0), /* SCIFB1 */
+ [MSTP206] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 6, 0), /* SCIFB0 */
+ [MSTP204] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 4, 0), /* SCIFA0 */
+ [MSTP203] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 3, 0), /* SCIFA1 */
+ [MSTP202] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 2, 0), /* SCIFA2 */
+ [MSTP1105] = SH_CLK_MSTP32(&mp_clk, SMSTPCR11, 5, 0), /* SCIFA3 */
+ [MSTP1106] = SH_CLK_MSTP32(&mp_clk, SMSTPCR11, 6, 0), /* SCIFA4 */
+ [MSTP1107] = SH_CLK_MSTP32(&mp_clk, SMSTPCR11, 7, 0), /* SCIFA5 */
+ [MSTP124] = SH_CLK_MSTP32(&rclk_clk, SMSTPCR1, 24, 0), /* CMT0 */
+};
+
+static struct clk_lookup lookups[] = {
+
+ /* main clocks */
+ CLKDEV_CON_ID("extal", &extal_clk),
+ CLKDEV_CON_ID("extal_div2", &extal_div2_clk),
+ CLKDEV_CON_ID("main", &main_clk),
+ CLKDEV_CON_ID("pll1", &pll1_clk),
+ CLKDEV_CON_ID("pll1_div2", &pll1_div2_clk),
+ CLKDEV_CON_ID("pll3", &pll3_clk),
+ CLKDEV_CON_ID("hp", &hp_clk),
+ CLKDEV_CON_ID("p", &p_clk),
+ CLKDEV_CON_ID("rclk", &rclk_clk),
+ CLKDEV_CON_ID("mp", &mp_clk),
+ CLKDEV_CON_ID("cp", &cp_clk),
+ CLKDEV_CON_ID("peripheral_clk", &hp_clk),
+
+ /* MSTP */
+ CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */
+ CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), /* SCIFA1 */
+ CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP206]), /* SCIFB0 */
+ CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP207]), /* SCIFB1 */
+ CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]), /* SCIFB2 */
+ CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP202]), /* SCIFA2 */
+ CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP721]), /* SCIF0 */
+ CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP720]), /* SCIF1 */
+ CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP719]), /* SCIF2 */
+ CLKDEV_DEV_ID("sh-sci.9", &mstp_clks[MSTP718]), /* SCIF3 */
+ CLKDEV_DEV_ID("sh-sci.10", &mstp_clks[MSTP715]), /* SCIF4 */
+ CLKDEV_DEV_ID("sh-sci.11", &mstp_clks[MSTP714]), /* SCIF5 */
+ CLKDEV_DEV_ID("sh-sci.12", &mstp_clks[MSTP1105]), /* SCIFA3 */
+ CLKDEV_DEV_ID("sh-sci.13", &mstp_clks[MSTP1106]), /* SCIFA4 */
+ CLKDEV_DEV_ID("sh-sci.14", &mstp_clks[MSTP1107]), /* SCIFA5 */
+ CLKDEV_DEV_ID("sh_cmt.0", &mstp_clks[MSTP124]),
+};
+
+#define R8A7791_CLOCK_ROOT(e, m, p0, p1, p30, p31) \
+ extal_clk.rate = e * 1000 * 1000; \
+ main_clk.parent = m; \
+ SH_CLK_SET_RATIO(&pll1_clk_ratio, p1 / 2, 1); \
+ if (mode & MD(19)) \
+ SH_CLK_SET_RATIO(&pll3_clk_ratio, p31, 1); \
+ else \
+ SH_CLK_SET_RATIO(&pll3_clk_ratio, p30, 1)
+
+
+void __init r8a7791_clock_init(void)
+{
+ void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
+ u32 mode;
+ int k, ret = 0;
+
+ BUG_ON(!modemr);
+ mode = ioread32(modemr);
+ iounmap(modemr);
+
+ switch (mode & (MD(14) | MD(13))) {
+ case 0:
+ R8A7791_CLOCK_ROOT(15, &extal_clk, 172, 208, 106, 88);
+ break;
+ case MD(13):
+ R8A7791_CLOCK_ROOT(20, &extal_clk, 130, 156, 80, 66);
+ break;
+ case MD(14):
+ R8A7791_CLOCK_ROOT(26, &extal_div2_clk, 200, 240, 122, 102);
+ break;
+ case MD(13) | MD(14):
+ R8A7791_CLOCK_ROOT(30, &extal_div2_clk, 172, 208, 106, 88);
+ break;
+ }
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+ ret = clk_register(main_clks[k]);
+
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+ if (!ret)
+ shmobile_clk_init();
+ else
+ goto epanic;
+
+ return;
+
+epanic:
+ panic("failed to setup r8a7791 clocks\n");
+}
diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S
index f93751caf5cb..e5be5c88644b 100644
--- a/arch/arm/mach-shmobile/headsmp.S
+++ b/arch/arm/mach-shmobile/headsmp.S
@@ -40,6 +40,9 @@ shmobile_boot_fn:
.globl shmobile_boot_arg
shmobile_boot_arg:
2: .space 4
+ .globl shmobile_boot_size
+shmobile_boot_size:
+ .long . - shmobile_boot_vector
/*
* Per-CPU SMP boot function/argument selection code based on MPIDR
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index 7b938681e756..e31980590eb4 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -9,16 +9,23 @@ extern void shmobile_setup_console(void);
extern void shmobile_boot_vector(void);
extern unsigned long shmobile_boot_fn;
extern unsigned long shmobile_boot_arg;
+extern unsigned long shmobile_boot_size;
extern void shmobile_smp_boot(void);
extern void shmobile_smp_sleep(void);
extern void shmobile_smp_hook(unsigned int cpu, unsigned long fn,
unsigned long arg);
+extern int shmobile_smp_cpu_disable(unsigned int cpu);
+extern void shmobile_invalidate_start(void);
extern void shmobile_boot_scu(void);
extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus);
-extern int shmobile_smp_scu_boot_secondary(unsigned int cpu,
- struct task_struct *idle);
extern void shmobile_smp_scu_cpu_die(unsigned int cpu);
extern int shmobile_smp_scu_cpu_kill(unsigned int cpu);
+extern void shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus);
+extern int shmobile_smp_apmu_boot_secondary(unsigned int cpu,
+ struct task_struct *idle);
+extern void shmobile_smp_apmu_cpu_die(unsigned int cpu);
+extern int shmobile_smp_apmu_cpu_kill(unsigned int cpu);
+extern void shmobile_invalidate_start(void);
struct clk;
extern int shmobile_clk_init(void);
extern void shmobile_handle_irq_intc(struct pt_regs *);
@@ -39,7 +46,6 @@ static inline int shmobile_cpuidle_init(void) { return 0; }
#endif
extern void __iomem *shmobile_scu_base;
-extern void shmobile_smp_init_cpus(unsigned int ncores);
static inline void __init shmobile_init_late(void)
{
diff --git a/arch/arm/mach-shmobile/include/mach/r8a73a4.h b/arch/arm/mach-shmobile/include/mach/r8a73a4.h
index f3a9b702da56..5214338a6a47 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a73a4.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a73a4.h
@@ -5,6 +5,6 @@ void r8a73a4_add_standard_devices(void);
void r8a73a4_add_dt_devices(void);
void r8a73a4_clock_init(void);
void r8a73a4_pinmux_init(void);
-void r8a73a4_init_delay(void);
+void r8a73a4_init_early(void);
#endif /* __ASM_R8A73A4_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7778.h b/arch/arm/mach-shmobile/include/mach/r8a7778.h
index adfcf51b163d..ea1dca6880f4 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7778.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7778.h
@@ -35,4 +35,6 @@ extern void r8a7778_clock_init(void);
extern void r8a7778_init_irq_extpin(int irlm);
extern void r8a7778_pinmux_init(void);
+extern int r8a7778_usb_phy_power(bool enable);
+
#endif /* __ASM_R8A7778_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h b/arch/arm/mach-shmobile/include/mach/r8a7790.h
index 788d55952091..79e731c83e50 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7790.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h
@@ -5,8 +5,9 @@ void r8a7790_add_standard_devices(void);
void r8a7790_add_dt_devices(void);
void r8a7790_clock_init(void);
void r8a7790_pinmux_init(void);
-void r8a7790_init_delay(void);
+void r8a7790_init_early(void);
void r8a7790_timer_init(void);
+extern struct smp_operations r8a7790_smp_ops;
#define MD(nr) BIT(nr)
u32 r8a7790_read_mode_pins(void);
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7791.h b/arch/arm/mach-shmobile/include/mach/r8a7791.h
new file mode 100644
index 000000000000..2e6d66131083
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/r8a7791.h
@@ -0,0 +1,8 @@
+#ifndef __ASM_R8A7791_H__
+#define __ASM_R8A7791_H__
+
+void r8a7791_add_dt_devices(void);
+void r8a7791_clock_init(void);
+void r8a7791_init_early(void);
+
+#endif /* __ASM_R8A7791_H__ */
diff --git a/arch/arm/mach-shmobile/platsmp-apmu.c b/arch/arm/mach-shmobile/platsmp-apmu.c
new file mode 100644
index 000000000000..1da5a72d9642
--- /dev/null
+++ b/arch/arm/mach-shmobile/platsmp-apmu.c
@@ -0,0 +1,195 @@
+/*
+ * SMP support for SoCs with APMU
+ *
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/of_address.h>
+#include <linux/smp.h>
+#include <asm/cacheflush.h>
+#include <asm/cp15.h>
+#include <asm/smp_plat.h>
+#include <mach/common.h>
+
+static struct {
+ void __iomem *iomem;
+ int bit;
+} apmu_cpus[CONFIG_NR_CPUS];
+
+#define WUPCR_OFFS 0x10
+#define PSTR_OFFS 0x40
+#define CPUNCR_OFFS(n) (0x100 + (0x10 * (n)))
+
+static int apmu_power_on(void __iomem *p, int bit)
+{
+ /* request power on */
+ writel_relaxed(BIT(bit), p + WUPCR_OFFS);
+
+ /* wait for APMU to finish */
+ while (readl_relaxed(p + WUPCR_OFFS) != 0)
+ ;
+
+ return 0;
+}
+
+static int apmu_power_off(void __iomem *p, int bit)
+{
+ /* request Core Standby for next WFI */
+ writel_relaxed(3, p + CPUNCR_OFFS(bit));
+ return 0;
+}
+
+static int apmu_power_off_poll(void __iomem *p, int bit)
+{
+ int k;
+
+ for (k = 0; k < 1000; k++) {
+ if (((readl_relaxed(p + PSTR_OFFS) >> (bit * 4)) & 0x03) == 3)
+ return 1;
+
+ mdelay(1);
+ }
+
+ return 0;
+}
+
+static int apmu_wrap(int cpu, int (*fn)(void __iomem *p, int cpu))
+{
+ void __iomem *p = apmu_cpus[cpu].iomem;
+
+ return p ? fn(p, apmu_cpus[cpu].bit) : -EINVAL;
+}
+
+static void apmu_init_cpu(struct resource *res, int cpu, int bit)
+{
+ if (apmu_cpus[cpu].iomem)
+ return;
+
+ apmu_cpus[cpu].iomem = ioremap_nocache(res->start, resource_size(res));
+ apmu_cpus[cpu].bit = bit;
+
+ pr_debug("apmu ioremap %d %d 0x%08x 0x%08x\n", cpu, bit,
+ res->start, resource_size(res));
+}
+
+static struct {
+ struct resource iomem;
+ int cpus[4];
+} apmu_config[] = {
+ {
+ .iomem = DEFINE_RES_MEM(0xe6152000, 0x88),
+ .cpus = { 0, 1, 2, 3 },
+ },
+ {
+ .iomem = DEFINE_RES_MEM(0xe6151000, 0x88),
+ .cpus = { 0x100, 0x101, 0x102, 0x103 },
+ }
+};
+
+static void apmu_parse_cfg(void (*fn)(struct resource *res, int cpu, int bit))
+{
+ u32 id;
+ int k;
+ int bit, index;
+ bool is_allowed;
+
+ for (k = 0; k < ARRAY_SIZE(apmu_config); k++) {
+ /* only enable the cluster that includes the boot CPU */
+ is_allowed = false;
+ for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) {
+ id = apmu_config[k].cpus[bit];
+ if (id >= 0) {
+ if (id == cpu_logical_map(0))
+ is_allowed = true;
+ }
+ }
+ if (!is_allowed)
+ continue;
+
+ for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) {
+ id = apmu_config[k].cpus[bit];
+ if (id >= 0) {
+ index = get_logical_index(id);
+ if (index >= 0)
+ fn(&apmu_config[k].iomem, index, bit);
+ }
+ }
+ }
+}
+
+void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus)
+{
+ /* install boot code shared by all CPUs */
+ shmobile_boot_fn = virt_to_phys(shmobile_smp_boot);
+ shmobile_boot_arg = MPIDR_HWID_BITMASK;
+
+ /* perform per-cpu setup */
+ apmu_parse_cfg(apmu_init_cpu);
+}
+
+int shmobile_smp_apmu_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ /* For this particular CPU register boot vector */
+ shmobile_smp_hook(cpu, virt_to_phys(shmobile_invalidate_start), 0);
+
+ return apmu_wrap(cpu, apmu_power_on);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+/* nicked from arch/arm/mach-exynos/hotplug.c */
+static inline void cpu_enter_lowpower_a15(void)
+{
+ unsigned int v;
+
+ asm volatile(
+ " mrc p15, 0, %0, c1, c0, 0\n"
+ " bic %0, %0, %1\n"
+ " mcr p15, 0, %0, c1, c0, 0\n"
+ : "=&r" (v)
+ : "Ir" (CR_C)
+ : "cc");
+
+ flush_cache_louis();
+
+ asm volatile(
+ /*
+ * Turn off coherency
+ */
+ " mrc p15, 0, %0, c1, c0, 1\n"
+ " bic %0, %0, %1\n"
+ " mcr p15, 0, %0, c1, c0, 1\n"
+ : "=&r" (v)
+ : "Ir" (0x40)
+ : "cc");
+
+ isb();
+ dsb();
+}
+
+void shmobile_smp_apmu_cpu_die(unsigned int cpu)
+{
+ /* For this particular CPU deregister boot vector */
+ shmobile_smp_hook(cpu, 0, 0);
+
+ /* Select next sleep mode using the APMU */
+ apmu_wrap(cpu, apmu_power_off);
+
+ /* Do ARM specific CPU shutdown */
+ cpu_enter_lowpower_a15();
+
+ /* jump to shared mach-shmobile sleep / reset code */
+ shmobile_smp_sleep();
+}
+
+int shmobile_smp_apmu_cpu_kill(unsigned int cpu)
+{
+ return apmu_wrap(cpu, apmu_power_off_poll);
+}
+#endif
diff --git a/arch/arm/mach-shmobile/platsmp-scu.c b/arch/arm/mach-shmobile/platsmp-scu.c
index c96f50160be6..673ad6e80869 100644
--- a/arch/arm/mach-shmobile/platsmp-scu.c
+++ b/arch/arm/mach-shmobile/platsmp-scu.c
@@ -7,6 +7,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <linux/cpu.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/io.h>
@@ -16,6 +17,26 @@
#include <asm/smp_scu.h>
#include <mach/common.h>
+static int shmobile_smp_scu_notifier_call(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (long)hcpu;
+
+ switch (action) {
+ case CPU_UP_PREPARE:
+ /* For this particular CPU register SCU SMP boot vector */
+ shmobile_smp_hook(cpu, virt_to_phys(shmobile_boot_scu),
+ (unsigned long)shmobile_scu_base);
+ break;
+ };
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block shmobile_smp_scu_notifier = {
+ .notifier_call = shmobile_smp_scu_notifier_call,
+};
+
void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus)
{
/* install boot code shared by all CPUs */
@@ -25,14 +46,9 @@ void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus)
/* enable SCU and cache coherency on booting CPU */
scu_enable(shmobile_scu_base);
scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
-}
-int shmobile_smp_scu_boot_secondary(unsigned int cpu, struct task_struct *idle)
-{
- /* For this particular CPU register SCU boot vector */
- shmobile_smp_hook(cpu, virt_to_phys(shmobile_boot_scu),
- (unsigned long)shmobile_scu_base);
- return 0;
+ /* Use CPU notifier for reset vector control */
+ register_cpu_notifier(&shmobile_smp_scu_notifier);
}
#ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
index d4ae616bcedb..9ebc246b8d7d 100644
--- a/arch/arm/mach-shmobile/platsmp.c
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -11,25 +11,10 @@
* published by the Free Software Foundation.
*/
#include <linux/init.h>
-#include <linux/smp.h>
#include <asm/cacheflush.h>
#include <asm/smp_plat.h>
#include <mach/common.h>
-void __init shmobile_smp_init_cpus(unsigned int ncores)
-{
- unsigned int i;
-
- if (ncores > nr_cpu_ids) {
- pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
- ncores, nr_cpu_ids);
- ncores = nr_cpu_ids;
- }
-
- for (i = 0; i < ncores; i++)
- set_cpu_possible(i, true);
-}
-
extern unsigned long shmobile_smp_fn[];
extern unsigned long shmobile_smp_arg[];
extern unsigned long shmobile_smp_mpidr[];
@@ -44,3 +29,10 @@ void shmobile_smp_hook(unsigned int cpu, unsigned long fn, unsigned long arg)
shmobile_smp_arg[cpu] = arg;
flush_cache_all();
}
+
+#ifdef CONFIG_HOTPLUG_CPU
+int shmobile_smp_cpu_disable(unsigned int cpu)
+{
+ return 0; /* Hotplug of any CPU is supported */
+}
+#endif
diff --git a/arch/arm/mach-shmobile/setup-r8a73a4.c b/arch/arm/mach-shmobile/setup-r8a73a4.c
index 89491700afb7..53a896275cae 100644
--- a/arch/arm/mach-shmobile/setup-r8a73a4.c
+++ b/arch/arm/mach-shmobile/setup-r8a73a4.c
@@ -207,7 +207,7 @@ void __init r8a73a4_add_standard_devices(void)
r8a73a4_register_thermal();
}
-void __init r8a73a4_init_delay(void)
+void __init r8a73a4_init_early(void)
{
#ifndef CONFIG_ARM_ARCH_TIMER
shmobile_setup_delay(1500, 2, 4); /* Cortex-A15 @ 1500MHz */
@@ -222,7 +222,7 @@ static const char *r8a73a4_boards_compat_dt[] __initdata = {
};
DT_MACHINE_START(R8A73A4_DT, "Generic R8A73A4 (Flattened Device Tree)")
- .init_early = r8a73a4_init_delay,
+ .init_early = r8a73a4_init_early,
.dt_compat = r8a73a4_boards_compat_dt,
MACHINE_END
#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c
index 6a2657ebd197..e484d1420a01 100644
--- a/arch/arm/mach-shmobile/setup-r8a7778.c
+++ b/arch/arm/mach-shmobile/setup-r8a7778.c
@@ -95,29 +95,46 @@ static struct sh_timer_config sh_tmu1_platform_data __initdata = {
&sh_tmu##idx##_platform_data, \
sizeof(sh_tmu##idx##_platform_data))
-/* USB */
-static struct usb_phy *phy;
+int r8a7778_usb_phy_power(bool enable)
+{
+ static struct usb_phy *phy = NULL;
+ int ret = 0;
+
+ if (!phy)
+ phy = usb_get_phy(USB_PHY_TYPE_USB2);
+
+ if (IS_ERR(phy)) {
+ pr_err("kernel doesn't have usb phy driver\n");
+ return PTR_ERR(phy);
+ }
+
+ if (enable)
+ ret = usb_phy_init(phy);
+ else
+ usb_phy_shutdown(phy);
+ return ret;
+}
+
+/* USB */
static int usb_power_on(struct platform_device *pdev)
{
- if (IS_ERR(phy))
- return PTR_ERR(phy);
+ int ret = r8a7778_usb_phy_power(true);
+
+ if (ret)
+ return ret;
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
- usb_phy_init(phy);
-
return 0;
}
static void usb_power_off(struct platform_device *pdev)
{
- if (IS_ERR(phy))
+ if (r8a7778_usb_phy_power(false))
return;
- usb_phy_shutdown(phy);
-
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
}
@@ -353,8 +370,6 @@ void __init r8a7778_add_standard_devices(void)
void __init r8a7778_init_late(void)
{
- phy = usb_get_phy(USB_PHY_TYPE_USB2);
-
platform_device_register_full(&ehci_info);
platform_device_register_full(&ohci_info);
}
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c
index d0f5c9f9349a..c7e24eff9ba2 100644
--- a/arch/arm/mach-shmobile/setup-r8a7790.c
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -31,17 +31,18 @@
#include <mach/r8a7790.h>
#include <asm/mach/arch.h>
-static struct resource pfc_resources[] __initdata = {
+static const struct resource pfc_resources[] __initconst = {
DEFINE_RES_MEM(0xe6060000, 0x250),
};
#define R8A7790_GPIO(idx) \
-static struct resource r8a7790_gpio##idx##_resources[] __initdata = { \
+static const struct resource r8a7790_gpio##idx##_resources[] __initconst = { \
DEFINE_RES_MEM(0xe6050000 + 0x1000 * (idx), 0x50), \
DEFINE_RES_IRQ(gic_spi(4 + (idx))), \
}; \
\
-static struct gpio_rcar_config r8a7790_gpio##idx##_platform_data __initdata = { \
+static const struct gpio_rcar_config \
+r8a7790_gpio##idx##_platform_data __initconst = { \
.gpio_base = 32 * (idx), \
.irq_base = 0, \
.number_of_pins = 32, \
@@ -112,7 +113,7 @@ void __init r8a7790_pinmux_init(void)
enum { SCIFA0, SCIFA1, SCIFB0, SCIFB1, SCIFB2, SCIFA2, SCIF0, SCIF1,
HSCIF0, HSCIF1 };
-static struct plat_sci_port scif[] __initdata = {
+static const struct plat_sci_port scif[] __initconst = {
SCIFA_DATA(SCIFA0, 0xe6c40000, gic_spi(144)), /* SCIFA0 */
SCIFA_DATA(SCIFA1, 0xe6c50000, gic_spi(145)), /* SCIFA1 */
SCIFB_DATA(SCIFB0, 0xe6c20000, gic_spi(148)), /* SCIFB0 */
@@ -131,11 +132,11 @@ static inline void r8a7790_register_scif(int idx)
sizeof(struct plat_sci_port));
}
-static struct renesas_irqc_config irqc0_data __initdata = {
+static const struct renesas_irqc_config irqc0_data __initconst = {
.irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
};
-static struct resource irqc0_resources[] __initdata = {
+static const struct resource irqc0_resources[] __initconst = {
DEFINE_RES_MEM(0xe61c0000, 0x200), /* IRQC Event Detector Block_0 */
DEFINE_RES_IRQ(gic_spi(0)), /* IRQ0 */
DEFINE_RES_IRQ(gic_spi(1)), /* IRQ1 */
@@ -150,7 +151,7 @@ static struct resource irqc0_resources[] __initdata = {
&irqc##idx##_data, \
sizeof(struct renesas_irqc_config))
-static struct resource thermal_resources[] __initdata = {
+static const struct resource thermal_resources[] __initconst = {
DEFINE_RES_MEM(0xe61f0000, 0x14),
DEFINE_RES_MEM(0xe61f0100, 0x38),
DEFINE_RES_IRQ(gic_spi(69)),
@@ -161,13 +162,13 @@ static struct resource thermal_resources[] __initdata = {
thermal_resources, \
ARRAY_SIZE(thermal_resources))
-static struct sh_timer_config cmt00_platform_data __initdata = {
+static const struct sh_timer_config cmt00_platform_data __initconst = {
.name = "CMT00",
.timer_bit = 0,
.clockevent_rating = 80,
};
-static struct resource cmt00_resources[] __initdata = {
+static const struct resource cmt00_resources[] __initconst = {
DEFINE_RES_MEM(0xffca0510, 0x0c),
DEFINE_RES_MEM(0xffca0500, 0x04),
DEFINE_RES_IRQ(gic_spi(142)), /* CMT0_0 */
@@ -267,7 +268,7 @@ void __init r8a7790_timer_init(void)
clocksource_of_init();
}
-void __init r8a7790_init_delay(void)
+void __init r8a7790_init_early(void)
{
#ifndef CONFIG_ARM_ARCH_TIMER
shmobile_setup_delay(1300, 2, 4); /* Cortex-A15 @ 1300MHz */
@@ -276,13 +277,14 @@ void __init r8a7790_init_delay(void)
#ifdef CONFIG_USE_OF
-static const char *r8a7790_boards_compat_dt[] __initdata = {
+static const char * const r8a7790_boards_compat_dt[] __initconst = {
"renesas,r8a7790",
NULL,
};
DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)")
- .init_early = r8a7790_init_delay,
+ .smp = smp_ops(r8a7790_smp_ops),
+ .init_early = r8a7790_init_early,
.init_time = r8a7790_timer_init,
.dt_compat = r8a7790_boards_compat_dt,
MACHINE_END
diff --git a/arch/arm/mach-shmobile/setup-r8a7791.c b/arch/arm/mach-shmobile/setup-r8a7791.c
new file mode 100644
index 000000000000..b56399d2e1de
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-r8a7791.c
@@ -0,0 +1,149 @@
+/*
+ * r8a7791 processor support
+ *
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * 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 of the License.
+ *
+ * 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/irq.h>
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <mach/common.h>
+#include <mach/irqs.h>
+#include <mach/r8a7791.h>
+#include <asm/mach/arch.h>
+
+#define SCIF_COMMON(scif_type, baseaddr, irq) \
+ .type = scif_type, \
+ .mapbase = baseaddr, \
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, \
+ .irqs = SCIx_IRQ_MUXED(irq)
+
+#define SCIFA_DATA(index, baseaddr, irq) \
+[index] = { \
+ SCIF_COMMON(PORT_SCIFA, baseaddr, irq), \
+ .scbrr_algo_id = SCBRR_ALGO_4, \
+ .scscr = SCSCR_RE | SCSCR_TE, \
+}
+
+#define SCIFB_DATA(index, baseaddr, irq) \
+[index] = { \
+ SCIF_COMMON(PORT_SCIFB, baseaddr, irq), \
+ .scbrr_algo_id = SCBRR_ALGO_4, \
+ .scscr = SCSCR_RE | SCSCR_TE, \
+}
+
+#define SCIF_DATA(index, baseaddr, irq) \
+[index] = { \
+ SCIF_COMMON(PORT_SCIF, baseaddr, irq), \
+ .scbrr_algo_id = SCBRR_ALGO_2, \
+ .scscr = SCSCR_RE | SCSCR_TE, \
+}
+
+#define HSCIF_DATA(index, baseaddr, irq) \
+[index] = { \
+ SCIF_COMMON(PORT_HSCIF, baseaddr, irq), \
+ .scbrr_algo_id = SCBRR_ALGO_6, \
+ .scscr = SCSCR_RE | SCSCR_TE, \
+}
+
+enum { SCIFA0, SCIFA1, SCIFB0, SCIFB1, SCIFB2, SCIFA2, SCIF0, SCIF1,
+ SCIF2, SCIF3, SCIF4, SCIF5, SCIFA3, SCIFA4, SCIFA5 };
+
+static const struct plat_sci_port scif[] __initconst = {
+ SCIFA_DATA(SCIFA0, 0xe6c40000, gic_spi(144)), /* SCIFA0 */
+ SCIFA_DATA(SCIFA1, 0xe6c50000, gic_spi(145)), /* SCIFA1 */
+ SCIFB_DATA(SCIFB0, 0xe6c20000, gic_spi(148)), /* SCIFB0 */
+ SCIFB_DATA(SCIFB1, 0xe6c30000, gic_spi(149)), /* SCIFB1 */
+ SCIFB_DATA(SCIFB2, 0xe6ce0000, gic_spi(150)), /* SCIFB2 */
+ SCIFA_DATA(SCIFA2, 0xe6c60000, gic_spi(151)), /* SCIFA2 */
+ SCIF_DATA(SCIF0, 0xe6e60000, gic_spi(152)), /* SCIF0 */
+ SCIF_DATA(SCIF1, 0xe6e68000, gic_spi(153)), /* SCIF1 */
+ SCIF_DATA(SCIF2, 0xe6e58000, gic_spi(22)), /* SCIF2 */
+ SCIF_DATA(SCIF3, 0xe6ea8000, gic_spi(23)), /* SCIF3 */
+ SCIF_DATA(SCIF4, 0xe6ee0000, gic_spi(24)), /* SCIF4 */
+ SCIF_DATA(SCIF5, 0xe6ee8000, gic_spi(25)), /* SCIF5 */
+ SCIFA_DATA(SCIFA3, 0xe6c70000, gic_spi(29)), /* SCIFA3 */
+ SCIFA_DATA(SCIFA4, 0xe6c78000, gic_spi(30)), /* SCIFA4 */
+ SCIFA_DATA(SCIFA5, 0xe6c80000, gic_spi(31)), /* SCIFA5 */
+};
+
+static inline void r8a7791_register_scif(int idx)
+{
+ platform_device_register_data(&platform_bus, "sh-sci", idx, &scif[idx],
+ sizeof(struct plat_sci_port));
+}
+
+static const struct sh_timer_config cmt00_platform_data __initconst = {
+ .name = "CMT00",
+ .timer_bit = 0,
+ .clockevent_rating = 80,
+};
+
+static const struct resource cmt00_resources[] __initconst = {
+ DEFINE_RES_MEM(0xffca0510, 0x0c),
+ DEFINE_RES_MEM(0xffca0500, 0x04),
+ DEFINE_RES_IRQ(gic_spi(142)), /* CMT0_0 */
+};
+
+#define r8a7791_register_cmt(idx) \
+ platform_device_register_resndata(&platform_bus, "sh_cmt", \
+ idx, cmt##idx##_resources, \
+ ARRAY_SIZE(cmt##idx##_resources), \
+ &cmt##idx##_platform_data, \
+ sizeof(struct sh_timer_config))
+
+void __init r8a7791_add_dt_devices(void)
+{
+ r8a7791_register_scif(SCIFA0);
+ r8a7791_register_scif(SCIFA1);
+ r8a7791_register_scif(SCIFB0);
+ r8a7791_register_scif(SCIFB1);
+ r8a7791_register_scif(SCIFB2);
+ r8a7791_register_scif(SCIFA2);
+ r8a7791_register_scif(SCIF0);
+ r8a7791_register_scif(SCIF1);
+ r8a7791_register_scif(SCIF2);
+ r8a7791_register_scif(SCIF3);
+ r8a7791_register_scif(SCIF4);
+ r8a7791_register_scif(SCIF5);
+ r8a7791_register_scif(SCIFA3);
+ r8a7791_register_scif(SCIFA4);
+ r8a7791_register_scif(SCIFA5);
+ r8a7791_register_cmt(00);
+}
+
+void __init r8a7791_init_early(void)
+{
+#ifndef CONFIG_ARM_ARCH_TIMER
+ shmobile_setup_delay(1300, 2, 4); /* Cortex-A15 @ 1300MHz */
+#endif
+}
+
+#ifdef CONFIG_USE_OF
+static const char *r8a7791_boards_compat_dt[] __initdata = {
+ "renesas,r8a7791",
+ NULL,
+};
+
+DT_MACHINE_START(R8A7791_DT, "Generic R8A7791 (Flattened Device Tree)")
+ .init_early = r8a7791_init_early,
+ .dt_compat = r8a7791_boards_compat_dt,
+MACHINE_END
+#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c
index 522de5ebb55f..f2ca92308f75 100644
--- a/arch/arm/mach-shmobile/smp-emev2.c
+++ b/arch/arm/mach-shmobile/smp-emev2.c
@@ -34,12 +34,6 @@
static int emev2_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
- int ret;
-
- ret = shmobile_smp_scu_boot_secondary(cpu, idle);
- if (ret)
- return ret;
-
arch_send_wakeup_ipi_mask(cpumask_of(cpu_logical_map(cpu)));
return 0;
}
diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c
index 0f05e9fb722f..627c1f0d9478 100644
--- a/arch/arm/mach-shmobile/smp-r8a7779.c
+++ b/arch/arm/mach-shmobile/smp-r8a7779.c
@@ -87,10 +87,6 @@ static int r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle)
unsigned int lcpu = cpu_logical_map(cpu);
int ret;
- ret = shmobile_smp_scu_boot_secondary(cpu, idle);
- if (ret)
- return ret;
-
if (lcpu < ARRAY_SIZE(r8a7779_ch_cpu))
ch = r8a7779_ch_cpu[lcpu];
diff --git a/arch/arm/mach-shmobile/smp-r8a7790.c b/arch/arm/mach-shmobile/smp-r8a7790.c
new file mode 100644
index 000000000000..015e2753de1f
--- /dev/null
+++ b/arch/arm/mach-shmobile/smp-r8a7790.c
@@ -0,0 +1,67 @@
+/*
+ * SMP support for r8a7790
+ *
+ * Copyright (C) 2012-2013 Renesas Solutions Corp.
+ * Copyright (C) 2012 Takashi Yoshii <takashi.yoshii.ze@renesas.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; version 2 of the License.
+ *
+ * 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.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <asm/smp_plat.h>
+#include <mach/common.h>
+
+#define RST 0xe6160000
+#define CA15BAR 0x0020
+#define CA7BAR 0x0030
+#define CA15RESCNT 0x0040
+#define CA7RESCNT 0x0044
+#define MERAM 0xe8080000
+
+static void __init r8a7790_smp_prepare_cpus(unsigned int max_cpus)
+{
+ void __iomem *p;
+ u32 bar;
+
+ /* let APMU code install data related to shmobile_boot_vector */
+ shmobile_smp_apmu_prepare_cpus(max_cpus);
+
+ /* MERAM for jump stub, because BAR requires 256KB aligned address */
+ p = ioremap_nocache(MERAM, shmobile_boot_size);
+ memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
+ iounmap(p);
+
+ /* setup reset vectors */
+ p = ioremap_nocache(RST, 0x63);
+ bar = (MERAM >> 8) & 0xfffffc00;
+ writel_relaxed(bar, p + CA15BAR);
+ writel_relaxed(bar, p + CA7BAR);
+ writel_relaxed(bar | 0x10, p + CA15BAR);
+ writel_relaxed(bar | 0x10, p + CA7BAR);
+
+ /* enable clocks to all CPUs */
+ writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000,
+ p + CA15RESCNT);
+ writel_relaxed((readl_relaxed(p + CA7RESCNT) & ~0x0f) | 0x5a5a0000,
+ p + CA7RESCNT);
+ iounmap(p);
+}
+
+struct smp_operations r8a7790_smp_ops __initdata = {
+ .smp_prepare_cpus = r8a7790_smp_prepare_cpus,
+ .smp_boot_secondary = shmobile_smp_apmu_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_disable = shmobile_smp_cpu_disable,
+ .cpu_die = shmobile_smp_apmu_cpu_die,
+ .cpu_kill = shmobile_smp_apmu_cpu_kill,
+#endif
+};
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index 0baa24443793..13ba36a6831f 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -46,11 +46,6 @@ void __init sh73a0_register_twd(void)
static int sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
unsigned int lcpu = cpu_logical_map(cpu);
- int ret;
-
- ret = shmobile_smp_scu_boot_secondary(cpu, idle);
- if (ret)
- return ret;
if (((__raw_readl(PSTR) >> (4 * lcpu)) & 3) == 3)
__raw_writel(1 << lcpu, WUPCR); /* wake up */
@@ -71,18 +66,11 @@ static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
shmobile_smp_scu_prepare_cpus(max_cpus);
}
-#ifdef CONFIG_HOTPLUG_CPU
-static int sh73a0_cpu_disable(unsigned int cpu)
-{
- return 0; /* CPU0 and CPU1 supported */
-}
-#endif /* CONFIG_HOTPLUG_CPU */
-
struct smp_operations sh73a0_smp_ops __initdata = {
.smp_prepare_cpus = sh73a0_smp_prepare_cpus,
.smp_boot_secondary = sh73a0_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
- .cpu_disable = sh73a0_cpu_disable,
+ .cpu_disable = shmobile_smp_cpu_disable,
.cpu_die = shmobile_smp_scu_cpu_die,
.cpu_kill = shmobile_smp_scu_cpu_kill,
#endif
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index e7e5f45c6558..97eb48e977e5 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -1,6 +1,5 @@
asflags-y += -march=armv7-a
-obj-y += common.o
obj-y += io.o
obj-y += irq.o
obj-y += fuse.o
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
index 740e16f64728..06f024070dab 100644
--- a/arch/arm/mach-tegra/board-paz00.c
+++ b/arch/arm/mach-tegra/board-paz00.c
@@ -20,12 +20,11 @@
#include <linux/platform_device.h>
#include <linux/rfkill-gpio.h>
#include "board.h"
-#include "board-paz00.h"
static struct rfkill_gpio_platform_data wifi_rfkill_platform_data = {
.name = "wifi_rfkill",
- .reset_gpio = TEGRA_WIFI_RST,
- .shutdown_gpio = TEGRA_WIFI_PWRN,
+ .reset_gpio = 25, /* PD1 */
+ .shutdown_gpio = 85, /* PK5 */
.type = RFKILL_TYPE_WLAN,
};
diff --git a/arch/arm/mach-tegra/board-paz00.h b/arch/arm/mach-tegra/board-paz00.h
deleted file mode 100644
index 25c08ecef52f..000000000000
--- a/arch/arm/mach-tegra/board-paz00.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * arch/arm/mach-tegra/board-paz00.h
- *
- * Copyright (C) 2010 Marc Dietrich <marvin24@gmx.de>
- *
- * 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.
- *
- */
-
-#ifndef _MACH_TEGRA_BOARD_PAZ00_H
-#define _MACH_TEGRA_BOARD_PAZ00_H
-
-#include "gpio-names.h"
-
-#define TEGRA_WIFI_PWRN TEGRA_GPIO_PK5
-#define TEGRA_WIFI_RST TEGRA_GPIO_PD1
-
-#endif
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
index db6810dc0b3d..bcf5dbf69d58 100644
--- a/arch/arm/mach-tegra/board.h
+++ b/arch/arm/mach-tegra/board.h
@@ -25,20 +25,8 @@
#include <linux/types.h>
#include <linux/reboot.h>
-void tegra_assert_system_reset(enum reboot_mode mode, const char *cmd);
-
-void __init tegra_init_early(void);
void __init tegra_map_common_io(void);
void __init tegra_init_irq(void);
-void __init tegra_dt_init_irq(void);
-
-void tegra_init_late(void);
-
-#ifdef CONFIG_DEBUG_FS
-int tegra_clk_debugfs_init(void);
-#else
-static inline int tegra_clk_debugfs_init(void) { return 0; }
-#endif
int __init tegra_powergate_init(void);
#if defined(CONFIG_ARCH_TEGRA_2x_SOC) && defined(CONFIG_DEBUG_FS)
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
deleted file mode 100644
index 94a119a35af8..000000000000
--- a/arch/arm/mach-tegra/common.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * arch/arm/mach-tegra/common.c
- *
- * Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- * Colin Cross <ccross@android.com>
- *
- * 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.
- *
- */
-
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/reboot.h>
-#include <linux/irqchip.h>
-#include <linux/clk-provider.h>
-
-#include <asm/hardware/cache-l2x0.h>
-
-#include "board.h"
-#include "common.h"
-#include "cpuidle.h"
-#include "fuse.h"
-#include "iomap.h"
-#include "irq.h"
-#include "pmc.h"
-#include "apbio.h"
-#include "sleep.h"
-#include "pm.h"
-#include "reset.h"
-
-/*
- * Storage for debug-macro.S's state.
- *
- * This must be in .data not .bss so that it gets initialized each time the
- * kernel is loaded. The data is declared here rather than debug-macro.S so
- * that multiple inclusions of debug-macro.S point at the same data.
- */
-u32 tegra_uart_config[4] = {
- /* Debug UART initialization required */
- 1,
- /* Debug UART physical address */
- 0,
- /* Debug UART virtual address */
- 0,
- /* Scratch space for debug macro */
- 0,
-};
-
-#ifdef CONFIG_OF
-void __init tegra_dt_init_irq(void)
-{
- of_clk_init(NULL);
- tegra_pmc_init();
- tegra_init_irq();
- irqchip_init();
- tegra_legacy_irq_syscore_init();
-}
-#endif
-
-void tegra_assert_system_reset(enum reboot_mode mode, const char *cmd)
-{
- void __iomem *reset = IO_ADDRESS(TEGRA_PMC_BASE + 0);
- u32 reg;
-
- reg = readl_relaxed(reset);
- reg |= 0x10;
- writel_relaxed(reg, reset);
-}
-
-static void __init tegra_init_cache(void)
-{
-#ifdef CONFIG_CACHE_L2X0
- int ret;
- void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
- u32 aux_ctrl, cache_type;
-
- cache_type = readl(p + L2X0_CACHE_TYPE);
- aux_ctrl = (cache_type & 0x700) << (17-8);
- aux_ctrl |= 0x7C400001;
-
- ret = l2x0_of_init(aux_ctrl, 0x8200c3fe);
- if (!ret)
- l2x0_saved_regs_addr = virt_to_phys(&l2x0_saved_regs);
-#endif
-
-}
-
-void __init tegra_init_early(void)
-{
- tegra_cpu_reset_handler_init();
- tegra_apb_io_init();
- tegra_init_fuse();
- tegra_init_cache();
- tegra_powergate_init();
- tegra_hotplug_init();
-}
-
-void __init tegra_init_late(void)
-{
- tegra_init_suspend();
- tegra_cpuidle_init();
- tegra_powergate_debugfs_init();
-}
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
index e035cd284a6e..9a4e910c3796 100644
--- a/arch/arm/mach-tegra/fuse.c
+++ b/arch/arm/mach-tegra/fuse.c
@@ -21,14 +21,26 @@
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/export.h>
+#include <linux/random.h>
#include <linux/tegra-soc.h>
#include "fuse.h"
#include "iomap.h"
#include "apbio.h"
+/* Tegra20 only */
#define FUSE_UID_LOW 0x108
#define FUSE_UID_HIGH 0x10c
+
+/* Tegra30 and later */
+#define FUSE_VENDOR_CODE 0x200
+#define FUSE_FAB_CODE 0x204
+#define FUSE_LOT_CODE_0 0x208
+#define FUSE_LOT_CODE_1 0x20c
+#define FUSE_WAFER_ID 0x210
+#define FUSE_X_COORDINATE 0x214
+#define FUSE_Y_COORDINATE 0x218
+
#define FUSE_SKU_INFO 0x110
#define TEGRA20_FUSE_SPARE_BIT 0x200
@@ -112,21 +124,51 @@ u32 tegra_read_chipid(void)
return readl_relaxed(IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804);
}
-void tegra_init_fuse(void)
+static void __init tegra20_fuse_init_randomness(void)
+{
+ u32 randomness[2];
+
+ randomness[0] = tegra_fuse_readl(FUSE_UID_LOW);
+ randomness[1] = tegra_fuse_readl(FUSE_UID_HIGH);
+
+ add_device_randomness(randomness, sizeof(randomness));
+}
+
+/* Applies to Tegra30 or later */
+static void __init tegra30_fuse_init_randomness(void)
+{
+ u32 randomness[7];
+
+ randomness[0] = tegra_fuse_readl(FUSE_VENDOR_CODE);
+ randomness[1] = tegra_fuse_readl(FUSE_FAB_CODE);
+ randomness[2] = tegra_fuse_readl(FUSE_LOT_CODE_0);
+ randomness[3] = tegra_fuse_readl(FUSE_LOT_CODE_1);
+ randomness[4] = tegra_fuse_readl(FUSE_WAFER_ID);
+ randomness[5] = tegra_fuse_readl(FUSE_X_COORDINATE);
+ randomness[6] = tegra_fuse_readl(FUSE_Y_COORDINATE);
+
+ add_device_randomness(randomness, sizeof(randomness));
+}
+
+void __init tegra_init_fuse(void)
{
u32 id;
+ u32 randomness[5];
u32 reg = readl(IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x48));
reg |= 1 << 28;
writel(reg, IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x48));
reg = tegra_fuse_readl(FUSE_SKU_INFO);
+ randomness[0] = reg;
tegra_sku_id = reg & 0xFF;
reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT);
+ randomness[1] = reg;
tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT;
id = tegra_read_chipid();
+ randomness[2] = id;
tegra_chip_id = (id >> 8) & 0xff;
switch (tegra_chip_id) {
@@ -149,19 +191,21 @@ void tegra_init_fuse(void)
tegra_revision = tegra_get_revision(id);
tegra_init_speedo_data();
+ randomness[3] = (tegra_cpu_process_id << 16) | tegra_core_process_id;
+ randomness[4] = (tegra_cpu_speedo_id << 16) | tegra_soc_speedo_id;
+
+ add_device_randomness(randomness, sizeof(randomness));
+ switch (tegra_chip_id) {
+ case TEGRA20:
+ tegra20_fuse_init_randomness();
+ case TEGRA30:
+ case TEGRA114:
+ default:
+ tegra30_fuse_init_randomness();
+ }
pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
tegra_revision_name[tegra_revision],
tegra_sku_id, tegra_cpu_process_id,
tegra_core_process_id);
}
-
-unsigned long long tegra_chip_uid(void)
-{
- unsigned long long lo, hi;
-
- lo = tegra_fuse_readl(FUSE_UID_LOW);
- hi = tegra_fuse_readl(FUSE_UID_HIGH);
- return (hi << 32ull) | lo;
-}
-EXPORT_SYMBOL(tegra_chip_uid);
diff --git a/arch/arm/mach-tegra/gpio-names.h b/arch/arm/mach-tegra/gpio-names.h
deleted file mode 100644
index f28220a641b2..000000000000
--- a/arch/arm/mach-tegra/gpio-names.h
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/gpio-names.h
- *
- * Copyright (c) 2010 Google, Inc
- *
- * Author:
- * Erik Gilling <konkers@google.com>
- *
- * 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.
- */
-
-#ifndef __MACH_TEGRA_GPIO_NAMES_H
-#define __MACH_TEGRA_GPIO_NAMES_H
-
-#define TEGRA_GPIO_PA0 0
-#define TEGRA_GPIO_PA1 1
-#define TEGRA_GPIO_PA2 2
-#define TEGRA_GPIO_PA3 3
-#define TEGRA_GPIO_PA4 4
-#define TEGRA_GPIO_PA5 5
-#define TEGRA_GPIO_PA6 6
-#define TEGRA_GPIO_PA7 7
-#define TEGRA_GPIO_PB0 8
-#define TEGRA_GPIO_PB1 9
-#define TEGRA_GPIO_PB2 10
-#define TEGRA_GPIO_PB3 11
-#define TEGRA_GPIO_PB4 12
-#define TEGRA_GPIO_PB5 13
-#define TEGRA_GPIO_PB6 14
-#define TEGRA_GPIO_PB7 15
-#define TEGRA_GPIO_PC0 16
-#define TEGRA_GPIO_PC1 17
-#define TEGRA_GPIO_PC2 18
-#define TEGRA_GPIO_PC3 19
-#define TEGRA_GPIO_PC4 20
-#define TEGRA_GPIO_PC5 21
-#define TEGRA_GPIO_PC6 22
-#define TEGRA_GPIO_PC7 23
-#define TEGRA_GPIO_PD0 24
-#define TEGRA_GPIO_PD1 25
-#define TEGRA_GPIO_PD2 26
-#define TEGRA_GPIO_PD3 27
-#define TEGRA_GPIO_PD4 28
-#define TEGRA_GPIO_PD5 29
-#define TEGRA_GPIO_PD6 30
-#define TEGRA_GPIO_PD7 31
-#define TEGRA_GPIO_PE0 32
-#define TEGRA_GPIO_PE1 33
-#define TEGRA_GPIO_PE2 34
-#define TEGRA_GPIO_PE3 35
-#define TEGRA_GPIO_PE4 36
-#define TEGRA_GPIO_PE5 37
-#define TEGRA_GPIO_PE6 38
-#define TEGRA_GPIO_PE7 39
-#define TEGRA_GPIO_PF0 40
-#define TEGRA_GPIO_PF1 41
-#define TEGRA_GPIO_PF2 42
-#define TEGRA_GPIO_PF3 43
-#define TEGRA_GPIO_PF4 44
-#define TEGRA_GPIO_PF5 45
-#define TEGRA_GPIO_PF6 46
-#define TEGRA_GPIO_PF7 47
-#define TEGRA_GPIO_PG0 48
-#define TEGRA_GPIO_PG1 49
-#define TEGRA_GPIO_PG2 50
-#define TEGRA_GPIO_PG3 51
-#define TEGRA_GPIO_PG4 52
-#define TEGRA_GPIO_PG5 53
-#define TEGRA_GPIO_PG6 54
-#define TEGRA_GPIO_PG7 55
-#define TEGRA_GPIO_PH0 56
-#define TEGRA_GPIO_PH1 57
-#define TEGRA_GPIO_PH2 58
-#define TEGRA_GPIO_PH3 59
-#define TEGRA_GPIO_PH4 60
-#define TEGRA_GPIO_PH5 61
-#define TEGRA_GPIO_PH6 62
-#define TEGRA_GPIO_PH7 63
-#define TEGRA_GPIO_PI0 64
-#define TEGRA_GPIO_PI1 65
-#define TEGRA_GPIO_PI2 66
-#define TEGRA_GPIO_PI3 67
-#define TEGRA_GPIO_PI4 68
-#define TEGRA_GPIO_PI5 69
-#define TEGRA_GPIO_PI6 70
-#define TEGRA_GPIO_PI7 71
-#define TEGRA_GPIO_PJ0 72
-#define TEGRA_GPIO_PJ1 73
-#define TEGRA_GPIO_PJ2 74
-#define TEGRA_GPIO_PJ3 75
-#define TEGRA_GPIO_PJ4 76
-#define TEGRA_GPIO_PJ5 77
-#define TEGRA_GPIO_PJ6 78
-#define TEGRA_GPIO_PJ7 79
-#define TEGRA_GPIO_PK0 80
-#define TEGRA_GPIO_PK1 81
-#define TEGRA_GPIO_PK2 82
-#define TEGRA_GPIO_PK3 83
-#define TEGRA_GPIO_PK4 84
-#define TEGRA_GPIO_PK5 85
-#define TEGRA_GPIO_PK6 86
-#define TEGRA_GPIO_PK7 87
-#define TEGRA_GPIO_PL0 88
-#define TEGRA_GPIO_PL1 89
-#define TEGRA_GPIO_PL2 90
-#define TEGRA_GPIO_PL3 91
-#define TEGRA_GPIO_PL4 92
-#define TEGRA_GPIO_PL5 93
-#define TEGRA_GPIO_PL6 94
-#define TEGRA_GPIO_PL7 95
-#define TEGRA_GPIO_PM0 96
-#define TEGRA_GPIO_PM1 97
-#define TEGRA_GPIO_PM2 98
-#define TEGRA_GPIO_PM3 99
-#define TEGRA_GPIO_PM4 100
-#define TEGRA_GPIO_PM5 101
-#define TEGRA_GPIO_PM6 102
-#define TEGRA_GPIO_PM7 103
-#define TEGRA_GPIO_PN0 104
-#define TEGRA_GPIO_PN1 105
-#define TEGRA_GPIO_PN2 106
-#define TEGRA_GPIO_PN3 107
-#define TEGRA_GPIO_PN4 108
-#define TEGRA_GPIO_PN5 109
-#define TEGRA_GPIO_PN6 110
-#define TEGRA_GPIO_PN7 111
-#define TEGRA_GPIO_PO0 112
-#define TEGRA_GPIO_PO1 113
-#define TEGRA_GPIO_PO2 114
-#define TEGRA_GPIO_PO3 115
-#define TEGRA_GPIO_PO4 116
-#define TEGRA_GPIO_PO5 117
-#define TEGRA_GPIO_PO6 118
-#define TEGRA_GPIO_PO7 119
-#define TEGRA_GPIO_PP0 120
-#define TEGRA_GPIO_PP1 121
-#define TEGRA_GPIO_PP2 122
-#define TEGRA_GPIO_PP3 123
-#define TEGRA_GPIO_PP4 124
-#define TEGRA_GPIO_PP5 125
-#define TEGRA_GPIO_PP6 126
-#define TEGRA_GPIO_PP7 127
-#define TEGRA_GPIO_PQ0 128
-#define TEGRA_GPIO_PQ1 129
-#define TEGRA_GPIO_PQ2 130
-#define TEGRA_GPIO_PQ3 131
-#define TEGRA_GPIO_PQ4 132
-#define TEGRA_GPIO_PQ5 133
-#define TEGRA_GPIO_PQ6 134
-#define TEGRA_GPIO_PQ7 135
-#define TEGRA_GPIO_PR0 136
-#define TEGRA_GPIO_PR1 137
-#define TEGRA_GPIO_PR2 138
-#define TEGRA_GPIO_PR3 139
-#define TEGRA_GPIO_PR4 140
-#define TEGRA_GPIO_PR5 141
-#define TEGRA_GPIO_PR6 142
-#define TEGRA_GPIO_PR7 143
-#define TEGRA_GPIO_PS0 144
-#define TEGRA_GPIO_PS1 145
-#define TEGRA_GPIO_PS2 146
-#define TEGRA_GPIO_PS3 147
-#define TEGRA_GPIO_PS4 148
-#define TEGRA_GPIO_PS5 149
-#define TEGRA_GPIO_PS6 150
-#define TEGRA_GPIO_PS7 151
-#define TEGRA_GPIO_PT0 152
-#define TEGRA_GPIO_PT1 153
-#define TEGRA_GPIO_PT2 154
-#define TEGRA_GPIO_PT3 155
-#define TEGRA_GPIO_PT4 156
-#define TEGRA_GPIO_PT5 157
-#define TEGRA_GPIO_PT6 158
-#define TEGRA_GPIO_PT7 159
-#define TEGRA_GPIO_PU0 160
-#define TEGRA_GPIO_PU1 161
-#define TEGRA_GPIO_PU2 162
-#define TEGRA_GPIO_PU3 163
-#define TEGRA_GPIO_PU4 164
-#define TEGRA_GPIO_PU5 165
-#define TEGRA_GPIO_PU6 166
-#define TEGRA_GPIO_PU7 167
-#define TEGRA_GPIO_PV0 168
-#define TEGRA_GPIO_PV1 169
-#define TEGRA_GPIO_PV2 170
-#define TEGRA_GPIO_PV3 171
-#define TEGRA_GPIO_PV4 172
-#define TEGRA_GPIO_PV5 173
-#define TEGRA_GPIO_PV6 174
-#define TEGRA_GPIO_PV7 175
-#define TEGRA_GPIO_PW0 176
-#define TEGRA_GPIO_PW1 177
-#define TEGRA_GPIO_PW2 178
-#define TEGRA_GPIO_PW3 179
-#define TEGRA_GPIO_PW4 180
-#define TEGRA_GPIO_PW5 181
-#define TEGRA_GPIO_PW6 182
-#define TEGRA_GPIO_PW7 183
-#define TEGRA_GPIO_PX0 184
-#define TEGRA_GPIO_PX1 185
-#define TEGRA_GPIO_PX2 186
-#define TEGRA_GPIO_PX3 187
-#define TEGRA_GPIO_PX4 188
-#define TEGRA_GPIO_PX5 189
-#define TEGRA_GPIO_PX6 190
-#define TEGRA_GPIO_PX7 191
-#define TEGRA_GPIO_PY0 192
-#define TEGRA_GPIO_PY1 193
-#define TEGRA_GPIO_PY2 194
-#define TEGRA_GPIO_PY3 195
-#define TEGRA_GPIO_PY4 196
-#define TEGRA_GPIO_PY5 197
-#define TEGRA_GPIO_PY6 198
-#define TEGRA_GPIO_PY7 199
-#define TEGRA_GPIO_PZ0 200
-#define TEGRA_GPIO_PZ1 201
-#define TEGRA_GPIO_PZ2 202
-#define TEGRA_GPIO_PZ3 203
-#define TEGRA_GPIO_PZ4 204
-#define TEGRA_GPIO_PZ5 205
-#define TEGRA_GPIO_PZ6 206
-#define TEGRA_GPIO_PZ7 207
-#define TEGRA_GPIO_PAA0 208
-#define TEGRA_GPIO_PAA1 209
-#define TEGRA_GPIO_PAA2 210
-#define TEGRA_GPIO_PAA3 211
-#define TEGRA_GPIO_PAA4 212
-#define TEGRA_GPIO_PAA5 213
-#define TEGRA_GPIO_PAA6 214
-#define TEGRA_GPIO_PAA7 215
-#define TEGRA_GPIO_PBB0 216
-#define TEGRA_GPIO_PBB1 217
-#define TEGRA_GPIO_PBB2 218
-#define TEGRA_GPIO_PBB3 219
-#define TEGRA_GPIO_PBB4 220
-#define TEGRA_GPIO_PBB5 221
-#define TEGRA_GPIO_PBB6 222
-#define TEGRA_GPIO_PBB7 223
-
-#endif
diff --git a/arch/arm/mach-tegra/iomap.h b/arch/arm/mach-tegra/iomap.h
index 3f5fa0749bde..cbee57fc4fd8 100644
--- a/arch/arm/mach-tegra/iomap.h
+++ b/arch/arm/mach-tegra/iomap.h
@@ -24,44 +24,12 @@
#define TEGRA_IRAM_BASE 0x40000000
#define TEGRA_IRAM_SIZE SZ_256K
-#define TEGRA_IRAM_CODE_AREA (TEGRA_IRAM_BASE + SZ_4K)
-
-#define TEGRA_HOST1X_BASE 0x50000000
-#define TEGRA_HOST1X_SIZE 0x24000
-
#define TEGRA_ARM_PERIF_BASE 0x50040000
#define TEGRA_ARM_PERIF_SIZE SZ_8K
-#define TEGRA_ARM_PL310_BASE 0x50043000
-#define TEGRA_ARM_PL310_SIZE SZ_4K
-
#define TEGRA_ARM_INT_DIST_BASE 0x50041000
#define TEGRA_ARM_INT_DIST_SIZE SZ_4K
-#define TEGRA_MPE_BASE 0x54040000
-#define TEGRA_MPE_SIZE SZ_256K
-
-#define TEGRA_VI_BASE 0x54080000
-#define TEGRA_VI_SIZE SZ_256K
-
-#define TEGRA_ISP_BASE 0x54100000
-#define TEGRA_ISP_SIZE SZ_256K
-
-#define TEGRA_DISPLAY_BASE 0x54200000
-#define TEGRA_DISPLAY_SIZE SZ_256K
-
-#define TEGRA_DISPLAY2_BASE 0x54240000
-#define TEGRA_DISPLAY2_SIZE SZ_256K
-
-#define TEGRA_HDMI_BASE 0x54280000
-#define TEGRA_HDMI_SIZE SZ_256K
-
-#define TEGRA_GART_BASE 0x58000000
-#define TEGRA_GART_SIZE SZ_32M
-
-#define TEGRA_RES_SEMA_BASE 0x60001000
-#define TEGRA_RES_SEMA_SIZE SZ_4K
-
#define TEGRA_PRIMARY_ICTLR_BASE 0x60004000
#define TEGRA_PRIMARY_ICTLR_SIZE SZ_64
@@ -98,51 +66,15 @@
#define TEGRA_FLOW_CTRL_BASE 0x60007000
#define TEGRA_FLOW_CTRL_SIZE 20
-#define TEGRA_AHB_DMA_BASE 0x60008000
-#define TEGRA_AHB_DMA_SIZE SZ_4K
-
-#define TEGRA_AHB_DMA_CH0_BASE 0x60009000
-#define TEGRA_AHB_DMA_CH0_SIZE 32
-
-#define TEGRA_APB_DMA_BASE 0x6000A000
-#define TEGRA_APB_DMA_SIZE SZ_4K
-
-#define TEGRA_APB_DMA_CH0_BASE 0x6000B000
-#define TEGRA_APB_DMA_CH0_SIZE 32
-
-#define TEGRA_AHB_GIZMO_BASE 0x6000C004
-#define TEGRA_AHB_GIZMO_SIZE 0x10C
-
#define TEGRA_SB_BASE 0x6000C200
#define TEGRA_SB_SIZE 256
-#define TEGRA_STATMON_BASE 0x6000C400
-#define TEGRA_STATMON_SIZE SZ_1K
-
-#define TEGRA_GPIO_BASE 0x6000D000
-#define TEGRA_GPIO_SIZE SZ_4K
-
#define TEGRA_EXCEPTION_VECTORS_BASE 0x6000F000
#define TEGRA_EXCEPTION_VECTORS_SIZE SZ_4K
#define TEGRA_APB_MISC_BASE 0x70000000
#define TEGRA_APB_MISC_SIZE SZ_4K
-#define TEGRA_APB_MISC_DAS_BASE 0x70000c00
-#define TEGRA_APB_MISC_DAS_SIZE SZ_128
-
-#define TEGRA_AC97_BASE 0x70002000
-#define TEGRA_AC97_SIZE SZ_512
-
-#define TEGRA_SPDIF_BASE 0x70002400
-#define TEGRA_SPDIF_SIZE SZ_512
-
-#define TEGRA_I2S1_BASE 0x70002800
-#define TEGRA_I2S1_SIZE SZ_256
-
-#define TEGRA_I2S2_BASE 0x70002A00
-#define TEGRA_I2S2_SIZE SZ_256
-
#define TEGRA_UARTA_BASE 0x70006000
#define TEGRA_UARTA_SIZE SZ_64
@@ -158,87 +90,15 @@
#define TEGRA_UARTE_BASE 0x70006400
#define TEGRA_UARTE_SIZE SZ_256
-#define TEGRA_NAND_BASE 0x70008000
-#define TEGRA_NAND_SIZE SZ_256
-
-#define TEGRA_HSMMC_BASE 0x70008500
-#define TEGRA_HSMMC_SIZE SZ_256
-
-#define TEGRA_SNOR_BASE 0x70009000
-#define TEGRA_SNOR_SIZE SZ_4K
-
-#define TEGRA_PWFM_BASE 0x7000A000
-#define TEGRA_PWFM_SIZE SZ_256
-
-#define TEGRA_PWFM0_BASE 0x7000A000
-#define TEGRA_PWFM0_SIZE 4
-
-#define TEGRA_PWFM1_BASE 0x7000A010
-#define TEGRA_PWFM1_SIZE 4
-
-#define TEGRA_PWFM2_BASE 0x7000A020
-#define TEGRA_PWFM2_SIZE 4
-
-#define TEGRA_PWFM3_BASE 0x7000A030
-#define TEGRA_PWFM3_SIZE 4
-
-#define TEGRA_MIPI_BASE 0x7000B000
-#define TEGRA_MIPI_SIZE SZ_256
-
-#define TEGRA_I2C_BASE 0x7000C000
-#define TEGRA_I2C_SIZE SZ_256
-
-#define TEGRA_TWC_BASE 0x7000C100
-#define TEGRA_TWC_SIZE SZ_256
-
-#define TEGRA_SPI_BASE 0x7000C380
-#define TEGRA_SPI_SIZE 48
-
-#define TEGRA_I2C2_BASE 0x7000C400
-#define TEGRA_I2C2_SIZE SZ_256
-
-#define TEGRA_I2C3_BASE 0x7000C500
-#define TEGRA_I2C3_SIZE SZ_256
-
-#define TEGRA_OWR_BASE 0x7000C600
-#define TEGRA_OWR_SIZE 80
-
-#define TEGRA_DVC_BASE 0x7000D000
-#define TEGRA_DVC_SIZE SZ_512
-
-#define TEGRA_SPI1_BASE 0x7000D400
-#define TEGRA_SPI1_SIZE SZ_512
-
-#define TEGRA_SPI2_BASE 0x7000D600
-#define TEGRA_SPI2_SIZE SZ_512
-
-#define TEGRA_SPI3_BASE 0x7000D800
-#define TEGRA_SPI3_SIZE SZ_512
-
-#define TEGRA_SPI4_BASE 0x7000DA00
-#define TEGRA_SPI4_SIZE SZ_512
-
-#define TEGRA_RTC_BASE 0x7000E000
-#define TEGRA_RTC_SIZE SZ_256
-
-#define TEGRA_KBC_BASE 0x7000E200
-#define TEGRA_KBC_SIZE SZ_256
-
#define TEGRA_PMC_BASE 0x7000E400
#define TEGRA_PMC_SIZE SZ_256
-#define TEGRA_MC_BASE 0x7000F000
-#define TEGRA_MC_SIZE SZ_1K
-
#define TEGRA_EMC_BASE 0x7000F400
#define TEGRA_EMC_SIZE SZ_1K
#define TEGRA_FUSE_BASE 0x7000F800
#define TEGRA_FUSE_SIZE SZ_1K
-#define TEGRA_KFUSE_BASE 0x7000FC00
-#define TEGRA_KFUSE_SIZE SZ_1K
-
#define TEGRA_EMC0_BASE 0x7001A000
#define TEGRA_EMC0_SIZE SZ_2K
@@ -248,18 +108,6 @@
#define TEGRA_CSITE_BASE 0x70040000
#define TEGRA_CSITE_SIZE SZ_256K
-#define TEGRA_SDMMC1_BASE 0xC8000000
-#define TEGRA_SDMMC1_SIZE SZ_512
-
-#define TEGRA_SDMMC2_BASE 0xC8000200
-#define TEGRA_SDMMC2_SIZE SZ_512
-
-#define TEGRA_SDMMC3_BASE 0xC8000400
-#define TEGRA_SDMMC3_SIZE SZ_512
-
-#define TEGRA_SDMMC4_BASE 0xC8000600
-#define TEGRA_SDMMC4_SIZE SZ_512
-
/* On TEGRA, many peripherals are very closely packed in
* two 256MB io windows (that actually only use about 64KB
* at the start of each).
diff --git a/arch/arm/mach-tegra/irammap.h b/arch/arm/mach-tegra/irammap.h
index 501952a84344..e32e1742c9a1 100644
--- a/arch/arm/mach-tegra/irammap.h
+++ b/arch/arm/mach-tegra/irammap.h
@@ -23,4 +23,10 @@
#define TEGRA_IRAM_RESET_HANDLER_OFFSET 0
#define TEGRA_IRAM_RESET_HANDLER_SIZE SZ_1K
+/*
+ * This area is used for LPx resume vector, only while LPx power state is
+ * active. At other times, the AVP may use this area for arbitrary purposes
+ */
+#define TEGRA_IRAM_LPx_RESUME_AREA (TEGRA_IRAM_BASE + SZ_4K)
+
#endif
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index ed294a04e1d3..36ed88af1cc1 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -263,10 +263,10 @@ static void tegra_suspend_enter_lp1(void)
tegra_pmc_suspend();
/* copy the reset vector & SDRAM shutdown code into IRAM */
- memcpy(iram_save_addr, IO_ADDRESS(TEGRA_IRAM_CODE_AREA),
- iram_save_size);
- memcpy(IO_ADDRESS(TEGRA_IRAM_CODE_AREA), tegra_lp1_iram.start_addr,
+ memcpy(iram_save_addr, IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA),
iram_save_size);
+ memcpy(IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA),
+ tegra_lp1_iram.start_addr, iram_save_size);
*((u32 *)tegra_cpu_lp1_mask) = 1;
}
@@ -276,7 +276,7 @@ static void tegra_suspend_exit_lp1(void)
tegra_pmc_resume();
/* restore IRAM */
- memcpy(IO_ADDRESS(TEGRA_IRAM_CODE_AREA), iram_save_addr,
+ memcpy(IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA), iram_save_addr,
iram_save_size);
*(u32 *)tegra_cpu_lp1_mask = 0;
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
index fe204e5256e7..6e92a7c2ecbd 100644
--- a/arch/arm/mach-tegra/pm.h
+++ b/arch/arm/mach-tegra/pm.h
@@ -37,9 +37,6 @@ void tegra30_sleep_core_init(void);
extern unsigned long l2x0_saved_regs_addr;
-void save_cpu_arch_register(void);
-void restore_cpu_arch_register(void);
-
void tegra_clear_cpu_in_lp2(void);
bool tegra_set_cpu_in_lp2(void);
diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
index 8acb881f7cfe..93a4dbcde27e 100644
--- a/arch/arm/mach-tegra/pmc.c
+++ b/arch/arm/mach-tegra/pmc.c
@@ -166,6 +166,15 @@ int tegra_pmc_cpu_remove_clamping(int cpuid)
return tegra_pmc_powergate_remove_clamping(id);
}
+void tegra_pmc_restart(enum reboot_mode mode, const char *cmd)
+{
+ u32 val;
+
+ val = tegra_pmc_readl(0);
+ val |= 0x10;
+ tegra_pmc_writel(val, 0);
+}
+
#ifdef CONFIG_PM_SLEEP
static void set_power_timers(u32 us_on, u32 us_off, unsigned long rate)
{
@@ -285,13 +294,10 @@ static const struct of_device_id matches[] __initconst = {
{ }
};
-static void __init tegra_pmc_parse_dt(void)
+void __init tegra_pmc_init_irq(void)
{
struct device_node *np;
- u32 prop;
- enum tegra_suspend_mode suspend_mode;
- u32 core_good_time[2] = {0, 0};
- u32 lp0_vec[2] = {0, 0};
+ u32 val;
np = of_find_matching_node(NULL, matches);
BUG_ON(!np);
@@ -300,6 +306,26 @@ static void __init tegra_pmc_parse_dt(void)
tegra_pmc_invert_interrupt = of_property_read_bool(np,
"nvidia,invert-interrupt");
+
+ val = tegra_pmc_readl(PMC_CTRL);
+ if (tegra_pmc_invert_interrupt)
+ val |= PMC_CTRL_INTR_LOW;
+ else
+ val &= ~PMC_CTRL_INTR_LOW;
+ tegra_pmc_writel(val, PMC_CTRL);
+}
+
+void __init tegra_pmc_init(void)
+{
+ struct device_node *np;
+ u32 prop;
+ enum tegra_suspend_mode suspend_mode;
+ u32 core_good_time[2] = {0, 0};
+ u32 lp0_vec[2] = {0, 0};
+
+ np = of_find_matching_node(NULL, matches);
+ BUG_ON(!np);
+
tegra_pclk = of_clk_get_by_name(np, "pclk");
WARN_ON(IS_ERR(tegra_pclk));
@@ -365,17 +391,3 @@ static void __init tegra_pmc_parse_dt(void)
pmc_pm_data.suspend_mode = suspend_mode;
}
-
-void __init tegra_pmc_init(void)
-{
- u32 val;
-
- tegra_pmc_parse_dt();
-
- val = tegra_pmc_readl(PMC_CTRL);
- if (tegra_pmc_invert_interrupt)
- val |= PMC_CTRL_INTR_LOW;
- else
- val &= ~PMC_CTRL_INTR_LOW;
- tegra_pmc_writel(val, PMC_CTRL);
-}
diff --git a/arch/arm/mach-tegra/pmc.h b/arch/arm/mach-tegra/pmc.h
index 549f8c7b762c..59e19c344298 100644
--- a/arch/arm/mach-tegra/pmc.h
+++ b/arch/arm/mach-tegra/pmc.h
@@ -18,6 +18,8 @@
#ifndef __MACH_TEGRA_PMC_H
#define __MACH_TEGRA_PMC_H
+#include <linux/reboot.h>
+
enum tegra_suspend_mode {
TEGRA_SUSPEND_NONE = 0,
TEGRA_SUSPEND_LP2, /* CPU voltage off */
@@ -39,6 +41,9 @@ bool tegra_pmc_cpu_is_powered(int cpuid);
int tegra_pmc_cpu_power_on(int cpuid);
int tegra_pmc_cpu_remove_clamping(int cpuid);
+void tegra_pmc_restart(enum reboot_mode mode, const char *cmd);
+
+void tegra_pmc_init_irq(void);
void tegra_pmc_init(void);
#endif
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c
index fd0bbf8a6c94..568f5bbf979d 100644
--- a/arch/arm/mach-tegra/reset.c
+++ b/arch/arm/mach-tegra/reset.c
@@ -82,7 +82,7 @@ void __init tegra_cpu_reset_handler_init(void)
#ifdef CONFIG_PM_SLEEP
__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP1] =
- TEGRA_IRAM_CODE_AREA;
+ TEGRA_IRAM_LPx_RESUME_AREA;
__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP2] =
virt_to_phys((void *)tegra_resume);
#endif
diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S
index 5c3bd11c9838..aaaf3abd2688 100644
--- a/arch/arm/mach-tegra/sleep-tegra20.S
+++ b/arch/arm/mach-tegra/sleep-tegra20.S
@@ -25,6 +25,7 @@
#include <asm/cp15.h>
#include <asm/cache.h>
+#include "irammap.h"
#include "sleep.h"
#include "flowctrl.h"
@@ -235,7 +236,7 @@ ENTRY(tegra20_sleep_core_finish)
mov32 r0, tegra20_tear_down_core
mov32 r1, tegra20_iram_start
sub r0, r0, r1
- mov32 r1, TEGRA_IRAM_CODE_AREA
+ mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA
add r0, r0, r1
mov pc, r3
@@ -328,7 +329,7 @@ tegra20_iram_start:
* The physical address of tegra_resume expected to be stored in
* PMC_SCRATCH41.
*
- * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_CODE_AREA.
+ * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
*/
ENTRY(tegra20_lp1_reset)
/*
diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S
index 63fa91b5fafb..c6fc15cb25df 100644
--- a/arch/arm/mach-tegra/sleep-tegra30.S
+++ b/arch/arm/mach-tegra/sleep-tegra30.S
@@ -20,6 +20,7 @@
#include <asm/asm-offsets.h>
#include <asm/cache.h>
+#include "irammap.h"
#include "fuse.h"
#include "sleep.h"
#include "flowctrl.h"
@@ -262,7 +263,7 @@ ENTRY(tegra30_sleep_core_finish)
mov32 r0, tegra30_tear_down_core
mov32 r1, tegra30_iram_start
sub r0, r0, r1
- mov32 r1, TEGRA_IRAM_CODE_AREA
+ mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA
add r0, r0, r1
mov pc, r3
@@ -314,7 +315,7 @@ tegra30_iram_start:
* The physical address of tegra_resume expected to be stored in
* PMC_SCRATCH41.
*
- * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_CODE_AREA.
+ * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
*/
ENTRY(tegra30_lp1_reset)
/*
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index 5b8605547a09..40b031c42299 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -33,17 +33,80 @@
#include <linux/slab.h>
#include <linux/sys_soc.h>
#include <linux/usb/tegra_usb_phy.h>
+#include <linux/clk-provider.h>
#include <linux/clk/tegra.h>
+#include <linux/irqchip.h>
+#include <asm/hardware/cache-l2x0.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <asm/setup.h>
+#include "apbio.h"
#include "board.h"
#include "common.h"
+#include "cpuidle.h"
#include "fuse.h"
#include "iomap.h"
+#include "irq.h"
+#include "pmc.h"
+#include "pm.h"
+#include "reset.h"
+#include "sleep.h"
+
+/*
+ * Storage for debug-macro.S's state.
+ *
+ * This must be in .data not .bss so that it gets initialized each time the
+ * kernel is loaded. The data is declared here rather than debug-macro.S so
+ * that multiple inclusions of debug-macro.S point at the same data.
+ */
+u32 tegra_uart_config[4] = {
+ /* Debug UART initialization required */
+ 1,
+ /* Debug UART physical address */
+ 0,
+ /* Debug UART virtual address */
+ 0,
+ /* Scratch space for debug macro */
+ 0,
+};
+
+static void __init tegra_init_cache(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+ int ret;
+ void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
+ u32 aux_ctrl, cache_type;
+
+ cache_type = readl(p + L2X0_CACHE_TYPE);
+ aux_ctrl = (cache_type & 0x700) << (17-8);
+ aux_ctrl |= 0x7C400001;
+
+ ret = l2x0_of_init(aux_ctrl, 0x8200c3fe);
+ if (!ret)
+ l2x0_saved_regs_addr = virt_to_phys(&l2x0_saved_regs);
+#endif
+}
+
+static void __init tegra_init_early(void)
+{
+ tegra_cpu_reset_handler_init();
+ tegra_apb_io_init();
+ tegra_init_fuse();
+ tegra_init_cache();
+ tegra_powergate_init();
+ tegra_hotplug_init();
+}
+
+static void __init tegra_dt_init_irq(void)
+{
+ tegra_pmc_init_irq();
+ tegra_init_irq();
+ irqchip_init();
+ tegra_legacy_irq_syscore_init();
+}
static void __init tegra_dt_init(void)
{
@@ -51,6 +114,8 @@ static void __init tegra_dt_init(void)
struct soc_device *soc_dev;
struct device *parent = NULL;
+ tegra_pmc_init();
+
tegra_clocks_apply_init_table();
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
@@ -80,6 +145,12 @@ out:
of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
}
+static void __init tegra_dt_init_time(void)
+{
+ of_clk_init(NULL);
+ clocksource_of_init();
+}
+
static void __init paz00_init(void)
{
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
@@ -97,7 +168,9 @@ static void __init tegra_dt_init_late(void)
{
int i;
- tegra_init_late();
+ tegra_init_suspend();
+ tegra_cpuidle_init();
+ tegra_powergate_debugfs_init();
for (i = 0; i < ARRAY_SIZE(board_init_funcs); i++) {
if (of_machine_is_compatible(board_init_funcs[i].machine)) {
@@ -119,9 +192,9 @@ DT_MACHINE_START(TEGRA_DT, "NVIDIA Tegra SoC (Flattened Device Tree)")
.smp = smp_ops(tegra_smp_ops),
.init_early = tegra_init_early,
.init_irq = tegra_dt_init_irq,
- .init_time = clocksource_of_init,
+ .init_time = tegra_dt_init_time,
.init_machine = tegra_dt_init,
.init_late = tegra_dt_init_late,
- .restart = tegra_assert_system_reset,
+ .restart = tegra_pmc_restart,
.dt_compat = tegra_dt_board_compat,
MACHINE_END
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index 0c6356255fe3..d27158c38eb0 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -202,13 +202,11 @@ int valid_phys_addr_range(phys_addr_t addr, size_t size)
}
/*
- * We don't use supersection mappings for mmap() on /dev/mem, which
- * means that we can't map the memory area above the 4G barrier into
- * userspace.
+ * Do not allow /dev/mem mappings beyond the supported physical range.
*/
int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
{
- return !(pfn + (size >> PAGE_SHIFT) > 0x00100000);
+ return (pfn + (size >> PAGE_SHIFT)) <= (1 + (PHYS_MASK >> PAGE_SHIFT));
}
#ifdef CONFIG_STRICT_DEVMEM
diff --git a/arch/arm/plat-iop/Makefile b/arch/arm/plat-iop/Makefile
index a99dc15a70f7..224e56c6049b 100644
--- a/arch/arm/plat-iop/Makefile
+++ b/arch/arm/plat-iop/Makefile
@@ -5,7 +5,6 @@
obj-y :=
# IOP32X
-obj-$(CONFIG_ARCH_IOP32X) += gpio.o
obj-$(CONFIG_ARCH_IOP32X) += i2c.o
obj-$(CONFIG_ARCH_IOP32X) += pci.o
obj-$(CONFIG_ARCH_IOP32X) += setup.o
@@ -16,7 +15,6 @@ obj-$(CONFIG_ARCH_IOP32X) += pmu.o
obj-$(CONFIG_ARCH_IOP32X) += restart.o
# IOP33X
-obj-$(CONFIG_ARCH_IOP33X) += gpio.o
obj-$(CONFIG_ARCH_IOP33X) += i2c.o
obj-$(CONFIG_ARCH_IOP33X) += pci.o
obj-$(CONFIG_ARCH_IOP33X) += setup.o
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index 4fb1f03a10d1..335beb341355 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -87,8 +87,12 @@ IS_SAMSUNG_CPU(exynos5440, EXYNOS5440_SOC_ID, EXYNOS5_SOC_MASK)
#endif
#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
+# define soc_is_s3c6400() is_samsung_s3c6400()
+# define soc_is_s3c6410() is_samsung_s3c6410()
# define soc_is_s3c64xx() (is_samsung_s3c6400() || is_samsung_s3c6410())
#else
+# define soc_is_s3c6400() 0
+# define soc_is_s3c6410() 0
# define soc_is_s3c64xx() 0
#endif
diff --git a/arch/arm/plat-samsung/include/plat/uncompress.h b/arch/arm/plat-samsung/include/plat/uncompress.h
index 4afc32f90b6d..f48dc0a4736c 100644
--- a/arch/arm/plat-samsung/include/plat/uncompress.h
+++ b/arch/arm/plat-samsung/include/plat/uncompress.h
@@ -145,6 +145,8 @@ static inline void arch_enable_uart_fifo(void)
if (!(fifocon & S3C2410_UFCON_RESETBOTH))
break;
}
+
+ uart_wr(S3C2410_UFCON, S3C2410_UFCON_FIFOMODE);
}
}
#else
diff --git a/arch/arm/plat-samsung/init.c b/arch/arm/plat-samsung/init.c
index 50a3ea0037db..aa9511b6914a 100644
--- a/arch/arm/plat-samsung/init.c
+++ b/arch/arm/plat-samsung/init.c
@@ -11,12 +11,18 @@
* published by the Free Software Foundation.
*/
+/*
+ * NOTE: Code in this file is not used on S3C64xx when booting with
+ * Device Tree support.
+ */
+
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h>
+#include <linux/of.h>
#include <mach/hardware.h>
@@ -148,8 +154,12 @@ static int __init s3c_arch_init(void)
// do the correct init for cpu
- if (cpu == NULL)
+ if (cpu == NULL) {
+ /* Not needed when booting with device tree. */
+ if (of_have_populated_dt())
+ return 0;
panic("s3c_arch_init: NULL cpu\n");
+ }
ret = (cpu->init)();
if (ret != 0)
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 79a642d199f2..519f89f5b6a3 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -50,3 +50,4 @@ generic-y += unaligned.h
generic-y += user.h
generic-y += vga.h
generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index edb3d5c73a32..7ecc2b23882e 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -166,9 +166,10 @@ do { \
#define get_user(x, ptr) \
({ \
+ __typeof__(*(ptr)) __user *__p = (ptr); \
might_fault(); \
- access_ok(VERIFY_READ, (ptr), sizeof(*(ptr))) ? \
- __get_user((x), (ptr)) : \
+ access_ok(VERIFY_READ, __p, sizeof(*__p)) ? \
+ __get_user((x), __p) : \
((x) = 0, -EFAULT); \
})
@@ -227,9 +228,10 @@ do { \
#define put_user(x, ptr) \
({ \
+ __typeof__(*(ptr)) __user *__p = (ptr); \
might_fault(); \
- access_ok(VERIFY_WRITE, (ptr), sizeof(*(ptr))) ? \
- __put_user((x), (ptr)) : \
+ access_ok(VERIFY_WRITE, __p, sizeof(*__p)) ? \
+ __put_user((x), __p) : \
-EFAULT; \
})
diff --git a/arch/arm64/mm/tlb.S b/arch/arm64/mm/tlb.S
index 8ae80a18e8ec..19da91e0cd27 100644
--- a/arch/arm64/mm/tlb.S
+++ b/arch/arm64/mm/tlb.S
@@ -35,7 +35,7 @@
*/
ENTRY(__cpu_flush_user_tlb_range)
vma_vm_mm x3, x2 // get vma->vm_mm
- mmid x3, x3 // get vm_mm->context.id
+ mmid w3, x3 // get vm_mm->context.id
dsb sy
lsr x0, x0, #12 // align address
lsr x1, x1, #12
diff --git a/arch/avr32/boards/atngw100/evklcd10x.c b/arch/avr32/boards/atngw100/evklcd10x.c
index 20388750d564..64919b0da7aa 100644
--- a/arch/avr32/boards/atngw100/evklcd10x.c
+++ b/arch/avr32/boards/atngw100/evklcd10x.c
@@ -58,7 +58,7 @@ static struct fb_monspecs __initdata atevklcd10x_default_monspecs = {
.dclkmax = 28330000,
};
-static struct atmel_lcdfb_info __initdata atevklcd10x_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata atevklcd10x_lcdc_data = {
.default_bpp = 16,
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
@@ -96,7 +96,7 @@ static struct fb_monspecs __initdata atevklcd10x_default_monspecs = {
.dclkmax = 7000000,
};
-static struct atmel_lcdfb_info __initdata atevklcd10x_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata atevklcd10x_lcdc_data = {
.default_bpp = 16,
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
@@ -134,7 +134,7 @@ static struct fb_monspecs __initdata atevklcd10x_default_monspecs = {
.dclkmax = 6400000,
};
-static struct atmel_lcdfb_info __initdata atevklcd10x_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata atevklcd10x_lcdc_data = {
.default_bpp = 16,
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
@@ -145,7 +145,7 @@ static struct atmel_lcdfb_info __initdata atevklcd10x_lcdc_data = {
};
#endif
-static void atevklcd10x_lcdc_power_control(int on)
+static void atevklcd10x_lcdc_power_control(struct atmel_lcdfb_pdata *pdata, int on)
{
gpio_set_value(GPIO_PIN_PB(15), on);
}
diff --git a/arch/avr32/boards/atngw100/mrmt.c b/arch/avr32/boards/atngw100/mrmt.c
index 7de083d19b7e..1ba09e4c02b1 100644
--- a/arch/avr32/boards/atngw100/mrmt.c
+++ b/arch/avr32/boards/atngw100/mrmt.c
@@ -83,7 +83,7 @@ static struct fb_monspecs __initdata lcd_fb_default_monspecs = {
.dclkmax = 9260000,
};
-static struct atmel_lcdfb_info __initdata rmt_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata rmt_lcdc_data = {
.default_bpp = 24,
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
@@ -126,7 +126,7 @@ static struct fb_monspecs __initdata lcd_fb_default_monspecs = {
.dclkmax = 9260000,
};
-static struct atmel_lcdfb_info __initdata rmt_lcdc_data = {
+static struct atmel_lcdfb_pdata __initdata rmt_lcdc_data = {
.default_bpp = 24,
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
diff --git a/arch/avr32/boards/atstk1000/atstk1000.h b/arch/avr32/boards/atstk1000/atstk1000.h
index 9392d3252865..653cc09e536c 100644
--- a/arch/avr32/boards/atstk1000/atstk1000.h
+++ b/arch/avr32/boards/atstk1000/atstk1000.h
@@ -10,7 +10,7 @@
#ifndef __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H
#define __ARCH_AVR32_BOARDS_ATSTK1000_ATSTK1000_H
-extern struct atmel_lcdfb_info atstk1000_lcdc_data;
+extern struct atmel_lcdfb_pdata atstk1000_lcdc_data;
void atstk1000_setup_j2_leds(void);
diff --git a/arch/avr32/boards/atstk1000/setup.c b/arch/avr32/boards/atstk1000/setup.c
index 2d6b560115d9..b6b88f5e0b43 100644
--- a/arch/avr32/boards/atstk1000/setup.c
+++ b/arch/avr32/boards/atstk1000/setup.c
@@ -55,7 +55,7 @@ static struct fb_monspecs __initdata atstk1000_default_monspecs = {
.dclkmax = 30000000,
};
-struct atmel_lcdfb_info __initdata atstk1000_lcdc_data = {
+struct atmel_lcdfb_pdata __initdata atstk1000_lcdc_data = {
.default_bpp = 24,
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
diff --git a/arch/avr32/boards/favr-32/setup.c b/arch/avr32/boards/favr-32/setup.c
index 27bd6fbe21cb..7b1f2cd85400 100644
--- a/arch/avr32/boards/favr-32/setup.c
+++ b/arch/avr32/boards/favr-32/setup.c
@@ -125,7 +125,7 @@ static struct fb_monspecs __initdata favr32_default_monspecs = {
.dclkmax = 28000000,
};
-struct atmel_lcdfb_info __initdata favr32_lcdc_data = {
+struct atmel_lcdfb_pdata __initdata favr32_lcdc_data = {
.default_bpp = 16,
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
diff --git a/arch/avr32/boards/hammerhead/setup.c b/arch/avr32/boards/hammerhead/setup.c
index 9d1efd1cd425..dc0e317f2ecd 100644
--- a/arch/avr32/boards/hammerhead/setup.c
+++ b/arch/avr32/boards/hammerhead/setup.c
@@ -77,7 +77,7 @@ static struct fb_monspecs __initdata hammerhead_hda350t_monspecs = {
.dclkmax = 10000000,
};
-struct atmel_lcdfb_info __initdata hammerhead_lcdc_data = {
+struct atmel_lcdfb_pdata __initdata hammerhead_lcdc_data = {
.default_bpp = 24,
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
diff --git a/arch/avr32/boards/merisc/display.c b/arch/avr32/boards/merisc/display.c
index 85a543cd4abc..e7683ee7ed40 100644
--- a/arch/avr32/boards/merisc/display.c
+++ b/arch/avr32/boards/merisc/display.c
@@ -45,7 +45,7 @@ static struct fb_monspecs merisc_fb_monspecs = {
.dclkmax = 30000000,
};
-struct atmel_lcdfb_info merisc_lcdc_data = {
+struct atmel_lcdfb_pdata merisc_lcdc_data = {
.default_bpp = 24,
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
diff --git a/arch/avr32/boards/mimc200/setup.c b/arch/avr32/boards/mimc200/setup.c
index 05358aa5ef7d..1cb8e9cc5cfa 100644
--- a/arch/avr32/boards/mimc200/setup.c
+++ b/arch/avr32/boards/mimc200/setup.c
@@ -8,7 +8,7 @@
* published by the Free Software Foundation.
*/
-extern struct atmel_lcdfb_info mimc200_lcdc_data;
+extern struct atmel_lcdfb_pdata mimc200_lcdc_data;
#include <linux/clk.h>
#include <linux/etherdevice.h>
@@ -71,7 +71,7 @@ static struct fb_monspecs __initdata mimc200_default_monspecs = {
.dclkmax = 25200000,
};
-struct atmel_lcdfb_info __initdata mimc200_lcdc_data = {
+struct atmel_lcdfb_pdata __initdata mimc200_lcdc_data = {
.default_bpp = 16,
.default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
.default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index d22af851f3f6..b946080ee8bb 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -3,3 +3,4 @@ generic-y += clkdev.h
generic-y += exec.h
generic-y += trace_clock.h
generic-y += param.h
+generic-y += preempt.h
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index a68f3cf7c3c1..a1f4d1e91b52 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -1439,7 +1439,7 @@ fail:
* LCDC
* -------------------------------------------------------------------- */
#if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7002)
-static struct atmel_lcdfb_info atmel_lcdfb0_data;
+static struct atmel_lcdfb_pdata atmel_lcdfb0_data;
static struct resource atmel_lcdfb0_resource[] = {
{
.start = 0xff000000,
@@ -1467,12 +1467,12 @@ static struct clk atmel_lcdfb0_pixclk = {
};
struct platform_device *__init
-at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
+at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_pdata *data,
unsigned long fbmem_start, unsigned long fbmem_len,
u64 pin_mask)
{
struct platform_device *pdev;
- struct atmel_lcdfb_info *info;
+ struct atmel_lcdfb_pdata *info;
struct fb_monspecs *monspecs;
struct fb_videomode *modedb;
unsigned int modedb_size;
@@ -1529,7 +1529,7 @@ at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
}
info = pdev->dev.platform_data;
- memcpy(info, data, sizeof(struct atmel_lcdfb_info));
+ memcpy(info, data, sizeof(struct atmel_lcdfb_pdata));
info->default_monspecs = monspecs;
pdev->name = "at32ap-lcdfb";
diff --git a/arch/avr32/mach-at32ap/include/mach/board.h b/arch/avr32/mach-at32ap/include/mach/board.h
index d485b0391357..f1a316d52c73 100644
--- a/arch/avr32/mach-at32ap/include/mach/board.h
+++ b/arch/avr32/mach-at32ap/include/mach/board.h
@@ -44,9 +44,9 @@ struct platform_device *
at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n);
void at32_spi_setup_slaves(unsigned int bus_num, struct spi_board_info *b, unsigned int n);
-struct atmel_lcdfb_info;
+struct atmel_lcdfb_pdata;
struct platform_device *
-at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
+at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_pdata *data,
unsigned long fbmem_start, unsigned long fbmem_len,
u64 pin_mask);
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index f78c9a2c7e28..74314bd8be39 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -52,6 +52,9 @@ config GENERIC_BUG
config ZONE_DMA
def_bool y
+config GENERIC_GPIO
+ def_bool y
+
config FORCE_MAX_ZONEORDER
int
default "14"
@@ -317,6 +320,14 @@ config BF53x
depends on (BF531 || BF532 || BF533 || BF534 || BF536 || BF537)
default y
+config GPIO_ADI
+ def_bool y
+ depends on (BF51x || BF52x || BF53x || BF538 || BF539 || BF561)
+
+config PINCTRL
+ def_bool y
+ depends on BF54x || BF60x
+
config MEM_MT48LC64M4A2FB_7E
bool
depends on (BFIN533_STAMP)
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 127826f8a375..f2b43474b0e2 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -44,3 +44,4 @@ generic-y += ucontext.h
generic-y += unaligned.h
generic-y += user.h
generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h
index 98d0133346b5..99d338ca2ea4 100644
--- a/arch/blackfin/include/asm/gpio.h
+++ b/arch/blackfin/include/asm/gpio.h
@@ -25,8 +25,12 @@
#ifndef __ASSEMBLY__
+#ifndef CONFIG_PINCTRL
+
#include <linux/compiler.h>
-#include <linux/gpio.h>
+#include <asm/blackfin.h>
+#include <asm/portmux.h>
+#include <asm/irq_handler.h>
/***********************************************************
*
@@ -45,7 +49,6 @@
* MODIFICATION HISTORY :
**************************************************************/
-#if !BFIN_GPIO_PINT
void set_gpio_dir(unsigned, unsigned short);
void set_gpio_inen(unsigned, unsigned short);
void set_gpio_polar(unsigned, unsigned short);
@@ -115,7 +118,6 @@ struct gpio_port_t {
unsigned short dummy16;
unsigned short inen;
};
-#endif
#ifdef BFIN_SPECIAL_GPIO_BANKS
void bfin_special_gpio_free(unsigned gpio);
@@ -127,25 +129,21 @@ void bfin_special_gpio_pm_hibernate_suspend(void);
#endif
#ifdef CONFIG_PM
-int bfin_pm_standby_ctrl(unsigned ctrl);
+void bfin_gpio_pm_hibernate_restore(void);
+void bfin_gpio_pm_hibernate_suspend(void);
+int bfin_gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl);
+int bfin_gpio_pm_standby_ctrl(unsigned ctrl);
static inline int bfin_pm_standby_setup(void)
{
- return bfin_pm_standby_ctrl(1);
+ return bfin_gpio_pm_standby_ctrl(1);
}
static inline void bfin_pm_standby_restore(void)
{
- bfin_pm_standby_ctrl(0);
+ bfin_gpio_pm_standby_ctrl(0);
}
-void bfin_gpio_pm_hibernate_restore(void);
-void bfin_gpio_pm_hibernate_suspend(void);
-void bfin_pint_suspend(void);
-void bfin_pint_resume(void);
-
-# if !BFIN_GPIO_PINT
-int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl);
struct gpio_port_s {
unsigned short data;
@@ -161,7 +159,6 @@ struct gpio_port_s {
unsigned short reserved;
unsigned short mux;
};
-# endif
#endif /*CONFIG_PM*/
/***********************************************************
@@ -178,36 +175,29 @@ struct gpio_port_s {
*************************************************************
* MODIFICATION HISTORY :
**************************************************************/
-
-int bfin_gpio_request(unsigned gpio, const char *label);
-void bfin_gpio_free(unsigned gpio);
int bfin_gpio_irq_request(unsigned gpio, const char *label);
void bfin_gpio_irq_free(unsigned gpio);
-int bfin_gpio_direction_input(unsigned gpio);
-int bfin_gpio_direction_output(unsigned gpio, int value);
-int bfin_gpio_get_value(unsigned gpio);
-void bfin_gpio_set_value(unsigned gpio, int value);
+void bfin_gpio_irq_prepare(unsigned gpio);
+
+static inline int irq_to_gpio(unsigned irq)
+{
+ return irq - GPIO_IRQ_BASE;
+}
+#endif /* CONFIG_PINCTRL */
#include <asm/irq.h>
#include <asm/errno.h>
-#ifdef CONFIG_GPIOLIB
#include <asm-generic/gpio.h> /* cansleep wrappers */
static inline int gpio_get_value(unsigned int gpio)
{
- if (gpio < MAX_BLACKFIN_GPIOS)
- return bfin_gpio_get_value(gpio);
- else
- return __gpio_get_value(gpio);
+ return __gpio_get_value(gpio);
}
static inline void gpio_set_value(unsigned int gpio, int value)
{
- if (gpio < MAX_BLACKFIN_GPIOS)
- bfin_gpio_set_value(gpio, value);
- else
- __gpio_set_value(gpio, value);
+ __gpio_set_value(gpio, value);
}
static inline int gpio_cansleep(unsigned int gpio)
@@ -219,113 +209,6 @@ static inline int gpio_to_irq(unsigned gpio)
{
return __gpio_to_irq(gpio);
}
-
-#else /* !CONFIG_GPIOLIB */
-
-static inline int gpio_request(unsigned gpio, const char *label)
-{
- return bfin_gpio_request(gpio, label);
-}
-
-static inline void gpio_free(unsigned gpio)
-{
- return bfin_gpio_free(gpio);
-}
-
-static inline int gpio_direction_input(unsigned gpio)
-{
- return bfin_gpio_direction_input(gpio);
-}
-
-static inline int gpio_direction_output(unsigned gpio, int value)
-{
- return bfin_gpio_direction_output(gpio, value);
-}
-
-static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)
-{
- return -EINVAL;
-}
-
-static inline int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
-{
- int err;
-
- err = bfin_gpio_request(gpio, label);
- if (err)
- return err;
-
- if (flags & GPIOF_DIR_IN)
- err = bfin_gpio_direction_input(gpio);
- else
- err = bfin_gpio_direction_output(gpio,
- (flags & GPIOF_INIT_HIGH) ? 1 : 0);
-
- if (err)
- bfin_gpio_free(gpio);
-
- return err;
-}
-
-static inline int gpio_request_array(const struct gpio *array, size_t num)
-{
- int i, err;
-
- for (i = 0; i < num; i++, array++) {
- err = gpio_request_one(array->gpio, array->flags, array->label);
- if (err)
- goto err_free;
- }
- return 0;
-
-err_free:
- while (i--)
- bfin_gpio_free((--array)->gpio);
- return err;
-}
-
-static inline void gpio_free_array(const struct gpio *array, size_t num)
-{
- while (num--)
- bfin_gpio_free((array++)->gpio);
-}
-
-static inline int __gpio_get_value(unsigned gpio)
-{
- return bfin_gpio_get_value(gpio);
-}
-
-static inline void __gpio_set_value(unsigned gpio, int value)
-{
- return bfin_gpio_set_value(gpio, value);
-}
-
-static inline int gpio_get_value(unsigned gpio)
-{
- return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
- return __gpio_set_value(gpio, value);
-}
-
-static inline int gpio_to_irq(unsigned gpio)
-{
- if (likely(gpio < MAX_BLACKFIN_GPIOS))
- return gpio + GPIO_IRQ_BASE;
-
- return -EINVAL;
-}
-
-#include <asm-generic/gpio.h> /* cansleep wrappers */
-#endif /* !CONFIG_GPIOLIB */
-
-static inline int irq_to_gpio(unsigned irq)
-{
- return (irq - GPIO_IRQ_BASE);
-}
-
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_BLACKFIN_GPIO_H__ */
diff --git a/arch/blackfin/include/asm/portmux.h b/arch/blackfin/include/asm/portmux.h
index 9b1e2c37b324..7aa20436e799 100644
--- a/arch/blackfin/include/asm/portmux.h
+++ b/arch/blackfin/include/asm/portmux.h
@@ -17,14 +17,29 @@
#define P_MAYSHARE 0x2000
#define P_DONTCARE 0x1000
-
+#ifdef CONFIG_PINCTRL
+#include <asm/irq_handler.h>
+
+#define gpio_pint_regs bfin_pint_regs
+#define adi_internal_set_wake bfin_internal_set_wake
+
+#define peripheral_request(per, label) 0
+#define peripheral_free(per)
+#define peripheral_request_list(per, label) \
+ (pdev ? (IS_ERR(devm_pinctrl_get_select_default(&pdev->dev)) \
+ ? -EINVAL : 0) : 0)
+#define peripheral_free_list(per)
+#else
int peripheral_request(unsigned short per, const char *label);
void peripheral_free(unsigned short per);
int peripheral_request_list(const unsigned short per[], const char *label);
void peripheral_free_list(const unsigned short per[]);
+#endif
-#include <asm/gpio.h>
+#include <linux/err.h>
+#include <linux/pinctrl/pinctrl.h>
#include <mach/portmux.h>
+#include <linux/gpio.h>
#ifndef P_SPORT2_TFS
#define P_SPORT2_TFS P_UNDEF
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index 735f24e07425..703dc7cf2ecc 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -7,7 +7,7 @@ extra-y := vmlinux.lds
obj-y := \
entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \
sys_bfin.o traps.o irqchip.o dma-mapping.o flat.o \
- fixed_code.o reboot.o bfin_gpio.o bfin_dma.o \
+ fixed_code.o reboot.o bfin_dma.o \
exception.o dumpstack.o
ifeq ($(CONFIG_GENERIC_CLOCKEVENTS),y)
@@ -16,6 +16,7 @@ else
obj-y += time.o
endif
+obj-$(CONFIG_GPIO_ADI) += bfin_gpio.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
obj-$(CONFIG_FUNCTION_TRACER) += ftrace-entry.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
diff --git a/arch/blackfin/mach-bf548/include/mach/portmux.h b/arch/blackfin/mach-bf548/include/mach/portmux.h
index e22246202730..d9f8632d7d09 100644
--- a/arch/blackfin/mach-bf548/include/mach/portmux.h
+++ b/arch/blackfin/mach-bf548/include/mach/portmux.h
@@ -7,8 +7,6 @@
#ifndef _MACH_PORTMUX_H_
#define _MACH_PORTMUX_H_
-#define MAX_RESOURCES MAX_BLACKFIN_GPIOS
-
#define P_SPORT2_TFS (P_DEFINED | P_IDENT(GPIO_PA0) | P_FUNCT(0))
#define P_SPORT2_DTSEC (P_DEFINED | P_IDENT(GPIO_PA1) | P_FUNCT(0))
#define P_SPORT2_DTPRI (P_DEFINED | P_IDENT(GPIO_PA2) | P_FUNCT(0))
diff --git a/arch/blackfin/mach-bf609/include/mach/portmux.h b/arch/blackfin/mach-bf609/include/mach/portmux.h
index 2e1a51c25098..fe34191eef0b 100644
--- a/arch/blackfin/mach-bf609/include/mach/portmux.h
+++ b/arch/blackfin/mach-bf609/include/mach/portmux.h
@@ -7,8 +7,6 @@
#ifndef _MACH_PORTMUX_H_
#define _MACH_PORTMUX_H_
-#define MAX_RESOURCES MAX_BLACKFIN_GPIOS
-
/* EMAC RMII Port Mux */
#define P_MII0_MDC (P_DEFINED | P_IDENT(GPIO_PC6) | P_FUNCT(0))
#define P_MII0_MDIO (P_DEFINED | P_IDENT(GPIO_PC7) | P_FUNCT(0))
diff --git a/arch/c6x/Kconfig b/arch/c6x/Kconfig
index 957dd00ea561..b4f77258cacc 100644
--- a/arch/c6x/Kconfig
+++ b/arch/c6x/Kconfig
@@ -105,10 +105,6 @@ menu "Processor type and features"
source "arch/c6x/platforms/Kconfig"
-config TMS320C6X_CACHES_ON
- bool "L2 cache support"
- default y
-
config KERNEL_RAM_BASE_ADDRESS
hex "Virtual address of memory base"
default 0xe0000000 if SOC_TMS320C6455
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index e49f918531ad..fc0b3c356027 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -56,3 +56,4 @@ generic-y += ucontext.h
generic-y += user.h
generic-y += vga.h
generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index c8325455520e..b06caf649a95 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += module.h
generic-y += trace_clock.h
generic-y += vga.h
generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index c5d767028306..74742dc6a3da 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -2,3 +2,4 @@
generic-y += clkdev.h
generic-y += exec.h
generic-y += trace_clock.h
+generic-y += preempt.h
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
deleted file mode 100644
index 24b1dc2564f1..000000000000
--- a/arch/h8300/Kconfig
+++ /dev/null
@@ -1,108 +0,0 @@
-config H8300
- bool
- default y
- select HAVE_IDE
- select GENERIC_ATOMIC64
- select HAVE_UID16
- select VIRT_TO_BUS
- select ARCH_WANT_IPC_PARSE_VERSION
- select GENERIC_IRQ_SHOW
- select GENERIC_CPU_DEVICES
- select MODULES_USE_ELF_RELA
- select OLD_SIGSUSPEND3
- select OLD_SIGACTION
- select HAVE_UNDERSCORE_SYMBOL_PREFIX
-
-config MMU
- bool
- default n
-
-config SWAP
- bool
- default n
-
-config ZONE_DMA
- bool
- default y
-
-config FPU
- bool
- default n
-
-config RWSEM_GENERIC_SPINLOCK
- bool
- default y
-
-config RWSEM_XCHGADD_ALGORITHM
- bool
- default n
-
-config ARCH_HAS_ILOG2_U32
- bool
- default n
-
-config ARCH_HAS_ILOG2_U64
- bool
- default n
-
-config GENERIC_HWEIGHT
- bool
- default y
-
-config GENERIC_CALIBRATE_DELAY
- bool
- default y
-
-config GENERIC_BUG
- bool
- depends on BUG
-
-config TIME_LOW_RES
- bool
- default y
-
-config NO_IOPORT
- def_bool y
-
-config NO_DMA
- def_bool y
-
-config ISA
- bool
- default y
-
-config PCI
- bool
- default n
-
-config HZ
- int
- default 100
-
-source "init/Kconfig"
-
-source "kernel/Kconfig.freezer"
-
-source "arch/h8300/Kconfig.cpu"
-
-menu "Executable file formats"
-
-source "fs/Kconfig.binfmt"
-
-endmenu
-
-source "net/Kconfig"
-
-source "drivers/Kconfig"
-
-source "arch/h8300/Kconfig.ide"
-
-source "fs/Kconfig"
-
-source "arch/h8300/Kconfig.debug"
-
-source "security/Kconfig"
-
-source "crypto/Kconfig"
-
-source "lib/Kconfig"
diff --git a/arch/h8300/Kconfig.cpu b/arch/h8300/Kconfig.cpu
deleted file mode 100644
index cdee771460ed..000000000000
--- a/arch/h8300/Kconfig.cpu
+++ /dev/null
@@ -1,171 +0,0 @@
-menu "Processor type and features"
-
-choice
- prompt "H8/300 platform"
- default H8300H_GENERIC
-
-config H8300H_GENERIC
- bool "H8/300H Generic"
- help
- H8/300H CPU Generic Hardware Support
-
-config H8300H_AKI3068NET
- bool "AE-3068/69"
- select H83068
- help
- AKI-H8/3068F / AKI-H8/3069F Flashmicom LAN Board Support
- More Information. (Japanese Only)
- <http://akizukidenshi.com/catalog/default.aspx>
- AE-3068/69 Evaluation Board Support
- More Information.
- <http://www.microtronique.com/ae3069lan.htm>
-
-config H8300H_H8MAX
- bool "H8MAX"
- select H83068
- help
- H8MAX Evaluation Board Support
- More Information. (Japanese Only)
- <http://strawberry-linux.com/h8/index.html>
-
-config H8300H_SIM
- bool "H8/300H Simulator"
- select H83007
- help
- GDB Simulator Support
- More Information.
- <http://sourceware.org/sid/>
-
-config H8S_GENERIC
- bool "H8S Generic"
- help
- H8S CPU Generic Hardware Support
-
-config H8S_EDOSK2674
- bool "EDOSK-2674"
- select H8S2678
- help
- Renesas EDOSK-2674 Evaluation Board Support
- More Information.
- <http://www.azpower.com/H8-uClinux/index.html>
- <http://www.renesas.eu/products/tools/introductory_evaluation_tools/evaluation_development_os_kits/edosk2674r/edosk2674r_software_tools_root.jsp>
-
-config H8S_SIM
- bool "H8S Simulator"
- help
- GDB Simulator Support
- More Information.
- <http://sourceware.org/sid/>
-
-endchoice
-
-choice
- prompt "CPU Selection"
-
-config H83002
- bool "H8/3001,3002,3003"
- depends on BROKEN
- select CPU_H8300H
-
-config H83007
- bool "H8/3006,3007"
- select CPU_H8300H
-
-config H83048
- bool "H8/3044,3045,3046,3047,3048,3052"
- depends on BROKEN
- select CPU_H8300H
-
-config H83068
- bool "H8/3065,3066,3067,3068,3069"
- select CPU_H8300H
-
-config H8S2678
- bool "H8S/2670,2673,2674R,2675,2676"
- select CPU_H8S
-
-endchoice
-
-config CPU_CLOCK
- int "CPU Clock Frequency (/1KHz)"
- default "20000"
- help
- CPU Clock Frequency divide to 1000
-
-choice
- prompt "Kernel executes from"
- ---help---
- Choose the memory type that the kernel will be running in.
-
-config RAMKERNEL
- bool "RAM"
- help
- The kernel will be resident in RAM when running.
-
-config ROMKERNEL
- bool "ROM"
- help
- The kernel will be resident in FLASH/ROM when running.
-endchoice
-
-
-config CPU_H8300H
- bool
- depends on (H83002 || H83007 || H83048 || H83068)
- default y
-
-config CPU_H8S
- bool
- depends on H8S2678
- default y
-
-choice
- prompt "Timer"
-config H8300_TIMER8
- bool "8bit timer (2ch cascade)"
- depends on (H83007 || H83068 || H8S2678)
-
-config H8300_TIMER16
- bool "16bit timer"
- depends on (H83007 || H83068)
-
-config H8300_ITU
- bool "ITU"
- depends on (H83002 || H83048)
-
-config H8300_TPU
- bool "TPU"
- depends on H8S2678
-endchoice
-
-if H8300_TIMER8
-choice
- prompt "Timer Channel"
-config H8300_TIMER8_CH0
- bool "Channel 0"
-config H8300_TIMER8_CH2
- bool "Channel 2"
- depends on CPU_H8300H
-endchoice
-endif
-
-config H8300_TIMER16_CH
- int "16bit timer channel (0 - 2)"
- depends on H8300_TIMER16
- range 0 2
-
-config H8300_ITU_CH
- int "ITU channel"
- depends on H8300_ITU
- range 0 4
-
-config H8300_TPU_CH
- int "TPU channel"
- depends on H8300_TPU
- range 0 4
-
-source "kernel/Kconfig.preempt"
-
-source "mm/Kconfig"
-
-endmenu
diff --git a/arch/h8300/Kconfig.debug b/arch/h8300/Kconfig.debug
deleted file mode 100644
index e8d1b236ad8c..000000000000
--- a/arch/h8300/Kconfig.debug
+++ /dev/null
@@ -1,68 +0,0 @@
-menu "Kernel hacking"
-
-source "lib/Kconfig.debug"
-
-config FULLDEBUG
- bool "Full Symbolic/Source Debugging support"
- help
- Enable debugging symbols on kernel build.
-
-config HIGHPROFILE
- bool "Use fast second timer for profiling"
- help
- Use a fast secondary clock to produce profiling information.
-
-config NO_KERNEL_MSG
- bool "Suppress Kernel BUG Messages"
- help
- Do not output any debug BUG messages within the kernel.
-
-config GDB_MAGICPRINT
- bool "Message Output for GDB MagicPrint service"
- depends on (H8300H_SIM || H8S_SIM)
- help
- kernel messages output using MagicPrint service from GDB
-
-config SYSCALL_PRINT
- bool "SystemCall trace print"
- help
- output history of systemcall
-
-config GDB_DEBUG
- bool "Use gdb stub"
- depends on (!H8300H_SIM && !H8S_SIM)
- help
- gdb stub exception support
-
-config SH_STANDARD_BIOS
- bool "Use gdb protocol serial console"
- depends on (!H8300H_SIM && !H8S_SIM)
- help
- serial console output using GDB protocol.
- Require eCos/RedBoot
-
-config DEFAULT_CMDLINE
- bool "Use builtin commandline"
- default n
- help
- builtin kernel commandline enabled.
-
-config KERNEL_COMMAND
- string "Buildin command string"
- depends on DEFAULT_CMDLINE
- help
- builtin kernel commandline strings.
-
-config BLKDEV_RESERVE
- bool "BLKDEV Reserved Memory"
- default n
- help
- Reserved BLKDEV area.
-
-config BLKDEV_RESERVE_ADDRESS
- hex 'start address'
- depends on BLKDEV_RESERVE
- help
- BLKDEV start address.
-
-endmenu
diff --git a/arch/h8300/Kconfig.ide b/arch/h8300/Kconfig.ide
deleted file mode 100644
index a38a63054ac2..000000000000
--- a/arch/h8300/Kconfig.ide
+++ /dev/null
@@ -1,44 +0,0 @@
-# uClinux H8/300 Target Board Selection Menu (IDE)
-
-if (H8300H_AKI3068NET)
-menu "IDE Extra configuration"
-
-config H8300_IDE_BASE
- hex "IDE register base address"
- depends on IDE
- default 0
- help
- IDE registers base address
-
-config H8300_IDE_ALT
- hex "IDE register alternate address"
- depends on IDE
- default 0
- help
- IDE alternate registers address
-
-config H8300_IDE_IRQ
- int "IDE IRQ no"
- depends on IDE
- default 0
- help
- IDE use IRQ no
-endmenu
-endif
-
-if (H8300H_H8MAX)
-config H8300_IDE_BASE
- hex
- depends on IDE
- default 0x200000
-
-config H8300_IDE_ALT
- hex
- depends on IDE
- default 0x60000c
-
-config H8300_IDE_IRQ
- int
- depends on IDE
- default 5
-endif
diff --git a/arch/h8300/Makefile b/arch/h8300/Makefile
deleted file mode 100644
index a556447877b4..000000000000
--- a/arch/h8300/Makefile
+++ /dev/null
@@ -1,71 +0,0 @@
-#
-# arch/h8300/Makefile
-#
-# 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.
-#
-# (C) Copyright 2002,2003 Yoshinori Sato <ysato@users.sourceforge.jp>
-#
-
-platform-$(CONFIG_CPU_H8300H) := h8300h
-platform-$(CONFIG_CPU_H8S) := h8s
-PLATFORM := $(platform-y)
-
-board-$(CONFIG_H8300H_GENERIC) := generic
-board-$(CONFIG_H8300H_AKI3068NET) := aki3068net
-board-$(CONFIG_H8300H_H8MAX) := h8max
-board-$(CONFIG_H8300H_SIM) := generic
-board-$(CONFIG_H8S_GENERIC) := generic
-board-$(CONFIG_H8S_EDOSK2674) := edosk2674
-board-$(CONFIG_H8S_SIM) := generic
-BOARD := $(board-y)
-
-model-$(CONFIG_RAMKERNEL) := ram
-model-$(CONFIG_ROMKERNEL) := rom
-MODEL := $(model-y)
-
-cflags-$(CONFIG_CPU_H8300H) := -mh
-ldflags-$(CONFIG_CPU_H8300H) := -mh8300helf
-cflags-$(CONFIG_CPU_H8S) := -ms
-ldflags-$(CONFIG_CPU_H8S) := -mh8300self
-
-KBUILD_CFLAGS += $(cflags-y)
-KBUILD_CFLAGS += -mint32 -fno-builtin
-KBUILD_CFLAGS += -g
-KBUILD_CFLAGS += -D__linux__
-KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
-KBUILD_AFLAGS += -DPLATFORM=$(PLATFORM) -DMODEL=$(MODEL) $(cflags-y)
-LDFLAGS += $(ldflags-y)
-
-CROSS_COMPILE = h8300-elf-
-LIBGCC := $(shell $(CROSS-COMPILE)$(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
-
-head-y := arch/$(ARCH)/platform/$(PLATFORM)/$(BOARD)/crt0_$(MODEL).o
-
-core-y += arch/$(ARCH)/kernel/ \
- arch/$(ARCH)/mm/
-ifdef PLATFORM
-core-y += arch/$(ARCH)/platform/$(PLATFORM)/ \
- arch/$(ARCH)/platform/$(PLATFORM)/$(BOARD)/
-endif
-
-libs-y += arch/$(ARCH)/lib/ $(LIBGCC)
-
-boot := arch/h8300/boot
-
-export MODEL PLATFORM BOARD
-
-archmrproper:
-
-archclean:
- $(Q)$(MAKE) $(clean)=$(boot)
-
-vmlinux.srec vmlinux.bin zImage: vmlinux
- $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
-
-define archhelp
- @echo 'vmlinux.bin - Create raw binary'
- @echo 'vmlinux.srec - Create srec binary'
- @echo 'zImage - Compressed kernel image'
-endef
diff --git a/arch/h8300/README b/arch/h8300/README
deleted file mode 100644
index efa805fda19b..000000000000
--- a/arch/h8300/README
+++ /dev/null
@@ -1,38 +0,0 @@
-linux-2.6 for H8/300 README
-Yoshinori Sato <ysato@users.sourceforge.jp>
-
-* Supported CPU
-H8/300H and H8S
-
-* Supported Target
-1.simulator of GDB
- require patches.
-
-2.AE 3068/AE 3069
- more information
- MICROTRONIQUE <http://www.microtronique.com/>
- Akizuki Denshi Tsusho Ltd. <http://akizukidenshi.com/> (Japanese Only)
-
-3.H8MAX
- see http://ip-sol.jp/h8max/ (Japanese Only)
-
-4.EDOSK2674
- see http://www.eu.renesas.com/products/mpumcu/tool/edk/support/edosk2674.html
- http://www.uclinux.org/pub/uClinux/ports/h8/HITACHI-EDOSK2674-HOWTO
- http://www.azpower.com/H8-uClinux/
-
-* Toolchain Version
-gcc-3.1 or higher and patch
-see arch/h8300/tools_patch/README
-binutils-2.12 or higher
-gdb-5.2 or higher
-The environment that can compile a h8300-elf binary is necessary.
-
-* Userland Develop environment
-used h8300-elf toolchains.
-see http://www.uclinux.org/pub/uClinux/ports/h8/
-
-* A few words of thanks
-Porting to H8/300 serieses is support of Information-technology Promotion Agency, Japan.
-I thank support.
-and All developer/user.
diff --git a/arch/h8300/boot/Makefile b/arch/h8300/boot/Makefile
deleted file mode 100644
index 0bb62e064eea..000000000000
--- a/arch/h8300/boot/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
-# arch/h8300/boot/Makefile
-
-targets := vmlinux.srec vmlinux.bin zImage
-subdir- := compressed
-
-OBJCOPYFLAGS_vmlinux.srec := -Osrec
-OBJCOPYFLAGS_vmlinux.bin := -Obinary
-OBJCOPYFLAGS_zImage := -O binary -R .note -R .comment -R .stab -R .stabstr -S
-
-$(obj)/vmlinux.srec $(obj)/vmlinux.bin: vmlinux FORCE
- $(call if_changed,objcopy)
- @echo ' Kernel: $@ is ready'
-
-$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
- $(call if_changed,objcopy)
- @echo 'Kernel: $@ is ready'
-
-$(obj)/compressed/vmlinux: FORCE
- $(Q)$(MAKE) $(build)=$(obj)/compressed $@
-
-CLEAN_FILES += arch/$(ARCH)/vmlinux.bin arch/$(ARCH)/vmlinux.srec
-
diff --git a/arch/h8300/boot/compressed/Makefile b/arch/h8300/boot/compressed/Makefile
deleted file mode 100644
index a6c98fe3bbc3..000000000000
--- a/arch/h8300/boot/compressed/Makefile
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# linux/arch/sh/boot/compressed/Makefile
-#
-# create a compressed vmlinux image from the original vmlinux
-#
-
-targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
-asflags-y := -traditional
-
-OBJECTS = $(obj)/head.o $(obj)/misc.o
-
-#
-# IMAGE_OFFSET is the load offset of the compression loader
-# Assign dummy values if these 2 variables are not defined,
-# in order to suppress error message.
-#
-CONFIG_MEMORY_START ?= 0x00400000
-CONFIG_BOOT_LINK_OFFSET ?= 0x00140000
-IMAGE_OFFSET := $(shell printf "0x%08x" $$(($(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET))))
-
-LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -estartup $(obj)/vmlinux.lds
-
-$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
- $(call if_changed,ld)
- @:
-
-$(obj)/vmlinux.bin: vmlinux FORCE
- $(call if_changed,objcopy)
-
-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
- $(call if_changed,gzip)
-
-LDFLAGS_piggy.o := -r --format binary --oformat elf32-h8300 -T
-OBJCOPYFLAGS := -O binary
-
-$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
- $(call if_changed,ld)
diff --git a/arch/h8300/boot/compressed/head.S b/arch/h8300/boot/compressed/head.S
deleted file mode 100644
index 10e9a2d1cc6c..000000000000
--- a/arch/h8300/boot/compressed/head.S
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * linux/arch/h8300/boot/compressed/head.S
- *
- * Copyright (C) 2006 Yoshinori Sato
- */
-
- .h8300h
-#include <linux/linkage.h>
-
-#define SRAM_START 0xff4000
-
- .section .text..startup
- .global startup
-startup:
- mov.l #SRAM_START+0x8000, sp
- mov.l #__sbss, er0
- mov.l #__ebss, er1
- sub.l er0, er1
- shlr er1
- shlr er1
- sub.l er2, er2
-1:
- mov.l er2, @er0
- adds #4, er0
- dec.l #1, er1
- bne 1b
- jsr @_decompress_kernel
- jmp @0x400000
-
- .align 9
-fake_headers_as_bzImage:
- .word 0
- .ascii "HdrS" ; header signature
- .word 0x0202 ; header version number (>= 0x0105)
- ; or else old loadlin-1.5 will fail)
- .word 0 ; default_switch
- .word 0 ; SETUPSEG
- .word 0x1000
- .word 0 ; pointing to kernel version string
- .byte 0 ; = 0, old one (LILO, Loadlin,
- ; 0xTV: T=0 for LILO
- ; V = version
- .byte 1 ; Load flags bzImage=1
- .word 0x8000 ; size to move, when setup is not
- .long 0x100000 ; 0x100000 = default for big kernel
- .long 0 ; address of loaded ramdisk image
- .long 0 ; its size in bytes
diff --git a/arch/h8300/boot/compressed/misc.c b/arch/h8300/boot/compressed/misc.c
deleted file mode 100644
index 4a1e3dd43948..000000000000
--- a/arch/h8300/boot/compressed/misc.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * arch/h8300/boot/compressed/misc.c
- *
- * This is a collection of several routines from gzip-1.0.3
- * adapted for Linux.
- *
- * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
- *
- * Adapted for h8300 by Yoshinori Sato 2006
- */
-
-#include <asm/uaccess.h>
-
-/*
- * gzip declarations
- */
-
-#define OF(args) args
-#define STATIC static
-
-#undef memset
-#undef memcpy
-#define memzero(s, n) memset ((s), 0, (n))
-
-typedef unsigned char uch;
-typedef unsigned short ush;
-typedef unsigned long ulg;
-
-#define WSIZE 0x8000 /* Window size must be at least 32k, */
- /* and a power of two */
-
-static uch *inbuf; /* input buffer */
-static uch window[WSIZE]; /* Sliding window buffer */
-
-static unsigned insize = 0; /* valid bytes in inbuf */
-static unsigned inptr = 0; /* index of next byte to be processed in inbuf */
-static unsigned outcnt = 0; /* bytes in output buffer */
-
-/* gzip flag byte */
-#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
-#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
-#define COMMENT 0x10 /* bit 4 set: file comment present */
-#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
-#define RESERVED 0xC0 /* bit 6,7: reserved */
-
-#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
-
-/* Diagnostic functions */
-#ifdef DEBUG
-# define Assert(cond,msg) {if(!(cond)) error(msg);}
-# define Trace(x) fprintf x
-# define Tracev(x) {if (verbose) fprintf x ;}
-# define Tracevv(x) {if (verbose>1) fprintf x ;}
-# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#else
-# define Assert(cond,msg)
-# define Trace(x)
-# define Tracev(x)
-# define Tracevv(x)
-# define Tracec(c,x)
-# define Tracecv(c,x)
-#endif
-
-static int fill_inbuf(void);
-static void flush_window(void);
-static void error(char *m);
-
-extern char input_data[];
-extern int input_len;
-
-static long bytes_out = 0;
-static uch *output_data;
-static unsigned long output_ptr = 0;
-
-static void error(char *m);
-
-int puts(const char *);
-
-extern int _end;
-static unsigned long free_mem_ptr;
-static unsigned long free_mem_end_ptr;
-
-#define HEAP_SIZE 0x10000
-
-#include "../../../../lib/inflate.c"
-
-#define SCR *((volatile unsigned char *)0xffff8a)
-#define TDR *((volatile unsigned char *)0xffff8b)
-#define SSR *((volatile unsigned char *)0xffff8c)
-
-int puts(const char *s)
-{
- return 0;
-}
-
-void* memset(void* s, int c, size_t n)
-{
- int i;
- char *ss = (char*)s;
-
- for (i=0;i<n;i++) ss[i] = c;
- return s;
-}
-
-void* memcpy(void* __dest, __const void* __src,
- size_t __n)
-{
- int i;
- char *d = (char *)__dest, *s = (char *)__src;
-
- for (i=0;i<__n;i++) d[i] = s[i];
- return __dest;
-}
-
-/* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
- */
-static int fill_inbuf(void)
-{
- if (insize != 0) {
- error("ran out of input data");
- }
-
- inbuf = input_data;
- insize = input_len;
- inptr = 1;
- return inbuf[0];
-}
-
-/* ===========================================================================
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
-static void flush_window(void)
-{
- ulg c = crc; /* temporary variable */
- unsigned n;
- uch *in, *out, ch;
-
- in = window;
- out = &output_data[output_ptr];
- for (n = 0; n < outcnt; n++) {
- ch = *out++ = *in++;
- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
- }
- crc = c;
- bytes_out += (ulg)outcnt;
- output_ptr += (ulg)outcnt;
- outcnt = 0;
-}
-
-static void error(char *x)
-{
- puts("\n\n");
- puts(x);
- puts("\n\n -- System halted");
-
- while(1); /* Halt */
-}
-
-#define STACK_SIZE (4096)
-long user_stack [STACK_SIZE];
-long* stack_start = &user_stack[STACK_SIZE];
-
-void decompress_kernel(void)
-{
- output_data = 0;
- output_ptr = (unsigned long)0x400000;
- free_mem_ptr = (unsigned long)&_end;
- free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
-
- makecrc();
- puts("Uncompressing Linux... ");
- gunzip();
- puts("Ok, booting the kernel.\n");
-}
diff --git a/arch/h8300/boot/compressed/vmlinux.lds b/arch/h8300/boot/compressed/vmlinux.lds
deleted file mode 100644
index a0a3a0ed54ef..000000000000
--- a/arch/h8300/boot/compressed/vmlinux.lds
+++ /dev/null
@@ -1,32 +0,0 @@
-SECTIONS
-{
- .text :
- {
- __stext = . ;
- __text = .;
- *(.text..startup)
- *(.text)
- __etext = . ;
- }
-
- .rodata :
- {
- *(.rodata)
- }
- .data :
-
- {
- __sdata = . ;
- ___data_start = . ;
- *(.data.*)
- }
- .bss :
- {
- . = ALIGN(0x4) ;
- __sbss = . ;
- *(.bss*)
- . = ALIGN(0x4) ;
- __ebss = . ;
- __end = . ;
- }
-}
diff --git a/arch/h8300/boot/compressed/vmlinux.scr b/arch/h8300/boot/compressed/vmlinux.scr
deleted file mode 100644
index a0f6962736e9..000000000000
--- a/arch/h8300/boot/compressed/vmlinux.scr
+++ /dev/null
@@ -1,9 +0,0 @@
-SECTIONS
-{
- .data : {
- _input_len = .;
- LONG(_input_data_end - _input_data) _input_data = .;
- *(.data)
- _input_data_end = .;
- }
-}
diff --git a/arch/h8300/defconfig b/arch/h8300/defconfig
deleted file mode 100644
index 042425a02645..000000000000
--- a/arch/h8300/defconfig
+++ /dev/null
@@ -1,42 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EXPERT=y
-# CONFIG_UID16 is not set
-# CONFIG_SYSCTL_SYSCALL is not set
-# CONFIG_KALLSYMS is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_BASE_FULL is not set
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-# CONFIG_SIGNALFD is not set
-# CONFIG_TIMERFD is not set
-# CONFIG_EVENTFD is not set
-# CONFIG_VM_EVENT_COUNTERS is not set
-# CONFIG_COMPAT_BRK is not set
-CONFIG_SLOB=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_H83007=y
-CONFIG_BINFMT_FLAT=y
-CONFIG_BINFMT_ZFLAT=y
-CONFIG_BINFMT_MISC=y
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_RAM=y
-CONFIG_MTD_ROM=y
-CONFIG_MTD_UCLINUX=y
-# CONFIG_BLK_DEV is not set
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_ROMFS_FS=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_CRC32 is not set
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
deleted file mode 100644
index 8ada3cf0c98d..000000000000
--- a/arch/h8300/include/asm/Kbuild
+++ /dev/null
@@ -1,8 +0,0 @@
-
-generic-y += clkdev.h
-generic-y += exec.h
-generic-y += linkage.h
-generic-y += mmu.h
-generic-y += module.h
-generic-y += trace_clock.h
-generic-y += xor.h
diff --git a/arch/h8300/include/asm/asm-offsets.h b/arch/h8300/include/asm/asm-offsets.h
deleted file mode 100644
index d370ee36a182..000000000000
--- a/arch/h8300/include/asm/asm-offsets.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <generated/asm-offsets.h>
diff --git a/arch/h8300/include/asm/atomic.h b/arch/h8300/include/asm/atomic.h
deleted file mode 100644
index 40901e353c21..000000000000
--- a/arch/h8300/include/asm/atomic.h
+++ /dev/null
@@ -1,146 +0,0 @@
-#ifndef __ARCH_H8300_ATOMIC__
-#define __ARCH_H8300_ATOMIC__
-
-#include <linux/types.h>
-#include <asm/cmpxchg.h>
-
-/*
- * Atomic operations that C can't guarantee us. Useful for
- * resource counting etc..
- */
-
-#define ATOMIC_INIT(i) { (i) }
-
-#define atomic_read(v) (*(volatile int *)&(v)->counter)
-#define atomic_set(v, i) (((v)->counter) = i)
-
-#include <linux/kernel.h>
-
-static __inline__ int atomic_add_return(int i, atomic_t *v)
-{
- unsigned long flags;
- int ret;
- local_irq_save(flags);
- ret = v->counter += i;
- local_irq_restore(flags);
- return ret;
-}
-
-#define atomic_add(i, v) atomic_add_return(i, v)
-#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
-
-static __inline__ int atomic_sub_return(int i, atomic_t *v)
-{
- unsigned long flags;
- int ret;
- local_irq_save(flags);
- ret = v->counter -= i;
- local_irq_restore(flags);
- return ret;
-}
-
-#define atomic_sub(i, v) atomic_sub_return(i, v)
-#define atomic_sub_and_test(i,v) (atomic_sub_return(i, v) == 0)
-
-static __inline__ int atomic_inc_return(atomic_t *v)
-{
- unsigned long flags;
- int ret;
- local_irq_save(flags);
- v->counter++;
- ret = v->counter;
- local_irq_restore(flags);
- return ret;
-}
-
-#define atomic_inc(v) atomic_inc_return(v)
-
-/*
- * atomic_inc_and_test - increment and test
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1
- * and returns true if the result is zero, or false for all
- * other cases.
- */
-#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
-
-static __inline__ int atomic_dec_return(atomic_t *v)
-{
- unsigned long flags;
- int ret;
- local_irq_save(flags);
- --v->counter;
- ret = v->counter;
- local_irq_restore(flags);
- return ret;
-}
-
-#define atomic_dec(v) atomic_dec_return(v)
-
-static __inline__ int atomic_dec_and_test(atomic_t *v)
-{
- unsigned long flags;
- int ret;
- local_irq_save(flags);
- --v->counter;
- ret = v->counter;
- local_irq_restore(flags);
- return ret == 0;
-}
-
-static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
-{
- int ret;
- unsigned long flags;
-
- local_irq_save(flags);
- ret = v->counter;
- if (likely(ret == old))
- v->counter = new;
- local_irq_restore(flags);
- return ret;
-}
-
-static inline int __atomic_add_unless(atomic_t *v, int a, int u)
-{
- int ret;
- unsigned long flags;
-
- local_irq_save(flags);
- ret = v->counter;
- if (ret != u)
- v->counter += a;
- local_irq_restore(flags);
- return ret;
-}
-
-static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *v)
-{
- __asm__ __volatile__("stc ccr,r1l\n\t"
- "orc #0x80,ccr\n\t"
- "mov.l %0,er0\n\t"
- "and.l %1,er0\n\t"
- "mov.l er0,%0\n\t"
- "ldc r1l,ccr"
- : "=m" (*v) : "g" (~(mask)) :"er0","er1");
-}
-
-static __inline__ void atomic_set_mask(unsigned long mask, unsigned long *v)
-{
- __asm__ __volatile__("stc ccr,r1l\n\t"
- "orc #0x80,ccr\n\t"
- "mov.l %0,er0\n\t"
- "or.l %1,er0\n\t"
- "mov.l er0,%0\n\t"
- "ldc r1l,ccr"
- : "=m" (*v) : "g" (mask) :"er0","er1");
-}
-
-/* Atomic operations are already serializing */
-#define smp_mb__before_atomic_dec() barrier()
-#define smp_mb__after_atomic_dec() barrier()
-#define smp_mb__before_atomic_inc() barrier()
-#define smp_mb__after_atomic_inc() barrier()
-
-#endif /* __ARCH_H8300_ATOMIC __ */
diff --git a/arch/h8300/include/asm/barrier.h b/arch/h8300/include/asm/barrier.h
deleted file mode 100644
index 9e0aa9fc195d..000000000000
--- a/arch/h8300/include/asm/barrier.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef _H8300_BARRIER_H
-#define _H8300_BARRIER_H
-
-#define nop() asm volatile ("nop"::)
-
-/*
- * Force strict CPU ordering.
- * Not really required on H8...
- */
-#define mb() asm volatile ("" : : :"memory")
-#define rmb() asm volatile ("" : : :"memory")
-#define wmb() asm volatile ("" : : :"memory")
-#define set_mb(var, value) do { xchg(&var, value); } while (0)
-
-#define read_barrier_depends() do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#define smp_read_barrier_depends() read_barrier_depends()
-#else
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define smp_read_barrier_depends() do { } while(0)
-#endif
-
-#endif /* _H8300_BARRIER_H */
diff --git a/arch/h8300/include/asm/bitops.h b/arch/h8300/include/asm/bitops.h
deleted file mode 100644
index eb34e0cd33d5..000000000000
--- a/arch/h8300/include/asm/bitops.h
+++ /dev/null
@@ -1,211 +0,0 @@
-#ifndef _H8300_BITOPS_H
-#define _H8300_BITOPS_H
-
-/*
- * Copyright 1992, Linus Torvalds.
- * Copyright 2002, Yoshinori Sato
- */
-
-#include <linux/compiler.h>
-
-#ifdef __KERNEL__
-
-#ifndef _LINUX_BITOPS_H
-#error only <linux/bitops.h> can be included directly
-#endif
-
-/*
- * Function prototypes to keep gcc -Wall happy
- */
-
-/*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
- */
-static __inline__ unsigned long ffz(unsigned long word)
-{
- unsigned long result;
-
- result = -1;
- __asm__("1:\n\t"
- "shlr.l %2\n\t"
- "adds #1,%0\n\t"
- "bcs 1b"
- : "=r" (result)
- : "0" (result),"r" (word));
- return result;
-}
-
-#define H8300_GEN_BITOP_CONST(OP,BIT) \
- case BIT: \
- __asm__(OP " #" #BIT ",@%0"::"r"(b_addr):"memory"); \
- break;
-
-#define H8300_GEN_BITOP(FNAME,OP) \
-static __inline__ void FNAME(int nr, volatile unsigned long* addr) \
-{ \
- volatile unsigned char *b_addr; \
- b_addr = (volatile unsigned char *)addr + ((nr >> 3) ^ 3); \
- if (__builtin_constant_p(nr)) { \
- switch(nr & 7) { \
- H8300_GEN_BITOP_CONST(OP,0) \
- H8300_GEN_BITOP_CONST(OP,1) \
- H8300_GEN_BITOP_CONST(OP,2) \
- H8300_GEN_BITOP_CONST(OP,3) \
- H8300_GEN_BITOP_CONST(OP,4) \
- H8300_GEN_BITOP_CONST(OP,5) \
- H8300_GEN_BITOP_CONST(OP,6) \
- H8300_GEN_BITOP_CONST(OP,7) \
- } \
- } else { \
- __asm__(OP " %w0,@%1"::"r"(nr),"r"(b_addr):"memory"); \
- } \
-}
-
-/*
- * clear_bit() doesn't provide any barrier for the compiler.
- */
-#define smp_mb__before_clear_bit() barrier()
-#define smp_mb__after_clear_bit() barrier()
-
-H8300_GEN_BITOP(set_bit ,"bset")
-H8300_GEN_BITOP(clear_bit ,"bclr")
-H8300_GEN_BITOP(change_bit,"bnot")
-#define __set_bit(nr,addr) set_bit((nr),(addr))
-#define __clear_bit(nr,addr) clear_bit((nr),(addr))
-#define __change_bit(nr,addr) change_bit((nr),(addr))
-
-#undef H8300_GEN_BITOP
-#undef H8300_GEN_BITOP_CONST
-
-static __inline__ int test_bit(int nr, const unsigned long* addr)
-{
- return (*((volatile unsigned char *)addr +
- ((nr >> 3) ^ 3)) & (1UL << (nr & 7))) != 0;
-}
-
-#define __test_bit(nr, addr) test_bit(nr, addr)
-
-#define H8300_GEN_TEST_BITOP_CONST_INT(OP,BIT) \
- case BIT: \
- __asm__("stc ccr,%w1\n\t" \
- "orc #0x80,ccr\n\t" \
- "bld #" #BIT ",@%4\n\t" \
- OP " #" #BIT ",@%4\n\t" \
- "rotxl.l %0\n\t" \
- "ldc %w1,ccr" \
- : "=r"(retval),"=&r"(ccrsave),"=m"(*b_addr) \
- : "0" (retval),"r" (b_addr) \
- : "memory"); \
- break;
-
-#define H8300_GEN_TEST_BITOP_CONST(OP,BIT) \
- case BIT: \
- __asm__("bld #" #BIT ",@%3\n\t" \
- OP " #" #BIT ",@%3\n\t" \
- "rotxl.l %0\n\t" \
- : "=r"(retval),"=m"(*b_addr) \
- : "0" (retval),"r" (b_addr) \
- : "memory"); \
- break;
-
-#define H8300_GEN_TEST_BITOP(FNNAME,OP) \
-static __inline__ int FNNAME(int nr, volatile void * addr) \
-{ \
- int retval = 0; \
- char ccrsave; \
- volatile unsigned char *b_addr; \
- b_addr = (volatile unsigned char *)addr + ((nr >> 3) ^ 3); \
- if (__builtin_constant_p(nr)) { \
- switch(nr & 7) { \
- H8300_GEN_TEST_BITOP_CONST_INT(OP,0) \
- H8300_GEN_TEST_BITOP_CONST_INT(OP,1) \
- H8300_GEN_TEST_BITOP_CONST_INT(OP,2) \
- H8300_GEN_TEST_BITOP_CONST_INT(OP,3) \
- H8300_GEN_TEST_BITOP_CONST_INT(OP,4) \
- H8300_GEN_TEST_BITOP_CONST_INT(OP,5) \
- H8300_GEN_TEST_BITOP_CONST_INT(OP,6) \
- H8300_GEN_TEST_BITOP_CONST_INT(OP,7) \
- } \
- } else { \
- __asm__("stc ccr,%w1\n\t" \
- "orc #0x80,ccr\n\t" \
- "btst %w5,@%4\n\t" \
- OP " %w5,@%4\n\t" \
- "beq 1f\n\t" \
- "inc.l #1,%0\n" \
- "1:\n\t" \
- "ldc %w1,ccr" \
- : "=r"(retval),"=&r"(ccrsave),"=m"(*b_addr) \
- : "0" (retval),"r" (b_addr),"r"(nr) \
- : "memory"); \
- } \
- return retval; \
-} \
- \
-static __inline__ int __ ## FNNAME(int nr, volatile void * addr) \
-{ \
- int retval = 0; \
- volatile unsigned char *b_addr; \
- b_addr = (volatile unsigned char *)addr + ((nr >> 3) ^ 3); \
- if (__builtin_constant_p(nr)) { \
- switch(nr & 7) { \
- H8300_GEN_TEST_BITOP_CONST(OP,0) \
- H8300_GEN_TEST_BITOP_CONST(OP,1) \
- H8300_GEN_TEST_BITOP_CONST(OP,2) \
- H8300_GEN_TEST_BITOP_CONST(OP,3) \
- H8300_GEN_TEST_BITOP_CONST(OP,4) \
- H8300_GEN_TEST_BITOP_CONST(OP,5) \
- H8300_GEN_TEST_BITOP_CONST(OP,6) \
- H8300_GEN_TEST_BITOP_CONST(OP,7) \
- } \
- } else { \
- __asm__("btst %w4,@%3\n\t" \
- OP " %w4,@%3\n\t" \
- "beq 1f\n\t" \
- "inc.l #1,%0\n" \
- "1:" \
- : "=r"(retval),"=m"(*b_addr) \
- : "0" (retval),"r" (b_addr),"r"(nr) \
- : "memory"); \
- } \
- return retval; \
-}
-
-H8300_GEN_TEST_BITOP(test_and_set_bit, "bset")
-H8300_GEN_TEST_BITOP(test_and_clear_bit, "bclr")
-H8300_GEN_TEST_BITOP(test_and_change_bit,"bnot")
-#undef H8300_GEN_TEST_BITOP_CONST
-#undef H8300_GEN_TEST_BITOP_CONST_INT
-#undef H8300_GEN_TEST_BITOP
-
-#include <asm-generic/bitops/ffs.h>
-
-static __inline__ unsigned long __ffs(unsigned long word)
-{
- unsigned long result;
-
- result = -1;
- __asm__("1:\n\t"
- "shlr.l %2\n\t"
- "adds #1,%0\n\t"
- "bcc 1b"
- : "=r" (result)
- : "0"(result),"r"(word));
- return result;
-}
-
-#include <asm-generic/bitops/find.h>
-#include <asm-generic/bitops/sched.h>
-#include <asm-generic/bitops/hweight.h>
-#include <asm-generic/bitops/lock.h>
-#include <asm-generic/bitops/le.h>
-#include <asm-generic/bitops/ext2-atomic.h>
-
-#endif /* __KERNEL__ */
-
-#include <asm-generic/bitops/fls.h>
-#include <asm-generic/bitops/__fls.h>
-#include <asm-generic/bitops/fls64.h>
-
-#endif /* _H8300_BITOPS_H */
diff --git a/arch/h8300/include/asm/bootinfo.h b/arch/h8300/include/asm/bootinfo.h
deleted file mode 100644
index 5bed7e7aac0a..000000000000
--- a/arch/h8300/include/asm/bootinfo.h
+++ /dev/null
@@ -1,2 +0,0 @@
-
-/* Nothing for h8300 */
diff --git a/arch/h8300/include/asm/bug.h b/arch/h8300/include/asm/bug.h
deleted file mode 100644
index 1e1be8119935..000000000000
--- a/arch/h8300/include/asm/bug.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _H8300_BUG_H
-#define _H8300_BUG_H
-
-/* always true */
-#define is_valid_bugaddr(addr) (1)
-
-#include <asm-generic/bug.h>
-
-struct pt_regs;
-extern void die(const char *str, struct pt_regs *fp, unsigned long err);
-
-#endif
diff --git a/arch/h8300/include/asm/bugs.h b/arch/h8300/include/asm/bugs.h
deleted file mode 100644
index 1cb4afba6eb1..000000000000
--- a/arch/h8300/include/asm/bugs.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-h8300/bugs.h
- *
- * Copyright (C) 1994 Linus Torvalds
- */
-
-/*
- * This is included by init/main.c to check for architecture-dependent bugs.
- *
- * Needs:
- * void check_bugs(void);
- */
-
-static void check_bugs(void)
-{
-}
diff --git a/arch/h8300/include/asm/cache.h b/arch/h8300/include/asm/cache.h
deleted file mode 100644
index 05887a1d80e5..000000000000
--- a/arch/h8300/include/asm/cache.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ARCH_H8300_CACHE_H
-#define __ARCH_H8300_CACHE_H
-
-/* bytes per L1 cache line */
-#define L1_CACHE_SHIFT 2
-#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
-
-/* m68k-elf-gcc 2.95.2 doesn't like these */
-
-#define __cacheline_aligned
-#define ____cacheline_aligned
-
-#endif
diff --git a/arch/h8300/include/asm/cachectl.h b/arch/h8300/include/asm/cachectl.h
deleted file mode 100644
index c464022d8e26..000000000000
--- a/arch/h8300/include/asm/cachectl.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _H8300_CACHECTL_H
-#define _H8300_CACHECTL_H
-
-/* Definitions for the cacheflush system call. */
-
-#define FLUSH_SCOPE_LINE 0 /* Flush a cache line */
-#define FLUSH_SCOPE_PAGE 0 /* Flush a page */
-#define FLUSH_SCOPE_ALL 0 /* Flush the whole cache -- superuser only */
-
-#define FLUSH_CACHE_DATA 0 /* Writeback and flush data cache */
-#define FLUSH_CACHE_INSN 0 /* Flush instruction cache */
-#define FLUSH_CACHE_BOTH 0 /* Flush both caches */
-
-#endif /* _H8300_CACHECTL_H */
diff --git a/arch/h8300/include/asm/cacheflush.h b/arch/h8300/include/asm/cacheflush.h
deleted file mode 100644
index 4cf2df20c1ce..000000000000
--- a/arch/h8300/include/asm/cacheflush.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * (C) Copyright 2002, Yoshinori Sato <ysato@users.sourceforge.jp>
- */
-
-#ifndef _ASM_H8300_CACHEFLUSH_H
-#define _ASM_H8300_CACHEFLUSH_H
-
-/*
- * Cache handling functions
- * No Cache memory all dummy functions
- */
-
-#define flush_cache_all()
-#define flush_cache_mm(mm)
-#define flush_cache_dup_mm(mm) do { } while (0)
-#define flush_cache_range(vma,a,b)
-#define flush_cache_page(vma,p,pfn)
-#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
-#define flush_dcache_page(page)
-#define flush_dcache_mmap_lock(mapping)
-#define flush_dcache_mmap_unlock(mapping)
-#define flush_icache()
-#define flush_icache_page(vma,page)
-#define flush_icache_range(start,len)
-#define flush_cache_vmap(start, end)
-#define flush_cache_vunmap(start, end)
-#define cache_push_v(vaddr,len)
-#define cache_push(paddr,len)
-#define cache_clear(paddr,len)
-
-#define flush_dcache_range(a,b)
-
-#define flush_icache_user_range(vma,page,addr,len)
-
-#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
- memcpy(dst, src, len)
-#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
- memcpy(dst, src, len)
-
-#endif /* _ASM_H8300_CACHEFLUSH_H */
diff --git a/arch/h8300/include/asm/checksum.h b/arch/h8300/include/asm/checksum.h
deleted file mode 100644
index 98724e12508c..000000000000
--- a/arch/h8300/include/asm/checksum.h
+++ /dev/null
@@ -1,102 +0,0 @@
-#ifndef _H8300_CHECKSUM_H
-#define _H8300_CHECKSUM_H
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-__wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- * the same as csum_partial, but copies from src while it
- * checksums
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum);
-
-
-/*
- * the same as csum_partial_copy, but copies from user space.
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
- int len, __wsum sum, int *csum_err);
-
-__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
-
-
-/*
- * Fold a partial checksum
- */
-
-static inline __sum16 csum_fold(__wsum sum)
-{
- __asm__("mov.l %0,er0\n\t"
- "add.w e0,r0\n\t"
- "xor.w e0,e0\n\t"
- "rotxl.w e0\n\t"
- "add.w e0,r0\n\t"
- "sub.w e0,e0\n\t"
- "mov.l er0,%0"
- : "=r"(sum)
- : "0"(sum)
- : "er0");
- return (__force __sum16)~sum;
-}
-
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-
-static inline __wsum
-csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
- unsigned short proto, __wsum sum)
-{
- __asm__ ("sub.l er0,er0\n\t"
- "add.l %2,%0\n\t"
- "addx #0,r0l\n\t"
- "add.l %3,%0\n\t"
- "addx #0,r0l\n\t"
- "add.l %4,%0\n\t"
- "addx #0,r0l\n\t"
- "add.l er0,%0\n\t"
- "bcc 1f\n\t"
- "inc.l #1,%0\n"
- "1:"
- : "=&r" (sum)
- : "0" (sum), "r" (daddr), "r" (saddr), "r" (len + proto)
- :"er0");
- return sum;
-}
-
-static inline __sum16
-csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
- unsigned short proto, __wsum sum)
-{
- return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-
-extern __sum16 ip_compute_csum(const void *buff, int len);
-
-#endif /* _H8300_CHECKSUM_H */
diff --git a/arch/h8300/include/asm/cmpxchg.h b/arch/h8300/include/asm/cmpxchg.h
deleted file mode 100644
index cdb203ef681f..000000000000
--- a/arch/h8300/include/asm/cmpxchg.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef __ARCH_H8300_CMPXCHG__
-#define __ARCH_H8300_CMPXCHG__
-
-#include <linux/irqflags.h>
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((volatile struct __xchg_dummy *)(x))
-
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
- unsigned long tmp, flags;
-
- local_irq_save(flags);
-
- switch (size) {
- case 1:
- __asm__ __volatile__
- ("mov.b %2,%0\n\t"
- "mov.b %1,%2"
- : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
- break;
- case 2:
- __asm__ __volatile__
- ("mov.w %2,%0\n\t"
- "mov.w %1,%2"
- : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
- break;
- case 4:
- __asm__ __volatile__
- ("mov.l %2,%0\n\t"
- "mov.l %1,%2"
- : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
- break;
- default:
- tmp = 0;
- }
- local_irq_restore(flags);
- return tmp;
-}
-
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n) \
- ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
- (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#ifndef CONFIG_SMP
-#include <asm-generic/cmpxchg.h>
-#endif
-
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-#endif /* __ARCH_H8300_CMPXCHG__ */
diff --git a/arch/h8300/include/asm/cputime.h b/arch/h8300/include/asm/cputime.h
deleted file mode 100644
index 092e187c7b08..000000000000
--- a/arch/h8300/include/asm/cputime.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __H8300_CPUTIME_H
-#define __H8300_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __H8300_CPUTIME_H */
diff --git a/arch/h8300/include/asm/current.h b/arch/h8300/include/asm/current.h
deleted file mode 100644
index 57d74ee55a14..000000000000
--- a/arch/h8300/include/asm/current.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef _H8300_CURRENT_H
-#define _H8300_CURRENT_H
-/*
- * current.h
- * (C) Copyright 2000, Lineo, David McCullough <davidm@lineo.com>
- * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
- *
- * rather than dedicate a register (as the m68k source does), we
- * just keep a global, we should probably just change it all to be
- * current and lose _current_task.
- */
-
-#include <linux/thread_info.h>
-#include <asm/thread_info.h>
-
-struct task_struct;
-
-static inline struct task_struct *get_current(void)
-{
- return(current_thread_info()->task);
-}
-
-#define current get_current()
-
-#endif /* _H8300_CURRENT_H */
diff --git a/arch/h8300/include/asm/dbg.h b/arch/h8300/include/asm/dbg.h
deleted file mode 100644
index 2c6d1cbcf736..000000000000
--- a/arch/h8300/include/asm/dbg.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#define DEBUG 1
-#define BREAK asm volatile ("trap #3")
diff --git a/arch/h8300/include/asm/delay.h b/arch/h8300/include/asm/delay.h
deleted file mode 100644
index 743beba70f82..000000000000
--- a/arch/h8300/include/asm/delay.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef _H8300_DELAY_H
-#define _H8300_DELAY_H
-
-#include <asm/param.h>
-
-/*
- * Copyright (C) 2002 Yoshinori Sato <ysato@sourceforge.jp>
- *
- * Delay routines, using a pre-computed "loops_per_second" value.
- */
-
-static inline void __delay(unsigned long loops)
-{
- __asm__ __volatile__ ("1:\n\t"
- "dec.l #1,%0\n\t"
- "bne 1b"
- :"=r" (loops):"0"(loops));
-}
-
-/*
- * Use only for very small delays ( < 1 msec). Should probably use a
- * lookup table, really, as the multiplications take much too long with
- * short delays. This is a "reasonable" implementation, though (and the
- * first constant multiplications gets optimized away if the delay is
- * a constant)
- */
-
-extern unsigned long loops_per_jiffy;
-
-static inline void udelay(unsigned long usecs)
-{
- usecs *= 4295; /* 2**32 / 1000000 */
- usecs /= (loops_per_jiffy*HZ);
- if (usecs)
- __delay(usecs);
-}
-
-#endif /* _H8300_DELAY_H */
diff --git a/arch/h8300/include/asm/device.h b/arch/h8300/include/asm/device.h
deleted file mode 100644
index d8f9872b0e2d..000000000000
--- a/arch/h8300/include/asm/device.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#include <asm-generic/device.h>
-
diff --git a/arch/h8300/include/asm/div64.h b/arch/h8300/include/asm/div64.h
deleted file mode 100644
index 6cd978cefb28..000000000000
--- a/arch/h8300/include/asm/div64.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/div64.h>
diff --git a/arch/h8300/include/asm/dma.h b/arch/h8300/include/asm/dma.h
deleted file mode 100644
index 3edbaaaedf5b..000000000000
--- a/arch/h8300/include/asm/dma.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef _H8300_DMA_H
-#define _H8300_DMA_H
-
-
-/*
- * Set number of channels of DMA on ColdFire for different implementations.
- */
-#define MAX_DMA_CHANNELS 0
-#define MAX_DMA_ADDRESS PAGE_OFFSET
-
-/* These are in kernel/dma.c: */
-extern int request_dma(unsigned int dmanr, const char *device_id); /* reserve a DMA channel */
-extern void free_dma(unsigned int dmanr); /* release it again */
-
-#endif /* _H8300_DMA_H */
diff --git a/arch/h8300/include/asm/elf.h b/arch/h8300/include/asm/elf.h
deleted file mode 100644
index 6db71248a82f..000000000000
--- a/arch/h8300/include/asm/elf.h
+++ /dev/null
@@ -1,101 +0,0 @@
-#ifndef __ASMH8300_ELF_H
-#define __ASMH8300_ELF_H
-
-/*
- * ELF register definitions..
- */
-
-#include <asm/ptrace.h>
-#include <asm/user.h>
-
-typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-typedef unsigned long elf_fpregset_t;
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) ((x)->e_machine == EM_H8_300)
-
-/*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_CLASS ELFCLASS32
-#define ELF_DATA ELFDATA2MSB
-#define ELF_ARCH EM_H8_300
-#if defined(__H8300H__)
-#define ELF_CORE_EFLAGS 0x810000
-#endif
-#if defined(__H8300S__)
-#define ELF_CORE_EFLAGS 0x820000
-#endif
-
-#define ELF_PLAT_INIT(_r) _r->er1 = 0
-
-#define ELF_EXEC_PAGESIZE 4096
-
-/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
- use of this is to invoke "./ld.so someprog" to test out a new version of
- the loader. We need to make sure that it is out of the way of the program
- that it will "exec", and that there is sufficient room for the brk. */
-
-#define ELF_ET_DYN_BASE 0xD0000000UL
-
-/* This yields a mask that user programs can use to figure out what
- instruction set this cpu supports. */
-
-#define ELF_HWCAP (0)
-
-/* This yields a string that ld.so will use to load implementation
- specific libraries for optimization. This is more specific in
- intent than poking at uname or /proc/cpuinfo. */
-
-#define ELF_PLATFORM (NULL)
-
-#define R_H8_NONE 0
-#define R_H8_DIR32 1
-#define R_H8_DIR32_28 2
-#define R_H8_DIR32_24 3
-#define R_H8_DIR32_16 4
-#define R_H8_DIR32U 6
-#define R_H8_DIR32U_28 7
-#define R_H8_DIR32U_24 8
-#define R_H8_DIR32U_20 9
-#define R_H8_DIR32U_16 10
-#define R_H8_DIR24 11
-#define R_H8_DIR24_20 12
-#define R_H8_DIR24_16 13
-#define R_H8_DIR24U 14
-#define R_H8_DIR24U_20 15
-#define R_H8_DIR24U_16 16
-#define R_H8_DIR16 17
-#define R_H8_DIR16U 18
-#define R_H8_DIR16S_32 19
-#define R_H8_DIR16S_28 20
-#define R_H8_DIR16S_24 21
-#define R_H8_DIR16S_20 22
-#define R_H8_DIR16S 23
-#define R_H8_DIR8 24
-#define R_H8_DIR8U 25
-#define R_H8_DIR8Z_32 26
-#define R_H8_DIR8Z_28 27
-#define R_H8_DIR8Z_24 28
-#define R_H8_DIR8Z_20 29
-#define R_H8_DIR8Z_16 30
-#define R_H8_PCREL16 31
-#define R_H8_PCREL8 32
-#define R_H8_BPOS 33
-#define R_H8_PCREL32 34
-#define R_H8_GOT32O 35
-#define R_H8_GOT16O 36
-#define R_H8_DIR16A8 59
-#define R_H8_DIR16R8 60
-#define R_H8_DIR24A8 61
-#define R_H8_DIR24R8 62
-#define R_H8_DIR32A16 63
-#define R_H8_ABS32 65
-#define R_H8_ABS32A16 127
-
-#endif
diff --git a/arch/h8300/include/asm/emergency-restart.h b/arch/h8300/include/asm/emergency-restart.h
deleted file mode 100644
index 108d8c48e42e..000000000000
--- a/arch/h8300/include/asm/emergency-restart.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/arch/h8300/include/asm/fb.h b/arch/h8300/include/asm/fb.h
deleted file mode 100644
index c7df38030992..000000000000
--- a/arch/h8300/include/asm/fb.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _ASM_FB_H_
-#define _ASM_FB_H_
-#include <linux/fb.h>
-
-#define fb_pgprotect(...) do {} while (0)
-
-static inline int fb_is_primary_device(struct fb_info *info)
-{
- return 0;
-}
-
-#endif /* _ASM_FB_H_ */
diff --git a/arch/h8300/include/asm/flat.h b/arch/h8300/include/asm/flat.h
deleted file mode 100644
index bd12b31b90e6..000000000000
--- a/arch/h8300/include/asm/flat.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * include/asm-h8300/flat.h -- uClinux flat-format executables
- */
-
-#ifndef __H8300_FLAT_H__
-#define __H8300_FLAT_H__
-
-#define flat_argvp_envp_on_stack() 1
-#define flat_old_ram_flag(flags) 1
-#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
-#define flat_set_persistent(relval, p) 0
-
-/*
- * on the H8 a couple of the relocations have an instruction in the
- * top byte. As there can only be 24bits of address space, we just
- * always preserve that 8bits at the top, when it isn't an instruction
- * is is 0 (davidm@snapgear.com)
- */
-
-#define flat_get_relocate_addr(rel) (rel)
-#define flat_get_addr_from_rp(rp, relval, flags, persistent) \
- (get_unaligned(rp) & ((flags & FLAT_FLAG_GOTPIC) ? 0xffffffff: 0x00ffffff))
-#define flat_put_addr_at_rp(rp, addr, rel) \
- put_unaligned (((*(char *)(rp)) << 24) | ((addr) & 0x00ffffff), rp)
-
-#endif /* __H8300_FLAT_H__ */
diff --git a/arch/h8300/include/asm/fpu.h b/arch/h8300/include/asm/fpu.h
deleted file mode 100644
index 4fc416e80bef..000000000000
--- a/arch/h8300/include/asm/fpu.h
+++ /dev/null
@@ -1 +0,0 @@
-/* Nothing do */
diff --git a/arch/h8300/include/asm/ftrace.h b/arch/h8300/include/asm/ftrace.h
deleted file mode 100644
index 40a8c178f10d..000000000000
--- a/arch/h8300/include/asm/ftrace.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/h8300/include/asm/futex.h b/arch/h8300/include/asm/futex.h
deleted file mode 100644
index 6a332a9f099c..000000000000
--- a/arch/h8300/include/asm/futex.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
-
-#include <asm-generic/futex.h>
-
-#endif
diff --git a/arch/h8300/include/asm/gpio-internal.h b/arch/h8300/include/asm/gpio-internal.h
deleted file mode 100644
index a714f0c0efbc..000000000000
--- a/arch/h8300/include/asm/gpio-internal.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef _H8300_GPIO_H
-#define _H8300_GPIO_H
-
-#define H8300_GPIO_P1 0
-#define H8300_GPIO_P2 1
-#define H8300_GPIO_P3 2
-#define H8300_GPIO_P4 3
-#define H8300_GPIO_P5 4
-#define H8300_GPIO_P6 5
-#define H8300_GPIO_P7 6
-#define H8300_GPIO_P8 7
-#define H8300_GPIO_P9 8
-#define H8300_GPIO_PA 9
-#define H8300_GPIO_PB 10
-#define H8300_GPIO_PC 11
-#define H8300_GPIO_PD 12
-#define H8300_GPIO_PE 13
-#define H8300_GPIO_PF 14
-#define H8300_GPIO_PG 15
-#define H8300_GPIO_PH 16
-
-#define H8300_GPIO_B7 0x80
-#define H8300_GPIO_B6 0x40
-#define H8300_GPIO_B5 0x20
-#define H8300_GPIO_B4 0x10
-#define H8300_GPIO_B3 0x08
-#define H8300_GPIO_B2 0x04
-#define H8300_GPIO_B1 0x02
-#define H8300_GPIO_B0 0x01
-
-#define H8300_GPIO_INPUT 0
-#define H8300_GPIO_OUTPUT 1
-
-#define H8300_GPIO_RESERVE(port, bits) \
- h8300_reserved_gpio(port, bits)
-
-#define H8300_GPIO_FREE(port, bits) \
- h8300_free_gpio(port, bits)
-
-#define H8300_GPIO_DDR(port, bit, dir) \
- h8300_set_gpio_dir(((port) << 8) | (bit), dir)
-
-#define H8300_GPIO_GETDIR(port, bit) \
- h8300_get_gpio_dir(((port) << 8) | (bit))
-
-extern int h8300_reserved_gpio(int port, int bits);
-extern int h8300_free_gpio(int port, int bits);
-extern int h8300_set_gpio_dir(int port_bit, int dir);
-extern int h8300_get_gpio_dir(int port_bit);
-extern int h8300_init_gpio(void);
-
-#endif
diff --git a/arch/h8300/include/asm/hardirq.h b/arch/h8300/include/asm/hardirq.h
deleted file mode 100644
index c2e1aa0f0d14..000000000000
--- a/arch/h8300/include/asm/hardirq.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __H8300_HARDIRQ_H
-#define __H8300_HARDIRQ_H
-
-#include <asm/irq.h>
-
-#define HARDIRQ_BITS 8
-
-/*
- * The hardirq mask has to be large enough to have
- * space for potentially all IRQ sources in the system
- * nesting on a single CPU:
- */
-#if (1 << HARDIRQ_BITS) < NR_IRQS
-# error HARDIRQ_BITS is too low!
-#endif
-
-#include <asm-generic/hardirq.h>
-
-#endif
diff --git a/arch/h8300/include/asm/hw_irq.h b/arch/h8300/include/asm/hw_irq.h
deleted file mode 100644
index d75a5a1119e8..000000000000
--- a/arch/h8300/include/asm/hw_irq.h
+++ /dev/null
@@ -1 +0,0 @@
-/* Do Nothing */
diff --git a/arch/h8300/include/asm/io.h b/arch/h8300/include/asm/io.h
deleted file mode 100644
index c1a8df22080f..000000000000
--- a/arch/h8300/include/asm/io.h
+++ /dev/null
@@ -1,358 +0,0 @@
-#ifndef _H8300_IO_H
-#define _H8300_IO_H
-
-#ifdef __KERNEL__
-
-#include <asm/virtconvert.h>
-
-#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
-#include <asm/regs306x.h>
-#elif defined(CONFIG_H8S2678)
-#include <asm/regs267x.h>
-#else
-#error UNKNOWN CPU TYPE
-#endif
-
-
-/*
- * These are for ISA/PCI shared memory _only_ and should never be used
- * on any other type of memory, including Zorro memory. They are meant to
- * access the bus in the bus byte order which is little-endian!.
- *
- * readX/writeX() are used to access memory mapped devices. On some
- * architectures the memory mapped IO stuff needs to be accessed
- * differently. On the m68k architecture, we just read/write the
- * memory location directly.
- */
-/* ++roman: The assignments to temp. vars avoid that gcc sometimes generates
- * two accesses to memory, which may be undesirable for some devices.
- */
-
-/*
- * swap functions are sometimes needed to interface little-endian hardware
- */
-
-static inline unsigned short _swapw(volatile unsigned short v)
-{
-#ifndef H8300_IO_NOSWAP
- unsigned short r;
- __asm__("xor.b %w0,%x0\n\t"
- "xor.b %x0,%w0\n\t"
- "xor.b %w0,%x0"
- :"=r"(r)
- :"0"(v));
- return r;
-#else
- return v;
-#endif
-}
-
-static inline unsigned long _swapl(volatile unsigned long v)
-{
-#ifndef H8300_IO_NOSWAP
- unsigned long r;
- __asm__("xor.b %w0,%x0\n\t"
- "xor.b %x0,%w0\n\t"
- "xor.b %w0,%x0\n\t"
- "xor.w %e0,%f0\n\t"
- "xor.w %f0,%e0\n\t"
- "xor.w %e0,%f0\n\t"
- "xor.b %w0,%x0\n\t"
- "xor.b %x0,%w0\n\t"
- "xor.b %w0,%x0"
- :"=r"(r)
- :"0"(v));
- return r;
-#else
- return v;
-#endif
-}
-
-#define readb(addr) \
- ({ unsigned char __v = \
- *(volatile unsigned char *)((unsigned long)(addr) & 0x00ffffff); \
- __v; })
-#define readw(addr) \
- ({ unsigned short __v = \
- *(volatile unsigned short *)((unsigned long)(addr) & 0x00ffffff); \
- __v; })
-#define readl(addr) \
- ({ unsigned long __v = \
- *(volatile unsigned long *)((unsigned long)(addr) & 0x00ffffff); \
- __v; })
-
-#define writeb(b,addr) (void)((*(volatile unsigned char *) \
- ((unsigned long)(addr) & 0x00ffffff)) = (b))
-#define writew(b,addr) (void)((*(volatile unsigned short *) \
- ((unsigned long)(addr) & 0x00ffffff)) = (b))
-#define writel(b,addr) (void)((*(volatile unsigned long *) \
- ((unsigned long)(addr) & 0x00ffffff)) = (b))
-#define readb_relaxed(addr) readb(addr)
-#define readw_relaxed(addr) readw(addr)
-#define readl_relaxed(addr) readl(addr)
-
-#define __raw_readb readb
-#define __raw_readw readw
-#define __raw_readl readl
-#define __raw_writeb writeb
-#define __raw_writew writew
-#define __raw_writel writel
-
-static inline int h8300_buswidth(unsigned int addr)
-{
- return (*(volatile unsigned char *)ABWCR & (1 << ((addr >> 21) & 7))) == 0;
-}
-
-static inline void io_outsb(unsigned int addr, const void *buf, int len)
-{
- volatile unsigned char *ap_b = (volatile unsigned char *) addr;
- volatile unsigned short *ap_w = (volatile unsigned short *) addr;
- unsigned char *bp = (unsigned char *) buf;
-
- if(h8300_buswidth(addr) && (addr & 1)) {
- while (len--)
- *ap_w = *bp++;
- } else {
- while (len--)
- *ap_b = *bp++;
- }
-}
-
-static inline void io_outsw(unsigned int addr, const void *buf, int len)
-{
- volatile unsigned short *ap = (volatile unsigned short *) addr;
- unsigned short *bp = (unsigned short *) buf;
- while (len--)
- *ap = _swapw(*bp++);
-}
-
-static inline void io_outsl(unsigned int addr, const void *buf, int len)
-{
- volatile unsigned long *ap = (volatile unsigned long *) addr;
- unsigned long *bp = (unsigned long *) buf;
- while (len--)
- *ap = _swapl(*bp++);
-}
-
-static inline void io_outsw_noswap(unsigned int addr, const void *buf, int len)
-{
- volatile unsigned short *ap = (volatile unsigned short *) addr;
- unsigned short *bp = (unsigned short *) buf;
- while (len--)
- *ap = *bp++;
-}
-
-static inline void io_outsl_noswap(unsigned int addr, const void *buf, int len)
-{
- volatile unsigned long *ap = (volatile unsigned long *) addr;
- unsigned long *bp = (unsigned long *) buf;
- while (len--)
- *ap = *bp++;
-}
-
-static inline void io_insb(unsigned int addr, void *buf, int len)
-{
- volatile unsigned char *ap_b;
- volatile unsigned short *ap_w;
- unsigned char *bp = (unsigned char *) buf;
-
- if(h8300_buswidth(addr)) {
- ap_w = (volatile unsigned short *)(addr & ~1);
- while (len--)
- *bp++ = *ap_w & 0xff;
- } else {
- ap_b = (volatile unsigned char *)addr;
- while (len--)
- *bp++ = *ap_b;
- }
-}
-
-static inline void io_insw(unsigned int addr, void *buf, int len)
-{
- volatile unsigned short *ap = (volatile unsigned short *) addr;
- unsigned short *bp = (unsigned short *) buf;
- while (len--)
- *bp++ = _swapw(*ap);
-}
-
-static inline void io_insl(unsigned int addr, void *buf, int len)
-{
- volatile unsigned long *ap = (volatile unsigned long *) addr;
- unsigned long *bp = (unsigned long *) buf;
- while (len--)
- *bp++ = _swapl(*ap);
-}
-
-static inline void io_insw_noswap(unsigned int addr, void *buf, int len)
-{
- volatile unsigned short *ap = (volatile unsigned short *) addr;
- unsigned short *bp = (unsigned short *) buf;
- while (len--)
- *bp++ = *ap;
-}
-
-static inline void io_insl_noswap(unsigned int addr, void *buf, int len)
-{
- volatile unsigned long *ap = (volatile unsigned long *) addr;
- unsigned long *bp = (unsigned long *) buf;
- while (len--)
- *bp++ = *ap;
-}
-
-/*
- * make the short names macros so specific devices
- * can override them as required
- */
-
-#define memset_io(a,b,c) memset((void *)(a),(b),(c))
-#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
-#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
-
-#define mmiowb()
-
-#define inb(addr) ((h8300_buswidth(addr))?readw((addr) & ~1) & 0xff:readb(addr))
-#define inw(addr) _swapw(readw(addr))
-#define inl(addr) _swapl(readl(addr))
-#define outb(x,addr) ((void)((h8300_buswidth(addr) && \
- ((addr) & 1))?writew(x,(addr) & ~1):writeb(x,addr)))
-#define outw(x,addr) ((void) writew(_swapw(x),addr))
-#define outl(x,addr) ((void) writel(_swapl(x),addr))
-
-#define inb_p(addr) inb(addr)
-#define inw_p(addr) inw(addr)
-#define inl_p(addr) inl(addr)
-#define outb_p(x,addr) outb(x,addr)
-#define outw_p(x,addr) outw(x,addr)
-#define outl_p(x,addr) outl(x,addr)
-
-#define outsb(a,b,l) io_outsb(a,b,l)
-#define outsw(a,b,l) io_outsw(a,b,l)
-#define outsl(a,b,l) io_outsl(a,b,l)
-
-#define insb(a,b,l) io_insb(a,b,l)
-#define insw(a,b,l) io_insw(a,b,l)
-#define insl(a,b,l) io_insl(a,b,l)
-
-#define IO_SPACE_LIMIT 0xffffff
-
-
-/* Values for nocacheflag and cmode */
-#define IOMAP_FULL_CACHING 0
-#define IOMAP_NOCACHE_SER 1
-#define IOMAP_NOCACHE_NONSER 2
-#define IOMAP_WRITETHROUGH 3
-
-extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag);
-extern void __iounmap(void *addr, unsigned long size);
-
-static inline void *ioremap(unsigned long physaddr, unsigned long size)
-{
- return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
-}
-static inline void *ioremap_nocache(unsigned long physaddr, unsigned long size)
-{
- return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
-}
-static inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size)
-{
- return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
-}
-static inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size)
-{
- return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
-}
-
-extern void iounmap(void *addr);
-
-/* H8/300 internal I/O functions */
-static __inline__ unsigned char ctrl_inb(unsigned long addr)
-{
- return *(volatile unsigned char*)addr;
-}
-
-static __inline__ unsigned short ctrl_inw(unsigned long addr)
-{
- return *(volatile unsigned short*)addr;
-}
-
-static __inline__ unsigned long ctrl_inl(unsigned long addr)
-{
- return *(volatile unsigned long*)addr;
-}
-
-static __inline__ void ctrl_outb(unsigned char b, unsigned long addr)
-{
- *(volatile unsigned char*)addr = b;
-}
-
-static __inline__ void ctrl_outw(unsigned short b, unsigned long addr)
-{
- *(volatile unsigned short*)addr = b;
-}
-
-static __inline__ void ctrl_outl(unsigned long b, unsigned long addr)
-{
- *(volatile unsigned long*)addr = b;
-}
-
-static __inline__ void ctrl_bclr(int b, unsigned long addr)
-{
- if (__builtin_constant_p(b))
- switch (b) {
- case 0: __asm__("bclr #0,@%0"::"r"(addr)); break;
- case 1: __asm__("bclr #1,@%0"::"r"(addr)); break;
- case 2: __asm__("bclr #2,@%0"::"r"(addr)); break;
- case 3: __asm__("bclr #3,@%0"::"r"(addr)); break;
- case 4: __asm__("bclr #4,@%0"::"r"(addr)); break;
- case 5: __asm__("bclr #5,@%0"::"r"(addr)); break;
- case 6: __asm__("bclr #6,@%0"::"r"(addr)); break;
- case 7: __asm__("bclr #7,@%0"::"r"(addr)); break;
- }
- else
- __asm__("bclr %w0,@%1"::"r"(b), "r"(addr));
-}
-
-static __inline__ void ctrl_bset(int b, unsigned long addr)
-{
- if (__builtin_constant_p(b))
- switch (b) {
- case 0: __asm__("bset #0,@%0"::"r"(addr)); break;
- case 1: __asm__("bset #1,@%0"::"r"(addr)); break;
- case 2: __asm__("bset #2,@%0"::"r"(addr)); break;
- case 3: __asm__("bset #3,@%0"::"r"(addr)); break;
- case 4: __asm__("bset #4,@%0"::"r"(addr)); break;
- case 5: __asm__("bset #5,@%0"::"r"(addr)); break;
- case 6: __asm__("bset #6,@%0"::"r"(addr)); break;
- case 7: __asm__("bset #7,@%0"::"r"(addr)); break;
- }
- else
- __asm__("bset %w0,@%1"::"r"(b), "r"(addr));
-}
-
-/* Pages to physical address... */
-#define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT)
-#define page_to_bus(page) ((page - mem_map) << PAGE_SHIFT)
-
-/*
- * Macros used for converting between virtual and physical mappings.
- */
-#define phys_to_virt(vaddr) ((void *) (vaddr))
-#define virt_to_phys(vaddr) ((unsigned long) (vaddr))
-
-#define virt_to_bus virt_to_phys
-#define bus_to_virt phys_to_virt
-
-/*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * access
- */
-#define xlate_dev_mem_ptr(p) __va(p)
-
-/*
- * Convert a virtual cached pointer to an uncached pointer
- */
-#define xlate_dev_kmem_ptr(p) p
-
-#endif /* __KERNEL__ */
-
-#endif /* _H8300_IO_H */
diff --git a/arch/h8300/include/asm/irq.h b/arch/h8300/include/asm/irq.h
deleted file mode 100644
index 13d7c601cd0a..000000000000
--- a/arch/h8300/include/asm/irq.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef _H8300_IRQ_H_
-#define _H8300_IRQ_H_
-
-#include <asm/ptrace.h>
-
-#if defined(CONFIG_CPU_H8300H)
-#define NR_IRQS 64
-#define EXT_IRQ0 12
-#define EXT_IRQ1 13
-#define EXT_IRQ2 14
-#define EXT_IRQ3 15
-#define EXT_IRQ4 16
-#define EXT_IRQ5 17
-#define EXT_IRQ6 18
-#define EXT_IRQ7 19
-#define EXT_IRQS 5
-#define IER_REGS *(volatile unsigned char *)IER
-#endif
-#if defined(CONFIG_CPU_H8S)
-#define NR_IRQS 128
-#define EXT_IRQ0 16
-#define EXT_IRQ1 17
-#define EXT_IRQ2 18
-#define EXT_IRQ3 19
-#define EXT_IRQ4 20
-#define EXT_IRQ5 21
-#define EXT_IRQ6 22
-#define EXT_IRQ7 23
-#define EXT_IRQ8 24
-#define EXT_IRQ9 25
-#define EXT_IRQ10 26
-#define EXT_IRQ11 27
-#define EXT_IRQ12 28
-#define EXT_IRQ13 29
-#define EXT_IRQ14 30
-#define EXT_IRQ15 31
-#define EXT_IRQS 15
-
-#define IER_REGS *(volatile unsigned short *)IER
-#endif
-
-static __inline__ int irq_canonicalize(int irq)
-{
- return irq;
-}
-
-typedef void (*h8300_vector)(void);
-
-#endif /* _H8300_IRQ_H_ */
diff --git a/arch/h8300/include/asm/irq_regs.h b/arch/h8300/include/asm/irq_regs.h
deleted file mode 100644
index 3dd9c0b70270..000000000000
--- a/arch/h8300/include/asm/irq_regs.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff --git a/arch/h8300/include/asm/irqflags.h b/arch/h8300/include/asm/irqflags.h
deleted file mode 100644
index 9617cd57aebd..000000000000
--- a/arch/h8300/include/asm/irqflags.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef _H8300_IRQFLAGS_H
-#define _H8300_IRQFLAGS_H
-
-static inline unsigned long arch_local_save_flags(void)
-{
- unsigned long flags;
- asm volatile ("stc ccr,%w0" : "=r" (flags));
- return flags;
-}
-
-static inline void arch_local_irq_disable(void)
-{
- asm volatile ("orc #0x80,ccr" : : : "memory");
-}
-
-static inline void arch_local_irq_enable(void)
-{
- asm volatile ("andc #0x7f,ccr" : : : "memory");
-}
-
-static inline unsigned long arch_local_irq_save(void)
-{
- unsigned long flags = arch_local_save_flags();
- arch_local_irq_disable();
- return flags;
-}
-
-static inline void arch_local_irq_restore(unsigned long flags)
-{
- asm volatile ("ldc %w0,ccr" : : "r" (flags) : "memory");
-}
-
-static inline bool arch_irqs_disabled_flags(unsigned long flags)
-{
- return (flags & 0x80) == 0x80;
-}
-
-static inline bool arch_irqs_disabled(void)
-{
- return arch_irqs_disabled_flags(arch_local_save_flags());
-}
-
-#endif /* _H8300_IRQFLAGS_H */
diff --git a/arch/h8300/include/asm/kdebug.h b/arch/h8300/include/asm/kdebug.h
deleted file mode 100644
index 6ece1b037665..000000000000
--- a/arch/h8300/include/asm/kdebug.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff --git a/arch/h8300/include/asm/kmap_types.h b/arch/h8300/include/asm/kmap_types.h
deleted file mode 100644
index be12a7160116..000000000000
--- a/arch/h8300/include/asm/kmap_types.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_H8300_KMAP_TYPES_H
-#define _ASM_H8300_KMAP_TYPES_H
-
-#include <asm-generic/kmap_types.h>
-
-#endif
diff --git a/arch/h8300/include/asm/local.h b/arch/h8300/include/asm/local.h
deleted file mode 100644
index fdd4efe437cd..000000000000
--- a/arch/h8300/include/asm/local.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_LOCAL_H_
-#define _H8300_LOCAL_H_
-
-#include <asm-generic/local.h>
-
-#endif
diff --git a/arch/h8300/include/asm/local64.h b/arch/h8300/include/asm/local64.h
deleted file mode 100644
index 36c93b5cc239..000000000000
--- a/arch/h8300/include/asm/local64.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
diff --git a/arch/h8300/include/asm/mc146818rtc.h b/arch/h8300/include/asm/mc146818rtc.h
deleted file mode 100644
index ab9d9646d241..000000000000
--- a/arch/h8300/include/asm/mc146818rtc.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Machine dependent access functions for RTC registers.
- */
-#ifndef _H8300_MC146818RTC_H
-#define _H8300_MC146818RTC_H
-
-/* empty include file to satisfy the include in genrtc.c/ide-geometry.c */
-
-#endif /* _H8300_MC146818RTC_H */
diff --git a/arch/h8300/include/asm/mmu_context.h b/arch/h8300/include/asm/mmu_context.h
deleted file mode 100644
index f44b730da54d..000000000000
--- a/arch/h8300/include/asm/mmu_context.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef __H8300_MMU_CONTEXT_H
-#define __H8300_MMU_CONTEXT_H
-
-#include <asm/setup.h>
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-#include <asm-generic/mm_hooks.h>
-
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
-{
-}
-
-static inline int
-init_new_context(struct task_struct *tsk, struct mm_struct *mm)
-{
- // mm->context = virt_to_phys(mm->pgd);
- return(0);
-}
-
-#define destroy_context(mm) do { } while(0)
-#define deactivate_mm(tsk,mm) do { } while(0)
-
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
-{
-}
-
-static inline void activate_mm(struct mm_struct *prev_mm,
- struct mm_struct *next_mm)
-{
-}
-
-#endif
diff --git a/arch/h8300/include/asm/mutex.h b/arch/h8300/include/asm/mutex.h
deleted file mode 100644
index 458c1f7fbc18..000000000000
--- a/arch/h8300/include/asm/mutex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/h8300/include/asm/page.h b/arch/h8300/include/asm/page.h
deleted file mode 100644
index 837381a2df46..000000000000
--- a/arch/h8300/include/asm/page.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef _H8300_PAGE_H
-#define _H8300_PAGE_H
-
-/* PAGE_SHIFT determines the page size */
-
-#define PAGE_SHIFT (12)
-#define PAGE_SIZE (1UL << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
-
-#include <asm/setup.h>
-
-#ifndef __ASSEMBLY__
-
-#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
-#define free_user_page(page, addr) free_page(addr)
-
-#define clear_page(page) memset((page), 0, PAGE_SIZE)
-#define copy_page(to,from) memcpy((to), (from), PAGE_SIZE)
-
-#define clear_user_page(page, vaddr, pg) clear_page(page)
-#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
-
-#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
- alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
-#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
-
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long pmd[16]; } pmd_t;
-typedef struct { unsigned long pgd; } pgd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
-typedef struct page *pgtable_t;
-
-#define pte_val(x) ((x).pte)
-#define pmd_val(x) ((&x)->pmd[0])
-#define pgd_val(x) ((x).pgd)
-#define pgprot_val(x) ((x).pgprot)
-
-#define __pte(x) ((pte_t) { (x) } )
-#define __pmd(x) ((pmd_t) { (x) } )
-#define __pgd(x) ((pgd_t) { (x) } )
-#define __pgprot(x) ((pgprot_t) { (x) } )
-
-extern unsigned long memory_start;
-extern unsigned long memory_end;
-
-#endif /* !__ASSEMBLY__ */
-
-#include <asm/page_offset.h>
-
-#define PAGE_OFFSET (PAGE_OFFSET_RAW)
-
-#ifndef __ASSEMBLY__
-
-#define __pa(vaddr) virt_to_phys(vaddr)
-#define __va(paddr) phys_to_virt((unsigned long)paddr)
-
-#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)
-#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT)
-
-#define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
-#define virt_to_page(addr) (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
-#define page_to_virt(page) ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
-#define pfn_valid(page) (page < max_mapnr)
-
-#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
-
-#define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
- ((void *)(kaddr) < (void *)memory_end))
-
-#endif /* __ASSEMBLY__ */
-
-#include <asm-generic/memory_model.h>
-#include <asm-generic/getorder.h>
-
-#endif /* _H8300_PAGE_H */
diff --git a/arch/h8300/include/asm/page_offset.h b/arch/h8300/include/asm/page_offset.h
deleted file mode 100644
index f8706463008c..000000000000
--- a/arch/h8300/include/asm/page_offset.h
+++ /dev/null
@@ -1,3 +0,0 @@
-
-#define PAGE_OFFSET_RAW 0x00000000
-
diff --git a/arch/h8300/include/asm/param.h b/arch/h8300/include/asm/param.h
deleted file mode 100644
index c3909e7ff178..000000000000
--- a/arch/h8300/include/asm/param.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _H8300_PARAM_H
-#define _H8300_PARAM_H
-
-#include <uapi/asm/param.h>
-
-#define HZ CONFIG_HZ
-#define USER_HZ HZ
-#define CLOCKS_PER_SEC (USER_HZ)
-#endif /* _H8300_PARAM_H */
diff --git a/arch/h8300/include/asm/pci.h b/arch/h8300/include/asm/pci.h
deleted file mode 100644
index 0b2acaa3dd84..000000000000
--- a/arch/h8300/include/asm/pci.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _ASM_H8300_PCI_H
-#define _ASM_H8300_PCI_H
-
-/*
- * asm-h8300/pci.h - H8/300 specific PCI declarations.
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- */
-
-#define pcibios_assign_all_busses() 0
-
-static inline void pcibios_penalize_isa_irq(int irq, int active)
-{
- /* We don't do dynamic PCI IRQ allocation */
-}
-
-#define PCI_DMA_BUS_IS_PHYS (1)
-
-#endif /* _ASM_H8300_PCI_H */
diff --git a/arch/h8300/include/asm/percpu.h b/arch/h8300/include/asm/percpu.h
deleted file mode 100644
index 72c03e3666d8..000000000000
--- a/arch/h8300/include/asm/percpu.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ARCH_H8300_PERCPU__
-#define __ARCH_H8300_PERCPU__
-
-#include <asm-generic/percpu.h>
-
-#endif /* __ARCH_H8300_PERCPU__ */
diff --git a/arch/h8300/include/asm/pgalloc.h b/arch/h8300/include/asm/pgalloc.h
deleted file mode 100644
index c2e89a286d23..000000000000
--- a/arch/h8300/include/asm/pgalloc.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _H8300_PGALLOC_H
-#define _H8300_PGALLOC_H
-
-#include <asm/setup.h>
-
-#define check_pgt_cache() do { } while (0)
-
-#endif /* _H8300_PGALLOC_H */
diff --git a/arch/h8300/include/asm/pgtable.h b/arch/h8300/include/asm/pgtable.h
deleted file mode 100644
index 7ca20f894dd7..000000000000
--- a/arch/h8300/include/asm/pgtable.h
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef _H8300_PGTABLE_H
-#define _H8300_PGTABLE_H
-
-#include <asm-generic/4level-fixup.h>
-
-#include <linux/slab.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/io.h>
-
-#define pgd_present(pgd) (1) /* pages are always present on NO_MM */
-#define pgd_none(pgd) (0)
-#define pgd_bad(pgd) (0)
-#define pgd_clear(pgdp)
-#define kern_addr_valid(addr) (1)
-#define pmd_offset(a, b) ((void *)0)
-#define pmd_none(pmd) (1)
-#define pgd_offset_k(adrdress) ((pgd_t *)0)
-#define pte_offset_kernel(dir, address) ((pte_t *)0)
-
-#define PAGE_NONE __pgprot(0) /* these mean nothing to NO_MM */
-#define PAGE_SHARED __pgprot(0) /* these mean nothing to NO_MM */
-#define PAGE_COPY __pgprot(0) /* these mean nothing to NO_MM */
-#define PAGE_READONLY __pgprot(0) /* these mean nothing to NO_MM */
-#define PAGE_KERNEL __pgprot(0) /* these mean nothing to NO_MM */
-
-extern void paging_init(void);
-#define swapper_pg_dir ((pgd_t *) 0)
-
-#define __swp_type(x) (0)
-#define __swp_offset(x) (0)
-#define __swp_entry(typ,off) ((swp_entry_t) { ((typ) | ((off) << 7)) })
-#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
-#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
-
-static inline int pte_file(pte_t pte) { return 0; }
-
-/*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-#define ZERO_PAGE(vaddr) (virt_to_page(0))
-
-/*
- * These would be in other places but having them here reduces the diffs.
- */
-extern unsigned int kobjsize(const void *objp);
-extern int is_in_rom(unsigned long);
-
-/*
- * No page table caches to initialise
- */
-#define pgtable_cache_init() do { } while (0)
-
-/*
- * All 32bit addresses are effectively valid for vmalloc...
- * Sort of meaningless for non-VM targets.
- */
-#define VMALLOC_START 0
-#define VMALLOC_END 0xffffffff
-
-/*
- * All 32bit addresses are effectively valid for vmalloc...
- * Sort of meaningless for non-VM targets.
- */
-#define VMALLOC_START 0
-#define VMALLOC_END 0xffffffff
-
-#define arch_enter_lazy_cpu_mode() do {} while (0)
-
-#include <asm-generic/pgtable.h>
-
-#endif /* _H8300_PGTABLE_H */
diff --git a/arch/h8300/include/asm/processor.h b/arch/h8300/include/asm/processor.h
deleted file mode 100644
index 4b0ca49bb463..000000000000
--- a/arch/h8300/include/asm/processor.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * include/asm-h8300/processor.h
- *
- * Copyright (C) 2002 Yoshinori Sato
- *
- * Based on: linux/asm-m68nommu/processor.h
- *
- * Copyright (C) 1995 Hamish Macdonald
- */
-
-#ifndef __ASM_H8300_PROCESSOR_H
-#define __ASM_H8300_PROCESSOR_H
-
-/*
- * Default implementation of macro that returns current
- * instruction pointer ("program counter").
- */
-#define current_text_addr() ({ __label__ _l; _l: &&_l;})
-
-#include <linux/compiler.h>
-#include <asm/segment.h>
-#include <asm/fpu.h>
-#include <asm/ptrace.h>
-#include <asm/current.h>
-
-static inline unsigned long rdusp(void) {
- extern unsigned int sw_usp;
- return(sw_usp);
-}
-
-static inline void wrusp(unsigned long usp) {
- extern unsigned int sw_usp;
- sw_usp = usp;
-}
-
-/*
- * User space process size: 3.75GB. This is hardcoded into a few places,
- * so don't change it unless you know what you are doing.
- */
-#define TASK_SIZE (0xFFFFFFFFUL)
-
-#ifdef __KERNEL__
-#define STACK_TOP TASK_SIZE
-#define STACK_TOP_MAX STACK_TOP
-#endif
-
-/*
- * This decides where the kernel will search for a free chunk of vm
- * space during mmap's. We won't be using it
- */
-#define TASK_UNMAPPED_BASE 0
-
-struct thread_struct {
- unsigned long ksp; /* kernel stack pointer */
- unsigned long usp; /* user stack pointer */
- unsigned long ccr; /* saved status register */
- unsigned long esp0; /* points to SR of stack frame */
- struct {
- unsigned short *addr;
- unsigned short inst;
- } breakinfo;
-};
-
-#define INIT_THREAD { \
- .ksp = sizeof(init_stack) + (unsigned long)init_stack, \
- .usp = 0, \
- .ccr = PS_S, \
- .esp0 = 0, \
- .breakinfo = { \
- .addr = (unsigned short *)-1, \
- .inst = 0 \
- } \
-}
-
-/*
- * Do necessary setup to start up a newly executed thread.
- *
- * pass the data segment into user programs if it exists,
- * it can't hurt anything as far as I can tell
- */
-#if defined(__H8300H__)
-#define start_thread(_regs, _pc, _usp) \
-do { \
- (_regs)->pc = (_pc); \
- (_regs)->ccr = 0x00; /* clear all flags */ \
- (_regs)->er5 = current->mm->start_data; /* GOT base */ \
- wrusp((unsigned long)(_usp) - sizeof(unsigned long)*3); \
-} while(0)
-#endif
-#if defined(__H8300S__)
-#define start_thread(_regs, _pc, _usp) \
-do { \
- (_regs)->pc = (_pc); \
- (_regs)->ccr = 0x00; /* clear kernel flag */ \
- (_regs)->exr = 0x78; /* enable all interrupts */ \
- (_regs)->er5 = current->mm->start_data; /* GOT base */ \
- /* 14 = space for retaddr(4), vector(4), er0(4) and ext(2) on stack */ \
- wrusp(((unsigned long)(_usp)) - 14); \
-} while(0)
-#endif
-
-/* Forward declaration, a strange C thing */
-struct task_struct;
-
-/* Free all resources held by a thread. */
-static inline void release_thread(struct task_struct *dead_task)
-{
-}
-
-/*
- * Free current thread data structures etc..
- */
-static inline void exit_thread(void)
-{
-}
-
-/*
- * Return saved PC of a blocked thread.
- */
-unsigned long thread_saved_pc(struct task_struct *tsk);
-unsigned long get_wchan(struct task_struct *p);
-
-#define KSTK_EIP(tsk) \
- ({ \
- unsigned long eip = 0; \
- if ((tsk)->thread.esp0 > PAGE_SIZE && \
- MAP_NR((tsk)->thread.esp0) < max_mapnr) \
- eip = ((struct pt_regs *) (tsk)->thread.esp0)->pc; \
- eip; })
-#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
-
-#define cpu_relax() barrier()
-
-#define HARD_RESET_NOW() ({ \
- local_irq_disable(); \
- asm("jmp @@0"); \
-})
-
-#endif
diff --git a/arch/h8300/include/asm/ptrace.h b/arch/h8300/include/asm/ptrace.h
deleted file mode 100644
index c1826b95c5ca..000000000000
--- a/arch/h8300/include/asm/ptrace.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef _H8300_PTRACE_H
-#define _H8300_PTRACE_H
-
-#include <uapi/asm/ptrace.h>
-
-#ifndef __ASSEMBLY__
-#if defined(CONFIG_CPU_H8S)
-#endif
-#ifndef PS_S
-#define PS_S (0x10)
-#endif
-
-#if defined(__H8300H__)
-#define H8300_REGS_NO 11
-#endif
-#if defined(__H8300S__)
-#define H8300_REGS_NO 12
-#endif
-
-/* Find the stack offset for a register, relative to thread.esp0. */
-#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg)
-
-#define arch_has_single_step() (1)
-
-#define user_mode(regs) (!((regs)->ccr & PS_S))
-#define instruction_pointer(regs) ((regs)->pc)
-#define profile_pc(regs) instruction_pointer(regs)
-#define current_pt_regs() ((struct pt_regs *) \
- (THREAD_SIZE + (unsigned long)current_thread_info()) - 1)
-#define signal_pt_regs() ((struct pt_regs *)current->thread.esp0)
-#define current_user_stack_pointer() rdusp()
-#endif /* __ASSEMBLY__ */
-#endif /* _H8300_PTRACE_H */
diff --git a/arch/h8300/include/asm/regs267x.h b/arch/h8300/include/asm/regs267x.h
deleted file mode 100644
index 1bff731a9f77..000000000000
--- a/arch/h8300/include/asm/regs267x.h
+++ /dev/null
@@ -1,336 +0,0 @@
-/* internal Peripherals Register address define */
-/* CPU: H8/306x */
-
-#if !defined(__REGS_H8S267x__)
-#define __REGS_H8S267x__
-
-#if defined(__KERNEL__)
-
-#define DASTCR 0xFEE01A
-#define DADR0 0xFFFFA4
-#define DADR1 0xFFFFA5
-#define DACR01 0xFFFFA6
-#define DADR2 0xFFFFA8
-#define DADR3 0xFFFFA9
-#define DACR23 0xFFFFAA
-
-#define ADDRA 0xFFFF90
-#define ADDRAH 0xFFFF90
-#define ADDRAL 0xFFFF91
-#define ADDRB 0xFFFF92
-#define ADDRBH 0xFFFF92
-#define ADDRBL 0xFFFF93
-#define ADDRC 0xFFFF94
-#define ADDRCH 0xFFFF94
-#define ADDRCL 0xFFFF95
-#define ADDRD 0xFFFF96
-#define ADDRDH 0xFFFF96
-#define ADDRDL 0xFFFF97
-#define ADDRE 0xFFFF98
-#define ADDREH 0xFFFF98
-#define ADDREL 0xFFFF99
-#define ADDRF 0xFFFF9A
-#define ADDRFH 0xFFFF9A
-#define ADDRFL 0xFFFF9B
-#define ADDRG 0xFFFF9C
-#define ADDRGH 0xFFFF9C
-#define ADDRGL 0xFFFF9D
-#define ADDRH 0xFFFF9E
-#define ADDRHH 0xFFFF9E
-#define ADDRHL 0xFFFF9F
-
-#define ADCSR 0xFFFFA0
-#define ADCR 0xFFFFA1
-
-#define ABWCR 0xFFFEC0
-#define ASTCR 0xFFFEC1
-#define WTCRAH 0xFFFEC2
-#define WTCRAL 0xFFFEC3
-#define WTCRBH 0xFFFEC4
-#define WTCRBL 0xFFFEC5
-#define RDNCR 0xFFFEC6
-#define CSACRH 0xFFFEC8
-#define CSACRL 0xFFFEC9
-#define BROMCRH 0xFFFECA
-#define BROMCRL 0xFFFECB
-#define BCR 0xFFFECC
-#define DRAMCR 0xFFFED0
-#define DRACCR 0xFFFED2
-#define REFCR 0xFFFED4
-#define RTCNT 0xFFFED6
-#define RTCOR 0xFFFED7
-
-#define MAR0AH 0xFFFEE0
-#define MAR0AL 0xFFFEE2
-#define IOAR0A 0xFFFEE4
-#define ETCR0A 0xFFFEE6
-#define MAR0BH 0xFFFEE8
-#define MAR0BL 0xFFFEEA
-#define IOAR0B 0xFFFEEC
-#define ETCR0B 0xFFFEEE
-#define MAR1AH 0xFFFEF0
-#define MAR1AL 0xFFFEF2
-#define IOAR1A 0xFFFEF4
-#define ETCR1A 0xFFFEF6
-#define MAR1BH 0xFFFEF8
-#define MAR1BL 0xFFFEFA
-#define IOAR1B 0xFFFEFC
-#define ETCR1B 0xFFFEFE
-#define DMAWER 0xFFFF20
-#define DMATCR 0xFFFF21
-#define DMACR0A 0xFFFF22
-#define DMACR0B 0xFFFF23
-#define DMACR1A 0xFFFF24
-#define DMACR1B 0xFFFF25
-#define DMABCRH 0xFFFF26
-#define DMABCRL 0xFFFF27
-
-#define EDSAR0 0xFFFDC0
-#define EDDAR0 0xFFFDC4
-#define EDTCR0 0xFFFDC8
-#define EDMDR0 0xFFFDCC
-#define EDMDR0H 0xFFFDCC
-#define EDMDR0L 0xFFFDCD
-#define EDACR0 0xFFFDCE
-#define EDSAR1 0xFFFDD0
-#define EDDAR1 0xFFFDD4
-#define EDTCR1 0xFFFDD8
-#define EDMDR1 0xFFFDDC
-#define EDMDR1H 0xFFFDDC
-#define EDMDR1L 0xFFFDDD
-#define EDACR1 0xFFFDDE
-#define EDSAR2 0xFFFDE0
-#define EDDAR2 0xFFFDE4
-#define EDTCR2 0xFFFDE8
-#define EDMDR2 0xFFFDEC
-#define EDMDR2H 0xFFFDEC
-#define EDMDR2L 0xFFFDED
-#define EDACR2 0xFFFDEE
-#define EDSAR3 0xFFFDF0
-#define EDDAR3 0xFFFDF4
-#define EDTCR3 0xFFFDF8
-#define EDMDR3 0xFFFDFC
-#define EDMDR3H 0xFFFDFC
-#define EDMDR3L 0xFFFDFD
-#define EDACR3 0xFFFDFE
-
-#define IPRA 0xFFFE00
-#define IPRB 0xFFFE02
-#define IPRC 0xFFFE04
-#define IPRD 0xFFFE06
-#define IPRE 0xFFFE08
-#define IPRF 0xFFFE0A
-#define IPRG 0xFFFE0C
-#define IPRH 0xFFFE0E
-#define IPRI 0xFFFE10
-#define IPRJ 0xFFFE12
-#define IPRK 0xFFFE14
-#define ITSR 0xFFFE16
-#define SSIER 0xFFFE18
-#define ISCRH 0xFFFE1A
-#define ISCRL 0xFFFE1C
-
-#define INTCR 0xFFFF31
-#define IER 0xFFFF32
-#define IERH 0xFFFF32
-#define IERL 0xFFFF33
-#define ISR 0xFFFF34
-#define ISRH 0xFFFF34
-#define ISRL 0xFFFF35
-
-#define P1DDR 0xFFFE20
-#define P2DDR 0xFFFE21
-#define P3DDR 0xFFFE22
-#define P4DDR 0xFFFE23
-#define P5DDR 0xFFFE24
-#define P6DDR 0xFFFE25
-#define P7DDR 0xFFFE26
-#define P8DDR 0xFFFE27
-#define P9DDR 0xFFFE28
-#define PADDR 0xFFFE29
-#define PBDDR 0xFFFE2A
-#define PCDDR 0xFFFE2B
-#define PDDDR 0xFFFE2C
-#define PEDDR 0xFFFE2D
-#define PFDDR 0xFFFE2E
-#define PGDDR 0xFFFE2F
-#define PHDDR 0xFFFF74
-
-#define PFCR0 0xFFFE32
-#define PFCR1 0xFFFE33
-#define PFCR2 0xFFFE34
-
-#define PAPCR 0xFFFE36
-#define PBPCR 0xFFFE37
-#define PCPCR 0xFFFE38
-#define PDPCR 0xFFFE39
-#define PEPCR 0xFFFE3A
-
-#define P3ODR 0xFFFE3C
-#define PAODR 0xFFFE3D
-
-#define P1DR 0xFFFF60
-#define P2DR 0xFFFF61
-#define P3DR 0xFFFF62
-#define P4DR 0xFFFF63
-#define P5DR 0xFFFF64
-#define P6DR 0xFFFF65
-#define P7DR 0xFFFF66
-#define P8DR 0xFFFF67
-#define P9DR 0xFFFF68
-#define PADR 0xFFFF69
-#define PBDR 0xFFFF6A
-#define PCDR 0xFFFF6B
-#define PDDR 0xFFFF6C
-#define PEDR 0xFFFF6D
-#define PFDR 0xFFFF6E
-#define PGDR 0xFFFF6F
-#define PHDR 0xFFFF72
-
-#define PORT1 0xFFFF50
-#define PORT2 0xFFFF51
-#define PORT3 0xFFFF52
-#define PORT4 0xFFFF53
-#define PORT5 0xFFFF54
-#define PORT6 0xFFFF55
-#define PORT7 0xFFFF56
-#define PORT8 0xFFFF57
-#define PORT9 0xFFFF58
-#define PORTA 0xFFFF59
-#define PORTB 0xFFFF5A
-#define PORTC 0xFFFF5B
-#define PORTD 0xFFFF5C
-#define PORTE 0xFFFF5D
-#define PORTF 0xFFFF5E
-#define PORTG 0xFFFF5F
-#define PORTH 0xFFFF70
-
-#define PCR 0xFFFF46
-#define PMR 0xFFFF47
-#define NDERH 0xFFFF48
-#define NDERL 0xFFFF49
-#define PODRH 0xFFFF4A
-#define PODRL 0xFFFF4B
-#define NDRH1 0xFFFF4C
-#define NDRL1 0xFFFF4D
-#define NDRH2 0xFFFF4E
-#define NDRL2 0xFFFF4F
-
-#define SMR0 0xFFFF78
-#define BRR0 0xFFFF79
-#define SCR0 0xFFFF7A
-#define TDR0 0xFFFF7B
-#define SSR0 0xFFFF7C
-#define RDR0 0xFFFF7D
-#define SCMR0 0xFFFF7E
-#define SMR1 0xFFFF80
-#define BRR1 0xFFFF81
-#define SCR1 0xFFFF82
-#define TDR1 0xFFFF83
-#define SSR1 0xFFFF84
-#define RDR1 0xFFFF85
-#define SCMR1 0xFFFF86
-#define SMR2 0xFFFF88
-#define BRR2 0xFFFF89
-#define SCR2 0xFFFF8A
-#define TDR2 0xFFFF8B
-#define SSR2 0xFFFF8C
-#define RDR2 0xFFFF8D
-#define SCMR2 0xFFFF8E
-
-#define IRCR0 0xFFFE1E
-#define SEMR 0xFFFDA8
-
-#define MDCR 0xFFFF3E
-#define SYSCR 0xFFFF3D
-#define MSTPCRH 0xFFFF40
-#define MSTPCRL 0xFFFF41
-#define FLMCR1 0xFFFFC8
-#define FLMCR2 0xFFFFC9
-#define EBR1 0xFFFFCA
-#define EBR2 0xFFFFCB
-#define CTGARC_RAMCR 0xFFFECE
-#define SBYCR 0xFFFF3A
-#define SCKCR 0xFFFF3B
-#define PLLCR 0xFFFF45
-
-#define TSTR 0xFFFFC0
-#define TSNC 0XFFFFC1
-
-#define TCR0 0xFFFFD0
-#define TMDR0 0xFFFFD1
-#define TIORH0 0xFFFFD2
-#define TIORL0 0xFFFFD3
-#define TIER0 0xFFFFD4
-#define TSR0 0xFFFFD5
-#define TCNT0 0xFFFFD6
-#define GRA0 0xFFFFD8
-#define GRB0 0xFFFFDA
-#define GRC0 0xFFFFDC
-#define GRD0 0xFFFFDE
-#define TCR1 0xFFFFE0
-#define TMDR1 0xFFFFE1
-#define TIORH1 0xFFFFE2
-#define TIORL1 0xFFFFE3
-#define TIER1 0xFFFFE4
-#define TSR1 0xFFFFE5
-#define TCNT1 0xFFFFE6
-#define GRA1 0xFFFFE8
-#define GRB1 0xFFFFEA
-#define TCR2 0xFFFFF0
-#define TMDR2 0xFFFFF1
-#define TIORH2 0xFFFFF2
-#define TIORL2 0xFFFFF3
-#define TIER2 0xFFFFF4
-#define TSR2 0xFFFFF5
-#define TCNT2 0xFFFFF6
-#define GRA2 0xFFFFF8
-#define GRB2 0xFFFFFA
-#define TCR3 0xFFFE80
-#define TMDR3 0xFFFE81
-#define TIORH3 0xFFFE82
-#define TIORL3 0xFFFE83
-#define TIER3 0xFFFE84
-#define TSR3 0xFFFE85
-#define TCNT3 0xFFFE86
-#define GRA3 0xFFFE88
-#define GRB3 0xFFFE8A
-#define GRC3 0xFFFE8C
-#define GRD3 0xFFFE8E
-#define TCR4 0xFFFE90
-#define TMDR4 0xFFFE91
-#define TIORH4 0xFFFE92
-#define TIORL4 0xFFFE93
-#define TIER4 0xFFFE94
-#define TSR4 0xFFFE95
-#define TCNT4 0xFFFE96
-#define GRA4 0xFFFE98
-#define GRB4 0xFFFE9A
-#define TCR5 0xFFFEA0
-#define TMDR5 0xFFFEA1
-#define TIORH5 0xFFFEA2
-#define TIORL5 0xFFFEA3
-#define TIER5 0xFFFEA4
-#define TSR5 0xFFFEA5
-#define TCNT5 0xFFFEA6
-#define GRA5 0xFFFEA8
-#define GRB5 0xFFFEAA
-
-#define _8TCR0 0xFFFFB0
-#define _8TCR1 0xFFFFB1
-#define _8TCSR0 0xFFFFB2
-#define _8TCSR1 0xFFFFB3
-#define _8TCORA0 0xFFFFB4
-#define _8TCORA1 0xFFFFB5
-#define _8TCORB0 0xFFFFB6
-#define _8TCORB1 0xFFFFB7
-#define _8TCNT0 0xFFFFB8
-#define _8TCNT1 0xFFFFB9
-
-#define TCSR 0xFFFFBC
-#define TCNT 0xFFFFBD
-#define RSTCSRW 0xFFFFBE
-#define RSTCSRR 0xFFFFBF
-
-#endif /* __KERNEL__ */
-#endif /* __REGS_H8S267x__ */
diff --git a/arch/h8300/include/asm/regs306x.h b/arch/h8300/include/asm/regs306x.h
deleted file mode 100644
index 027dd633fa25..000000000000
--- a/arch/h8300/include/asm/regs306x.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/* internal Peripherals Register address define */
-/* CPU: H8/306x */
-
-#if !defined(__REGS_H8306x__)
-#define __REGS_H8306x__
-
-#if defined(__KERNEL__)
-
-#define DASTCR 0xFEE01A
-#define DADR0 0xFEE09C
-#define DADR1 0xFEE09D
-#define DACR 0xFEE09E
-
-#define ADDRAH 0xFFFFE0
-#define ADDRAL 0xFFFFE1
-#define ADDRBH 0xFFFFE2
-#define ADDRBL 0xFFFFE3
-#define ADDRCH 0xFFFFE4
-#define ADDRCL 0xFFFFE5
-#define ADDRDH 0xFFFFE6
-#define ADDRDL 0xFFFFE7
-#define ADCSR 0xFFFFE8
-#define ADCR 0xFFFFE9
-
-#define BRCR 0xFEE013
-#define ADRCR 0xFEE01E
-#define CSCR 0xFEE01F
-#define ABWCR 0xFEE020
-#define ASTCR 0xFEE021
-#define WCRH 0xFEE022
-#define WCRL 0xFEE023
-#define BCR 0xFEE024
-#define DRCRA 0xFEE026
-#define DRCRB 0xFEE027
-#define RTMCSR 0xFEE028
-#define RTCNT 0xFEE029
-#define RTCOR 0xFEE02A
-
-#define MAR0AR 0xFFFF20
-#define MAR0AE 0xFFFF21
-#define MAR0AH 0xFFFF22
-#define MAR0AL 0xFFFF23
-#define ETCR0AL 0xFFFF24
-#define ETCR0AH 0xFFFF25
-#define IOAR0A 0xFFFF26
-#define DTCR0A 0xFFFF27
-#define MAR0BR 0xFFFF28
-#define MAR0BE 0xFFFF29
-#define MAR0BH 0xFFFF2A
-#define MAR0BL 0xFFFF2B
-#define ETCR0BL 0xFFFF2C
-#define ETCR0BH 0xFFFF2D
-#define IOAR0B 0xFFFF2E
-#define DTCR0B 0xFFFF2F
-#define MAR1AR 0xFFFF30
-#define MAR1AE 0xFFFF31
-#define MAR1AH 0xFFFF32
-#define MAR1AL 0xFFFF33
-#define ETCR1AL 0xFFFF34
-#define ETCR1AH 0xFFFF35
-#define IOAR1A 0xFFFF36
-#define DTCR1A 0xFFFF37
-#define MAR1BR 0xFFFF38
-#define MAR1BE 0xFFFF39
-#define MAR1BH 0xFFFF3A
-#define MAR1BL 0xFFFF3B
-#define ETCR1BL 0xFFFF3C
-#define ETCR1BH 0xFFFF3D
-#define IOAR1B 0xFFFF3E
-#define DTCR1B 0xFFFF3F
-
-#define ISCR 0xFEE014
-#define IER 0xFEE015
-#define ISR 0xFEE016
-#define IPRA 0xFEE018
-#define IPRB 0xFEE019
-
-#define P1DDR 0xFEE000
-#define P2DDR 0xFEE001
-#define P3DDR 0xFEE002
-#define P4DDR 0xFEE003
-#define P5DDR 0xFEE004
-#define P6DDR 0xFEE005
-/*#define P7DDR 0xFEE006*/
-#define P8DDR 0xFEE007
-#define P9DDR 0xFEE008
-#define PADDR 0xFEE009
-#define PBDDR 0xFEE00A
-
-#define P1DR 0xFFFFD0
-#define P2DR 0xFFFFD1
-#define P3DR 0xFFFFD2
-#define P4DR 0xFFFFD3
-#define P5DR 0xFFFFD4
-#define P6DR 0xFFFFD5
-/*#define P7DR 0xFFFFD6*/
-#define P8DR 0xFFFFD7
-#define P9DR 0xFFFFD8
-#define PADR 0xFFFFD9
-#define PBDR 0xFFFFDA
-
-#define P2CR 0xFEE03C
-#define P4CR 0xFEE03E
-#define P5CR 0xFEE03F
-
-#define SMR0 0xFFFFB0
-#define BRR0 0xFFFFB1
-#define SCR0 0xFFFFB2
-#define TDR0 0xFFFFB3
-#define SSR0 0xFFFFB4
-#define RDR0 0xFFFFB5
-#define SCMR0 0xFFFFB6
-#define SMR1 0xFFFFB8
-#define BRR1 0xFFFFB9
-#define SCR1 0xFFFFBA
-#define TDR1 0xFFFFBB
-#define SSR1 0xFFFFBC
-#define RDR1 0xFFFFBD
-#define SCMR1 0xFFFFBE
-#define SMR2 0xFFFFC0
-#define BRR2 0xFFFFC1
-#define SCR2 0xFFFFC2
-#define TDR2 0xFFFFC3
-#define SSR2 0xFFFFC4
-#define RDR2 0xFFFFC5
-#define SCMR2 0xFFFFC6
-
-#define MDCR 0xFEE011
-#define SYSCR 0xFEE012
-#define DIVCR 0xFEE01B
-#define MSTCRH 0xFEE01C
-#define MSTCRL 0xFEE01D
-#define FLMCR1 0xFEE030
-#define FLMCR2 0xFEE031
-#define EBR1 0xFEE032
-#define EBR2 0xFEE033
-#define RAMCR 0xFEE077
-
-#define TSTR 0xFFFF60
-#define TSNC 0XFFFF61
-#define TMDR 0xFFFF62
-#define TOLR 0xFFFF63
-#define TISRA 0xFFFF64
-#define TISRB 0xFFFF65
-#define TISRC 0xFFFF66
-#define TCR0 0xFFFF68
-#define TIOR0 0xFFFF69
-#define TCNT0H 0xFFFF6A
-#define TCNT0L 0xFFFF6B
-#define GRA0H 0xFFFF6C
-#define GRA0L 0xFFFF6D
-#define GRB0H 0xFFFF6E
-#define GRB0L 0xFFFF6F
-#define TCR1 0xFFFF70
-#define TIOR1 0xFFFF71
-#define TCNT1H 0xFFFF72
-#define TCNT1L 0xFFFF73
-#define GRA1H 0xFFFF74
-#define GRA1L 0xFFFF75
-#define GRB1H 0xFFFF76
-#define GRB1L 0xFFFF77
-#define TCR3 0xFFFF78
-#define TIOR3 0xFFFF79
-#define TCNT3H 0xFFFF7A
-#define TCNT3L 0xFFFF7B
-#define GRA3H 0xFFFF7C
-#define GRA3L 0xFFFF7D
-#define GRB3H 0xFFFF7E
-#define GRB3L 0xFFFF7F
-
-#define _8TCR0 0xFFFF80
-#define _8TCR1 0xFFFF81
-#define _8TCSR0 0xFFFF82
-#define _8TCSR1 0xFFFF83
-#define TCORA0 0xFFFF84
-#define TCORA1 0xFFFF85
-#define TCORB0 0xFFFF86
-#define TCORB1 0xFFFF87
-#define _8TCNT0 0xFFFF88
-#define _8TCNT1 0xFFFF89
-
-#define _8TCR2 0xFFFF90
-#define _8TCR3 0xFFFF91
-#define _8TCSR2 0xFFFF92
-#define _8TCSR3 0xFFFF93
-#define TCORA2 0xFFFF94
-#define TCORA3 0xFFFF95
-#define TCORB2 0xFFFF96
-#define TCORB3 0xFFFF97
-#define _8TCNT2 0xFFFF98
-#define _8TCNT3 0xFFFF99
-
-#define TCSR 0xFFFF8C
-#define TCNT 0xFFFF8D
-#define RSTCSR 0xFFFF8F
-
-#define TPMR 0xFFFFA0
-#define TPCR 0xFFFFA1
-#define NDERB 0xFFFFA2
-#define NDERA 0xFFFFA3
-#define NDRB1 0xFFFFA4
-#define NDRA1 0xFFFFA5
-#define NDRB2 0xFFFFA6
-#define NDRA2 0xFFFFA7
-
-#define TCSR 0xFFFF8C
-#define TCNT 0xFFFF8D
-#define RSTCSRW 0xFFFF8E
-#define RSTCSRR 0xFFFF8F
-
-#endif /* __KERNEL__ */
-#endif /* __REGS_H8306x__ */
diff --git a/arch/h8300/include/asm/scatterlist.h b/arch/h8300/include/asm/scatterlist.h
deleted file mode 100644
index 82130eda0e5f..000000000000
--- a/arch/h8300/include/asm/scatterlist.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_SCATTERLIST_H
-#define _H8300_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* !(_H8300_SCATTERLIST_H) */
diff --git a/arch/h8300/include/asm/sections.h b/arch/h8300/include/asm/sections.h
deleted file mode 100644
index a81743e8b743..000000000000
--- a/arch/h8300/include/asm/sections.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_SECTIONS_H_
-#define _H8300_SECTIONS_H_
-
-#include <asm-generic/sections.h>
-
-#endif
diff --git a/arch/h8300/include/asm/segment.h b/arch/h8300/include/asm/segment.h
deleted file mode 100644
index b79a82d0f99d..000000000000
--- a/arch/h8300/include/asm/segment.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef _H8300_SEGMENT_H
-#define _H8300_SEGMENT_H
-
-/* define constants */
-#define USER_DATA (1)
-#ifndef __USER_DS
-#define __USER_DS (USER_DATA)
-#endif
-#define USER_PROGRAM (2)
-#define SUPER_DATA (3)
-#ifndef __KERNEL_DS
-#define __KERNEL_DS (SUPER_DATA)
-#endif
-#define SUPER_PROGRAM (4)
-
-#ifndef __ASSEMBLY__
-
-typedef struct {
- unsigned long seg;
-} mm_segment_t;
-
-#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
-#define USER_DS MAKE_MM_SEG(__USER_DS)
-#define KERNEL_DS MAKE_MM_SEG(__KERNEL_DS)
-
-/*
- * Get/set the SFC/DFC registers for MOVES instructions
- */
-
-static inline mm_segment_t get_fs(void)
-{
- return USER_DS;
-}
-
-static inline mm_segment_t get_ds(void)
-{
- /* return the supervisor data space code */
- return KERNEL_DS;
-}
-
-static inline void set_fs(mm_segment_t val)
-{
-}
-
-#define segment_eq(a,b) ((a).seg == (b).seg)
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* _H8300_SEGMENT_H */
diff --git a/arch/h8300/include/asm/sh_bios.h b/arch/h8300/include/asm/sh_bios.h
deleted file mode 100644
index b6bb6e58295c..000000000000
--- a/arch/h8300/include/asm/sh_bios.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* eCos HAL interface header */
-
-#ifndef SH_BIOS_H
-#define SH_BIOS_H
-
-#define HAL_IF_VECTOR_TABLE 0xfffe20
-#define CALL_IF_SET_CONSOLE_COMM 13
-#define QUERY_CURRENT -1
-#define MANGLER -3
-
-/* Checking for GDB stub active */
-/* suggestion Jonathan Larmour */
-static int sh_bios_in_gdb_mode(void)
-{
- static int gdb_active = -1;
- if (gdb_active == -1) {
- int (*set_console_comm)(int);
- set_console_comm = ((void **)HAL_IF_VECTOR_TABLE)[CALL_IF_SET_CONSOLE_COMM];
- gdb_active = (set_console_comm(QUERY_CURRENT) == MANGLER);
- }
- return gdb_active;
-}
-
-static void sh_bios_gdb_detach(void)
-{
-
-}
-
-#endif
diff --git a/arch/h8300/include/asm/shm.h b/arch/h8300/include/asm/shm.h
deleted file mode 100644
index ed6623c0545d..000000000000
--- a/arch/h8300/include/asm/shm.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _H8300_SHM_H
-#define _H8300_SHM_H
-
-
-/* format of page table entries that correspond to shared memory pages
- currently out in swap space (see also mm/swap.c):
- bits 0-1 (PAGE_PRESENT) is = 0
- bits 8..2 (SWP_TYPE) are = SHM_SWP_TYPE
- bits 31..9 are used like this:
- bits 15..9 (SHM_ID) the id of the shared memory segment
- bits 30..16 (SHM_IDX) the index of the page within the shared memory segment
- (actually only bits 25..16 get used since SHMMAX is so low)
- bit 31 (SHM_READ_ONLY) flag whether the page belongs to a read-only attach
-*/
-/* on the m68k both bits 0 and 1 must be zero */
-/* format on the sun3 is similar, but bits 30, 31 are set to zero and all
- others are reduced by 2. --m */
-
-#ifndef CONFIG_SUN3
-#define SHM_ID_SHIFT 9
-#else
-#define SHM_ID_SHIFT 7
-#endif
-#define _SHM_ID_BITS 7
-#define SHM_ID_MASK ((1<<_SHM_ID_BITS)-1)
-
-#define SHM_IDX_SHIFT (SHM_ID_SHIFT+_SHM_ID_BITS)
-#define _SHM_IDX_BITS 15
-#define SHM_IDX_MASK ((1<<_SHM_IDX_BITS)-1)
-
-#endif /* _H8300_SHM_H */
diff --git a/arch/h8300/include/asm/shmparam.h b/arch/h8300/include/asm/shmparam.h
deleted file mode 100644
index d1863953ec64..000000000000
--- a/arch/h8300/include/asm/shmparam.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_SHMPARAM_H
-#define _H8300_SHMPARAM_H
-
-#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
-
-#endif /* _H8300_SHMPARAM_H */
diff --git a/arch/h8300/include/asm/signal.h b/arch/h8300/include/asm/signal.h
deleted file mode 100644
index 6341e36386f8..000000000000
--- a/arch/h8300/include/asm/signal.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _H8300_SIGNAL_H
-#define _H8300_SIGNAL_H
-
-#include <uapi/asm/signal.h>
-
-/* Most things should be clean enough to redefine this at will, if care
- is taken to make libc match. */
-
-#define _NSIG 64
-#define _NSIG_BPW 32
-#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
-
-typedef unsigned long old_sigset_t; /* at least 32 bits */
-
-typedef struct {
- unsigned long sig[_NSIG_WORDS];
-} sigset_t;
-
-#define __ARCH_HAS_SA_RESTORER
-
-#include <asm/sigcontext.h>
-#undef __HAVE_ARCH_SIG_BITOPS
-
-#endif /* _H8300_SIGNAL_H */
diff --git a/arch/h8300/include/asm/smp.h b/arch/h8300/include/asm/smp.h
deleted file mode 100644
index 9e9bd7e58922..000000000000
--- a/arch/h8300/include/asm/smp.h
+++ /dev/null
@@ -1 +0,0 @@
-/* nothing required here yet */
diff --git a/arch/h8300/include/asm/spinlock.h b/arch/h8300/include/asm/spinlock.h
deleted file mode 100644
index d5407fa173e4..000000000000
--- a/arch/h8300/include/asm/spinlock.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __H8300_SPINLOCK_H
-#define __H8300_SPINLOCK_H
-
-#error "H8/300 doesn't do SMP yet"
-
-#endif
diff --git a/arch/h8300/include/asm/string.h b/arch/h8300/include/asm/string.h
deleted file mode 100644
index ca5034897d87..000000000000
--- a/arch/h8300/include/asm/string.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef _H8300_STRING_H_
-#define _H8300_STRING_H_
-
-#ifdef __KERNEL__ /* only set these up for kernel code */
-
-#include <asm/setup.h>
-#include <asm/page.h>
-
-#define __HAVE_ARCH_MEMSET
-extern void * memset(void * s, int c, size_t count);
-
-#define __HAVE_ARCH_MEMCPY
-extern void * memcpy(void *d, const void *s, size_t count);
-
-#else /* KERNEL */
-
-/*
- * let user libraries deal with these,
- * IMHO the kernel has no place defining these functions for user apps
- */
-
-#define __HAVE_ARCH_STRCPY 1
-#define __HAVE_ARCH_STRNCPY 1
-#define __HAVE_ARCH_STRCAT 1
-#define __HAVE_ARCH_STRNCAT 1
-#define __HAVE_ARCH_STRCMP 1
-#define __HAVE_ARCH_STRNCMP 1
-#define __HAVE_ARCH_STRNICMP 1
-#define __HAVE_ARCH_STRCHR 1
-#define __HAVE_ARCH_STRRCHR 1
-#define __HAVE_ARCH_STRSTR 1
-#define __HAVE_ARCH_STRLEN 1
-#define __HAVE_ARCH_STRNLEN 1
-#define __HAVE_ARCH_MEMSET 1
-#define __HAVE_ARCH_MEMCPY 1
-#define __HAVE_ARCH_MEMMOVE 1
-#define __HAVE_ARCH_MEMSCAN 1
-#define __HAVE_ARCH_MEMCMP 1
-#define __HAVE_ARCH_MEMCHR 1
-#define __HAVE_ARCH_STRTOK 1
-
-#endif /* KERNEL */
-
-#endif /* _M68K_STRING_H_ */
diff --git a/arch/h8300/include/asm/switch_to.h b/arch/h8300/include/asm/switch_to.h
deleted file mode 100644
index cdd8731ce487..000000000000
--- a/arch/h8300/include/asm/switch_to.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef _H8300_SWITCH_TO_H
-#define _H8300_SWITCH_TO_H
-
-/*
- * switch_to(n) should switch tasks to task ptr, first checking that
- * ptr isn't the current task, in which case it does nothing. This
- * also clears the TS-flag if the task we switched to has used the
- * math co-processor latest.
- */
-/*
- * switch_to() saves the extra registers, that are not saved
- * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
- * a0-a1. Some of these are used by schedule() and its predecessors
- * and so we might get see unexpected behaviors when a task returns
- * with unexpected register values.
- *
- * syscall stores these registers itself and none of them are used
- * by syscall after the function in the syscall has been called.
- *
- * Beware that resume now expects *next to be in d1 and the offset of
- * tss to be in a1. This saves a few instructions as we no longer have
- * to push them onto the stack and read them back right after.
- *
- * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
- *
- * Changed 96/09/19 by Andreas Schwab
- * pass prev in a0, next in a1, offset of tss in d1, and whether
- * the mm structures are shared in d2 (to avoid atc flushing).
- *
- * H8/300 Porting 2002/09/04 Yoshinori Sato
- */
-
-asmlinkage void resume(void);
-#define switch_to(prev,next,last) { \
- void *_last; \
- __asm__ __volatile__( \
- "mov.l %1, er0\n\t" \
- "mov.l %2, er1\n\t" \
- "mov.l %3, er2\n\t" \
- "jsr @_resume\n\t" \
- "mov.l er2,%0\n\t" \
- : "=r" (_last) \
- : "r" (&(prev->thread)), \
- "r" (&(next->thread)), \
- "g" (prev) \
- : "cc", "er0", "er1", "er2", "er3"); \
- (last) = _last; \
-}
-
-#endif /* _H8300_SWITCH_TO_H */
diff --git a/arch/h8300/include/asm/target_time.h b/arch/h8300/include/asm/target_time.h
deleted file mode 100644
index 9f2a9aa1fe6f..000000000000
--- a/arch/h8300/include/asm/target_time.h
+++ /dev/null
@@ -1,4 +0,0 @@
-extern int platform_timer_setup(void (*timer_int)(int, void *, struct pt_regs *));
-extern void platform_timer_eoi(void);
-extern void platform_gettod(unsigned int *year, unsigned int *mon, unsigned int *day,
- unsigned int *hour, unsigned int *min, unsigned int *sec);
diff --git a/arch/h8300/include/asm/termios.h b/arch/h8300/include/asm/termios.h
deleted file mode 100644
index 93a63df56247..000000000000
--- a/arch/h8300/include/asm/termios.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef _H8300_TERMIOS_H
-#define _H8300_TERMIOS_H
-
-#include <uapi/asm/termios.h>
-
-/* intr=^C quit=^| erase=del kill=^U
- eof=^D vtime=\0 vmin=\1 sxtc=\0
- start=^Q stop=^S susp=^Z eol=\0
- reprint=^R discard=^U werase=^W lnext=^V
- eol2=\0
-*/
-#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-
-/*
- * Translate a "termio" structure into a "termios". Ugh.
- */
-#define user_termio_to_kernel_termios(termios, termio) \
-({ \
- unsigned short tmp; \
- get_user(tmp, &(termio)->c_iflag); \
- (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
- get_user(tmp, &(termio)->c_oflag); \
- (termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
- get_user(tmp, &(termio)->c_cflag); \
- (termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
- get_user(tmp, &(termio)->c_lflag); \
- (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
- get_user((termios)->c_line, &(termio)->c_line); \
- copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-})
-
-/*
- * Translate a "termios" structure into a "termio". Ugh.
- */
-#define kernel_termios_to_user_termio(termio, termios) \
-({ \
- put_user((termios)->c_iflag, &(termio)->c_iflag); \
- put_user((termios)->c_oflag, &(termio)->c_oflag); \
- put_user((termios)->c_cflag, &(termio)->c_cflag); \
- put_user((termios)->c_lflag, &(termio)->c_lflag); \
- put_user((termios)->c_line, &(termio)->c_line); \
- copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
-})
-
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
-#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
-
-#endif /* _H8300_TERMIOS_H */
diff --git a/arch/h8300/include/asm/thread_info.h b/arch/h8300/include/asm/thread_info.h
deleted file mode 100644
index ec2f7777c65a..000000000000
--- a/arch/h8300/include/asm/thread_info.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* thread_info.h: h8300 low-level thread information
- * adapted from the i386 and PPC versions by Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * Copyright (C) 2002 David Howells (dhowells@redhat.com)
- * - Incorporating suggestions made by Linus Torvalds and Dave Miller
- */
-
-#ifndef _ASM_THREAD_INFO_H
-#define _ASM_THREAD_INFO_H
-
-#include <asm/page.h>
-
-#ifdef __KERNEL__
-
-#ifndef __ASSEMBLY__
-
-/*
- * low level task data.
- * If you change this, change the TI_* offsets below to match.
- */
-struct thread_info {
- struct task_struct *task; /* main task structure */
- struct exec_domain *exec_domain; /* execution domain */
- unsigned long flags; /* low level flags */
- int cpu; /* cpu we're on */
- int preempt_count; /* 0 => preemptable, <0 => BUG */
- struct restart_block restart_block;
-};
-
-/*
- * macros/functions for gaining access to the thread information structure
- */
-#define INIT_THREAD_INFO(tsk) \
-{ \
- .task = &tsk, \
- .exec_domain = &default_exec_domain, \
- .flags = 0, \
- .cpu = 0, \
- .preempt_count = INIT_PREEMPT_COUNT, \
- .restart_block = { \
- .fn = do_no_restart_syscall, \
- }, \
-}
-
-#define init_thread_info (init_thread_union.thread_info)
-#define init_stack (init_thread_union.stack)
-
-
-/*
- * Size of kernel stack for each process. This must be a power of 2...
- */
-#define THREAD_SIZE_ORDER 1
-#define THREAD_SIZE 8192 /* 2 pages */
-
-
-/* how to get the thread information struct from C */
-static inline struct thread_info *current_thread_info(void)
-{
- struct thread_info *ti;
- __asm__(
- "mov.l sp, %0 \n\t"
- "and.l %1, %0"
- : "=&r"(ti)
- : "i" (~(THREAD_SIZE-1))
- );
- return ti;
-}
-
-#endif /* __ASSEMBLY__ */
-
-/*
- * Offsets in thread_info structure, used in assembly code
- */
-#define TI_TASK 0
-#define TI_EXECDOMAIN 4
-#define TI_FLAGS 8
-#define TI_CPU 12
-#define TI_PRE_COUNT 16
-
-#define PREEMPT_ACTIVE 0x4000000
-
-/*
- * thread information flag bit numbers
- */
-#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
-#define TIF_SIGPENDING 1 /* signal pending */
-#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
-#define TIF_MEMDIE 4 /* is terminating due to OOM killer */
-#define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */
-#define TIF_NOTIFY_RESUME 6 /* callback before returning to user */
-
-/* as above, but as bit values */
-#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
-#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
-#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
-#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
-
-#define _TIF_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
- _TIF_NOTIFY_RESUME)
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/h8300/include/asm/timer.h b/arch/h8300/include/asm/timer.h
deleted file mode 100644
index def80464d38f..000000000000
--- a/arch/h8300/include/asm/timer.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef __H8300_TIMER_H
-#define __H8300_TIMER_H
-
-void h8300_timer_tick(void);
-void h8300_timer_setup(void);
-void h8300_gettod(unsigned int *year, unsigned int *mon, unsigned int *day,
- unsigned int *hour, unsigned int *min, unsigned int *sec);
-
-#define TIMER_FREQ (CONFIG_CPU_CLOCK*10000) /* Timer input freq. */
-
-#define calc_param(cnt, div, rate, limit) \
-do { \
- cnt = TIMER_FREQ / HZ; \
- for (div = 0; div < ARRAY_SIZE(divide_rate); div++) { \
- if (rate[div] == 0) \
- continue; \
- if ((cnt / rate[div]) > limit) \
- break; \
- } \
- if (div == ARRAY_SIZE(divide_rate)) \
- panic("Timer counter overflow"); \
- cnt /= divide_rate[div]; \
-} while(0)
-
-#endif
diff --git a/arch/h8300/include/asm/timex.h b/arch/h8300/include/asm/timex.h
deleted file mode 100644
index 23e67013439f..000000000000
--- a/arch/h8300/include/asm/timex.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * linux/include/asm-h8300/timex.h
- *
- * H8/300 architecture timex specifications
- */
-#ifndef _ASM_H8300_TIMEX_H
-#define _ASM_H8300_TIMEX_H
-
-#define CLOCK_TICK_RATE (CONFIG_CPU_CLOCK*1000/8192) /* Timer input freq. */
-
-typedef unsigned long cycles_t;
-extern short h8300_timer_count;
-
-static inline cycles_t get_cycles(void)
-{
- return 0;
-}
-
-#endif
diff --git a/arch/h8300/include/asm/tlb.h b/arch/h8300/include/asm/tlb.h
deleted file mode 100644
index 7f0743051ad5..000000000000
--- a/arch/h8300/include/asm/tlb.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __H8300_TLB_H__
-#define __H8300_TLB_H__
-
-#define tlb_flush(tlb) do { } while(0)
-
-#include <asm-generic/tlb.h>
-
-#endif
diff --git a/arch/h8300/include/asm/tlbflush.h b/arch/h8300/include/asm/tlbflush.h
deleted file mode 100644
index 41c148a9208e..000000000000
--- a/arch/h8300/include/asm/tlbflush.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef _H8300_TLBFLUSH_H
-#define _H8300_TLBFLUSH_H
-
-/*
- * Copyright (C) 2000 Lineo, David McCullough <davidm@uclinux.org>
- * Copyright (C) 2000-2002, Greg Ungerer <gerg@snapgear.com>
- */
-
-#include <asm/setup.h>
-
-/*
- * flush all user-space atc entries.
- */
-static inline void __flush_tlb(void)
-{
- BUG();
-}
-
-static inline void __flush_tlb_one(unsigned long addr)
-{
- BUG();
-}
-
-#define flush_tlb() __flush_tlb()
-
-/*
- * flush all atc entries (both kernel and user-space entries).
- */
-static inline void flush_tlb_all(void)
-{
- BUG();
-}
-
-static inline void flush_tlb_mm(struct mm_struct *mm)
-{
- BUG();
-}
-
-static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
-{
- BUG();
-}
-
-static inline void flush_tlb_range(struct mm_struct *mm,
- unsigned long start, unsigned long end)
-{
- BUG();
-}
-
-static inline void flush_tlb_kernel_page(unsigned long addr)
-{
- BUG();
-}
-
-#endif /* _H8300_TLBFLUSH_H */
diff --git a/arch/h8300/include/asm/topology.h b/arch/h8300/include/asm/topology.h
deleted file mode 100644
index fdc121924d4c..000000000000
--- a/arch/h8300/include/asm/topology.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_H8300_TOPOLOGY_H
-#define _ASM_H8300_TOPOLOGY_H
-
-#include <asm-generic/topology.h>
-
-#endif /* _ASM_H8300_TOPOLOGY_H */
diff --git a/arch/h8300/include/asm/traps.h b/arch/h8300/include/asm/traps.h
deleted file mode 100644
index 41cf6be02f68..000000000000
--- a/arch/h8300/include/asm/traps.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * linux/include/asm-h8300/traps.h
- *
- * Copyright (C) 2003 Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * 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.
- */
-
-#ifndef _H8300_TRAPS_H
-#define _H8300_TRAPS_H
-
-extern void system_call(void);
-extern void interrupt_entry(void);
-extern void trace_break(void);
-
-#define JMP_OP 0x5a000000
-#define JSR_OP 0x5e000000
-#define VECTOR(address) ((JMP_OP)|((unsigned long)address))
-#define REDIRECT(address) ((JSR_OP)|((unsigned long)address))
-
-#define TRACE_VEC 5
-
-#define TRAP0_VEC 8
-#define TRAP1_VEC 9
-#define TRAP2_VEC 10
-#define TRAP3_VEC 11
-
-#if defined(__H8300H__)
-#define NR_TRAPS 12
-#endif
-#if defined(__H8300S__)
-#define NR_TRAPS 16
-#endif
-
-#endif /* _H8300_TRAPS_H */
diff --git a/arch/h8300/include/asm/types.h b/arch/h8300/include/asm/types.h
deleted file mode 100644
index c012707f6037..000000000000
--- a/arch/h8300/include/asm/types.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _H8300_TYPES_H
-#define _H8300_TYPES_H
-
-#include <uapi/asm/types.h>
-
-
-#define BITS_PER_LONG 32
-
-#endif /* _H8300_TYPES_H */
diff --git a/arch/h8300/include/asm/uaccess.h b/arch/h8300/include/asm/uaccess.h
deleted file mode 100644
index 8725d1ad4272..000000000000
--- a/arch/h8300/include/asm/uaccess.h
+++ /dev/null
@@ -1,163 +0,0 @@
-#ifndef __H8300_UACCESS_H
-#define __H8300_UACCESS_H
-
-/*
- * User space memory access functions
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-
-#include <asm/segment.h>
-
-#define VERIFY_READ 0
-#define VERIFY_WRITE 1
-
-/* We let the MMU do all checking */
-#define access_ok(type, addr, size) __access_ok((unsigned long)addr,size)
-static inline int __access_ok(unsigned long addr, unsigned long size)
-{
-#define RANGE_CHECK_OK(addr, size, lower, upper) \
- (((addr) >= (lower)) && (((addr) + (size)) < (upper)))
-
- extern unsigned long _ramend;
- return(RANGE_CHECK_OK(addr, size, 0L, (unsigned long)&_ramend));
-}
-
-/*
- * The exception table consists of pairs of addresses: the first is the
- * address of an instruction that is allowed to fault, and the second is
- * the address at which the program should continue. No registers are
- * modified, so it is entirely up to the continuation code to figure out
- * what to do.
- *
- * All the routines below use bits of fixup code that are out of line
- * with the main instruction path. This means when everything is well,
- * we don't even have to jump over them. Further, they do not intrude
- * on our cache or tlb entries.
- */
-
-struct exception_table_entry
-{
- unsigned long insn, fixup;
-};
-
-/* Returns 0 if exception not found and fixup otherwise. */
-extern unsigned long search_exception_table(unsigned long);
-
-
-/*
- * These are the main single-value transfer routines. They automatically
- * use the right size if we just have the right pointer type.
- */
-
-#define put_user(x, ptr) \
-({ \
- int __pu_err = 0; \
- typeof(*(ptr)) __pu_val = (x); \
- switch (sizeof (*(ptr))) { \
- case 1: \
- case 2: \
- case 4: \
- *(ptr) = (__pu_val); \
- break; \
- case 8: \
- memcpy(ptr, &__pu_val, sizeof (*(ptr))); \
- break; \
- default: \
- __pu_err = __put_user_bad(); \
- break; \
- } \
- __pu_err; \
-})
-#define __put_user(x, ptr) put_user(x, ptr)
-
-extern int __put_user_bad(void);
-
-/*
- * Tell gcc we read from memory instead of writing: this is because
- * we do not write to any memory gcc knows about, so there are no
- * aliasing issues.
- */
-
-#define __ptr(x) ((unsigned long *)(x))
-
-/*
- * Tell gcc we read from memory instead of writing: this is because
- * we do not write to any memory gcc knows about, so there are no
- * aliasing issues.
- */
-
-#define get_user(x, ptr) \
-({ \
- int __gu_err = 0; \
- typeof(*(ptr)) __gu_val = *ptr; \
- switch (sizeof(*(ptr))) { \
- case 1: \
- case 2: \
- case 4: \
- case 8: \
- break; \
- default: \
- __gu_err = __get_user_bad(); \
- break; \
- } \
- (x) = __gu_val; \
- __gu_err; \
-})
-#define __get_user(x, ptr) get_user(x, ptr)
-
-extern int __get_user_bad(void);
-
-#define copy_from_user(to, from, n) (memcpy(to, from, n), 0)
-#define copy_to_user(to, from, n) (memcpy(to, from, n), 0)
-
-#define __copy_from_user(to, from, n) copy_from_user(to, from, n)
-#define __copy_to_user(to, from, n) copy_to_user(to, from, n)
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
-
-#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
-
-#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; })
-
-/*
- * Copy a null terminated string from userspace.
- */
-
-static inline long
-strncpy_from_user(char *dst, const char *src, long count)
-{
- char *tmp;
- strncpy(dst, src, count);
- for (tmp = dst; *tmp && count > 0; tmp++, count--)
- ;
- return(tmp - dst); /* DAVIDM should we count a NUL ? check getname */
-}
-
-/*
- * Return the size of a string (including the ending 0)
- *
- * Return 0 on exception, a value greater than N if too long
- */
-static inline long strnlen_user(const char *src, long n)
-{
- return(strlen(src) + 1); /* DAVIDM make safer */
-}
-
-#define strlen_user(str) strnlen_user(str, 32767)
-
-/*
- * Zero Userspace
- */
-
-static inline unsigned long
-clear_user(void *to, unsigned long n)
-{
- memset(to, 0, n);
- return 0;
-}
-
-#define __clear_user clear_user
-
-#endif /* _H8300_UACCESS_H */
diff --git a/arch/h8300/include/asm/ucontext.h b/arch/h8300/include/asm/ucontext.h
deleted file mode 100644
index 0bcf8f85fab9..000000000000
--- a/arch/h8300/include/asm/ucontext.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _H8300_UCONTEXT_H
-#define _H8300_UCONTEXT_H
-
-struct ucontext {
- unsigned long uc_flags;
- struct ucontext *uc_link;
- stack_t uc_stack;
- struct sigcontext uc_mcontext;
- sigset_t uc_sigmask; /* mask last for extensibility */
-};
-
-#endif
diff --git a/arch/h8300/include/asm/unaligned.h b/arch/h8300/include/asm/unaligned.h
deleted file mode 100644
index b8d06c70c2da..000000000000
--- a/arch/h8300/include/asm/unaligned.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _ASM_H8300_UNALIGNED_H
-#define _ASM_H8300_UNALIGNED_H
-
-#include <linux/unaligned/be_memmove.h>
-#include <linux/unaligned/le_byteshift.h>
-#include <linux/unaligned/generic.h>
-
-#define get_unaligned __get_unaligned_be
-#define put_unaligned __put_unaligned_be
-
-#endif /* _ASM_H8300_UNALIGNED_H */
diff --git a/arch/h8300/include/asm/unistd.h b/arch/h8300/include/asm/unistd.h
deleted file mode 100644
index ab671ecf5196..000000000000
--- a/arch/h8300/include/asm/unistd.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef _ASM_H8300_UNISTD_H_
-#define _ASM_H8300_UNISTD_H_
-
-#include <uapi/asm/unistd.h>
-
-
-#define NR_syscalls 321
-
-#define __ARCH_WANT_OLD_READDIR
-#define __ARCH_WANT_OLD_STAT
-#define __ARCH_WANT_STAT64
-#define __ARCH_WANT_SYS_ALARM
-#define __ARCH_WANT_SYS_GETHOSTNAME
-#define __ARCH_WANT_SYS_IPC
-#define __ARCH_WANT_SYS_PAUSE
-#define __ARCH_WANT_SYS_SGETMASK
-#define __ARCH_WANT_SYS_SIGNAL
-#define __ARCH_WANT_SYS_TIME
-#define __ARCH_WANT_SYS_UTIME
-#define __ARCH_WANT_SYS_WAITPID
-#define __ARCH_WANT_SYS_SOCKETCALL
-#define __ARCH_WANT_SYS_FADVISE64
-#define __ARCH_WANT_SYS_GETPGRP
-#define __ARCH_WANT_SYS_LLSEEK
-#define __ARCH_WANT_SYS_NICE
-#define __ARCH_WANT_SYS_OLD_GETRLIMIT
-#define __ARCH_WANT_SYS_OLD_MMAP
-#define __ARCH_WANT_SYS_OLD_SELECT
-#define __ARCH_WANT_SYS_OLDUMOUNT
-#define __ARCH_WANT_SYS_SIGPENDING
-#define __ARCH_WANT_SYS_SIGPROCMASK
-#define __ARCH_WANT_SYS_FORK
-#define __ARCH_WANT_SYS_VFORK
-#define __ARCH_WANT_SYS_CLONE
-
-#endif /* _ASM_H8300_UNISTD_H_ */
diff --git a/arch/h8300/include/asm/user.h b/arch/h8300/include/asm/user.h
deleted file mode 100644
index 14a9e18950f1..000000000000
--- a/arch/h8300/include/asm/user.h
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef _H8300_USER_H
-#define _H8300_USER_H
-
-#include <asm/page.h>
-
-/* Core file format: The core file is written in such a way that gdb
- can understand it and provide useful information to the user (under
- linux we use the 'trad-core' bfd). There are quite a number of
- obstacles to being able to view the contents of the floating point
- registers, and until these are solved you will not be able to view the
- contents of them. Actually, you can read in the core file and look at
- the contents of the user struct to find out what the floating point
- registers contain.
- The actual file contents are as follows:
- UPAGE: 1 page consisting of a user struct that tells gdb what is present
- in the file. Directly after this is a copy of the task_struct, which
- is currently not used by gdb, but it may come in useful at some point.
- All of the registers are stored as part of the upage. The upage should
- always be only one page.
- DATA: The data area is stored. We use current->end_text to
- current->brk to pick up all of the user variables, plus any memory
- that may have been malloced. No attempt is made to determine if a page
- is demand-zero or if a page is totally unused, we just cover the entire
- range. All of the addresses are rounded in such a way that an integral
- number of pages is written.
- STACK: We need the stack information in order to get a meaningful
- backtrace. We need to write the data from (esp) to
- current->start_stack, so we round each of these off in order to be able
- to write an integer number of pages.
- The minimum core file size is 3 pages, or 12288 bytes.
-*/
-
-/* This is the old layout of "struct pt_regs" as of Linux 1.x, and
- is still the layout used by user (the new pt_regs doesn't have
- all registers). */
-struct user_regs_struct {
- long er1,er2,er3,er4,er5,er6;
- long er0;
- long usp;
- long orig_er0;
- short ccr;
- long pc;
-};
-
-
-/* When the kernel dumps core, it starts by dumping the user struct -
- this will be used by gdb to figure out where the data and stack segments
- are within the file, and what virtual addresses to use. */
-struct user{
-/* We start with the registers, to mimic the way that "memory" is returned
- from the ptrace(3,...) function. */
- struct user_regs_struct regs; /* Where the registers are actually stored */
-/* ptrace does not yet supply these. Someday.... */
-/* The rest of this junk is to help gdb figure out what goes where */
- unsigned long int u_tsize; /* Text segment size (pages). */
- unsigned long int u_dsize; /* Data segment size (pages). */
- unsigned long int u_ssize; /* Stack segment size (pages). */
- unsigned long start_code; /* Starting virtual address of text. */
- unsigned long start_stack; /* Starting virtual address of stack area.
- This is actually the bottom of the stack,
- the top of the stack is always found in the
- esp register. */
- long int signal; /* Signal that caused the core dump. */
- int reserved; /* No longer used */
- unsigned long u_ar0; /* Used by gdb to help find the values for */
- /* the registers. */
- unsigned long magic; /* To uniquely identify a core file */
- char u_comm[32]; /* User command that was responsible */
-};
-#define NBPG PAGE_SIZE
-#define UPAGES 1
-#define HOST_TEXT_START_ADDR (u.start_code)
-#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
-
-#endif
diff --git a/arch/h8300/include/asm/virtconvert.h b/arch/h8300/include/asm/virtconvert.h
deleted file mode 100644
index 19cfd62b11c3..000000000000
--- a/arch/h8300/include/asm/virtconvert.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __H8300_VIRT_CONVERT__
-#define __H8300_VIRT_CONVERT__
-
-/*
- * Macros used for converting between virtual and physical mappings.
- */
-
-#ifdef __KERNEL__
-
-#include <asm/setup.h>
-#include <asm/page.h>
-
-#define phys_to_virt(vaddr) ((void *) (vaddr))
-#define virt_to_phys(vaddr) ((unsigned long) (vaddr))
-
-#define virt_to_bus virt_to_phys
-#define bus_to_virt phys_to_virt
-
-#endif
-#endif
diff --git a/arch/h8300/include/uapi/asm/Kbuild b/arch/h8300/include/uapi/asm/Kbuild
deleted file mode 100644
index 040178cdb3eb..000000000000
--- a/arch/h8300/include/uapi/asm/Kbuild
+++ /dev/null
@@ -1,34 +0,0 @@
-# UAPI Header export list
-include include/uapi/asm-generic/Kbuild.asm
-
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += byteorder.h
-header-y += errno.h
-header-y += fcntl.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += kvm_para.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += param.h
-header-y += poll.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
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += termbits.h
-header-y += termios.h
-header-y += types.h
-header-y += unistd.h
diff --git a/arch/h8300/include/uapi/asm/auxvec.h b/arch/h8300/include/uapi/asm/auxvec.h
deleted file mode 100644
index 1d36fe38b088..000000000000
--- a/arch/h8300/include/uapi/asm/auxvec.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __ASMH8300_AUXVEC_H
-#define __ASMH8300_AUXVEC_H
-
-#endif
diff --git a/arch/h8300/include/uapi/asm/bitsperlong.h b/arch/h8300/include/uapi/asm/bitsperlong.h
deleted file mode 100644
index 6dc0bb0c13b2..000000000000
--- a/arch/h8300/include/uapi/asm/bitsperlong.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/bitsperlong.h>
diff --git a/arch/h8300/include/uapi/asm/byteorder.h b/arch/h8300/include/uapi/asm/byteorder.h
deleted file mode 100644
index 13539da99efd..000000000000
--- a/arch/h8300/include/uapi/asm/byteorder.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_BYTEORDER_H
-#define _H8300_BYTEORDER_H
-
-#include <linux/byteorder/big_endian.h>
-
-#endif /* _H8300_BYTEORDER_H */
diff --git a/arch/h8300/include/uapi/asm/errno.h b/arch/h8300/include/uapi/asm/errno.h
deleted file mode 100644
index 0c2f5641fdcc..000000000000
--- a/arch/h8300/include/uapi/asm/errno.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_ERRNO_H
-#define _H8300_ERRNO_H
-
-#include <asm-generic/errno.h>
-
-#endif /* _H8300_ERRNO_H */
diff --git a/arch/h8300/include/uapi/asm/fcntl.h b/arch/h8300/include/uapi/asm/fcntl.h
deleted file mode 100644
index 1952cb2e3b06..000000000000
--- a/arch/h8300/include/uapi/asm/fcntl.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _H8300_FCNTL_H
-#define _H8300_FCNTL_H
-
-#define O_DIRECTORY 040000 /* must be a directory */
-#define O_NOFOLLOW 0100000 /* don't follow links */
-#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */
-#define O_LARGEFILE 0400000
-
-#include <asm-generic/fcntl.h>
-
-#endif /* _H8300_FCNTL_H */
diff --git a/arch/h8300/include/uapi/asm/ioctl.h b/arch/h8300/include/uapi/asm/ioctl.h
deleted file mode 100644
index b279fe06dfe5..000000000000
--- a/arch/h8300/include/uapi/asm/ioctl.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctl.h>
diff --git a/arch/h8300/include/uapi/asm/ioctls.h b/arch/h8300/include/uapi/asm/ioctls.h
deleted file mode 100644
index 30eaed2facdb..000000000000
--- a/arch/h8300/include/uapi/asm/ioctls.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __ARCH_H8300_IOCTLS_H__
-#define __ARCH_H8300_IOCTLS_H__
-
-#define FIOQSIZE 0x545E
-
-#include <asm-generic/ioctls.h>
-
-#endif /* __ARCH_H8300_IOCTLS_H__ */
diff --git a/arch/h8300/include/uapi/asm/ipcbuf.h b/arch/h8300/include/uapi/asm/ipcbuf.h
deleted file mode 100644
index 84c7e51cb6d0..000000000000
--- a/arch/h8300/include/uapi/asm/ipcbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipcbuf.h>
diff --git a/arch/h8300/include/uapi/asm/kvm_para.h b/arch/h8300/include/uapi/asm/kvm_para.h
deleted file mode 100644
index 14fab8f0b957..000000000000
--- a/arch/h8300/include/uapi/asm/kvm_para.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
diff --git a/arch/h8300/include/uapi/asm/mman.h b/arch/h8300/include/uapi/asm/mman.h
deleted file mode 100644
index 8eebf89f5ab1..000000000000
--- a/arch/h8300/include/uapi/asm/mman.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/mman.h>
diff --git a/arch/h8300/include/uapi/asm/msgbuf.h b/arch/h8300/include/uapi/asm/msgbuf.h
deleted file mode 100644
index 6b148cd09aa5..000000000000
--- a/arch/h8300/include/uapi/asm/msgbuf.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _H8300_MSGBUF_H
-#define _H8300_MSGBUF_H
-
-/*
- * The msqid64_ds structure for H8/300 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct msqid64_ds {
- struct ipc64_perm msg_perm;
- __kernel_time_t msg_stime; /* last msgsnd time */
- unsigned long __unused1;
- __kernel_time_t msg_rtime; /* last msgrcv time */
- unsigned long __unused2;
- __kernel_time_t msg_ctime; /* last change time */
- unsigned long __unused3;
- unsigned long msg_cbytes; /* current number of bytes on queue */
- unsigned long msg_qnum; /* number of messages in queue */
- unsigned long msg_qbytes; /* max number of bytes on queue */
- __kernel_pid_t msg_lspid; /* pid of last msgsnd */
- __kernel_pid_t msg_lrpid; /* last receive pid */
- unsigned long __unused4;
- unsigned long __unused5;
-};
-
-#endif /* _H8300_MSGBUF_H */
diff --git a/arch/h8300/include/uapi/asm/param.h b/arch/h8300/include/uapi/asm/param.h
deleted file mode 100644
index 3dd18ae15f03..000000000000
--- a/arch/h8300/include/uapi/asm/param.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _UAPI_H8300_PARAM_H
-#define _UAPI_H8300_PARAM_H
-
-#ifndef __KERNEL__
-#define HZ 100
-#endif
-
-#define EXEC_PAGESIZE 4096
-
-#ifndef NOGROUP
-#define NOGROUP (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64 /* max length of hostname */
-
-#endif /* _UAPI_H8300_PARAM_H */
diff --git a/arch/h8300/include/uapi/asm/poll.h b/arch/h8300/include/uapi/asm/poll.h
deleted file mode 100644
index f61540c22d94..000000000000
--- a/arch/h8300/include/uapi/asm/poll.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __H8300_POLL_H
-#define __H8300_POLL_H
-
-#define POLLWRNORM POLLOUT
-#define POLLWRBAND 256
-
-#include <asm-generic/poll.h>
-
-#undef POLLREMOVE
-
-#endif
diff --git a/arch/h8300/include/uapi/asm/posix_types.h b/arch/h8300/include/uapi/asm/posix_types.h
deleted file mode 100644
index 91e62ba4c7b0..000000000000
--- a/arch/h8300/include/uapi/asm/posix_types.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef __ARCH_H8300_POSIX_TYPES_H
-#define __ARCH_H8300_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc. Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned short __kernel_mode_t;
-#define __kernel_mode_t __kernel_mode_t
-
-typedef unsigned short __kernel_ipc_pid_t;
-#define __kernel_ipc_pid_t __kernel_ipc_pid_t
-
-typedef unsigned short __kernel_uid_t;
-typedef unsigned short __kernel_gid_t;
-#define __kernel_uid_t __kernel_uid_t
-
-typedef unsigned short __kernel_old_uid_t;
-typedef unsigned short __kernel_old_gid_t;
-#define __kernel_old_uid_t __kernel_old_uid_t
-
-#include <asm-generic/posix_types.h>
-
-#endif
diff --git a/arch/h8300/include/uapi/asm/ptrace.h b/arch/h8300/include/uapi/asm/ptrace.h
deleted file mode 100644
index ef39ec5977b6..000000000000
--- a/arch/h8300/include/uapi/asm/ptrace.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef _UAPI_H8300_PTRACE_H
-#define _UAPI_H8300_PTRACE_H
-
-#ifndef __ASSEMBLY__
-
-#define PT_ER1 0
-#define PT_ER2 1
-#define PT_ER3 2
-#define PT_ER4 3
-#define PT_ER5 4
-#define PT_ER6 5
-#define PT_ER0 6
-#define PT_ORIG_ER0 7
-#define PT_CCR 8
-#define PT_PC 9
-#define PT_USP 10
-#define PT_EXR 12
-
-/* this struct defines the way the registers are stored on the
- stack during a system call. */
-
-struct pt_regs {
- long retpc;
- long er4;
- long er5;
- long er6;
- long er3;
- long er2;
- long er1;
- long orig_er0;
- unsigned short ccr;
- long er0;
- long vector;
-#if defined(CONFIG_CPU_H8S)
- unsigned short exr;
-#endif
- unsigned long pc;
-} __attribute__((aligned(2),packed));
-
-#define PTRACE_GETREGS 12
-#define PTRACE_SETREGS 13
-
-#endif /* __ASSEMBLY__ */
-#endif /* _UAPI_H8300_PTRACE_H */
diff --git a/arch/h8300/include/uapi/asm/resource.h b/arch/h8300/include/uapi/asm/resource.h
deleted file mode 100644
index 46c5f4391607..000000000000
--- a/arch/h8300/include/uapi/asm/resource.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_RESOURCE_H
-#define _H8300_RESOURCE_H
-
-#include <asm-generic/resource.h>
-
-#endif /* _H8300_RESOURCE_H */
diff --git a/arch/h8300/include/uapi/asm/sembuf.h b/arch/h8300/include/uapi/asm/sembuf.h
deleted file mode 100644
index e04a3ec0cb92..000000000000
--- a/arch/h8300/include/uapi/asm/sembuf.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef _H8300_SEMBUF_H
-#define _H8300_SEMBUF_H
-
-/*
- * The semid64_ds structure for m68k architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct semid64_ds {
- struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
- __kernel_time_t sem_otime; /* last semop time */
- unsigned long __unused1;
- __kernel_time_t sem_ctime; /* last change time */
- unsigned long __unused2;
- unsigned long sem_nsems; /* no. of semaphores in array */
- unsigned long __unused3;
- unsigned long __unused4;
-};
-
-#endif /* _H8300_SEMBUF_H */
diff --git a/arch/h8300/include/uapi/asm/setup.h b/arch/h8300/include/uapi/asm/setup.h
deleted file mode 100644
index e2c600e96733..000000000000
--- a/arch/h8300/include/uapi/asm/setup.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __H8300_SETUP_H
-#define __H8300_SETUP_H
-
-#define COMMAND_LINE_SIZE 512
-
-#endif
diff --git a/arch/h8300/include/uapi/asm/shmbuf.h b/arch/h8300/include/uapi/asm/shmbuf.h
deleted file mode 100644
index 64e77993a7a9..000000000000
--- a/arch/h8300/include/uapi/asm/shmbuf.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef _H8300_SHMBUF_H
-#define _H8300_SHMBUF_H
-
-/*
- * The shmid64_ds structure for m68k architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct shmid64_ds {
- struct ipc64_perm shm_perm; /* operation perms */
- size_t shm_segsz; /* size of segment (bytes) */
- __kernel_time_t shm_atime; /* last attach time */
- unsigned long __unused1;
- __kernel_time_t shm_dtime; /* last detach time */
- unsigned long __unused2;
- __kernel_time_t shm_ctime; /* last change time */
- unsigned long __unused3;
- __kernel_pid_t shm_cpid; /* pid of creator */
- __kernel_pid_t shm_lpid; /* pid of last operator */
- unsigned long shm_nattch; /* no. of current attaches */
- unsigned long __unused4;
- unsigned long __unused5;
-};
-
-struct shminfo64 {
- unsigned long shmmax;
- unsigned long shmmin;
- unsigned long shmmni;
- unsigned long shmseg;
- unsigned long shmall;
- unsigned long __unused1;
- unsigned long __unused2;
- unsigned long __unused3;
- unsigned long __unused4;
-};
-
-#endif /* _H8300_SHMBUF_H */
diff --git a/arch/h8300/include/uapi/asm/sigcontext.h b/arch/h8300/include/uapi/asm/sigcontext.h
deleted file mode 100644
index e4b81505f8f8..000000000000
--- a/arch/h8300/include/uapi/asm/sigcontext.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _ASM_H8300_SIGCONTEXT_H
-#define _ASM_H8300_SIGCONTEXT_H
-
-struct sigcontext {
- unsigned long sc_mask; /* old sigmask */
- unsigned long sc_usp; /* old user stack pointer */
- unsigned long sc_er0;
- unsigned long sc_er1;
- unsigned long sc_er2;
- unsigned long sc_er3;
- unsigned long sc_er4;
- unsigned long sc_er5;
- unsigned long sc_er6;
- unsigned short sc_ccr;
- unsigned long sc_pc;
-};
-
-#endif
diff --git a/arch/h8300/include/uapi/asm/siginfo.h b/arch/h8300/include/uapi/asm/siginfo.h
deleted file mode 100644
index bc8fbea931a5..000000000000
--- a/arch/h8300/include/uapi/asm/siginfo.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_SIGINFO_H
-#define _H8300_SIGINFO_H
-
-#include <asm-generic/siginfo.h>
-
-#endif
diff --git a/arch/h8300/include/uapi/asm/signal.h b/arch/h8300/include/uapi/asm/signal.h
deleted file mode 100644
index af3a6c37fee6..000000000000
--- a/arch/h8300/include/uapi/asm/signal.h
+++ /dev/null
@@ -1,115 +0,0 @@
-#ifndef _UAPI_H8300_SIGNAL_H
-#define _UAPI_H8300_SIGNAL_H
-
-#include <linux/types.h>
-
-/* Avoid too many header ordering problems. */
-struct siginfo;
-
-#ifndef __KERNEL__
-/* Here we must cater to libcs that poke about in kernel headers. */
-
-#define NSIG 32
-typedef unsigned long sigset_t;
-
-#endif /* __KERNEL__ */
-
-#define SIGHUP 1
-#define SIGINT 2
-#define SIGQUIT 3
-#define SIGILL 4
-#define SIGTRAP 5
-#define SIGABRT 6
-#define SIGIOT 6
-#define SIGBUS 7
-#define SIGFPE 8
-#define SIGKILL 9
-#define SIGUSR1 10
-#define SIGSEGV 11
-#define SIGUSR2 12
-#define SIGPIPE 13
-#define SIGALRM 14
-#define SIGTERM 15
-#define SIGSTKFLT 16
-#define SIGCHLD 17
-#define SIGCONT 18
-#define SIGSTOP 19
-#define SIGTSTP 20
-#define SIGTTIN 21
-#define SIGTTOU 22
-#define SIGURG 23
-#define SIGXCPU 24
-#define SIGXFSZ 25
-#define SIGVTALRM 26
-#define SIGPROF 27
-#define SIGWINCH 28
-#define SIGIO 29
-#define SIGPOLL SIGIO
-/*
-#define SIGLOST 29
-*/
-#define SIGPWR 30
-#define SIGSYS 31
-#define SIGUNUSED 31
-
-/* These should not be considered constants from userland. */
-#define SIGRTMIN 32
-#define SIGRTMAX _NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP 0x00000001
-#define SA_NOCLDWAIT 0x00000002 /* not supported yet */
-#define SA_SIGINFO 0x00000004
-#define SA_ONSTACK 0x08000000
-#define SA_RESTART 0x10000000
-#define SA_NODEFER 0x40000000
-#define SA_RESETHAND 0x80000000
-
-#define SA_NOMASK SA_NODEFER
-#define SA_ONESHOT SA_RESETHAND
-
-#define SA_RESTORER 0x04000000
-
-#define MINSIGSTKSZ 2048
-#define SIGSTKSZ 8192
-
-#include <asm-generic/signal-defs.h>
-
-#ifndef __KERNEL__
-/* Here we must cater to libcs that poke about in kernel headers. */
-
-struct sigaction {
- union {
- __sighandler_t _sa_handler;
- void (*_sa_sigaction)(int, struct siginfo *, void *);
- } _u;
- sigset_t sa_mask;
- unsigned long sa_flags;
- void (*sa_restorer)(void);
-};
-
-#define sa_handler _u._sa_handler
-#define sa_sigaction _u._sa_sigaction
-
-#endif /* __KERNEL__ */
-
-typedef struct sigaltstack {
- void *ss_sp;
- int ss_flags;
- size_t ss_size;
-} stack_t;
-
-
-#endif /* _UAPI_H8300_SIGNAL_H */
diff --git a/arch/h8300/include/uapi/asm/socket.h b/arch/h8300/include/uapi/asm/socket.h
deleted file mode 100644
index 9490758c5e2b..000000000000
--- a/arch/h8300/include/uapi/asm/socket.h
+++ /dev/null
@@ -1,79 +0,0 @@
-#ifndef _ASM_SOCKET_H
-#define _ASM_SOCKET_H
-
-#include <asm/sockios.h>
-
-/* For setsockoptions(2) */
-#define SOL_SOCKET 1
-
-#define SO_DEBUG 1
-#define SO_REUSEADDR 2
-#define SO_TYPE 3
-#define SO_ERROR 4
-#define SO_DONTROUTE 5
-#define SO_BROADCAST 6
-#define SO_SNDBUF 7
-#define SO_RCVBUF 8
-#define SO_SNDBUFFORCE 32
-#define SO_RCVBUFFORCE 33
-#define SO_KEEPALIVE 9
-#define SO_OOBINLINE 10
-#define SO_NO_CHECK 11
-#define SO_PRIORITY 12
-#define SO_LINGER 13
-#define SO_BSDCOMPAT 14
-#define SO_REUSEPORT 15
-#define SO_PASSCRED 16
-#define SO_PEERCRED 17
-#define SO_RCVLOWAT 18
-#define SO_SNDLOWAT 19
-#define SO_RCVTIMEO 20
-#define SO_SNDTIMEO 21
-
-/* Security levels - as per NRL IPv6 - don't actually do anything */
-#define SO_SECURITY_AUTHENTICATION 22
-#define SO_SECURITY_ENCRYPTION_TRANSPORT 23
-#define SO_SECURITY_ENCRYPTION_NETWORK 24
-
-#define SO_BINDTODEVICE 25
-
-/* Socket filtering */
-#define SO_ATTACH_FILTER 26
-#define SO_DETACH_FILTER 27
-#define SO_GET_FILTER SO_ATTACH_FILTER
-
-#define SO_PEERNAME 28
-#define SO_TIMESTAMP 29
-#define SCM_TIMESTAMP SO_TIMESTAMP
-
-#define SO_ACCEPTCONN 30
-
-#define SO_PEERSEC 31
-#define SO_PASSSEC 34
-#define SO_TIMESTAMPNS 35
-#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
-
-#define SO_MARK 36
-
-#define SO_TIMESTAMPING 37
-#define SCM_TIMESTAMPING SO_TIMESTAMPING
-
-#define SO_PROTOCOL 38
-#define SO_DOMAIN 39
-
-#define SO_RXQ_OVFL 40
-
-#define SO_WIFI_STATUS 41
-#define SCM_WIFI_STATUS SO_WIFI_STATUS
-#define SO_PEEK_OFF 42
-
-/* Instruct lower device to use last 4-bytes of skb data as FCS */
-#define SO_NOFCS 43
-
-#define SO_LOCK_FILTER 44
-
-#define SO_SELECT_ERR_QUEUE 45
-
-#define SO_BUSY_POLL 46
-
-#endif /* _ASM_SOCKET_H */
diff --git a/arch/h8300/include/uapi/asm/sockios.h b/arch/h8300/include/uapi/asm/sockios.h
deleted file mode 100644
index e9c7ec810c23..000000000000
--- a/arch/h8300/include/uapi/asm/sockios.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ARCH_H8300_SOCKIOS__
-#define __ARCH_H8300_SOCKIOS__
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN 0x8901
-#define SIOCSPGRP 0x8902
-#define FIOGETOWN 0x8903
-#define SIOCGPGRP 0x8904
-#define SIOCATMARK 0x8905
-#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
-#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
-
-#endif /* __ARCH_H8300_SOCKIOS__ */
diff --git a/arch/h8300/include/uapi/asm/stat.h b/arch/h8300/include/uapi/asm/stat.h
deleted file mode 100644
index 62c3cc24dfe6..000000000000
--- a/arch/h8300/include/uapi/asm/stat.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef _H8300_STAT_H
-#define _H8300_STAT_H
-
-struct __old_kernel_stat {
- unsigned short st_dev;
- unsigned short st_ino;
- unsigned short st_mode;
- unsigned short st_nlink;
- unsigned short st_uid;
- unsigned short st_gid;
- unsigned short st_rdev;
- unsigned long st_size;
- unsigned long st_atime;
- unsigned long st_mtime;
- unsigned long st_ctime;
-};
-
-struct stat {
- unsigned short st_dev;
- unsigned short __pad1;
- unsigned long st_ino;
- unsigned short st_mode;
- unsigned short st_nlink;
- unsigned short st_uid;
- unsigned short st_gid;
- unsigned short st_rdev;
- unsigned short __pad2;
- unsigned long st_size;
- unsigned long st_blksize;
- unsigned long st_blocks;
- unsigned long st_atime;
- unsigned long __unused1;
- unsigned long st_mtime;
- unsigned long __unused2;
- unsigned long st_ctime;
- unsigned long __unused3;
- unsigned long __unused4;
- unsigned long __unused5;
-};
-
-/* This matches struct stat64 in glibc2.1, hence the absolutely
- * insane amounts of padding around dev_t's.
- */
-struct stat64 {
- unsigned long long st_dev;
- unsigned char __pad1[2];
-
-#define STAT64_HAS_BROKEN_ST_INO 1
- unsigned long __st_ino;
-
- unsigned int st_mode;
- unsigned int st_nlink;
-
- unsigned long st_uid;
- unsigned long st_gid;
-
- unsigned long long st_rdev;
- unsigned char __pad3[2];
-
- long long st_size;
- unsigned long st_blksize;
-
- unsigned long __pad4; /* future possible st_blocks high bits */
- unsigned long st_blocks; /* Number 512-byte blocks allocated. */
-
- unsigned long st_atime;
- unsigned long st_atime_nsec;
-
- unsigned long st_mtime;
- unsigned long st_mtime_nsec;
-
- unsigned long st_ctime;
- unsigned long st_ctime_nsec;
-
- unsigned long long st_ino;
-};
-
-#endif /* _H8300_STAT_H */
diff --git a/arch/h8300/include/uapi/asm/statfs.h b/arch/h8300/include/uapi/asm/statfs.h
deleted file mode 100644
index b96efa712aac..000000000000
--- a/arch/h8300/include/uapi/asm/statfs.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_STATFS_H
-#define _H8300_STATFS_H
-
-#include <asm-generic/statfs.h>
-
-#endif /* _H8300_STATFS_H */
diff --git a/arch/h8300/include/uapi/asm/swab.h b/arch/h8300/include/uapi/asm/swab.h
deleted file mode 100644
index 39abbf52807d..000000000000
--- a/arch/h8300/include/uapi/asm/swab.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _H8300_SWAB_H
-#define _H8300_SWAB_H
-
-#include <linux/types.h>
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-# define __SWAB_64_THRU_32__
-#endif
-
-#endif /* _H8300_SWAB_H */
diff --git a/arch/h8300/include/uapi/asm/termbits.h b/arch/h8300/include/uapi/asm/termbits.h
deleted file mode 100644
index 3287a6244d74..000000000000
--- a/arch/h8300/include/uapi/asm/termbits.h
+++ /dev/null
@@ -1,201 +0,0 @@
-#ifndef __ARCH_H8300_TERMBITS_H__
-#define __ARCH_H8300_TERMBITS_H__
-
-#include <linux/posix_types.h>
-
-typedef unsigned char cc_t;
-typedef unsigned int speed_t;
-typedef unsigned int tcflag_t;
-
-#define NCCS 19
-struct termios {
- tcflag_t c_iflag; /* input mode flags */
- tcflag_t c_oflag; /* output mode flags */
- tcflag_t c_cflag; /* control mode flags */
- tcflag_t c_lflag; /* local mode flags */
- cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
-};
-
-struct termios2 {
- tcflag_t c_iflag; /* input mode flags */
- tcflag_t c_oflag; /* output mode flags */
- tcflag_t c_cflag; /* control mode flags */
- tcflag_t c_lflag; /* local mode flags */
- cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
- speed_t c_ispeed; /* input speed */
- speed_t c_ospeed; /* output speed */
-};
-
-struct ktermios {
- tcflag_t c_iflag; /* input mode flags */
- tcflag_t c_oflag; /* output mode flags */
- tcflag_t c_cflag; /* control mode flags */
- tcflag_t c_lflag; /* local mode flags */
- cc_t c_line; /* line discipline */
- cc_t c_cc[NCCS]; /* control characters */
- speed_t c_ispeed; /* input speed */
- speed_t c_ospeed; /* output speed */
-};
-
-/* c_cc characters */
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-
-/* c_iflag bits */
-#define IGNBRK 0000001
-#define BRKINT 0000002
-#define IGNPAR 0000004
-#define PARMRK 0000010
-#define INPCK 0000020
-#define ISTRIP 0000040
-#define INLCR 0000100
-#define IGNCR 0000200
-#define ICRNL 0000400
-#define IUCLC 0001000
-#define IXON 0002000
-#define IXANY 0004000
-#define IXOFF 0010000
-#define IMAXBEL 0020000
-#define IUTF8 0040000
-
-/* c_oflag bits */
-#define OPOST 0000001
-#define OLCUC 0000002
-#define ONLCR 0000004
-#define OCRNL 0000010
-#define ONOCR 0000020
-#define ONLRET 0000040
-#define OFILL 0000100
-#define OFDEL 0000200
-#define NLDLY 0000400
-#define NL0 0000000
-#define NL1 0000400
-#define CRDLY 0003000
-#define CR0 0000000
-#define CR1 0001000
-#define CR2 0002000
-#define CR3 0003000
-#define TABDLY 0014000
-#define TAB0 0000000
-#define TAB1 0004000
-#define TAB2 0010000
-#define TAB3 0014000
-#define XTABS 0014000
-#define BSDLY 0020000
-#define BS0 0000000
-#define BS1 0020000
-#define VTDLY 0040000
-#define VT0 0000000
-#define VT1 0040000
-#define FFDLY 0100000
-#define FF0 0000000
-#define FF1 0100000
-
-/* c_cflag bit meaning */
-#define CBAUD 0010017
-#define B0 0000000 /* hang up */
-#define B50 0000001
-#define B75 0000002
-#define B110 0000003
-#define B134 0000004
-#define B150 0000005
-#define B200 0000006
-#define B300 0000007
-#define B600 0000010
-#define B1200 0000011
-#define B1800 0000012
-#define B2400 0000013
-#define B4800 0000014
-#define B9600 0000015
-#define B19200 0000016
-#define B38400 0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE 0000060
-#define CS5 0000000
-#define CS6 0000020
-#define CS7 0000040
-#define CS8 0000060
-#define CSTOPB 0000100
-#define CREAD 0000200
-#define PARENB 0000400
-#define PARODD 0001000
-#define HUPCL 0002000
-#define CLOCAL 0004000
-#define CBAUDEX 0010000
-#define BOTHER 0010000
-#define B57600 0010001
-#define B115200 0010002
-#define B230400 0010003
-#define B460800 0010004
-#define B500000 0010005
-#define B576000 0010006
-#define B921600 0010007
-#define B1000000 0010010
-#define B1152000 0010011
-#define B1500000 0010012
-#define B2000000 0010013
-#define B2500000 0010014
-#define B3000000 0010015
-#define B3500000 0010016
-#define B4000000 0010017
-#define CIBAUD 002003600000 /* input baud rate */
-#define CMSPAR 010000000000 /* mark or space (stick) parity */
-#define CRTSCTS 020000000000 /* flow control */
-
-#define IBSHIFT 16 /* shift from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-#define ISIG 0000001
-#define ICANON 0000002
-#define XCASE 0000004
-#define ECHO 0000010
-#define ECHOE 0000020
-#define ECHOK 0000040
-#define ECHONL 0000100
-#define NOFLSH 0000200
-#define TOSTOP 0000400
-#define ECHOCTL 0001000
-#define ECHOPRT 0002000
-#define ECHOKE 0004000
-#define FLUSHO 0010000
-#define PENDIN 0040000
-#define IEXTEN 0100000
-#define EXTPROC 0200000
-
-
-/* tcflow() and TCXONC use these */
-#define TCOOFF 0
-#define TCOON 1
-#define TCIOFF 2
-#define TCION 3
-
-/* tcflush() and TCFLSH use these */
-#define TCIFLUSH 0
-#define TCOFLUSH 1
-#define TCIOFLUSH 2
-
-/* tcsetattr uses these */
-#define TCSANOW 0
-#define TCSADRAIN 1
-#define TCSAFLUSH 2
-
-#endif /* __ARCH_H8300_TERMBITS_H__ */
diff --git a/arch/h8300/include/uapi/asm/termios.h b/arch/h8300/include/uapi/asm/termios.h
deleted file mode 100644
index 5a67d7e38843..000000000000
--- a/arch/h8300/include/uapi/asm/termios.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef _UAPI_H8300_TERMIOS_H
-#define _UAPI_H8300_TERMIOS_H
-
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
-
-struct winsize {
- unsigned short ws_row;
- unsigned short ws_col;
- unsigned short ws_xpixel;
- unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
- unsigned short c_iflag; /* input mode flags */
- unsigned short c_oflag; /* output mode flags */
- unsigned short c_cflag; /* control mode flags */
- unsigned short c_lflag; /* local mode flags */
- unsigned char c_line; /* line discipline */
- unsigned char c_cc[NCC]; /* control characters */
-};
-
-
-/* modem lines */
-#define TIOCM_LE 0x001
-#define TIOCM_DTR 0x002
-#define TIOCM_RTS 0x004
-#define TIOCM_ST 0x008
-#define TIOCM_SR 0x010
-#define TIOCM_CTS 0x020
-#define TIOCM_CAR 0x040
-#define TIOCM_RNG 0x080
-#define TIOCM_DSR 0x100
-#define TIOCM_CD TIOCM_CAR
-#define TIOCM_RI TIOCM_RNG
-#define TIOCM_OUT1 0x2000
-#define TIOCM_OUT2 0x4000
-#define TIOCM_LOOP 0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-
-#endif /* _UAPI_H8300_TERMIOS_H */
diff --git a/arch/h8300/include/uapi/asm/types.h b/arch/h8300/include/uapi/asm/types.h
deleted file mode 100644
index 9ec9d4c5ac4d..000000000000
--- a/arch/h8300/include/uapi/asm/types.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/int-ll64.h>
diff --git a/arch/h8300/include/uapi/asm/unistd.h b/arch/h8300/include/uapi/asm/unistd.h
deleted file mode 100644
index 8cb5d429f840..000000000000
--- a/arch/h8300/include/uapi/asm/unistd.h
+++ /dev/null
@@ -1,330 +0,0 @@
-#ifndef _UAPI_ASM_H8300_UNISTD_H_
-#define _UAPI_ASM_H8300_UNISTD_H_
-
-/*
- * This file contains the system call numbers.
- */
-
-#define __NR_restart_syscall 0
-#define __NR_exit 1
-#define __NR_fork 2
-#define __NR_read 3
-#define __NR_write 4
-#define __NR_open 5
-#define __NR_close 6
-#define __NR_waitpid 7
-#define __NR_creat 8
-#define __NR_link 9
-#define __NR_unlink 10
-#define __NR_execve 11
-#define __NR_chdir 12
-#define __NR_time 13
-#define __NR_mknod 14
-#define __NR_chmod 15
-#define __NR_lchown 16
-#define __NR_break 17
-#define __NR_oldstat 18
-#define __NR_lseek 19
-#define __NR_getpid 20
-#define __NR_mount 21
-#define __NR_umount 22
-#define __NR_setuid 23
-#define __NR_getuid 24
-#define __NR_stime 25
-#define __NR_ptrace 26
-#define __NR_alarm 27
-#define __NR_oldfstat 28
-#define __NR_pause 29
-#define __NR_utime 30
-#define __NR_stty 31
-#define __NR_gtty 32
-#define __NR_access 33
-#define __NR_nice 34
-#define __NR_ftime 35
-#define __NR_sync 36
-#define __NR_kill 37
-#define __NR_rename 38
-#define __NR_mkdir 39
-#define __NR_rmdir 40
-#define __NR_dup 41
-#define __NR_pipe 42
-#define __NR_times 43
-#define __NR_prof 44
-#define __NR_brk 45
-#define __NR_setgid 46
-#define __NR_getgid 47
-#define __NR_signal 48
-#define __NR_geteuid 49
-#define __NR_getegid 50
-#define __NR_acct 51
-#define __NR_umount2 52
-#define __NR_lock 53
-#define __NR_ioctl 54
-#define __NR_fcntl 55
-#define __NR_mpx 56
-#define __NR_setpgid 57
-#define __NR_ulimit 58
-#define __NR_oldolduname 59
-#define __NR_umask 60
-#define __NR_chroot 61
-#define __NR_ustat 62
-#define __NR_dup2 63
-#define __NR_getppid 64
-#define __NR_getpgrp 65
-#define __NR_setsid 66
-#define __NR_sigaction 67
-#define __NR_sgetmask 68
-#define __NR_ssetmask 69
-#define __NR_setreuid 70
-#define __NR_setregid 71
-#define __NR_sigsuspend 72
-#define __NR_sigpending 73
-#define __NR_sethostname 74
-#define __NR_setrlimit 75
-#define __NR_getrlimit 76
-#define __NR_getrusage 77
-#define __NR_gettimeofday 78
-#define __NR_settimeofday 79
-#define __NR_getgroups 80
-#define __NR_setgroups 81
-#define __NR_select 82
-#define __NR_symlink 83
-#define __NR_oldlstat 84
-#define __NR_readlink 85
-#define __NR_uselib 86
-#define __NR_swapon 87
-#define __NR_reboot 88
-#define __NR_readdir 89
-#define __NR_mmap 90
-#define __NR_munmap 91
-#define __NR_truncate 92
-#define __NR_ftruncate 93
-#define __NR_fchmod 94
-#define __NR_fchown 95
-#define __NR_getpriority 96
-#define __NR_setpriority 97
-#define __NR_profil 98
-#define __NR_statfs 99
-#define __NR_fstatfs 100
-#define __NR_ioperm 101
-#define __NR_socketcall 102
-#define __NR_syslog 103
-#define __NR_setitimer 104
-#define __NR_getitimer 105
-#define __NR_stat 106
-#define __NR_lstat 107
-#define __NR_fstat 108
-#define __NR_olduname 109
-#define __NR_iopl 110
-#define __NR_vhangup 111
-#define __NR_idle 112
-#define __NR_vm86old 113
-#define __NR_wait4 114
-#define __NR_swapoff 115
-#define __NR_sysinfo 116
-#define __NR_ipc 117
-#define __NR_fsync 118
-#define __NR_sigreturn 119
-#define __NR_clone 120
-#define __NR_setdomainname 121
-#define __NR_uname 122
-#define __NR_modify_ldt 123
-#define __NR_adjtimex 124
-#define __NR_mprotect 125
-#define __NR_sigprocmask 126
-#define __NR_create_module 127
-#define __NR_init_module 128
-#define __NR_delete_module 129
-#define __NR_get_kernel_syms 130
-#define __NR_quotactl 131
-#define __NR_getpgid 132
-#define __NR_fchdir 133
-#define __NR_bdflush 134
-#define __NR_sysfs 135
-#define __NR_personality 136
-#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
-#define __NR_setfsuid 138
-#define __NR_setfsgid 139
-#define __NR__llseek 140
-#define __NR_getdents 141
-#define __NR__newselect 142
-#define __NR_flock 143
-#define __NR_msync 144
-#define __NR_readv 145
-#define __NR_writev 146
-#define __NR_getsid 147
-#define __NR_fdatasync 148
-#define __NR__sysctl 149
-#define __NR_mlock 150
-#define __NR_munlock 151
-#define __NR_mlockall 152
-#define __NR_munlockall 153
-#define __NR_sched_setparam 154
-#define __NR_sched_getparam 155
-#define __NR_sched_setscheduler 156
-#define __NR_sched_getscheduler 157
-#define __NR_sched_yield 158
-#define __NR_sched_get_priority_max 159
-#define __NR_sched_get_priority_min 160
-#define __NR_sched_rr_get_interval 161
-#define __NR_nanosleep 162
-#define __NR_mremap 163
-#define __NR_setresuid 164
-#define __NR_getresuid 165
-#define __NR_vm86 166
-#define __NR_query_module 167
-#define __NR_poll 168
-#define __NR_nfsservctl 169
-#define __NR_setresgid 170
-#define __NR_getresgid 171
-#define __NR_prctl 172
-#define __NR_rt_sigreturn 173
-#define __NR_rt_sigaction 174
-#define __NR_rt_sigprocmask 175
-#define __NR_rt_sigpending 176
-#define __NR_rt_sigtimedwait 177
-#define __NR_rt_sigqueueinfo 178
-#define __NR_rt_sigsuspend 179
-#define __NR_pread64 180
-#define __NR_pwrite64 181
-#define __NR_chown 182
-#define __NR_getcwd 183
-#define __NR_capget 184
-#define __NR_capset 185
-#define __NR_sigaltstack 186
-#define __NR_sendfile 187
-#define __NR_getpmsg 188 /* some people actually want streams */
-#define __NR_putpmsg 189 /* some people actually want streams */
-#define __NR_vfork 190
-#define __NR_ugetrlimit 191
-#define __NR_mmap2 192
-#define __NR_truncate64 193
-#define __NR_ftruncate64 194
-#define __NR_stat64 195
-#define __NR_lstat64 196
-#define __NR_fstat64 197
-#define __NR_lchown32 198
-#define __NR_getuid32 199
-#define __NR_getgid32 200
-#define __NR_geteuid32 201
-#define __NR_getegid32 202
-#define __NR_setreuid32 203
-#define __NR_setregid32 204
-#define __NR_getgroups32 205
-#define __NR_setgroups32 206
-#define __NR_fchown32 207
-#define __NR_setresuid32 208
-#define __NR_getresuid32 209
-#define __NR_setresgid32 210
-#define __NR_getresgid32 211
-#define __NR_chown32 212
-#define __NR_setuid32 213
-#define __NR_setgid32 214
-#define __NR_setfsuid32 215
-#define __NR_setfsgid32 216
-#define __NR_pivot_root 217
-#define __NR_mincore 218
-#define __NR_madvise 219
-#define __NR_madvise1 219
-#define __NR_getdents64 220
-#define __NR_fcntl64 221
-/* 223 is unused */
-#define __NR_gettid 224
-#define __NR_readahead 225
-#define __NR_setxattr 226
-#define __NR_lsetxattr 227
-#define __NR_fsetxattr 228
-#define __NR_getxattr 229
-#define __NR_lgetxattr 230
-#define __NR_fgetxattr 231
-#define __NR_listxattr 232
-#define __NR_llistxattr 233
-#define __NR_flistxattr 234
-#define __NR_removexattr 235
-#define __NR_lremovexattr 236
-#define __NR_fremovexattr 237
-#define __NR_tkill 238
-#define __NR_sendfile64 239
-#define __NR_futex 240
-#define __NR_sched_setaffinity 241
-#define __NR_sched_getaffinity 242
-#define __NR_set_thread_area 243
-#define __NR_get_thread_area 244
-#define __NR_io_setup 245
-#define __NR_io_destroy 246
-#define __NR_io_getevents 247
-#define __NR_io_submit 248
-#define __NR_io_cancel 249
-#define __NR_fadvise64 250
-/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
-#define __NR_exit_group 252
-#define __NR_lookup_dcookie 253
-#define __NR_epoll_create 254
-#define __NR_epoll_ctl 255
-#define __NR_epoll_wait 256
-#define __NR_remap_file_pages 257
-#define __NR_set_tid_address 258
-#define __NR_timer_create 259
-#define __NR_timer_settime (__NR_timer_create+1)
-#define __NR_timer_gettime (__NR_timer_create+2)
-#define __NR_timer_getoverrun (__NR_timer_create+3)
-#define __NR_timer_delete (__NR_timer_create+4)
-#define __NR_clock_settime (__NR_timer_create+5)
-#define __NR_clock_gettime (__NR_timer_create+6)
-#define __NR_clock_getres (__NR_timer_create+7)
-#define __NR_clock_nanosleep (__NR_timer_create+8)
-#define __NR_statfs64 268
-#define __NR_fstatfs64 269
-#define __NR_tgkill 270
-#define __NR_utimes 271
-#define __NR_fadvise64_64 272
-#define __NR_vserver 273
-#define __NR_mbind 274
-#define __NR_get_mempolicy 275
-#define __NR_set_mempolicy 276
-#define __NR_mq_open 277
-#define __NR_mq_unlink (__NR_mq_open+1)
-#define __NR_mq_timedsend (__NR_mq_open+2)
-#define __NR_mq_timedreceive (__NR_mq_open+3)
-#define __NR_mq_notify (__NR_mq_open+4)
-#define __NR_mq_getsetattr (__NR_mq_open+5)
-#define __NR_kexec_load 283
-#define __NR_waitid 284
-/* #define __NR_sys_setaltroot 285 */
-#define __NR_add_key 286
-#define __NR_request_key 287
-#define __NR_keyctl 288
-#define __NR_ioprio_set 289
-#define __NR_ioprio_get 290
-#define __NR_inotify_init 291
-#define __NR_inotify_add_watch 292
-#define __NR_inotify_rm_watch 293
-#define __NR_migrate_pages 294
-#define __NR_openat 295
-#define __NR_mkdirat 296
-#define __NR_mknodat 297
-#define __NR_fchownat 298
-#define __NR_futimesat 299
-#define __NR_fstatat64 300
-#define __NR_unlinkat 301
-#define __NR_renameat 302
-#define __NR_linkat 303
-#define __NR_symlinkat 304
-#define __NR_readlinkat 305
-#define __NR_fchmodat 306
-#define __NR_faccessat 307
-#define __NR_pselect6 308
-#define __NR_ppoll 309
-#define __NR_unshare 310
-#define __NR_set_robust_list 311
-#define __NR_get_robust_list 312
-#define __NR_splice 313
-#define __NR_sync_file_range 314
-#define __NR_tee 315
-#define __NR_vmsplice 316
-#define __NR_move_pages 317
-#define __NR_getcpu 318
-#define __NR_epoll_pwait 319
-#define __NR_setns 320
-
-#endif /* _UAPI_ASM_H8300_UNISTD_H_ */
diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile
deleted file mode 100644
index 1cc57f872d34..000000000000
--- a/arch/h8300/kernel/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-extra-y := vmlinux.lds
-
-obj-y := process.o traps.o ptrace.o irq.o \
- sys_h8300.o time.o signal.o \
- setup.o gpio.o syscalls.o \
- entry.o timer/
-
-obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o
diff --git a/arch/h8300/kernel/asm-offsets.c b/arch/h8300/kernel/asm-offsets.c
deleted file mode 100644
index fd961e0bd741..000000000000
--- a/arch/h8300/kernel/asm-offsets.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * This program is used to generate definitions needed by
- * assembly language modules.
- *
- * We use the technique used in the OSF Mach kernel code:
- * generate asm statements containing #defines,
- * compile this file to assembler, and then extract the
- * #defines from the assembly-language output.
- */
-
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <linux/ptrace.h>
-#include <linux/hardirq.h>
-#include <linux/kbuild.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/ptrace.h>
-
-int main(void)
-{
- /* offsets into the task struct */
- DEFINE(TASK_STATE, offsetof(struct task_struct, state));
- DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
- DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
- DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
- DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
- DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
- DEFINE(TASK_MM, offsetof(struct task_struct, mm));
- DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
-
- /* offsets into the irq_cpustat_t struct */
- DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
-
- /* offsets into the thread struct */
- DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
- DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
- DEFINE(THREAD_CCR, offsetof(struct thread_struct, ccr));
-
- /* offsets into the pt_regs struct */
- DEFINE(LER0, offsetof(struct pt_regs, er0) - sizeof(long));
- DEFINE(LER1, offsetof(struct pt_regs, er1) - sizeof(long));
- DEFINE(LER2, offsetof(struct pt_regs, er2) - sizeof(long));
- DEFINE(LER3, offsetof(struct pt_regs, er3) - sizeof(long));
- DEFINE(LER4, offsetof(struct pt_regs, er4) - sizeof(long));
- DEFINE(LER5, offsetof(struct pt_regs, er5) - sizeof(long));
- DEFINE(LER6, offsetof(struct pt_regs, er6) - sizeof(long));
- DEFINE(LORIG, offsetof(struct pt_regs, orig_er0) - sizeof(long));
- DEFINE(LCCR, offsetof(struct pt_regs, ccr) - sizeof(long));
- DEFINE(LVEC, offsetof(struct pt_regs, vector) - sizeof(long));
-#if defined(__H8300S__)
- DEFINE(LEXR, offsetof(struct pt_regs, exr) - sizeof(long));
-#endif
- DEFINE(LRET, offsetof(struct pt_regs, pc) - sizeof(long));
-
- DEFINE(PT_PTRACED, PT_PTRACED);
-
- return 0;
-}
diff --git a/arch/h8300/kernel/entry.S b/arch/h8300/kernel/entry.S
deleted file mode 100644
index 94bd30f11df6..000000000000
--- a/arch/h8300/kernel/entry.S
+++ /dev/null
@@ -1,402 +0,0 @@
-/* -*- mode: asm -*-
- *
- * linux/arch/h8300/platform/h8300h/entry.S
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- * David McCullough <davidm@snapgear.com>
- *
- */
-
-/*
- * entry.S
- * include exception/interrupt gateway
- * system call entry
- */
-
-#include <linux/sys.h>
-#include <asm/unistd.h>
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/linkage.h>
-#include <asm/asm-offsets.h>
-#include <asm/thread_info.h>
-#include <asm/errno.h>
-
-#if defined(CONFIG_CPU_H8300H)
-#define USERRET 8
-INTERRUPTS = 64
- .h8300h
- .macro SHLL2 reg
- shll.l \reg
- shll.l \reg
- .endm
- .macro SHLR2 reg
- shlr.l \reg
- shlr.l \reg
- .endm
- .macro SAVEREGS
- mov.l er0,@-sp
- mov.l er1,@-sp
- mov.l er2,@-sp
- mov.l er3,@-sp
- .endm
- .macro RESTOREREGS
- mov.l @sp+,er3
- mov.l @sp+,er2
- .endm
- .macro SAVEEXR
- .endm
- .macro RESTOREEXR
- .endm
-#endif
-#if defined(CONFIG_CPU_H8S)
-#define USERRET 10
-#define USEREXR 8
-INTERRUPTS = 128
- .h8300s
- .macro SHLL2 reg
- shll.l #2,\reg
- .endm
- .macro SHLR2 reg
- shlr.l #2,\reg
- .endm
- .macro SAVEREGS
- stm.l er0-er3,@-sp
- .endm
- .macro RESTOREREGS
- ldm.l @sp+,er2-er3
- .endm
- .macro SAVEEXR
- mov.w @(USEREXR:16,er0),r1
- mov.w r1,@(LEXR-LER3:16,sp) /* copy EXR */
- .endm
- .macro RESTOREEXR
- mov.w @(LEXR-LER1:16,sp),r1 /* restore EXR */
- mov.b r1l,r1h
- mov.w r1,@(USEREXR:16,er0)
- .endm
-#endif
-
-
-/* CPU context save/restore macros. */
-
- .macro SAVE_ALL
- mov.l er0,@-sp
- stc ccr,r0l /* check kernel mode */
- btst #4,r0l
- bne 5f
-
- /* user mode */
- mov.l sp,@_sw_usp
- mov.l @sp,er0 /* restore saved er0 */
- orc #0x10,ccr /* switch kernel stack */
- mov.l @_sw_ksp,sp
- sub.l #(LRET-LORIG),sp /* allocate LORIG - LRET */
- SAVEREGS
- mov.l @_sw_usp,er0
- mov.l @(USERRET:16,er0),er1 /* copy the RET addr */
- mov.l er1,@(LRET-LER3:16,sp)
- SAVEEXR
-
- mov.l @(LORIG-LER3:16,sp),er0
- mov.l er0,@(LER0-LER3:16,sp) /* copy ER0 */
- mov.w e1,r1 /* e1 highbyte = ccr */
- and #0xef,r1h /* mask mode? flag */
- bra 6f
-5:
- /* kernel mode */
- mov.l @sp,er0 /* restore saved er0 */
- subs #2,sp /* set dummy ccr */
- SAVEREGS
- mov.w @(LRET-LER3:16,sp),r1 /* copy old ccr */
-6:
- mov.b r1h,r1l
- mov.b #0,r1h
- mov.w r1,@(LCCR-LER3:16,sp) /* set ccr */
- mov.l er6,@-sp /* syscall arg #6 */
- mov.l er5,@-sp /* syscall arg #5 */
- mov.l er4,@-sp /* syscall arg #4 */
- .endm /* r1 = ccr */
-
- .macro RESTORE_ALL
- mov.l @sp+,er4
- mov.l @sp+,er5
- mov.l @sp+,er6
- RESTOREREGS
- mov.w @(LCCR-LER1:16,sp),r0 /* check kernel mode */
- btst #4,r0l
- bne 7f
-
- orc #0x80,ccr
- mov.l @_sw_usp,er0
- mov.l @(LER0-LER1:16,sp),er1 /* restore ER0 */
- mov.l er1,@er0
- RESTOREEXR
- mov.w @(LCCR-LER1:16,sp),r1 /* restore the RET addr */
- mov.b r1l,r1h
- mov.b @(LRET+1-LER1:16,sp),r1l
- mov.w r1,e1
- mov.w @(LRET+2-LER1:16,sp),r1
- mov.l er1,@(USERRET:16,er0)
-
- mov.l @sp+,er1
- add.l #(LRET-LER1),sp /* remove LORIG - LRET */
- mov.l sp,@_sw_ksp
- andc #0xef,ccr /* switch to user mode */
- mov.l er0,sp
- bra 8f
-7:
- mov.l @sp+,er1
- adds #4,sp
- adds #2,sp
-8:
- mov.l @sp+,er0
- adds #4,sp /* remove the sw created LVEC */
- rte
- .endm
-
-.globl _system_call
-.globl _ret_from_exception
-.globl _ret_from_fork
-.globl _ret_from_kernel_thread
-.globl _ret_from_interrupt
-.globl _interrupt_redirect_table
-.globl _sw_ksp,_sw_usp
-.globl _resume
-.globl _interrupt_entry
-.globl _trace_break
-
-#if defined(CONFIG_ROMKERNEL)
- .section .int_redirect,"ax"
-_interrupt_redirect_table:
-#if defined(CONFIG_CPU_H8300H)
- .rept 7
- .long 0
- .endr
-#endif
-#if defined(CONFIG_CPU_H8S)
- .rept 5
- .long 0
- .endr
- jmp @_trace_break
- .long 0
-#endif
-
- jsr @_interrupt_entry /* NMI */
- jmp @_system_call /* TRAPA #0 (System call) */
- .long 0
- .long 0
- jmp @_trace_break /* TRAPA #3 (breakpoint) */
- .rept INTERRUPTS-12
- jsr @_interrupt_entry
- .endr
-#endif
-#if defined(CONFIG_RAMKERNEL)
-.globl _interrupt_redirect_table
- .section .bss
-_interrupt_redirect_table:
- .space 4
-#endif
-
- .section .text
- .align 2
-_interrupt_entry:
- SAVE_ALL
- mov.l sp,er0
- add.l #LVEC,er0
- btst #4,r1l
- bne 1f
- /* user LVEC */
- mov.l @_sw_usp,er0
- adds #4,er0
-1:
- mov.l @er0,er0 /* LVEC address */
-#if defined(CONFIG_ROMKERNEL)
- sub.l #_interrupt_redirect_table,er0
-#endif
-#if defined(CONFIG_RAMKERNEL)
- mov.l @_interrupt_redirect_table,er1
- sub.l er1,er0
-#endif
- SHLR2 er0
- dec.l #1,er0
- mov.l sp,er1
- subs #4,er1 /* adjust ret_pc */
- jsr @_do_IRQ
- jmp @_ret_from_interrupt
-
-_system_call:
- subs #4,sp /* dummy LVEC */
- SAVE_ALL
- andc #0x7f,ccr
- mov.l er0,er4
-
- /* save top of frame */
- mov.l sp,er0
- jsr @_set_esp0
- mov.l sp,er2
- and.w #0xe000,r2
- mov.b @((TI_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
- btst #(TIF_SYSCALL_TRACE & 7),r2l
- beq 1f
- jsr @_do_syscall_trace
-1:
- cmp.l #NR_syscalls,er4
- bcc badsys
- SHLL2 er4
- mov.l #_sys_call_table,er0
- add.l er4,er0
- mov.l @er0,er4
- beq _ret_from_exception:16
- mov.l @(LER1:16,sp),er0
- mov.l @(LER2:16,sp),er1
- mov.l @(LER3:16,sp),er2
- jsr @er4
- mov.l er0,@(LER0:16,sp) /* save the return value */
- mov.l sp,er2
- and.w #0xe000,r2
- mov.b @((TI_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
- btst #(TIF_SYSCALL_TRACE & 7),r2l
- beq 2f
- jsr @_do_syscall_trace
-2:
-#if defined(CONFIG_SYSCALL_PRINT)
- jsr @_syscall_print
-#endif
- orc #0x80,ccr
- bra resume_userspace
-
-badsys:
- mov.l #-ENOSYS,er0
- mov.l er0,@(LER0:16,sp)
- bra resume_userspace
-
-#if !defined(CONFIG_PREEMPT)
-#define resume_kernel restore_all
-#endif
-
-_ret_from_exception:
-#if defined(CONFIG_PREEMPT)
- orc #0x80,ccr
-#endif
-_ret_from_interrupt:
- mov.b @(LCCR+1:16,sp),r0l
- btst #4,r0l
- bne resume_kernel:8 /* return from kernel */
-resume_userspace:
- andc #0x7f,ccr
- mov.l sp,er4
- and.w #0xe000,r4 /* er4 <- current thread info */
- mov.l @(TI_FLAGS:16,er4),er1
- and.l #_TIF_WORK_MASK,er1
- beq restore_all:8
-work_pending:
- btst #TIF_NEED_RESCHED,r1l
- bne work_resched:8
- /* work notifysig */
- mov.l sp,er0
- subs #4,er0 /* er0: pt_regs */
- jsr @_do_notify_resume
- bra restore_all:8
-work_resched:
- mov.l sp,er0
- jsr @_set_esp0
- jsr @_schedule
- bra resume_userspace:8
-restore_all:
- RESTORE_ALL /* Does RTE */
-
-#if defined(CONFIG_PREEMPT)
-resume_kernel:
- mov.l @(TI_PRE_COUNT:16,er4),er0
- bne restore_all:8
-need_resched:
- mov.l @(TI_FLAGS:16,er4),er0
- btst #TIF_NEED_RESCHED,r0l
- beq restore_all:8
- mov.b @(LCCR+1:16,sp),r0l /* Interrupt Enabled? */
- bmi restore_all:8
- mov.l #PREEMPT_ACTIVE,er0
- mov.l er0,@(TI_PRE_COUNT:16,er4)
- andc #0x7f,ccr
- mov.l sp,er0
- jsr @_set_esp0
- jsr @_schedule
- orc #0x80,ccr
- bra need_resched:8
-#endif
-
-_ret_from_fork:
- mov.l er2,er0
- jsr @_schedule_tail
- jmp @_ret_from_exception
-
-_ret_from_kernel_thread:
- mov.l er2,er0
- jsr @_schedule_tail
- mov.l @(LER4:16,sp),er0
- mov.l @(LER5:16,sp),er1
- jsr @er1
- jmp @_ret_from_exception
-
-_resume:
- /*
- * Beware - when entering resume, offset of tss is in d1,
- * prev (the current task) is in a0, next (the new task)
- * is in a1 and d2.b is non-zero if the mm structure is
- * shared between the tasks, so don't change these
- * registers until their contents are no longer needed.
- */
-
- /* save sr */
- sub.w r3,r3
- stc ccr,r3l
- mov.w r3,@(THREAD_CCR+2:16,er0)
-
- /* disable interrupts */
- orc #0x80,ccr
- mov.l @_sw_usp,er3
- mov.l er3,@(THREAD_USP:16,er0)
- mov.l sp,@(THREAD_KSP:16,er0)
-
- /* Skip address space switching if they are the same. */
- /* FIXME: what did we hack out of here, this does nothing! */
-
- mov.l @(THREAD_USP:16,er1),er0
- mov.l er0,@_sw_usp
- mov.l @(THREAD_KSP:16,er1),sp
-
- /* restore status register */
- mov.w @(THREAD_CCR+2:16,er1),r3
-
- ldc r3l,ccr
- rts
-
-_trace_break:
- subs #4,sp
- SAVE_ALL
- sub.l er1,er1
- dec.l #1,er1
- mov.l er1,@(LORIG,sp)
- mov.l sp,er0
- jsr @_set_esp0
- mov.l @_sw_usp,er0
- mov.l @er0,er1
- mov.w @(-2:16,er1),r2
- cmp.w #0x5730,r2
- beq 1f
- subs #2,er1
- mov.l er1,@er0
-1:
- and.w #0xff,e1
- mov.l er1,er0
- jsr @_trace_trap
- jmp @_ret_from_exception
-
- .section .bss
-_sw_ksp:
- .space 4
-_sw_usp:
- .space 4
-
- .end
diff --git a/arch/h8300/kernel/gpio.c b/arch/h8300/kernel/gpio.c
deleted file mode 100644
index 084bfd0c107e..000000000000
--- a/arch/h8300/kernel/gpio.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * linux/arch/h8300/kernel/gpio.c
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- */
-
-/*
- * Internal I/O Port Management
- */
-
-#include <linux/stddef.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-
-#define _(addr) (volatile unsigned char *)(addr)
-#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
-#include <asm/regs306x.h>
-static volatile unsigned char *ddrs[] = {
- _(P1DDR),_(P2DDR),_(P3DDR),_(P4DDR),_(P5DDR),_(P6DDR),
- NULL, _(P8DDR),_(P9DDR),_(PADDR),_(PBDDR),
-};
-#define MAX_PORT 11
-#endif
-
- #if defined(CONFIG_H83002) || defined(CONFIG_H8048)
-/* Fix me!! */
-#include <asm/regs306x.h>
-static volatile unsigned char *ddrs[] = {
- _(P1DDR),_(P2DDR),_(P3DDR),_(P4DDR),_(P5DDR),_(P6DDR),
- NULL, _(P8DDR),_(P9DDR),_(PADDR),_(PBDDR),
-};
-#define MAX_PORT 11
-#endif
-
-#if defined(CONFIG_H8S2678)
-#include <asm/regs267x.h>
-static volatile unsigned char *ddrs[] = {
- _(P1DDR),_(P2DDR),_(P3DDR),NULL ,_(P5DDR),_(P6DDR),
- _(P7DDR),_(P8DDR),NULL, _(PADDR),_(PBDDR),_(PCDDR),
- _(PDDDR),_(PEDDR),_(PFDDR),_(PGDDR),_(PHDDR),
- _(PADDR),_(PBDDR),_(PCDDR),_(PDDDR),_(PEDDR),_(PFDDR),
- _(PGDDR),_(PHDDR)
-};
-#define MAX_PORT 17
-#endif
-#undef _
-
-#if !defined(P1DDR)
-#error Unsuppoted CPU Selection
-#endif
-
-static struct {
- unsigned char used;
- unsigned char ddr;
-} gpio_regs[MAX_PORT];
-
-extern char *_platform_gpio_table(int length);
-
-int h8300_reserved_gpio(int port, unsigned int bits)
-{
- unsigned char *used;
-
- if (port < 0 || port >= MAX_PORT)
- return -1;
- used = &(gpio_regs[port].used);
- if ((*used & bits) != 0)
- return 0;
- *used |= bits;
- return 1;
-}
-
-int h8300_free_gpio(int port, unsigned int bits)
-{
- unsigned char *used;
-
- if (port < 0 || port >= MAX_PORT)
- return -1;
- used = &(gpio_regs[port].used);
- if ((*used & bits) != bits)
- return 0;
- *used &= (~bits);
- return 1;
-}
-
-int h8300_set_gpio_dir(int port_bit,int dir)
-{
- int port = (port_bit >> 8) & 0xff;
- int bit = port_bit & 0xff;
-
- if (ddrs[port] == NULL)
- return 0;
- if (gpio_regs[port].used & bit) {
- if (dir)
- gpio_regs[port].ddr |= bit;
- else
- gpio_regs[port].ddr &= ~bit;
- *ddrs[port] = gpio_regs[port].ddr;
- return 1;
- } else
- return 0;
-}
-
-int h8300_get_gpio_dir(int port_bit)
-{
- int port = (port_bit >> 8) & 0xff;
- int bit = port_bit & 0xff;
-
- if (ddrs[port] == NULL)
- return 0;
- if (gpio_regs[port].used & bit) {
- return (gpio_regs[port].ddr & bit) != 0;
- } else
- return -1;
-}
-
-#if defined(CONFIG_PROC_FS)
-static char *port_status(int portno)
-{
- static char result[10];
- static const char io[2]={'I','O'};
- char *rp;
- int c;
- unsigned char used,ddr;
-
- used = gpio_regs[portno].used;
- ddr = gpio_regs[portno].ddr;
- result[8]='\0';
- rp = result + 7;
- for (c = 8; c > 0; c--,rp--,used >>= 1, ddr >>= 1)
- if (used & 0x01)
- *rp = io[ ddr & 0x01];
- else
- *rp = '-';
- return result;
-}
-
-static int gpio_proc_show(struct seq_file *m, void *v)
-{
- static const char port_name[]="123456789ABCDEFGH";
- int c;
-
- for (c = 0; c < MAX_PORT; c++) {
- if (ddrs[c] == NULL)
- continue;
- seq_printf(m, "P%c: %s\n", port_name[c], port_status(c));
- }
- return 0;
-}
-
-static int gpio_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, gpio_proc_show, PDE_DATA(inode));
-}
-
-static const struct file_operations gpio_proc_fops = {
- .open = gpio_proc_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static __init int register_proc(void)
-{
- return proc_create("gpio", S_IRUGO, NULL, &gpio_proc_fops) != NULL;
-}
-
-__initcall(register_proc);
-#endif
-
-void __init h8300_gpio_init(void)
-{
- memcpy(gpio_regs,_platform_gpio_table(sizeof(gpio_regs)),sizeof(gpio_regs));
-}
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
deleted file mode 100644
index 53d7c0e4bd83..000000000000
--- a/arch/h8300/kernel/h8300_ksyms.c
+++ /dev/null
@@ -1,100 +0,0 @@
-#include <linux/module.h>
-#include <linux/linkage.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-#include <linux/in6.h>
-#include <linux/interrupt.h>
-
-#include <asm/setup.h>
-#include <asm/pgalloc.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/checksum.h>
-#include <asm/current.h>
-#include <asm/gpio.h>
-
-//asmlinkage long long __ashrdi3 (long long, int);
-//asmlinkage long long __lshrdi3 (long long, int);
-extern char h8300_debug_device[];
-
-/* platform dependent support */
-
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strncmp);
-
-EXPORT_SYMBOL(ip_fast_csum);
-
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
-
-/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy_nocheck);
-
-/* The following are special because they're not called
- explicitly (the C compiler generates them). Fortunately,
- their interface isn't gonna change any time soon now, so
- it's OK to leave it out of version control. */
-//EXPORT_SYMBOL(__ashrdi3);
-//EXPORT_SYMBOL(__lshrdi3);
-EXPORT_SYMBOL(memcpy);
-EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
-EXPORT_SYMBOL(memmove);
-
-/*
- * libgcc functions - functions that are used internally by the
- * compiler... (prototypes are not correct though, but that
- * doesn't really matter since they're not versioned).
- */
-extern void __gcc_bcmp(void);
-extern void __ashldi3(void);
-extern void __ashrdi3(void);
-extern void __cmpdi2(void);
-extern void __divdi3(void);
-extern void __divsi3(void);
-extern void __lshrdi3(void);
-extern void __moddi3(void);
-extern void __modsi3(void);
-extern void __muldi3(void);
-extern void __mulsi3(void);
-extern void __negdi2(void);
-extern void __ucmpdi2(void);
-extern void __udivdi3(void);
-extern void __udivmoddi4(void);
-extern void __udivsi3(void);
-extern void __umoddi3(void);
-extern void __umodsi3(void);
-
- /* gcc lib functions */
-EXPORT_SYMBOL(__gcc_bcmp);
-EXPORT_SYMBOL(__ashldi3);
-EXPORT_SYMBOL(__ashrdi3);
-EXPORT_SYMBOL(__cmpdi2);
-EXPORT_SYMBOL(__divdi3);
-EXPORT_SYMBOL(__divsi3);
-EXPORT_SYMBOL(__lshrdi3);
-EXPORT_SYMBOL(__moddi3);
-EXPORT_SYMBOL(__modsi3);
-EXPORT_SYMBOL(__muldi3);
-EXPORT_SYMBOL(__mulsi3);
-EXPORT_SYMBOL(__negdi2);
-EXPORT_SYMBOL(__ucmpdi2);
-EXPORT_SYMBOL(__udivdi3);
-EXPORT_SYMBOL(__udivmoddi4);
-EXPORT_SYMBOL(__udivsi3);
-EXPORT_SYMBOL(__umoddi3);
-EXPORT_SYMBOL(__umodsi3);
-
-EXPORT_SYMBOL(h8300_reserved_gpio);
-EXPORT_SYMBOL(h8300_free_gpio);
-EXPORT_SYMBOL(h8300_set_gpio_dir);
diff --git a/arch/h8300/kernel/irq.c b/arch/h8300/kernel/irq.c
deleted file mode 100644
index 2fa8ac7b79b5..000000000000
--- a/arch/h8300/kernel/irq.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * linux/arch/h8300/kernel/irq.c
- *
- * Copyright 2007 Yoshinori Sato <ysato@users.sourceforge.jp>
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <linux/seq_file.h>
-#include <linux/init.h>
-#include <linux/random.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-
-#include <asm/traps.h>
-#include <asm/io.h>
-#include <asm/setup.h>
-#include <asm/errno.h>
-
-/*#define DEBUG*/
-
-extern unsigned long *interrupt_redirect_table;
-extern const int h8300_saved_vectors[];
-extern const h8300_vector h8300_trap_table[];
-int h8300_enable_irq_pin(unsigned int irq);
-void h8300_disable_irq_pin(unsigned int irq);
-
-#define CPU_VECTOR ((unsigned long *)0x000000)
-#define ADDR_MASK (0xffffff)
-
-static inline int is_ext_irq(unsigned int irq)
-{
- return (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS));
-}
-
-static void h8300_enable_irq(struct irq_data *data)
-{
- if (is_ext_irq(data->irq))
- IER_REGS |= 1 << (data->irq - EXT_IRQ0);
-}
-
-static void h8300_disable_irq(struct irq_data *data)
-{
- if (is_ext_irq(data->irq))
- IER_REGS &= ~(1 << (data->irq - EXT_IRQ0));
-}
-
-static unsigned int h8300_startup_irq(struct irq_data *data)
-{
- if (is_ext_irq(data->irq))
- return h8300_enable_irq_pin(data->irq);
- else
- return 0;
-}
-
-static void h8300_shutdown_irq(struct irq_data *data)
-{
- if (is_ext_irq(data->irq))
- h8300_disable_irq_pin(data->irq);
-}
-
-/*
- * h8300 interrupt controller implementation
- */
-struct irq_chip h8300irq_chip = {
- .name = "H8300-INTC",
- .irq_startup = h8300_startup_irq,
- .irq_shutdown = h8300_shutdown_irq,
- .irq_enable = h8300_enable_irq,
- .irq_disable = h8300_disable_irq,
-};
-
-#if defined(CONFIG_RAMKERNEL)
-static unsigned long __init *get_vector_address(void)
-{
- unsigned long *rom_vector = CPU_VECTOR;
- unsigned long base,tmp;
- int vec_no;
-
- base = rom_vector[EXT_IRQ0] & ADDR_MASK;
-
- /* check romvector format */
- for (vec_no = EXT_IRQ1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) {
- if ((base+(vec_no - EXT_IRQ0)*4) != (rom_vector[vec_no] & ADDR_MASK))
- return NULL;
- }
-
- /* ramvector base address */
- base -= EXT_IRQ0*4;
-
- /* writerble check */
- tmp = ~(*(volatile unsigned long *)base);
- (*(volatile unsigned long *)base) = tmp;
- if ((*(volatile unsigned long *)base) != tmp)
- return NULL;
- return (unsigned long *)base;
-}
-
-static void __init setup_vector(void)
-{
- int i;
- unsigned long *ramvec,*ramvec_p;
- const h8300_vector *trap_entry;
- const int *saved_vector;
-
- ramvec = get_vector_address();
- if (ramvec == NULL)
- panic("interrupt vector serup failed.");
- else
- printk(KERN_INFO "virtual vector at 0x%08lx\n",(unsigned long)ramvec);
-
- /* create redirect table */
- ramvec_p = ramvec;
- trap_entry = h8300_trap_table;
- saved_vector = h8300_saved_vectors;
- for ( i = 0; i < NR_IRQS; i++) {
- if (i == *saved_vector) {
- ramvec_p++;
- saved_vector++;
- } else {
- if ( i < NR_TRAPS ) {
- if (*trap_entry)
- *ramvec_p = VECTOR(*trap_entry);
- ramvec_p++;
- trap_entry++;
- } else
- *ramvec_p++ = REDIRECT(interrupt_entry);
- }
- }
- interrupt_redirect_table = ramvec;
-#ifdef DEBUG
- ramvec_p = ramvec;
- for (i = 0; i < NR_IRQS; i++) {
- if ((i % 8) == 0)
- printk(KERN_DEBUG "\n%p: ",ramvec_p);
- printk(KERN_DEBUG "%p ",*ramvec_p);
- ramvec_p++;
- }
- printk(KERN_DEBUG "\n");
-#endif
-}
-#else
-#define setup_vector() do { } while(0)
-#endif
-
-void __init init_IRQ(void)
-{
- int c;
-
- setup_vector();
-
- for (c = 0; c < NR_IRQS; c++)
- irq_set_chip_and_handler(c, &h8300irq_chip, handle_simple_irq);
-}
-
-asmlinkage void do_IRQ(int irq)
-{
- irq_enter();
- generic_handle_irq(irq);
- irq_exit();
-}
diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c
deleted file mode 100644
index 1d526e05db19..000000000000
--- a/arch/h8300/kernel/module.c
+++ /dev/null
@@ -1,75 +0,0 @@
-#include <linux/moduleloader.h>
-#include <linux/elf.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(fmt...)
-#endif
-
-int apply_relocate_add(Elf32_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- unsigned int i;
- Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
-
- DEBUGP("Applying relocate section %u to %u\n", relsec,
- sechdrs[relsec].sh_info);
- for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
- /* This is where to make the change */
- uint32_t *loc = (uint32_t *)(sechdrs[sechdrs[relsec].sh_info].sh_addr
- + rela[i].r_offset);
- /* This is the symbol it is referring to. Note that all
- undefined symbols have been resolved. */
- Elf32_Sym *sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
- + ELF32_R_SYM(rela[i].r_info);
- uint32_t v = sym->st_value + rela[i].r_addend;
-
- switch (ELF32_R_TYPE(rela[i].r_info)) {
- case R_H8_DIR24R8:
- loc = (uint32_t *)((uint32_t)loc - 1);
- *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
- break;
- case R_H8_DIR24A8:
- if (ELF32_R_SYM(rela[i].r_info))
- *loc += v;
- break;
- case R_H8_DIR32:
- case R_H8_DIR32A16:
- *loc += v;
- break;
- case R_H8_PCREL16:
- v -= (unsigned long)loc + 2;
- if ((Elf32_Sword)v > 0x7fff ||
- (Elf32_Sword)v < -(Elf32_Sword)0x8000)
- goto overflow;
- else
- *(unsigned short *)loc = v;
- break;
- case R_H8_PCREL8:
- v -= (unsigned long)loc + 1;
- if ((Elf32_Sword)v > 0x7f ||
- (Elf32_Sword)v < -(Elf32_Sword)0x80)
- goto overflow;
- else
- *(unsigned char *)loc = v;
- break;
- default:
- printk(KERN_ERR "module %s: Unknown relocation: %u\n",
- me->name, ELF32_R_TYPE(rela[i].r_info));
- return -ENOEXEC;
- }
- }
- return 0;
- overflow:
- printk(KERN_ERR "module %s: relocation offset overflow: %08x\n",
- me->name, rela[i].r_offset);
- return -ENOEXEC;
-}
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c
deleted file mode 100644
index 1a744ab7e7e5..000000000000
--- a/arch/h8300/kernel/process.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * linux/arch/h8300/kernel/process.c
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * Based on:
- *
- * linux/arch/m68knommu/kernel/process.c
- *
- * Copyright (C) 1998 D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>,
- * Kenneth Albanowski <kjahds@kjahds.com>,
- * The Silver Hammer Group, Ltd.
- *
- * linux/arch/m68k/kernel/process.c
- *
- * Copyright (C) 1995 Hamish Macdonald
- *
- * 68060 fixes by Jesper Skov
- */
-
-/*
- * This file handles the architecture-dependent parts of process handling..
- */
-
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/user.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/rcupdate.h>
-
-#include <asm/uaccess.h>
-#include <asm/traps.h>
-#include <asm/setup.h>
-#include <asm/pgtable.h>
-
-void (*pm_power_off)(void) = NULL;
-EXPORT_SYMBOL(pm_power_off);
-
-asmlinkage void ret_from_fork(void);
-asmlinkage void ret_from_kernel_thread(void);
-
-/*
- * The idle loop on an H8/300..
- */
-#if !defined(CONFIG_H8300H_SIM) && !defined(CONFIG_H8S_SIM)
-void arch_cpu_idle(void)
-{
- local_irq_enable();
- /* XXX: race here! What if need_resched() gets set now? */
- __asm__("sleep");
-}
-#endif
-
-void machine_restart(char * __unused)
-{
- local_irq_disable();
- __asm__("jmp @@0");
-}
-
-void machine_halt(void)
-{
- local_irq_disable();
- __asm__("sleep");
- for (;;);
-}
-
-void machine_power_off(void)
-{
- local_irq_disable();
- __asm__("sleep");
- for (;;);
-}
-
-void show_regs(struct pt_regs * regs)
-{
- show_regs_print_info(KERN_DEFAULT);
-
- printk("\nPC: %08lx Status: %02x",
- regs->pc, regs->ccr);
- printk("\nORIG_ER0: %08lx ER0: %08lx ER1: %08lx",
- regs->orig_er0, regs->er0, regs->er1);
- printk("\nER2: %08lx ER3: %08lx ER4: %08lx ER5: %08lx",
- regs->er2, regs->er3, regs->er4, regs->er5);
- printk("\nER6' %08lx ",regs->er6);
- if (user_mode(regs))
- printk("USP: %08lx\n", rdusp());
- else
- printk("\n");
-}
-
-void flush_thread(void)
-{
-}
-
-int copy_thread(unsigned long clone_flags,
- unsigned long usp, unsigned long topstk,
- struct task_struct * p)
-{
- struct pt_regs * childregs;
-
- childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1;
-
- if (unlikely(p->flags & PF_KTHREAD)) {
- memset(childregs, 0, sizeof(struct pt_regs));
- childregs->retpc = (unsigned long) ret_from_kernel_thread;
- childregs->er4 = topstk; /* arg */
- childregs->er5 = usp; /* fn */
- p->thread.ksp = (unsigned long)childregs;
- }
- *childregs = *current_pt_regs();
- childregs->retpc = (unsigned long) ret_from_fork;
- childregs->er0 = 0;
- p->thread.usp = usp ?: rdusp();
- p->thread.ksp = (unsigned long)childregs;
-
- return 0;
-}
-
-unsigned long thread_saved_pc(struct task_struct *tsk)
-{
- return ((struct pt_regs *)tsk->thread.esp0)->pc;
-}
-
-unsigned long get_wchan(struct task_struct *p)
-{
- unsigned long fp, pc;
- unsigned long stack_page;
- int count = 0;
- if (!p || p == current || p->state == TASK_RUNNING)
- return 0;
-
- stack_page = (unsigned long)p;
- fp = ((struct pt_regs *)p->thread.ksp)->er6;
- do {
- if (fp < stack_page+sizeof(struct thread_info) ||
- fp >= 8184+stack_page)
- return 0;
- pc = ((unsigned long *)fp)[1];
- if (!in_sched_functions(pc))
- return pc;
- fp = *(unsigned long *) fp;
- } while (count++ < 16);
- return 0;
-}
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c
deleted file mode 100644
index 748cf6585aa4..000000000000
--- a/arch/h8300/kernel/ptrace.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * linux/arch/h8300/kernel/ptrace.c
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * Based on:
- * linux/arch/m68k/kernel/ptrace.c
- *
- * Copyright (C) 1994 by Hamish Macdonald
- * Taken from linux/kernel/ptrace.c and modified for M680x0.
- * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
- *
- * 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/errno.h>
-#include <linux/ptrace.h>
-#include <linux/user.h>
-#include <linux/signal.h>
-
-#include <asm/uaccess.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/signal.h>
-
-/* cpu depend functions */
-extern long h8300_get_reg(struct task_struct *task, int regno);
-extern int h8300_put_reg(struct task_struct *task, int regno, unsigned long data);
-
-
-void user_disable_single_step(struct task_struct *child)
-{
-}
-
-/*
- * does not yet catch signals sent when the child dies.
- * in exit.c or in signal.c.
- */
-
-void ptrace_disable(struct task_struct *child)
-{
- user_disable_single_step(child);
-}
-
-long arch_ptrace(struct task_struct *child, long request,
- unsigned long addr, unsigned long data)
-{
- int ret;
- int regno = addr >> 2;
- unsigned long __user *datap = (unsigned long __user *) data;
-
- switch (request) {
- /* read the word at location addr in the USER area. */
- case PTRACE_PEEKUSR: {
- unsigned long tmp = 0;
-
- if ((addr & 3) || addr >= sizeof(struct user)) {
- ret = -EIO;
- break ;
- }
-
- ret = 0; /* Default return condition */
-
- if (regno < H8300_REGS_NO)
- tmp = h8300_get_reg(child, regno);
- else {
- switch (regno) {
- case 49:
- tmp = child->mm->start_code;
- break ;
- case 50:
- tmp = child->mm->start_data;
- break ;
- case 51:
- tmp = child->mm->end_code;
- break ;
- case 52:
- tmp = child->mm->end_data;
- break ;
- default:
- ret = -EIO;
- }
- }
- if (!ret)
- ret = put_user(tmp, datap);
- break ;
- }
-
- /* when I and D space are separate, this will have to be fixed. */
- case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
- if ((addr & 3) || addr >= sizeof(struct user)) {
- ret = -EIO;
- break ;
- }
-
- if (regno == PT_ORIG_ER0) {
- ret = -EIO;
- break ;
- }
- if (regno < H8300_REGS_NO) {
- ret = h8300_put_reg(child, regno, data);
- break ;
- }
- ret = -EIO;
- break ;
-
- case PTRACE_GETREGS: { /* Get all gp regs from the child. */
- int i;
- unsigned long tmp;
- for (i = 0; i < H8300_REGS_NO; i++) {
- tmp = h8300_get_reg(child, i);
- if (put_user(tmp, datap)) {
- ret = -EFAULT;
- break;
- }
- datap++;
- }
- ret = 0;
- break;
- }
-
- case PTRACE_SETREGS: { /* Set all gp regs in the child. */
- int i;
- unsigned long tmp;
- for (i = 0; i < H8300_REGS_NO; i++) {
- if (get_user(tmp, datap)) {
- ret = -EFAULT;
- break;
- }
- h8300_put_reg(child, i, tmp);
- datap++;
- }
- ret = 0;
- break;
- }
-
- default:
- ret = ptrace_request(child, request, addr, data);
- break;
- }
- return ret;
-}
-
-asmlinkage void do_syscall_trace(void)
-{
- if (!test_thread_flag(TIF_SYSCALL_TRACE))
- return;
- if (!(current->ptrace & PT_PTRACED))
- return;
- ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
- ? 0x80 : 0));
- /*
- * this isn't the same as continuing with a signal, but it will do
- * for normal use. strace only continues with a signal if the
- * stopping signal is not SIGTRAP. -brl
- */
- if (current->exit_code) {
- send_sig(current->exit_code, current, 1);
- current->exit_code = 0;
- }
-}
diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c
deleted file mode 100644
index d0b1607f2711..000000000000
--- a/arch/h8300/kernel/setup.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * linux/arch/h8300/kernel/setup.c
- *
- * Copyleft ()) 2000 James D. Schettine {james@telos-systems.com}
- * Copyright (C) 1999,2000 Greg Ungerer (gerg@snapgear.com)
- * Copyright (C) 1998,1999 D. Jeff Dionne <jeff@lineo.ca>
- * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
- * Copyright (C) 1995 Hamish Macdonald
- * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
- * Copyright (C) 2001 Lineo, Inc. <www.lineo.com>
- *
- * H8/300 porting Yoshinori Sato <ysato@users.sourceforge.jp>
- */
-
-/*
- * This file handles the architecture-dependent parts of system setup
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/genhd.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/major.h>
-#include <linux/bootmem.h>
-#include <linux/seq_file.h>
-#include <linux/init.h>
-
-#include <asm/setup.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/sections.h>
-
-#if defined(__H8300H__)
-#define CPU "H8/300H"
-#include <asm/regs306x.h>
-#endif
-
-#if defined(__H8300S__)
-#define CPU "H8S"
-#include <asm/regs267x.h>
-#endif
-
-#define STUBSIZE 0xc000
-
-unsigned long rom_length;
-unsigned long memory_start;
-unsigned long memory_end;
-
-char __initdata command_line[COMMAND_LINE_SIZE];
-
-extern int _ramstart, _ramend;
-extern char _target_name[];
-extern void h8300_gpio_init(void);
-
-#if (defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)) \
- && defined(CONFIG_GDB_MAGICPRINT)
-/* printk with gdb service */
-static void gdb_console_output(struct console *c, const char *msg, unsigned len)
-{
- for (; len > 0; len--) {
- asm("mov.w %0,r2\n\t"
- "jsr @0xc4"::"r"(*msg++):"er2");
- }
-}
-
-/*
- * Setup initial baud/bits/parity. We do two things here:
- * - construct a cflag setting for the first rs_open()
- * - initialize the serial port
- * Return non-zero if we didn't find a serial port.
- */
-static int __init gdb_console_setup(struct console *co, char *options)
-{
- return 0;
-}
-
-static const struct console gdb_console = {
- .name = "gdb_con",
- .write = gdb_console_output,
- .device = NULL,
- .setup = gdb_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-#endif
-
-void __init setup_arch(char **cmdline_p)
-{
- int bootmap_size;
-
- memory_start = (unsigned long) &_ramstart;
-
- /* allow for ROMFS on the end of the kernel */
- if (memcmp((void *)memory_start, "-rom1fs-", 8) == 0) {
-#if defined(CONFIG_BLK_DEV_INITRD)
- initrd_start = memory_start;
- initrd_end = memory_start += be32_to_cpu(((unsigned long *) (memory_start))[2]);
-#else
- memory_start += be32_to_cpu(((unsigned long *) memory_start)[2]);
-#endif
- }
- memory_start = PAGE_ALIGN(memory_start);
-#if !defined(CONFIG_BLKDEV_RESERVE)
- memory_end = (unsigned long) &_ramend; /* by now the stack is part of the init task */
-#if defined(CONFIG_GDB_DEBUG)
- memory_end -= STUBSIZE;
-#endif
-#else
- if ((memory_end < CONFIG_BLKDEV_RESERVE_ADDRESS) &&
- (memory_end > CONFIG_BLKDEV_RESERVE_ADDRESS))
- /* overlap userarea */
- memory_end = CONFIG_BLKDEV_RESERVE_ADDRESS;
-#endif
-
- init_mm.start_code = (unsigned long) _stext;
- init_mm.end_code = (unsigned long) _etext;
- init_mm.end_data = (unsigned long) _edata;
- init_mm.brk = (unsigned long) 0;
-
-#if (defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)) && defined(CONFIG_GDB_MAGICPRINT)
- register_console((struct console *)&gdb_console);
-#endif
-
- printk(KERN_INFO "\r\n\nuClinux " CPU "\n");
- printk(KERN_INFO "Target Hardware: %s\n",_target_name);
- printk(KERN_INFO "Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n");
- printk(KERN_INFO "H8/300 series support by Yoshinori Sato <ysato@users.sourceforge.jp>\n");
-
-#ifdef DEBUG
- printk(KERN_DEBUG "KERNEL -> TEXT=0x%p-0x%p DATA=0x%p-0x%p "
- "BSS=0x%p-0x%p\n", _stext, _etext, _sdata, _edata, __bss_start,
- __bss_stop);
- printk(KERN_DEBUG "KERNEL -> ROMFS=0x%p-0x%06lx MEM=0x%06lx-0x%06lx "
- "STACK=0x%06lx-0x%p\n", __bss_stop, memory_start, memory_start,
- memory_end, memory_end, &_ramend);
-#endif
-
-#ifdef CONFIG_DEFAULT_CMDLINE
- /* set from default command line */
- if (*command_line == '\0')
- strcpy(command_line,CONFIG_KERNEL_COMMAND);
-#endif
- /* Keep a copy of command line */
- *cmdline_p = &command_line[0];
- memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
- boot_command_line[COMMAND_LINE_SIZE-1] = 0;
-
-#ifdef DEBUG
- if (strlen(*cmdline_p))
- printk(KERN_DEBUG "Command line: '%s'\n", *cmdline_p);
-#endif
-
- /*
- * give all the memory to the bootmap allocator, tell it to put the
- * boot mem_map at the start of memory
- */
- bootmap_size = init_bootmem_node(
- NODE_DATA(0),
- memory_start >> PAGE_SHIFT, /* map goes here */
- PAGE_OFFSET >> PAGE_SHIFT, /* 0 on coldfire */
- memory_end >> PAGE_SHIFT);
- /*
- * free the usable memory, we have to make sure we do not free
- * the bootmem bitmap so we then reserve it after freeing it :-)
- */
- free_bootmem(memory_start, memory_end - memory_start);
- reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT);
- /*
- * get kmalloc into gear
- */
- paging_init();
- h8300_gpio_init();
-#if defined(CONFIG_H8300_AKI3068NET) && defined(CONFIG_IDE)
- {
-#define AREABIT(addr) (1 << (((addr) >> 21) & 7))
- /* setup BSC */
- volatile unsigned char *abwcr = (volatile unsigned char *)ABWCR;
- volatile unsigned char *cscr = (volatile unsigned char *)CSCR;
- *abwcr &= ~(AREABIT(CONFIG_H8300_IDE_BASE) | AREABIT(CONFIG_H8300_IDE_ALT));
- *cscr |= (AREABIT(CONFIG_H8300_IDE_BASE) | AREABIT(CONFIG_H8300_IDE_ALT)) | 0x0f;
- }
-#endif
-#ifdef DEBUG
- printk(KERN_DEBUG "Done setup_arch\n");
-#endif
-}
-
-/*
- * Get CPU information for use by the procfs.
- */
-
-static int show_cpuinfo(struct seq_file *m, void *v)
-{
- char *cpu;
- int mode;
- u_long clockfreq;
-
- cpu = CPU;
- mode = *(volatile unsigned char *)MDCR & 0x07;
-
- clockfreq = CONFIG_CPU_CLOCK;
-
- seq_printf(m, "CPU:\t\t%s (mode:%d)\n"
- "Clock:\t\t%lu.%1luMHz\n"
- "BogoMips:\t%lu.%02lu\n"
- "Calibration:\t%lu loops\n",
- cpu,mode,
- clockfreq/1000,clockfreq%1000,
- (loops_per_jiffy*HZ)/500000,((loops_per_jiffy*HZ)/5000)%100,
- (loops_per_jiffy*HZ));
-
- return 0;
-}
-
-static void *c_start(struct seq_file *m, loff_t *pos)
-{
- return *pos < NR_CPUS ? ((void *) 0x12345678) : NULL;
-}
-
-static void *c_next(struct seq_file *m, void *v, loff_t *pos)
-{
- ++*pos;
- return c_start(m, pos);
-}
-
-static void c_stop(struct seq_file *m, void *v)
-{
-}
-
-const struct seq_operations cpuinfo_op = {
- .start = c_start,
- .next = c_next,
- .stop = c_stop,
- .show = show_cpuinfo,
-};
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
deleted file mode 100644
index a65ff3b76326..000000000000
--- a/arch/h8300/kernel/signal.c
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * linux/arch/h8300/kernel/signal.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * 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.
- */
-
-/*
- * uClinux H8/300 support by Yoshinori Sato <ysato@users.sourceforge.jp>
- * and David McCullough <davidm@snapgear.com>
- *
- * Based on
- * Linux/m68k by Hamish Macdonald
- */
-
-/*
- * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
- * Atari :-) Current limitation: Only one sigstack can be active at one time.
- * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
- * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
- * signal handlers!
- */
-
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/syscalls.h>
-#include <linux/errno.h>
-#include <linux/wait.h>
-#include <linux/ptrace.h>
-#include <linux/unistd.h>
-#include <linux/stddef.h>
-#include <linux/highuid.h>
-#include <linux/personality.h>
-#include <linux/tty.h>
-#include <linux/binfmts.h>
-#include <linux/tracehook.h>
-
-#include <asm/setup.h>
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/traps.h>
-#include <asm/ucontext.h>
-
-/*
- * Do a signal return; undo the signal stack.
- *
- * Keep the return code on the stack quadword aligned!
- * That makes the cache flush below easier.
- */
-
-struct sigframe
-{
- long dummy_er0;
- long dummy_vector;
-#if defined(CONFIG_CPU_H8S)
- short dummy_exr;
-#endif
- long dummy_pc;
- char *pretcode;
- unsigned char retcode[8];
- unsigned long extramask[_NSIG_WORDS-1];
- struct sigcontext sc;
- int sig;
-} __attribute__((aligned(2),packed));
-
-struct rt_sigframe
-{
- long dummy_er0;
- long dummy_vector;
-#if defined(CONFIG_CPU_H8S)
- short dummy_exr;
-#endif
- long dummy_pc;
- char *pretcode;
- struct siginfo *pinfo;
- void *puc;
- unsigned char retcode[8];
- struct siginfo info;
- struct ucontext uc;
- int sig;
-} __attribute__((aligned(2),packed));
-
-static inline int
-restore_sigcontext(struct sigcontext *usc, int *pd0)
-{
- struct pt_regs *regs = current_pt_regs();
- int err = 0;
- unsigned int ccr;
- unsigned int usp;
- unsigned int er0;
-
- /* Always make any pending restarted system calls return -EINTR */
- current_thread_info()->restart_block.fn = do_no_restart_syscall;
-
-#define COPY(r) err |= __get_user(regs->r, &usc->sc_##r) /* restore passed registers */
- COPY(er1);
- COPY(er2);
- COPY(er3);
- COPY(er5);
- COPY(pc);
- ccr = regs->ccr & 0x10;
- COPY(ccr);
-#undef COPY
- regs->ccr &= 0xef;
- regs->ccr |= ccr;
- regs->orig_er0 = -1; /* disable syscall checks */
- err |= __get_user(usp, &usc->sc_usp);
- wrusp(usp);
-
- err |= __get_user(er0, &usc->sc_er0);
- *pd0 = er0;
- return err;
-}
-
-asmlinkage int sys_sigreturn(void)
-{
- unsigned long usp = rdusp();
- struct sigframe *frame = (struct sigframe *)(usp - 4);
- sigset_t set;
- int er0;
-
- if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
- goto badframe;
- if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
- (_NSIG_WORDS > 1 &&
- __copy_from_user(&set.sig[1], &frame->extramask,
- sizeof(frame->extramask))))
- goto badframe;
-
- set_current_blocked(&set);
-
- if (restore_sigcontext(&frame->sc, &er0))
- goto badframe;
- return er0;
-
-badframe:
- force_sig(SIGSEGV, current);
- return 0;
-}
-
-asmlinkage int sys_rt_sigreturn(void)
-{
- unsigned long usp = rdusp();
- struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4);
- sigset_t set;
- int er0;
-
- if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
- goto badframe;
- if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
- goto badframe;
-
- set_current_blocked(&set);
-
- if (restore_sigcontext(&frame->uc.uc_mcontext, &er0))
- goto badframe;
-
- if (restore_altstack(&frame->uc.uc_stack))
- goto badframe;
-
- return er0;
-
-badframe:
- force_sig(SIGSEGV, current);
- return 0;
-}
-
-static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
- unsigned long mask)
-{
- int err = 0;
-
- err |= __put_user(regs->er0, &sc->sc_er0);
- err |= __put_user(regs->er1, &sc->sc_er1);
- err |= __put_user(regs->er2, &sc->sc_er2);
- err |= __put_user(regs->er3, &sc->sc_er3);
- err |= __put_user(regs->er4, &sc->sc_er4);
- err |= __put_user(regs->er5, &sc->sc_er5);
- err |= __put_user(regs->er6, &sc->sc_er6);
- err |= __put_user(rdusp(), &sc->sc_usp);
- err |= __put_user(regs->pc, &sc->sc_pc);
- err |= __put_user(regs->ccr, &sc->sc_ccr);
- err |= __put_user(mask, &sc->sc_mask);
-
- return err;
-}
-
-static inline void *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
-{
- unsigned long usp;
-
- /* Default to using normal stack. */
- usp = rdusp();
-
- /* This is the X/Open sanctioned signal stack switching. */
- if (ka->sa.sa_flags & SA_ONSTACK) {
- if (!sas_ss_flags(usp))
- usp = current->sas_ss_sp + current->sas_ss_size;
- }
- return (void *)((usp - frame_size) & -8UL);
-}
-
-static int setup_frame (int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs *regs)
-{
- struct sigframe *frame;
- int err = 0;
- int usig;
- unsigned char *ret;
-
- frame = get_sigframe(ka, regs, sizeof(*frame));
-
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
-
- usig = current_thread_info()->exec_domain
- && current_thread_info()->exec_domain->signal_invmap
- && sig < 32
- ? current_thread_info()->exec_domain->signal_invmap[sig]
- : sig;
-
- err |= __put_user(usig, &frame->sig);
- if (err)
- goto give_sigsegv;
-
- err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
- if (err)
- goto give_sigsegv;
-
- if (_NSIG_WORDS > 1) {
- err |= copy_to_user(frame->extramask, &set->sig[1],
- sizeof(frame->extramask));
- if (err)
- goto give_sigsegv;
- }
-
- ret = frame->retcode;
- if (ka->sa.sa_flags & SA_RESTORER)
- ret = (unsigned char *)(ka->sa.sa_restorer);
- else {
- /* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */
- err |= __put_user(0x1a80f800 + (__NR_sigreturn & 0xff),
- (unsigned long *)(frame->retcode + 0));
- err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4));
- }
-
- /* Set up to return from userspace. */
- err |= __put_user(ret, &frame->pretcode);
-
- if (err)
- goto give_sigsegv;
-
- /* Set up registers for signal handler */
- wrusp ((unsigned long) frame);
- regs->pc = (unsigned long) ka->sa.sa_handler;
- regs->er0 = (current_thread_info()->exec_domain
- && current_thread_info()->exec_domain->signal_invmap
- && sig < 32
- ? current_thread_info()->exec_domain->signal_invmap[sig]
- : sig);
- regs->er1 = (unsigned long)&(frame->sc);
- regs->er5 = current->mm->start_data; /* GOT base */
-
- return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
-}
-
-static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
-{
- struct rt_sigframe *frame;
- int err = 0;
- int usig;
- unsigned char *ret;
-
- frame = get_sigframe(ka, regs, sizeof(*frame));
-
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
-
- usig = current_thread_info()->exec_domain
- && current_thread_info()->exec_domain->signal_invmap
- && sig < 32
- ? current_thread_info()->exec_domain->signal_invmap[sig]
- : sig;
-
- err |= __put_user(usig, &frame->sig);
- if (err)
- goto give_sigsegv;
-
- err |= __put_user(&frame->info, &frame->pinfo);
- err |= __put_user(&frame->uc, &frame->puc);
- err |= copy_siginfo_to_user(&frame->info, info);
- if (err)
- goto give_sigsegv;
-
- /* Create the ucontext. */
- err |= __put_user(0, &frame->uc.uc_flags);
- err |= __put_user(0, &frame->uc.uc_link);
- err |= __save_altstack(&frame->uc.uc_stack, rdusp());
- err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
- err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
- if (err)
- goto give_sigsegv;
-
- /* Set up to return from userspace. */
- ret = frame->retcode;
- if (ka->sa.sa_flags & SA_RESTORER)
- ret = (unsigned char *)(ka->sa.sa_restorer);
- else {
- /* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */
- err |= __put_user(0x1a80f800 + (__NR_sigreturn & 0xff),
- (unsigned long *)(frame->retcode + 0));
- err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4));
- }
- err |= __put_user(ret, &frame->pretcode);
-
- if (err)
- goto give_sigsegv;
-
- /* Set up registers for signal handler */
- wrusp ((unsigned long) frame);
- regs->pc = (unsigned long) ka->sa.sa_handler;
- regs->er0 = (current_thread_info()->exec_domain
- && current_thread_info()->exec_domain->signal_invmap
- && sig < 32
- ? current_thread_info()->exec_domain->signal_invmap[sig]
- : sig);
- regs->er1 = (unsigned long)&(frame->info);
- regs->er2 = (unsigned long)&frame->uc;
- regs->er5 = current->mm->start_data; /* GOT base */
-
- return 0;
-
-give_sigsegv:
- force_sigsegv(sig, current);
- return -EFAULT;
-}
-
-/*
- * OK, we're invoking a handler
- */
-static void
-handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
- struct pt_regs * regs)
-{
- sigset_t *oldset = sigmask_to_save();
- int ret;
- /* are we from a system call? */
- if (regs->orig_er0 >= 0) {
- switch (regs->er0) {
- case -ERESTART_RESTARTBLOCK:
- case -ERESTARTNOHAND:
- regs->er0 = -EINTR;
- break;
-
- case -ERESTARTSYS:
- if (!(ka->sa.sa_flags & SA_RESTART)) {
- regs->er0 = -EINTR;
- break;
- }
- /* fallthrough */
- case -ERESTARTNOINTR:
- regs->er0 = regs->orig_er0;
- regs->pc -= 2;
- }
- }
-
- /* set up the stack frame */
- if (ka->sa.sa_flags & SA_SIGINFO)
- ret = setup_rt_frame(sig, ka, info, oldset, regs);
- else
- ret = setup_frame(sig, ka, oldset, regs);
-
- if (!ret)
- signal_delivered(sig, info, ka, regs, 0);
-}
-
-/*
- * Note that 'init' is a special process: it doesn't get signals it doesn't
- * want to handle. Thus you cannot kill init even with a SIGKILL even by
- * mistake.
- */
-static void do_signal(struct pt_regs *regs)
-{
- siginfo_t info;
- int signr;
- struct k_sigaction ka;
-
- /*
- * We want the common case to go fast, which
- * is why we may in certain cases get here from
- * kernel mode. Just return without doing anything
- * if so.
- */
- if ((regs->ccr & 0x10))
- return;
-
- current->thread.esp0 = (unsigned long) regs;
-
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- if (signr > 0) {
- /* Whee! Actually deliver the signal. */
- handle_signal(signr, &info, &ka, regs);
- return;
- }
- /* Did we come from a system call? */
- if (regs->orig_er0 >= 0) {
- /* Restart the system call - no handlers present */
- if (regs->er0 == -ERESTARTNOHAND ||
- regs->er0 == -ERESTARTSYS ||
- regs->er0 == -ERESTARTNOINTR) {
- regs->er0 = regs->orig_er0;
- regs->pc -= 2;
- }
- if (regs->er0 == -ERESTART_RESTARTBLOCK){
- regs->er0 = __NR_restart_syscall;
- regs->pc -= 2;
- }
- }
-
- /* If there's no signal to deliver, we just restore the saved mask. */
- restore_saved_sigmask();
-}
-
-asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
-{
- if (thread_info_flags & _TIF_SIGPENDING)
- do_signal(regs);
-
- if (thread_info_flags & _TIF_NOTIFY_RESUME) {
- clear_thread_flag(TIF_NOTIFY_RESUME);
- tracehook_notify_resume(regs);
- }
-}
diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c
deleted file mode 100644
index bf350cb7f597..000000000000
--- a/arch/h8300/kernel/sys_h8300.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * linux/arch/h8300/kernel/sys_h8300.c
- *
- * This file contains various random system calls that
- * have a non-standard calling sequence on the H8/300
- * platform.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/sem.h>
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <linux/stat.h>
-#include <linux/syscalls.h>
-#include <linux/mman.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/ipc.h>
-
-#include <asm/setup.h>
-#include <asm/uaccess.h>
-#include <asm/cachectl.h>
-#include <asm/traps.h>
-#include <asm/unistd.h>
-
-/* sys_cacheflush -- no support. */
-asmlinkage int
-sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
-{
- return -EINVAL;
-}
-
-asmlinkage int sys_getpagesize(void)
-{
- return PAGE_SIZE;
-}
-
-#if defined(CONFIG_SYSCALL_PRINT)
-asmlinkage void syscall_print(void *dummy,...)
-{
- struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4);
- printk("call %06lx:%ld 1:%08lx,2:%08lx,3:%08lx,ret:%08lx\n",
- ((regs->pc)&0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0);
-}
-#endif
diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S
deleted file mode 100644
index c55e0ed270d5..000000000000
--- a/arch/h8300/kernel/syscalls.S
+++ /dev/null
@@ -1,338 +0,0 @@
-/* Systemcall Entry Table */
-#include <linux/sys.h>
-#include <asm/linkage.h>
-#include <asm/unistd.h>
-
-#define CALL(x) .long _ ## x
-
-.globl _sys_call_table
-
-#if defined(CONFIG_CPU_H8300H)
- .h8300h
-#endif
-#if defined(CONFIG_CPU_H8S)
- .h8300s
-#endif
- .section .text
- .align 2
-_sys_call_table:
- CALL(sys_ni_syscall) /* 0 - old "setup()" system call*/
- CALL(sys_exit)
- CALL(sys_fork)
- CALL(sys_read)
- CALL(sys_write)
- CALL(sys_open) /* 5 */
- CALL(sys_close)
- CALL(sys_waitpid)
- CALL(sys_creat)
- CALL(sys_link)
- CALL(sys_unlink) /* 10 */
- CALL(sys_execve)
- CALL(sys_chdir)
- CALL(sys_time)
- CALL(sys_mknod)
- CALL(sys_chmod) /* 15 */
- CALL(sys_chown16)
- CALL(sys_ni_syscall) /* old break syscall holder */
- CALL(sys_stat)
- CALL(sys_lseek)
- CALL(sys_getpid) /* 20 */
- CALL(sys_mount)
- CALL(sys_oldumount)
- CALL(sys_setuid16)
- CALL(sys_getuid16)
- CALL(sys_stime) /* 25 */
- CALL(sys_ptrace)
- CALL(sys_alarm)
- CALL(sys_fstat)
- CALL(sys_pause)
- CALL(sys_utime) /* 30 */
- CALL(sys_ni_syscall) /* old stty syscall holder */
- CALL(sys_ni_syscall) /* old gtty syscall holder */
- CALL(sys_access)
- CALL(sys_nice)
- CALL(sys_ni_syscall) /* 35 old ftime syscall holder */
- CALL(sys_sync)
- CALL(sys_kill)
- CALL(sys_rename)
- CALL(sys_mkdir)
- CALL(sys_rmdir) /* 40 */
- CALL(sys_dup)
- CALL(sys_pipe)
- CALL(sys_times)
- CALL(sys_ni_syscall) /* old prof syscall holder */
- CALL(sys_brk) /* 45 */
- CALL(sys_setgid16)
- CALL(sys_getgid16)
- CALL(sys_signal)
- CALL(sys_geteuid16)
- CALL(sys_getegid16) /* 50 */
- CALL(sys_acct)
- CALL(sys_umount) /* recycled never used phys() */
- CALL(sys_ni_syscall) /* old lock syscall holder */
- CALL(sys_ioctl)
- CALL(sys_fcntl) /* 55 */
- CALL(sys_ni_syscall) /* old mpx syscall holder */
- CALL(sys_setpgid)
- CALL(sys_ni_syscall) /* old ulimit syscall holder */
- CALL(sys_ni_syscall)
- CALL(sys_umask) /* 60 */
- CALL(sys_chroot)
- CALL(sys_ustat)
- CALL(sys_dup2)
- CALL(sys_getppid)
- CALL(sys_getpgrp) /* 65 */
- CALL(sys_setsid)
- CALL(sys_sigaction)
- CALL(sys_sgetmask)
- CALL(sys_ssetmask)
- CALL(sys_setreuid16) /* 70 */
- CALL(sys_setregid16)
- CALL(sys_sigsuspend)
- CALL(sys_sigpending)
- CALL(sys_sethostname)
- CALL(sys_setrlimit) /* 75 */
- CALL(sys_old_getrlimit)
- CALL(sys_getrusage)
- CALL(sys_gettimeofday)
- CALL(sys_settimeofday)
- CALL(sys_getgroups16) /* 80 */
- CALL(sys_setgroups16)
- CALL(sys_old_select)
- CALL(sys_symlink)
- CALL(sys_lstat)
- CALL(sys_readlink) /* 85 */
- CALL(sys_uselib)
- CALL(sys_swapon)
- CALL(sys_reboot)
- CALL(sys_old_readdir)
- CALL(sys_old_mmap) /* 90 */
- CALL(sys_munmap)
- CALL(sys_truncate)
- CALL(sys_ftruncate)
- CALL(sys_fchmod)
- CALL(sys_fchown16) /* 95 */
- CALL(sys_getpriority)
- CALL(sys_setpriority)
- CALL(sys_ni_syscall) /* old profil syscall holder */
- CALL(sys_statfs)
- CALL(sys_fstatfs) /* 100 */
- CALL(sys_ni_syscall) /* ioperm for i386 */
- CALL(sys_socketcall)
- CALL(sys_syslog)
- CALL(sys_setitimer)
- CALL(sys_getitimer) /* 105 */
- CALL(sys_newstat)
- CALL(sys_newlstat)
- CALL(sys_newfstat)
- CALL(sys_ni_syscall)
- CALL(sys_ni_syscall) /* iopl for i386 */ /* 110 */
- CALL(sys_vhangup)
- CALL(sys_ni_syscall) /* obsolete idle() syscall */
- CALL(sys_ni_syscall) /* vm86old for i386 */
- CALL(sys_wait4)
- CALL(sys_swapoff) /* 115 */
- CALL(sys_sysinfo)
- CALL(sys_ipc)
- CALL(sys_fsync)
- CALL(sys_sigreturn)
- CALL(sys_clone) /* 120 */
- CALL(sys_setdomainname)
- CALL(sys_newuname)
- CALL(sys_cacheflush) /* modify_ldt for i386 */
- CALL(sys_adjtimex)
- CALL(sys_ni_syscall) /* 125 sys_mprotect */
- CALL(sys_sigprocmask)
- CALL(sys_ni_syscall) /* sys_create_module */
- CALL(sys_init_module)
- CALL(sys_delete_module)
- CALL(sys_ni_syscall) /* 130 sys_get_kernel_syms */
- CALL(sys_quotactl)
- CALL(sys_getpgid)
- CALL(sys_fchdir)
- CALL(sys_bdflush)
- CALL(sys_sysfs) /* 135 */
- CALL(sys_personality)
- CALL(sys_ni_syscall) /* for afs_syscall */
- CALL(sys_setfsuid16)
- CALL(sys_setfsgid16)
- CALL(sys_llseek) /* 140 */
- CALL(sys_getdents)
- CALL(sys_select)
- CALL(sys_flock)
- CALL(sys_ni_syscall) /* sys_msync */
- CALL(sys_readv) /* 145 */
- CALL(sys_writev)
- CALL(sys_getsid)
- CALL(sys_fdatasync)
- CALL(sys_sysctl)
- CALL(sys_ni_syscall) /* 150 sys_mlock */
- CALL(sys_ni_syscall) /* sys_munlock */
- CALL(sys_ni_syscall) /* sys_mlockall */
- CALL(sys_ni_syscall) /* sys_munlockall */
- CALL(sys_sched_setparam)
- CALL(sys_sched_getparam) /* 155 */
- CALL(sys_sched_setscheduler)
- CALL(sys_sched_getscheduler)
- CALL(sys_sched_yield)
- CALL(sys_sched_get_priority_max)
- CALL(sys_sched_get_priority_min) /* 160 */
- CALL(sys_sched_rr_get_interval)
- CALL(sys_nanosleep)
- CALL(sys_ni_syscall) /* sys_mremap */
- CALL(sys_setresuid16)
- CALL(sys_getresuid16) /* 165 */
- CALL(sys_ni_syscall) /* for vm86 */
- CALL(sys_ni_syscall) /* sys_query_module */
- CALL(sys_poll)
- CALL(sys_ni_syscall) /* old nfsservctl */
- CALL(sys_setresgid16) /* 170 */
- CALL(sys_getresgid16)
- CALL(sys_prctl)
- CALL(sys_rt_sigreturn)
- CALL(sys_rt_sigaction)
- CALL(sys_rt_sigprocmask) /* 175 */
- CALL(sys_rt_sigpending)
- CALL(sys_rt_sigtimedwait)
- CALL(sys_rt_sigqueueinfo)
- CALL(sys_rt_sigsuspend)
- CALL(sys_pread64) /* 180 */
- CALL(sys_pwrite64)
- CALL(sys_lchown16);
- CALL(sys_getcwd)
- CALL(sys_capget)
- CALL(sys_capset) /* 185 */
- CALL(sys_sigaltstack)
- CALL(sys_sendfile)
- CALL(sys_ni_syscall) /* streams1 */
- CALL(sys_ni_syscall) /* streams2 */
- CALL(sys_vfork) /* 190 */
- CALL(sys_getrlimit)
- CALL(sys_mmap_pgoff)
- CALL(sys_truncate64)
- CALL(sys_ftruncate64)
- CALL(sys_stat64) /* 195 */
- CALL(sys_lstat64)
- CALL(sys_fstat64)
- CALL(sys_chown)
- CALL(sys_getuid)
- CALL(sys_getgid) /* 200 */
- CALL(sys_geteuid)
- CALL(sys_getegid)
- CALL(sys_setreuid)
- CALL(sys_setregid)
- CALL(sys_getgroups) /* 205 */
- CALL(sys_setgroups)
- CALL(sys_fchown)
- CALL(sys_setresuid)
- CALL(sys_getresuid)
- CALL(sys_setresgid) /* 210 */
- CALL(sys_getresgid)
- CALL(sys_lchown)
- CALL(sys_setuid)
- CALL(sys_setgid)
- CALL(sys_setfsuid) /* 215 */
- CALL(sys_setfsgid)
- CALL(sys_pivot_root)
- CALL(sys_ni_syscall)
- CALL(sys_ni_syscall)
- CALL(sys_getdents64) /* 220 */
- CALL(sys_fcntl64)
- CALL(sys_ni_syscall) /* reserved TUX */
- CALL(sys_ni_syscall) /* reserved Security */
- CALL(sys_gettid)
- CALL(sys_readahead) /* 225 */
- CALL(sys_setxattr)
- CALL(sys_lsetxattr)
- CALL(sys_fsetxattr)
- CALL(sys_getxattr)
- CALL(sys_lgetxattr) /* 230 */
- CALL(sys_fgetxattr)
- CALL(sys_listxattr)
- CALL(sys_llistxattr)
- CALL(sys_flistxattr)
- CALL(sys_removexattr) /* 235 */
- CALL(sys_lremovexattr)
- CALL(sys_fremovexattr)
- CALL(sys_tkill)
- CALL(sys_sendfile64)
- CALL(sys_futex) /* 240 */
- CALL(sys_sched_setaffinity)
- CALL(sys_sched_getaffinity)
- CALL(sys_ni_syscall)
- CALL(sys_ni_syscall)
- CALL(sys_io_setup) /* 245 */
- CALL(sys_io_destroy)
- CALL(sys_io_getevents)
- CALL(sys_io_submit)
- CALL(sys_io_cancel)
- CALL(sys_fadvise64) /* 250 */
- CALL(sys_ni_syscall)
- CALL(sys_exit_group)
- CALL(sys_lookup_dcookie)
- CALL(sys_epoll_create)
- CALL(sys_epoll_ctl) /* 255 */
- CALL(sys_epoll_wait)
- CALL(sys_ni_syscall) /* sys_remap_file_pages */
- CALL(sys_set_tid_address)
- CALL(sys_timer_create)
- CALL(sys_timer_settime) /* 260 */
- CALL(sys_timer_gettime)
- CALL(sys_timer_getoverrun)
- CALL(sys_timer_delete)
- CALL(sys_clock_settime)
- CALL(sys_clock_gettime) /* 265 */
- CALL(sys_clock_getres)
- CALL(sys_clock_nanosleep)
- CALL(sys_statfs64)
- CALL(sys_fstatfs64)
- CALL(sys_tgkill) /* 270 */
- CALL(sys_utimes)
- CALL(sys_fadvise64_64)
- CALL(sys_ni_syscall) /* sys_vserver */
- CALL(sys_ni_syscall)
- CALL(sys_get_mempolicy) /* 275 */
- CALL(sys_set_mempolicy)
- CALL(sys_mq_open)
- CALL(sys_mq_unlink)
- CALL(sys_mq_timedsend)
- CALL(sys_mq_timedreceive) /* 280 */
- CALL(sys_mq_notify)
- CALL(sys_mq_getsetattr)
- CALL(sys_waitid)
- CALL(sys_ni_syscall) /* sys_kexec_load */
- CALL(sys_add_key) /* 285 */
- CALL(sys_request_key)
- CALL(sys_keyctl)
- CALL(sys_ioprio_set)
- CALL(sys_ioprio_get) /* 290 */
- CALL(sys_inotify_init)
- CALL(sys_inotify_add_watch)
- CALL(sys_inotify_rm_watch)
- CALL(sys_migrate_pages)
- CALL(sys_openat) /* 295 */
- CALL(sys_mkdirat)
- CALL(sys_mknodat)
- CALL(sys_fchownat)
- CALL(sys_futimesat)
- CALL(sys_fstatat64) /* 300 */
- CALL(sys_unlinkat)
- CALL(sys_renameat)
- CALL(sys_linkat)
- CALL(sys_symlinkat)
- CALL(sys_readlinkat) /* 305 */
- CALL(sys_fchmodat)
- CALL(sys_faccessat)
- CALL(sys_ni_syscall) /* sys_pselect6 */
- CALL(sys_ni_syscall) /* sys_ppoll */
- CALL(sys_unshare) /* 310 */
- CALL(sys_set_robust_list)
- CALL(sys_get_robust_list)
- CALL(sys_splice)
- CALL(sys_sync_file_range)
- CALL(sys_tee) /* 315 */
- CALL(sys_vmsplice)
- CALL(sys_ni_syscall) /* sys_move_pages */
- CALL(sys_getcpu)
- CALL(sys_ni_syscall) /* sys_epoll_pwait */
- CALL(sys_setns) /* 320 */
diff --git a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c
deleted file mode 100644
index e0f74191d553..000000000000
--- a/arch/h8300/kernel/time.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * linux/arch/h8300/kernel/time.c
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * Copied/hacked from:
- *
- * linux/arch/m68k/kernel/time.c
- *
- * Copyright (C) 1991, 1992, 1995 Linus Torvalds
- *
- * This file contains the m68k-specific time handling details.
- * Most of the stuff is located in the machine specific files.
- *
- * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
- * "A Kernel Model for Precision Timekeeping" by Dave Mills
- */
-
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/timex.h>
-#include <linux/profile.h>
-
-#include <asm/io.h>
-#include <asm/irq_regs.h>
-#include <asm/timer.h>
-
-#define TICK_SIZE (tick_nsec / 1000)
-
-void h8300_timer_tick(void)
-{
- if (current->pid)
- profile_tick(CPU_PROFILING);
- xtime_update(1);
- update_process_times(user_mode(get_irq_regs()));
-}
-
-void read_persistent_clock(struct timespec *ts)
-{
- unsigned int year, mon, day, hour, min, sec;
-
- /* FIX by dqg : Set to zero for platforms that don't have tod */
- /* without this time is undefined and can overflow time_t, causing */
- /* very strange errors */
- year = 1980;
- mon = day = 1;
- hour = min = sec = 0;
-#ifdef CONFIG_H8300_GETTOD
- h8300_gettod (&year, &mon, &day, &hour, &min, &sec);
-#endif
- if ((year += 1900) < 1970)
- year += 100;
- ts->tv_sec = mktime(year, mon, day, hour, min, sec);
- ts->tv_nsec = 0;
-}
-
-void __init time_init(void)
-{
-
- h8300_timer_setup();
-}
diff --git a/arch/h8300/kernel/timer/Makefile b/arch/h8300/kernel/timer/Makefile
deleted file mode 100644
index bef0510ea6ad..000000000000
--- a/arch/h8300/kernel/timer/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# h8300 internal timer handler
-
-obj-$(CONFIG_H8300_TIMER8) := timer8.o
-obj-$(CONFIG_H8300_TIMER16) := timer16.o
-obj-$(CONFIG_H8300_ITU) := itu.o
-obj-$(CONFIG_H8300_TPU) := tpu.o
diff --git a/arch/h8300/kernel/timer/itu.c b/arch/h8300/kernel/timer/itu.c
deleted file mode 100644
index 0a8b5cd5bf38..000000000000
--- a/arch/h8300/kernel/timer/itu.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * linux/arch/h8300/kernel/timer/itu.c
- *
- * Yoshinori Sato <ysato@users.sourcefoge.jp>
- *
- * ITU Timer Handler
- *
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/regs306x.h>
-
-#if CONFIG_H8300_ITU_CH == 0
-#define ITUBASE 0xffff64
-#define ITUIRQ 24
-#elif CONFIG_H8300_ITU_CH == 1
-#define ITUBASE 0xffff6e
-#define ITUIRQ 28
-#elif CONFIG_H8300_ITU_CH == 2
-#define ITUBASE 0xffff78
-#define ITUIRQ 32
-#elif CONFIG_H8300_ITU_CH == 3
-#define ITUBASE 0xffff82
-#define ITUIRQ 36
-#elif CONFIG_H8300_ITU_CH == 4
-#define ITUBASE 0xffff92
-#define ITUIRQ 40
-#else
-#error Unknown timer channel.
-#endif
-
-#define TCR 0
-#define TIOR 1
-#define TIER 2
-#define TSR 3
-#define TCNT 4
-#define GRA 6
-#define GRB 8
-
-static irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
- h8300_timer_tick();
- ctrl_bclr(IMFA, ITUBASE + TSR);
- return IRQ_HANDLED;
-}
-
-static struct irqaction itu_irq = {
- .name = "itu",
- .handler = timer_interrupt,
- .flags = IRQF_DISABLED | IRQF_TIMER,
-};
-
-static const int __initconst divide_rate[] = {1, 2, 4, 8};
-
-void __init h8300_timer_setup(void)
-{
- unsigned int div;
- unsigned int cnt;
-
- calc_param(cnt, div, divide_rate, 0x10000);
-
- setup_irq(ITUIRQ, &itu_irq);
-
- /* initialize timer */
- ctrl_outb(0, TSTR);
- ctrl_outb(CCLR0 | div, ITUBASE + TCR);
- ctrl_outb(0x01, ITUBASE + TIER);
- ctrl_outw(cnt, ITUBASE + GRA);
- ctrl_bset(CONFIG_H8300_ITU_CH, TSTR);
-}
diff --git a/arch/h8300/kernel/timer/timer16.c b/arch/h8300/kernel/timer/timer16.c
deleted file mode 100644
index 462d9f581719..000000000000
--- a/arch/h8300/kernel/timer/timer16.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * linux/arch/h8300/kernel/timer/timer16.c
- *
- * Yoshinori Sato <ysato@users.sourcefoge.jp>
- *
- * 16bit Timer Handler
- *
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/regs306x.h>
-
-/* 16bit timer */
-#if CONFIG_H8300_TIMER16_CH == 0
-#define _16BASE 0xffff78
-#define _16IRQ 24
-#elif CONFIG_H8300_TIMER16_CH == 1
-#define _16BASE 0xffff80
-#define _16IRQ 28
-#elif CONFIG_H8300_TIMER16_CH == 2
-#define _16BASE 0xffff88
-#define _16IRQ 32
-#else
-#error Unknown timer channel.
-#endif
-
-#define TCR 0
-#define TIOR 1
-#define TCNT 2
-#define GRA 4
-#define GRB 6
-
-#define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*10000 /* Timer input freq. */
-
-static irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
- h8300_timer_tick();
- ctrl_bclr(CONFIG_H8300_TIMER16_CH, TISRA);
- return IRQ_HANDLED;
-}
-
-static struct irqaction timer16_irq = {
- .name = "timer-16",
- .handler = timer_interrupt,
- .flags = IRQF_DISABLED | IRQF_TIMER,
-};
-
-static const int __initconst divide_rate[] = {1, 2, 4, 8};
-
-void __init h8300_timer_setup(void)
-{
- unsigned int div;
- unsigned int cnt;
-
- calc_param(cnt, div, divide_rate, 0x10000);
-
- setup_irq(_16IRQ, &timer16_irq);
-
- /* initialize timer */
- ctrl_outb(0, TSTR);
- ctrl_outb(CCLR0 | div, _16BASE + TCR);
- ctrl_outw(cnt, _16BASE + GRA);
- ctrl_bset(4 + CONFIG_H8300_TIMER16_CH, TISRA);
- ctrl_bset(CONFIG_H8300_TIMER16_CH, TSTR);
-}
diff --git a/arch/h8300/kernel/timer/timer8.c b/arch/h8300/kernel/timer/timer8.c
deleted file mode 100644
index 505f3415b40f..000000000000
--- a/arch/h8300/kernel/timer/timer8.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * linux/arch/h8300/kernel/cpu/timer/timer8.c
- *
- * Yoshinori Sato <ysato@users.sourcefoge.jp>
- *
- * 8bit Timer Handler
- *
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/profile.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/timer.h>
-#if defined(CONFIG_CPU_H8300H)
-#include <asm/regs306x.h>
-#endif
-#if defined(CONFIG_CPU_H8S)
-#include <asm/regs267x.h>
-#endif
-
-/* 8bit timer x2 */
-#define CMFA 6
-
-#if defined(CONFIG_H8300_TIMER8_CH0)
-#define _8BASE _8TCR0
-#ifdef CONFIG_CPU_H8300H
-#define _8IRQ 36
-#endif
-#ifdef CONFIG_CPU_H8S
-#define _8IRQ 72
-#endif
-#elif defined(CONFIG_H8300_TIMER8_CH2)
-#ifdef CONFIG_CPU_H8300H
-#define _8BASE _8TCR2
-#define _8IRQ 40
-#endif
-#endif
-
-#ifndef _8BASE
-#error Unknown timer channel.
-#endif
-
-#define _8TCR 0
-#define _8TCSR 2
-#define TCORA 4
-#define TCORB 6
-#define _8TCNT 8
-
-#define CMIEA 0x40
-#define CCLR_CMA 0x08
-#define CKS2 0x04
-
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "xtime_update()" routine every clocktick
- */
-
-static irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
- h8300_timer_tick();
- ctrl_bclr(CMFA, _8BASE + _8TCSR);
- return IRQ_HANDLED;
-}
-
-static struct irqaction timer8_irq = {
- .name = "timer-8",
- .handler = timer_interrupt,
- .flags = IRQF_DISABLED | IRQF_TIMER,
-};
-
-static const int __initconst divide_rate[] = {8, 64, 8192};
-
-void __init h8300_timer_setup(void)
-{
- unsigned int div;
- unsigned int cnt;
-
- calc_param(cnt, div, divide_rate, 0x10000);
- div++;
-
- setup_irq(_8IRQ, &timer8_irq);
-
-#if defined(CONFIG_CPU_H8S)
- /* Timer module enable */
- ctrl_bclr(0, MSTPCRL)
-#endif
-
- /* initialize timer */
- ctrl_outw(cnt, _8BASE + TCORA);
- ctrl_outw(0x0000, _8BASE + _8TCSR);
- ctrl_outw((CMIEA|CCLR_CMA|CKS2) << 8 | div,
- _8BASE + _8TCR);
-}
diff --git a/arch/h8300/kernel/timer/tpu.c b/arch/h8300/kernel/timer/tpu.c
deleted file mode 100644
index 0350f6204ecf..000000000000
--- a/arch/h8300/kernel/timer/tpu.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * linux/arch/h8300/kernel/timer/tpu.c
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * TPU Timer Handler
- *
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/regs267x.h>
-
-/* TPU */
-#if CONFIG_H8300_TPU_CH == 0
-#define TPUBASE 0xffffd0
-#define TPUIRQ 40
-#elif CONFIG_H8300_TPU_CH == 1
-#define TPUBASE 0xffffe0
-#define TPUIRQ 48
-#elif CONFIG_H8300_TPU_CH == 2
-#define TPUBASE 0xfffff0
-#define TPUIRQ 52
-#elif CONFIG_H8300_TPU_CH == 3
-#define TPUBASE 0xfffe80
-#define TPUIRQ 56
-#elif CONFIG_H8300_TPU_CH == 4
-#define TPUBASE 0xfffe90
-#define TPUIRQ 64
-#else
-#error Unknown timer channel.
-#endif
-
-#define _TCR 0
-#define _TMDR 1
-#define _TIOR 2
-#define _TIER 4
-#define _TSR 5
-#define _TCNT 6
-#define _GRA 8
-#define _GRB 10
-
-#define CCLR0 0x20
-
-static irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
- h8300_timer_tick();
- ctrl_bclr(0, TPUBASE + _TSR);
- return IRQ_HANDLED;
-}
-
-static struct irqaction tpu_irq = {
- .name = "tpu",
- .handler = timer_interrupt,
- .flags = IRQF_DISABLED | IRQF_TIMER,
-};
-
-static const int __initconst divide_rate[] = {
-#if CONFIG_H8300_TPU_CH == 0
- 1,4,16,64,0,0,0,0,
-#elif (CONFIG_H8300_TPU_CH == 1) || (CONFIG_H8300_TPU_CH == 5)
- 1,4,16,64,0,0,256,0,
-#elif (CONFIG_H8300_TPU_CH == 2) || (CONFIG_H8300_TPU_CH == 4)
- 1,4,16,64,0,0,0,1024,
-#elif CONFIG_H8300_TPU_CH == 3
- 1,4,16,64,0,1024,256,4096,
-#endif
-};
-
-void __init h8300_timer_setup(void)
-{
- unsigned int cnt;
- unsigned int div;
-
- calc_param(cnt, div, divide_rate, 0x10000);
-
- setup_irq(TPUIRQ, &tpu_irq);
-
- /* TPU module enabled */
- ctrl_bclr(3, MSTPCRH);
-
- ctrl_outb(0, TSTR);
- ctrl_outb(CCLR0 | div, TPUBASE + _TCR);
- ctrl_outb(0, TPUBASE + _TMDR);
- ctrl_outw(0, TPUBASE + _TIOR);
- ctrl_outb(0x01, TPUBASE + _TIER);
- ctrl_outw(cnt, TPUBASE + _GRA);
- ctrl_bset(CONFIG_H8300_TPU_CH, TSTR);
-}
diff --git a/arch/h8300/kernel/traps.c b/arch/h8300/kernel/traps.c
deleted file mode 100644
index cfe494dbe3da..000000000000
--- a/arch/h8300/kernel/traps.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * linux/arch/h8300/boot/traps.c -- general exception handling code
- * H8/300 support Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * Cloned from Linux/m68k.
- *
- * No original Copyright holder listed,
- * Probable original (C) Roman Zippel (assigned DJD, 1999)
- *
- * Copyright 1999-2000 D. Jeff Dionne, <jeff@rt-control.com>
- *
- * 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.
- */
-
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/bug.h>
-
-#include <asm/irq.h>
-#include <asm/traps.h>
-#include <asm/page.h>
-
-static DEFINE_SPINLOCK(die_lock);
-
-/*
- * this must be called very early as the kernel might
- * use some instruction that are emulated on the 060
- */
-
-void __init base_trap_init(void)
-{
-}
-
-void __init trap_init (void)
-{
-}
-
-asmlinkage void set_esp0 (unsigned long ssp)
-{
- current->thread.esp0 = ssp;
-}
-
-/*
- * Generic dumping code. Used for panic and debug.
- */
-
-static void dump(struct pt_regs *fp)
-{
- unsigned long *sp;
- unsigned char *tp;
- int i;
-
- printk("\nCURRENT PROCESS:\n\n");
- printk("COMM=%s PID=%d\n", current->comm, current->pid);
- if (current->mm) {
- printk("TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n",
- (int) current->mm->start_code,
- (int) current->mm->end_code,
- (int) current->mm->start_data,
- (int) current->mm->end_data,
- (int) current->mm->end_data,
- (int) current->mm->brk);
- printk("USER-STACK=%08x KERNEL-STACK=%08lx\n\n",
- (int) current->mm->start_stack,
- (int) PAGE_SIZE+(unsigned long)current);
- }
-
- show_regs(fp);
- printk("\nCODE:");
- tp = ((unsigned char *) fp->pc) - 0x20;
- for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) {
- if ((i % 0x10) == 0)
- printk("\n%08x: ", (int) (tp + i));
- printk("%08x ", (int) *sp++);
- }
- printk("\n");
-
- printk("\nKERNEL STACK:");
- tp = ((unsigned char *) fp) - 0x40;
- for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) {
- if ((i % 0x10) == 0)
- printk("\n%08x: ", (int) (tp + i));
- printk("%08x ", (int) *sp++);
- }
- printk("\n");
- if (STACK_MAGIC != *(unsigned long *)((unsigned long)current+PAGE_SIZE))
- printk("(Possibly corrupted stack page??)\n");
-
- printk("\n\n");
-}
-
-void die(const char *str, struct pt_regs *fp, unsigned long err)
-{
- static int diecount;
-
- oops_enter();
-
- console_verbose();
- spin_lock_irq(&die_lock);
- report_bug(fp->pc, fp);
- printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++diecount);
- dump(fp);
-
- spin_unlock_irq(&die_lock);
- do_exit(SIGSEGV);
-}
-
-extern char _start, _etext;
-#define check_kernel_text(addr) \
- ((addr >= (unsigned long)(&_start)) && \
- (addr < (unsigned long)(&_etext)))
-
-static int kstack_depth_to_print = 24;
-
-void show_stack(struct task_struct *task, unsigned long *esp)
-{
- unsigned long *stack, addr;
- int i;
-
- if (esp == NULL)
- esp = (unsigned long *) &esp;
-
- stack = esp;
-
- printk("Stack from %08lx:", (unsigned long)stack);
- for (i = 0; i < kstack_depth_to_print; i++) {
- if (((unsigned long)stack & (THREAD_SIZE - 1)) == 0)
- break;
- if (i % 8 == 0)
- printk("\n ");
- printk(" %08lx", *stack++);
- }
-
- printk("\nCall Trace:");
- i = 0;
- stack = esp;
- while (((unsigned long)stack & (THREAD_SIZE - 1)) != 0) {
- addr = *stack++;
- /*
- * If the address is either in the text segment of the
- * kernel, or in the region which contains vmalloc'ed
- * memory, it *may* be the address of a calling
- * routine; if so, print it so that someone tracing
- * down the cause of the crash will be able to figure
- * out the call path that was taken.
- */
- if (check_kernel_text(addr)) {
- if (i % 4 == 0)
- printk("\n ");
- printk(" [<%08lx>]", addr);
- i++;
- }
- }
- printk("\n");
-}
-
-void show_trace_task(struct task_struct *tsk)
-{
- show_stack(tsk,(unsigned long *)tsk->thread.esp0);
-}
diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S
deleted file mode 100644
index 3253fed42ac1..000000000000
--- a/arch/h8300/kernel/vmlinux.lds.S
+++ /dev/null
@@ -1,157 +0,0 @@
-#include <asm-generic/vmlinux.lds.h>
-#include <asm/page.h>
-
-/* target memory map */
-#ifdef CONFIG_H8300H_GENERIC
-#define ROMTOP 0x000000
-#define ROMSIZE 0x400000
-#define RAMTOP 0x400000
-#define RAMSIZE 0x400000
-#endif
-
-#ifdef CONFIG_H8300H_AKI3068NET
-#define ROMTOP 0x000000
-#define ROMSIZE 0x080000
-#define RAMTOP 0x400000
-#define RAMSIZE 0x200000
-#endif
-
-#ifdef CONFIG_H8300H_H8MAX
-#define ROMTOP 0x000000
-#define ROMSIZE 0x080000
-#define RAMTOP 0x400000
-#define RAMSIZE 0x200000
-#endif
-
-#ifdef CONFIG_H8300H_SIM
-#define ROMTOP 0x000000
-#define ROMSIZE 0x400000
-#define RAMTOP 0x400000
-#define RAMSIZE 0x400000
-#endif
-
-#ifdef CONFIG_H8S_SIM
-#define ROMTOP 0x000000
-#define ROMSIZE 0x400000
-#define RAMTOP 0x400000
-#define RAMSIZE 0x800000
-#endif
-
-#ifdef CONFIG_H8S_EDOSK2674
-#define ROMTOP 0x000000
-#define ROMSIZE 0x400000
-#define RAMTOP 0x400000
-#define RAMSIZE 0x800000
-#endif
-
-#if defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)
-INPUT(romfs.o)
-#endif
-
-_jiffies = _jiffies_64 + 4;
-
-ENTRY(__start)
-
-SECTIONS
-{
-#if defined(CONFIG_ROMKERNEL)
- . = ROMTOP;
- .vectors :
- {
- __vector = . ;
- *(.vectors*)
- }
-#else
- . = RAMTOP;
- .bootvec :
- {
- *(.bootvec)
- }
-#endif
- .text :
- {
- _text = .;
-#if defined(CONFIG_ROMKERNEL)
- *(.int_redirect)
-#endif
- __stext = . ;
- TEXT_TEXT
- SCHED_TEXT
- LOCK_TEXT
- __etext = . ;
- }
- EXCEPTION_TABLE(16)
-
- RODATA
-#if defined(CONFIG_ROMKERNEL)
- SECURITY_INIT
-#endif
- ROEND = .;
-#if defined(CONFIG_ROMKERNEL)
- . = RAMTOP;
- .data : AT(ROEND)
-#else
- .data :
-#endif
- {
- __sdata = . ;
- ___data_start = . ;
-
- INIT_TASK_DATA(0x2000)
- . = ALIGN(0x4) ;
- DATA_DATA
- . = ALIGN(0x4) ;
- *(.data.*)
-
- . = ALIGN(0x4) ;
- ___init_begin = .;
- __sinittext = .;
- INIT_TEXT
- __einittext = .;
- INIT_DATA
- . = ALIGN(0x4) ;
- INIT_SETUP(0x4)
- ___setup_start = .;
- *(.init.setup)
- . = ALIGN(0x4) ;
- ___setup_end = .;
- INIT_CALLS
- CON_INITCALL
- EXIT_TEXT
- EXIT_DATA
- INIT_RAM_FS
- . = ALIGN(0x4) ;
- ___init_end = .;
- __edata = . ;
- }
-#if defined(CONFIG_RAMKERNEL)
- SECURITY_INIT
-#endif
- __begin_data = LOADADDR(.data);
- .bss :
- {
- . = ALIGN(0x4) ;
- __sbss = . ;
- ___bss_start = . ;
- *(.bss*)
- . = ALIGN(0x4) ;
- *(COMMON)
- . = ALIGN(0x4) ;
- ___bss_stop = . ;
- __ebss = . ;
- __end = . ;
- __ramstart = .;
- }
- .romfs :
- {
- *(.romfs*)
- }
- . = RAMTOP+RAMSIZE;
- .dummy :
- {
- COMMAND_START = . - 0x200 ;
- __ramend = . ;
- }
-
- DISCARDS
-}
diff --git a/arch/h8300/lib/Makefile b/arch/h8300/lib/Makefile
deleted file mode 100644
index 1577f5075b10..000000000000
--- a/arch/h8300/lib/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for H8/300-specific library files..
-#
-
-lib-y = ashrdi3.o checksum.o memcpy.o memset.o abs.o romfs.o
diff --git a/arch/h8300/lib/abs.S b/arch/h8300/lib/abs.S
deleted file mode 100644
index ddd1fb3d01ad..000000000000
--- a/arch/h8300/lib/abs.S
+++ /dev/null
@@ -1,21 +0,0 @@
-;;; abs.S
-
-#include <asm/linkage.h>
-
-#if defined(__H8300H__)
- .h8300h
-#endif
-#if defined(__H8300S__)
- .h8300s
-#endif
- .text
-.global _abs
-
-;;; int abs(int n)
-_abs:
- mov.l er0,er0
- bpl 1f
- neg.l er0
-1:
- rts
-
diff --git a/arch/h8300/lib/ashrdi3.c b/arch/h8300/lib/ashrdi3.c
deleted file mode 100644
index 78efb65e315a..000000000000
--- a/arch/h8300/lib/ashrdi3.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC 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, or (at your option)
-any later version.
-
-GNU CC 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 GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#define BITS_PER_UNIT 8
-
-typedef int SItype __attribute__ ((mode (SI)));
-typedef unsigned int USItype __attribute__ ((mode (SI)));
-typedef int DItype __attribute__ ((mode (DI)));
-typedef int word_type __attribute__ ((mode (__word__)));
-
-struct DIstruct {SItype high, low;};
-
-typedef union
-{
- struct DIstruct s;
- DItype ll;
-} DIunion;
-
-DItype
-__ashrdi3 (DItype u, word_type b)
-{
- DIunion w;
- word_type bm;
- DIunion uu;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
-
- bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
- if (bm <= 0)
- {
- /* w.s.high = 1..1 or 0..0 */
- w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
- w.s.low = uu.s.high >> -bm;
- }
- else
- {
- USItype carries = (USItype)uu.s.high << bm;
- w.s.high = uu.s.high >> b;
- w.s.low = ((USItype)uu.s.low >> b) | carries;
- }
-
- return w.ll;
-}
diff --git a/arch/h8300/lib/checksum.c b/arch/h8300/lib/checksum.c
deleted file mode 100644
index bdc5b032acd6..000000000000
--- a/arch/h8300/lib/checksum.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * IP/TCP/UDP checksumming routines
- *
- * Authors: Jorge Cwik, <jorge@laser.satlink.net>
- * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
- * Tom May, <ftom@netcom.com>
- * Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
- * Lots of code moved from tcp.c and ip.c; see those files
- * for more names.
- *
- * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek:
- * Fixed some nasty bugs, causing some horrible crashes.
- * A: At some points, the sum (%0) was used as
- * length-counter instead of the length counter
- * (%1). Thanks to Roman Hodek for pointing this out.
- * B: GCC seems to mess up if one uses too many
- * data-registers to hold input values and one tries to
- * specify d0 and d1 as scratch registers. Letting gcc choose these
- * registers itself solves the problem.
- *
- * 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.
- */
-
-/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access kills, so most
- of the assembly has to go. */
-
-#include <net/checksum.h>
-#include <linux/module.h>
-
-static inline unsigned short from32to16(unsigned long x)
-{
- /* add up 16-bit and 16-bit for 16+c bit */
- x = (x & 0xffff) + (x >> 16);
- /* add up carry.. */
- x = (x & 0xffff) + (x >> 16);
- return x;
-}
-
-static unsigned long do_csum(const unsigned char * buff, int len)
-{
- int odd, count;
- unsigned long result = 0;
-
- if (len <= 0)
- goto out;
- odd = 1 & (unsigned long) buff;
- if (odd) {
- result = *buff;
- len--;
- buff++;
- }
- count = len >> 1; /* nr of 16-bit words.. */
- if (count) {
- if (2 & (unsigned long) buff) {
- result += *(unsigned short *) buff;
- count--;
- len -= 2;
- buff += 2;
- }
- count >>= 1; /* nr of 32-bit words.. */
- if (count) {
- unsigned long carry = 0;
- do {
- unsigned long w = *(unsigned long *) buff;
- count--;
- buff += 4;
- result += carry;
- result += w;
- carry = (w > result);
- } while (count);
- result += carry;
- result = (result & 0xffff) + (result >> 16);
- }
- if (len & 2) {
- result += *(unsigned short *) buff;
- buff += 2;
- }
- }
- if (len & 1)
- result += (*buff << 8);
- result = from32to16(result);
- if (odd)
- result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
-out:
- return result;
-}
-
-/*
- * This is a version of ip_compute_csum() optimized for IP headers,
- * which always checksum on 4 octet boundaries.
- */
-__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
- return (__force __sum16)~do_csum(iph,ihl*4);
-}
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-/*
- * Egads... That thing apparently assumes that *all* checksums it ever sees will
- * be folded. Very likely a bug.
- */
-__wsum csum_partial(const void *buff, int len, __wsum sum)
-{
- unsigned int result = do_csum(buff, len);
-
- /* add in old sum, and carry.. */
- result += (__force u32)sum;
- /* 16+c bits -> 16 bits */
- result = (result & 0xffff) + (result >> 16);
- return (__force __wsum)result;
-}
-
-EXPORT_SYMBOL(csum_partial);
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-__sum16 ip_compute_csum(const void *buff, int len)
-{
- return (__force __sum16)~do_csum(buff,len);
-}
-
-/*
- * copy from fs while checksumming, otherwise like csum_partial
- */
-
-__wsum
-csum_partial_copy_from_user(const void __user *src, void *dst, int len,
- __wsum sum, int *csum_err)
-{
- if (csum_err) *csum_err = 0;
- memcpy(dst, (__force const void *)src, len);
- return csum_partial(dst, len, sum);
-}
-
-/*
- * copy from ds while checksumming, otherwise like csum_partial
- */
-
-__wsum
-csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
-{
- memcpy(dst, src, len);
- return csum_partial(dst, len, sum);
-}
diff --git a/arch/h8300/lib/memcpy.S b/arch/h8300/lib/memcpy.S
deleted file mode 100644
index cad325e2c0e8..000000000000
--- a/arch/h8300/lib/memcpy.S
+++ /dev/null
@@ -1,84 +0,0 @@
-;;; memcpy.S
-
-#include <asm/linkage.h>
-
-#if defined(__H8300H__)
- .h8300h
-#endif
-#if defined(__H8300S__)
- .h8300s
-#endif
-
- .text
-.global _memcpy
-
-;;; void *memcpy(void *to, void *from, size_t n)
-_memcpy:
- mov.l er2,er2
- bne 1f
- rts
-1:
- ;; address check
- bld #0,r0l
- bxor #0,r1l
- bcs 4f
- mov.l er4,@-sp
- mov.l er0,@-sp
- btst #0,r0l
- beq 1f
- ;; (aligned even) odd address
- mov.b @er1,r3l
- mov.b r3l,@er0
- adds #1,er1
- adds #1,er0
- dec.l #1,er2
- beq 3f
-1:
- ;; n < sizeof(unsigned long) check
- sub.l er4,er4
- adds #4,er4 ; loop count check value
- cmp.l er4,er2
- blo 2f
- ;; unsigned long copy
-1:
- mov.l @er1,er3
- mov.l er3,@er0
- adds #4,er0
- adds #4,er1
- subs #4,er2
- cmp.l er4,er2
- bcc 1b
- ;; rest
-2:
- mov.l er2,er2
- beq 3f
-1:
- mov.b @er1,r3l
- mov.b r3l,@er0
- adds #1,er1
- adds #1,er0
- dec.l #1,er2
- bne 1b
-3:
- mov.l @sp+,er0
- mov.l @sp+,er4
- rts
-
- ;; odd <- even / even <- odd
-4:
- mov.l er4,er3
- mov.l er2,er4
- mov.l er5,er2
- mov.l er1,er5
- mov.l er6,er1
- mov.l er0,er6
-1:
- eepmov.w
- mov.w r4,r4
- bne 1b
- dec.w #1,e4
- bpl 1b
- mov.l er1,er6
- mov.l er2,er5
- mov.l er3,er4
- rts
diff --git a/arch/h8300/lib/memset.S b/arch/h8300/lib/memset.S
deleted file mode 100644
index 4549a64c5b79..000000000000
--- a/arch/h8300/lib/memset.S
+++ /dev/null
@@ -1,61 +0,0 @@
-/* memset.S */
-
-#include <asm/linkage.h>
-
-#if defined(__H8300H__)
- .h8300h
-#endif
-#if defined(__H8300S__)
- .h8300s
-#endif
- .text
-
-.global _memset
-
-;;void *memset(*ptr, int c, size_t count)
-;; ptr = er0
-;; c = er1(r1l)
-;; count = er2
-_memset:
- btst #0,r0l
- beq 2f
-
- ;; odd address
-1:
- mov.b r1l,@er0
- adds #1,er0
- dec.l #1,er2
- beq 6f
-
- ;; even address
-2:
- mov.l er2,er3
- cmp.l #4,er2
- blo 4f
- ;; count>=4 -> count/4
-#if defined(__H8300H__)
- shlr.l er2
- shlr.l er2
-#endif
-#if defined(__H8300S__)
- shlr.l #2,er2
-#endif
- ;; byte -> long
- mov.b r1l,r1h
- mov.w r1,e1
-3:
- mov.l er1,@er0
- adds #4,er0
- dec.l #1,er2
- bne 3b
-4:
- ;; count % 4
- and.b #3,r3l
- beq 6f
-5:
- mov.b r1l,@er0
- adds #1,er0
- dec.b r3l
- bne 5b
-6:
- rts
diff --git a/arch/h8300/lib/romfs.S b/arch/h8300/lib/romfs.S
deleted file mode 100644
index 68910d8e1ff4..000000000000
--- a/arch/h8300/lib/romfs.S
+++ /dev/null
@@ -1,57 +0,0 @@
-/* romfs move to __ebss */
-
-#include <asm/linkage.h>
-
-#if defined(__H8300H__)
- .h8300h
-#endif
-#if defined(__H8300S__)
- .h8300s
-#endif
-
-#define BLKOFFSET 512
-
- .text
-.globl __move_romfs
-_romfs_sig_len = 8
-
-__move_romfs:
- mov.l #__sbss,er0
- mov.l #_romfs_sig,er1
- mov.b #_romfs_sig_len,r3l
-1: /* check romfs image */
- mov.b @er0+,r2l
- mov.b @er1+,r2h
- cmp.b r2l,r2h
- bne 2f
- dec.b r3l
- bne 1b
-
- /* find romfs image */
- mov.l @__sbss+8,er0 /* romfs length(be) */
- mov.l #__sbss,er1
- add.l er0,er1 /* romfs image end */
- mov.l #__ebss,er2
- add.l er0,er2 /* distination address */
-#if defined(CONFIG_INTELFLASH)
- add.l #BLKOFFSET,er2
-#endif
- adds #2,er0
- adds #1,er0
- shlr er0
- shlr er0 /* transfer length */
-1:
- mov.l @er1,er3 /* copy image */
- mov.l er3,@er2
- subs #4,er1
- subs #4,er2
- dec.l #1,er0
- bpl 1b
-2:
- rts
-
- .section .rodata
-_romfs_sig:
- .ascii "-rom1fs-"
-
- .end
diff --git a/arch/h8300/mm/Makefile b/arch/h8300/mm/Makefile
deleted file mode 100644
index 5f4bc42b6453..000000000000
--- a/arch/h8300/mm/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the linux m68k-specific parts of the memory manager.
-#
-
-obj-y := init.o fault.o memory.o kmap.o
diff --git a/arch/h8300/mm/fault.c b/arch/h8300/mm/fault.c
deleted file mode 100644
index 472535977006..000000000000
--- a/arch/h8300/mm/fault.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * linux/arch/h8300/mm/fault.c
- *
- * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
- * Copyright (C) 2000 Lineo, Inc. (www.lineo.com)
- *
- * Based on:
- *
- * linux/arch/m68knommu/mm/fault.c
- * linux/arch/m68k/mm/fault.c
- *
- * Copyright (C) 1995 Hamish Macdonald
- */
-
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/ptrace.h>
-
-#include <asm/pgtable.h>
-
-/*
- * This routine handles page faults. It determines the problem, and
- * then passes it off to one of the appropriate routines.
- *
- * error_code:
- * bit 0 == 0 means no page found, 1 means protection fault
- * bit 1 == 0 means read, 1 means write
- *
- * If this routine detects a bad access, it returns 1, otherwise it
- * returns 0.
- */
-asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
- unsigned long error_code)
-{
-#ifdef DEBUG
- printk ("regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld\n",
- regs->sr, regs->pc, address, error_code);
-#endif
-
-/*
- * Oops. The kernel tried to access some bad page. We'll have to
- * terminate things with extreme prejudice.
- */
- if ((unsigned long) address < PAGE_SIZE) {
- printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
- } else
- printk(KERN_ALERT "Unable to handle kernel access");
- printk(" at virtual address %08lx\n",address);
- if (!user_mode(regs))
- die("Oops", regs, error_code);
- do_exit(SIGKILL);
-
- return 1;
-}
-
diff --git a/arch/h8300/mm/init.c b/arch/h8300/mm/init.c
deleted file mode 100644
index 6c1251e491af..000000000000
--- a/arch/h8300/mm/init.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * linux/arch/h8300/mm/init.c
- *
- * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
- * Kenneth Albanowski <kjahds@kjahds.com>,
- * Copyright (C) 2000 Lineo, Inc. (www.lineo.com)
- *
- * Based on:
- *
- * linux/arch/m68knommu/mm/init.c
- * linux/arch/m68k/mm/init.c
- *
- * Copyright (C) 1995 Hamish Macdonald
- *
- * JAN/1999 -- hacked to support ColdFire (gerg@snapgear.com)
- * DEC/2000 -- linux 2.4 support <davidm@snapgear.com>
- */
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/init.h>
-#include <linux/highmem.h>
-#include <linux/pagemap.h>
-#include <linux/bootmem.h>
-#include <linux/gfp.h>
-
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/sections.h>
-
-#undef DEBUG
-
-/*
- * BAD_PAGE is the page that is used for page faults when linux
- * is out-of-memory. Older versions of linux just did a
- * do_exit(), but using this instead means there is less risk
- * for a process dying in kernel mode, possibly leaving a inode
- * unused etc..
- *
- * BAD_PAGETABLE is the accompanying page-table: it is initialized
- * to point to BAD_PAGE entries.
- *
- * ZERO_PAGE is a special page that is used for zero-initialized
- * data and COW.
- */
-static unsigned long empty_bad_page_table;
-
-static unsigned long empty_bad_page;
-
-unsigned long empty_zero_page;
-
-extern unsigned long rom_length;
-
-extern unsigned long memory_start;
-extern unsigned long memory_end;
-
-/*
- * paging_init() continues the virtual memory environment setup which
- * was begun by the code in arch/head.S.
- * The parameters are pointers to where to stick the starting and ending
- * addresses of available kernel virtual memory.
- */
-void __init paging_init(void)
-{
- /*
- * Make sure start_mem is page aligned, otherwise bootmem and
- * page_alloc get different views og the world.
- */
-#ifdef DEBUG
- unsigned long start_mem = PAGE_ALIGN(memory_start);
-#endif
- unsigned long end_mem = memory_end & PAGE_MASK;
-
-#ifdef DEBUG
- printk ("start_mem is %#lx\nvirtual_end is %#lx\n",
- start_mem, end_mem);
-#endif
-
- /*
- * Initialize the bad page table and bad page to point
- * to a couple of allocated pages.
- */
- empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
- empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
- empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
- memset((void *)empty_zero_page, 0, PAGE_SIZE);
-
- /*
- * Set up SFC/DFC registers (user data space).
- */
- set_fs (USER_DS);
-
-#ifdef DEBUG
- printk ("before free_area_init\n");
-
- printk ("free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n",
- start_mem, end_mem);
-#endif
-
- {
- unsigned long zones_size[MAX_NR_ZONES] = {0, };
-
- zones_size[ZONE_DMA] = 0 >> PAGE_SHIFT;
- zones_size[ZONE_NORMAL] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
-#ifdef CONFIG_HIGHMEM
- zones_size[ZONE_HIGHMEM] = 0;
-#endif
- free_area_init(zones_size);
- }
-}
-
-void __init mem_init(void)
-{
- unsigned long codesize = _etext - _stext;
-
- pr_devel("Mem_init: start=%lx, end=%lx\n", memory_start, memory_end);
-
- high_memory = (void *) (memory_end & PAGE_MASK);
- max_mapnr = MAP_NR(high_memory);
-
- /* this will put all low memory onto the freelists */
- free_all_bootmem();
-
- mem_init_print_info(NULL);
- if (rom_length > 0 && rom_length > codesize)
- pr_info("Memory available: %luK/%luK ROM\n",
- (rom_length - codesize) >> 10, rom_length >> 10);
-}
-
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
- free_reserved_area((void *)start, (void *)end, -1, "initrd");
-}
-#endif
-
-void
-free_initmem(void)
-{
-#ifdef CONFIG_RAMKERNEL
- free_initmem_default(-1);
-#endif
-}
-
diff --git a/arch/h8300/mm/kmap.c b/arch/h8300/mm/kmap.c
deleted file mode 100644
index f79edcdadf39..000000000000
--- a/arch/h8300/mm/kmap.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * linux/arch/h8300/mm/kmap.c
- *
- * Based on
- * linux/arch/m68knommu/mm/kmap.c
- *
- * Copyright (C) 2000 Lineo, <davidm@snapgear.com>
- * Copyright (C) 2000-2002 David McCullough <davidm@snapgear.com>
- */
-
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/vmalloc.h>
-
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-#include <asm/io.h>
-
-#undef DEBUG
-
-#define VIRT_OFFSET (0x01000000)
-
-/*
- * Map some physical address range into the kernel address space.
- */
-void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
-{
- return (void *)(physaddr + VIRT_OFFSET);
-}
-
-/*
- * Unmap a ioremap()ed region again.
- */
-void iounmap(void *addr)
-{
-}
-
-/*
- * __iounmap unmaps nearly everything, so be careful
- * it doesn't free currently pointer/page tables anymore but it
- * wans't used anyway and might be added later.
- */
-void __iounmap(void *addr, unsigned long size)
-{
-}
-
-/*
- * Set new cache mode for some kernel address space.
- * The caller must push data for that range itself, if such data may already
- * be in the cache.
- */
-void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
-{
-}
diff --git a/arch/h8300/mm/memory.c b/arch/h8300/mm/memory.c
deleted file mode 100644
index 06e364641392..000000000000
--- a/arch/h8300/mm/memory.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * linux/arch/h8300/mm/memory.c
- *
- * Copyright (C) 2002 Yoshinori Sato <ysato@users.sourceforge.jp>,
- *
- * Based on:
- *
- * linux/arch/m68knommu/mm/memory.c
- *
- * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>,
- * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
- *
- * Based on:
- *
- * linux/arch/m68k/mm/memory.c
- *
- * Copyright (C) 1995 Hamish Macdonald
- */
-
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/types.h>
-
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/traps.h>
-#include <asm/io.h>
-
-void cache_clear (unsigned long paddr, int len)
-{
-}
-
-
-void cache_push (unsigned long paddr, int len)
-{
-}
-
-void cache_push_v (unsigned long vaddr, int len)
-{
-}
-
-/*
- * Map some physical address range into the kernel address space.
- */
-
-unsigned long kernel_map(unsigned long paddr, unsigned long size,
- int nocacheflag, unsigned long *memavailp )
-{
- return paddr;
-}
-
diff --git a/arch/h8300/platform/h8300h/Makefile b/arch/h8300/platform/h8300h/Makefile
deleted file mode 100644
index 420f73b0d962..000000000000
--- a/arch/h8300/platform/h8300h/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-# Reuse any files we can from the H8/300H
-#
-
-obj-y := irq.o ptrace_h8300h.o
diff --git a/arch/h8300/platform/h8300h/aki3068net/Makefile b/arch/h8300/platform/h8300h/aki3068net/Makefile
deleted file mode 100644
index b7ff78050b7f..000000000000
--- a/arch/h8300/platform/h8300h/aki3068net/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-extra-y := crt0_ram.o
diff --git a/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S b/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S
deleted file mode 100644
index b2ad0f2d0417..000000000000
--- a/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * linux/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * Platform depend startup
- * Target Archtecture: AE-3068 (aka. aki3068net)
- * Memory Layout : RAM
- */
-
-#define ASSEMBLY
-
-#include <asm/linkage.h>
-
-#if !defined(CONFIG_BLKDEV_RESERVE)
-#if defined(CONFIG_GDB_DEBUG)
-#define RAMEND (__ramend - 0xc000)
-#else
-#define RAMEND __ramend
-#endif
-#else
-#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS
-#endif
-
- .global __start
- .global _command_line
- .global __platform_gpio_table
- .global __target_name
-
- .h8300h
-
- .section .text
- .file "crt0_ram.S"
-
- /* CPU Reset entry */
-__start:
- mov.l #RAMEND,sp
- ldc #0x80,ccr
-
- /* Peripheral Setup */
-
-#if defined(CONFIG_MTD_UCLINUX)
- /* move romfs image */
- jsr @__move_romfs
-#endif
-
- /* .bss clear */
- mov.l #__sbss,er5
- mov.l #__ebss,er4
- sub.l er5,er4
- shlr er4
- shlr er4
- sub.l er0,er0
-1:
- mov.l er0,@er5
- adds #4,er5
- dec.l #1,er4
- bne 1b
-
- /* copy kernel commandline */
- mov.l #COMMAND_START,er5
- mov.l #_command_line,er6
- mov.w #512,r4
- eepmov.w
-
- /* uClinux kernel start */
- ldc #0x90,ccr /* running kernel */
- mov.l #_init_thread_union,sp
- add.l #0x2000,sp
- jsr @_start_kernel
-_exit:
-
- jmp _exit
-
- rts
-
- /* I/O port assign information */
-__platform_gpio_table:
- mov.l #gpio_table,er0
- rts
-
-gpio_table:
- ;; P1DDR
- .byte 0xff,0xff
- ;; P2DDR
- .byte 0xff,0xff
- ;; P3DDR
- .byte 0xff,0x00
- ;; P4DDR
- .byte 0x00,0x00
- ;; P5DDR
- .byte 0x01,0x01
- ;; P6DDR
- .byte 0x00,0x00
- ;; dummy
- .byte 0x00,0x00
- ;; P8DDR
- .byte 0x0c,0x0c
- ;; P9DDR
- .byte 0x00,0x00
- ;; PADDR
- .byte 0x00,0x00
- ;; PBDDR
- .byte 0x30,0x30
-
-__target_name:
- .asciz "AE-3068"
-
- .section .bootvec,"ax"
- jmp @__start
diff --git a/arch/h8300/platform/h8300h/generic/Makefile b/arch/h8300/platform/h8300h/generic/Makefile
deleted file mode 100644
index 2b12a170209e..000000000000
--- a/arch/h8300/platform/h8300h/generic/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-extra-y := crt0_$(MODEL).o
diff --git a/arch/h8300/platform/h8300h/generic/crt0_ram.S b/arch/h8300/platform/h8300h/generic/crt0_ram.S
deleted file mode 100644
index 5ab7d9c12910..000000000000
--- a/arch/h8300/platform/h8300h/generic/crt0_ram.S
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * linux/arch/h8300/platform/h8300h/generic/crt0_ram.S
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * Platform depend startup
- * Target Archtecture: AE-3068 (aka. aki3068net)
- * Memory Layout : RAM
- */
-
-#define ASSEMBLY
-
-#include <asm/linkage.h>
-
-#if !defined(CONFIG_BLKDEV_RESERVE)
-#if defined(CONFIG_GDB_DEBUG)
-#define RAMEND (__ramend - 0xc000)
-#else
-#define RAMEND __ramend
-#endif
-#else
-#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS
-#endif
-
- .global __start
- .global _command_line
- .global __platform_gpio_table
- .global __target_name
-
- .h8300h
-
- .section .text
- .file "crt0_ram.S"
-
- /* CPU Reset entry */
-__start:
- mov.l #RAMEND,sp
- ldc #0x80,ccr
-
- /* Peripheral Setup */
-
-#if defined(CONFIG_BLK_DEV_BLKMEM)
- /* move romfs image */
- jsr @__move_romfs
-#endif
-
- /* .bss clear */
- mov.l #__sbss,er5
- mov.l #__ebss,er4
- sub.l er5,er4
- shlr er4
- shlr er4
- sub.l er0,er0
-1:
- mov.l er0,@er5
- adds #4,er5
- dec.l #1,er4
- bne 1b
-
- /* copy kernel commandline */
- mov.l #COMMAND_START,er5
- mov.l #_command_line,er6
- mov.w #512,r4
- eepmov.w
-
- /* uClinux kernel start */
- ldc #0x90,ccr /* running kernel */
- mov.l #_init_thread_union,sp
- add.l #0x2000,sp
- jsr @_start_kernel
-_exit:
-
- jmp _exit
-
- rts
-
- /* I/O port assign information */
-__platform_gpio_table:
- mov.l #gpio_table,er0
- rts
-
-gpio_table:
- ;; P1DDR
- .byte 0x00,0x00
- ;; P2DDR
- .byte 0x00,0x00
- ;; P3DDR
- .byte 0x00,0x00
- ;; P4DDR
- .byte 0x00,0x00
- ;; P5DDR
- .byte 0x00,0x00
- ;; P6DDR
- .byte 0x00,0x00
- ;; dummy
- .byte 0x00,0x00
- ;; P8DDR
- .byte 0x00,0x00
- ;; P9DDR
- .byte 0x00,0x00
- ;; PADDR
- .byte 0x00,0x00
- ;; PBDDR
- .byte 0x00,0x00
-
-__target_name:
- .asciz "generic"
diff --git a/arch/h8300/platform/h8300h/generic/crt0_rom.S b/arch/h8300/platform/h8300h/generic/crt0_rom.S
deleted file mode 100644
index dda1dfa15a5e..000000000000
--- a/arch/h8300/platform/h8300h/generic/crt0_rom.S
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * linux/arch/h8300/platform/h8300h/generic/crt0_rom.S
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * Platform depend startup
- * Target Archtecture: generic
- * Memory Layout : ROM
- */
-
-#define ASSEMBLY
-
-#include <asm/linkage.h>
-
- .global __start
- .global __command_line
- .global __platform_gpio_table
- .global __target_name
-
- .h8300h
- .section .text
- .file "crt0_rom.S"
-
- /* CPU Reset entry */
-__start:
- mov.l #__ramend,sp
- ldc #0x80,ccr
-
- /* Peripheral Setup */
-
- /* .bss clear */
- mov.l #__sbss,er5
- mov.l #__ebss,er4
- sub.l er5,er4
- shlr er4
- shlr er4
- sub.l er0,er0
-1:
- mov.l er0,@er5
- adds #4,er5
- dec.l #1,er4
- bne 1b
-
- /* copy .data */
-#if !defined(CONFIG_H8300H_SIM)
- /* copy .data */
- mov.l #__begin_data,er5
- mov.l #__sdata,er6
- mov.l #__edata,er4
- sub.l er6,er4
- shlr.l er4
- shlr.l er4
-1:
- mov.l @er5+,er0
- mov.l er0,@er6
- adds #4,er6
- dec.l #1,er4
- bne 1b
-#endif
-
- /* copy kernel commandline */
- mov.l #COMMAND_START,er5
- mov.l #__command_line,er6
- mov.w #512,r4
- eepmov.w
-
- /* linux kernel start */
- ldc #0x90,ccr /* running kernel */
- mov.l #_init_thread_union,sp
- add.l #0x2000,sp
- jsr @_start_kernel
-_exit:
-
- jmp _exit
-
- rts
-
- /* I/O port assign information */
-__platform_gpio_table:
- mov.l #gpio_table,er0
- rts
-
-gpio_table:
- ;; P1DDR
- .byte 0x00,0x00
- ;; P2DDR
- .byte 0x00,0x00
- ;; P3DDR
- .byte 0x00,0x00
- ;; P4DDR
- .byte 0x00,0x00
- ;; P5DDR
- .byte 0x00,0x00
- ;; P6DDR
- .byte 0x00,0x00
- ;; dummy
- .byte 0x00,0x00
- ;; P8DDR
- .byte 0x00,0x00
- ;; P9DDR
- .byte 0x00,0x00
- ;; PADDR
- .byte 0x00,0x00
- ;; PBDDR
- .byte 0x00,0x00
-
- .section .rodata
-__target_name:
- .asciz "generic"
-
- .section .bss
-__command_line:
- .space 512
-
- /* interrupt vector */
- .section .vectors,"ax"
- .long __start
-vector = 1
- .rept 64-1
- .long _interrupt_redirect_table+vector*4
-vector = vector + 1
- .endr
diff --git a/arch/h8300/platform/h8300h/h8max/Makefile b/arch/h8300/platform/h8300h/h8max/Makefile
deleted file mode 100644
index b7ff78050b7f..000000000000
--- a/arch/h8300/platform/h8300h/h8max/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-extra-y := crt0_ram.o
diff --git a/arch/h8300/platform/h8300h/h8max/crt0_ram.S b/arch/h8300/platform/h8300h/h8max/crt0_ram.S
deleted file mode 100644
index 6a0d4e2d9ec6..000000000000
--- a/arch/h8300/platform/h8300h/h8max/crt0_ram.S
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * linux/arch/h8300/platform/h8300h/h8max/crt0_ram.S
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * Platform depend startup
- * Target Archtecture: H8MAX
- * Memory Layout : RAM
- */
-
-#define ASSEMBLY
-
-#include <asm/linkage.h>
-
-#if !defined(CONFIG_BLKDEV_RESERVE)
-#if defined(CONFIG_GDB_DEBUG)
-#define RAMEND (__ramend - 0xc000)
-#else
-#define RAMEND __ramend
-#endif
-#else
-#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS
-#endif
-
- .global __start
- .global _command_line
- .global __platform_gpio_table
- .global __target_name
-
- .h8300h
-
- .section .text
- .file "crt0_ram.S"
-
- /* CPU Reset entry */
-__start:
- mov.l #RAMEND,sp
- ldc #0x80,ccr
-
- /* Peripheral Setup */
-
-#if defined(CONFIG_MTD_UCLINUX)
- /* move romfs image */
- jsr @__move_romfs
-#endif
-
- /* .bss clear */
- mov.l #__sbss,er5
- mov.l #__ebss,er4
- sub.l er5,er4
- shlr er4
- shlr er4
- sub.l er0,er0
-1:
- mov.l er0,@er5
- adds #4,er5
- dec.l #1,er4
- bne 1b
-
- /* copy kernel commandline */
- mov.l #COMMAND_START,er5
- mov.l #_command_line,er6
- mov.w #512,r4
- eepmov.w
-
- /* uClinux kernel start */
- ldc #0x90,ccr /* running kernel */
- mov.l #_init_thread_union,sp
- add.l #0x2000,sp
- jsr @_start_kernel
-_exit:
-
- jmp _exit
-
- rts
-
- /* I/O port assign information */
-__platform_gpio_table:
- mov.l #gpio_table,er0
- rts
-
-gpio_table:
- ;; P1DDR
- .byte 0xff,0xff
- ;; P2DDR
- .byte 0xff,0xff
- ;; P3DDR
- .byte 0x00,0x00
- ;; P4DDR
- .byte 0x00,0x00
- ;; P5DDR
- .byte 0x01,0x01
- ;; P6DDR
- .byte 0xf6,0xf6
- ;; dummy
- .byte 0x00,0x00
- ;; P8DDR
- .byte 0xee,0xee
- ;; P9DDR
- .byte 0x00,0x00
- ;; PADDR
- .byte 0x00,0x00
- ;; PBDDR
- .byte 0x30,0x30
-
-__target_name:
- .asciz "H8MAX"
-
- .section .bootvec,"ax"
- jmp @__start
diff --git a/arch/h8300/platform/h8300h/irq.c b/arch/h8300/platform/h8300h/irq.c
deleted file mode 100644
index 0a50353e09d5..000000000000
--- a/arch/h8300/platform/h8300h/irq.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Interrupt handling H8/300H depend.
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- */
-
-#include <linux/init.h>
-#include <linux/errno.h>
-
-#include <asm/ptrace.h>
-#include <asm/traps.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/gpio-internal.h>
-#include <asm/regs306x.h>
-
-const int __initconst h8300_saved_vectors[] = {
-#if defined(CONFIG_GDB_DEBUG)
- TRAP3_VEC, /* TRAPA #3 is GDB breakpoint */
-#endif
- -1,
-};
-
-const h8300_vector __initconst h8300_trap_table[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- system_call,
- 0,
- 0,
- trace_break,
-};
-
-int h8300_enable_irq_pin(unsigned int irq)
-{
- int bitmask;
- if (irq < EXT_IRQ0 || irq > EXT_IRQ5)
- return 0;
-
- /* initialize IRQ pin */
- bitmask = 1 << (irq - EXT_IRQ0);
- switch(irq) {
- case EXT_IRQ0:
- case EXT_IRQ1:
- case EXT_IRQ2:
- case EXT_IRQ3:
- if (H8300_GPIO_RESERVE(H8300_GPIO_P8, bitmask) == 0)
- return -EBUSY;
- H8300_GPIO_DDR(H8300_GPIO_P8, bitmask, H8300_GPIO_INPUT);
- break;
- case EXT_IRQ4:
- case EXT_IRQ5:
- if (H8300_GPIO_RESERVE(H8300_GPIO_P9, bitmask) == 0)
- return -EBUSY;
- H8300_GPIO_DDR(H8300_GPIO_P9, bitmask, H8300_GPIO_INPUT);
- break;
- }
-
- return 0;
-}
-
-void h8300_disable_irq_pin(unsigned int irq)
-{
- int bitmask;
- if (irq < EXT_IRQ0 || irq > EXT_IRQ5)
- return;
-
- /* disable interrupt & release IRQ pin */
- bitmask = 1 << (irq - EXT_IRQ0);
- switch(irq) {
- case EXT_IRQ0:
- case EXT_IRQ1:
- case EXT_IRQ2:
- case EXT_IRQ3:
- *(volatile unsigned char *)IER &= ~bitmask;
- H8300_GPIO_FREE(H8300_GPIO_P8, bitmask);
- break ;
- case EXT_IRQ4:
- case EXT_IRQ5:
- *(volatile unsigned char *)IER &= ~bitmask;
- H8300_GPIO_FREE(H8300_GPIO_P9, bitmask);
- break;
- }
-}
diff --git a/arch/h8300/platform/h8300h/ptrace_h8300h.c b/arch/h8300/platform/h8300h/ptrace_h8300h.c
deleted file mode 100644
index 4f1ed0279633..000000000000
--- a/arch/h8300/platform/h8300h/ptrace_h8300h.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * linux/arch/h8300/platform/h8300h/ptrace_h8300h.c
- * ptrace cpu depend helper functions
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * 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.
- */
-
-#include <linux/linkage.h>
-#include <linux/sched.h>
-#include <asm/ptrace.h>
-
-#define CCR_MASK 0x6f /* mode/imask not set */
-#define BREAKINST 0x5730 /* trapa #3 */
-
-/* Mapping from PT_xxx to the stack offset at which the register is
- saved. Notice that usp has no stack-slot and needs to be treated
- specially (see get_reg/put_reg below). */
-static const int h8300_register_offset[] = {
- PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4),
- PT_REG(er5), PT_REG(er6), PT_REG(er0), PT_REG(orig_er0),
- PT_REG(ccr), PT_REG(pc)
-};
-
-/* read register */
-long h8300_get_reg(struct task_struct *task, int regno)
-{
- switch (regno) {
- case PT_USP:
- return task->thread.usp + sizeof(long)*2;
- case PT_CCR:
- return *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
- default:
- return *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]);
- }
-}
-
-/* write register */
-int h8300_put_reg(struct task_struct *task, int regno, unsigned long data)
-{
- unsigned short oldccr;
- switch (regno) {
- case PT_USP:
- task->thread.usp = data - sizeof(long)*2;
- case PT_CCR:
- oldccr = *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
- oldccr &= ~CCR_MASK;
- data &= CCR_MASK;
- data |= oldccr;
- *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
- break;
- default:
- *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
- break;
- }
- return 0;
-}
-
-/* disable singlestep */
-void user_disable_single_step(struct task_struct *child)
-{
- if((long)child->thread.breakinfo.addr != -1L) {
- *child->thread.breakinfo.addr = child->thread.breakinfo.inst;
- child->thread.breakinfo.addr = (unsigned short *)-1L;
- }
-}
-
-/* calculate next pc */
-enum jump_type {none, /* normal instruction */
- jabs, /* absolute address jump */
- ind, /* indirect address jump */
- ret, /* return to subrutine */
- reg, /* register indexed jump */
- relb, /* pc relative jump (byte offset) */
- relw, /* pc relative jump (word offset) */
- };
-
-/* opcode decode table define
- ptn: opcode pattern
- msk: opcode bitmask
- len: instruction length (<0 next table index)
- jmp: jump operation mode */
-struct optable {
- unsigned char bitpattern;
- unsigned char bitmask;
- signed char length;
- signed char type;
-} __attribute__((aligned(1),packed));
-
-#define OPTABLE(ptn,msk,len,jmp) \
- { \
- .bitpattern = ptn, \
- .bitmask = msk, \
- .length = len, \
- .type = jmp, \
- }
-
-static const struct optable optable_0[] = {
- OPTABLE(0x00,0xff, 1,none), /* 0x00 */
- OPTABLE(0x01,0xff,-1,none), /* 0x01 */
- OPTABLE(0x02,0xfe, 1,none), /* 0x02-0x03 */
- OPTABLE(0x04,0xee, 1,none), /* 0x04-0x05/0x14-0x15 */
- OPTABLE(0x06,0xfe, 1,none), /* 0x06-0x07 */
- OPTABLE(0x08,0xea, 1,none), /* 0x08-0x09/0x0c-0x0d/0x18-0x19/0x1c-0x1d */
- OPTABLE(0x0a,0xee, 1,none), /* 0x0a-0x0b/0x1a-0x1b */
- OPTABLE(0x0e,0xee, 1,none), /* 0x0e-0x0f/0x1e-0x1f */
- OPTABLE(0x10,0xfc, 1,none), /* 0x10-0x13 */
- OPTABLE(0x16,0xfe, 1,none), /* 0x16-0x17 */
- OPTABLE(0x20,0xe0, 1,none), /* 0x20-0x3f */
- OPTABLE(0x40,0xf0, 1,relb), /* 0x40-0x4f */
- OPTABLE(0x50,0xfc, 1,none), /* 0x50-0x53 */
- OPTABLE(0x54,0xfd, 1,ret ), /* 0x54/0x56 */
- OPTABLE(0x55,0xff, 1,relb), /* 0x55 */
- OPTABLE(0x57,0xff, 1,none), /* 0x57 */
- OPTABLE(0x58,0xfb, 2,relw), /* 0x58/0x5c */
- OPTABLE(0x59,0xfb, 1,reg ), /* 0x59/0x5b */
- OPTABLE(0x5a,0xfb, 2,jabs), /* 0x5a/0x5e */
- OPTABLE(0x5b,0xfb, 2,ind ), /* 0x5b/0x5f */
- OPTABLE(0x60,0xe8, 1,none), /* 0x60-0x67/0x70-0x77 */
- OPTABLE(0x68,0xfa, 1,none), /* 0x68-0x69/0x6c-0x6d */
- OPTABLE(0x6a,0xfe,-2,none), /* 0x6a-0x6b */
- OPTABLE(0x6e,0xfe, 2,none), /* 0x6e-0x6f */
- OPTABLE(0x78,0xff, 4,none), /* 0x78 */
- OPTABLE(0x79,0xff, 2,none), /* 0x79 */
- OPTABLE(0x7a,0xff, 3,none), /* 0x7a */
- OPTABLE(0x7b,0xff, 2,none), /* 0x7b */
- OPTABLE(0x7c,0xfc, 2,none), /* 0x7c-0x7f */
- OPTABLE(0x80,0x80, 1,none), /* 0x80-0xff */
-};
-
-static const struct optable optable_1[] = {
- OPTABLE(0x00,0xff,-3,none), /* 0x0100 */
- OPTABLE(0x40,0xf0,-3,none), /* 0x0140-0x14f */
- OPTABLE(0x80,0xf0, 1,none), /* 0x0180-0x018f */
- OPTABLE(0xc0,0xc0, 2,none), /* 0x01c0-0x01ff */
-};
-
-static const struct optable optable_2[] = {
- OPTABLE(0x00,0x20, 2,none), /* 0x6a0?/0x6a8?/0x6b0?/0x6b8? */
- OPTABLE(0x20,0x20, 3,none), /* 0x6a2?/0x6aa?/0x6b2?/0x6ba? */
-};
-
-static const struct optable optable_3[] = {
- OPTABLE(0x69,0xfb, 2,none), /* 0x010069/0x01006d/014069/0x01406d */
- OPTABLE(0x6b,0xff,-4,none), /* 0x01006b/0x01406b */
- OPTABLE(0x6f,0xff, 3,none), /* 0x01006f/0x01406f */
- OPTABLE(0x78,0xff, 5,none), /* 0x010078/0x014078 */
-};
-
-static const struct optable optable_4[] = {
- OPTABLE(0x00,0x78, 3,none), /* 0x0100690?/0x01006d0?/0140690/0x01406d0?/0x0100698?/0x01006d8?/0140698?/0x01406d8? */
- OPTABLE(0x20,0x78, 4,none), /* 0x0100692?/0x01006d2?/0140692/0x01406d2?/0x010069a?/0x01006da?/014069a?/0x01406da? */
-};
-
-static const struct optables_list {
- const struct optable *ptr;
- int size;
-} optables[] = {
-#define OPTABLES(no) \
- { \
- .ptr = optable_##no, \
- .size = sizeof(optable_##no) / sizeof(struct optable), \
- }
- OPTABLES(0),
- OPTABLES(1),
- OPTABLES(2),
- OPTABLES(3),
- OPTABLES(4),
-
-};
-
-const unsigned char condmask[] = {
- 0x00,0x40,0x01,0x04,0x02,0x08,0x10,0x20
-};
-
-static int isbranch(struct task_struct *task,int reson)
-{
- unsigned char cond = h8300_get_reg(task, PT_CCR);
- /* encode complex conditions */
- /* B4: N^V
- B5: Z|(N^V)
- B6: C|Z */
- __asm__("bld #3,%w0\n\t"
- "bxor #1,%w0\n\t"
- "bst #4,%w0\n\t"
- "bor #2,%w0\n\t"
- "bst #5,%w0\n\t"
- "bld #2,%w0\n\t"
- "bor #0,%w0\n\t"
- "bst #6,%w0\n\t"
- :"=&r"(cond)::"cc");
- cond &= condmask[reson >> 1];
- if (!(reson & 1))
- return cond == 0;
- else
- return cond != 0;
-}
-
-static unsigned short *getnextpc(struct task_struct *child, unsigned short *pc)
-{
- const struct optable *op;
- unsigned char *fetch_p;
- unsigned char inst;
- unsigned long addr;
- unsigned long *sp;
- int op_len,regno;
- op = optables[0].ptr;
- op_len = optables[0].size;
- fetch_p = (unsigned char *)pc;
- inst = *fetch_p++;
- do {
- if ((inst & op->bitmask) == op->bitpattern) {
- if (op->length < 0) {
- op = optables[-op->length].ptr;
- op_len = optables[-op->length].size + 1;
- inst = *fetch_p++;
- } else {
- switch (op->type) {
- case none:
- return pc + op->length;
- case jabs:
- addr = *(unsigned long *)pc;
- return (unsigned short *)(addr & 0x00ffffff);
- case ind:
- addr = *pc & 0xff;
- return (unsigned short *)(*(unsigned long *)addr);
- case ret:
- sp = (unsigned long *)h8300_get_reg(child, PT_USP);
- /* user stack frames
- | er0 | temporary saved
- +--------+
- | exp | exception stack frames
- +--------+
- | ret pc | userspace return address
- */
- return (unsigned short *)(*(sp+2) & 0x00ffffff);
- case reg:
- regno = (*pc >> 4) & 0x07;
- if (regno == 0)
- addr = h8300_get_reg(child, PT_ER0);
- else
- addr = h8300_get_reg(child, regno-1+PT_ER1);
- return (unsigned short *)addr;
- case relb:
- if (inst == 0x55 || isbranch(child,inst & 0x0f))
- pc = (unsigned short *)((unsigned long)pc +
- ((signed char)(*fetch_p)));
- return pc+1; /* skip myself */
- case relw:
- if (inst == 0x5c || isbranch(child,(*fetch_p & 0xf0) >> 4))
- pc = (unsigned short *)((unsigned long)pc +
- ((signed short)(*(pc+1))));
- return pc+2; /* skip myself */
- }
- }
- } else
- op++;
- } while(--op_len > 0);
- return NULL;
-}
-
-/* Set breakpoint(s) to simulate a single step from the current PC. */
-
-void user_enable_single_step(struct task_struct *child)
-{
- unsigned short *nextpc;
- nextpc = getnextpc(child,(unsigned short *)h8300_get_reg(child, PT_PC));
- child->thread.breakinfo.addr = nextpc;
- child->thread.breakinfo.inst = *nextpc;
- *nextpc = BREAKINST;
-}
-
-asmlinkage void trace_trap(unsigned long bp)
-{
- if ((unsigned long)current->thread.breakinfo.addr == bp) {
- user_disable_single_step(current);
- force_sig(SIGTRAP,current);
- } else
- force_sig(SIGILL,current);
-}
-
diff --git a/arch/h8300/platform/h8s/Makefile b/arch/h8300/platform/h8s/Makefile
deleted file mode 100644
index bf1241883766..000000000000
--- a/arch/h8300/platform/h8s/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-# Reuse any files we can from the H8S
-#
-
-obj-y := ints_h8s.o ptrace_h8s.o
diff --git a/arch/h8300/platform/h8s/edosk2674/Makefile b/arch/h8300/platform/h8s/edosk2674/Makefile
deleted file mode 100644
index 8e349723bb4f..000000000000
--- a/arch/h8300/platform/h8s/edosk2674/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-extra-y := crt0_$(MODEL).o
diff --git a/arch/h8300/platform/h8s/edosk2674/crt0_ram.S b/arch/h8300/platform/h8s/edosk2674/crt0_ram.S
deleted file mode 100644
index 5ed191b37cde..000000000000
--- a/arch/h8300/platform/h8s/edosk2674/crt0_ram.S
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * linux/arch/h8300/platform/h8s/edosk2674/crt0_ram.S
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * Platform depend startup
- * Target Archtecture: EDOSK-2674
- * Memory Layout : RAM
- */
-
-#define ASSEMBLY
-
-#include <asm/linkage.h>
-#include <asm/regs267x.h>
-
-#if !defined(CONFIG_BLKDEV_RESERVE)
-#if defined(CONFIG_GDB_DEBUG)
-#define RAMEND (__ramend - 0xc000)
-#else
-#define RAMEND __ramend
-#endif
-#else
-#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS
-#endif
-
- .global __start
- .global __command_line
- .global __platform_gpio_table
- .global __target_name
-
- .h8300s
-
- .section .text
- .file "crt0_ram.S"
-
- /* CPU Reset entry */
-__start:
- mov.l #RAMEND,sp
- ldc #0x80,ccr
- ldc #0x00,exr
-
- /* Peripheral Setup */
- bclr #4,@INTCR:8 /* interrupt mode 2 */
- bset #5,@INTCR:8
- bclr #0,@IER+1:16
- bset #1,@ISCRL+1:16 /* IRQ0 Positive Edge */
- bclr #0,@ISCRL+1:16
-
-#if defined(CONFIG_MTD_UCLINUX)
- /* move romfs image */
- jsr @__move_romfs
-#endif
-
- /* .bss clear */
- mov.l #__sbss,er5
- mov.l er5,er6
- mov.l #__ebss,er4
- sub.l er5,er4
- shlr #2,er4
- sub.l er0,er0
-1:
- mov.l er0,@er5
- adds #4,er5
- dec.l #1,er4
- bne 1b
-
- /* copy kernel commandline */
- mov.l #COMMAND_START,er5
- mov.l #_command_line,er6
- mov.w #512,r4
- eepmov.w
-
- /* uClinux kernel start */
- ldc #0x90,ccr /* running kernel */
- mov.l #_init_thread_union,sp
- add.l #0x2000,sp
- jsr @_start_kernel
-_exit:
-
- jmp _exit
-
- rts
-
- /* I/O port assign information */
-__platform_gpio_table:
- mov.l #gpio_table,er0
- rts
-
-gpio_table:
- ;; P1DDR
- ;; used,ddr
- .byte 0x00,0x00
- ;; P2DDR
- .byte 0x00,0x00
- ;; P3DDR
- .byte 0x3f,0x3a
- ;; dummy
- .byte 0x00,0x00
- ;; P5DDR
- .byte 0x00,0x00
- ;; P6DDR
- .byte 0x00,0x00
- ;; P7DDR
- .byte 0x00,0x00
- ;; P8DDR
- .byte 0x00,0x00
- ;; dummy
- .byte 0x00,0x00
- ;; PADDR
- .byte 0xff,0xff
- ;; PBDDR
- .byte 0xff,0x00
- ;; PCDDR
- .byte 0xff,0x00
- ;; PDDDR
- .byte 0xff,0x00
- ;; PEDDR
- .byte 0xff,0x00
- ;; PFDDR
- .byte 0xff,0xff
- ;; PGDDR
- .byte 0x0f,0x0f
- ;; PHDDR
- .byte 0x0f,0x0f
-
-__target_name:
- .asciz "EDOSK-2674"
-
- .section .bootvec,"ax"
- jmp @__start
diff --git a/arch/h8300/platform/h8s/edosk2674/crt0_rom.S b/arch/h8300/platform/h8s/edosk2674/crt0_rom.S
deleted file mode 100644
index 06d1d7f324ca..000000000000
--- a/arch/h8300/platform/h8s/edosk2674/crt0_rom.S
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * linux/arch/h8300/platform/h8s/edosk2674/crt0_rom.S
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * Platform depend startup
- * Target Archtecture: EDOSK-2674
- * Memory Layout : ROM
- */
-
-#define ASSEMBLY
-
-#include <asm/linkage.h>
-#include <asm/regs267x.h>
-
- .global __start
- .global __command_line
- .global __platform_gpio_table
- .global __target_name
-
- .h8300s
- .section .text
- .file "crt0_rom.S"
-
- /* CPU Reset entry */
-__start:
- mov.l #__ramend,sp
- ldc #0x80,ccr
- ldc #0,exr
-
- /* Peripheral Setup */
-;BSC/GPIO setup
- mov.l #init_regs,er0
- mov.w #0xffff,e2
-1:
- mov.w @er0+,r2
- beq 2f
- mov.w @er0+,r1
- mov.b r1l,@er2
- bra 1b
-
-2:
-;SDRAM setup
-#define SDRAM_SMR 0x400040
-
- mov.b #0,r0l
- mov.b r0l,@DRACCR:16
- mov.w #0x188,r0
- mov.w r0,@REFCR:16
- mov.w #0x85b4,r0
- mov.w r0,@DRAMCR:16
- mov.b #0,r1l
- mov.b r1l,@SDRAM_SMR
- mov.w #0x84b4,r0
- mov.w r0,@DRAMCR:16
-;special thanks to Arizona Cooperative Power
-
- /* copy .data */
- mov.l #__begin_data,er5
- mov.l #__sdata,er6
- mov.l #__edata,er4
- sub.l er6,er4
- shlr.l #2,er4
-1:
- mov.l @er5+,er0
- mov.l er0,@er6
- adds #4,er6
- dec.l #1,er4
- bne 1b
-
- /* .bss clear */
- mov.l #__sbss,er5
- mov.l #__ebss,er4
- sub.l er5,er4
- shlr.l #2,er4
- sub.l er0,er0
-1:
- mov.l er0,@er5
- adds #4,er5
- dec.l #1,er4
- bne 1b
-
- /* copy kernel commandline */
- mov.l #COMMAND_START,er5
- mov.l #__command_line,er6
- mov.w #512,r4
- eepmov.w
-
- /* linux kernel start */
- ldc #0x90,ccr /* running kernel */
- mov.l #_init_thread_union,sp
- add.l #0x2000,sp
- jsr @_start_kernel
-_exit:
-
- jmp _exit
-
- rts
-
- /* I/O port assign information */
-__platform_gpio_table:
- mov.l #gpio_table,er0
- rts
-
-#define INIT_REGS_DATA(REGS,DATA) \
- .word ((REGS) & 0xffff),DATA
-
-init_regs:
-INIT_REGS_DATA(ASTCR,0xff)
-INIT_REGS_DATA(RDNCR,0x00)
-INIT_REGS_DATA(ABWCR,0x80)
-INIT_REGS_DATA(WTCRAH,0x27)
-INIT_REGS_DATA(WTCRAL,0x77)
-INIT_REGS_DATA(WTCRBH,0x71)
-INIT_REGS_DATA(WTCRBL,0x22)
-INIT_REGS_DATA(CSACRH,0x80)
-INIT_REGS_DATA(CSACRL,0x80)
-INIT_REGS_DATA(BROMCRH,0xa0)
-INIT_REGS_DATA(BROMCRL,0xa0)
-INIT_REGS_DATA(P3DDR,0x3a)
-INIT_REGS_DATA(P3ODR,0x06)
-INIT_REGS_DATA(PADDR,0xff)
-INIT_REGS_DATA(PFDDR,0xfe)
-INIT_REGS_DATA(PGDDR,0x0f)
-INIT_REGS_DATA(PHDDR,0x0f)
-INIT_REGS_DATA(PFCR0,0xff)
-INIT_REGS_DATA(PFCR2,0x0d)
-INIT_REGS_DATA(ITSR, 0x00)
-INIT_REGS_DATA(ITSR+1,0x3f)
-INIT_REGS_DATA(INTCR,0x20)
-
- .word 0
-
-gpio_table:
- ;; P1DDR
- .byte 0x00,0x00
- ;; P2DDR
- .byte 0x00,0x00
- ;; P3DDR
- .byte 0x00,0x00
- ;; dummy
- .byte 0x00,0x00
- ;; P5DDR
- .byte 0x00,0x00
- ;; P6DDR
- .byte 0x00,0x00
- ;; P7DDR
- .byte 0x00,0x00
- ;; P8DDR
- .byte 0x00,0x00
- ;; dummy
- .byte 0x00,0x00
- ;; PADDR
- .byte 0x00,0x00
- ;; PBDDR
- .byte 0x00,0x00
- ;; PCDDR
- .byte 0x00,0x00
- ;; PDDDR
- .byte 0x00,0x00
- ;; PEDDR
- .byte 0x00,0x00
- ;; PFDDR
- .byte 0x00,0x00
- ;; PGDDR
- .byte 0x00,0x00
- ;; PHDDR
- .byte 0x00,0x00
-
- .section .rodata
-__target_name:
- .asciz "EDOSK-2674"
-
- .section .bss
-__command_line:
- .space 512
-
- /* interrupt vector */
- .section .vectors,"ax"
- .long __start
- .long __start
-vector = 2
- .rept 126
- .long _interrupt_redirect_table+vector*4
-vector = vector + 1
- .endr
diff --git a/arch/h8300/platform/h8s/generic/Makefile b/arch/h8300/platform/h8s/generic/Makefile
deleted file mode 100644
index 44b4685c664c..000000000000
--- a/arch/h8300/platform/h8s/generic/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-extra-y = crt0_$(MODEL).o
diff --git a/arch/h8300/platform/h8s/generic/crt0_ram.S b/arch/h8300/platform/h8s/generic/crt0_ram.S
deleted file mode 100644
index 7018915de74f..000000000000
--- a/arch/h8300/platform/h8s/generic/crt0_ram.S
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * linux/arch/h8300/platform/h8s/edosk2674/crt0_ram.S
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * Platform depend startup
- * Target Archtecture: generic
- * Memory Layout : RAM
- */
-
-#define ASSEMBLY
-
-#include <asm/linkage.h>
-#include <asm/regs267x.h>
-
-#if !defined(CONFIG_BLKDEV_RESERVE)
-#if defined(CONFIG_GDB_DEBUG)
-#define RAMEND (__ramend - 0xc000)
-#else
-#define RAMEND __ramend
-#endif
-#else
-#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS
-#endif
-
- .global __start
- .global __command_line
- .global __platform_gpio_table
- .global __target_name
-
- .h8300s
-
- .section .text
- .file "crt0_ram.S"
-
- /* CPU Reset entry */
-__start:
- mov.l #RAMEND,sp
- ldc #0x80,ccr
- ldc #0x00,exr
-
- /* Peripheral Setup */
- bclr #4,@INTCR:8 /* interrupt mode 2 */
- bset #5,@INTCR:8
-
-#if defined(CONFIG_MTD_UCLINUX)
- /* move romfs image */
- jsr @__move_romfs
-#endif
-
- /* .bss clear */
- mov.l #__sbss,er5
- mov.l er5,er6
- mov.l #__ebss,er4
- sub.l er5,er4
- shlr #2,er4
- sub.l er0,er0
-1:
- mov.l er0,@er5
- adds #4,er5
- dec.l #1,er4
- bne 1b
-
- /* copy kernel commandline */
- mov.l #COMMAND_START,er5
- mov.l #_command_line,er6
- mov.w #512,r4
- eepmov.w
-
- /* uClinux kernel start */
- ldc #0x90,ccr /* running kernel */
- mov.l #_init_thread_union,sp
- add.l #0x2000,sp
- jsr @_start_kernel
-_exit:
-
- jmp _exit
-
- rts
-
- /* I/O port assign information */
-__platform_gpio_table:
- mov.l #gpio_table,er0
- rts
-
-gpio_table:
- ;; P1DDR
- ;; used,ddr
- .byte 0x00,0x00
- ;; P2DDR
- .byte 0x00,0x00
- ;; P3DDR
- .byte 0x00,0x00
- ;; dummy
- .byte 0x00,0x00
- ;; P5DDR
- .byte 0x00,0x00
- ;; P6DDR
- .byte 0x00,0x00
- ;; P7DDR
- .byte 0x00,0x00
- ;; P8DDR
- .byte 0x00,0x00
- ;; dummy
- .byte 0x00,0x00
- ;; PADDR
- .byte 0x00,0x00
- ;; PBDDR
- .byte 0x00,0x00
- ;; PCDDR
- .byte 0x00,0x00
- ;; PDDDR
- .byte 0x00,0x00
- ;; PEDDR
- .byte 0x00,0x00
- ;; PFDDR
- .byte 0x00,0x00
- ;; PGDDR
- .byte 0x00,0x00
- ;; PHDDR
- .byte 0x00,0x00
-
-__target_name:
- .asciz "generic"
-
- .section .bootvec,"ax"
- jmp @__start
diff --git a/arch/h8300/platform/h8s/generic/crt0_rom.S b/arch/h8300/platform/h8s/generic/crt0_rom.S
deleted file mode 100644
index 623ba7828193..000000000000
--- a/arch/h8300/platform/h8s/generic/crt0_rom.S
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * linux/arch/h8300/platform/h8s/generic/crt0_rom.S
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * Platform depend startup
- * Target Archtecture: generic
- * Memory Layout : ROM
- */
-
-#define ASSEMBLY
-
-#include <asm/linkage.h>
-#include <asm/regs267x.h>
-
- .global __start
- .global __command_line
- .global __platform_gpio_table
- .global __target_name
-
- .h8300s
- .section .text
- .file "crt0_rom.S"
-
- /* CPU Reset entry */
-__start:
- mov.l #__ramend,sp
- ldc #0x80,ccr
- ldc #0,exr
- bclr #4,@INTCR:8
- bset #5,@INTCR:8 /* Interrupt mode 2 */
-
- /* Peripheral Setup */
-
- /* copy .data */
-#if !defined(CONFIG_H8S_SIM)
- mov.l #__begin_data,er5
- mov.l #__sdata,er6
- mov.l #__edata,er4
- sub.l er6,er4
- shlr.l #2,er4
-1:
- mov.l @er5+,er0
- mov.l er0,@er6
- adds #4,er6
- dec.l #1,er4
- bne 1b
-#endif
-
- /* .bss clear */
- mov.l #__sbss,er5
- mov.l #__ebss,er4
- sub.l er5,er4
- shlr.l #2,er4
- sub.l er0,er0
-1:
- mov.l er0,@er5
- adds #4,er5
- dec.l #1,er4
- bne 1b
-
- /* linux kernel start */
- ldc #0x90,ccr /* running kernel */
- mov.l #_init_thread_union,sp
- add.l #0x2000,sp
- jsr @_start_kernel
-_exit:
-
- jmp _exit
-
- rts
-
- /* I/O port assign information */
-__platform_gpio_table:
- mov.l #gpio_table,er0
- rts
-
-gpio_table:
- ;; P1DDR
- .byte 0x00,0x00
- ;; P2DDR
- .byte 0x00,0x00
- ;; P3DDR
- .byte 0x00,0x00
- ;; P4DDR
- .byte 0x00,0x00
- ;; P5DDR
- .byte 0x00,0x00
- ;; P6DDR
- .byte 0x00,0x00
- ;; dummy
- .byte 0x00,0x00
- ;; P8DDR
- .byte 0x00,0x00
- ;; PADDR
- .byte 0x00,0x00
- ;; PBDDR
- .byte 0x00,0x00
- ;; PCDDR
- .byte 0x00,0x00
- ;; PDDDR
- .byte 0x00,0x00
- ;; PEDDR
- .byte 0x00,0x00
- ;; PFDDR
- .byte 0x00,0x00
- ;; PGDDR
- .byte 0x00,0x00
- ;; PHDDR
- .byte 0x00,0x00
-
- .section .rodata
-__target_name:
- .asciz "generic"
-
- .section .bss
-__command_line:
- .space 512
-
- /* interrupt vector */
- .section .vectors,"ax"
- .long __start
- .long __start
-vector = 2
- .rept 126-1
- .long _interrupt_redirect_table+vector*4
-vector = vector + 1
- .endr
diff --git a/arch/h8300/platform/h8s/irq.c b/arch/h8300/platform/h8s/irq.c
deleted file mode 100644
index f3a5511c16b1..000000000000
--- a/arch/h8300/platform/h8s/irq.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * linux/arch/h8300/platform/h8s/ints_h8s.c
- * Interrupt handling CPU variants
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- */
-
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-
-#include <asm/ptrace.h>
-#include <asm/traps.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/gpio-internal.h>
-#include <asm/regs267x.h>
-
-/* saved vector list */
-const int __initconst h8300_saved_vectors[] = {
-#if defined(CONFIG_GDB_DEBUG)
- TRACE_VEC,
- TRAP3_VEC,
-#endif
- -1
-};
-
-/* trap entry table */
-const H8300_VECTOR __initconst h8300_trap_table[] = {
- 0,0,0,0,0,
- trace_break, /* TRACE */
- 0,0,
- system_call, /* TRAPA #0 */
- 0,0,0,0,0,0,0
-};
-
-/* IRQ pin assignment */
-struct irq_pins {
- unsigned char port_no;
- unsigned char bit_no;
-} __attribute__((aligned(1),packed));
-/* ISTR = 0 */
-static const struct irq_pins irq_assign_table0[16]={
- {H8300_GPIO_P5,H8300_GPIO_B0},{H8300_GPIO_P5,H8300_GPIO_B1},
- {H8300_GPIO_P5,H8300_GPIO_B2},{H8300_GPIO_P5,H8300_GPIO_B3},
- {H8300_GPIO_P5,H8300_GPIO_B4},{H8300_GPIO_P5,H8300_GPIO_B5},
- {H8300_GPIO_P5,H8300_GPIO_B6},{H8300_GPIO_P5,H8300_GPIO_B7},
- {H8300_GPIO_P6,H8300_GPIO_B0},{H8300_GPIO_P6,H8300_GPIO_B1},
- {H8300_GPIO_P6,H8300_GPIO_B2},{H8300_GPIO_P6,H8300_GPIO_B3},
- {H8300_GPIO_P6,H8300_GPIO_B4},{H8300_GPIO_P6,H8300_GPIO_B5},
- {H8300_GPIO_PF,H8300_GPIO_B1},{H8300_GPIO_PF,H8300_GPIO_B2},
-};
-/* ISTR = 1 */
-static const struct irq_pins irq_assign_table1[16]={
- {H8300_GPIO_P8,H8300_GPIO_B0},{H8300_GPIO_P8,H8300_GPIO_B1},
- {H8300_GPIO_P8,H8300_GPIO_B2},{H8300_GPIO_P8,H8300_GPIO_B3},
- {H8300_GPIO_P8,H8300_GPIO_B4},{H8300_GPIO_P8,H8300_GPIO_B5},
- {H8300_GPIO_PH,H8300_GPIO_B2},{H8300_GPIO_PH,H8300_GPIO_B3},
- {H8300_GPIO_P2,H8300_GPIO_B0},{H8300_GPIO_P2,H8300_GPIO_B1},
- {H8300_GPIO_P2,H8300_GPIO_B2},{H8300_GPIO_P2,H8300_GPIO_B3},
- {H8300_GPIO_P2,H8300_GPIO_B4},{H8300_GPIO_P2,H8300_GPIO_B5},
- {H8300_GPIO_P2,H8300_GPIO_B6},{H8300_GPIO_P2,H8300_GPIO_B7},
-};
-
-/* IRQ to GPIO pin translation */
-#define IRQ_GPIO_MAP(irqbit,irq,port,bit) \
-do { \
- if (*(volatile unsigned short *)ITSR & irqbit) { \
- port = irq_assign_table1[irq - EXT_IRQ0].port_no; \
- bit = irq_assign_table1[irq - EXT_IRQ0].bit_no; \
- } else { \
- port = irq_assign_table0[irq - EXT_IRQ0].port_no; \
- bit = irq_assign_table0[irq - EXT_IRQ0].bit_no; \
- } \
-} while(0)
-
-int h8300_enable_irq_pin(unsigned int irq)
-{
- if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) {
- unsigned short ptn = 1 << (irq - EXT_IRQ0);
- unsigned int port_no,bit_no;
- IRQ_GPIO_MAP(ptn, irq, port_no, bit_no);
- if (H8300_GPIO_RESERVE(port_no, bit_no) == 0)
- return -EBUSY; /* pin already use */
- H8300_GPIO_DDR(port_no, bit_no, H8300_GPIO_INPUT);
- *(volatile unsigned short *)ISR &= ~ptn; /* ISR clear */
- }
-
- return 0;
-}
-
-void h8300_disable_irq_pin(unsigned int irq)
-{
- if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) {
- /* disable interrupt & release IRQ pin */
- unsigned short ptn = 1 << (irq - EXT_IRQ0);
- unsigned short port_no,bit_no;
- *(volatile unsigned short *)ISR &= ~ptn;
- *(volatile unsigned short *)IER &= ~ptn;
- IRQ_GPIO_MAP(ptn, irq, port_no, bit_no);
- H8300_GPIO_FREE(port_no, bit_no);
- }
-}
diff --git a/arch/h8300/platform/h8s/ptrace_h8s.c b/arch/h8300/platform/h8s/ptrace_h8s.c
deleted file mode 100644
index c058ab1a8495..000000000000
--- a/arch/h8300/platform/h8s/ptrace_h8s.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * linux/arch/h8300/platform/h8s/ptrace_h8s.c
- * ptrace cpu depend helper functions
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * 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.
- */
-
-#include <linux/linkage.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <asm/ptrace.h>
-
-#define CCR_MASK 0x6f
-#define EXR_TRACE 0x80
-
-/* Mapping from PT_xxx to the stack offset at which the register is
- saved. Notice that usp has no stack-slot and needs to be treated
- specially (see get_reg/put_reg below). */
-static const int h8300_register_offset[] = {
- PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4),
- PT_REG(er5), PT_REG(er6), PT_REG(er0), PT_REG(orig_er0),
- PT_REG(ccr), PT_REG(pc), 0, PT_REG(exr)
-};
-
-/* read register */
-long h8300_get_reg(struct task_struct *task, int regno)
-{
- switch (regno) {
- case PT_USP:
- return task->thread.usp + sizeof(long)*2 + 2;
- case PT_CCR:
- case PT_EXR:
- return *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
- default:
- return *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]);
- }
-}
-
-/* write register */
-int h8300_put_reg(struct task_struct *task, int regno, unsigned long data)
-{
- unsigned short oldccr;
- switch (regno) {
- case PT_USP:
- task->thread.usp = data - sizeof(long)*2 - 2;
- case PT_CCR:
- oldccr = *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
- oldccr &= ~CCR_MASK;
- data &= CCR_MASK;
- data |= oldccr;
- *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
- break;
- case PT_EXR:
- /* exr modify not support */
- return -EIO;
- default:
- *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
- break;
- }
- return 0;
-}
-
-/* disable singlestep */
-void user_disable_single_step(struct task_struct *child)
-{
- *(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) &= ~EXR_TRACE;
-}
-
-/* enable singlestep */
-void user_enable_single_step(struct task_struct *child)
-{
- *(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) |= EXR_TRACE;
-}
-
-asmlinkage void trace_trap(unsigned long bp)
-{
- (void)bp;
- force_sig(SIGTRAP,current);
-}
-
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 1da17caac23c..67c3450309b7 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -53,3 +53,4 @@ generic-y += types.h
generic-y += ucontext.h
generic-y += unaligned.h
generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index a3456f34f672..f93ee087e8fe 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -3,4 +3,5 @@ generic-y += clkdev.h
generic-y += exec.h
generic-y += kvm_para.h
generic-y += trace_clock.h
+generic-y += preempt.h
generic-y += vtime.h \ No newline at end of file
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 5eb71d22c3d5..59d52e3aef12 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -882,40 +882,10 @@ __init void prefill_possible_map(void)
set_cpu_possible(i, true);
}
-static int _acpi_map_lsapic(acpi_handle handle, int *pcpu)
+static int _acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu)
{
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- union acpi_object *obj;
- struct acpi_madt_local_sapic *lsapic;
cpumask_t tmp_map;
- int cpu, physid;
-
- if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
- return -EINVAL;
-
- if (!buffer.length || !buffer.pointer)
- return -EINVAL;
-
- obj = buffer.pointer;
- if (obj->type != ACPI_TYPE_BUFFER)
- {
- kfree(buffer.pointer);
- return -EINVAL;
- }
-
- lsapic = (struct acpi_madt_local_sapic *)obj->buffer.pointer;
-
- if ((lsapic->header.type != ACPI_MADT_TYPE_LOCAL_SAPIC) ||
- (!(lsapic->lapic_flags & ACPI_MADT_ENABLED))) {
- kfree(buffer.pointer);
- return -EINVAL;
- }
-
- physid = ((lsapic->id << 8) | (lsapic->eid));
-
- kfree(buffer.pointer);
- buffer.length = ACPI_ALLOCATE_BUFFER;
- buffer.pointer = NULL;
+ int cpu;
cpumask_complement(&tmp_map, cpu_present_mask);
cpu = cpumask_first(&tmp_map);
@@ -934,9 +904,9 @@ static int _acpi_map_lsapic(acpi_handle handle, int *pcpu)
}
/* wrapper to silence section mismatch warning */
-int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu)
+int __ref acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu)
{
- return _acpi_map_lsapic(handle, pcpu);
+ return _acpi_map_lsapic(handle, physid, pcpu);
}
EXPORT_SYMBOL(acpi_map_lsapic);
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index bebdc36ebb0a..2b58c5f0bc38 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -3,3 +3,4 @@ generic-y += clkdev.h
generic-y += exec.h
generic-y += module.h
generic-y += trace_clock.h
+generic-y += preempt.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 09d77a862da3..a5d27f272a59 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -31,3 +31,4 @@ generic-y += trace_clock.h
generic-y += types.h
generic-y += word-at-a-time.h
generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/m68k/include/asm/floppy.h b/arch/m68k/include/asm/floppy.h
index 697d50393dd0..47365b1ccbec 100644
--- a/arch/m68k/include/asm/floppy.h
+++ b/arch/m68k/include/asm/floppy.h
@@ -85,7 +85,7 @@ static int fd_request_irq(void)
{
if(MACH_IS_Q40)
return request_irq(FLOPPY_IRQ, floppy_hardint,
- IRQF_DISABLED, "floppy", floppy_hardint);
+ 0, "floppy", floppy_hardint);
else if(MACH_IS_SUN3X)
return sun3xflop_request_irq();
return -ENXIO;
diff --git a/arch/m68k/include/asm/sun3xflop.h b/arch/m68k/include/asm/sun3xflop.h
index 95231e2f9d64..a02ea3a7bb20 100644
--- a/arch/m68k/include/asm/sun3xflop.h
+++ b/arch/m68k/include/asm/sun3xflop.h
@@ -207,7 +207,7 @@ static int sun3xflop_request_irq(void)
if(!once) {
once = 1;
error = request_irq(FLOPPY_IRQ, sun3xflop_hardint,
- IRQF_DISABLED, "floppy", NULL);
+ 0, "floppy", NULL);
return ((error == 0) ? 0 : -1);
} else return 0;
}
diff --git a/arch/m68k/include/asm/uaccess.h b/arch/m68k/include/asm/uaccess.h
index 639c731568b0..3fadc4a93d97 100644
--- a/arch/m68k/include/asm/uaccess.h
+++ b/arch/m68k/include/asm/uaccess.h
@@ -3,3 +3,10 @@
#else
#include <asm/uaccess_mm.h>
#endif
+
+#ifdef CONFIG_CPU_HAS_NO_UNALIGNED
+#include <asm-generic/uaccess-unaligned.h>
+#else
+#define __get_user_unaligned(x, ptr) __get_user((x), (ptr))
+#define __put_user_unaligned(x, ptr) __put_user((x), (ptr))
+#endif
diff --git a/arch/m68k/platform/68000/timers.c b/arch/m68k/platform/68000/timers.c
index ec30acbfe6db..99a98698bc95 100644
--- a/arch/m68k/platform/68000/timers.c
+++ b/arch/m68k/platform/68000/timers.c
@@ -70,7 +70,7 @@ static irqreturn_t hw_tick(int irq, void *dummy)
static struct irqaction m68328_timer_irq = {
.name = "timer",
- .flags = IRQF_DISABLED | IRQF_TIMER,
+ .flags = IRQF_TIMER,
.handler = hw_tick,
};
diff --git a/arch/m68k/platform/68360/config.c b/arch/m68k/platform/68360/config.c
index 0570741e5500..d493ac43fe3f 100644
--- a/arch/m68k/platform/68360/config.c
+++ b/arch/m68k/platform/68360/config.c
@@ -59,7 +59,7 @@ static irqreturn_t hw_tick(int irq, void *dummy)
static struct irqaction m68360_timer_irq = {
.name = "timer",
- .flags = IRQF_DISABLED | IRQF_TIMER,
+ .flags = IRQF_TIMER,
.handler = hw_tick,
};
diff --git a/arch/m68k/platform/coldfire/pit.c b/arch/m68k/platform/coldfire/pit.c
index e8f3b97b0f77..493b3111d4c1 100644
--- a/arch/m68k/platform/coldfire/pit.c
+++ b/arch/m68k/platform/coldfire/pit.c
@@ -118,7 +118,7 @@ static irqreturn_t pit_tick(int irq, void *dummy)
static struct irqaction pit_irq = {
.name = "timer",
- .flags = IRQF_DISABLED | IRQF_TIMER,
+ .flags = IRQF_TIMER,
.handler = pit_tick,
};
diff --git a/arch/m68k/platform/coldfire/sltimers.c b/arch/m68k/platform/coldfire/sltimers.c
index bb5a25ada848..831a08cf6f40 100644
--- a/arch/m68k/platform/coldfire/sltimers.c
+++ b/arch/m68k/platform/coldfire/sltimers.c
@@ -51,7 +51,7 @@ irqreturn_t mcfslt_profile_tick(int irq, void *dummy)
static struct irqaction mcfslt_profile_irq = {
.name = "profile timer",
- .flags = IRQF_DISABLED | IRQF_TIMER,
+ .flags = IRQF_TIMER,
.handler = mcfslt_profile_tick,
};
@@ -93,7 +93,7 @@ static irqreturn_t mcfslt_tick(int irq, void *dummy)
static struct irqaction mcfslt_timer_irq = {
.name = "timer",
- .flags = IRQF_DISABLED | IRQF_TIMER,
+ .flags = IRQF_TIMER,
.handler = mcfslt_tick,
};
diff --git a/arch/m68k/platform/coldfire/timers.c b/arch/m68k/platform/coldfire/timers.c
index d06068e45764..cd496a20fcc7 100644
--- a/arch/m68k/platform/coldfire/timers.c
+++ b/arch/m68k/platform/coldfire/timers.c
@@ -83,7 +83,7 @@ static irqreturn_t mcftmr_tick(int irq, void *dummy)
static struct irqaction mcftmr_timer_irq = {
.name = "timer",
- .flags = IRQF_DISABLED | IRQF_TIMER,
+ .flags = IRQF_TIMER,
.handler = mcftmr_tick,
};
@@ -171,7 +171,7 @@ irqreturn_t coldfire_profile_tick(int irq, void *dummy)
static struct irqaction coldfire_profile_irq = {
.name = "profile timer",
- .flags = IRQF_DISABLED | IRQF_TIMER,
+ .flags = IRQF_TIMER,
.handler = coldfire_profile_tick,
};
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 6ae0ccb632cb..84d0c1d6b9b3 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -52,3 +52,4 @@ generic-y += unaligned.h
generic-y += user.h
generic-y += vga.h
generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/metag/include/asm/topology.h b/arch/metag/include/asm/topology.h
index 23f5118f58db..8e9c0b3b9691 100644
--- a/arch/metag/include/asm/topology.h
+++ b/arch/metag/include/asm/topology.h
@@ -26,6 +26,8 @@
.last_balance = jiffies, \
.balance_interval = 1, \
.nr_balance_failed = 0, \
+ .max_newidle_lb_cost = 0, \
+ .next_decay_max_lb_cost = jiffies, \
}
#define cpu_to_node(cpu) ((void)(cpu), 0)
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index d3c51a6a601d..ce0bbf8f5640 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -3,3 +3,4 @@ generic-y += clkdev.h
generic-y += exec.h
generic-y += trace_clock.h
generic-y += syscalls.h
+generic-y += preempt.h
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index d9d81c219253..6e239123d6fe 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -20,7 +20,6 @@ platforms += mti-sead3
platforms += netlogic
platforms += pmcs-msp71xx
platforms += pnx833x
-platforms += powertv
platforms += ralink
platforms += rb532
platforms += sgi-ip22
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index f75ab4a2f246..17cc7ff8458c 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -8,6 +8,7 @@ config MIPS
select HAVE_PERF_EVENTS
select PERF_USE_VMALLOC
select HAVE_ARCH_KGDB
+ select HAVE_ARCH_TRACEHOOK
select ARCH_HAVE_CUSTOM_GPIO_H
select HAVE_FUNCTION_TRACER
select HAVE_FUNCTION_TRACE_MCOUNT_TEST
@@ -18,6 +19,7 @@ config MIPS
select HAVE_KPROBES
select HAVE_KRETPROBES
select HAVE_DEBUG_KMEMLEAK
+ select HAVE_SYSCALL_TRACEPOINTS
select ARCH_BINFMT_ELF_RANDOMIZE_PIE
select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES && 64BIT
select RTC_LIB if !MACH_LOONGSON
@@ -146,6 +148,7 @@ config MIPS_COBALT
select CSRC_R4K
select CEVT_GT641XX
select DMA_NONCOHERENT
+ select EARLY_PRINTK_8250 if EARLY_PRINTK
select HW_HAS_PCI
select I8253
select I8259
@@ -412,23 +415,6 @@ config PMC_MSP
of integrated peripherals, interfaces and DSPs in addition to
a variety of MIPS cores.
-config POWERTV
- bool "Cisco PowerTV"
- select BOOT_ELF32
- select CEVT_R4K
- select CPU_MIPSR2_IRQ_VI
- select CPU_MIPSR2_IRQ_EI
- select CSRC_POWERTV
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select SYS_HAS_CPU_MIPS32_R2
- select SYS_SUPPORTS_32BIT_KERNEL
- select SYS_SUPPORTS_BIG_ENDIAN
- select SYS_SUPPORTS_HIGHMEM
- select USB_OHCI_LITTLE_ENDIAN
- help
- This enables support for the Cisco PowerTV Platform.
-
config RALINK
bool "Ralink based machines"
select CEVT_R4K
@@ -811,7 +797,6 @@ source "arch/mips/jz4740/Kconfig"
source "arch/mips/lantiq/Kconfig"
source "arch/mips/lasat/Kconfig"
source "arch/mips/pmcs-msp71xx/Kconfig"
-source "arch/mips/powertv/Kconfig"
source "arch/mips/ralink/Kconfig"
source "arch/mips/sgi-ip27/Kconfig"
source "arch/mips/sibyte/Kconfig"
@@ -890,9 +875,6 @@ config CSRC_BCM1480
config CSRC_IOASIC
bool
-config CSRC_POWERTV
- bool
-
config CSRC_R4K
bool
@@ -1489,8 +1471,10 @@ config SYS_SUPPORTS_ZBOOT
bool
select HAVE_KERNEL_GZIP
select HAVE_KERNEL_BZIP2
+ select HAVE_KERNEL_LZ4
select HAVE_KERNEL_LZMA
select HAVE_KERNEL_LZO
+ select HAVE_KERNEL_XZ
config SYS_SUPPORTS_ZBOOT_UART16550
bool
@@ -1977,6 +1961,7 @@ config MIPS_VPE_APSP_API
config MIPS_CMP
bool "MIPS CMP framework support"
depends on SYS_SUPPORTS_MIPS_CMP
+ select SMP
select SYNC_R4K
select SYS_SUPPORTS_SMP
select SYS_SUPPORTS_SCHED_SMT if SMP
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index 37871f0de15e..b147e7038ff0 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -20,6 +20,14 @@ config EARLY_PRINTK
doesn't cooperate with an X server. You should normally say N here,
unless you want to debug such a crash.
+config EARLY_PRINTK_8250
+ bool "8250/16550 and compatible serial early printk driver"
+ depends on EARLY_PRINTK
+ default n
+ help
+ If you say Y here, it will be possible to use a 8250/16550 serial
+ port as the boot console.
+
config CMDLINE_BOOL
bool "Built-in kernel command line"
default n
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index ca8f8340d75f..de300b993607 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -285,15 +285,19 @@ endif
# Other need ECOFF, so we build a 32-bit ELF binary for them which we then
# convert to ECOFF using elf2ecoff.
#
+quiet_cmd_32 = OBJCOPY $@
+ cmd_32 = $(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@
vmlinux.32: vmlinux
- $(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@
+ $(call cmd,32)
#
# The 64-bit ELF tools are pretty broken so at this time we generate 64-bit
# ELF files from 32-bit files by conversion.
#
+quiet_cmd_64 = OBJCOPY $@
+ cmd_64 = $(OBJCOPY) -O $(64bit-bfd) $(OBJCOPYFLAGS) $< $@
vmlinux.64: vmlinux
- $(OBJCOPY) -O $(64bit-bfd) $(OBJCOPYFLAGS) $< $@
+ $(call cmd,64)
all: $(all-y)
@@ -302,10 +306,16 @@ $(boot-y): $(vmlinux-32) FORCE
$(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) \
$(bootvars-y) arch/mips/boot/$@
+ifdef CONFIG_SYS_SUPPORTS_ZBOOT
# boot/compressed
$(bootz-y): $(vmlinux-32) FORCE
$(Q)$(MAKE) $(build)=arch/mips/boot/compressed \
$(bootvars-y) 32bit-bfd=$(32bit-bfd) $@
+else
+vmlinuz: FORCE
+ @echo ' CONFIG_SYS_SUPPORTS_ZBOOT is not enabled'
+ /bin/false
+endif
CLEAN_FILES += vmlinux.32 vmlinux.64
diff --git a/arch/mips/alchemy/devboards/db1235.c b/arch/mips/alchemy/devboards/db1235.c
index c76a90f78664..bac19dc43d1d 100644
--- a/arch/mips/alchemy/devboards/db1235.c
+++ b/arch/mips/alchemy/devboards/db1235.c
@@ -59,7 +59,7 @@ void __init board_setup(void)
ret = -ENODEV;
}
if (ret)
- panic("cannot initialize board support\n");
+ panic("cannot initialize board support");
}
int __init db1235_arch_init(void)
diff --git a/arch/mips/ath79/dev-common.c b/arch/mips/ath79/dev-common.c
index c3b04c929f29..516225d207ee 100644
--- a/arch/mips/ath79/dev-common.c
+++ b/arch/mips/ath79/dev-common.c
@@ -20,7 +20,6 @@
#include <asm/mach-ath79/ath79.h>
#include <asm/mach-ath79/ar71xx_regs.h>
-#include <asm/mach-ath79/ar933x_uart_platform.h>
#include "common.h"
#include "dev-common.h"
@@ -68,15 +67,11 @@ static struct resource ar933x_uart_resources[] = {
},
};
-static struct ar933x_uart_platform_data ar933x_uart_data;
static struct platform_device ar933x_uart_device = {
.name = "ar933x-uart",
.id = -1,
.resource = ar933x_uart_resources,
.num_resources = ARRAY_SIZE(ar933x_uart_resources),
- .dev = {
- .platform_data = &ar933x_uart_data,
- },
};
void __init ath79_register_uart(void)
@@ -93,7 +88,6 @@ void __init ath79_register_uart(void)
ath79_uart_data[0].uartclk = uart_clk_rate;
platform_device_register(&ath79_uart_device);
} else if (soc_is_ar933x()) {
- ar933x_uart_data.uartclk = uart_clk_rate;
platform_device_register(&ar933x_uart_device);
} else {
BUG();
diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile
index f3bf6d5bfb9d..c52daf9b05c6 100644
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -4,4 +4,5 @@
#
obj-y += irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
+obj-y += board.o
obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o
diff --git a/arch/mips/bcm47xx/board.c b/arch/mips/bcm47xx/board.c
new file mode 100644
index 000000000000..f3f6bfe68a2a
--- /dev/null
+++ b/arch/mips/bcm47xx/board.c
@@ -0,0 +1,309 @@
+#include <linux/export.h>
+#include <linux/string.h>
+#include <bcm47xx_board.h>
+#include <bcm47xx_nvram.h>
+
+struct bcm47xx_board_type {
+ const enum bcm47xx_board board;
+ const char *name;
+};
+
+struct bcm47xx_board_type_list1 {
+ struct bcm47xx_board_type board;
+ const char *value1;
+};
+
+struct bcm47xx_board_type_list2 {
+ struct bcm47xx_board_type board;
+ const char *value1;
+ const char *value2;
+};
+
+struct bcm47xx_board_type_list3 {
+ struct bcm47xx_board_type board;
+ const char *value1;
+ const char *value2;
+ const char *value3;
+};
+
+struct bcm47xx_board_store {
+ enum bcm47xx_board board;
+ char name[BCM47XX_BOARD_MAX_NAME];
+};
+
+/* model_name */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_model_name[] __initconst = {
+ {{BCM47XX_BOARD_DLINK_DIR130, "D-Link DIR-130"}, "DIR-130"},
+ {{BCM47XX_BOARD_DLINK_DIR330, "D-Link DIR-330"}, "DIR-330"},
+ { {0}, 0},
+};
+
+/* model_no */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_model_no[] __initconst = {
+ {{BCM47XX_BOARD_ASUS_WL700GE, "Asus WL700"}, "WL700"},
+ { {0}, 0},
+};
+
+/* machine_name */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_machine_name[] __initconst = {
+ {{BCM47XX_BOARD_LINKSYS_WRTSL54GS, "Linksys WRTSL54GS"}, "WRTSL54GS"},
+ { {0}, 0},
+};
+
+/* hardware_version */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_hardware_version[] __initconst = {
+ {{BCM47XX_BOARD_ASUS_RTN16, "Asus RT-N16"}, "RT-N16-"},
+ {{BCM47XX_BOARD_ASUS_WL320GE, "Asus WL320GE"}, "WL320G-"},
+ {{BCM47XX_BOARD_ASUS_WL330GE, "Asus WL330GE"}, "WL330GE-"},
+ {{BCM47XX_BOARD_ASUS_WL500GD, "Asus WL500GD"}, "WL500gd-"},
+ {{BCM47XX_BOARD_ASUS_WL500GPV1, "Asus WL500GP V1"}, "WL500gp-"},
+ {{BCM47XX_BOARD_ASUS_WL500GPV2, "Asus WL500GP V2"}, "WL500GPV2-"},
+ {{BCM47XX_BOARD_ASUS_WL500W, "Asus WL500W"}, "WL500gW-"},
+ {{BCM47XX_BOARD_ASUS_WL520GC, "Asus WL520GC"}, "WL520GC-"},
+ {{BCM47XX_BOARD_ASUS_WL520GU, "Asus WL520GU"}, "WL520GU-"},
+ {{BCM47XX_BOARD_BELKIN_F7D4301, "Belkin F7D4301"}, "F7D4301"},
+ { {0}, 0},
+};
+
+/* productid */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_productid[] __initconst = {
+ {{BCM47XX_BOARD_ASUS_RTAC66U, "Asus RT-AC66U"}, "RT-AC66U"},
+ {{BCM47XX_BOARD_ASUS_RTN10, "Asus RT-N10"}, "RT-N10"},
+ {{BCM47XX_BOARD_ASUS_RTN10D, "Asus RT-N10D"}, "RT-N10D"},
+ {{BCM47XX_BOARD_ASUS_RTN10U, "Asus RT-N10U"}, "RT-N10U"},
+ {{BCM47XX_BOARD_ASUS_RTN12, "Asus RT-N12"}, "RT-N12"},
+ {{BCM47XX_BOARD_ASUS_RTN12B1, "Asus RT-N12B1"}, "RT-N12B1"},
+ {{BCM47XX_BOARD_ASUS_RTN12C1, "Asus RT-N12C1"}, "RT-N12C1"},
+ {{BCM47XX_BOARD_ASUS_RTN12D1, "Asus RT-N12D1"}, "RT-N12D1"},
+ {{BCM47XX_BOARD_ASUS_RTN12HP, "Asus RT-N12HP"}, "RT-N12HP"},
+ {{BCM47XX_BOARD_ASUS_RTN15U, "Asus RT-N15U"}, "RT-N15U"},
+ {{BCM47XX_BOARD_ASUS_RTN16, "Asus RT-N16"}, "RT-N16"},
+ {{BCM47XX_BOARD_ASUS_RTN53, "Asus RT-N53"}, "RT-N53"},
+ {{BCM47XX_BOARD_ASUS_RTN66U, "Asus RT-N66U"}, "RT-N66U"},
+ {{BCM47XX_BOARD_ASUS_WL300G, "Asus WL300G"}, "WL300g"},
+ {{BCM47XX_BOARD_ASUS_WLHDD, "Asus WLHDD"}, "WLHDD"},
+ { {0}, 0},
+};
+
+/* ModelId */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_ModelId[] __initconst = {
+ {{BCM47XX_BOARD_DELL_TM2300, "Dell WX-5565"}, "WX-5565"},
+ {{BCM47XX_BOARD_MOTOROLA_WE800G, "Motorola WE800G"}, "WE800G"},
+ {{BCM47XX_BOARD_MOTOROLA_WR850GP, "Motorola WR850GP"}, "WR850GP"},
+ {{BCM47XX_BOARD_MOTOROLA_WR850GV2V3, "Motorola WR850G"}, "WR850G"},
+ { {0}, 0},
+};
+
+/* melco_id or buf1falo_id */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_melco_id[] __initconst = {
+ {{BCM47XX_BOARD_BUFFALO_WBR2_G54, "Buffalo WBR2-G54"}, "29bb0332"},
+ {{BCM47XX_BOARD_BUFFALO_WHR2_A54G54, "Buffalo WHR2-A54G54"}, "290441dd"},
+ {{BCM47XX_BOARD_BUFFALO_WHR_G125, "Buffalo WHR-G125"}, "32093"},
+ {{BCM47XX_BOARD_BUFFALO_WHR_G54S, "Buffalo WHR-G54S"}, "30182"},
+ {{BCM47XX_BOARD_BUFFALO_WHR_HP_G54, "Buffalo WHR-HP-G54"}, "30189"},
+ {{BCM47XX_BOARD_BUFFALO_WLA2_G54L, "Buffalo WLA2-G54L"}, "29129"},
+ {{BCM47XX_BOARD_BUFFALO_WZR_G300N, "Buffalo WZR-G300N"}, "31120"},
+ {{BCM47XX_BOARD_BUFFALO_WZR_RS_G54, "Buffalo WZR-RS-G54"}, "30083"},
+ {{BCM47XX_BOARD_BUFFALO_WZR_RS_G54HP, "Buffalo WZR-RS-G54HP"}, "30103"},
+ { {0}, 0},
+};
+
+/* boot_hw_model, boot_hw_ver */
+static const
+struct bcm47xx_board_type_list2 bcm47xx_board_list_boot_hw[] __initconst = {
+ /* like WRT160N v3.0 */
+ {{BCM47XX_BOARD_CISCO_M10V1, "Cisco M10"}, "M10", "1.0"},
+ /* like WRT310N v2.0 */
+ {{BCM47XX_BOARD_CISCO_M20V1, "Cisco M20"}, "M20", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_E900V1, "Linksys E900 V1"}, "E900", "1.0"},
+ /* like WRT160N v3.0 */
+ {{BCM47XX_BOARD_LINKSYS_E1000V1, "Linksys E1000 V1"}, "E100", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_E1000V2, "Linksys E1000 V2"}, "E1000", "2.0"},
+ {{BCM47XX_BOARD_LINKSYS_E1000V21, "Linksys E1000 V2.1"}, "E1000", "2.1"},
+ {{BCM47XX_BOARD_LINKSYS_E1200V2, "Linksys E1200 V2"}, "E1200", "2.0"},
+ {{BCM47XX_BOARD_LINKSYS_E2000V1, "Linksys E2000 V1"}, "Linksys E2000", "1.0"},
+ /* like WRT610N v2.0 */
+ {{BCM47XX_BOARD_LINKSYS_E3000V1, "Linksys E3000 V1"}, "E300", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_E3200V1, "Linksys E3200 V1"}, "E3200", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_E4200V1, "Linksys E4200 V1"}, "E4200", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_WRT150NV11, "Linksys WRT150N V1.1"}, "WRT150N", "1.1"},
+ {{BCM47XX_BOARD_LINKSYS_WRT150NV1, "Linksys WRT150N V1"}, "WRT150N", "1"},
+ {{BCM47XX_BOARD_LINKSYS_WRT160NV1, "Linksys WRT160N V1"}, "WRT160N", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_WRT160NV3, "Linksys WRT160N V3"}, "WRT160N", "3.0"},
+ {{BCM47XX_BOARD_LINKSYS_WRT300NV11, "Linksys WRT300N V1.1"}, "WRT300N", "1.1"},
+ {{BCM47XX_BOARD_LINKSYS_WRT310NV1, "Linksys WRT310N V1"}, "WRT310N", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_WRT310NV2, "Linksys WRT310N V2"}, "WRT310N", "2.0"},
+ {{BCM47XX_BOARD_LINKSYS_WRT54G3GV2, "Linksys WRT54G3GV2-VF"}, "WRT54G3GV2-VF", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_WRT610NV1, "Linksys WRT610N V1"}, "WRT610N", "1.0"},
+ {{BCM47XX_BOARD_LINKSYS_WRT610NV2, "Linksys WRT610N V2"}, "WRT610N", "2.0"},
+ { {0}, 0},
+};
+
+/* board_id */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_board_id[] __initconst = {
+ {{BCM47XX_BOARD_NETGEAR_WGR614V8, "Netgear WGR614 V8"}, "U12H072T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WGR614V9, "Netgear WGR614 V9"}, "U12H094T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNDR3300, "Netgear WNDR3300"}, "U12H093T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNDR3400V1, "Netgear WNDR3400 V1"}, "U12H155T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNDR3400V2, "Netgear WNDR3400 V2"}, "U12H187T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNDR3400VCNA, "Netgear WNDR3400 Vcna"}, "U12H155T01_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNDR3700V3, "Netgear WNDR3700 V3"}, "U12H194T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNDR4000, "Netgear WNDR4000"}, "U12H181T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNDR4500V1, "Netgear WNDR4500 V1"}, "U12H189T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNDR4500V2, "Netgear WNDR4500 V2"}, "U12H224T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNR2000, "Netgear WNR2000"}, "U12H114T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNR3500L, "Netgear WNR3500L"}, "U12H136T99_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNR3500U, "Netgear WNR3500U"}, "U12H136T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNR3500V2, "Netgear WNR3500 V2"}, "U12H127T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNR3500V2VC, "Netgear WNR3500 V2vc"}, "U12H127T70_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNR834BV2, "Netgear WNR834B V2"}, "U12H081T00_NETGEAR"},
+ { {0}, 0},
+};
+
+/* boardtype, boardnum, boardrev */
+static const
+struct bcm47xx_board_type_list3 bcm47xx_board_list_board[] __initconst = {
+ {{BCM47XX_BOARD_HUAWEI_E970, "Huawei E970"}, "0x048e", "0x5347", "0x11"},
+ {{BCM47XX_BOARD_PHICOMM_M1, "Phicomm M1"}, "0x0590", "80", "0x1104"},
+ {{BCM47XX_BOARD_ZTE_H218N, "ZTE H218N"}, "0x053d", "1234", "0x1305"},
+ { {0}, 0},
+};
+
+static const
+struct bcm47xx_board_type bcm47xx_board_unknown[] __initconst = {
+ {BCM47XX_BOARD_UNKNOWN, "Unknown Board"},
+};
+
+static struct bcm47xx_board_store bcm47xx_board = {BCM47XX_BOARD_NO, "Unknown Board"};
+
+static __init const struct bcm47xx_board_type *bcm47xx_board_get_nvram(void)
+{
+ char buf1[30];
+ char buf2[30];
+ char buf3[30];
+ const struct bcm47xx_board_type_list1 *e1;
+ const struct bcm47xx_board_type_list2 *e2;
+ const struct bcm47xx_board_type_list3 *e3;
+
+ if (bcm47xx_nvram_getenv("model_name", buf1, sizeof(buf1)) >= 0) {
+ for (e1 = bcm47xx_board_list_model_name; e1->value1; e1++) {
+ if (!strcmp(buf1, e1->value1))
+ return &e1->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("model_no", buf1, sizeof(buf1)) >= 0) {
+ for (e1 = bcm47xx_board_list_model_no; e1->value1; e1++) {
+ if (strstarts(buf1, e1->value1))
+ return &e1->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("machine_name", buf1, sizeof(buf1)) >= 0) {
+ for (e1 = bcm47xx_board_list_machine_name; e1->value1; e1++) {
+ if (strstarts(buf1, e1->value1))
+ return &e1->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("hardware_version", buf1, sizeof(buf1)) >= 0) {
+ for (e1 = bcm47xx_board_list_hardware_version; e1->value1; e1++) {
+ if (strstarts(buf1, e1->value1))
+ return &e1->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("productid", buf1, sizeof(buf1)) >= 0) {
+ for (e1 = bcm47xx_board_list_productid; e1->value1; e1++) {
+ if (!strcmp(buf1, e1->value1))
+ return &e1->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("ModelId", buf1, sizeof(buf1)) >= 0) {
+ for (e1 = bcm47xx_board_list_ModelId; e1->value1; e1++) {
+ if (!strcmp(buf1, e1->value1))
+ return &e1->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("melco_id", buf1, sizeof(buf1)) >= 0 ||
+ bcm47xx_nvram_getenv("buf1falo_id", buf1, sizeof(buf1)) >= 0) {
+ /* buffalo hardware, check id for specific hardware matches */
+ for (e1 = bcm47xx_board_list_melco_id; e1->value1; e1++) {
+ if (!strcmp(buf1, e1->value1))
+ return &e1->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("boot_hw_model", buf1, sizeof(buf1)) >= 0 &&
+ bcm47xx_nvram_getenv("boot_hw_ver", buf2, sizeof(buf2)) >= 0) {
+ for (e2 = bcm47xx_board_list_boot_hw; e2->value1; e2++) {
+ if (!strcmp(buf1, e2->value1) &&
+ !strcmp(buf2, e2->value2))
+ return &e2->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("board_id", buf1, sizeof(buf1)) >= 0) {
+ for (e1 = bcm47xx_board_list_board_id; e1->value1; e1++) {
+ if (!strcmp(buf1, e1->value1))
+ return &e1->board;
+ }
+ }
+
+ if (bcm47xx_nvram_getenv("boardtype", buf1, sizeof(buf1)) >= 0 &&
+ bcm47xx_nvram_getenv("boardnum", buf2, sizeof(buf2)) >= 0 &&
+ bcm47xx_nvram_getenv("boardrev", buf3, sizeof(buf3)) >= 0) {
+ for (e3 = bcm47xx_board_list_board; e3->value1; e3++) {
+ if (!strcmp(buf1, e3->value1) &&
+ !strcmp(buf2, e3->value2) &&
+ !strcmp(buf3, e3->value3))
+ return &e3->board;
+ }
+ }
+ return bcm47xx_board_unknown;
+}
+
+void __init bcm47xx_board_detect(void)
+{
+ int err;
+ char buf[10];
+ const struct bcm47xx_board_type *board_detected;
+
+ if (bcm47xx_board.board != BCM47XX_BOARD_NO)
+ return;
+
+ /* check if the nvram is available */
+ err = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf));
+
+ /* init of nvram failed, probably too early now */
+ if (err == -ENXIO) {
+ return;
+ }
+
+ board_detected = bcm47xx_board_get_nvram();
+ bcm47xx_board.board = board_detected->board;
+ strlcpy(bcm47xx_board.name, board_detected->name,
+ BCM47XX_BOARD_MAX_NAME);
+}
+
+enum bcm47xx_board bcm47xx_board_get(void)
+{
+ return bcm47xx_board.board;
+}
+EXPORT_SYMBOL(bcm47xx_board_get);
+
+const char *bcm47xx_board_get_name(void)
+{
+ return bcm47xx_board.name;
+}
+EXPORT_SYMBOL(bcm47xx_board_get_name);
diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c
index cc40b74940f5..b4c585b1c62e 100644
--- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c
@@ -190,3 +190,23 @@ int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len)
return -ENOENT;
}
EXPORT_SYMBOL(bcm47xx_nvram_getenv);
+
+int bcm47xx_nvram_gpio_pin(const char *name)
+{
+ int i, err;
+ char nvram_var[10];
+ char buf[30];
+
+ for (i = 0; i < 16; i++) {
+ err = snprintf(nvram_var, sizeof(nvram_var), "gpio%i", i);
+ if (err <= 0)
+ continue;
+ err = bcm47xx_nvram_getenv(nvram_var, buf, sizeof(buf));
+ if (err <= 0)
+ continue;
+ if (!strcmp(name, buf))
+ return i;
+ }
+ return -ENOENT;
+}
+EXPORT_SYMBOL(bcm47xx_nvram_gpio_pin);
diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c
index 8c155afb1299..5cba318bc1cd 100644
--- a/arch/mips/bcm47xx/prom.c
+++ b/arch/mips/bcm47xx/prom.c
@@ -32,12 +32,37 @@
#include <asm/bootinfo.h>
#include <asm/fw/cfe/cfe_api.h>
#include <asm/fw/cfe/cfe_error.h>
+#include <bcm47xx.h>
+#include <bcm47xx_board.h>
static int cfe_cons_handle;
+static u16 get_chip_id(void)
+{
+ switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+ case BCM47XX_BUS_TYPE_SSB:
+ return bcm47xx_bus.ssb.chip_id;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+ case BCM47XX_BUS_TYPE_BCMA:
+ return bcm47xx_bus.bcma.bus.chipinfo.id;
+#endif
+ }
+ return 0;
+}
+
const char *get_system_type(void)
{
- return "Broadcom BCM47XX";
+ static char buf[50];
+ u16 chip_id = get_chip_id();
+
+ snprintf(buf, sizeof(buf),
+ (chip_id > 0x9999) ? "Broadcom BCM%d (%s)" :
+ "Broadcom BCM%04X (%s)",
+ chip_id, bcm47xx_board_get_name());
+
+ return buf;
}
void prom_putchar(char c)
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index b2246cd9ca12..1f30571968e7 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -36,6 +36,7 @@
#include <asm/time.h>
#include <bcm47xx.h>
#include <bcm47xx_nvram.h>
+#include <bcm47xx_board.h>
union bcm47xx_bus bcm47xx_bus;
EXPORT_SYMBOL(bcm47xx_bus);
@@ -221,6 +222,7 @@ void __init plat_mem_setup(void)
_machine_restart = bcm47xx_machine_restart;
_machine_halt = bcm47xx_machine_halt;
pm_power_off = bcm47xx_machine_halt;
+ bcm47xx_board_detect();
}
static int __init bcm47xx_register_bus_complete(void)
diff --git a/arch/mips/bcm47xx/time.c b/arch/mips/bcm47xx/time.c
index 536374dcba78..2c85d9254b5e 100644
--- a/arch/mips/bcm47xx/time.c
+++ b/arch/mips/bcm47xx/time.c
@@ -27,10 +27,16 @@
#include <linux/ssb/ssb.h>
#include <asm/time.h>
#include <bcm47xx.h>
+#include <bcm47xx_nvram.h>
+#include <bcm47xx_board.h>
void __init plat_time_init(void)
{
unsigned long hz = 0;
+ u16 chip_id = 0;
+ char buf[10];
+ int len;
+ enum bcm47xx_board board = bcm47xx_board_get();
/*
* Use deterministic values for initial counter interrupt
@@ -43,15 +49,32 @@ void __init plat_time_init(void)
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2;
+ chip_id = bcm47xx_bus.ssb.chip_id;
break;
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
hz = bcma_cpu_clock(&bcm47xx_bus.bcma.bus.drv_mips) / 2;
+ chip_id = bcm47xx_bus.bcma.bus.chipinfo.id;
break;
#endif
}
+ if (chip_id == 0x5354) {
+ len = bcm47xx_nvram_getenv("clkfreq", buf, sizeof(buf));
+ if (len >= 0 && !strncmp(buf, "200", 4))
+ hz = 100000000;
+ }
+
+ switch (board) {
+ case BCM47XX_BOARD_ASUS_WL520GC:
+ case BCM47XX_BOARD_ASUS_WL520GU:
+ hz = 100000000;
+ break;
+ default:
+ break;
+ }
+
if (!hz)
hz = 100000000;
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index 0048c0897896..ca0c343c9ea5 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -37,6 +37,10 @@ vmlinuzobjs-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART16550) += $(obj)/uart-16550.o
vmlinuzobjs-$(CONFIG_MIPS_ALCHEMY) += $(obj)/uart-alchemy.o
endif
+ifdef CONFIG_KERNEL_XZ
+vmlinuzobjs-y += $(obj)/../../lib/ashldi3.o
+endif
+
targets += vmlinux.bin
OBJCOPYFLAGS_vmlinux.bin := $(OBJCOPYFLAGS) -O binary -R .comment -S
$(obj)/vmlinux.bin: $(KBUILD_IMAGE) FORCE
@@ -44,8 +48,10 @@ $(obj)/vmlinux.bin: $(KBUILD_IMAGE) FORCE
tool_$(CONFIG_KERNEL_GZIP) = gzip
tool_$(CONFIG_KERNEL_BZIP2) = bzip2
+tool_$(CONFIG_KERNEL_LZ4) = lz4
tool_$(CONFIG_KERNEL_LZMA) = lzma
tool_$(CONFIG_KERNEL_LZO) = lzo
+tool_$(CONFIG_KERNEL_XZ) = xzkern
targets += vmlinux.bin.z
$(obj)/vmlinux.bin.z: $(obj)/vmlinux.bin FORCE
diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c
index 2c9573098c0d..a8c6fd6a4406 100644
--- a/arch/mips/boot/compressed/decompress.c
+++ b/arch/mips/boot/compressed/decompress.c
@@ -43,7 +43,8 @@ void error(char *x)
/* activate the code for pre-boot environment */
#define STATIC static
-#ifdef CONFIG_KERNEL_GZIP
+#if defined(CONFIG_KERNEL_GZIP) || defined(CONFIG_KERNEL_XZ) || \
+ defined(CONFIG_KERNEL_LZ4)
void *memcpy(void *dest, const void *src, size_t n)
{
int i;
@@ -54,6 +55,8 @@ void *memcpy(void *dest, const void *src, size_t n)
d[i] = s[i];
return dest;
}
+#endif
+#ifdef CONFIG_KERNEL_GZIP
#include "../../../../lib/decompress_inflate.c"
#endif
@@ -70,6 +73,10 @@ void *memset(void *s, int c, size_t n)
#include "../../../../lib/decompress_bunzip2.c"
#endif
+#ifdef CONFIG_KERNEL_LZ4
+#include "../../../../lib/decompress_unlz4.c"
+#endif
+
#ifdef CONFIG_KERNEL_LZMA
#include "../../../../lib/decompress_unlzma.c"
#endif
@@ -78,6 +85,10 @@ void *memset(void *s, int c, size_t n)
#include "../../../../lib/decompress_unlzo.c"
#endif
+#ifdef CONFIG_KERNEL_XZ
+#include "../../../../lib/decompress_unxz.c"
+#endif
+
void decompress_kernel(unsigned long boot_heap_start)
{
unsigned long zimage_start, zimage_size;
diff --git a/arch/mips/boot/compressed/ld.script b/arch/mips/boot/compressed/ld.script
index 8e6b07ca2f5e..5a33409c7f63 100644
--- a/arch/mips/boot/compressed/ld.script
+++ b/arch/mips/boot/compressed/ld.script
@@ -8,6 +8,9 @@
OUTPUT_ARCH(mips)
ENTRY(start)
+PHDRS {
+ text PT_LOAD FLAGS(7); /* RWX */
+}
SECTIONS
{
/* Text and read-only data */
@@ -15,7 +18,7 @@ SECTIONS
.text : {
*(.text)
*(.rodata)
- }
+ }: text
/* End of text section */
/* Writable data */
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index b212ae12e5ac..331b837cec57 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -999,7 +999,7 @@ void __init plat_mem_setup(void)
if (total == 0)
panic("Unable to allocate memory from "
- "cvmx_bootmem_phy_alloc\n");
+ "cvmx_bootmem_phy_alloc");
}
/*
@@ -1081,7 +1081,7 @@ void __init device_tree_init(void)
/* Copy the default tree from init memory. */
initial_boot_params = early_init_dt_alloc_memory_arch(dt_size, 8);
if (initial_boot_params == NULL)
- panic("Could not allocate initial_boot_params\n");
+ panic("Could not allocate initial_boot_params");
memcpy(initial_boot_params, fdt, dt_size);
if (do_prune) {
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
index 61a334ac43ac..558e94977942 100644
--- a/arch/mips/cobalt/Makefile
+++ b/arch/mips/cobalt/Makefile
@@ -5,5 +5,4 @@
obj-y := buttons.o irq.o lcd.o led.o reset.o rtc.o serial.o setup.o time.o
obj-$(CONFIG_PCI) += pci.o
-obj-$(CONFIG_EARLY_PRINTK) += console.o
obj-$(CONFIG_MTD_PHYSMAP) += mtd.o
diff --git a/arch/mips/cobalt/console.c b/arch/mips/cobalt/console.c
deleted file mode 100644
index d1ba701c9dd1..000000000000
--- a/arch/mips/cobalt/console.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * (C) P. Horton 2006
- */
-#include <linux/io.h>
-#include <linux/serial_reg.h>
-
-#include <cobalt.h>
-
-#define UART_BASE ((void __iomem *)CKSEG1ADDR(0x1c800000))
-
-void prom_putchar(char c)
-{
- if (cobalt_board_id <= COBALT_BRD_ID_QUBE1)
- return;
-
- while (!(readb(UART_BASE + UART_LSR) & UART_LSR_THRE))
- ;
-
- writeb(c, UART_BASE + UART_TX);
-}
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
index ec3b2c417f7c..9a8c2fe8d334 100644
--- a/arch/mips/cobalt/setup.c
+++ b/arch/mips/cobalt/setup.c
@@ -17,6 +17,7 @@
#include <asm/bootinfo.h>
#include <asm/reboot.h>
+#include <asm/setup.h>
#include <asm/gt64120.h>
#include <cobalt.h>
@@ -112,6 +113,8 @@ void __init prom_init(void)
}
add_memory_region(0x0, memsz, BOOT_MEM_RAM);
+
+ setup_8250_early_printk_port(CKSEG1ADDR(0x1c800000), 0, 0);
}
void __init prom_free_prom_memory(void)
diff --git a/arch/mips/configs/powertv_defconfig b/arch/mips/configs/powertv_defconfig
deleted file mode 100644
index 7fda0ce5f692..000000000000
--- a/arch/mips/configs/powertv_defconfig
+++ /dev/null
@@ -1,136 +0,0 @@
-CONFIG_POWERTV=y
-CONFIG_BOOTLOADER_FAMILY="R2"
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_HZ_1000=y
-CONFIG_PREEMPT=y
-# CONFIG_SECCOMP is not set
-CONFIG_EXPERIMENTAL=y
-CONFIG_CROSS_COMPILE=""
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_RELAY=y
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_RD_GZIP is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-# CONFIG_SYSCTL_SYSCALL is not set
-CONFIG_KALLSYMS_ALL=y
-# CONFIG_PCSPKR_PLATFORM is not set
-# CONFIG_EPOLL is not set
-# CONFIG_SIGNALFD is not set
-# CONFIG_EVENTFD is not set
-# CONFIG_VM_EVENT_COUNTERS is not set
-# CONFIG_SLUB_DEBUG is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_PCI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_PNP=y
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
-CONFIG_INET6_AH=y
-CONFIG_INET6_ESP=y
-CONFIG_INET6_IPCOMP=y
-# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET6_XFRM_MODE_BEET is not set
-# CONFIG_IPV6_SIT is not set
-CONFIG_IPV6_TUNNEL=y
-CONFIG_NETFILTER=y
-# CONFIG_BRIDGE_NETFILTER is not set
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
-CONFIG_IP_NF_IPTABLES=y
-CONFIG_IP_NF_FILTER=y
-CONFIG_IP_NF_ARPTABLES=y
-CONFIG_IP_NF_ARPFILTER=y
-CONFIG_IP6_NF_IPTABLES=y
-CONFIG_IP6_NF_FILTER=y
-CONFIG_BRIDGE=y
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_TBF=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_NAND=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=32768
-# CONFIG_MISC_DEVICES is not set
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_ATA=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-# CONFIG_WLAN is not set
-CONFIG_USB_RTL8150=y
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-# CONFIG_DEVKMEM is not set
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_MFD_SUPPORT is not set
-# CONFIG_VGA_ARB is not set
-CONFIG_USB_HIDDEV=y
-CONFIG_USB=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_EHCI_HCD=y
-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_SERIAL=y
-CONFIG_USB_SERIAL_CONSOLE=y
-CONFIG_USB_SERIAL_CP210X=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_FUSE_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_PRINTK_TIME=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_PREEMPT is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_EARLY_PRINTK is not set
-CONFIG_CMDLINE_BOOL=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRYPTO_HW is not set
diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
index 22afed16ccde..41a2fa1fa12e 100644
--- a/arch/mips/dec/int-handler.S
+++ b/arch/mips/dec/int-handler.S
@@ -118,7 +118,7 @@
* 7 FPU/R4k timer
*
* We handle the IRQ according to _our_ priority (see setup.c),
- * then we just return. If multiple IRQs are pending then we will
+ * then we just return. If multiple IRQs are pending then we will
* just take another exception, big deal.
*/
.align 5
@@ -146,7 +146,7 @@
/*
* Find irq with highest priority
*/
- PTR_LA t1,cpu_mask_nr_tbl
+ PTR_LA t1,cpu_mask_nr_tbl
1: lw t2,(t1)
nop
and t2,t0
@@ -195,7 +195,7 @@
/*
* Find irq with highest priority
*/
- PTR_LA t1,asic_mask_nr_tbl
+ PTR_LA t1,asic_mask_nr_tbl
2: lw t2,(t1)
nop
and t2,t0
@@ -221,7 +221,7 @@
FEXPORT(cpu_all_int) # HALT, timers, software junk
li a0,DEC_CPU_IRQ_BASE
srl t0,CAUSEB_IP
- li t1,CAUSEF_IP>>CAUSEB_IP # mask
+ li t1,CAUSEF_IP>>CAUSEB_IP # mask
b 1f
li t2,4 # nr of bits / 2
diff --git a/arch/mips/dec/ioasic-irq.c b/arch/mips/dec/ioasic-irq.c
index 4b3e3a4375a6..e04d973ce5aa 100644
--- a/arch/mips/dec/ioasic-irq.c
+++ b/arch/mips/dec/ioasic-irq.c
@@ -1,7 +1,7 @@
/*
* DEC I/O ASIC interrupts.
*
- * Copyright (c) 2002, 2003 Maciej W. Rozycki
+ * Copyright (c) 2002, 2003, 2013 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
@@ -51,22 +51,51 @@ static struct irq_chip ioasic_irq_type = {
.irq_unmask = unmask_ioasic_irq,
};
-void clear_ioasic_dma_irq(unsigned int irq)
+static void clear_ioasic_dma_irq(struct irq_data *d)
{
u32 sir;
- sir = ~(1 << (irq - ioasic_irq_base));
+ sir = ~(1 << (d->irq - ioasic_irq_base));
ioasic_write(IO_REG_SIR, sir);
+ fast_iob();
}
static struct irq_chip ioasic_dma_irq_type = {
.name = "IO-ASIC-DMA",
- .irq_ack = ack_ioasic_irq,
+ .irq_ack = clear_ioasic_dma_irq,
.irq_mask = mask_ioasic_irq,
- .irq_mask_ack = ack_ioasic_irq,
.irq_unmask = unmask_ioasic_irq,
+ .irq_eoi = clear_ioasic_dma_irq,
};
+/*
+ * I/O ASIC implements two kinds of DMA interrupts, informational and
+ * error interrupts.
+ *
+ * The formers do not stop DMA and should be cleared as soon as possible
+ * so that if they retrigger before the handler has completed, usually as
+ * a side effect of actions taken by the handler, then they are reissued.
+ * These use the `handle_edge_irq' handler that clears the request right
+ * away.
+ *
+ * The latters stop DMA and do not resume it until the interrupt has been
+ * cleared. This cannot be done until after a corrective action has been
+ * taken and this also means they will not retrigger. Therefore they use
+ * the `handle_fasteoi_irq' handler that only clears the request on the
+ * way out. Because MIPS processor interrupt inputs, one of which the I/O
+ * ASIC is cascaded to, are level-triggered it is recommended that error
+ * DMA interrupt action handlers are registered with the IRQF_ONESHOT flag
+ * set so that they are run with the interrupt line masked.
+ *
+ * This mask has `1' bits in the positions of informational interrupts.
+ */
+#define IO_IRQ_DMA_INFO \
+ (IO_IRQ_MASK(IO_INR_SCC0A_RXDMA) | \
+ IO_IRQ_MASK(IO_INR_SCC1A_RXDMA) | \
+ IO_IRQ_MASK(IO_INR_ISDN_TXDMA) | \
+ IO_IRQ_MASK(IO_INR_ISDN_RXDMA) | \
+ IO_IRQ_MASK(IO_INR_ASC_DMA))
+
void __init init_ioasic_irqs(int base)
{
int i;
@@ -79,7 +108,9 @@ void __init init_ioasic_irqs(int base)
irq_set_chip_and_handler(i, &ioasic_irq_type,
handle_level_irq);
for (; i < base + IO_IRQ_LINES; i++)
- irq_set_chip(i, &ioasic_dma_irq_type);
+ irq_set_chip_and_handler(i, &ioasic_dma_irq_type,
+ 1 << (i - base) & IO_IRQ_DMA_INFO ?
+ handle_edge_irq : handle_fasteoi_irq);
ioasic_irq_base = base;
}
diff --git a/arch/mips/dec/prom/call_o32.S b/arch/mips/dec/prom/call_o32.S
index c0d1522d448f..8c8498159e43 100644
--- a/arch/mips/dec/prom/call_o32.S
+++ b/arch/mips/dec/prom/call_o32.S
@@ -14,7 +14,7 @@
/* 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 both of the above. */
#define O32_FRAMESZ (4 * O32_ARGC + SZREG * O32_STATC)
diff --git a/arch/mips/dec/prom/init.c b/arch/mips/dec/prom/init.c
index 468f665de7bb..4e1761e0a09a 100644
--- a/arch/mips/dec/prom/init.c
+++ b/arch/mips/dec/prom/init.c
@@ -104,7 +104,7 @@ void __init prom_init(void)
if (prom_is_rex(magic))
rex_clear_cache();
- /* Register the early console. */
+ /* Register the early console. */
register_prom_console();
/* Were we compiled with the right CPU option? */
diff --git a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c
index 0aadac742900..8c62316f22f4 100644
--- a/arch/mips/dec/prom/memory.c
+++ b/arch/mips/dec/prom/memory.c
@@ -22,7 +22,7 @@ volatile unsigned long mem_err; /* So we know an error occurred */
/*
* Probe memory in 4MB chunks, waiting for an error to tell us we've fallen
- * off the end of real memory. Only suitable for the 2100/3100's (PMAX).
+ * off the end of real memory. Only suitable for the 2100/3100's (PMAX).
*/
#define CHUNK_SIZE 0x400000
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index 741cb4235bde..56e6e2c23683 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -65,7 +65,7 @@ EXPORT_SYMBOL(ioasic_base);
/*
* IRQ routing and priority tables. Priorites are set as follows:
*
- * KN01 KN230 KN02 KN02-BA KN02-CA KN03
+ * KN01 KN230 KN02 KN02-BA KN02-CA KN03
*
* MEMORY CPU CPU CPU ASIC CPU CPU
* RTC CPU CPU CPU ASIC CPU CPU
@@ -413,7 +413,7 @@ static void __init dec_init_kn02(void)
/*
* Machine-specific initialisation for KN02-BA, aka DS5000/1xx
- * (xx = 20, 25, 33), aka 3min. Also applies to KN04(-BA), aka
+ * (xx = 20, 25, 33), aka 3min. Also applies to KN04(-BA), aka
* DS5000/150, aka 4min.
*/
static int kn02ba_interrupt[DEC_NR_INTS] __initdata = {
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 454ddf9bb76f..1acbb8b77a71 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -11,5 +11,6 @@ generic-y += sections.h
generic-y += segment.h
generic-y += serial.h
generic-y += trace_clock.h
+generic-y += preempt.h
generic-y += ucontext.h
generic-y += xor.h
diff --git a/arch/mips/include/asm/dec/ioasic.h b/arch/mips/include/asm/dec/ioasic.h
index a6e505a0e44b..be4d62a5a10e 100644
--- a/arch/mips/include/asm/dec/ioasic.h
+++ b/arch/mips/include/asm/dec/ioasic.h
@@ -31,8 +31,6 @@ static inline u32 ioasic_read(unsigned int reg)
return ioasic_base[reg / 4];
}
-extern void clear_ioasic_dma_irq(unsigned int irq);
-
extern void init_ioasic_irqs(int base);
extern int dec_ioasic_clocksource_init(void);
diff --git a/arch/mips/include/asm/dec/ioasic_addrs.h b/arch/mips/include/asm/dec/ioasic_addrs.h
index a8665a7611c2..8bd95971fe2d 100644
--- a/arch/mips/include/asm/dec/ioasic_addrs.h
+++ b/arch/mips/include/asm/dec/ioasic_addrs.h
@@ -40,7 +40,7 @@
#define IOASIC_FLOPPY (11*IOASIC_SLOT_SIZE) /* FDC (maxine) */
#define IOASIC_SCSI (12*IOASIC_SLOT_SIZE) /* ASC SCSI */
#define IOASIC_FDC_DMA (13*IOASIC_SLOT_SIZE) /* FDC DMA (maxine) */
-#define IOASIC_SCSI_DMA (14*IOASIC_SLOT_SIZE) /* ??? */
+#define IOASIC_SCSI_DMA (14*IOASIC_SLOT_SIZE) /* ??? */
#define IOASIC_RES_15 (15*IOASIC_SLOT_SIZE) /* unused? */
diff --git a/arch/mips/include/asm/dec/kn01.h b/arch/mips/include/asm/dec/kn01.h
index 0eb3241de706..88d9ffd74258 100644
--- a/arch/mips/include/asm/dec/kn01.h
+++ b/arch/mips/include/asm/dec/kn01.h
@@ -57,12 +57,12 @@
/*
* System Control & Status Register bits.
*/
-#define KN01_CSR_MNFMOD (1<<15) /* MNFMOD manufacturing jumper */
-#define KN01_CSR_STATUS (1<<14) /* self-test result status output */
-#define KN01_CSR_PARDIS (1<<13) /* parity error disable */
-#define KN01_CSR_CRSRTST (1<<12) /* PCC test output */
-#define KN01_CSR_MONO (1<<11) /* mono/color fb SIMM installed */
-#define KN01_CSR_MEMERR (1<<10) /* write timeout error status & ack*/
+#define KN01_CSR_MNFMOD (1<<15) /* MNFMOD manufacturing jumper */
+#define KN01_CSR_STATUS (1<<14) /* self-test result status output */
+#define KN01_CSR_PARDIS (1<<13) /* parity error disable */
+#define KN01_CSR_CRSRTST (1<<12) /* PCC test output */
+#define KN01_CSR_MONO (1<<11) /* mono/color fb SIMM installed */
+#define KN01_CSR_MEMERR (1<<10) /* write timeout error status & ack*/
#define KN01_CSR_VINT (1<<9) /* PCC area detect #2 status & ack */
#define KN01_CSR_TXDIS (1<<8) /* DZ11 transmit disable */
#define KN01_CSR_VBGTRG (1<<2) /* blue DAC voltage over green (r/o) */
diff --git a/arch/mips/include/asm/dec/kn02ca.h b/arch/mips/include/asm/dec/kn02ca.h
index 69dc2a9a2d0f..92c0fe256099 100644
--- a/arch/mips/include/asm/dec/kn02ca.h
+++ b/arch/mips/include/asm/dec/kn02ca.h
@@ -68,7 +68,7 @@
#define KN03CA_IO_SSR_ISDN_RST (1<<12) /* ~ISDN (Am79C30A) reset */
#define KN03CA_IO_SSR_FLOPPY_RST (1<<7) /* ~FDC (82077) reset */
-#define KN03CA_IO_SSR_VIDEO_RST (1<<6) /* ~framebuffer reset */
+#define KN03CA_IO_SSR_VIDEO_RST (1<<6) /* ~framebuffer reset */
#define KN03CA_IO_SSR_AB_RST (1<<5) /* ACCESS.bus reset */
#define KN03CA_IO_SSR_RES_4 (1<<4) /* unused */
#define KN03CA_IO_SSR_RES_3 (1<<4) /* unused */
diff --git a/arch/mips/include/asm/dec/prom.h b/arch/mips/include/asm/dec/prom.h
index 446577712bee..c0ead6313845 100644
--- a/arch/mips/include/asm/dec/prom.h
+++ b/arch/mips/include/asm/dec/prom.h
@@ -49,7 +49,7 @@
#ifdef CONFIG_64BIT
-#define prom_is_rex(magic) 1 /* KN04 and KN05 are REX PROMs. */
+#define prom_is_rex(magic) 1 /* KN04 and KN05 are REX PROMs. */
#else /* !CONFIG_64BIT */
diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index cf3ae2480b1d..a66359ef4ece 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -331,6 +331,7 @@ extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) \
dump_task_fpu(tsk, elf_fpregs)
+#define CORE_DUMP_USE_REGSET
#define ELF_EXEC_PAGESIZE PAGE_SIZE
/* This yields a mask that user programs can use to figure out what
diff --git a/arch/mips/include/asm/mach-ath79/ar933x_uart_platform.h b/arch/mips/include/asm/mach-ath79/ar933x_uart_platform.h
deleted file mode 100644
index 6cb30f2b7198..000000000000
--- a/arch/mips/include/asm/mach-ath79/ar933x_uart_platform.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Platform data definition for Atheros AR933X UART
- *
- * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.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.
- */
-
-#ifndef _AR933X_UART_PLATFORM_H
-#define _AR933X_UART_PLATFORM_H
-
-struct ar933x_uart_platform_data {
- unsigned uartclk;
-};
-
-#endif /* _AR933X_UART_PLATFORM_H */
diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
new file mode 100644
index 000000000000..00867dd05a69
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
@@ -0,0 +1,110 @@
+#ifndef __BCM47XX_BOARD_H
+#define __BCM47XX_BOARD_H
+
+enum bcm47xx_board {
+ BCM47XX_BOARD_ASUS_RTAC66U,
+ BCM47XX_BOARD_ASUS_RTN10,
+ BCM47XX_BOARD_ASUS_RTN10D,
+ BCM47XX_BOARD_ASUS_RTN10U,
+ BCM47XX_BOARD_ASUS_RTN12,
+ BCM47XX_BOARD_ASUS_RTN12B1,
+ BCM47XX_BOARD_ASUS_RTN12C1,
+ BCM47XX_BOARD_ASUS_RTN12D1,
+ BCM47XX_BOARD_ASUS_RTN12HP,
+ BCM47XX_BOARD_ASUS_RTN15U,
+ BCM47XX_BOARD_ASUS_RTN16,
+ BCM47XX_BOARD_ASUS_RTN53,
+ BCM47XX_BOARD_ASUS_RTN66U,
+ BCM47XX_BOARD_ASUS_WL300G,
+ BCM47XX_BOARD_ASUS_WL320GE,
+ BCM47XX_BOARD_ASUS_WL330GE,
+ BCM47XX_BOARD_ASUS_WL500GD,
+ BCM47XX_BOARD_ASUS_WL500GPV1,
+ BCM47XX_BOARD_ASUS_WL500GPV2,
+ BCM47XX_BOARD_ASUS_WL500W,
+ BCM47XX_BOARD_ASUS_WL520GC,
+ BCM47XX_BOARD_ASUS_WL520GU,
+ BCM47XX_BOARD_ASUS_WL700GE,
+ BCM47XX_BOARD_ASUS_WLHDD,
+
+ BCM47XX_BOARD_BELKIN_F7D4301,
+
+ BCM47XX_BOARD_BUFFALO_WBR2_G54,
+ BCM47XX_BOARD_BUFFALO_WHR2_A54G54,
+ BCM47XX_BOARD_BUFFALO_WHR_G125,
+ BCM47XX_BOARD_BUFFALO_WHR_G54S,
+ BCM47XX_BOARD_BUFFALO_WHR_HP_G54,
+ BCM47XX_BOARD_BUFFALO_WLA2_G54L,
+ BCM47XX_BOARD_BUFFALO_WZR_G300N,
+ BCM47XX_BOARD_BUFFALO_WZR_RS_G54,
+ BCM47XX_BOARD_BUFFALO_WZR_RS_G54HP,
+
+ BCM47XX_BOARD_CISCO_M10V1,
+ BCM47XX_BOARD_CISCO_M20V1,
+
+ BCM47XX_BOARD_DELL_TM2300,
+
+ BCM47XX_BOARD_DLINK_DIR130,
+ BCM47XX_BOARD_DLINK_DIR330,
+
+ BCM47XX_BOARD_HUAWEI_E970,
+
+ BCM47XX_BOARD_LINKSYS_E900V1,
+ BCM47XX_BOARD_LINKSYS_E1000V1,
+ BCM47XX_BOARD_LINKSYS_E1000V2,
+ BCM47XX_BOARD_LINKSYS_E1000V21,
+ BCM47XX_BOARD_LINKSYS_E1200V2,
+ BCM47XX_BOARD_LINKSYS_E2000V1,
+ BCM47XX_BOARD_LINKSYS_E3000V1,
+ BCM47XX_BOARD_LINKSYS_E3200V1,
+ BCM47XX_BOARD_LINKSYS_E4200V1,
+ BCM47XX_BOARD_LINKSYS_WRT150NV1,
+ BCM47XX_BOARD_LINKSYS_WRT150NV11,
+ BCM47XX_BOARD_LINKSYS_WRT160NV1,
+ BCM47XX_BOARD_LINKSYS_WRT160NV3,
+ BCM47XX_BOARD_LINKSYS_WRT300NV11,
+ BCM47XX_BOARD_LINKSYS_WRT310NV1,
+ BCM47XX_BOARD_LINKSYS_WRT310NV2,
+ BCM47XX_BOARD_LINKSYS_WRT54G3GV2,
+ BCM47XX_BOARD_LINKSYS_WRT610NV1,
+ BCM47XX_BOARD_LINKSYS_WRT610NV2,
+ BCM47XX_BOARD_LINKSYS_WRTSL54GS,
+
+ BCM47XX_BOARD_MOTOROLA_WE800G,
+ BCM47XX_BOARD_MOTOROLA_WR850GP,
+ BCM47XX_BOARD_MOTOROLA_WR850GV2V3,
+
+ BCM47XX_BOARD_NETGEAR_WGR614V8,
+ BCM47XX_BOARD_NETGEAR_WGR614V9,
+ BCM47XX_BOARD_NETGEAR_WNDR3300,
+ BCM47XX_BOARD_NETGEAR_WNDR3400V1,
+ BCM47XX_BOARD_NETGEAR_WNDR3400V2,
+ BCM47XX_BOARD_NETGEAR_WNDR3400VCNA,
+ BCM47XX_BOARD_NETGEAR_WNDR3700V3,
+ BCM47XX_BOARD_NETGEAR_WNDR4000,
+ BCM47XX_BOARD_NETGEAR_WNDR4500V1,
+ BCM47XX_BOARD_NETGEAR_WNDR4500V2,
+ BCM47XX_BOARD_NETGEAR_WNR2000,
+ BCM47XX_BOARD_NETGEAR_WNR3500L,
+ BCM47XX_BOARD_NETGEAR_WNR3500U,
+ BCM47XX_BOARD_NETGEAR_WNR3500V2,
+ BCM47XX_BOARD_NETGEAR_WNR3500V2VC,
+ BCM47XX_BOARD_NETGEAR_WNR834BV2,
+
+ BCM47XX_BOARD_PHICOMM_M1,
+
+ BCM47XX_BOARD_SIMPLETECH_SIMPLESHARE,
+
+ BCM47XX_BOARD_ZTE_H218N,
+
+ BCM47XX_BOARD_UNKNOWN,
+ BCM47XX_BOARD_NO,
+};
+
+#define BCM47XX_BOARD_MAX_NAME 30
+
+void bcm47xx_board_detect(void);
+enum bcm47xx_board bcm47xx_board_get(void);
+const char *bcm47xx_board_get_name(void);
+
+#endif /* __BCM47XX_BOARD_H */
diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
index b8e7be8f34dd..36a3fc1aa3ae 100644
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
@@ -48,4 +48,6 @@ static inline void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6])
printk(KERN_WARNING "Can not parse mac address: %s\n", buf);
}
+int bcm47xx_nvram_gpio_pin(const char *name);
+
#endif /* __BCM47XX_NVRAM_H */
diff --git a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
index 47fb247f9663..f9f448650505 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
@@ -52,23 +52,11 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
return 0;
}
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
- BUG();
-}
-
static inline int plat_device_is_coherent(struct device *dev)
{
return 1;
}
-static inline int plat_dma_mapping_error(struct device *dev,
- dma_addr_t dma_addr)
-{
- BUG();
- return 0;
-}
-
dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
diff --git a/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h b/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h
new file mode 100644
index 000000000000..acce27fd2bb8
--- /dev/null
+++ b/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h
@@ -0,0 +1,87 @@
+/*
+ * CPU feature overrides for DECstation systems. Two variations
+ * are generally applicable.
+ *
+ * Copyright (C) 2013 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.
+ */
+#ifndef __ASM_MACH_DEC_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_DEC_CPU_FEATURE_OVERRIDES_H
+
+/* Generic ones first. */
+#define cpu_has_tlb 1
+#define cpu_has_tx39_cache 0
+#define cpu_has_fpu 1
+#define cpu_has_divec 0
+#define cpu_has_prefetch 0
+#define cpu_has_mcheck 0
+#define cpu_has_ejtag 0
+#define cpu_has_mips16 0
+#define cpu_has_mdmx 0
+#define cpu_has_mips3d 0
+#define cpu_has_smartmips 0
+#define cpu_has_rixi 0
+#define cpu_has_vtag_icache 0
+#define cpu_has_ic_fills_f_dc 0
+#define cpu_has_pindexed_dcache 0
+#define cpu_has_local_ebase 0
+#define cpu_icache_snoops_remote_store 1
+#define cpu_has_mips_4 0
+#define cpu_has_mips_5 0
+#define cpu_has_mips32r1 0
+#define cpu_has_mips32r2 0
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+#define cpu_has_dsp 0
+#define cpu_has_mipsmt 0
+#define cpu_has_userlocal 0
+
+/* R3k-specific ones. */
+#ifdef CONFIG_CPU_R3000
+#define cpu_has_4kex 0
+#define cpu_has_3k_cache 1
+#define cpu_has_4k_cache 0
+#define cpu_has_32fpr 0
+#define cpu_has_counter 0
+#define cpu_has_watch 0
+#define cpu_has_vce 0
+#define cpu_has_cache_cdex_p 0
+#define cpu_has_cache_cdex_s 0
+#define cpu_has_llsc 0
+#define cpu_has_dc_aliases 0
+#define cpu_has_mips_2 0
+#define cpu_has_mips_3 0
+#define cpu_has_nofpuex 1
+#define cpu_has_inclusive_pcaches 0
+#define cpu_dcache_line_size() 4
+#define cpu_icache_line_size() 4
+#define cpu_scache_line_size() 0
+#endif /* CONFIG_CPU_R3000 */
+
+/* R4k-specific ones. */
+#ifdef CONFIG_CPU_R4X00
+#define cpu_has_4kex 1
+#define cpu_has_3k_cache 0
+#define cpu_has_4k_cache 1
+#define cpu_has_32fpr 1
+#define cpu_has_counter 1
+#define cpu_has_watch 1
+#define cpu_has_vce 1
+#define cpu_has_cache_cdex_p 1
+#define cpu_has_cache_cdex_s 1
+#define cpu_has_llsc 1
+#define cpu_has_dc_aliases (PAGE_SIZE < 0x4000)
+#define cpu_has_mips_2 1
+#define cpu_has_mips_3 1
+#define cpu_has_nofpuex 0
+#define cpu_has_inclusive_pcaches 1
+#define cpu_dcache_line_size() 16
+#define cpu_icache_line_size() 16
+#define cpu_scache_line_size() 32
+#endif /* CONFIG_CPU_R4X00 */
+
+#endif /* __ASM_MACH_DEC_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h
index 74cb99257d5b..a9e8f6b62b0b 100644
--- a/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ b/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -47,16 +47,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
return 1;
}
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
- dma_addr_t dma_addr)
-{
- return 0;
-}
-
static inline int plat_device_is_coherent(struct device *dev)
{
#ifdef CONFIG_DMA_COHERENT
diff --git a/arch/mips/include/asm/mach-ip27/dma-coherence.h b/arch/mips/include/asm/mach-ip27/dma-coherence.h
index 06c441968e6e..4ffddfdb5062 100644
--- a/arch/mips/include/asm/mach-ip27/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip27/dma-coherence.h
@@ -58,16 +58,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
return 1;
}
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
- dma_addr_t dma_addr)
-{
- return 0;
-}
-
static inline int plat_device_is_coherent(struct device *dev)
{
return 1; /* IP27 non-cohernet mode is unsupported */
diff --git a/arch/mips/include/asm/mach-ip32/dma-coherence.h b/arch/mips/include/asm/mach-ip32/dma-coherence.h
index 073f0c4760ba..104cfbc3ed63 100644
--- a/arch/mips/include/asm/mach-ip32/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip32/dma-coherence.h
@@ -80,17 +80,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
return 1;
}
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
- return;
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
- dma_addr_t dma_addr)
-{
- return 0;
-}
-
static inline int plat_device_is_coherent(struct device *dev)
{
return 0; /* IP32 is non-cohernet */
diff --git a/arch/mips/include/asm/mach-jazz/dma-coherence.h b/arch/mips/include/asm/mach-jazz/dma-coherence.h
index 9fc1e9ad7038..949003ef97b3 100644
--- a/arch/mips/include/asm/mach-jazz/dma-coherence.h
+++ b/arch/mips/include/asm/mach-jazz/dma-coherence.h
@@ -48,16 +48,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
return 1;
}
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
- dma_addr_t dma_addr)
-{
- return 0;
-}
-
static inline int plat_device_is_coherent(struct device *dev)
{
return 0;
diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h
index e1433055fe98..aeb2c05d6145 100644
--- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
+++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
@@ -53,16 +53,6 @@ static inline int plat_dma_supported(struct device *dev, u64 mask)
return 1;
}
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
- dma_addr_t dma_addr)
-{
- return 0;
-}
-
static inline int plat_device_is_coherent(struct device *dev)
{
return 0;
diff --git a/arch/mips/include/asm/mach-powertv/asic.h b/arch/mips/include/asm/mach-powertv/asic.h
deleted file mode 100644
index b341108d12f1..000000000000
--- a/arch/mips/include/asm/mach-powertv/asic.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2009 Cisco Systems, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _ASM_MACH_POWERTV_ASIC_H
-#define _ASM_MACH_POWERTV_ASIC_H
-
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <asm/mach-powertv/asic_regs.h>
-
-#define DVR_CAPABLE (1<<0)
-#define PCIE_CAPABLE (1<<1)
-#define FFS_CAPABLE (1<<2)
-#define DISPLAY_CAPABLE (1<<3)
-
-/* Platform Family types
- * For compitability, the new value must be added in the end */
-enum family_type {
- FAMILY_8500,
- FAMILY_8500RNG,
- FAMILY_4500,
- FAMILY_1500,
- FAMILY_8600,
- FAMILY_4600,
- FAMILY_4600VZA,
- FAMILY_8600VZB,
- FAMILY_1500VZE,
- FAMILY_1500VZF,
- FAMILY_8700,
- FAMILIES
-};
-
-/* Register maps for each ASIC */
-extern const struct register_map calliope_register_map;
-extern const struct register_map cronus_register_map;
-extern const struct register_map gaia_register_map;
-extern const struct register_map zeus_register_map;
-
-extern struct resource dvr_cronus_resources[];
-extern struct resource dvr_gaia_resources[];
-extern struct resource dvr_zeus_resources[];
-extern struct resource non_dvr_calliope_resources[];
-extern struct resource non_dvr_cronus_resources[];
-extern struct resource non_dvr_cronuslite_resources[];
-extern struct resource non_dvr_gaia_resources[];
-extern struct resource non_dvr_vz_calliope_resources[];
-extern struct resource non_dvr_vze_calliope_resources[];
-extern struct resource non_dvr_vzf_calliope_resources[];
-extern struct resource non_dvr_zeus_resources[];
-
-extern void powertv_platform_init(void);
-extern void platform_alloc_bootmem(void);
-extern enum asic_type platform_get_asic(void);
-extern enum family_type platform_get_family(void);
-extern int platform_supports_dvr(void);
-extern int platform_supports_ffs(void);
-extern int platform_supports_pcie(void);
-extern int platform_supports_display(void);
-extern void configure_platform(void);
-
-/* Platform Resources */
-#define ASIC_RESOURCE_GET_EXISTS 1
-extern struct resource *asic_resource_get(const char *name);
-extern void platform_release_memory(void *baddr, int size);
-
-/* USB configuration */
-struct usb_hcd; /* Forward reference */
-extern void platform_configure_usb_ehci(void);
-extern void platform_unconfigure_usb_ehci(void);
-extern void platform_configure_usb_ohci(void);
-extern void platform_unconfigure_usb_ohci(void);
-
-/* Resource for ASIC registers */
-extern struct resource asic_resource;
-extern int platform_usb_devices_init(struct platform_device **echi_dev,
- struct platform_device **ohci_dev);
-
-/* Reboot Cause */
-extern void set_reboot_cause(char code, unsigned int data, unsigned int data2);
-extern void set_locked_reboot_cause(char code, unsigned int data,
- unsigned int data2);
-
-enum sys_reboot_type {
- sys_unknown_reboot = 0x00, /* Unknown reboot cause */
- sys_davic_change = 0x01, /* Reboot due to change in DAVIC
- * mode */
- sys_user_reboot = 0x02, /* Reboot initiated by user */
- sys_system_reboot = 0x03, /* Reboot initiated by OS */
- sys_trap_reboot = 0x04, /* Reboot due to a CPU trap */
- sys_silent_reboot = 0x05, /* Silent reboot */
- sys_boot_ldr_reboot = 0x06, /* Bootloader reboot */
- sys_power_up_reboot = 0x07, /* Power on bootup. Older
- * drivers may report as
- * userReboot. */
- sys_code_change = 0x08, /* Reboot to take code change.
- * Older drivers may report as
- * userReboot. */
- sys_hardware_reset = 0x09, /* HW watchdog or front-panel
- * reset button reset. Older
- * drivers may report as
- * userReboot. */
- sys_watchdogInterrupt = 0x0A /* Pre-watchdog interrupt */
-};
-
-#endif /* _ASM_MACH_POWERTV_ASIC_H */
diff --git a/arch/mips/include/asm/mach-powertv/asic_reg_map.h b/arch/mips/include/asm/mach-powertv/asic_reg_map.h
deleted file mode 100644
index 20348e817b09..000000000000
--- a/arch/mips/include/asm/mach-powertv/asic_reg_map.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * asic_reg_map.h
- *
- * A macro-enclosed list of the elements for the register_map structure for
- * use in defining and manipulating the structure.
- *
- * Copyright (C) 2009 Cisco Systems, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-REGISTER_MAP_ELEMENT(eic_slow0_strt_add)
-REGISTER_MAP_ELEMENT(eic_cfg_bits)
-REGISTER_MAP_ELEMENT(eic_ready_status)
-REGISTER_MAP_ELEMENT(chipver3)
-REGISTER_MAP_ELEMENT(chipver2)
-REGISTER_MAP_ELEMENT(chipver1)
-REGISTER_MAP_ELEMENT(chipver0)
-REGISTER_MAP_ELEMENT(uart1_intstat)
-REGISTER_MAP_ELEMENT(uart1_inten)
-REGISTER_MAP_ELEMENT(uart1_config1)
-REGISTER_MAP_ELEMENT(uart1_config2)
-REGISTER_MAP_ELEMENT(uart1_divisorhi)
-REGISTER_MAP_ELEMENT(uart1_divisorlo)
-REGISTER_MAP_ELEMENT(uart1_data)
-REGISTER_MAP_ELEMENT(uart1_status)
-REGISTER_MAP_ELEMENT(int_stat_3)
-REGISTER_MAP_ELEMENT(int_stat_2)
-REGISTER_MAP_ELEMENT(int_stat_1)
-REGISTER_MAP_ELEMENT(int_stat_0)
-REGISTER_MAP_ELEMENT(int_config)
-REGISTER_MAP_ELEMENT(int_int_scan)
-REGISTER_MAP_ELEMENT(ien_int_3)
-REGISTER_MAP_ELEMENT(ien_int_2)
-REGISTER_MAP_ELEMENT(ien_int_1)
-REGISTER_MAP_ELEMENT(ien_int_0)
-REGISTER_MAP_ELEMENT(int_level_3_3)
-REGISTER_MAP_ELEMENT(int_level_3_2)
-REGISTER_MAP_ELEMENT(int_level_3_1)
-REGISTER_MAP_ELEMENT(int_level_3_0)
-REGISTER_MAP_ELEMENT(int_level_2_3)
-REGISTER_MAP_ELEMENT(int_level_2_2)
-REGISTER_MAP_ELEMENT(int_level_2_1)
-REGISTER_MAP_ELEMENT(int_level_2_0)
-REGISTER_MAP_ELEMENT(int_level_1_3)
-REGISTER_MAP_ELEMENT(int_level_1_2)
-REGISTER_MAP_ELEMENT(int_level_1_1)
-REGISTER_MAP_ELEMENT(int_level_1_0)
-REGISTER_MAP_ELEMENT(int_level_0_3)
-REGISTER_MAP_ELEMENT(int_level_0_2)
-REGISTER_MAP_ELEMENT(int_level_0_1)
-REGISTER_MAP_ELEMENT(int_level_0_0)
-REGISTER_MAP_ELEMENT(int_docsis_en)
-REGISTER_MAP_ELEMENT(mips_pll_setup)
-REGISTER_MAP_ELEMENT(fs432x4b4_usb_ctl)
-REGISTER_MAP_ELEMENT(test_bus)
-REGISTER_MAP_ELEMENT(crt_spare)
-REGISTER_MAP_ELEMENT(usb2_ohci_int_mask)
-REGISTER_MAP_ELEMENT(usb2_strap)
-REGISTER_MAP_ELEMENT(ehci_hcapbase)
-REGISTER_MAP_ELEMENT(ohci_hc_revision)
-REGISTER_MAP_ELEMENT(bcm1_bs_lmi_steer)
-REGISTER_MAP_ELEMENT(usb2_control)
-REGISTER_MAP_ELEMENT(usb2_stbus_obc)
-REGISTER_MAP_ELEMENT(usb2_stbus_mess_size)
-REGISTER_MAP_ELEMENT(usb2_stbus_chunk_size)
-REGISTER_MAP_ELEMENT(pcie_regs)
-REGISTER_MAP_ELEMENT(tim_ch)
-REGISTER_MAP_ELEMENT(tim_cl)
-REGISTER_MAP_ELEMENT(gpio_dout)
-REGISTER_MAP_ELEMENT(gpio_din)
-REGISTER_MAP_ELEMENT(gpio_dir)
-REGISTER_MAP_ELEMENT(watchdog)
-REGISTER_MAP_ELEMENT(front_panel)
-REGISTER_MAP_ELEMENT(misc_clk_ctl1)
-REGISTER_MAP_ELEMENT(misc_clk_ctl2)
-REGISTER_MAP_ELEMENT(crt_ext_ctl)
-REGISTER_MAP_ELEMENT(register_maps)
diff --git a/arch/mips/include/asm/mach-powertv/asic_regs.h b/arch/mips/include/asm/mach-powertv/asic_regs.h
deleted file mode 100644
index 06712abb3e55..000000000000
--- a/arch/mips/include/asm/mach-powertv/asic_regs.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2009 Cisco Systems, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef __ASM_MACH_POWERTV_ASIC_H_
-#define __ASM_MACH_POWERTV_ASIC_H_
-#include <linux/io.h>
-
-/* ASIC types */
-enum asic_type {
- ASIC_UNKNOWN,
- ASIC_ZEUS,
- ASIC_CALLIOPE,
- ASIC_CRONUS,
- ASIC_CRONUSLITE,
- ASIC_GAIA,
- ASICS /* Number of supported ASICs */
-};
-
-/* hardcoded values read from Chip Version registers */
-#define CRONUS_10 0x0B4C1C20
-#define CRONUS_11 0x0B4C1C21
-#define CRONUSLITE_10 0x0B4C1C40
-
-#define NAND_FLASH_BASE 0x03000000
-#define CALLIOPE_IO_BASE 0x08000000
-#define GAIA_IO_BASE 0x09000000
-#define CRONUS_IO_BASE 0x09000000
-#define ZEUS_IO_BASE 0x09000000
-
-#define ASIC_IO_SIZE 0x01000000
-
-/* Definitions for backward compatibility */
-#define UART1_INTSTAT uart1_intstat
-#define UART1_INTEN uart1_inten
-#define UART1_CONFIG1 uart1_config1
-#define UART1_CONFIG2 uart1_config2
-#define UART1_DIVISORHI uart1_divisorhi
-#define UART1_DIVISORLO uart1_divisorlo
-#define UART1_DATA uart1_data
-#define UART1_STATUS uart1_status
-
-/* ASIC register enumeration */
-union register_map_entry {
- unsigned long phys;
- u32 *virt;
-};
-
-#define REGISTER_MAP_ELEMENT(x) union register_map_entry x;
-struct register_map {
-#include <asm/mach-powertv/asic_reg_map.h>
-};
-#undef REGISTER_MAP_ELEMENT
-
-/**
- * register_map_offset_phys - add an offset to the physical address
- * @map: Pointer to the &struct register_map
- * @offset: Value to add
- *
- * Only adds the base to non-zero physical addresses
- */
-static inline void register_map_offset_phys(struct register_map *map,
- unsigned long offset)
-{
-#define REGISTER_MAP_ELEMENT(x) do { \
- if (map->x.phys != 0) \
- map->x.phys += offset; \
- } while (false);
-
-#include <asm/mach-powertv/asic_reg_map.h>
-#undef REGISTER_MAP_ELEMENT
-}
-
-/**
- * register_map_virtualize - Convert &register_map to virtual addresses
- * @map: Pointer to &register_map to virtualize
- */
-static inline void register_map_virtualize(struct register_map *map)
-{
-#define REGISTER_MAP_ELEMENT(x) do { \
- map->x.virt = (!map->x.phys) ? NULL : \
- UNCAC_ADDR(phys_to_virt(map->x.phys)); \
- } while (false);
-
-#include <asm/mach-powertv/asic_reg_map.h>
-#undef REGISTER_MAP_ELEMENT
-}
-
-extern struct register_map _asic_register_map;
-extern unsigned long asic_phy_base;
-
-/*
- * Macros to interface to registers through their ioremapped address
- * asic_reg_phys_addr Returns the physical address of the given register
- * asic_reg_addr Returns the iomapped virtual address of the given
- * register.
- */
-#define asic_reg_addr(x) (_asic_register_map.x.virt)
-#define asic_reg_phys_addr(x) (virt_to_phys((void *) CAC_ADDR( \
- (unsigned long) asic_reg_addr(x))))
-
-/*
- * The asic_reg macro is gone. It should be replaced by either asic_read or
- * asic_write, as appropriate.
- */
-
-#define asic_read(x) readl(asic_reg_addr(x))
-#define asic_write(v, x) writel(v, asic_reg_addr(x))
-
-extern void asic_irq_init(void);
-#endif
diff --git a/arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h b/arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h
deleted file mode 100644
index 58c76ec32a19..000000000000
--- a/arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2010 Cisco Systems, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _ASM_MACH_POWERTV_CPU_FEATURE_OVERRIDES_H_
-#define _ASM_MACH_POWERTV_CPU_FEATURE_OVERRIDES_H_
-#define cpu_has_tlb 1
-#define cpu_has_4kex 1
-#define cpu_has_3k_cache 0
-#define cpu_has_4k_cache 1
-#define cpu_has_tx39_cache 0
-#define cpu_has_fpu 0
-#define cpu_has_counter 1
-#define cpu_has_watch 1
-#define cpu_has_divec 1
-#define cpu_has_vce 0
-#define cpu_has_cache_cdex_p 0
-#define cpu_has_cache_cdex_s 0
-#define cpu_has_mcheck 1
-#define cpu_has_ejtag 1
-#define cpu_has_llsc 1
-#define cpu_has_mips16 0
-#define cpu_has_mdmx 0
-#define cpu_has_mips3d 0
-#define cpu_has_smartmips 0
-#define cpu_has_vtag_icache 0
-#define cpu_has_dc_aliases 0
-#define cpu_has_ic_fills_f_dc 0
-#define cpu_has_mips32r1 0
-#define cpu_has_mips32r2 1
-#define cpu_has_mips64r1 0
-#define cpu_has_mips64r2 0
-#define cpu_has_dsp 0
-#define cpu_has_dsp2 0
-#define cpu_has_mipsmt 0
-#define cpu_has_userlocal 0
-#define cpu_has_nofpuex 0
-#define cpu_has_64bits 0
-#define cpu_has_64bit_zero_reg 0
-#define cpu_has_vint 1
-#define cpu_has_veic 1
-#define cpu_has_inclusive_pcaches 0
-
-#define cpu_dcache_line_size() 32
-#define cpu_icache_line_size() 32
-#endif
diff --git a/arch/mips/include/asm/mach-powertv/dma-coherence.h b/arch/mips/include/asm/mach-powertv/dma-coherence.h
deleted file mode 100644
index f8316720a218..000000000000
--- a/arch/mips/include/asm/mach-powertv/dma-coherence.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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.
- *
- * Version from mach-generic modified to support PowerTV port
- * Portions Copyright (C) 2009 Cisco Systems, Inc.
- * Copyright (C) 2006 Ralf Baechle <ralf@linux-mips.org>
- *
- */
-
-#ifndef __ASM_MACH_POWERTV_DMA_COHERENCE_H
-#define __ASM_MACH_POWERTV_DMA_COHERENCE_H
-
-#include <linux/sched.h>
-#include <linux/device.h>
-#include <asm/mach-powertv/asic.h>
-
-static inline bool is_kseg2(void *addr)
-{
- return (unsigned long)addr >= KSEG2;
-}
-
-static inline unsigned long virt_to_phys_from_pte(void *addr)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *ptep, pte;
-
- unsigned long virt_addr = (unsigned long)addr;
- unsigned long phys_addr = 0UL;
-
- /* get the page global directory. */
- pgd = pgd_offset_k(virt_addr);
-
- if (!pgd_none(*pgd)) {
- /* get the page upper directory */
- pud = pud_offset(pgd, virt_addr);
- if (!pud_none(*pud)) {
- /* get the page middle directory */
- pmd = pmd_offset(pud, virt_addr);
- if (!pmd_none(*pmd)) {
- /* get a pointer to the page table entry */
- ptep = pte_offset(pmd, virt_addr);
- pte = *ptep;
- /* check for a valid page */
- if (pte_present(pte)) {
- /* get the physical address the page is
- * referring to */
- phys_addr = (unsigned long)
- page_to_phys(pte_page(pte));
- /* add the offset within the page */
- phys_addr |= (virt_addr & ~PAGE_MASK);
- }
- }
- }
- }
-
- return phys_addr;
-}
-
-static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
- size_t size)
-{
- if (is_kseg2(addr))
- return phys_to_dma(virt_to_phys_from_pte(addr));
- else
- return phys_to_dma(virt_to_phys(addr));
-}
-
-static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
- struct page *page)
-{
- return phys_to_dma(page_to_phys(page));
-}
-
-static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
- dma_addr_t dma_addr)
-{
- return dma_to_phys(dma_addr);
-}
-
-static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
- size_t size, enum dma_data_direction direction)
-{
-}
-
-static inline int plat_dma_supported(struct device *dev, u64 mask)
-{
- /*
- * we fall back to GFP_DMA when the mask isn't all 1s,
- * so we can't guarantee allocations that must be
- * within a tighter range than GFP_DMA..
- */
- if (mask < DMA_BIT_MASK(24))
- return 0;
-
- return 1;
-}
-
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
- dma_addr_t dma_addr)
-{
- return 0;
-}
-
-static inline int plat_device_is_coherent(struct device *dev)
-{
- return 0;
-}
-
-#endif /* __ASM_MACH_POWERTV_DMA_COHERENCE_H */
diff --git a/arch/mips/include/asm/mach-powertv/interrupts.h b/arch/mips/include/asm/mach-powertv/interrupts.h
deleted file mode 100644
index 6c463be62156..000000000000
--- a/arch/mips/include/asm/mach-powertv/interrupts.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (C) 2009 Cisco Systems, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _ASM_MACH_POWERTV_INTERRUPTS_H_
-#define _ASM_MACH_POWERTV_INTERRUPTS_H_
-
-/*
- * Defines for all of the interrupt lines
- */
-
-/* Definitions for backward compatibility */
-#define kIrq_Uart1 irq_uart1
-
-#define ibase 0
-
-/*------------- Register: int_stat_3 */
-/* 126 unused (bit 31) */
-#define irq_asc2video (ibase+126) /* ASC 2 Video Interrupt */
-#define irq_asc1video (ibase+125) /* ASC 1 Video Interrupt */
-#define irq_comms_block_wd (ibase+124) /* ASC 1 Video Interrupt */
-#define irq_fdma_mailbox (ibase+123) /* FDMA Mailbox Output */
-#define irq_fdma_gp (ibase+122) /* FDMA GP Output */
-#define irq_mips_pic (ibase+121) /* MIPS Performance Counter
- * Interrupt */
-#define irq_mips_timer (ibase+120) /* MIPS Timer Interrupt */
-#define irq_memory_protect (ibase+119) /* Memory Protection Interrupt
- * -- Ored by glue logic inside
- * SPARC ILC (see
- * INT_MEM_PROT_STAT, below,
- * for individual interrupts)
- */
-/* 118 unused (bit 22) */
-#define irq_sbag (ibase+117) /* SBAG Interrupt -- Ored by
- * glue logic inside SPARC ILC
- * (see INT_SBAG_STAT, below,
- * for individual interrupts) */
-#define irq_qam_b_fec (ibase+116) /* QAM B FEC Interrupt */
-#define irq_qam_a_fec (ibase+115) /* QAM A FEC Interrupt */
-/* 114 unused (bit 18) */
-#define irq_mailbox (ibase+113) /* Mailbox Debug Interrupt --
- * Ored by glue logic inside
- * SPARC ILC (see
- * INT_MAILBOX_STAT, below, for
- * individual interrupts) */
-#define irq_fuse_stat1 (ibase+112) /* Fuse Status 1 */
-#define irq_fuse_stat2 (ibase+111) /* Fuse Status 2 */
-#define irq_fuse_stat3 (ibase+110) /* Blitter Interrupt / Fuse
- * Status 3 */
-#define irq_blitter (ibase+110) /* Blitter Interrupt / Fuse
- * Status 3 */
-#define irq_avc1_pp0 (ibase+109) /* AVC Decoder #1 PP0
- * Interrupt */
-#define irq_avc1_pp1 (ibase+108) /* AVC Decoder #1 PP1
- * Interrupt */
-#define irq_avc1_mbe (ibase+107) /* AVC Decoder #1 MBE
- * Interrupt */
-#define irq_avc2_pp0 (ibase+106) /* AVC Decoder #2 PP0
- * Interrupt */
-#define irq_avc2_pp1 (ibase+105) /* AVC Decoder #2 PP1
- * Interrupt */
-#define irq_avc2_mbe (ibase+104) /* AVC Decoder #2 MBE
- * Interrupt */
-#define irq_zbug_spi (ibase+103) /* Zbug SPI Slave Interrupt */
-#define irq_qam_mod2 (ibase+102) /* QAM Modulator 2 DMA
- * Interrupt */
-#define irq_ir_rx (ibase+101) /* IR RX 2 Interrupt */
-#define irq_aud_dsp2 (ibase+100) /* Audio DSP #2 Interrupt */
-#define irq_aud_dsp1 (ibase+99) /* Audio DSP #1 Interrupt */
-#define irq_docsis (ibase+98) /* DOCSIS Debug Interrupt */
-#define irq_sd_dvp1 (ibase+97) /* SD DVP #1 Interrupt */
-#define irq_sd_dvp2 (ibase+96) /* SD DVP #2 Interrupt */
-/*------------- Register: int_stat_2 */
-#define irq_hd_dvp (ibase+95) /* HD DVP Interrupt */
-#define kIrq_Prewatchdog (ibase+94) /* watchdog Pre-Interrupt */
-#define irq_timer2 (ibase+93) /* Programmable Timer
- * Interrupt 2 */
-#define irq_1394 (ibase+92) /* 1394 Firewire Interrupt */
-#define irq_usbohci (ibase+91) /* USB 2.0 OHCI Interrupt */
-#define irq_usbehci (ibase+90) /* USB 2.0 EHCI Interrupt */
-#define irq_pciexp (ibase+89) /* PCI Express 0 Interrupt */
-#define irq_pciexp0 (ibase+89) /* PCI Express 0 Interrupt */
-#define irq_afe1 (ibase+88) /* AFE 1 Interrupt */
-#define irq_sata (ibase+87) /* SATA 1 Interrupt */
-#define irq_sata1 (ibase+87) /* SATA 1 Interrupt */
-#define irq_dtcp (ibase+86) /* DTCP Interrupt */
-#define irq_pciexp1 (ibase+85) /* PCI Express 1 Interrupt */
-/* 84 unused (bit 20) */
-/* 83 unused (bit 19) */
-/* 82 unused (bit 18) */
-#define irq_sata2 (ibase+81) /* SATA2 Interrupt */
-#define irq_uart2 (ibase+80) /* UART2 Interrupt */
-#define irq_legacy_usb (ibase+79) /* Legacy USB Host ISR (1.1
- * Host module) */
-#define irq_pod (ibase+78) /* POD Interrupt */
-#define irq_slave_usb (ibase+77) /* Slave USB */
-#define irq_denc1 (ibase+76) /* DENC #1 VTG Interrupt */
-#define irq_vbi_vtg (ibase+75) /* VBI VTG Interrupt */
-#define irq_afe2 (ibase+74) /* AFE 2 Interrupt */
-#define irq_denc2 (ibase+73) /* DENC #2 VTG Interrupt */
-#define irq_asc2 (ibase+72) /* ASC #2 Interrupt */
-#define irq_asc1 (ibase+71) /* ASC #1 Interrupt */
-#define irq_mod_dma (ibase+70) /* Modulator DMA Interrupt */
-#define irq_byte_eng1 (ibase+69) /* Byte Engine Interrupt [1] */
-#define irq_byte_eng0 (ibase+68) /* Byte Engine Interrupt [0] */
-/* 67 unused (bit 03) */
-/* 66 unused (bit 02) */
-/* 65 unused (bit 01) */
-/* 64 unused (bit 00) */
-/*------------- Register: int_stat_1 */
-/* 63 unused (bit 31) */
-/* 62 unused (bit 30) */
-/* 61 unused (bit 29) */
-/* 60 unused (bit 28) */
-/* 59 unused (bit 27) */
-/* 58 unused (bit 26) */
-/* 57 unused (bit 25) */
-/* 56 unused (bit 24) */
-#define irq_buf_dma_mem2mem (ibase+55) /* BufDMA Memory to Memory
- * Interrupt */
-#define irq_buf_dma_usbtransmit (ibase+54) /* BufDMA USB Transmit
- * Interrupt */
-#define irq_buf_dma_qpskpodtransmit (ibase+53) /* BufDMA QPSK/POD Tramsit
- * Interrupt */
-#define irq_buf_dma_transmit_error (ibase+52) /* BufDMA Transmit Error
- * Interrupt */
-#define irq_buf_dma_usbrecv (ibase+51) /* BufDMA USB Receive
- * Interrupt */
-#define irq_buf_dma_qpskpodrecv (ibase+50) /* BufDMA QPSK/POD Receive
- * Interrupt */
-#define irq_buf_dma_recv_error (ibase+49) /* BufDMA Receive Error
- * Interrupt */
-#define irq_qamdma_transmit_play (ibase+48) /* QAMDMA Transmit/Play
- * Interrupt */
-#define irq_qamdma_transmit_error (ibase+47) /* QAMDMA Transmit Error
- * Interrupt */
-#define irq_qamdma_recv2high (ibase+46) /* QAMDMA Receive 2 High
- * (Chans 63-32) */
-#define irq_qamdma_recv2low (ibase+45) /* QAMDMA Receive 2 Low
- * (Chans 31-0) */
-#define irq_qamdma_recv1high (ibase+44) /* QAMDMA Receive 1 High
- * (Chans 63-32) */
-#define irq_qamdma_recv1low (ibase+43) /* QAMDMA Receive 1 Low
- * (Chans 31-0) */
-#define irq_qamdma_recv_error (ibase+42) /* QAMDMA Receive Error
- * Interrupt */
-#define irq_mpegsplice (ibase+41) /* MPEG Splice Interrupt */
-#define irq_deinterlace_rdy (ibase+40) /* Deinterlacer Frame Ready
- * Interrupt */
-#define irq_ext_in0 (ibase+39) /* External Interrupt irq_in0 */
-#define irq_gpio3 (ibase+38) /* GP I/O IRQ 3 - From GP I/O
- * Module */
-#define irq_gpio2 (ibase+37) /* GP I/O IRQ 2 - From GP I/O
- * Module (ABE_intN) */
-#define irq_pcrcmplt1 (ibase+36) /* PCR Capture Complete or
- * Discontinuity 1 */
-#define irq_pcrcmplt2 (ibase+35) /* PCR Capture Complete or
- * Discontinuity 2 */
-#define irq_parse_peierr (ibase+34) /* PID Parser Error Detect
- * (PEI) */
-#define irq_parse_cont_err (ibase+33) /* PID Parser continuity error
- * detect */
-#define irq_ds1framer (ibase+32) /* DS1 Framer Interrupt */
-/*------------- Register: int_stat_0 */
-#define irq_gpio1 (ibase+31) /* GP I/O IRQ 1 - From GP I/O
- * Module */
-#define irq_gpio0 (ibase+30) /* GP I/O IRQ 0 - From GP I/O
- * Module */
-#define irq_qpsk_out_aloha (ibase+29) /* QPSK Output Slotted Aloha
- * (chan 3) Transmission
- * Completed OK */
-#define irq_qpsk_out_tdma (ibase+28) /* QPSK Output TDMA (chan 2)
- * Transmission Completed OK */
-#define irq_qpsk_out_reserve (ibase+27) /* QPSK Output Reservation
- * (chan 1) Transmission
- * Completed OK */
-#define irq_qpsk_out_aloha_err (ibase+26) /* QPSK Output Slotted Aloha
- * (chan 3)Transmission
- * completed with Errors. */
-#define irq_qpsk_out_tdma_err (ibase+25) /* QPSK Output TDMA (chan 2)
- * Transmission completed with
- * Errors. */
-#define irq_qpsk_out_rsrv_err (ibase+24) /* QPSK Output Reservation
- * (chan 1) Transmission
- * completed with Errors */
-#define irq_aloha_fail (ibase+23) /* Unsuccessful Resend of Aloha
- * for N times. Aloha retry
- * timeout for channel 3. */
-#define irq_timer1 (ibase+22) /* Programmable Timer
- * Interrupt */
-#define irq_keyboard (ibase+21) /* Keyboard Module Interrupt */
-#define irq_i2c (ibase+20) /* I2C Module Interrupt */
-#define irq_spi (ibase+19) /* SPI Module Interrupt */
-#define irq_irblaster (ibase+18) /* IR Blaster Interrupt */
-#define irq_splice_detect (ibase+17) /* PID Key Change Interrupt or
- * Splice Detect Interrupt */
-#define irq_se_micro (ibase+16) /* Secure Micro I/F Module
- * Interrupt */
-#define irq_uart1 (ibase+15) /* UART Interrupt */
-#define irq_irrecv (ibase+14) /* IR Receiver Interrupt */
-#define irq_host_int1 (ibase+13) /* Host-to-Host Interrupt 1 */
-#define irq_host_int0 (ibase+12) /* Host-to-Host Interrupt 0 */
-#define irq_qpsk_hecerr (ibase+11) /* QPSK HEC Error Interrupt */
-#define irq_qpsk_crcerr (ibase+10) /* QPSK AAL-5 CRC Error
- * Interrupt */
-/* 9 unused (bit 09) */
-/* 8 unused (bit 08) */
-#define irq_psicrcerr (ibase+7) /* QAM PSI CRC Error
- * Interrupt */
-#define irq_psilength_err (ibase+6) /* QAM PSI Length Error
- * Interrupt */
-#define irq_esfforward (ibase+5) /* ESF Interrupt Mark From
- * Forward Path Reference -
- * every 3ms when forward Mbits
- * and forward slot control
- * bytes are updated. */
-#define irq_esfreverse (ibase+4) /* ESF Interrupt Mark from
- * Reverse Path Reference -
- * delayed from forward mark by
- * the ranging delay plus a
- * fixed amount. When reverse
- * Mbits and reverse slot
- * control bytes are updated.
- * Occurs every 3ms for 3.0M and
- * 1.554 M upstream rates and
- * every 6 ms for 256K upstream
- * rate. */
-#define irq_aloha_timeout (ibase+3) /* Slotted-Aloha timeout on
- * Channel 1. */
-#define irq_reservation (ibase+2) /* Partial (or Incremental)
- * Reservation Message Completed
- * or Slotted aloha verify for
- * channel 1. */
-#define irq_aloha3 (ibase+1) /* Slotted-Aloha Message Verify
- * Interrupt or Reservation
- * increment completed for
- * channel 3. */
-#define irq_mpeg_d (ibase+0) /* MPEG Decoder Interrupt */
-#endif /* _ASM_MACH_POWERTV_INTERRUPTS_H_ */
diff --git a/arch/mips/include/asm/mach-powertv/ioremap.h b/arch/mips/include/asm/mach-powertv/ioremap.h
deleted file mode 100644
index c86ef094ec37..000000000000
--- a/arch/mips/include/asm/mach-powertv/ioremap.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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.
- *
- * Portions Copyright (C) Cisco Systems, Inc.
- */
-#ifndef __ASM_MACH_POWERTV_IOREMAP_H
-#define __ASM_MACH_POWERTV_IOREMAP_H
-
-#include <linux/types.h>
-#include <linux/log2.h>
-#include <linux/compiler.h>
-
-#include <asm/pgtable-bits.h>
-#include <asm/addrspace.h>
-
-/* We're going to mess with bits, so get sizes */
-#define IOR_BPC 8 /* Bits per char */
-#define IOR_PHYS_BITS (IOR_BPC * sizeof(phys_addr_t))
-#define IOR_DMA_BITS (IOR_BPC * sizeof(dma_addr_t))
-
-/*
- * Define the granularity of physical/DMA mapping in terms of the number
- * of bits that defines the offset within a grain. These will be the
- * least significant bits of the address. The rest of a physical or DMA
- * address will be used to index into an appropriate table to find the
- * offset to add to the address to yield the corresponding DMA or physical
- * address, respectively.
- */
-#define IOR_LSBITS 22 /* Bits in a grain */
-
-/*
- * Compute the number of most significant address bits after removing those
- * used for the offset within a grain and then compute the number of table
- * entries for the conversion.
- */
-#define IOR_PHYS_MSBITS (IOR_PHYS_BITS - IOR_LSBITS)
-#define IOR_NUM_PHYS_TO_DMA ((phys_addr_t) 1 << IOR_PHYS_MSBITS)
-
-#define IOR_DMA_MSBITS (IOR_DMA_BITS - IOR_LSBITS)
-#define IOR_NUM_DMA_TO_PHYS ((dma_addr_t) 1 << IOR_DMA_MSBITS)
-
-/*
- * Define data structures used as elements in the arrays for the conversion
- * between physical and DMA addresses. We do some slightly fancy math to
- * compute the width of the offset element of the conversion tables so
- * that we can have the smallest conversion tables. Next, round up the
- * sizes to the next higher power of two, i.e. the offset element will have
- * 8, 16, 32, 64, etc. bits. This eliminates the need to mask off any
- * bits. Finally, we compute a shift value that puts the most significant
- * bits of the offset into the most significant bits of the offset element.
- * This makes it more efficient on processors without barrel shifters and
- * easier to see the values if the conversion table is dumped in binary.
- */
-#define _IOR_OFFSET_WIDTH(n) (1 << order_base_2(n))
-#define IOR_OFFSET_WIDTH(n) \
- (_IOR_OFFSET_WIDTH(n) < 8 ? 8 : _IOR_OFFSET_WIDTH(n))
-
-#define IOR_PHYS_OFFSET_BITS IOR_OFFSET_WIDTH(IOR_PHYS_MSBITS)
-#define IOR_PHYS_SHIFT (IOR_PHYS_BITS - IOR_PHYS_OFFSET_BITS)
-
-#define IOR_DMA_OFFSET_BITS IOR_OFFSET_WIDTH(IOR_DMA_MSBITS)
-#define IOR_DMA_SHIFT (IOR_DMA_BITS - IOR_DMA_OFFSET_BITS)
-
-struct ior_phys_to_dma {
- dma_addr_t offset:IOR_DMA_OFFSET_BITS __packed
- __aligned((IOR_DMA_OFFSET_BITS / IOR_BPC));
-};
-
-struct ior_dma_to_phys {
- dma_addr_t offset:IOR_PHYS_OFFSET_BITS __packed
- __aligned((IOR_PHYS_OFFSET_BITS / IOR_BPC));
-};
-
-extern struct ior_phys_to_dma _ior_phys_to_dma[IOR_NUM_PHYS_TO_DMA];
-extern struct ior_dma_to_phys _ior_dma_to_phys[IOR_NUM_DMA_TO_PHYS];
-
-static inline dma_addr_t _phys_to_dma_offset_raw(phys_addr_t phys)
-{
- return (dma_addr_t)_ior_phys_to_dma[phys >> IOR_LSBITS].offset;
-}
-
-static inline dma_addr_t _dma_to_phys_offset_raw(dma_addr_t dma)
-{
- return (dma_addr_t)_ior_dma_to_phys[dma >> IOR_LSBITS].offset;
-}
-
-/* These are not portable and should not be used in drivers. Drivers should
- * be using ioremap() and friends to map physical addresses to virtual
- * addresses and dma_map*() and friends to map virtual addresses into DMA
- * addresses and back.
- */
-static inline dma_addr_t phys_to_dma(phys_addr_t phys)
-{
- return phys + (_phys_to_dma_offset_raw(phys) << IOR_PHYS_SHIFT);
-}
-
-static inline phys_addr_t dma_to_phys(dma_addr_t dma)
-{
- return dma + (_dma_to_phys_offset_raw(dma) << IOR_DMA_SHIFT);
-}
-
-extern void ioremap_add_map(dma_addr_t phys, phys_addr_t alias,
- dma_addr_t size);
-
-/*
- * Allow physical addresses to be fixed up to help peripherals located
- * outside the low 32-bit range -- generic pass-through version.
- */
-static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
-{
- return phys_addr;
-}
-
-/*
- * Handle the special case of addresses the area aliased into the first
- * 512 MiB of the processor's physical address space. These turn into either
- * kseg0 or kseg1 addresses, depending on flags.
- */
-static inline void __iomem *plat_ioremap(phys_t start, unsigned long size,
- unsigned long flags)
-{
- phys_addr_t start_offset;
- void __iomem *result = NULL;
-
- /* Start by checking to see whether this is an aliased address */
- start_offset = _dma_to_phys_offset_raw(start);
-
- /*
- * If:
- * o the memory is aliased into the first 512 MiB, and
- * o the start and end are in the same RAM bank, and
- * o we don't have a zero size or wrap around, and
- * o we are supposed to create an uncached mapping,
- * handle this is a kseg0 or kseg1 address
- */
- if (start_offset != 0) {
- phys_addr_t last;
- dma_addr_t dma_to_phys_offset;
-
- last = start + size - 1;
- dma_to_phys_offset =
- _dma_to_phys_offset_raw(last) << IOR_DMA_SHIFT;
-
- if (dma_to_phys_offset == start_offset &&
- size != 0 && start <= last) {
- phys_t adjusted_start;
- adjusted_start = start + start_offset;
- if (flags == _CACHE_UNCACHED)
- result = (void __iomem *) (unsigned long)
- CKSEG1ADDR(adjusted_start);
- else
- result = (void __iomem *) (unsigned long)
- CKSEG0ADDR(adjusted_start);
- }
- }
-
- return result;
-}
-
-static inline int plat_iounmap(const volatile void __iomem *addr)
-{
- return 0;
-}
-#endif /* __ASM_MACH_POWERTV_IOREMAP_H */
diff --git a/arch/mips/include/asm/mach-powertv/irq.h b/arch/mips/include/asm/mach-powertv/irq.h
deleted file mode 100644
index 4bd5d0c61a91..000000000000
--- a/arch/mips/include/asm/mach-powertv/irq.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2009 Cisco Systems, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _ASM_MACH_POWERTV_IRQ_H
-#define _ASM_MACH_POWERTV_IRQ_H
-#include <asm/mach-powertv/interrupts.h>
-
-#define MIPS_CPU_IRQ_BASE ibase
-#define NR_IRQS 127
-#endif
diff --git a/arch/mips/include/asm/mach-powertv/powertv-clock.h b/arch/mips/include/asm/mach-powertv/powertv-clock.h
deleted file mode 100644
index 6f3e9a0fcf8c..000000000000
--- a/arch/mips/include/asm/mach-powertv/powertv-clock.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2009 Cisco Systems, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-/*
- * Local definitions for the powertv PCI code
- */
-
-#ifndef _POWERTV_PCI_POWERTV_PCI_H_
-#define _POWERTV_PCI_POWERTV_PCI_H_
-extern int asic_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
-extern int asic_pcie_init(void);
-extern int asic_pcie_init(void);
-
-extern int log_level;
-#endif
diff --git a/arch/mips/include/asm/mach-powertv/war.h b/arch/mips/include/asm/mach-powertv/war.h
deleted file mode 100644
index c5651c8e58d1..000000000000
--- a/arch/mips/include/asm/mach-powertv/war.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.
- *
- * This version for the PowerTV platform copied from the Malta version.
- *
- * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- */
-#ifndef __ASM_MACH_POWERTV_WAR_H
-#define __ASM_MACH_POWERTV_WAR_H
-
-#define R4600_V1_INDEX_ICACHEOP_WAR 0
-#define R4600_V1_HIT_CACHEOP_WAR 0
-#define R4600_V2_HIT_CACHEOP_WAR 0
-#define R5432_CP0_INTERRUPT_WAR 0
-#define BCM1250_M3_WAR 0
-#define SIBYTE_1956_WAR 0
-#define MIPS4K_ICACHE_REFILL_WAR 1
-#define MIPS_CACHE_SYNC_WAR 1
-#define TX49XX_ICACHE_INDEX_INV_WAR 0
-#define ICACHE_REFILLS_WORKAROUND_WAR 1
-#define R10000_LLSC_WAR 0
-#define MIPS34K_MISSED_ITLB_WAR 0
-
-#endif /* __ASM_MACH_POWERTV_WAR_H */
diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index 3b29079b5424..e277bbad2871 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -24,21 +24,21 @@
#endif /* SMTC */
#include <asm-generic/mm_hooks.h>
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
-
#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
do { \
extern void tlbmiss_handler_setup_pgd(unsigned long); \
tlbmiss_handler_setup_pgd((unsigned long)(pgd)); \
} while (0)
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
#define TLBMISS_HANDLER_SETUP() \
do { \
TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir); \
- write_c0_xcontext((unsigned long) smp_processor_id() << 51); \
+ write_c0_xcontext((unsigned long) smp_processor_id() << \
+ SMP_CPUID_REGSHIFT); \
} while (0)
-#else /* CONFIG_MIPS_PGD_C0_CONTEXT: using pgd_current*/
+#else /* !CONFIG_MIPS_PGD_C0_CONTEXT: using pgd_current*/
/*
* For the fast tlb miss handlers, we keep a per cpu array of pointers
@@ -47,21 +47,11 @@ do { \
*/
extern unsigned long pgd_current[];
-#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
- pgd_current[smp_processor_id()] = (unsigned long)(pgd)
-
-#ifdef CONFIG_32BIT
#define TLBMISS_HANDLER_SETUP() \
- write_c0_context((unsigned long) smp_processor_id() << 25); \
+ write_c0_context((unsigned long) smp_processor_id() << \
+ SMP_CPUID_REGSHIFT); \
back_to_back_c0_hazard(); \
TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
-#endif
-#ifdef CONFIG_64BIT
-#define TLBMISS_HANDLER_SETUP() \
- write_c0_context((unsigned long) smp_processor_id() << 26); \
- back_to_back_c0_hazard(); \
- TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
-#endif
#endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/
#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index 5e6cd0947393..7bba9da110af 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -81,7 +81,6 @@ static inline long regs_return_value(struct pt_regs *regs)
#define instruction_pointer(regs) ((regs)->cp0_epc)
#define profile_pc(regs) instruction_pointer(regs)
-#define user_stack_pointer(r) ((r)->regs[29])
extern asmlinkage void syscall_trace_enter(struct pt_regs *regs);
extern asmlinkage void syscall_trace_leave(struct pt_regs *regs);
@@ -100,4 +99,17 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs)
(struct pt_regs *)((sp | (THREAD_SIZE - 1)) + 1 - 32) - 1; \
})
+/* Helpers for working with the user stack pointer */
+
+static inline unsigned long user_stack_pointer(struct pt_regs *regs)
+{
+ return regs->regs[29];
+}
+
+static inline void user_stack_pointer_set(struct pt_regs *regs,
+ unsigned long val)
+{
+ regs->regs[29] = val;
+}
+
#endif /* _ASM_PTRACE_H */
diff --git a/arch/mips/include/asm/setup.h b/arch/mips/include/asm/setup.h
index e26589ef36ee..d7bfdeba9e84 100644
--- a/arch/mips/include/asm/setup.h
+++ b/arch/mips/include/asm/setup.h
@@ -5,6 +5,14 @@
extern void setup_early_printk(void);
+#ifdef CONFIG_EARLY_PRINTK_8250
+extern void setup_8250_early_printk_port(unsigned long base,
+ unsigned int reg_shift, unsigned int timeout);
+#else
+static inline void setup_8250_early_printk_port(unsigned long base,
+ unsigned int reg_shift, unsigned int timeout) {}
+#endif
+
extern void set_handler(unsigned long offset, void *addr, unsigned long len);
extern void set_uncached_handler(unsigned long offset, void *addr, unsigned long len);
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index 23fc95e65673..4857e2c8df5a 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -17,6 +17,7 @@
#include <asm/asmmacro.h>
#include <asm/mipsregs.h>
#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
/*
* For SMTC kernel, global IE should be left set, and interrupts
@@ -93,21 +94,8 @@
.endm
#ifdef CONFIG_SMP
-#ifdef CONFIG_MIPS_MT_SMTC
-#define PTEBASE_SHIFT 19 /* TCBIND */
-#define CPU_ID_REG CP0_TCBIND
-#define CPU_ID_MFC0 mfc0
-#elif defined(CONFIG_MIPS_PGD_C0_CONTEXT)
-#define PTEBASE_SHIFT 48 /* XCONTEXT */
-#define CPU_ID_REG CP0_XCONTEXT
-#define CPU_ID_MFC0 MFC0
-#else
-#define PTEBASE_SHIFT 23 /* CONTEXT */
-#define CPU_ID_REG CP0_CONTEXT
-#define CPU_ID_MFC0 MFC0
-#endif
.macro get_saved_sp /* SMP variation */
- CPU_ID_MFC0 k0, CPU_ID_REG
+ ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG
#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
lui k1, %hi(kernelsp)
#else
@@ -117,17 +105,17 @@
daddiu k1, %hi(kernelsp)
dsll k1, 16
#endif
- LONG_SRL k0, PTEBASE_SHIFT
+ LONG_SRL k0, SMP_CPUID_PTRSHIFT
LONG_ADDU k1, k0
LONG_L k1, %lo(kernelsp)(k1)
.endm
.macro set_saved_sp stackp temp temp2
- CPU_ID_MFC0 \temp, CPU_ID_REG
- LONG_SRL \temp, PTEBASE_SHIFT
+ ASM_CPUID_MFC0 \temp, ASM_SMP_CPUID_REG
+ LONG_SRL \temp, SMP_CPUID_PTRSHIFT
LONG_S \stackp, kernelsp(\temp)
.endm
-#else
+#else /* !CONFIG_SMP */
.macro get_saved_sp /* Uniprocessor variation */
#ifdef CONFIG_CPU_JUMP_WORKAROUNDS
/*
diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h
new file mode 100644
index 000000000000..81c89132c59d
--- /dev/null
+++ b/arch/mips/include/asm/syscall.h
@@ -0,0 +1,116 @@
+/*
+ * Access to user system call parameters and results
+ *
+ * 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.
+ *
+ * See asm-generic/syscall.h for descriptions of what we must do here.
+ *
+ * Copyright (C) 2012 Ralf Baechle <ralf@linux-mips.org>
+ */
+
+#ifndef __ASM_MIPS_SYSCALL_H
+#define __ASM_MIPS_SYSCALL_H
+
+#include <linux/audit.h>
+#include <linux/elf-em.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <asm/ptrace.h>
+
+static inline long syscall_get_nr(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ return regs->regs[2];
+}
+
+static inline unsigned long mips_get_syscall_arg(unsigned long *arg,
+ struct task_struct *task, struct pt_regs *regs, unsigned int n)
+{
+ unsigned long usp = regs->regs[29];
+
+ switch (n) {
+ case 0: case 1: case 2: case 3:
+ *arg = regs->regs[4 + n];
+
+ return 0;
+
+#ifdef CONFIG_32BIT
+ case 4: case 5: case 6: case 7:
+ return get_user(*arg, (int *)usp + 4 * n);
+#endif
+
+#ifdef CONFIG_64BIT
+ case 4: case 5: case 6: case 7:
+#ifdef CONFIG_MIPS32_O32
+ if (test_thread_flag(TIF_32BIT_REGS))
+ return get_user(*arg, (int *)usp + 4 * n);
+ else
+#endif
+ *arg = regs->regs[4 + n];
+
+ return 0;
+#endif
+
+ default:
+ BUG();
+ }
+}
+
+static inline long syscall_get_return_value(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ return regs->regs[2];
+}
+
+static inline void syscall_set_return_value(struct task_struct *task,
+ struct pt_regs *regs,
+ int error, long val)
+{
+ if (error) {
+ regs->regs[2] = -error;
+ regs->regs[7] = -1;
+ } else {
+ regs->regs[2] = val;
+ regs->regs[7] = 0;
+ }
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+ struct pt_regs *regs,
+ unsigned int i, unsigned int n,
+ unsigned long *args)
+{
+ unsigned long arg;
+ int ret;
+
+ while (n--)
+ ret |= mips_get_syscall_arg(&arg, task, regs, i++);
+
+ /*
+ * No way to communicate an error because this is a void function.
+ */
+#if 0
+ return ret;
+#endif
+}
+
+extern const unsigned long sys_call_table[];
+extern const unsigned long sys32_call_table[];
+extern const unsigned long sysn32_call_table[];
+
+static inline int __syscall_get_arch(void)
+{
+ int arch = EM_MIPS;
+#ifdef CONFIG_64BIT
+ arch |= __AUDIT_ARCH_64BIT;
+#endif
+#if defined(__LITTLE_ENDIAN)
+ arch |= __AUDIT_ARCH_LE;
+#endif
+ return arch;
+}
+
+#endif /* __ASM_MIPS_SYSCALL_H */
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 61215a34acc6..f9b24bfbdbae 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -116,6 +116,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_32BIT_ADDR 23 /* 32-bit address space (o32/n32) */
#define TIF_FPUBOUND 24 /* thread bound to FPU-full CPU set */
#define TIF_LOAD_WATCH 25 /* If set, load watch registers */
+#define TIF_SYSCALL_TRACEPOINT 26 /* syscall tracepoint instrumentation */
#define TIF_SYSCALL_TRACE 31 /* syscall trace active */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -132,21 +133,54 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_32BIT_ADDR (1<<TIF_32BIT_ADDR)
#define _TIF_FPUBOUND (1<<TIF_FPUBOUND)
#define _TIF_LOAD_WATCH (1<<TIF_LOAD_WATCH)
+#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
#define _TIF_WORK_SYSCALL_ENTRY (_TIF_NOHZ | _TIF_SYSCALL_TRACE | \
- _TIF_SYSCALL_AUDIT)
+ _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT)
/* work to do in syscall_trace_leave() */
#define _TIF_WORK_SYSCALL_EXIT (_TIF_NOHZ | _TIF_SYSCALL_TRACE | \
- _TIF_SYSCALL_AUDIT)
+ _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK \
(_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME)
/* work to do on any return to u-space */
#define _TIF_ALLWORK_MASK (_TIF_NOHZ | _TIF_WORK_MASK | \
- _TIF_WORK_SYSCALL_EXIT)
+ _TIF_WORK_SYSCALL_EXIT | \
+ _TIF_SYSCALL_TRACEPOINT)
-#endif /* __KERNEL__ */
+/*
+ * We stash processor id into a COP0 register to retrieve it fast
+ * at kernel exception entry.
+ */
+#if defined(CONFIG_MIPS_MT_SMTC)
+#define SMP_CPUID_REG 2, 2 /* TCBIND */
+#define ASM_SMP_CPUID_REG $2, 2
+#define SMP_CPUID_PTRSHIFT 19
+#elif defined(CONFIG_MIPS_PGD_C0_CONTEXT)
+#define SMP_CPUID_REG 20, 0 /* XCONTEXT */
+#define ASM_SMP_CPUID_REG $20
+#define SMP_CPUID_PTRSHIFT 48
+#else
+#define SMP_CPUID_REG 4, 0 /* CONTEXT */
+#define ASM_SMP_CPUID_REG $4
+#define SMP_CPUID_PTRSHIFT 23
+#endif
+#ifdef CONFIG_64BIT
+#define SMP_CPUID_REGSHIFT (SMP_CPUID_PTRSHIFT + 3)
+#else
+#define SMP_CPUID_REGSHIFT (SMP_CPUID_PTRSHIFT + 2)
+#endif
+
+#ifdef CONFIG_MIPS_MT_SMTC
+#define ASM_CPUID_MFC0 mfc0
+#define UASM_i_CPUID_MFC0 uasm_i_mfc0
+#else
+#define ASM_CPUID_MFC0 MFC0
+#define UASM_i_CPUID_MFC0 UASM_i_MFC0
+#endif
+
+#endif /* __KERNEL__ */
#endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h
index 63c9c886173a..4d3b92886665 100644
--- a/arch/mips/include/asm/unistd.h
+++ b/arch/mips/include/asm/unistd.h
@@ -14,6 +14,13 @@
#include <uapi/asm/unistd.h>
+#ifdef CONFIG_MIPS32_N32
+#define NR_syscalls (__NR_N32_Linux + __NR_N32_Linux_syscalls)
+#elif defined(CONFIG_64BIT)
+#define NR_syscalls (__NR_64_Linux + __NR_64_Linux_syscalls)
+#else
+#define NR_syscalls (__NR_O32_Linux + __NR_O32_Linux_syscalls)
+#endif
#ifndef __ASSEMBLY__
diff --git a/arch/mips/include/uapi/asm/siginfo.h b/arch/mips/include/uapi/asm/siginfo.h
index 88e292b7719e..e81174432bab 100644
--- a/arch/mips/include/uapi/asm/siginfo.h
+++ b/arch/mips/include/uapi/asm/siginfo.h
@@ -33,6 +33,8 @@ struct siginfo;
#error _MIPS_SZLONG neither 32 nor 64
#endif
+#define __ARCH_SIGSYS
+
#include <asm-generic/siginfo.h>
typedef struct siginfo {
@@ -97,6 +99,13 @@ typedef struct siginfo {
__ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd;
} _sigpoll;
+
+ /* SIGSYS */
+ struct {
+ void __user *_call_addr; /* calling user insn */
+ int _syscall; /* triggering system call number */
+ unsigned int _arch; /* AUDIT_ARCH_* of syscall */
+ } _sigsys;
} _sifields;
} siginfo_t;
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 423d871a946b..1c1b71752c84 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -26,7 +26,6 @@ obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o
obj-$(CONFIG_CSRC_BCM1480) += csrc-bcm1480.o
obj-$(CONFIG_CSRC_GIC) += csrc-gic.o
obj-$(CONFIG_CSRC_IOASIC) += csrc-ioasic.o
-obj-$(CONFIG_CSRC_POWERTV) += csrc-powertv.o
obj-$(CONFIG_CSRC_R4K) += csrc-r4k.o
obj-$(CONFIG_CSRC_SB1250) += csrc-sb1250.o
obj-$(CONFIG_SYNC_R4K) += sync-r4k.o
@@ -35,6 +34,7 @@ obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_MODULES) += mips_ksyms.o module.o
obj-$(CONFIG_MODULES_USE_ELF_RELA) += module-rela.o
+obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o
obj-$(CONFIG_CPU_R4K_FPU) += r4k_fpu.o r4k_switch.o
@@ -84,6 +84,7 @@ obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+obj-$(CONFIG_EARLY_PRINTK_8250) += early_printk_8250.o
obj-$(CONFIG_SPINLOCK_TEST) += spinlock_test.o
obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 5465dc183e5a..040b83de00ac 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -376,13 +376,33 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "R4000PC";
}
} else {
+ int cca = read_c0_config() & CONF_CM_CMASK;
+ int mc;
+
+ /*
+ * SC and MC versions can't be reliably told apart,
+ * but only the latter support coherent caching
+ * modes so assume the firmware has set the KSEG0
+ * coherency attribute reasonably (if uncached, we
+ * assume SC).
+ */
+ switch (cca) {
+ case CONF_CM_CACHABLE_CE:
+ case CONF_CM_CACHABLE_COW:
+ case CONF_CM_CACHABLE_CUW:
+ mc = 1;
+ break;
+ default:
+ mc = 0;
+ break;
+ }
if ((c->processor_id & PRID_REV_MASK) >=
PRID_REV_R4400) {
- c->cputype = CPU_R4400SC;
- __cpu_name[cpu] = "R4400SC";
+ c->cputype = mc ? CPU_R4400MC : CPU_R4400SC;
+ __cpu_name[cpu] = mc ? "R4400MC" : "R4400SC";
} else {
- c->cputype = CPU_R4000SC;
- __cpu_name[cpu] = "R4000SC";
+ c->cputype = mc ? CPU_R4000MC : CPU_R4000SC;
+ __cpu_name[cpu] = mc ? "R4000MC" : "R4000SC";
}
}
diff --git a/arch/mips/kernel/csrc-powertv.c b/arch/mips/kernel/csrc-powertv.c
deleted file mode 100644
index abd99ea911ae..000000000000
--- a/arch/mips/kernel/csrc-powertv.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2008 Scientific-Atlanta, Inc.
- *
- * 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.
- */
-/*
- * The file comes from kernel/csrc-r4k.c
- */
-#include <linux/clocksource.h>
-#include <linux/init.h>
-
-#include <asm/time.h> /* Not included in linux/time.h */
-
-#include <asm/mach-powertv/asic_regs.h>
-#include "powertv-clock.h"
-
-/* MIPS PLL Register Definitions */
-#define PLL_GET_M(x) (((x) >> 8) & 0x000000FF)
-#define PLL_GET_N(x) (((x) >> 16) & 0x000000FF)
-#define PLL_GET_P(x) (((x) >> 24) & 0x00000007)
-
-/*
- * returns: Clock frequency in kHz
- */
-unsigned int __init mips_get_pll_freq(void)
-{
- unsigned int pll_reg, m, n, p;
- unsigned int fin = 54000; /* Base frequency in kHz */
- unsigned int fout;
-
- /* Read PLL register setting */
- pll_reg = asic_read(mips_pll_setup);
- m = PLL_GET_M(pll_reg);
- n = PLL_GET_N(pll_reg);
- p = PLL_GET_P(pll_reg);
- pr_info("MIPS PLL Register:0x%x M=%d N=%d P=%d\n", pll_reg, m, n, p);
-
- /* Calculate clock frequency = (2 * N * 54MHz) / (M * (2**P)) */
- fout = ((2 * n * fin) / (m * (0x01 << p)));
-
- pr_info("MIPS Clock Freq=%d kHz\n", fout);
-
- return fout;
-}
-
-static cycle_t c0_hpt_read(struct clocksource *cs)
-{
- return read_c0_count();
-}
-
-static struct clocksource clocksource_mips = {
- .name = "powertv-counter",
- .read = c0_hpt_read,
- .mask = CLOCKSOURCE_MASK(32),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static void __init powertv_c0_hpt_clocksource_init(void)
-{
- unsigned int pll_freq = mips_get_pll_freq();
-
- pr_info("CPU frequency %d.%02d MHz\n", pll_freq / 1000,
- (pll_freq % 1000) * 100 / 1000);
-
- mips_hpt_frequency = pll_freq / 2 * 1000;
-
- clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
-
- clocksource_register_hz(&clocksource_mips, mips_hpt_frequency);
-}
-
-/**
- * struct tim_c - free running counter
- * @hi: High 16 bits of the counter
- * @lo: Low 32 bits of the counter
- *
- * Lays out the structure of the free running counter in memory. This counter
- * increments at a rate of 27 MHz/8 on all platforms.
- */
-struct tim_c {
- unsigned int hi;
- unsigned int lo;
-};
-
-static struct tim_c *tim_c;
-
-static cycle_t tim_c_read(struct clocksource *cs)
-{
- unsigned int hi;
- unsigned int next_hi;
- unsigned int lo;
-
- hi = readl(&tim_c->hi);
-
- for (;;) {
- lo = readl(&tim_c->lo);
- next_hi = readl(&tim_c->hi);
- if (next_hi == hi)
- break;
- hi = next_hi;
- }
-
-pr_crit("%s: read %llx\n", __func__, ((u64) hi << 32) | lo);
- return ((u64) hi << 32) | lo;
-}
-
-#define TIM_C_SIZE 48 /* # bits in the timer */
-
-static struct clocksource clocksource_tim_c = {
- .name = "powertv-tim_c",
- .read = tim_c_read,
- .mask = CLOCKSOURCE_MASK(TIM_C_SIZE),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-/**
- * powertv_tim_c_clocksource_init - set up a clock source for the TIM_C clock
- *
- * We know that TIM_C counts at 27 MHz/8, so each cycle corresponds to
- * 1 / (27,000,000/8) seconds.
- */
-static void __init powertv_tim_c_clocksource_init(void)
-{
- const unsigned long counts_per_second = 27000000 / 8;
-
- clocksource_tim_c.rating = 200;
-
- clocksource_register_hz(&clocksource_tim_c, counts_per_second);
- tim_c = (struct tim_c *) asic_reg_addr(tim_ch);
-}
-
-/**
- powertv_clocksource_init - initialize all clocksources
- */
-void __init powertv_clocksource_init(void)
-{
- powertv_c0_hpt_clocksource_init();
- powertv_tim_c_clocksource_init();
-}
diff --git a/arch/mips/kernel/early_printk_8250.c b/arch/mips/kernel/early_printk_8250.c
new file mode 100644
index 000000000000..83cea3767556
--- /dev/null
+++ b/arch/mips/kernel/early_printk_8250.c
@@ -0,0 +1,66 @@
+/*
+ * 8250/16550-type serial ports prom_putchar()
+ *
+ * Copyright (C) 2010 Yoichi Yuasa <yuasa@linux-mips.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/io.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+
+static void __iomem *serial8250_base;
+static unsigned int serial8250_reg_shift;
+static unsigned int serial8250_tx_timeout;
+
+void setup_8250_early_printk_port(unsigned long base, unsigned int reg_shift,
+ unsigned int timeout)
+{
+ serial8250_base = (void __iomem *)base;
+ serial8250_reg_shift = reg_shift;
+ serial8250_tx_timeout = timeout;
+}
+
+static inline u8 serial_in(int offset)
+{
+ return readb(serial8250_base + (offset << serial8250_reg_shift));
+}
+
+static inline void serial_out(int offset, char value)
+{
+ writeb(value, serial8250_base + (offset << serial8250_reg_shift));
+}
+
+void prom_putchar(char c)
+{
+ unsigned int timeout;
+ int status, bits;
+
+ if (!serial8250_base)
+ return;
+
+ timeout = serial8250_tx_timeout;
+ bits = UART_LSR_TEMT | UART_LSR_THRE;
+
+ do {
+ status = serial_in(UART_LSR);
+
+ if (--timeout == 0)
+ break;
+ } while ((status & bits) != bits);
+
+ if (timeout)
+ serial_out(UART_TX, c);
+}
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index dba90ec0dc38..185ba258361b 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -11,11 +11,14 @@
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/ftrace.h>
+#include <linux/syscalls.h>
#include <asm/asm.h>
#include <asm/asm-offsets.h>
#include <asm/cacheflush.h>
+#include <asm/syscall.h>
#include <asm/uasm.h>
+#include <asm/unistd.h>
#include <asm-generic/sections.h>
@@ -364,3 +367,33 @@ out:
WARN_ON(1);
}
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+#ifdef CONFIG_FTRACE_SYSCALLS
+
+#ifdef CONFIG_32BIT
+unsigned long __init arch_syscall_addr(int nr)
+{
+ return (unsigned long)sys_call_table[nr - __NR_O32_Linux];
+}
+#endif
+
+#ifdef CONFIG_64BIT
+
+unsigned long __init arch_syscall_addr(int nr)
+{
+#ifdef CONFIG_MIPS32_N32
+ if (nr >= __NR_N32_Linux && nr <= __NR_N32_Linux + __NR_N32_Linux_syscalls)
+ return (unsigned long)sysn32_call_table[nr - __NR_N32_Linux];
+#endif
+ if (nr >= __NR_64_Linux && nr <= __NR_64_Linux + __NR_64_Linux_syscalls)
+ return (unsigned long)sys_call_table[nr - __NR_64_Linux];
+#ifdef CONFIG_MIPS32_O32
+ if (nr >= __NR_O32_Linux && nr <= __NR_O32_Linux + __NR_O32_Linux_syscalls)
+ return (unsigned long)sys32_call_table[nr - __NR_O32_Linux];
+#endif
+
+ return (unsigned long) &sys_ni_syscall;
+}
+#endif
+
+#endif /* CONFIG_FTRACE_SYSCALLS */
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 72ef2d25cbf2..e498f2b3646a 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -150,7 +150,7 @@ int __init mips_cpu_intc_init(struct device_node *of_node,
domain = irq_domain_add_legacy(of_node, 8, MIPS_CPU_IRQ_BASE, 0,
&mips_cpu_intc_irq_domain_ops, NULL);
if (!domain)
- panic("Failed to add irqdomain for MIPS CPU\n");
+ panic("Failed to add irqdomain for MIPS CPU");
return 0;
}
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index 977a623d9253..2a52568dbcd6 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -23,6 +23,7 @@
#include <linux/moduleloader.h>
#include <linux/elf.h>
#include <linux/mm.h>
+#include <linux/numa.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/fs.h>
@@ -46,7 +47,7 @@ static DEFINE_SPINLOCK(dbe_lock);
void *module_alloc(unsigned long size)
{
return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
- GFP_KERNEL, PAGE_KERNEL, -1,
+ GFP_KERNEL, PAGE_KERNEL, NUMA_NO_NODE,
__builtin_return_address(0));
}
#endif
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 8ae1ebef8b71..b52e1d2b33e0 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -16,16 +16,20 @@
*/
#include <linux/compiler.h>
#include <linux/context_tracking.h>
+#include <linux/elf.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
+#include <linux/regset.h>
#include <linux/smp.h>
#include <linux/user.h>
#include <linux/security.h>
+#include <linux/tracehook.h>
#include <linux/audit.h>
#include <linux/seccomp.h>
+#include <linux/ftrace.h>
#include <asm/byteorder.h>
#include <asm/cpu.h>
@@ -35,10 +39,14 @@
#include <asm/mipsmtregs.h>
#include <asm/pgtable.h>
#include <asm/page.h>
+#include <asm/syscall.h>
#include <asm/uaccess.h>
#include <asm/bootinfo.h>
#include <asm/reg.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
/*
* Called by kernel/ptrace.c when detaching..
*
@@ -255,6 +263,133 @@ int ptrace_set_watch_regs(struct task_struct *child,
return 0;
}
+/* regset get/set implementations */
+
+static int gpr_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ struct pt_regs *regs = task_pt_regs(target);
+
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ regs, 0, sizeof(*regs));
+}
+
+static int gpr_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ struct pt_regs newregs;
+ int ret;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &newregs,
+ 0, sizeof(newregs));
+ if (ret)
+ return ret;
+
+ *task_pt_regs(target) = newregs;
+
+ return 0;
+}
+
+static int fpr_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.fpu,
+ 0, sizeof(elf_fpregset_t));
+ /* XXX fcr31 */
+}
+
+static int fpr_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.fpu,
+ 0, sizeof(elf_fpregset_t));
+ /* XXX fcr31 */
+}
+
+enum mips_regset {
+ REGSET_GPR,
+ REGSET_FPR,
+};
+
+static const struct user_regset mips_regsets[] = {
+ [REGSET_GPR] = {
+ .core_note_type = NT_PRSTATUS,
+ .n = ELF_NGREG,
+ .size = sizeof(unsigned int),
+ .align = sizeof(unsigned int),
+ .get = gpr_get,
+ .set = gpr_set,
+ },
+ [REGSET_FPR] = {
+ .core_note_type = NT_PRFPREG,
+ .n = ELF_NFPREG,
+ .size = sizeof(elf_fpreg_t),
+ .align = sizeof(elf_fpreg_t),
+ .get = fpr_get,
+ .set = fpr_set,
+ },
+};
+
+static const struct user_regset_view user_mips_view = {
+ .name = "mips",
+ .e_machine = ELF_ARCH,
+ .ei_osabi = ELF_OSABI,
+ .regsets = mips_regsets,
+ .n = ARRAY_SIZE(mips_regsets),
+};
+
+static const struct user_regset mips64_regsets[] = {
+ [REGSET_GPR] = {
+ .core_note_type = NT_PRSTATUS,
+ .n = ELF_NGREG,
+ .size = sizeof(unsigned long),
+ .align = sizeof(unsigned long),
+ .get = gpr_get,
+ .set = gpr_set,
+ },
+ [REGSET_FPR] = {
+ .core_note_type = NT_PRFPREG,
+ .n = ELF_NFPREG,
+ .size = sizeof(elf_fpreg_t),
+ .align = sizeof(elf_fpreg_t),
+ .get = fpr_get,
+ .set = fpr_set,
+ },
+};
+
+static const struct user_regset_view user_mips64_view = {
+ .name = "mips",
+ .e_machine = ELF_ARCH,
+ .ei_osabi = ELF_OSABI,
+ .regsets = mips64_regsets,
+ .n = ARRAY_SIZE(mips_regsets),
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+#ifdef CONFIG_32BIT
+ return &user_mips_view;
+#endif
+
+#ifdef CONFIG_MIPS32_O32
+ if (test_thread_flag(TIF_32BIT_REGS))
+ return &user_mips_view;
+#endif
+
+ return &user_mips64_view;
+}
+
long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{
@@ -517,52 +652,27 @@ long arch_ptrace(struct task_struct *child, long request,
return ret;
}
-static inline int audit_arch(void)
-{
- int arch = EM_MIPS;
-#ifdef CONFIG_64BIT
- arch |= __AUDIT_ARCH_64BIT;
-#endif
-#if defined(__LITTLE_ENDIAN)
- arch |= __AUDIT_ARCH_LE;
-#endif
- return arch;
-}
-
/*
* Notification of system call entry/exit
* - triggered by current->work.syscall_trace
*/
asmlinkage void syscall_trace_enter(struct pt_regs *regs)
{
+ long ret = 0;
user_exit();
/* do the secure computing check first */
secure_computing_strict(regs->regs[2]);
- if (!(current->ptrace & PT_PTRACED))
- goto out;
-
- if (!test_thread_flag(TIF_SYSCALL_TRACE))
- goto out;
+ if (test_thread_flag(TIF_SYSCALL_TRACE) &&
+ tracehook_report_syscall_entry(regs))
+ ret = -1;
- /* The 0x80 provides a way for the tracing parent to distinguish
- between a syscall stop and SIGTRAP delivery */
- ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ?
- 0x80 : 0));
-
- /*
- * this isn't the same as continuing with a signal, but it will do
- * for normal use. strace only continues with a signal if the
- * stopping signal is not SIGTRAP. -brl
- */
- if (current->exit_code) {
- send_sig(current->exit_code, current, 1);
- current->exit_code = 0;
- }
+ if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
+ trace_sys_enter(regs, regs->regs[2]);
-out:
- audit_syscall_entry(audit_arch(), regs->regs[2],
+ audit_syscall_entry(__syscall_get_arch(),
+ regs->regs[2],
regs->regs[4], regs->regs[5],
regs->regs[6], regs->regs[7]);
}
@@ -582,26 +692,11 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs)
audit_syscall_exit(regs);
- if (!(current->ptrace & PT_PTRACED))
- return;
-
- if (!test_thread_flag(TIF_SYSCALL_TRACE))
- return;
-
- /* The 0x80 provides a way for the tracing parent to distinguish
- between a syscall stop and SIGTRAP delivery */
- ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ?
- 0x80 : 0));
+ if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
+ trace_sys_exit(regs, regs->regs[2]);
- /*
- * this isn't the same as continuing with a signal, but it will do
- * for normal use. strace only continues with a signal if the
- * stopping signal is not SIGTRAP. -brl
- */
- if (current->exit_code) {
- send_sig(current->exit_code, current, 1);
- current->exit_code = 0;
- }
+ if (test_thread_flag(TIF_SYSCALL_TRACE))
+ tracehook_report_syscall_exit(regs, 0);
user_enter();
}
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index e774bb1088b5..e8e541b40d86 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -40,17 +40,58 @@ NESTED(handle_sys, PT_SIZE, sp)
sw t1, PT_EPC(sp)
beqz t0, illegal_syscall
- sll t0, v0, 3
+ sll t0, v0, 2
la t1, sys_call_table
addu t1, t0
lw t2, (t1) # syscall routine
- lw t3, 4(t1) # >= 0 if we need stack arguments
beqz t2, illegal_syscall
sw a3, PT_R26(sp) # save a3 for syscall restarting
- bgez t3, stackargs
-stack_done:
+ /*
+ * More than four arguments. Try to deal with it by copying the
+ * stack arguments from the user stack to the kernel stack.
+ * This Sucks (TM).
+ */
+ lw t0, PT_R29(sp) # get old user stack pointer
+
+ /*
+ * We intentionally keep the kernel stack a little below the top of
+ * userspace so we don't have to do a slower byte accurate check here.
+ */
+ lw t5, TI_ADDR_LIMIT($28)
+ addu t4, t0, 32
+ and t5, t4
+ bltz t5, bad_stack # -> sp is bad
+
+ /*
+ * Ok, copy the args from the luser stack to the kernel stack.
+ * t3 is the precomputed number of instruction bytes needed to
+ * load or store arguments 6-8.
+ */
+
+ .set push
+ .set noreorder
+ .set nomacro
+
+1: lw t5, 16(t0) # argument #5 from usp
+4: lw t6, 20(t0) # argument #6 from usp
+3: lw t7, 24(t0) # argument #7 from usp
+2: lw t8, 28(t0) # argument #8 from usp
+
+ sw t5, 16(sp) # argument #5 to ksp
+ sw t6, 20(sp) # argument #6 to ksp
+ sw t7, 24(sp) # argument #7 to ksp
+ sw t8, 28(sp) # argument #8 to ksp
+ .set pop
+
+ .section __ex_table,"a"
+ PTR 1b,bad_stack
+ PTR 2b,bad_stack
+ PTR 3b,bad_stack
+ PTR 4b,bad_stack
+ .previous
+
lw t0, TI_FLAGS($28) # syscall tracing enabled?
li t1, _TIF_WORK_SYSCALL_ENTRY
and t0, t1
@@ -102,66 +143,6 @@ syscall_trace_entry:
/* ------------------------------------------------------------------------ */
/*
- * More than four arguments. Try to deal with it by copying the
- * stack arguments from the user stack to the kernel stack.
- * This Sucks (TM).
- */
-stackargs:
- lw t0, PT_R29(sp) # get old user stack pointer
-
- /*
- * We intentionally keep the kernel stack a little below the top of
- * userspace so we don't have to do a slower byte accurate check here.
- */
- lw t5, TI_ADDR_LIMIT($28)
- addu t4, t0, 32
- and t5, t4
- bltz t5, bad_stack # -> sp is bad
-
- /* Ok, copy the args from the luser stack to the kernel stack.
- * t3 is the precomputed number of instruction bytes needed to
- * load or store arguments 6-8.
- */
-
- la t1, 5f # load up to 3 arguments
- subu t1, t3
-1: lw t5, 16(t0) # argument #5 from usp
- .set push
- .set noreorder
- .set nomacro
- jr t1
- addiu t1, 6f - 5f
-
-2: lw t8, 28(t0) # argument #8 from usp
-3: lw t7, 24(t0) # argument #7 from usp
-4: lw t6, 20(t0) # argument #6 from usp
-5: jr t1
- sw t5, 16(sp) # argument #5 to ksp
-
-#ifdef CONFIG_CPU_MICROMIPS
- sw t8, 28(sp) # argument #8 to ksp
- nop
- sw t7, 24(sp) # argument #7 to ksp
- nop
- sw t6, 20(sp) # argument #6 to ksp
- nop
-#else
- sw t8, 28(sp) # argument #8 to ksp
- sw t7, 24(sp) # argument #7 to ksp
- sw t6, 20(sp) # argument #6 to ksp
-#endif
-6: j stack_done # go back
- nop
- .set pop
-
- .section __ex_table,"a"
- PTR 1b,bad_stack
- PTR 2b,bad_stack
- PTR 3b,bad_stack
- PTR 4b,bad_stack
- .previous
-
- /*
* The stackpointer for a call with more than 4 arguments is bad.
* We probably should handle this case a bit more drastic.
*/
@@ -187,7 +168,7 @@ illegal_syscall:
subu t0, a0, __NR_O32_Linux # check syscall number
sltiu v0, t0, __NR_O32_Linux_syscalls + 1
beqz t0, einval # do not recurse
- sll t1, t0, 3
+ sll t1, t0, 2
beqz v0, einval
lw t2, sys_call_table(t1) # syscall routine
@@ -218,260 +199,248 @@ einval: li v0, -ENOSYS
jr ra
END(sys_syscall)
- .macro fifty ptr, nargs, from=1, to=50
- sys \ptr \nargs
- .if \to-\from
- fifty \ptr,\nargs,"(\from+1)",\to
- .endif
- .endm
-
- .macro mille ptr, nargs, from=1, to=20
- fifty \ptr,\nargs
- .if \to-\from
- mille \ptr,\nargs,"(\from+1)",\to
- .endif
- .endm
-
- .macro syscalltable
- sys sys_syscall 8 /* 4000 */
- sys sys_exit 1
- sys __sys_fork 0
- sys sys_read 3
- sys sys_write 3
- sys sys_open 3 /* 4005 */
- sys sys_close 1
- sys sys_waitpid 3
- sys sys_creat 2
- sys sys_link 2
- sys sys_unlink 1 /* 4010 */
- sys sys_execve 0
- sys sys_chdir 1
- sys sys_time 1
- sys sys_mknod 3
- sys sys_chmod 2 /* 4015 */
- sys sys_lchown 3
- sys sys_ni_syscall 0
- sys sys_ni_syscall 0 /* was sys_stat */
- sys sys_lseek 3
- sys sys_getpid 0 /* 4020 */
- sys sys_mount 5
- sys sys_oldumount 1
- sys sys_setuid 1
- sys sys_getuid 0
- sys sys_stime 1 /* 4025 */
- sys sys_ptrace 4
- sys sys_alarm 1
- sys sys_ni_syscall 0 /* was sys_fstat */
- sys sys_pause 0
- sys sys_utime 2 /* 4030 */
- sys sys_ni_syscall 0
- sys sys_ni_syscall 0
- sys sys_access 2
- sys sys_nice 1
- sys sys_ni_syscall 0 /* 4035 */
- sys sys_sync 0
- sys sys_kill 2
- sys sys_rename 2
- sys sys_mkdir 2
- sys sys_rmdir 1 /* 4040 */
- sys sys_dup 1
- sys sysm_pipe 0
- sys sys_times 1
- sys sys_ni_syscall 0
- sys sys_brk 1 /* 4045 */
- sys sys_setgid 1
- sys sys_getgid 0
- sys sys_ni_syscall 0 /* was signal(2) */
- sys sys_geteuid 0
- sys sys_getegid 0 /* 4050 */
- sys sys_acct 1
- sys sys_umount 2
- sys sys_ni_syscall 0
- sys sys_ioctl 3
- sys sys_fcntl 3 /* 4055 */
- sys sys_ni_syscall 2
- sys sys_setpgid 2
- sys sys_ni_syscall 0
- sys sys_olduname 1
- sys sys_umask 1 /* 4060 */
- sys sys_chroot 1
- sys sys_ustat 2
- sys sys_dup2 2
- sys sys_getppid 0
- sys sys_getpgrp 0 /* 4065 */
- sys sys_setsid 0
- sys sys_sigaction 3
- sys sys_sgetmask 0
- sys sys_ssetmask 1
- sys sys_setreuid 2 /* 4070 */
- sys sys_setregid 2
- sys sys_sigsuspend 0
- sys sys_sigpending 1
- sys sys_sethostname 2
- sys sys_setrlimit 2 /* 4075 */
- sys sys_getrlimit 2
- sys sys_getrusage 2
- sys sys_gettimeofday 2
- sys sys_settimeofday 2
- sys sys_getgroups 2 /* 4080 */
- sys sys_setgroups 2
- sys sys_ni_syscall 0 /* old_select */
- sys sys_symlink 2
- sys sys_ni_syscall 0 /* was sys_lstat */
- sys sys_readlink 3 /* 4085 */
- sys sys_uselib 1
- sys sys_swapon 2
- sys sys_reboot 3
- sys sys_old_readdir 3
- sys sys_mips_mmap 6 /* 4090 */
- sys sys_munmap 2
- sys sys_truncate 2
- sys sys_ftruncate 2
- sys sys_fchmod 2
- sys sys_fchown 3 /* 4095 */
- sys sys_getpriority 2
- sys sys_setpriority 3
- sys sys_ni_syscall 0
- sys sys_statfs 2
- sys sys_fstatfs 2 /* 4100 */
- sys sys_ni_syscall 0 /* was ioperm(2) */
- sys sys_socketcall 2
- sys sys_syslog 3
- sys sys_setitimer 3
- sys sys_getitimer 2 /* 4105 */
- sys sys_newstat 2
- sys sys_newlstat 2
- sys sys_newfstat 2
- sys sys_uname 1
- sys sys_ni_syscall 0 /* 4110 was iopl(2) */
- sys sys_vhangup 0
- sys sys_ni_syscall 0 /* was sys_idle() */
- sys sys_ni_syscall 0 /* was sys_vm86 */
- sys sys_wait4 4
- sys sys_swapoff 1 /* 4115 */
- sys sys_sysinfo 1
- sys sys_ipc 6
- sys sys_fsync 1
- sys sys_sigreturn 0
- sys __sys_clone 6 /* 4120 */
- sys sys_setdomainname 2
- sys sys_newuname 1
- sys sys_ni_syscall 0 /* sys_modify_ldt */
- sys sys_adjtimex 1
- sys sys_mprotect 3 /* 4125 */
- sys sys_sigprocmask 3
- sys sys_ni_syscall 0 /* was create_module */
- sys sys_init_module 5
- sys sys_delete_module 1
- sys sys_ni_syscall 0 /* 4130 was get_kernel_syms */
- sys sys_quotactl 4
- sys sys_getpgid 1
- sys sys_fchdir 1
- sys sys_bdflush 2
- sys sys_sysfs 3 /* 4135 */
- sys sys_personality 1
- sys sys_ni_syscall 0 /* for afs_syscall */
- sys sys_setfsuid 1
- sys sys_setfsgid 1
- sys sys_llseek 5 /* 4140 */
- sys sys_getdents 3
- sys sys_select 5
- sys sys_flock 2
- sys sys_msync 3
- sys sys_readv 3 /* 4145 */
- sys sys_writev 3
- sys sys_cacheflush 3
- sys sys_cachectl 3
- sys sys_sysmips 4
- sys sys_ni_syscall 0 /* 4150 */
- sys sys_getsid 1
- sys sys_fdatasync 1
- sys sys_sysctl 1
- sys sys_mlock 2
- sys sys_munlock 2 /* 4155 */
- sys sys_mlockall 1
- sys sys_munlockall 0
- sys sys_sched_setparam 2
- sys sys_sched_getparam 2
- sys sys_sched_setscheduler 3 /* 4160 */
- sys sys_sched_getscheduler 1
- sys sys_sched_yield 0
- sys sys_sched_get_priority_max 1
- sys sys_sched_get_priority_min 1
- sys sys_sched_rr_get_interval 2 /* 4165 */
- sys sys_nanosleep, 2
- sys sys_mremap, 5
- sys sys_accept 3
- sys sys_bind 3
- sys sys_connect 3 /* 4170 */
- sys sys_getpeername 3
- sys sys_getsockname 3
- sys sys_getsockopt 5
- sys sys_listen 2
- sys sys_recv 4 /* 4175 */
- sys sys_recvfrom 6
- sys sys_recvmsg 3
- sys sys_send 4
- sys sys_sendmsg 3
- sys sys_sendto 6 /* 4180 */
- sys sys_setsockopt 5
- sys sys_shutdown 2
- sys sys_socket 3
- sys sys_socketpair 4
- sys sys_setresuid 3 /* 4185 */
- sys sys_getresuid 3
- sys sys_ni_syscall 0 /* was sys_query_module */
- sys sys_poll 3
- sys sys_ni_syscall 0 /* was nfsservctl */
- sys sys_setresgid 3 /* 4190 */
- sys sys_getresgid 3
- sys sys_prctl 5
- sys sys_rt_sigreturn 0
- sys sys_rt_sigaction 4
- sys sys_rt_sigprocmask 4 /* 4195 */
- sys sys_rt_sigpending 2
- sys sys_rt_sigtimedwait 4
- sys sys_rt_sigqueueinfo 3
- sys sys_rt_sigsuspend 0
- sys sys_pread64 6 /* 4200 */
- sys sys_pwrite64 6
- sys sys_chown 3
- sys sys_getcwd 2
- sys sys_capget 2
- sys sys_capset 2 /* 4205 */
- sys sys_sigaltstack 0
- sys sys_sendfile 4
- sys sys_ni_syscall 0
- sys sys_ni_syscall 0
- sys sys_mips_mmap2 6 /* 4210 */
- sys sys_truncate64 4
- sys sys_ftruncate64 4
- sys sys_stat64 2
- sys sys_lstat64 2
- sys sys_fstat64 2 /* 4215 */
- sys sys_pivot_root 2
- sys sys_mincore 3
- sys sys_madvise 3
- sys sys_getdents64 3
- sys sys_fcntl64 3 /* 4220 */
- sys sys_ni_syscall 0
- sys sys_gettid 0
- sys sys_readahead 5
- sys sys_setxattr 5
- sys sys_lsetxattr 5 /* 4225 */
- sys sys_fsetxattr 5
- sys sys_getxattr 4
- sys sys_lgetxattr 4
- sys sys_fgetxattr 4
- sys sys_listxattr 3 /* 4230 */
- sys sys_llistxattr 3
- sys sys_flistxattr 3
- sys sys_removexattr 2
- sys sys_lremovexattr 2
- sys sys_fremovexattr 2 /* 4235 */
- sys sys_tkill 2
- sys sys_sendfile64 5
- sys sys_futex 6
+ .align 2
+ .type sys_call_table, @object
+EXPORT(sys_call_table)
+ PTR sys_syscall /* 4000 */
+ PTR sys_exit
+ PTR __sys_fork
+ PTR sys_read
+ PTR sys_write
+ PTR sys_open /* 4005 */
+ PTR sys_close
+ PTR sys_waitpid
+ PTR sys_creat
+ PTR sys_link
+ PTR sys_unlink /* 4010 */
+ PTR sys_execve
+ PTR sys_chdir
+ PTR sys_time
+ PTR sys_mknod
+ PTR sys_chmod /* 4015 */
+ PTR sys_lchown
+ PTR sys_ni_syscall
+ PTR sys_ni_syscall /* was sys_stat */
+ PTR sys_lseek
+ PTR sys_getpid /* 4020 */
+ PTR sys_mount
+ PTR sys_oldumount
+ PTR sys_setuid
+ PTR sys_getuid
+ PTR sys_stime /* 4025 */
+ PTR sys_ptrace
+ PTR sys_alarm
+ PTR sys_ni_syscall /* was sys_fstat */
+ PTR sys_pause
+ PTR sys_utime /* 4030 */
+ PTR sys_ni_syscall
+ PTR sys_ni_syscall
+ PTR sys_access
+ PTR sys_nice
+ PTR sys_ni_syscall /* 4035 */
+ PTR sys_sync
+ PTR sys_kill
+ PTR sys_rename
+ PTR sys_mkdir
+ PTR sys_rmdir /* 4040 */
+ PTR sys_dup
+ PTR sysm_pipe
+ PTR sys_times
+ PTR sys_ni_syscall
+ PTR sys_brk /* 4045 */
+ PTR sys_setgid
+ PTR sys_getgid
+ PTR sys_ni_syscall /* was signal(2) */
+ PTR sys_geteuid
+ PTR sys_getegid /* 4050 */
+ PTR sys_acct
+ PTR sys_umount
+ PTR sys_ni_syscall
+ PTR sys_ioctl
+ PTR sys_fcntl /* 4055 */
+ PTR sys_ni_syscall
+ PTR sys_setpgid
+ PTR sys_ni_syscall
+ PTR sys_olduname
+ PTR sys_umask /* 4060 */
+ PTR sys_chroot
+ PTR sys_ustat
+ PTR sys_dup2
+ PTR sys_getppid
+ PTR sys_getpgrp /* 4065 */
+ PTR sys_setsid
+ PTR sys_sigaction
+ PTR sys_sgetmask
+ PTR sys_ssetmask
+ PTR sys_setreuid /* 4070 */
+ PTR sys_setregid
+ PTR sys_sigsuspend
+ PTR sys_sigpending
+ PTR sys_sethostname
+ PTR sys_setrlimit /* 4075 */
+ PTR sys_getrlimit
+ PTR sys_getrusage
+ PTR sys_gettimeofday
+ PTR sys_settimeofday
+ PTR sys_getgroups /* 4080 */
+ PTR sys_setgroups
+ PTR sys_ni_syscall /* old_select */
+ PTR sys_symlink
+ PTR sys_ni_syscall /* was sys_lstat */
+ PTR sys_readlink /* 4085 */
+ PTR sys_uselib
+ PTR sys_swapon
+ PTR sys_reboot
+ PTR sys_old_readdir
+ PTR sys_mips_mmap /* 4090 */
+ PTR sys_munmap
+ PTR sys_truncate
+ PTR sys_ftruncate
+ PTR sys_fchmod
+ PTR sys_fchown /* 4095 */
+ PTR sys_getpriority
+ PTR sys_setpriority
+ PTR sys_ni_syscall
+ PTR sys_statfs
+ PTR sys_fstatfs /* 4100 */
+ PTR sys_ni_syscall /* was ioperm(2) */
+ PTR sys_socketcall
+ PTR sys_syslog
+ PTR sys_setitimer
+ PTR sys_getitimer /* 4105 */
+ PTR sys_newstat
+ PTR sys_newlstat
+ PTR sys_newfstat
+ PTR sys_uname
+ PTR sys_ni_syscall /* 4110 was iopl(2) */
+ PTR sys_vhangup
+ PTR sys_ni_syscall /* was sys_idle() */
+ PTR sys_ni_syscall /* was sys_vm86 */
+ PTR sys_wait4
+ PTR sys_swapoff /* 4115 */
+ PTR sys_sysinfo
+ PTR sys_ipc
+ PTR sys_fsync
+ PTR sys_sigreturn
+ PTR __sys_clone /* 4120 */
+ PTR sys_setdomainname
+ PTR sys_newuname
+ PTR sys_ni_syscall /* sys_modify_ldt */
+ PTR sys_adjtimex
+ PTR sys_mprotect /* 4125 */
+ PTR sys_sigprocmask
+ PTR sys_ni_syscall /* was create_module */
+ PTR sys_init_module
+ PTR sys_delete_module
+ PTR sys_ni_syscall /* 4130 was get_kernel_syms */
+ PTR sys_quotactl
+ PTR sys_getpgid
+ PTR sys_fchdir
+ PTR sys_bdflush
+ PTR sys_sysfs /* 4135 */
+ PTR sys_personality
+ PTR sys_ni_syscall /* for afs_syscall */
+ PTR sys_setfsuid
+ PTR sys_setfsgid
+ PTR sys_llseek /* 4140 */
+ PTR sys_getdents
+ PTR sys_select
+ PTR sys_flock
+ PTR sys_msync
+ PTR sys_readv /* 4145 */
+ PTR sys_writev
+ PTR sys_cacheflush
+ PTR sys_cachectl
+ PTR sys_sysmips
+ PTR sys_ni_syscall /* 4150 */
+ PTR sys_getsid
+ PTR sys_fdatasync
+ PTR sys_sysctl
+ PTR sys_mlock
+ PTR sys_munlock /* 4155 */
+ PTR sys_mlockall
+ PTR sys_munlockall
+ PTR sys_sched_setparam
+ PTR sys_sched_getparam
+ PTR sys_sched_setscheduler /* 4160 */
+ PTR sys_sched_getscheduler
+ PTR sys_sched_yield
+ PTR sys_sched_get_priority_max
+ PTR sys_sched_get_priority_min
+ PTR sys_sched_rr_get_interval /* 4165 */
+ PTR sys_nanosleep
+ PTR sys_mremap
+ PTR sys_accept
+ PTR sys_bind
+ PTR sys_connect /* 4170 */
+ PTR sys_getpeername
+ PTR sys_getsockname
+ PTR sys_getsockopt
+ PTR sys_listen
+ PTR sys_recv /* 4175 */
+ PTR sys_recvfrom
+ PTR sys_recvmsg
+ PTR sys_send
+ PTR sys_sendmsg
+ PTR sys_sendto /* 4180 */
+ PTR sys_setsockopt
+ PTR sys_shutdown
+ PTR sys_socket
+ PTR sys_socketpair
+ PTR sys_setresuid /* 4185 */
+ PTR sys_getresuid
+ PTR sys_ni_syscall /* was sys_query_module */
+ PTR sys_poll
+ PTR sys_ni_syscall /* was nfsservctl */
+ PTR sys_setresgid /* 4190 */
+ PTR sys_getresgid
+ PTR sys_prctl
+ PTR sys_rt_sigreturn
+ PTR sys_rt_sigaction
+ PTR sys_rt_sigprocmask /* 4195 */
+ PTR sys_rt_sigpending
+ PTR sys_rt_sigtimedwait
+ PTR sys_rt_sigqueueinfo
+ PTR sys_rt_sigsuspend
+ PTR sys_pread64 /* 4200 */
+ PTR sys_pwrite64
+ PTR sys_chown
+ PTR sys_getcwd
+ PTR sys_capget
+ PTR sys_capset /* 4205 */
+ PTR sys_sigaltstack
+ PTR sys_sendfile
+ PTR sys_ni_syscall
+ PTR sys_ni_syscall
+ PTR sys_mips_mmap2 /* 4210 */
+ PTR sys_truncate64
+ PTR sys_ftruncate64
+ PTR sys_stat64
+ PTR sys_lstat64
+ PTR sys_fstat64 /* 4215 */
+ PTR sys_pivot_root
+ PTR sys_mincore
+ PTR sys_madvise
+ PTR sys_getdents64
+ PTR sys_fcntl64 /* 4220 */
+ PTR sys_ni_syscall
+ PTR sys_gettid
+ PTR sys_readahead
+ PTR sys_setxattr
+ PTR sys_lsetxattr /* 4225 */
+ PTR sys_fsetxattr
+ PTR sys_getxattr
+ PTR sys_lgetxattr
+ PTR sys_fgetxattr
+ PTR sys_listxattr /* 4230 */
+ PTR sys_llistxattr
+ PTR sys_flistxattr
+ PTR sys_removexattr
+ PTR sys_lremovexattr
+ PTR sys_fremovexattr /* 4235 */
+ PTR sys_tkill
+ PTR sys_sendfile64
+ PTR sys_futex
#ifdef CONFIG_MIPS_MT_FPAFF
/*
* For FPU affinity scheduling on MIPS MT processors, we need to
@@ -480,132 +449,117 @@ einval: li v0, -ENOSYS
* these hooks for the 32-bit kernel - there is no MIPS64 MT processor
* atm.
*/
- sys mipsmt_sys_sched_setaffinity 3
- sys mipsmt_sys_sched_getaffinity 3
+ PTR mipsmt_sys_sched_setaffinity
+ PTR mipsmt_sys_sched_getaffinity
#else
- sys sys_sched_setaffinity 3
- sys sys_sched_getaffinity 3 /* 4240 */
+ PTR sys_sched_setaffinity
+ PTR sys_sched_getaffinity /* 4240 */
#endif /* CONFIG_MIPS_MT_FPAFF */
- sys sys_io_setup 2
- sys sys_io_destroy 1
- sys sys_io_getevents 5
- sys sys_io_submit 3
- sys sys_io_cancel 3 /* 4245 */
- sys sys_exit_group 1
- sys sys_lookup_dcookie 4
- sys sys_epoll_create 1
- sys sys_epoll_ctl 4
- sys sys_epoll_wait 4 /* 4250 */
- sys sys_remap_file_pages 5
- sys sys_set_tid_address 1
- sys sys_restart_syscall 0
- sys sys_fadvise64_64 7
- sys sys_statfs64 3 /* 4255 */
- sys sys_fstatfs64 2
- sys sys_timer_create 3
- sys sys_timer_settime 4
- sys sys_timer_gettime 2
- sys sys_timer_getoverrun 1 /* 4260 */
- sys sys_timer_delete 1
- sys sys_clock_settime 2
- sys sys_clock_gettime 2
- sys sys_clock_getres 2
- sys sys_clock_nanosleep 4 /* 4265 */
- sys sys_tgkill 3
- sys sys_utimes 2
- sys sys_mbind 4
- sys sys_ni_syscall 0 /* sys_get_mempolicy */
- sys sys_ni_syscall 0 /* 4270 sys_set_mempolicy */
- sys sys_mq_open 4
- sys sys_mq_unlink 1
- sys sys_mq_timedsend 5
- sys sys_mq_timedreceive 5
- sys sys_mq_notify 2 /* 4275 */
- sys sys_mq_getsetattr 3
- sys sys_ni_syscall 0 /* sys_vserver */
- sys sys_waitid 5
- sys sys_ni_syscall 0 /* available, was setaltroot */
- sys sys_add_key 5 /* 4280 */
- sys sys_request_key 4
- sys sys_keyctl 5
- sys sys_set_thread_area 1
- sys sys_inotify_init 0
- sys sys_inotify_add_watch 3 /* 4285 */
- sys sys_inotify_rm_watch 2
- sys sys_migrate_pages 4
- sys sys_openat 4
- sys sys_mkdirat 3
- sys sys_mknodat 4 /* 4290 */
- sys sys_fchownat 5
- sys sys_futimesat 3
- sys sys_fstatat64 4
- sys sys_unlinkat 3
- sys sys_renameat 4 /* 4295 */
- sys sys_linkat 5
- sys sys_symlinkat 3
- sys sys_readlinkat 4
- sys sys_fchmodat 3
- sys sys_faccessat 3 /* 4300 */
- sys sys_pselect6 6
- sys sys_ppoll 5
- sys sys_unshare 1
- sys sys_splice 6
- sys sys_sync_file_range 7 /* 4305 */
- sys sys_tee 4
- sys sys_vmsplice 4
- sys sys_move_pages 6
- sys sys_set_robust_list 2
- sys sys_get_robust_list 3 /* 4310 */
- sys sys_kexec_load 4
- sys sys_getcpu 3
- sys sys_epoll_pwait 6
- sys sys_ioprio_set 3
- sys sys_ioprio_get 2 /* 4315 */
- sys sys_utimensat 4
- sys sys_signalfd 3
- sys sys_ni_syscall 0 /* was timerfd */
- sys sys_eventfd 1
- sys sys_fallocate 6 /* 4320 */
- sys sys_timerfd_create 2
- sys sys_timerfd_gettime 2
- sys sys_timerfd_settime 4
- sys sys_signalfd4 4
- sys sys_eventfd2 2 /* 4325 */
- sys sys_epoll_create1 1
- sys sys_dup3 3
- sys sys_pipe2 2
- sys sys_inotify_init1 1
- sys sys_preadv 6 /* 4330 */
- sys sys_pwritev 6
- sys sys_rt_tgsigqueueinfo 4
- sys sys_perf_event_open 5
- sys sys_accept4 4
- sys sys_recvmmsg 5 /* 4335 */
- sys sys_fanotify_init 2
- sys sys_fanotify_mark 6
- sys sys_prlimit64 4
- sys sys_name_to_handle_at 5
- sys sys_open_by_handle_at 3 /* 4340 */
- sys sys_clock_adjtime 2
- sys sys_syncfs 1
- sys sys_sendmmsg 4
- sys sys_setns 2
- sys sys_process_vm_readv 6 /* 4345 */
- sys sys_process_vm_writev 6
- sys sys_kcmp 5
- sys sys_finit_module 3
- .endm
-
- /* We pre-compute the number of _instruction_ bytes needed to
- load or store the arguments 6-8. Negative values are ignored. */
-
- .macro sys function, nargs
- PTR \function
- LONG (\nargs << 2) - (5 << 2)
- .endm
-
- .align 3
- .type sys_call_table,@object
-EXPORT(sys_call_table)
- syscalltable
- .size sys_call_table, . - sys_call_table
+ PTR sys_io_setup
+ PTR sys_io_destroy
+ PTR sys_io_getevents
+ PTR sys_io_submit
+ PTR sys_io_cancel /* 4245 */
+ PTR sys_exit_group
+ PTR sys_lookup_dcookie
+ PTR sys_epoll_create
+ PTR sys_epoll_ctl
+ PTR sys_epoll_wait /* 4250 */
+ PTR sys_remap_file_pages
+ PTR sys_set_tid_address
+ PTR sys_restart_syscall
+ PTR sys_fadvise64_64
+ PTR sys_statfs64 /* 4255 */
+ PTR sys_fstatfs64
+ PTR sys_timer_create
+ PTR sys_timer_settime
+ PTR sys_timer_gettime
+ PTR sys_timer_getoverrun /* 4260 */
+ PTR sys_timer_delete
+ PTR sys_clock_settime
+ PTR sys_clock_gettime
+ PTR sys_clock_getres
+ PTR sys_clock_nanosleep /* 4265 */
+ PTR sys_tgkill
+ PTR sys_utimes
+ PTR sys_mbind
+ PTR sys_ni_syscall /* sys_get_mempolicy */
+ PTR sys_ni_syscall /* 4270 sys_set_mempolicy */
+ PTR sys_mq_open
+ PTR sys_mq_unlink
+ PTR sys_mq_timedsend
+ PTR sys_mq_timedreceive
+ PTR sys_mq_notify /* 4275 */
+ PTR sys_mq_getsetattr
+ PTR sys_ni_syscall /* sys_vserver */
+ PTR sys_waitid
+ PTR sys_ni_syscall /* available, was setaltroot */
+ PTR sys_add_key /* 4280 */
+ PTR sys_request_key
+ PTR sys_keyctl
+ PTR sys_set_thread_area
+ PTR sys_inotify_init
+ PTR sys_inotify_add_watch /* 4285 */
+ PTR sys_inotify_rm_watch
+ PTR sys_migrate_pages
+ PTR sys_openat
+ PTR sys_mkdirat
+ PTR sys_mknodat /* 4290 */
+ PTR sys_fchownat
+ PTR sys_futimesat
+ PTR sys_fstatat64
+ PTR sys_unlinkat
+ PTR sys_renameat /* 4295 */
+ PTR sys_linkat
+ PTR sys_symlinkat
+ PTR sys_readlinkat
+ PTR sys_fchmodat
+ PTR sys_faccessat /* 4300 */
+ PTR sys_pselect6
+ PTR sys_ppoll
+ PTR sys_unshare
+ PTR sys_splice
+ PTR sys_sync_file_range /* 4305 */
+ PTR sys_tee
+ PTR sys_vmsplice
+ PTR sys_move_pages
+ PTR sys_set_robust_list
+ PTR sys_get_robust_list /* 4310 */
+ PTR sys_kexec_load
+ PTR sys_getcpu
+ PTR sys_epoll_pwait
+ PTR sys_ioprio_set
+ PTR sys_ioprio_get /* 4315 */
+ PTR sys_utimensat
+ PTR sys_signalfd
+ PTR sys_ni_syscall /* was timerfd */
+ PTR sys_eventfd
+ PTR sys_fallocate /* 4320 */
+ PTR sys_timerfd_create
+ PTR sys_timerfd_gettime
+ PTR sys_timerfd_settime
+ PTR sys_signalfd4
+ PTR sys_eventfd2 /* 4325 */
+ PTR sys_epoll_create1
+ PTR sys_dup3
+ PTR sys_pipe2
+ PTR sys_inotify_init1
+ PTR sys_preadv /* 4330 */
+ PTR sys_pwritev
+ PTR sys_rt_tgsigqueueinfo
+ PTR sys_perf_event_open
+ PTR sys_accept4
+ PTR sys_recvmmsg /* 4335 */
+ PTR sys_fanotify_init
+ PTR sys_fanotify_mark
+ PTR sys_prlimit64
+ PTR sys_name_to_handle_at
+ PTR sys_open_by_handle_at /* 4340 */
+ PTR sys_clock_adjtime
+ PTR sys_syncfs
+ PTR sys_sendmmsg
+ PTR sys_setns
+ PTR sys_process_vm_readv /* 4345 */
+ PTR sys_process_vm_writev
+ PTR sys_kcmp
+ PTR sys_finit_module
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index be6627ead619..57e3742fec59 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -114,7 +114,8 @@ illegal_syscall:
END(handle_sys64)
.align 3
-sys_call_table:
+ .type sys_call_table, @object
+EXPORT(sys_call_table)
PTR sys_read /* 5000 */
PTR sys_write
PTR sys_open
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index cab150789c8d..2f48f5934399 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -103,6 +103,7 @@ not_n32_scall:
END(handle_sysn32)
+ .type sysn32_call_table, @object
EXPORT(sysn32_call_table)
PTR sys_read /* 6000 */
PTR sys_write
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 37605dc8eef7..f1acdb429f4f 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -53,7 +53,7 @@ NESTED(handle_sys, PT_SIZE, sp)
sll a3, a3, 0
dsll t0, v0, 3 # offset into table
- ld t2, (sys_call_table - (__NR_O32_Linux * 8))(t0)
+ ld t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
sd a3, PT_R26(sp) # save a3 for syscall restarting
@@ -168,7 +168,7 @@ LEAF(sys32_syscall)
beqz t0, einval # do not recurse
dsll t1, t0, 3
beqz v0, einval
- ld t2, sys_call_table(t1) # syscall routine
+ ld t2, sys32_call_table(t1) # syscall routine
move a0, a1 # shift argument registers
move a1, a2
@@ -190,8 +190,8 @@ einval: li v0, -ENOSYS
END(sys32_syscall)
.align 3
- .type sys_call_table,@object
-sys_call_table:
+ .type sys32_call_table,@object
+EXPORT(sys32_call_table)
PTR sys32_syscall /* 4000 */
PTR sys_exit
PTR __sys_fork
@@ -541,4 +541,4 @@ sys_call_table:
PTR compat_sys_process_vm_writev
PTR sys_kcmp
PTR sys_finit_module
- .size sys_call_table,.-sys_call_table
+ .size sys32_call_table,.-sys32_call_table
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index c538d6e01b7b..5342385628af 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -300,12 +300,13 @@ static void __init bootmem_init(void)
int i;
/*
- * Init any data related to initrd. It's a nop if INITRD is
- * not selected. Once that done we can determine the low bound
- * of usable memory.
+ * Sanity check any INITRD first. We don't take it into account
+ * for bootmem setup initially, rely on the end-of-kernel-code
+ * as our memory range starting point. Once bootmem is inited we
+ * will reserve the area used for the initrd.
*/
- reserved_end = max(init_initrd(),
- (unsigned long) PFN_UP(__pa_symbol(&_end)));
+ init_initrd();
+ reserved_end = (unsigned long) PFN_UP(__pa_symbol(&_end));
/*
* max_low_pfn is not a number of pages. The number of pages
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c
index 126da74d4c55..2362665ba496 100644
--- a/arch/mips/kernel/smp-bmips.c
+++ b/arch/mips/kernel/smp-bmips.c
@@ -136,10 +136,10 @@ static void bmips_prepare_cpus(unsigned int max_cpus)
{
if (request_irq(IPI0_IRQ, bmips_ipi_interrupt, IRQF_PERCPU,
"smp_ipi0", NULL))
- panic("Can't request IPI0 interrupt\n");
+ panic("Can't request IPI0 interrupt");
if (request_irq(IPI1_IRQ, bmips_ipi_interrupt, IRQF_PERCPU,
"smp_ipi1", NULL))
- panic("Can't request IPI1 interrupt\n");
+ panic("Can't request IPI1 interrupt");
}
/*
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 5c208ed8f856..0a022ee33b2a 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -150,7 +150,6 @@ asmlinkage void start_secondary(void)
void __irq_entry smp_call_function_interrupt(void)
{
irq_enter();
- generic_smp_call_function_single_interrupt();
generic_smp_call_function_interrupt();
irq_exit();
}
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 524841f02803..f2ae9cb57ff0 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1554,7 +1554,6 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
unsigned char *b;
BUG_ON(!cpu_has_veic && !cpu_has_vint);
- BUG_ON((n < 0) && (n > 9));
if (addr == NULL) {
handler = (unsigned long) do_default_vi;
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index eb3e18659630..85685e1cdb89 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -390,7 +390,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
ret = of_irq_to_resource_table(eiu_node,
ltq_eiu_irq, exin_avail);
if (ret != exin_avail)
- panic("failed to load external irq resources\n");
+ panic("failed to load external irq resources");
if (request_mem_region(res.start, resource_size(&res),
res.name) < 0)
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
index c24924fe087d..51804b10a036 100644
--- a/arch/mips/lantiq/xway/sysctrl.c
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -128,7 +128,7 @@ static int pmu_enable(struct clk *clk)
do {} while (--retry && (pmu_r32(PWDSR(clk->module)) & clk->bits));
if (!retry)
- panic("activating PMU module failed!\n");
+ panic("activating PMU module failed!");
return 0;
}
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 627883bc6d5f..1129a89209a2 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -346,14 +346,8 @@ static void r4k_blast_scache_setup(void)
static inline void local_r4k___flush_cache_all(void * args)
{
-#if defined(CONFIG_CPU_LOONGSON2)
- r4k_blast_scache();
- return;
-#endif
- r4k_blast_dcache();
- r4k_blast_icache();
-
switch (current_cpu_type()) {
+ case CPU_LOONGSON2:
case CPU_R4000SC:
case CPU_R4000MC:
case CPU_R4400SC:
@@ -361,7 +355,18 @@ static inline void local_r4k___flush_cache_all(void * args)
case CPU_R10000:
case CPU_R12000:
case CPU_R14000:
+ /*
+ * These caches are inclusive caches, that is, if something
+ * is not cached in the S-cache, we know it also won't be
+ * in one of the primary caches.
+ */
r4k_blast_scache();
+ break;
+
+ default:
+ r4k_blast_dcache();
+ r4k_blast_icache();
+ break;
}
}
@@ -1107,15 +1112,14 @@ static void probe_pcache(void)
case CPU_ALCHEMY:
c->icache.flags |= MIPS_CACHE_IC_F_DC;
break;
- }
-#ifdef CONFIG_CPU_LOONGSON2
- /*
- * LOONGSON2 has 4 way icache, but when using indexed cache op,
- * one op will act on all 4 ways
- */
- c->icache.ways = 1;
-#endif
+ case CPU_LOONGSON2:
+ /*
+ * LOONGSON2 has 4 way icache, but when using indexed cache op,
+ * one op will act on all 4 ways
+ */
+ c->icache.ways = 1;
+ }
printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n",
icache_size >> 10,
@@ -1191,7 +1195,6 @@ static int probe_scache(void)
return 1;
}
-#if defined(CONFIG_CPU_LOONGSON2)
static void __init loongson2_sc_init(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
@@ -1207,7 +1210,6 @@ static void __init loongson2_sc_init(void)
c->options |= MIPS_CPU_INCLUSIVE_CACHES;
}
-#endif
extern int r5k_sc_init(void);
extern int rm7k_sc_init(void);
@@ -1257,11 +1259,10 @@ static void setup_scache(void)
#endif
return;
-#if defined(CONFIG_CPU_LOONGSON2)
case CPU_LOONGSON2:
loongson2_sc_init();
return;
-#endif
+
case CPU_XLP:
/* don't need to worry about L2, fully coherent */
return;
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 5f8b95512580..2e9418562258 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -297,7 +297,6 @@ static void mips_dma_sync_single_for_cpu(struct device *dev,
static void mips_dma_sync_single_for_device(struct device *dev,
dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
{
- plat_extra_sync_for_device(dev);
if (!plat_device_is_coherent(dev))
__dma_sync(dma_addr_to_page(dev, dma_handle),
dma_handle & ~PAGE_MASK, size, direction);
@@ -327,7 +326,7 @@ static void mips_dma_sync_sg_for_device(struct device *dev,
int mips_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
- return plat_dma_mapping_error(dev, dma_addr);
+ return 0;
}
int mips_dma_supported(struct device *dev, u64 mask)
@@ -340,7 +339,6 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
{
BUG_ON(direction == DMA_NONE);
- plat_extra_sync_for_device(dev);
if (!plat_device_is_coherent(dev))
__dma_sync_virtual(vaddr, size, direction);
}
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index e205ef598e97..12156176c7ca 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -124,7 +124,7 @@ void *kmap_coherent(struct page *page, unsigned long addr)
BUG_ON(Page_dcache_dirty(page));
- inc_preempt_count();
+ pagefault_disable();
idx = (addr >> PAGE_SHIFT) & (FIX_N_COLOURS - 1);
#ifdef CONFIG_MIPS_MT_SMTC
idx += FIX_N_COLOURS * smp_processor_id() +
@@ -193,8 +193,7 @@ void kunmap_coherent(void)
write_c0_entryhi(old_ctx);
EXIT_CRITICAL(flags);
#endif
- dec_preempt_count();
- preempt_check_resched();
+ pagefault_enable();
}
void copy_user_highpage(struct page *to, struct page *from,
diff --git a/arch/mips/mm/tlb-funcs.S b/arch/mips/mm/tlb-funcs.S
index 79bca3130bd1..30a494db99c2 100644
--- a/arch/mips/mm/tlb-funcs.S
+++ b/arch/mips/mm/tlb-funcs.S
@@ -16,12 +16,10 @@
#define FASTPATH_SIZE 128
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
LEAF(tlbmiss_handler_setup_pgd)
.space 16 * 4
END(tlbmiss_handler_setup_pgd)
EXPORT(tlbmiss_handler_setup_pgd_end)
-#endif
LEAF(handle_tlbm)
.space FASTPATH_SIZE * 4
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index bb3a5f643e97..da3b0b9c9eae 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -52,21 +52,26 @@ extern void build_tlb_refill_handler(void);
#endif /* CONFIG_MIPS_MT_SMTC */
-#if defined(CONFIG_CPU_LOONGSON2)
/*
* LOONGSON2 has a 4 entry itlb which is a subset of dtlb,
* unfortrunately, itlb is not totally transparent to software.
*/
-#define FLUSH_ITLB write_c0_diag(4);
-
-#define FLUSH_ITLB_VM(vma) { if ((vma)->vm_flags & VM_EXEC) write_c0_diag(4); }
-
-#else
-
-#define FLUSH_ITLB
-#define FLUSH_ITLB_VM(vma)
+static inline void flush_itlb(void)
+{
+ switch (current_cpu_type()) {
+ case CPU_LOONGSON2:
+ write_c0_diag(4);
+ break;
+ default:
+ break;
+ }
+}
-#endif
+static inline void flush_itlb_vm(struct vm_area_struct *vma)
+{
+ if (vma->vm_flags & VM_EXEC)
+ flush_itlb();
+}
void local_flush_tlb_all(void)
{
@@ -93,7 +98,7 @@ void local_flush_tlb_all(void)
}
tlbw_use_hazard();
write_c0_entryhi(old_ctx);
- FLUSH_ITLB;
+ flush_itlb();
EXIT_CRITICAL(flags);
}
EXPORT_SYMBOL(local_flush_tlb_all);
@@ -155,7 +160,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
} else {
drop_mmu_context(mm, cpu);
}
- FLUSH_ITLB;
+ flush_itlb();
EXIT_CRITICAL(flags);
}
}
@@ -197,7 +202,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
} else {
local_flush_tlb_all();
}
- FLUSH_ITLB;
+ flush_itlb();
EXIT_CRITICAL(flags);
}
@@ -230,7 +235,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
finish:
write_c0_entryhi(oldpid);
- FLUSH_ITLB_VM(vma);
+ flush_itlb_vm(vma);
EXIT_CRITICAL(flags);
}
}
@@ -262,7 +267,7 @@ void local_flush_tlb_one(unsigned long page)
tlbw_use_hazard();
}
write_c0_entryhi(oldpid);
- FLUSH_ITLB;
+ flush_itlb();
EXIT_CRITICAL(flags);
}
@@ -335,7 +340,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
tlb_write_indexed();
}
tlbw_use_hazard();
- FLUSH_ITLB_VM(vma);
+ flush_itlb_vm(vma);
EXIT_CRITICAL(flags);
}
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 9bb3a9363b06..fffa7fe319a0 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -340,10 +340,6 @@ static struct work_registers build_get_work_registers(u32 **p)
{
struct work_registers r;
- int smp_processor_id_reg;
- int smp_processor_id_sel;
- int smp_processor_id_shift;
-
if (scratch_reg >= 0) {
/* Save in CPU local C0_KScratch? */
UASM_i_MTC0(p, 1, c0_kscratch(), scratch_reg);
@@ -354,25 +350,9 @@ static struct work_registers build_get_work_registers(u32 **p)
}
if (num_possible_cpus() > 1) {
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
- smp_processor_id_shift = 51;
- smp_processor_id_reg = 20; /* XContext */
- smp_processor_id_sel = 0;
-#else
-# ifdef CONFIG_32BIT
- smp_processor_id_shift = 25;
- smp_processor_id_reg = 4; /* Context */
- smp_processor_id_sel = 0;
-# endif
-# ifdef CONFIG_64BIT
- smp_processor_id_shift = 26;
- smp_processor_id_reg = 4; /* Context */
- smp_processor_id_sel = 0;
-# endif
-#endif
/* Get smp_processor_id */
- UASM_i_MFC0(p, K0, smp_processor_id_reg, smp_processor_id_sel);
- UASM_i_SRL_SAFE(p, K0, K0, smp_processor_id_shift);
+ UASM_i_CPUID_MFC0(p, K0, SMP_CPUID_REG);
+ UASM_i_SRL_SAFE(p, K0, K0, SMP_CPUID_REGSHIFT);
/* handler_reg_save index in K0 */
UASM_i_SLL(p, K0, K0, ilog2(sizeof(struct tlb_reg_save)));
@@ -819,11 +799,11 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
}
/* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
if (pgd_reg != -1) {
/* pgd is in pgd_reg */
UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg);
} else {
+#if defined(CONFIG_MIPS_PGD_C0_CONTEXT)
/*
* &pgd << 11 stored in CONTEXT [23..63].
*/
@@ -835,30 +815,18 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
/* 1 0 1 0 1 << 6 xkphys cached */
uasm_i_ori(p, ptr, ptr, 0x540);
uasm_i_drotr(p, ptr, ptr, 11);
- }
#elif defined(CONFIG_SMP)
-# ifdef CONFIG_MIPS_MT_SMTC
- /*
- * SMTC uses TCBind value as "CPU" index
- */
- uasm_i_mfc0(p, ptr, C0_TCBIND);
- uasm_i_dsrl_safe(p, ptr, ptr, 19);
-# else
- /*
- * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
- * stored in CONTEXT.
- */
- uasm_i_dmfc0(p, ptr, C0_CONTEXT);
- uasm_i_dsrl_safe(p, ptr, ptr, 23);
-# endif
- UASM_i_LA_mostly(p, tmp, pgdc);
- uasm_i_daddu(p, ptr, ptr, tmp);
- uasm_i_dmfc0(p, tmp, C0_BADVADDR);
- uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
+ UASM_i_CPUID_MFC0(p, ptr, SMP_CPUID_REG);
+ uasm_i_dsrl_safe(p, ptr, ptr, SMP_CPUID_PTRSHIFT);
+ UASM_i_LA_mostly(p, tmp, pgdc);
+ uasm_i_daddu(p, ptr, ptr, tmp);
+ uasm_i_dmfc0(p, tmp, C0_BADVADDR);
+ uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
#else
- UASM_i_LA_mostly(p, ptr, pgdc);
- uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
+ UASM_i_LA_mostly(p, ptr, pgdc);
+ uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
#endif
+ }
uasm_l_vmalloc_done(l, *p);
@@ -953,31 +921,25 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
static void __maybe_unused
build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
{
- long pgdc = (long)pgd_current;
+ if (pgd_reg != -1) {
+ /* pgd is in pgd_reg */
+ uasm_i_mfc0(p, ptr, c0_kscratch(), pgd_reg);
+ uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
+ } else {
+ long pgdc = (long)pgd_current;
- /* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
+ /* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
#ifdef CONFIG_SMP
-#ifdef CONFIG_MIPS_MT_SMTC
- /*
- * SMTC uses TCBind value as "CPU" index
- */
- uasm_i_mfc0(p, ptr, C0_TCBIND);
- UASM_i_LA_mostly(p, tmp, pgdc);
- uasm_i_srl(p, ptr, ptr, 19);
-#else
- /*
- * smp_processor_id() << 2 is stored in CONTEXT.
- */
- uasm_i_mfc0(p, ptr, C0_CONTEXT);
- UASM_i_LA_mostly(p, tmp, pgdc);
- uasm_i_srl(p, ptr, ptr, 23);
-#endif
- uasm_i_addu(p, ptr, tmp, ptr);
+ uasm_i_mfc0(p, ptr, SMP_CPUID_REG);
+ UASM_i_LA_mostly(p, tmp, pgdc);
+ uasm_i_srl(p, ptr, ptr, SMP_CPUID_PTRSHIFT);
+ uasm_i_addu(p, ptr, tmp, ptr);
#else
- UASM_i_LA_mostly(p, ptr, pgdc);
+ UASM_i_LA_mostly(p, ptr, pgdc);
#endif
- uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
- uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
+ uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
+ uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
+ }
uasm_i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */
uasm_i_sll(p, tmp, tmp, PGD_T_LOG2);
uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */
@@ -1451,28 +1413,30 @@ 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[];
-
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
extern u32 tlbmiss_handler_setup_pgd[], tlbmiss_handler_setup_pgd_end[];
-static void build_r4000_setup_pgd(void)
+static void build_setup_pgd(void)
{
const int a0 = 4;
- const int a1 = 5;
+ const int __maybe_unused a1 = 5;
+ const int __maybe_unused a2 = 6;
u32 *p = tlbmiss_handler_setup_pgd;
const int tlbmiss_handler_setup_pgd_size =
tlbmiss_handler_setup_pgd_end - tlbmiss_handler_setup_pgd;
- struct uasm_label *l = labels;
- struct uasm_reloc *r = relocs;
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
+ long pgdc = (long)pgd_current;
+#endif
memset(tlbmiss_handler_setup_pgd, 0, tlbmiss_handler_setup_pgd_size *
sizeof(tlbmiss_handler_setup_pgd[0]));
memset(labels, 0, sizeof(labels));
memset(relocs, 0, sizeof(relocs));
-
pgd_reg = allocate_kscratch();
-
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
if (pgd_reg == -1) {
+ struct uasm_label *l = labels;
+ struct uasm_reloc *r = relocs;
+
/* PGD << 11 in c0_Context */
/*
* If it is a ckseg0 address, convert to a physical
@@ -1494,6 +1458,26 @@ static void build_r4000_setup_pgd(void)
uasm_i_jr(&p, 31);
UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
}
+#else
+#ifdef CONFIG_SMP
+ /* Save PGD to pgd_current[smp_processor_id()] */
+ UASM_i_CPUID_MFC0(&p, a1, SMP_CPUID_REG);
+ UASM_i_SRL_SAFE(&p, a1, a1, SMP_CPUID_PTRSHIFT);
+ UASM_i_LA_mostly(&p, a2, pgdc);
+ UASM_i_ADDU(&p, a2, a2, a1);
+ UASM_i_SW(&p, a0, uasm_rel_lo(pgdc), a2);
+#else
+ UASM_i_LA_mostly(&p, a2, pgdc);
+ UASM_i_SW(&p, a0, uasm_rel_lo(pgdc), a2);
+#endif /* SMP */
+ uasm_i_jr(&p, 31);
+
+ /* if pgd_reg is allocated, save PGD also to scratch register */
+ if (pgd_reg != -1)
+ UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
+ else
+ uasm_i_nop(&p);
+#endif
if (p >= tlbmiss_handler_setup_pgd_end)
panic("tlbmiss_handler_setup_pgd space exceeded");
@@ -1504,7 +1488,6 @@ static void build_r4000_setup_pgd(void)
dump_handler("tlbmiss_handler", tlbmiss_handler_setup_pgd,
tlbmiss_handler_setup_pgd_size);
}
-#endif
static void
iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr)
@@ -2197,10 +2180,8 @@ static void flush_tlb_handlers(void)
(unsigned long)handle_tlbs_end);
local_flush_icache_range((unsigned long)handle_tlbm,
(unsigned long)handle_tlbm_end);
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd,
(unsigned long)tlbmiss_handler_setup_pgd_end);
-#endif
}
void build_tlb_refill_handler(void)
@@ -2232,6 +2213,7 @@ void build_tlb_refill_handler(void)
if (!run_once) {
if (!cpu_has_local_ebase)
build_r3000_tlb_refill_handler();
+ build_setup_pgd();
build_r3000_tlb_load_handler();
build_r3000_tlb_store_handler();
build_r3000_tlb_modify_handler();
@@ -2255,9 +2237,7 @@ void build_tlb_refill_handler(void)
default:
if (!run_once) {
scratch_reg = allocate_kscratch();
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
- build_r4000_setup_pgd();
-#endif
+ build_setup_pgd();
build_r4000_tlb_load_handler();
build_r4000_tlb_store_handler();
build_r4000_tlb_modify_handler();
diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index 6f8feb9efcff..c0eded01fde9 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -245,7 +245,7 @@ static int nlm_parse_cpumask(cpumask_t *wakeup_mask)
return threadmode;
unsupp:
- panic("Unsupported CPU mask %lx\n",
+ panic("Unsupported CPU mask %lx",
(unsigned long)cpumask_bits(wakeup_mask)[0]);
return 0;
}
diff --git a/arch/mips/pci/pci-ar71xx.c b/arch/mips/pci/pci-ar71xx.c
index 18517dd0f709..d471a26dd5f8 100644
--- a/arch/mips/pci/pci-ar71xx.c
+++ b/arch/mips/pci/pci-ar71xx.c
@@ -363,9 +363,6 @@ static int ar71xx_pci_probe(struct platform_device *pdev)
spin_lock_init(&apc->lock);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base");
- if (!res)
- return -EINVAL;
-
apc->cfg_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(apc->cfg_base))
return PTR_ERR(apc->cfg_base);
diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
index 65ec032fa0b4..785b2659b519 100644
--- a/arch/mips/pci/pci-ar724x.c
+++ b/arch/mips/pci/pci-ar724x.c
@@ -362,25 +362,16 @@ static int ar724x_pci_probe(struct platform_device *pdev)
return -ENOMEM;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl_base");
- if (!res)
- return -EINVAL;
-
apc->ctrl_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(apc->ctrl_base))
return PTR_ERR(apc->ctrl_base);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base");
- if (!res)
- return -EINVAL;
-
apc->devcfg_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(apc->devcfg_base))
return PTR_ERR(apc->devcfg_base);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "crp_base");
- if (!res)
- return -EINVAL;
-
apc->crp_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(apc->crp_base))
return PTR_ERR(apc->crp_base);
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 33e7aa52d9c4..1bf60b127377 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -120,51 +120,37 @@ static void pcibios_scanbus(struct pci_controller *hose)
#ifdef CONFIG_OF
void pci_load_of_ranges(struct pci_controller *hose, struct device_node *node)
{
- const __be32 *ranges;
- int rlen;
- int pna = of_n_addr_cells(node);
- int np = pna + 5;
+ struct of_pci_range range;
+ struct of_pci_range_parser parser;
pr_info("PCI host bridge %s ranges:\n", node->full_name);
- ranges = of_get_property(node, "ranges", &rlen);
- if (ranges == NULL)
- return;
hose->of_node = node;
- while ((rlen -= np * 4) >= 0) {
- u32 pci_space;
+ if (of_pci_range_parser_init(&parser, node))
+ return;
+
+ for_each_of_pci_range(&parser, &range) {
struct resource *res = NULL;
- u64 addr, size;
-
- pci_space = be32_to_cpup(&ranges[0]);
- addr = of_translate_address(node, ranges + 3);
- size = of_read_number(ranges + pna + 3, 2);
- ranges += np;
- switch ((pci_space >> 24) & 0x3) {
- case 1: /* PCI IO space */
+
+ switch (range.flags & IORESOURCE_TYPE_BITS) {
+ case IORESOURCE_IO:
pr_info(" IO 0x%016llx..0x%016llx\n",
- addr, addr + size - 1);
+ range.cpu_addr,
+ range.cpu_addr + range.size - 1);
hose->io_map_base =
- (unsigned long)ioremap(addr, size);
+ (unsigned long)ioremap(range.cpu_addr,
+ range.size);
res = hose->io_resource;
- res->flags = IORESOURCE_IO;
break;
- case 2: /* PCI Memory space */
- case 3: /* PCI 64 bits Memory space */
+ case IORESOURCE_MEM:
pr_info(" MEM 0x%016llx..0x%016llx\n",
- addr, addr + size - 1);
+ range.cpu_addr,
+ range.cpu_addr + range.size - 1);
res = hose->mem_resource;
- res->flags = IORESOURCE_MEM;
break;
}
- if (res != NULL) {
- res->start = addr;
- res->name = node->full_name;
- res->end = res->start + size - 1;
- res->parent = NULL;
- res->sibling = NULL;
- res->child = NULL;
- }
+ if (res != NULL)
+ of_pci_range_to_resource(&range, node, res);
}
}
diff --git a/arch/mips/powertv/Kconfig b/arch/mips/powertv/Kconfig
deleted file mode 100644
index dd91fbacbcba..000000000000
--- a/arch/mips/powertv/Kconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-config BOOTLOADER_FAMILY
- string "POWERTV Bootloader Family string"
- default "85"
- depends on POWERTV
- help
- This value should be specified when the bootloader driver is disabled
- and must be exactly two characters long. Families supported are:
- R1 - RNG-100 R2 - RNG-200
- A1 - Class A B1 - Class B
- E1 - Class E F1 - Class F
- 44 - 45xx 46 - 46xx
- 85 - 85xx 86 - 86xx
diff --git a/arch/mips/powertv/Makefile b/arch/mips/powertv/Makefile
deleted file mode 100644
index 39ca9f8d63ae..000000000000
--- a/arch/mips/powertv/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Carsten Langgaard, carstenl@mips.com
-# Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
-#
-# Carsten Langgaard, carstenl@mips.com
-# Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
-# Portions copyright (C) 2009 Cisco Systems, Inc.
-#
-# This program is free software; you can distribute 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 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.
-#
-# Makefile for the Cisco PowerTV-specific kernel interface routines
-# under Linux.
-#
-
-obj-y += init.o ioremap.o memory.o powertv_setup.o reset.o time.o \
- asic/ pci/
-
-obj-$(CONFIG_USB) += powertv-usb.o
diff --git a/arch/mips/powertv/Platform b/arch/mips/powertv/Platform
deleted file mode 100644
index 4eb5af1d8eea..000000000000
--- a/arch/mips/powertv/Platform
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Cisco PowerTV Platform
-#
-platform-$(CONFIG_POWERTV) += powertv/
-cflags-$(CONFIG_POWERTV) += \
- -I$(srctree)/arch/mips/include/asm/mach-powertv
-load-$(CONFIG_POWERTV) += 0xffffffff90800000
diff --git a/arch/mips/powertv/asic/Makefile b/arch/mips/powertv/asic/Makefile
deleted file mode 100644
index 35dcc53eb25f..000000000000
--- a/arch/mips/powertv/asic/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Copyright (C) 2009 Scientific-Atlanta, Inc.
-#
-# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
-
-obj-y += asic-calliope.o asic-cronus.o asic-gaia.o asic-zeus.o \
- asic_devices.o asic_int.o irq_asic.o prealloc-calliope.o \
- prealloc-cronus.o prealloc-cronuslite.o prealloc-gaia.o prealloc-zeus.o
diff --git a/arch/mips/powertv/asic/asic-calliope.c b/arch/mips/powertv/asic/asic-calliope.c
deleted file mode 100644
index 2f539b43f56b..000000000000
--- a/arch/mips/powertv/asic/asic-calliope.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Locations of devices in the Calliope ASIC.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: Ken Eppinett
- * David Schleef <ds@schleef.org>
- *
- * Description: Defines the platform resources for the SA settop.
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/asic.h>
-
-#define CALLIOPE_ADDR(x) (CALLIOPE_IO_BASE + (x))
-
-const struct register_map calliope_register_map __initconst = {
- .eic_slow0_strt_add = {.phys = CALLIOPE_ADDR(0x800000)},
- .eic_cfg_bits = {.phys = CALLIOPE_ADDR(0x800038)},
- .eic_ready_status = {.phys = CALLIOPE_ADDR(0x80004c)},
-
- .chipver3 = {.phys = CALLIOPE_ADDR(0xA00800)},
- .chipver2 = {.phys = CALLIOPE_ADDR(0xA00804)},
- .chipver1 = {.phys = CALLIOPE_ADDR(0xA00808)},
- .chipver0 = {.phys = CALLIOPE_ADDR(0xA0080c)},
-
- /* The registers of IRBlaster */
- .uart1_intstat = {.phys = CALLIOPE_ADDR(0xA01800)},
- .uart1_inten = {.phys = CALLIOPE_ADDR(0xA01804)},
- .uart1_config1 = {.phys = CALLIOPE_ADDR(0xA01808)},
- .uart1_config2 = {.phys = CALLIOPE_ADDR(0xA0180C)},
- .uart1_divisorhi = {.phys = CALLIOPE_ADDR(0xA01810)},
- .uart1_divisorlo = {.phys = CALLIOPE_ADDR(0xA01814)},
- .uart1_data = {.phys = CALLIOPE_ADDR(0xA01818)},
- .uart1_status = {.phys = CALLIOPE_ADDR(0xA0181C)},
-
- .int_stat_3 = {.phys = CALLIOPE_ADDR(0xA02800)},
- .int_stat_2 = {.phys = CALLIOPE_ADDR(0xA02804)},
- .int_stat_1 = {.phys = CALLIOPE_ADDR(0xA02808)},
- .int_stat_0 = {.phys = CALLIOPE_ADDR(0xA0280c)},
- .int_config = {.phys = CALLIOPE_ADDR(0xA02810)},
- .int_int_scan = {.phys = CALLIOPE_ADDR(0xA02818)},
- .ien_int_3 = {.phys = CALLIOPE_ADDR(0xA02830)},
- .ien_int_2 = {.phys = CALLIOPE_ADDR(0xA02834)},
- .ien_int_1 = {.phys = CALLIOPE_ADDR(0xA02838)},
- .ien_int_0 = {.phys = CALLIOPE_ADDR(0xA0283c)},
- .int_level_3_3 = {.phys = CALLIOPE_ADDR(0xA02880)},
- .int_level_3_2 = {.phys = CALLIOPE_ADDR(0xA02884)},
- .int_level_3_1 = {.phys = CALLIOPE_ADDR(0xA02888)},
- .int_level_3_0 = {.phys = CALLIOPE_ADDR(0xA0288c)},
- .int_level_2_3 = {.phys = CALLIOPE_ADDR(0xA02890)},
- .int_level_2_2 = {.phys = CALLIOPE_ADDR(0xA02894)},
- .int_level_2_1 = {.phys = CALLIOPE_ADDR(0xA02898)},
- .int_level_2_0 = {.phys = CALLIOPE_ADDR(0xA0289c)},
- .int_level_1_3 = {.phys = CALLIOPE_ADDR(0xA028a0)},
- .int_level_1_2 = {.phys = CALLIOPE_ADDR(0xA028a4)},
- .int_level_1_1 = {.phys = CALLIOPE_ADDR(0xA028a8)},
- .int_level_1_0 = {.phys = CALLIOPE_ADDR(0xA028ac)},
- .int_level_0_3 = {.phys = CALLIOPE_ADDR(0xA028b0)},
- .int_level_0_2 = {.phys = CALLIOPE_ADDR(0xA028b4)},
- .int_level_0_1 = {.phys = CALLIOPE_ADDR(0xA028b8)},
- .int_level_0_0 = {.phys = CALLIOPE_ADDR(0xA028bc)},
- .int_docsis_en = {.phys = CALLIOPE_ADDR(0xA028F4)},
-
- .mips_pll_setup = {.phys = CALLIOPE_ADDR(0x980000)},
- .fs432x4b4_usb_ctl = {.phys = CALLIOPE_ADDR(0x980030)},
- .test_bus = {.phys = CALLIOPE_ADDR(0x9800CC)},
- .crt_spare = {.phys = CALLIOPE_ADDR(0x9800d4)},
- .usb2_ohci_int_mask = {.phys = CALLIOPE_ADDR(0x9A000c)},
- .usb2_strap = {.phys = CALLIOPE_ADDR(0x9A0014)},
- .ehci_hcapbase = {.phys = CALLIOPE_ADDR(0x9BFE00)},
- .ohci_hc_revision = {.phys = CALLIOPE_ADDR(0x9BFC00)},
- .bcm1_bs_lmi_steer = {.phys = CALLIOPE_ADDR(0x9E0004)},
- .usb2_control = {.phys = CALLIOPE_ADDR(0x9E0054)},
- .usb2_stbus_obc = {.phys = CALLIOPE_ADDR(0x9BFF00)},
- .usb2_stbus_mess_size = {.phys = CALLIOPE_ADDR(0x9BFF04)},
- .usb2_stbus_chunk_size = {.phys = CALLIOPE_ADDR(0x9BFF08)},
-
- .pcie_regs = {.phys = 0x000000}, /* -doesn't exist- */
- .tim_ch = {.phys = CALLIOPE_ADDR(0xA02C10)},
- .tim_cl = {.phys = CALLIOPE_ADDR(0xA02C14)},
- .gpio_dout = {.phys = CALLIOPE_ADDR(0xA02c20)},
- .gpio_din = {.phys = CALLIOPE_ADDR(0xA02c24)},
- .gpio_dir = {.phys = CALLIOPE_ADDR(0xA02c2C)},
- .watchdog = {.phys = CALLIOPE_ADDR(0xA02c30)},
- .front_panel = {.phys = 0x000000}, /* -not used- */
-};
diff --git a/arch/mips/powertv/asic/asic-cronus.c b/arch/mips/powertv/asic/asic-cronus.c
deleted file mode 100644
index 7f8f3429b35a..000000000000
--- a/arch/mips/powertv/asic/asic-cronus.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Locations of devices in the Cronus ASIC
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: Ken Eppinett
- * David Schleef <ds@schleef.org>
- *
- * Description: Defines the platform resources for the SA settop.
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/asic.h>
-
-#define CRONUS_ADDR(x) (CRONUS_IO_BASE + (x))
-
-const struct register_map cronus_register_map __initconst = {
- .eic_slow0_strt_add = {.phys = CRONUS_ADDR(0x000000)},
- .eic_cfg_bits = {.phys = CRONUS_ADDR(0x000038)},
- .eic_ready_status = {.phys = CRONUS_ADDR(0x00004C)},
-
- .chipver3 = {.phys = CRONUS_ADDR(0x2A0800)},
- .chipver2 = {.phys = CRONUS_ADDR(0x2A0804)},
- .chipver1 = {.phys = CRONUS_ADDR(0x2A0808)},
- .chipver0 = {.phys = CRONUS_ADDR(0x2A080C)},
-
- /* The registers of IRBlaster */
- .uart1_intstat = {.phys = CRONUS_ADDR(0x2A1800)},
- .uart1_inten = {.phys = CRONUS_ADDR(0x2A1804)},
- .uart1_config1 = {.phys = CRONUS_ADDR(0x2A1808)},
- .uart1_config2 = {.phys = CRONUS_ADDR(0x2A180C)},
- .uart1_divisorhi = {.phys = CRONUS_ADDR(0x2A1810)},
- .uart1_divisorlo = {.phys = CRONUS_ADDR(0x2A1814)},
- .uart1_data = {.phys = CRONUS_ADDR(0x2A1818)},
- .uart1_status = {.phys = CRONUS_ADDR(0x2A181C)},
-
- .int_stat_3 = {.phys = CRONUS_ADDR(0x2A2800)},
- .int_stat_2 = {.phys = CRONUS_ADDR(0x2A2804)},
- .int_stat_1 = {.phys = CRONUS_ADDR(0x2A2808)},
- .int_stat_0 = {.phys = CRONUS_ADDR(0x2A280C)},
- .int_config = {.phys = CRONUS_ADDR(0x2A2810)},
- .int_int_scan = {.phys = CRONUS_ADDR(0x2A2818)},
- .ien_int_3 = {.phys = CRONUS_ADDR(0x2A2830)},
- .ien_int_2 = {.phys = CRONUS_ADDR(0x2A2834)},
- .ien_int_1 = {.phys = CRONUS_ADDR(0x2A2838)},
- .ien_int_0 = {.phys = CRONUS_ADDR(0x2A283C)},
- .int_level_3_3 = {.phys = CRONUS_ADDR(0x2A2880)},
- .int_level_3_2 = {.phys = CRONUS_ADDR(0x2A2884)},
- .int_level_3_1 = {.phys = CRONUS_ADDR(0x2A2888)},
- .int_level_3_0 = {.phys = CRONUS_ADDR(0x2A288C)},
- .int_level_2_3 = {.phys = CRONUS_ADDR(0x2A2890)},
- .int_level_2_2 = {.phys = CRONUS_ADDR(0x2A2894)},
- .int_level_2_1 = {.phys = CRONUS_ADDR(0x2A2898)},
- .int_level_2_0 = {.phys = CRONUS_ADDR(0x2A289C)},
- .int_level_1_3 = {.phys = CRONUS_ADDR(0x2A28A0)},
- .int_level_1_2 = {.phys = CRONUS_ADDR(0x2A28A4)},
- .int_level_1_1 = {.phys = CRONUS_ADDR(0x2A28A8)},
- .int_level_1_0 = {.phys = CRONUS_ADDR(0x2A28AC)},
- .int_level_0_3 = {.phys = CRONUS_ADDR(0x2A28B0)},
- .int_level_0_2 = {.phys = CRONUS_ADDR(0x2A28B4)},
- .int_level_0_1 = {.phys = CRONUS_ADDR(0x2A28B8)},
- .int_level_0_0 = {.phys = CRONUS_ADDR(0x2A28BC)},
- .int_docsis_en = {.phys = CRONUS_ADDR(0x2A28F4)},
-
- .mips_pll_setup = {.phys = CRONUS_ADDR(0x1C0000)},
- .fs432x4b4_usb_ctl = {.phys = CRONUS_ADDR(0x1C0028)},
- .test_bus = {.phys = CRONUS_ADDR(0x1C00CC)},
- .crt_spare = {.phys = CRONUS_ADDR(0x1c00d4)},
- .usb2_ohci_int_mask = {.phys = CRONUS_ADDR(0x20000C)},
- .usb2_strap = {.phys = CRONUS_ADDR(0x200014)},
- .ehci_hcapbase = {.phys = CRONUS_ADDR(0x21FE00)},
- .ohci_hc_revision = {.phys = CRONUS_ADDR(0x21fc00)},
- .bcm1_bs_lmi_steer = {.phys = CRONUS_ADDR(0x2E0008)},
- .usb2_control = {.phys = CRONUS_ADDR(0x2E004C)},
- .usb2_stbus_obc = {.phys = CRONUS_ADDR(0x21FF00)},
- .usb2_stbus_mess_size = {.phys = CRONUS_ADDR(0x21FF04)},
- .usb2_stbus_chunk_size = {.phys = CRONUS_ADDR(0x21FF08)},
-
- .pcie_regs = {.phys = CRONUS_ADDR(0x220000)},
- .tim_ch = {.phys = CRONUS_ADDR(0x2A2C10)},
- .tim_cl = {.phys = CRONUS_ADDR(0x2A2C14)},
- .gpio_dout = {.phys = CRONUS_ADDR(0x2A2C20)},
- .gpio_din = {.phys = CRONUS_ADDR(0x2A2C24)},
- .gpio_dir = {.phys = CRONUS_ADDR(0x2A2C2C)},
- .watchdog = {.phys = CRONUS_ADDR(0x2A2C30)},
- .front_panel = {.phys = CRONUS_ADDR(0x2A3800)},
-};
diff --git a/arch/mips/powertv/asic/asic-gaia.c b/arch/mips/powertv/asic/asic-gaia.c
deleted file mode 100644
index 1265b49012e6..000000000000
--- a/arch/mips/powertv/asic/asic-gaia.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Locations of devices in the Gaia ASIC
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: David VomLehn
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/asic.h>
-
-const struct register_map gaia_register_map __initconst = {
- .eic_slow0_strt_add = {.phys = GAIA_IO_BASE + 0x000000},
- .eic_cfg_bits = {.phys = GAIA_IO_BASE + 0x000038},
- .eic_ready_status = {.phys = GAIA_IO_BASE + 0x00004C},
-
- .chipver3 = {.phys = GAIA_IO_BASE + 0x2A0800},
- .chipver2 = {.phys = GAIA_IO_BASE + 0x2A0804},
- .chipver1 = {.phys = GAIA_IO_BASE + 0x2A0808},
- .chipver0 = {.phys = GAIA_IO_BASE + 0x2A080C},
-
- /* The registers of IRBlaster */
- .uart1_intstat = {.phys = GAIA_IO_BASE + 0x2A1800},
- .uart1_inten = {.phys = GAIA_IO_BASE + 0x2A1804},
- .uart1_config1 = {.phys = GAIA_IO_BASE + 0x2A1808},
- .uart1_config2 = {.phys = GAIA_IO_BASE + 0x2A180C},
- .uart1_divisorhi = {.phys = GAIA_IO_BASE + 0x2A1810},
- .uart1_divisorlo = {.phys = GAIA_IO_BASE + 0x2A1814},
- .uart1_data = {.phys = GAIA_IO_BASE + 0x2A1818},
- .uart1_status = {.phys = GAIA_IO_BASE + 0x2A181C},
-
- .int_stat_3 = {.phys = GAIA_IO_BASE + 0x2A2800},
- .int_stat_2 = {.phys = GAIA_IO_BASE + 0x2A2804},
- .int_stat_1 = {.phys = GAIA_IO_BASE + 0x2A2808},
- .int_stat_0 = {.phys = GAIA_IO_BASE + 0x2A280C},
- .int_config = {.phys = GAIA_IO_BASE + 0x2A2810},
- .int_int_scan = {.phys = GAIA_IO_BASE + 0x2A2818},
- .ien_int_3 = {.phys = GAIA_IO_BASE + 0x2A2830},
- .ien_int_2 = {.phys = GAIA_IO_BASE + 0x2A2834},
- .ien_int_1 = {.phys = GAIA_IO_BASE + 0x2A2838},
- .ien_int_0 = {.phys = GAIA_IO_BASE + 0x2A283C},
- .int_level_3_3 = {.phys = GAIA_IO_BASE + 0x2A2880},
- .int_level_3_2 = {.phys = GAIA_IO_BASE + 0x2A2884},
- .int_level_3_1 = {.phys = GAIA_IO_BASE + 0x2A2888},
- .int_level_3_0 = {.phys = GAIA_IO_BASE + 0x2A288C},
- .int_level_2_3 = {.phys = GAIA_IO_BASE + 0x2A2890},
- .int_level_2_2 = {.phys = GAIA_IO_BASE + 0x2A2894},
- .int_level_2_1 = {.phys = GAIA_IO_BASE + 0x2A2898},
- .int_level_2_0 = {.phys = GAIA_IO_BASE + 0x2A289C},
- .int_level_1_3 = {.phys = GAIA_IO_BASE + 0x2A28A0},
- .int_level_1_2 = {.phys = GAIA_IO_BASE + 0x2A28A4},
- .int_level_1_1 = {.phys = GAIA_IO_BASE + 0x2A28A8},
- .int_level_1_0 = {.phys = GAIA_IO_BASE + 0x2A28AC},
- .int_level_0_3 = {.phys = GAIA_IO_BASE + 0x2A28B0},
- .int_level_0_2 = {.phys = GAIA_IO_BASE + 0x2A28B4},
- .int_level_0_1 = {.phys = GAIA_IO_BASE + 0x2A28B8},
- .int_level_0_0 = {.phys = GAIA_IO_BASE + 0x2A28BC},
- .int_docsis_en = {.phys = GAIA_IO_BASE + 0x2A28F4},
-
- .mips_pll_setup = {.phys = GAIA_IO_BASE + 0x1C0000},
- .fs432x4b4_usb_ctl = {.phys = GAIA_IO_BASE + 0x1C0024},
- .test_bus = {.phys = GAIA_IO_BASE + 0x1C00CC},
- .crt_spare = {.phys = GAIA_IO_BASE + 0x1c0108},
- .usb2_ohci_int_mask = {.phys = GAIA_IO_BASE + 0x20000C},
- .usb2_strap = {.phys = GAIA_IO_BASE + 0x200014},
- .ehci_hcapbase = {.phys = GAIA_IO_BASE + 0x21FE00},
- .ohci_hc_revision = {.phys = GAIA_IO_BASE + 0x21fc00},
- .bcm1_bs_lmi_steer = {.phys = GAIA_IO_BASE + 0x2E0004},
- .usb2_control = {.phys = GAIA_IO_BASE + 0x2E004C},
- .usb2_stbus_obc = {.phys = GAIA_IO_BASE + 0x21FF00},
- .usb2_stbus_mess_size = {.phys = GAIA_IO_BASE + 0x21FF04},
- .usb2_stbus_chunk_size = {.phys = GAIA_IO_BASE + 0x21FF08},
-
- .pcie_regs = {.phys = GAIA_IO_BASE + 0x220000},
- .tim_ch = {.phys = GAIA_IO_BASE + 0x2A2C10},
- .tim_cl = {.phys = GAIA_IO_BASE + 0x2A2C14},
- .gpio_dout = {.phys = GAIA_IO_BASE + 0x2A2C20},
- .gpio_din = {.phys = GAIA_IO_BASE + 0x2A2C24},
- .gpio_dir = {.phys = GAIA_IO_BASE + 0x2A2C2C},
- .watchdog = {.phys = GAIA_IO_BASE + 0x2A2C30},
- .front_panel = {.phys = GAIA_IO_BASE + 0x2A3800},
-};
diff --git a/arch/mips/powertv/asic/asic-zeus.c b/arch/mips/powertv/asic/asic-zeus.c
deleted file mode 100644
index 14e7de137e03..000000000000
--- a/arch/mips/powertv/asic/asic-zeus.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Locations of devices in the Zeus ASIC
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: Ken Eppinett
- * David Schleef <ds@schleef.org>
- *
- * Description: Defines the platform resources for the SA settop.
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/asic.h>
-
-#define ZEUS_ADDR(x) (ZEUS_IO_BASE + (x))
-
-const struct register_map zeus_register_map __initconst = {
- .eic_slow0_strt_add = {.phys = ZEUS_ADDR(0x000000)},
- .eic_cfg_bits = {.phys = ZEUS_ADDR(0x000038)},
- .eic_ready_status = {.phys = ZEUS_ADDR(0x00004c)},
-
- .chipver3 = {.phys = ZEUS_ADDR(0x280800)},
- .chipver2 = {.phys = ZEUS_ADDR(0x280804)},
- .chipver1 = {.phys = ZEUS_ADDR(0x280808)},
- .chipver0 = {.phys = ZEUS_ADDR(0x28080c)},
-
- /* The registers of IRBlaster */
- .uart1_intstat = {.phys = ZEUS_ADDR(0x281800)},
- .uart1_inten = {.phys = ZEUS_ADDR(0x281804)},
- .uart1_config1 = {.phys = ZEUS_ADDR(0x281808)},
- .uart1_config2 = {.phys = ZEUS_ADDR(0x28180C)},
- .uart1_divisorhi = {.phys = ZEUS_ADDR(0x281810)},
- .uart1_divisorlo = {.phys = ZEUS_ADDR(0x281814)},
- .uart1_data = {.phys = ZEUS_ADDR(0x281818)},
- .uart1_status = {.phys = ZEUS_ADDR(0x28181C)},
-
- .int_stat_3 = {.phys = ZEUS_ADDR(0x282800)},
- .int_stat_2 = {.phys = ZEUS_ADDR(0x282804)},
- .int_stat_1 = {.phys = ZEUS_ADDR(0x282808)},
- .int_stat_0 = {.phys = ZEUS_ADDR(0x28280c)},
- .int_config = {.phys = ZEUS_ADDR(0x282810)},
- .int_int_scan = {.phys = ZEUS_ADDR(0x282818)},
- .ien_int_3 = {.phys = ZEUS_ADDR(0x282830)},
- .ien_int_2 = {.phys = ZEUS_ADDR(0x282834)},
- .ien_int_1 = {.phys = ZEUS_ADDR(0x282838)},
- .ien_int_0 = {.phys = ZEUS_ADDR(0x28283c)},
- .int_level_3_3 = {.phys = ZEUS_ADDR(0x282880)},
- .int_level_3_2 = {.phys = ZEUS_ADDR(0x282884)},
- .int_level_3_1 = {.phys = ZEUS_ADDR(0x282888)},
- .int_level_3_0 = {.phys = ZEUS_ADDR(0x28288c)},
- .int_level_2_3 = {.phys = ZEUS_ADDR(0x282890)},
- .int_level_2_2 = {.phys = ZEUS_ADDR(0x282894)},
- .int_level_2_1 = {.phys = ZEUS_ADDR(0x282898)},
- .int_level_2_0 = {.phys = ZEUS_ADDR(0x28289c)},
- .int_level_1_3 = {.phys = ZEUS_ADDR(0x2828a0)},
- .int_level_1_2 = {.phys = ZEUS_ADDR(0x2828a4)},
- .int_level_1_1 = {.phys = ZEUS_ADDR(0x2828a8)},
- .int_level_1_0 = {.phys = ZEUS_ADDR(0x2828ac)},
- .int_level_0_3 = {.phys = ZEUS_ADDR(0x2828b0)},
- .int_level_0_2 = {.phys = ZEUS_ADDR(0x2828b4)},
- .int_level_0_1 = {.phys = ZEUS_ADDR(0x2828b8)},
- .int_level_0_0 = {.phys = ZEUS_ADDR(0x2828bc)},
- .int_docsis_en = {.phys = ZEUS_ADDR(0x2828F4)},
-
- .mips_pll_setup = {.phys = ZEUS_ADDR(0x1a0000)},
- .fs432x4b4_usb_ctl = {.phys = ZEUS_ADDR(0x1a0018)},
- .test_bus = {.phys = ZEUS_ADDR(0x1a0238)},
- .crt_spare = {.phys = ZEUS_ADDR(0x1a0090)},
- .usb2_ohci_int_mask = {.phys = ZEUS_ADDR(0x1e000c)},
- .usb2_strap = {.phys = ZEUS_ADDR(0x1e0014)},
- .ehci_hcapbase = {.phys = ZEUS_ADDR(0x1FFE00)},
- .ohci_hc_revision = {.phys = ZEUS_ADDR(0x1FFC00)},
- .bcm1_bs_lmi_steer = {.phys = ZEUS_ADDR(0x2C0008)},
- .usb2_control = {.phys = ZEUS_ADDR(0x2c01a0)},
- .usb2_stbus_obc = {.phys = ZEUS_ADDR(0x1FFF00)},
- .usb2_stbus_mess_size = {.phys = ZEUS_ADDR(0x1FFF04)},
- .usb2_stbus_chunk_size = {.phys = ZEUS_ADDR(0x1FFF08)},
-
- .pcie_regs = {.phys = ZEUS_ADDR(0x200000)},
- .tim_ch = {.phys = ZEUS_ADDR(0x282C10)},
- .tim_cl = {.phys = ZEUS_ADDR(0x282C14)},
- .gpio_dout = {.phys = ZEUS_ADDR(0x282c20)},
- .gpio_din = {.phys = ZEUS_ADDR(0x282c24)},
- .gpio_dir = {.phys = ZEUS_ADDR(0x282c2C)},
- .watchdog = {.phys = ZEUS_ADDR(0x282c30)},
- .front_panel = {.phys = ZEUS_ADDR(0x283800)},
-};
diff --git a/arch/mips/powertv/asic/asic_devices.c b/arch/mips/powertv/asic/asic_devices.c
deleted file mode 100644
index 8380605d597d..000000000000
--- a/arch/mips/powertv/asic/asic_devices.c
+++ /dev/null
@@ -1,549 +0,0 @@
-/*
- *
- * Description: Defines the platform resources for Gaia-based settops.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * NOTE: The bootloader allocates persistent memory at an address which is
- * 16 MiB below the end of the highest address in KSEG0. All fixed
- * address memory reservations must avoid this region.
- */
-
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/resource.h>
-#include <linux/serial_reg.h>
-#include <linux/io.h>
-#include <linux/bootmem.h>
-#include <linux/mm.h>
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <asm/page.h>
-#include <linux/swap.h>
-#include <linux/highmem.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/mach-powertv/asic.h>
-#include <asm/mach-powertv/asic_regs.h>
-#include <asm/mach-powertv/interrupts.h>
-
-#ifdef CONFIG_BOOTLOADER_DRIVER
-#include <asm/mach-powertv/kbldr.h>
-#endif
-#include <asm/bootinfo.h>
-
-#define BOOTLDRFAMILY(byte1, byte0) (((byte1) << 8) | (byte0))
-
-/*
- * Forward Prototypes
- */
-static void pmem_setup_resource(void);
-
-/*
- * Global Variables
- */
-enum asic_type asic;
-
-unsigned int platform_features;
-unsigned int platform_family;
-struct register_map _asic_register_map;
-EXPORT_SYMBOL(_asic_register_map); /* Exported for testing */
-unsigned long asic_phy_base;
-unsigned long asic_base;
-EXPORT_SYMBOL(asic_base); /* Exported for testing */
-struct resource *gp_resources;
-
-/*
- * Don't recommend to use it directly, it is usually used by kernel internally.
- * Portable code should be using interfaces such as ioremp, dma_map_single, etc.
- */
-unsigned long phys_to_dma_offset;
-EXPORT_SYMBOL(phys_to_dma_offset);
-
-/*
- *
- * IO Resource Definition
- *
- */
-
-struct resource asic_resource = {
- .name = "ASIC Resource",
- .start = 0,
- .end = ASIC_IO_SIZE,
- .flags = IORESOURCE_MEM,
-};
-
-/*
- * Allow override of bootloader-specified model
- * Returns zero on success, a negative errno value on failure. This parameter
- * allows overriding of the bootloader-specified model.
- */
-static char __initdata cmdline[COMMAND_LINE_SIZE];
-
-#define FORCEFAMILY_PARAM "forcefamily"
-
-/*
- * check_forcefamily - check for, and parse, forcefamily command line parameter
- * @forced_family: Pointer to two-character array in which to store the
- * value of the forcedfamily parameter, if any.
- */
-static __init int check_forcefamily(unsigned char forced_family[2])
-{
- const char *p;
-
- forced_family[0] = '\0';
- forced_family[1] = '\0';
-
- /* Check the command line for a forcefamily directive */
- strncpy(cmdline, arcs_cmdline, COMMAND_LINE_SIZE - 1);
- p = strstr(cmdline, FORCEFAMILY_PARAM);
- if (p && (p != cmdline) && (*(p - 1) != ' '))
- p = strstr(p, " " FORCEFAMILY_PARAM "=");
-
- if (p) {
- p += strlen(FORCEFAMILY_PARAM "=");
-
- if (*p == '\0' || *(p + 1) == '\0' ||
- (*(p + 2) != '\0' && *(p + 2) != ' '))
- pr_err(FORCEFAMILY_PARAM " must be exactly two "
- "characters long, ignoring value\n");
-
- else {
- forced_family[0] = *p;
- forced_family[1] = *(p + 1);
- }
- }
-
- return 0;
-}
-
-/*
- * platform_set_family - determine major platform family type.
- *
- * Returns family type; -1 if none
- * Returns the family type; -1 if none
- *
- */
-static __init noinline void platform_set_family(void)
-{
- unsigned char forced_family[2];
- unsigned short bootldr_family;
-
- if (check_forcefamily(forced_family) == 0)
- bootldr_family = BOOTLDRFAMILY(forced_family[0],
- forced_family[1]);
- else
- bootldr_family = (unsigned short) BOOTLDRFAMILY(
- CONFIG_BOOTLOADER_FAMILY[0],
- CONFIG_BOOTLOADER_FAMILY[1]);
-
- pr_info("Bootloader Family = 0x%04X\n", bootldr_family);
-
- switch (bootldr_family) {
- case BOOTLDRFAMILY('R', '1'):
- platform_family = FAMILY_1500;
- break;
- case BOOTLDRFAMILY('4', '4'):
- platform_family = FAMILY_4500;
- break;
- case BOOTLDRFAMILY('4', '6'):
- platform_family = FAMILY_4600;
- break;
- case BOOTLDRFAMILY('A', '1'):
- platform_family = FAMILY_4600VZA;
- break;
- case BOOTLDRFAMILY('8', '5'):
- platform_family = FAMILY_8500;
- break;
- case BOOTLDRFAMILY('R', '2'):
- platform_family = FAMILY_8500RNG;
- break;
- case BOOTLDRFAMILY('8', '6'):
- platform_family = FAMILY_8600;
- break;
- case BOOTLDRFAMILY('B', '1'):
- platform_family = FAMILY_8600VZB;
- break;
- case BOOTLDRFAMILY('E', '1'):
- platform_family = FAMILY_1500VZE;
- break;
- case BOOTLDRFAMILY('F', '1'):
- platform_family = FAMILY_1500VZF;
- break;
- case BOOTLDRFAMILY('8', '7'):
- platform_family = FAMILY_8700;
- break;
- default:
- platform_family = -1;
- }
-}
-
-unsigned int platform_get_family(void)
-{
- return platform_family;
-}
-EXPORT_SYMBOL(platform_get_family);
-
-/*
- * platform_get_asic - determine the ASIC type.
- *
- * Returns the ASIC type, or ASIC_UNKNOWN if unknown
- *
- */
-enum asic_type platform_get_asic(void)
-{
- return asic;
-}
-EXPORT_SYMBOL(platform_get_asic);
-
-/*
- * set_register_map - set ASIC register configuration
- * @phys_base: Physical address of the base of the ASIC registers
- * @map: Description of key ASIC registers
- */
-static void __init set_register_map(unsigned long phys_base,
- const struct register_map *map)
-{
- asic_phy_base = phys_base;
- _asic_register_map = *map;
- register_map_virtualize(&_asic_register_map);
- asic_base = (unsigned long)ioremap_nocache(phys_base, ASIC_IO_SIZE);
-}
-
-/**
- * configure_platform - configuration based on platform type.
- */
-void __init configure_platform(void)
-{
- platform_set_family();
-
- switch (platform_family) {
- case FAMILY_1500:
- case FAMILY_1500VZE:
- case FAMILY_1500VZF:
- platform_features = FFS_CAPABLE;
- asic = ASIC_CALLIOPE;
- set_register_map(CALLIOPE_IO_BASE, &calliope_register_map);
-
- if (platform_family == FAMILY_1500VZE) {
- gp_resources = non_dvr_vze_calliope_resources;
- pr_info("Platform: 1500/Vz Class E - "
- "CALLIOPE, NON_DVR_CAPABLE\n");
- } else if (platform_family == FAMILY_1500VZF) {
- gp_resources = non_dvr_vzf_calliope_resources;
- pr_info("Platform: 1500/Vz Class F - "
- "CALLIOPE, NON_DVR_CAPABLE\n");
- } else {
- gp_resources = non_dvr_calliope_resources;
- pr_info("Platform: 1500/RNG100 - CALLIOPE, "
- "NON_DVR_CAPABLE\n");
- }
- break;
-
- case FAMILY_4500:
- platform_features = FFS_CAPABLE | PCIE_CAPABLE |
- DISPLAY_CAPABLE;
- asic = ASIC_ZEUS;
- set_register_map(ZEUS_IO_BASE, &zeus_register_map);
- gp_resources = non_dvr_zeus_resources;
-
- pr_info("Platform: 4500 - ZEUS, NON_DVR_CAPABLE\n");
- break;
-
- case FAMILY_4600:
- {
- unsigned int chipversion = 0;
-
- /* The settop has PCIE but it isn't used, so don't advertise
- * it*/
- platform_features = FFS_CAPABLE | DISPLAY_CAPABLE;
-
- /* Cronus and Cronus Lite have the same register map */
- set_register_map(CRONUS_IO_BASE, &cronus_register_map);
-
- /* ASIC version will determine if this is a real CronusLite or
- * Castrati(Cronus) */
- chipversion = asic_read(chipver3) << 24;
- chipversion |= asic_read(chipver2) << 16;
- chipversion |= asic_read(chipver1) << 8;
- chipversion |= asic_read(chipver0);
-
- if ((chipversion == CRONUS_10) || (chipversion == CRONUS_11))
- asic = ASIC_CRONUS;
- else
- asic = ASIC_CRONUSLITE;
-
- gp_resources = non_dvr_cronuslite_resources;
- pr_info("Platform: 4600 - %s, NON_DVR_CAPABLE, "
- "chipversion=0x%08X\n",
- (asic == ASIC_CRONUS) ? "CRONUS" : "CRONUS LITE",
- chipversion);
- break;
- }
- case FAMILY_4600VZA:
- platform_features = FFS_CAPABLE | DISPLAY_CAPABLE;
- asic = ASIC_CRONUS;
- set_register_map(CRONUS_IO_BASE, &cronus_register_map);
- gp_resources = non_dvr_cronus_resources;
-
- pr_info("Platform: Vz Class A - CRONUS, NON_DVR_CAPABLE\n");
- break;
-
- case FAMILY_8500:
- case FAMILY_8500RNG:
- platform_features = DVR_CAPABLE | PCIE_CAPABLE |
- DISPLAY_CAPABLE;
- asic = ASIC_ZEUS;
- set_register_map(ZEUS_IO_BASE, &zeus_register_map);
- gp_resources = dvr_zeus_resources;
-
- pr_info("Platform: 8500/RNG200 - ZEUS, DVR_CAPABLE\n");
- break;
-
- case FAMILY_8600:
- case FAMILY_8600VZB:
- platform_features = DVR_CAPABLE | PCIE_CAPABLE |
- DISPLAY_CAPABLE;
- asic = ASIC_CRONUS;
- set_register_map(CRONUS_IO_BASE, &cronus_register_map);
- gp_resources = dvr_cronus_resources;
-
- pr_info("Platform: 8600/Vz Class B - CRONUS, "
- "DVR_CAPABLE\n");
- break;
-
- case FAMILY_8700:
- platform_features = FFS_CAPABLE | PCIE_CAPABLE;
- asic = ASIC_GAIA;
- set_register_map(GAIA_IO_BASE, &gaia_register_map);
- gp_resources = dvr_gaia_resources;
-
- pr_info("Platform: 8700 - GAIA, DVR_CAPABLE\n");
- break;
-
- default:
- pr_crit("Platform: UNKNOWN PLATFORM\n");
- break;
- }
-
- switch (asic) {
- case ASIC_ZEUS:
- phys_to_dma_offset = 0x30000000;
- break;
- case ASIC_CALLIOPE:
- phys_to_dma_offset = 0x10000000;
- break;
- case ASIC_CRONUSLITE:
- /* Fall through */
- case ASIC_CRONUS:
- /*
- * TODO: We suppose 0x10000000 aliases into 0x20000000-
- * 0x2XXXXXXX. If 0x10000000 aliases into 0x60000000-
- * 0x6XXXXXXX, the offset should be 0x50000000, not 0x10000000.
- */
- phys_to_dma_offset = 0x10000000;
- break;
- default:
- phys_to_dma_offset = 0x00000000;
- break;
- }
-}
-
-/*
- * RESOURCE ALLOCATION
- *
- */
-/*
- * Allocates/reserves the Platform memory resources early in the boot process.
- * This ignores any resources that are designated IORESOURCE_IO
- */
-void __init platform_alloc_bootmem(void)
-{
- int i;
- int total = 0;
-
- /* Get persistent memory data from command line before allocating
- * resources. This need to happen before normal command line parsing
- * has been done */
- pmem_setup_resource();
-
- /* Loop through looking for resources that want a particular address */
- for (i = 0; gp_resources[i].flags != 0; i++) {
- int size = resource_size(&gp_resources[i]);
- if ((gp_resources[i].start != 0) &&
- ((gp_resources[i].flags & IORESOURCE_MEM) != 0)) {
- reserve_bootmem(dma_to_phys(gp_resources[i].start),
- size, 0);
- total += resource_size(&gp_resources[i]);
- pr_info("reserve resource %s at %08x (%u bytes)\n",
- gp_resources[i].name, gp_resources[i].start,
- resource_size(&gp_resources[i]));
- }
- }
-
- /* Loop through assigning addresses for those that are left */
- for (i = 0; gp_resources[i].flags != 0; i++) {
- int size = resource_size(&gp_resources[i]);
- if ((gp_resources[i].start == 0) &&
- ((gp_resources[i].flags & IORESOURCE_MEM) != 0)) {
- void *mem = alloc_bootmem_pages(size);
-
- if (mem == NULL)
- pr_err("Unable to allocate bootmem pages "
- "for %s\n", gp_resources[i].name);
-
- else {
- gp_resources[i].start =
- phys_to_dma(virt_to_phys(mem));
- gp_resources[i].end =
- gp_resources[i].start + size - 1;
- total += size;
- pr_info("allocate resource %s at %08x "
- "(%u bytes)\n",
- gp_resources[i].name,
- gp_resources[i].start, size);
- }
- }
- }
-
- pr_info("Total Platform driver memory allocation: 0x%08x\n", total);
-
- /* indicate resources that are platform I/O related */
- for (i = 0; gp_resources[i].flags != 0; i++) {
- if ((gp_resources[i].start != 0) &&
- ((gp_resources[i].flags & IORESOURCE_IO) != 0)) {
- pr_info("reserved platform resource %s at %08x\n",
- gp_resources[i].name, gp_resources[i].start);
- }
- }
-}
-
-/*
- *
- * PERSISTENT MEMORY (PMEM) CONFIGURATION
- *
- */
-static unsigned long pmemaddr __initdata;
-
-static int __init early_param_pmemaddr(char *p)
-{
- pmemaddr = (unsigned long)simple_strtoul(p, NULL, 0);
- return 0;
-}
-early_param("pmemaddr", early_param_pmemaddr);
-
-static long pmemlen __initdata;
-
-static int __init early_param_pmemlen(char *p)
-{
-/* TODO: we can use this code when and if the bootloader ever changes this */
-#if 0
- pmemlen = (unsigned long)simple_strtoul(p, NULL, 0);
-#else
- pmemlen = 0x20000;
-#endif
- return 0;
-}
-early_param("pmemlen", early_param_pmemlen);
-
-/*
- * Set up persistent memory. If we were given values, we patch the array of
- * resources. Otherwise, persistent memory may be allocated anywhere at all.
- */
-static void __init pmem_setup_resource(void)
-{
- struct resource *resource;
- resource = asic_resource_get("DiagPersistentMemory");
-
- if (resource && pmemaddr && pmemlen) {
- /* The address provided by bootloader is in kseg0. Convert to
- * a bus address. */
- resource->start = phys_to_dma(pmemaddr - 0x80000000);
- resource->end = resource->start + pmemlen - 1;
-
- pr_info("persistent memory: start=0x%x end=0x%x\n",
- resource->start, resource->end);
- }
-}
-
-/*
- *
- * RESOURCE ACCESS FUNCTIONS
- *
- */
-
-/**
- * asic_resource_get - retrieves parameters for a platform resource.
- * @name: string to match resource
- *
- * Returns a pointer to a struct resource corresponding to the given name.
- *
- * CANNOT BE NAMED platform_resource_get, which would be the obvious choice,
- * as this function name is already declared
- */
-struct resource *asic_resource_get(const char *name)
-{
- int i;
-
- for (i = 0; gp_resources[i].flags != 0; i++) {
- if (strcmp(gp_resources[i].name, name) == 0)
- return &gp_resources[i];
- }
-
- return NULL;
-}
-EXPORT_SYMBOL(asic_resource_get);
-
-/**
- * platform_release_memory - release pre-allocated memory
- * @ptr: pointer to memory to release
- * @size: size of resource
- *
- * This must only be called for memory allocated or reserved via the boot
- * memory allocator.
- */
-void platform_release_memory(void *ptr, int size)
-{
- free_reserved_area(ptr, ptr + size, -1, NULL);
-}
-EXPORT_SYMBOL(platform_release_memory);
-
-/*
- *
- * FEATURE AVAILABILITY FUNCTIONS
- *
- */
-int platform_supports_dvr(void)
-{
- return (platform_features & DVR_CAPABLE) != 0;
-}
-
-int platform_supports_ffs(void)
-{
- return (platform_features & FFS_CAPABLE) != 0;
-}
-
-int platform_supports_pcie(void)
-{
- return (platform_features & PCIE_CAPABLE) != 0;
-}
-
-int platform_supports_display(void)
-{
- return (platform_features & DISPLAY_CAPABLE) != 0;
-}
diff --git a/arch/mips/powertv/asic/asic_int.c b/arch/mips/powertv/asic/asic_int.c
deleted file mode 100644
index f44cd9295cae..000000000000
--- a/arch/mips/powertv/asic/asic_int.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
- * Copyright (C) 2001 Ralf Baechle
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- * This program is free software; you can distribute 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 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.
- *
- * Routines for generic manipulation of the interrupts found on the PowerTV
- * platform.
- *
- * The interrupt controller is located in the South Bridge a PIIX4 device
- * with two internal 82C95 interrupt controllers.
- */
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/kernel.h>
-#include <linux/random.h>
-
-#include <asm/irq_cpu.h>
-#include <linux/io.h>
-#include <asm/irq_regs.h>
-#include <asm/setup.h>
-#include <asm/mips-boards/generic.h>
-
-#include <asm/mach-powertv/asic_regs.h>
-
-static DEFINE_RAW_SPINLOCK(asic_irq_lock);
-
-static inline int get_int(void)
-{
- unsigned long flags;
- int irq;
-
- raw_spin_lock_irqsave(&asic_irq_lock, flags);
-
- irq = (asic_read(int_int_scan) >> 4) - 1;
-
- if (irq == 0 || irq >= NR_IRQS)
- irq = -1;
-
- raw_spin_unlock_irqrestore(&asic_irq_lock, flags);
-
- return irq;
-}
-
-static void asic_irqdispatch(void)
-{
- int irq;
-
- irq = get_int();
- if (irq < 0)
- return; /* interrupt has already been cleared */
-
- do_IRQ(irq);
-}
-
-static inline int clz(unsigned long x)
-{
- __asm__(
- " .set push \n"
- " .set mips32 \n"
- " clz %0, %1 \n"
- " .set pop \n"
- : "=r" (x)
- : "r" (x));
-
- return x;
-}
-
-/*
- * Version of ffs that only looks at bits 12..15.
- */
-static inline unsigned int irq_ffs(unsigned int pending)
-{
- return fls(pending) - 1 + CAUSEB_IP;
-}
-
-/*
- * TODO: check how it works under EIC mode.
- */
-asmlinkage void plat_irq_dispatch(void)
-{
- unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
- int irq;
-
- irq = irq_ffs(pending);
-
- if (irq == CAUSEF_IP3)
- asic_irqdispatch();
- else if (irq >= 0)
- do_IRQ(irq);
- else
- spurious_interrupt();
-}
-
-void __init arch_init_irq(void)
-{
- int i;
-
- asic_irq_init();
-
- /*
- * Initialize interrupt exception vectors.
- */
- if (cpu_has_veic || cpu_has_vint) {
- int nvec = cpu_has_veic ? 64 : 8;
- for (i = 0; i < nvec; i++)
- set_vi_handler(i, asic_irqdispatch);
- }
-}
diff --git a/arch/mips/powertv/asic/irq_asic.c b/arch/mips/powertv/asic/irq_asic.c
deleted file mode 100644
index 9344902dc586..000000000000
--- a/arch/mips/powertv/asic/irq_asic.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Portions copyright (C) 2005-2009 Scientific Atlanta
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- * Modified from arch/mips/kernel/irq-rm7000.c:
- * Copyright (C) 2003 Ralf Baechle
- *
- * 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 <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/irq.h>
-
-#include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
-
-#include <asm/mach-powertv/asic_regs.h>
-
-static inline void unmask_asic_irq(struct irq_data *d)
-{
- unsigned long enable_bit;
- unsigned int irq = d->irq;
-
- enable_bit = (1 << (irq & 0x1f));
-
- switch (irq >> 5) {
- case 0:
- asic_write(asic_read(ien_int_0) | enable_bit, ien_int_0);
- break;
- case 1:
- asic_write(asic_read(ien_int_1) | enable_bit, ien_int_1);
- break;
- case 2:
- asic_write(asic_read(ien_int_2) | enable_bit, ien_int_2);
- break;
- case 3:
- asic_write(asic_read(ien_int_3) | enable_bit, ien_int_3);
- break;
- default:
- BUG();
- }
-}
-
-static inline void mask_asic_irq(struct irq_data *d)
-{
- unsigned long disable_mask;
- unsigned int irq = d->irq;
-
- disable_mask = ~(1 << (irq & 0x1f));
-
- switch (irq >> 5) {
- case 0:
- asic_write(asic_read(ien_int_0) & disable_mask, ien_int_0);
- break;
- case 1:
- asic_write(asic_read(ien_int_1) & disable_mask, ien_int_1);
- break;
- case 2:
- asic_write(asic_read(ien_int_2) & disable_mask, ien_int_2);
- break;
- case 3:
- asic_write(asic_read(ien_int_3) & disable_mask, ien_int_3);
- break;
- default:
- BUG();
- }
-}
-
-static struct irq_chip asic_irq_chip = {
- .name = "ASIC Level",
- .irq_mask = mask_asic_irq,
- .irq_unmask = unmask_asic_irq,
-};
-
-void __init asic_irq_init(void)
-{
- int i;
-
- /* set priority to 0 */
- write_c0_status(read_c0_status() & ~(0x0000fc00));
-
- asic_write(0, ien_int_0);
- asic_write(0, ien_int_1);
- asic_write(0, ien_int_2);
- asic_write(0, ien_int_3);
-
- asic_write(0x0fffffff, int_level_3_3);
- asic_write(0xffffffff, int_level_3_2);
- asic_write(0xffffffff, int_level_3_1);
- asic_write(0xffffffff, int_level_3_0);
- asic_write(0xffffffff, int_level_2_3);
- asic_write(0xffffffff, int_level_2_2);
- asic_write(0xffffffff, int_level_2_1);
- asic_write(0xffffffff, int_level_2_0);
- asic_write(0xffffffff, int_level_1_3);
- asic_write(0xffffffff, int_level_1_2);
- asic_write(0xffffffff, int_level_1_1);
- asic_write(0xffffffff, int_level_1_0);
- asic_write(0xffffffff, int_level_0_3);
- asic_write(0xffffffff, int_level_0_2);
- asic_write(0xffffffff, int_level_0_1);
- asic_write(0xffffffff, int_level_0_0);
-
- asic_write(0xf, int_int_scan);
-
- /*
- * Initialize interrupt handlers.
- */
- for (i = 0; i < NR_IRQS; i++)
- irq_set_chip_and_handler(i, &asic_irq_chip, handle_level_irq);
-}
diff --git a/arch/mips/powertv/asic/prealloc-calliope.c b/arch/mips/powertv/asic/prealloc-calliope.c
deleted file mode 100644
index 98dc51650577..000000000000
--- a/arch/mips/powertv/asic/prealloc-calliope.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * Memory pre-allocations for Calliope boxes.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: Ken Eppinett
- * David Schleef <ds@schleef.org>
- */
-
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <asm/mach-powertv/asic.h>
-#include "prealloc.h"
-
-/*
- * NON_DVR_CAPABLE CALLIOPE RESOURCES
- */
-struct resource non_dvr_calliope_resources[] __initdata =
-{
- /*
- * VIDEO / LX1
- */
- /* Delta-Mu 1 image (2MiB) */
- PREALLOC_NORMAL("ST231aImage", 0x24000000, 0x24200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 monitor (8KiB) */
- PREALLOC_NORMAL("ST231aMonitor", 0x24200000, 0x24202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 RAM (~36.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory1", 0x24202000, 0x26700000-1,
- IORESOURCE_MEM)
-
- /*
- * Sysaudio Driver
- */
- /* DSP code and data images (1MiB) */
- PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC CPU PCM buffer (40KiB) */
- PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC AUX buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC Main buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * STAVEM driver/STAPI
- */
- /* 6MiB */
- PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00600000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * DOCSIS Subsystem
- */
- /* 7MiB */
- PREALLOC_DOCSIS("Docsis", 0x27500000, 0x27c00000-1, IORESOURCE_MEM)
-
- /*
- * GHW HAL Driver
- */
- /* PowerTV Graphics Heap (14MiB) */
- PREALLOC_NORMAL("GraphicsHeap", 0x26700000, 0x26700000+(14*1048576)-1,
- IORESOURCE_MEM)
-
- /*
- * multi com buffer area
- */
- /* 128KiB */
- PREALLOC_NORMAL("MulticomSHM", 0x23700000, 0x23720000-1,
- IORESOURCE_MEM)
-
- /*
- * DMA Ring buffer (don't need recording buffers)
- */
- /* 680KiB */
- PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x000AA000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit0
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * AVFS: player HAL memory
- */
- /* 945K * 3 for playback */
- PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x002c4c00-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * PMEM
- */
- /* Persistent memory for diagnostics (64KiB) */
- PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Smartcard
- */
- /* Read and write buffers for Internal/External cards (10KiB) */
- PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * NAND Flash
- */
- /* 10KiB */
- PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
- IORESOURCE_MEM)
-
- /*
- * Synopsys GMAC Memory Region
- */
- /* 64KiB */
- PREALLOC_NORMAL("GMAC", 0x00000000, 0x00010000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * TFTPBuffer
- *
- * This buffer is used in some minimal configurations (e.g. two-way
- * loader) for storing software images
- */
- PREALLOC_TFTP("TFTPBuffer", 0x00000000, MEBIBYTE(80)-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Add other resources here
- */
-
- /*
- * End of Resource marker
- */
- {
- .flags = 0,
- },
-};
-
-
-struct resource non_dvr_vze_calliope_resources[] __initdata =
-{
- /*
- * VIDEO / LX1
- */
- /* Delta-Mu 1 image (2MiB) */
- PREALLOC_NORMAL("ST231aImage", 0x22000000, 0x22200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 monitor (8KiB) */
- PREALLOC_NORMAL("ST231aMonitor", 0x22200000, 0x22202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 RAM (10.12MiB) */
- PREALLOC_NORMAL("MediaMemory1", 0x22202000, 0x22C20B85-1,
- IORESOURCE_MEM)
-
- /*
- * Sysaudio Driver
- */
- /* DSP code and data images (1MiB) */
- PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC CPU PCM buffer (40KiB) */
- PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC AUX buffer (16KiB) */
- PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00004000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC Main buffer (16KiB) */
- PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00004000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * STAVEM driver/STAPI
- */
- /* 3.125MiB */
- PREALLOC_NORMAL("AVMEMPartition0", 0x20396000, 0x206B6000-1,
- IORESOURCE_MEM)
-
- /*
- * GHW HAL Driver
- */
- /* PowerTV Graphics Heap (2.59MiB) */
- PREALLOC_NORMAL("GraphicsHeap", 0x20100000, 0x20396000-1,
- IORESOURCE_MEM)
-
- /*
- * multi com buffer area
- */
- /* 128KiB */
- PREALLOC_NORMAL("MulticomSHM", 0x206B6000, 0x206D6000-1,
- IORESOURCE_MEM)
-
- /*
- * DMA Ring buffer (don't need recording buffers)
- */
- /* 680KiB */
- PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x000AA000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit0
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * PMEM
- */
- /* Persistent memory for diagnostics (64KiB) */
- PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Smartcard
- */
- /* Read and write buffers for Internal/External cards (10KiB) */
- PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * NAND Flash
- */
- /* 10KiB */
- PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
- IORESOURCE_MEM)
-
- /*
- * Synopsys GMAC Memory Region
- */
- /* 64KiB */
- PREALLOC_NORMAL("GMAC", 0x00000000, 0x00010000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Add other resources here
- */
-
- /*
- * End of Resource marker
- */
- {
- .flags = 0,
- },
-};
-
-struct resource non_dvr_vzf_calliope_resources[] __initdata =
-{
- /*
- * VIDEO / LX1
- */
- /* Delta-Mu 1 image (2MiB) */
- PREALLOC_NORMAL("ST231aImage", 0x24000000, 0x24200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 monitor (8KiB) */
- PREALLOC_NORMAL("ST231aMonitor", 0x24200000, 0x24202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 RAM (~19.4 (21.5MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory1", 0x24202000, 0x25580000-1,
- IORESOURCE_MEM)
-
- /*
- * Sysaudio Driver
- */
- /* DSP code and data images (1MiB) */
- PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC CPU PCM buffer (40KiB) */
- PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC AUX buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC Main buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * STAVEM driver/STAPI
- */
- /* 4.5MiB */
- PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00480000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * GHW HAL Driver
- */
- /* PowerTV Graphics Heap (14MiB) */
- PREALLOC_NORMAL("GraphicsHeap", 0x25600000, 0x25600000+(14*1048576)-1,
- IORESOURCE_MEM)
-
- /*
- * multi com buffer area
- */
- /* 128KiB */
- PREALLOC_NORMAL("MulticomSHM", 0x23700000, 0x23720000-1,
- IORESOURCE_MEM)
-
- /*
- * DMA Ring buffer (don't need recording buffers)
- */
- /* 680KiB */
- PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x000AA000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit0
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit1
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins1", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * AVFS: player HAL memory
- */
- /* 945K * 3 for playback */
- PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x002c4c00-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * PMEM
- */
- /* Persistent memory for diagnostics (64KiB) */
- PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Smartcard
- */
- /* Read and write buffers for Internal/External cards (10KiB) */
- PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * NAND Flash
- */
- /* 10KiB */
- PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
- IORESOURCE_MEM)
-
- /*
- * Synopsys GMAC Memory Region
- */
- /* 64KiB */
- PREALLOC_NORMAL("GMAC", 0x00000000, 0x00010000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Add other resources here
- */
-
- /*
- * End of Resource marker
- */
- {
- .flags = 0,
- },
-};
diff --git a/arch/mips/powertv/asic/prealloc-cronus.c b/arch/mips/powertv/asic/prealloc-cronus.c
deleted file mode 100644
index 7c6ce7596935..000000000000
--- a/arch/mips/powertv/asic/prealloc-cronus.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Memory pre-allocations for Cronus boxes.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: Ken Eppinett
- * David Schleef <ds@schleef.org>
- */
-
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <asm/mach-powertv/asic.h>
-#include "prealloc.h"
-
-/*
- * DVR_CAPABLE CRONUS RESOURCES
- */
-struct resource dvr_cronus_resources[] __initdata =
-{
- /*
- * VIDEO1 / LX1
- */
- /* Delta-Mu 1 image (2MiB) */
- PREALLOC_NORMAL("ST231aImage", 0x24000000, 0x24200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 monitor (8KiB) */
- PREALLOC_NORMAL("ST231aMonitor", 0x24200000, 0x24202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory1", 0x24202000, 0x26000000-1,
- IORESOURCE_MEM)
-
- /*
- * VIDEO2 / LX2
- */
- /* Delta-Mu 2 image (2MiB) */
- PREALLOC_NORMAL("ST231bImage", 0x60000000, 0x60200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 2 monitor (8KiB) */
- PREALLOC_NORMAL("ST231bMonitor", 0x60200000, 0x60202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 2 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory2", 0x60202000, 0x62000000-1,
- IORESOURCE_MEM)
-
- /*
- * Sysaudio Driver
- */
- /* DSP code and data images (1MiB) */
- PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC CPU PCM buffer (40KiB) */
- PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC AUX buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC Main buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * STAVEM driver/STAPI
- *
- * This memory area is used for allocating buffers for Video decoding
- * purposes. Allocation/De-allocation within this buffer is managed
- * by the STAVMEM driver of the STAPI. They could be Decimated
- * Picture Buffers, Intermediate Buffers, as deemed necessary for
- * video decoding purposes, for any video decoders on Zeus.
- */
- /* 12MiB */
- PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00c00000-1,
- IORESOURCE_MEM)
-
- /*
- * DOCSIS Subsystem
- */
- /* 7MiB */
- PREALLOC_DOCSIS("Docsis", 0x67500000, 0x67c00000-1, IORESOURCE_MEM)
-
- /*
- * GHW HAL Driver
- */
- /* PowerTV Graphics Heap (14MiB) */
- PREALLOC_NORMAL("GraphicsHeap", 0x62700000, 0x63500000-1,
- IORESOURCE_MEM)
-
- /*
- * multi com buffer area
- */
- /* 128KiB */
- PREALLOC_NORMAL("MulticomSHM", 0x26000000, 0x26020000-1,
- IORESOURCE_MEM)
-
- /*
- * DMA Ring buffer
- */
- PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x002EA000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit0
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit1
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins1", 0x00000000, 0x00001000-1,
- IORESOURCE_MEM)
-
- /*
- * ITFS
- */
- /* 815,104 bytes each for 2 ITFS partitions. */
- PREALLOC_NORMAL("ITFS", 0x00000000, 0x0018E000-1, IORESOURCE_MEM)
-
- /*
- * AVFS
- */
- /* (945K * 8) = (128K * 3) 5 playbacks / 3 server */
- PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x007c2000-1,
- IORESOURCE_MEM)
-
- /* 4KiB */
- PREALLOC_NORMAL("AvfsFileSys", 0x00000000, 0x00001000-1,
- IORESOURCE_MEM)
-
- /*
- * PMEM
- */
- /* Persistent memory for diagnostics (64KiB) */
- PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Smartcard
- */
- /* Read and write buffers for Internal/External cards (10KiB) */
- PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
- IORESOURCE_MEM)
-
- /*
- * KAVNET
- */
- /* NP Reset Vector - must be of the form xxCxxxxx (4KiB) */
- PREALLOC_NORMAL("NP_Reset_Vector", 0x27c00000, 0x27c01000-1,
- IORESOURCE_MEM)
- /* NP Image - must be video bank 1 (320KiB) */
- PREALLOC_NORMAL("NP_Image", 0x27020000, 0x27070000-1, IORESOURCE_MEM)
- /* NP IPC - must be video bank 2 (512KiB) */
- PREALLOC_NORMAL("NP_IPC", 0x63500000, 0x63580000-1, IORESOURCE_MEM)
-
- /*
- * TFTPBuffer
- *
- * This buffer is used in some minimal configurations (e.g. two-way
- * loader) for storing software images
- */
- PREALLOC_TFTP("TFTPBuffer", 0x00000000, MEBIBYTE(80)-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Add other resources here
- */
-
- /*
- * End of Resource marker
- */
- {
- .flags = 0,
- },
-};
-
-/*
- * NON_DVR_CAPABLE CRONUS RESOURCES
- */
-struct resource non_dvr_cronus_resources[] __initdata =
-{
- /*
- * VIDEO1 / LX1
- */
- /* Delta-Mu 1 image (2MiB) */
- PREALLOC_NORMAL("ST231aImage", 0x24000000, 0x24200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 monitor (8KiB) */
- PREALLOC_NORMAL("ST231aMonitor", 0x24200000, 0x24202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory1", 0x24202000, 0x26000000-1,
- IORESOURCE_MEM)
-
- /*
- * VIDEO2 / LX2
- */
- /* Delta-Mu 2 image (2MiB) */
- PREALLOC_NORMAL("ST231bImage", 0x60000000, 0x60200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 2 monitor (8KiB) */
- PREALLOC_NORMAL("ST231bMonitor", 0x60200000, 0x60202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 2 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory2", 0x60202000, 0x62000000-1,
- IORESOURCE_MEM)
-
- /*
- * Sysaudio Driver
- */
- /* DSP code and data images (1MiB) */
- PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC CPU PCM buffer (40KiB) */
- PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC AUX buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC Main buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * STAVEM driver/STAPI
- *
- * This memory area is used for allocating buffers for Video decoding
- * purposes. Allocation/De-allocation within this buffer is managed
- * by the STAVMEM driver of the STAPI. They could be Decimated
- * Picture Buffers, Intermediate Buffers, as deemed necessary for
- * video decoding purposes, for any video decoders on Zeus.
- */
- /* 12MiB */
- PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00c00000-1,
- IORESOURCE_MEM)
-
- /*
- * DOCSIS Subsystem
- */
- /* 7MiB */
- PREALLOC_DOCSIS("Docsis", 0x67500000, 0x67c00000-1, IORESOURCE_MEM)
-
- /*
- * GHW HAL Driver
- */
- /* PowerTV Graphics Heap (14MiB) */
- PREALLOC_NORMAL("GraphicsHeap", 0x62700000, 0x63500000-1,
- IORESOURCE_MEM)
-
- /*
- * multi com buffer area
- */
- /* 128KiB */
- PREALLOC_NORMAL("MulticomSHM", 0x26000000, 0x26020000-1,
- IORESOURCE_MEM)
-
- /*
- * DMA Ring buffer (don't need recording buffers)
- */
- /* 680KiB */
- PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x000AA000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit0
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit1
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins1", 0x00000000, 0x00001000-1,
- IORESOURCE_MEM)
-
- /*
- * AVFS: player HAL memory
- */
- /* 945K * 3 for playback */
- PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x002c4c00-1, IORESOURCE_MEM)
-
- /*
- * PMEM
- */
- /* Persistent memory for diagnostics (64KiB) */
- PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Smartcard
- */
- /* Read and write buffers for Internal/External cards (10KiB) */
- PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1, IORESOURCE_MEM)
-
- /*
- * KAVNET
- */
- /* NP Reset Vector - must be of the form xxCxxxxx (4KiB) */
- PREALLOC_NORMAL("NP_Reset_Vector", 0x27c00000, 0x27c01000-1,
- IORESOURCE_MEM)
- /* NP Image - must be video bank 1 (320KiB) */
- PREALLOC_NORMAL("NP_Image", 0x27020000, 0x27070000-1, IORESOURCE_MEM)
- /* NP IPC - must be video bank 2 (512KiB) */
- PREALLOC_NORMAL("NP_IPC", 0x63500000, 0x63580000-1, IORESOURCE_MEM)
-
- /*
- * NAND Flash
- */
- /* 10KiB */
- PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
- IORESOURCE_MEM)
-
- /*
- * Add other resources here
- */
-
- /*
- * End of Resource marker
- */
- {
- .flags = 0,
- },
-};
diff --git a/arch/mips/powertv/asic/prealloc-cronuslite.c b/arch/mips/powertv/asic/prealloc-cronuslite.c
deleted file mode 100644
index a7937ba7b4c0..000000000000
--- a/arch/mips/powertv/asic/prealloc-cronuslite.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Memory pre-allocations for Cronus Lite boxes.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: Ken Eppinett
- * David Schleef <ds@schleef.org>
- */
-
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <asm/mach-powertv/asic.h>
-#include "prealloc.h"
-
-/*
- * NON_DVR_CAPABLE CRONUSLITE RESOURCES
- */
-struct resource non_dvr_cronuslite_resources[] __initdata =
-{
- /*
- * VIDEO2 / LX2
- */
- /* Delta-Mu 1 image (2MiB) */
- PREALLOC_NORMAL("ST231aImage", 0x60000000, 0x60200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 monitor (8KiB) */
- PREALLOC_NORMAL("ST231aMonitor", 0x60200000, 0x60202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory1", 0x60202000, 0x62000000-1,
- IORESOURCE_MEM)
-
- /*
- * Sysaudio Driver
- */
- /* DSP code and data images (1MiB) */
- PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC CPU PCM buffer (40KiB) */
- PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC AUX buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC Main buffer (128KiB) */
- PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00020000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * STAVEM driver/STAPI
- *
- * This memory area is used for allocating buffers for Video decoding
- * purposes. Allocation/De-allocation within this buffer is managed
- * by the STAVMEM driver of the STAPI. They could be Decimated
- * Picture Buffers, Intermediate Buffers, as deemed necessary for
- * video decoding purposes, for any video decoders on Zeus.
- */
- /* 6MiB */
- PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00600000-1,
- IORESOURCE_MEM)
-
- /*
- * DOCSIS Subsystem
- */
- /* 7MiB */
- PREALLOC_DOCSIS("Docsis", 0x67500000, 0x67c00000-1, IORESOURCE_MEM)
-
- /*
- * GHW HAL Driver
- */
- /* PowerTV Graphics Heap (14MiB) */
- PREALLOC_NORMAL("GraphicsHeap", 0x62700000, 0x63500000-1,
- IORESOURCE_MEM)
-
- /*
- * multi com buffer area
- */
- /* 128KiB */
- PREALLOC_NORMAL("MulticomSHM", 0x26000000, 0x26020000-1,
- IORESOURCE_MEM)
-
- /*
- * DMA Ring buffer (don't need recording buffers)
- */
- /* 680KiB */
- PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x000AA000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit0
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit1
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins1", 0x00000000, 0x00001000-1,
- IORESOURCE_MEM)
-
- /*
- * AVFS: player HAL memory
- */
- /* 945K * 3 for playback */
- PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x002c4c00-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * PMEM
- */
- /* Persistent memory for diagnostics (64KiB) */
- PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Smartcard
- */
- /* Read and write buffers for Internal/External cards (10KiB) */
- PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1, IORESOURCE_MEM)
-
- /*
- * KAVNET
- */
- /* NP Reset Vector - must be of the form xxCxxxxx (4KiB) */
- PREALLOC_NORMAL("NP_Reset_Vector", 0x27c00000, 0x27c01000-1,
- IORESOURCE_MEM)
- /* NP Image - must be video bank 1 (320KiB) */
- PREALLOC_NORMAL("NP_Image", 0x27020000, 0x27070000-1, IORESOURCE_MEM)
- /* NP IPC - must be video bank 2 (512KiB) */
- PREALLOC_NORMAL("NP_IPC", 0x63500000, 0x63580000-1, IORESOURCE_MEM)
-
- /*
- * NAND Flash
- */
- /* 10KiB */
- PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
- IORESOURCE_MEM)
-
- /*
- * TFTPBuffer
- *
- * This buffer is used in some minimal configurations (e.g. two-way
- * loader) for storing software images
- */
- PREALLOC_TFTP("TFTPBuffer", 0x00000000, MEBIBYTE(80)-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Add other resources here
- */
-
- /*
- * End of Resource marker
- */
- {
- .flags = 0,
- },
-};
diff --git a/arch/mips/powertv/asic/prealloc-gaia.c b/arch/mips/powertv/asic/prealloc-gaia.c
deleted file mode 100644
index 2303bbfe6b82..000000000000
--- a/arch/mips/powertv/asic/prealloc-gaia.c
+++ /dev/null
@@ -1,589 +0,0 @@
-/*
- * Memory pre-allocations for Gaia boxes.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: David VomLehn
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/asic.h>
-
-/*
- * DVR_CAPABLE GAIA RESOURCES
- */
-struct resource dvr_gaia_resources[] __initdata = {
- /*
- *
- * VIDEO1 / LX1
- *
- */
- {
- .name = "ST231aImage", /* Delta-Mu 1 image and ram */
- .start = 0x24000000,
- .end = 0x241FFFFF, /* 2MiB */
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "ST231aMonitor", /* 8KiB block ST231a monitor */
- .start = 0x24200000,
- .end = 0x24201FFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "MediaMemory1",
- .start = 0x24202000,
- .end = 0x25FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * VIDEO2 / LX2
- *
- */
- {
- .name = "ST231bImage", /* Delta-Mu 2 image and ram */
- .start = 0x60000000,
- .end = 0x601FFFFF, /* 2MiB */
- .flags = IORESOURCE_IO,
- },
- {
- .name = "ST231bMonitor", /* 8KiB block ST231b monitor */
- .start = 0x60200000,
- .end = 0x60201FFF,
- .flags = IORESOURCE_IO,
- },
- {
- .name = "MediaMemory2",
- .start = 0x60202000,
- .end = 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * Sysaudio Driver
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * DSP_Image_Buff - DSP code and data images (1MB)
- * ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB)
- * ADSC_AUX_Buff - ADSC AUX buffer (16KB)
- * ADSC_Main_Buff - ADSC Main buffer (16KB)
- *
- */
- {
- .name = "DSP_Image_Buff",
- .start = 0x00000000,
- .end = 0x000FFFFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "ADSC_CPU_PCM_Buff",
- .start = 0x00000000,
- .end = 0x00009FFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "ADSC_AUX_Buff",
- .start = 0x00000000,
- .end = 0x00003FFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "ADSC_Main_Buff",
- .start = 0x00000000,
- .end = 0x00003FFF,
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * STAVEM driver/STAPI
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * This memory area is used for allocating buffers for Video decoding
- * purposes. Allocation/De-allocation within this buffer is managed
- * by the STAVMEM driver of the STAPI. They could be Decimated
- * Picture Buffers, Intermediate Buffers, as deemed necessary for
- * video decoding purposes, for any video decoders on Zeus.
- *
- */
- {
- .name = "AVMEMPartition0",
- .start = 0x63580000,
- .end = 0x64180000 - 1, /* 12 MB total */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * DOCSIS Subsystem
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Docsis -
- *
- */
- {
- .name = "Docsis",
- .start = 0x62000000,
- .end = 0x62700000 - 1, /* 7 MB total */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * GHW HAL Driver
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * GraphicsHeap - PowerTV Graphics Heap
- *
- */
- {
- .name = "GraphicsHeap",
- .start = 0x62700000,
- .end = 0x63500000 - 1, /* 14 MB total */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * multi com buffer area
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Docsis -
- *
- */
- {
- .name = "MulticomSHM",
- .start = 0x26000000,
- .end = 0x26020000 - 1,
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * DMA Ring buffer
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Docsis -
- *
- */
- {
- .name = "BMM_Buffer",
- .start = 0x00000000,
- .end = 0x00280000 - 1,
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * Display bins buffer for unit0
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Display Bins for unit0
- *
- */
- {
- .name = "DisplayBins0",
- .start = 0x00000000,
- .end = 0x00000FFF, /* 4 KB total */
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * Display bins buffer
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Display Bins for unit1
- *
- */
- {
- .name = "DisplayBins1",
- .start = 0x64AD4000,
- .end = 0x64AD5000 - 1, /* 4 KB total */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * ITFS
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Docsis -
- *
- */
- {
- .name = "ITFS",
- .start = 0x64180000,
- /* 815,104 bytes each for 2 ITFS partitions. */
- .end = 0x6430DFFF,
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * AVFS
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Docsis -
- *
- */
- {
- .name = "AvfsDmaMem",
- .start = 0x6430E000,
- /* (945K * 8) = (128K *3) 5 playbacks / 3 server */
- .end = 0x64AD0000 - 1,
- .flags = IORESOURCE_IO,
- },
- {
- .name = "AvfsFileSys",
- .start = 0x64AD0000,
- .end = 0x64AD1000 - 1, /* 4K */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * Smartcard
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Read and write buffers for Internal/External cards
- *
- */
- {
- .name = "SmartCardInfo",
- .start = 0x64AD1000,
- .end = 0x64AD3800 - 1,
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * KAVNET
- * NP Reset Vector - must be of the form xxCxxxxx
- * NP Image - must be video bank 1
- * NP IPC - must be video bank 2
- */
- {
- .name = "NP_Reset_Vector",
- .start = 0x27c00000,
- .end = 0x27c01000 - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "NP_Image",
- .start = 0x27020000,
- .end = 0x27060000 - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "NP_IPC",
- .start = 0x63500000,
- .end = 0x63580000 - 1,
- .flags = IORESOURCE_IO,
- },
- /*
- * Add other resources here
- */
- { },
-};
-
-/*
- * NON_DVR_CAPABLE GAIA RESOURCES
- */
-struct resource non_dvr_gaia_resources[] __initdata = {
- /*
- *
- * VIDEO1 / LX1
- *
- */
- {
- .name = "ST231aImage", /* Delta-Mu 1 image and ram */
- .start = 0x24000000,
- .end = 0x241FFFFF, /* 2MiB */
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "ST231aMonitor", /* 8KiB block ST231a monitor */
- .start = 0x24200000,
- .end = 0x24201FFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "MediaMemory1",
- .start = 0x24202000,
- .end = 0x25FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * VIDEO2 / LX2
- *
- */
- {
- .name = "ST231bImage", /* Delta-Mu 2 image and ram */
- .start = 0x60000000,
- .end = 0x601FFFFF, /* 2MiB */
- .flags = IORESOURCE_IO,
- },
- {
- .name = "ST231bMonitor", /* 8KiB block ST231b monitor */
- .start = 0x60200000,
- .end = 0x60201FFF,
- .flags = IORESOURCE_IO,
- },
- {
- .name = "MediaMemory2",
- .start = 0x60202000,
- .end = 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * Sysaudio Driver
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * DSP_Image_Buff - DSP code and data images (1MB)
- * ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB)
- * ADSC_AUX_Buff - ADSC AUX buffer (16KB)
- * ADSC_Main_Buff - ADSC Main buffer (16KB)
- *
- */
- {
- .name = "DSP_Image_Buff",
- .start = 0x00000000,
- .end = 0x000FFFFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "ADSC_CPU_PCM_Buff",
- .start = 0x00000000,
- .end = 0x00009FFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "ADSC_AUX_Buff",
- .start = 0x00000000,
- .end = 0x00003FFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "ADSC_Main_Buff",
- .start = 0x00000000,
- .end = 0x00003FFF,
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * STAVEM driver/STAPI
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * This memory area is used for allocating buffers for Video decoding
- * purposes. Allocation/De-allocation within this buffer is managed
- * by the STAVMEM driver of the STAPI. They could be Decimated
- * Picture Buffers, Intermediate Buffers, as deemed necessary for
- * video decoding purposes, for any video decoders on Zeus.
- *
- */
- {
- .name = "AVMEMPartition0",
- .start = 0x63580000,
- .end = 0x64180000 - 1, /* 12 MB total */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * DOCSIS Subsystem
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Docsis -
- *
- */
- {
- .name = "Docsis",
- .start = 0x62000000,
- .end = 0x62700000 - 1, /* 7 MB total */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * GHW HAL Driver
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * GraphicsHeap - PowerTV Graphics Heap
- *
- */
- {
- .name = "GraphicsHeap",
- .start = 0x62700000,
- .end = 0x63500000 - 1, /* 14 MB total */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * multi com buffer area
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Docsis -
- *
- */
- {
- .name = "MulticomSHM",
- .start = 0x26000000,
- .end = 0x26020000 - 1,
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * DMA Ring buffer
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Docsis -
- *
- */
- {
- .name = "BMM_Buffer",
- .start = 0x00000000,
- .end = 0x000AA000 - 1,
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * Display bins buffer for unit0
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Display Bins for unit0
- *
- */
- {
- .name = "DisplayBins0",
- .start = 0x00000000,
- .end = 0x00000FFF, /* 4 KB total */
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * Display bins buffer
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Display Bins for unit1
- *
- */
- {
- .name = "DisplayBins1",
- .start = 0x64AD4000,
- .end = 0x64AD5000 - 1, /* 4 KB total */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * AVFS: player HAL memory
- *
- *
- */
- {
- .name = "AvfsDmaMem",
- .start = 0x6430E000,
- .end = 0x645D2C00 - 1, /* 945K * 3 for playback */
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * PMEM
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Persistent memory for diagnostics.
- *
- */
- {
- .name = "DiagPersistentMemory",
- .start = 0x00000000,
- .end = 0x10000 - 1,
- .flags = IORESOURCE_MEM,
- },
- /*
- *
- * Smartcard
- *
- * This driver requires:
- *
- * Arbitrary Based Buffers:
- * Read and write buffers for Internal/External cards
- *
- */
- {
- .name = "SmartCardInfo",
- .start = 0x64AD1000,
- .end = 0x64AD3800 - 1,
- .flags = IORESOURCE_IO,
- },
- /*
- *
- * KAVNET
- * NP Reset Vector - must be of the form xxCxxxxx
- * NP Image - must be video bank 1
- * NP IPC - must be video bank 2
- */
- {
- .name = "NP_Reset_Vector",
- .start = 0x27c00000,
- .end = 0x27c01000 - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "NP_Image",
- .start = 0x27020000,
- .end = 0x27060000 - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "NP_IPC",
- .start = 0x63500000,
- .end = 0x63580000 - 1,
- .flags = IORESOURCE_IO,
- },
- { },
-};
diff --git a/arch/mips/powertv/asic/prealloc-zeus.c b/arch/mips/powertv/asic/prealloc-zeus.c
deleted file mode 100644
index 6e76f09c68d6..000000000000
--- a/arch/mips/powertv/asic/prealloc-zeus.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Memory pre-allocations for Zeus boxes.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: Ken Eppinett
- * David Schleef <ds@schleef.org>
- */
-
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <asm/mach-powertv/asic.h>
-#include "prealloc.h"
-
-/*
- * DVR_CAPABLE RESOURCES
- */
-struct resource dvr_zeus_resources[] __initdata =
-{
- /*
- * VIDEO1 / LX1
- */
- /* Delta-Mu 1 image (2MiB) */
- PREALLOC_NORMAL("ST231aImage", 0x20000000, 0x20200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 monitor (8KiB) */
- PREALLOC_NORMAL("ST231aMonitor", 0x20200000, 0x20202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory1", 0x20202000, 0x22000000-1,
- IORESOURCE_MEM)
-
- /*
- * VIDEO2 / LX2
- */
- /* Delta-Mu 2 image (2MiB) */
- PREALLOC_NORMAL("ST231bImage", 0x30000000, 0x30200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 2 monitor (8KiB) */
- PREALLOC_NORMAL("ST231bMonitor", 0x30200000, 0x30202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 2 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory2", 0x30202000, 0x32000000-1,
- IORESOURCE_MEM)
-
- /*
- * Sysaudio Driver
- */
- /* DSP code and data images (1MiB) */
- PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC CPU PCM buffer (40KiB) */
- PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC AUX buffer (16KiB) */
- PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00004000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC Main buffer (16KiB) */
- PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00004000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * STAVEM driver/STAPI
- *
- * This memory area is used for allocating buffers for Video decoding
- * purposes. Allocation/De-allocation within this buffer is managed
- * by the STAVMEM driver of the STAPI. They could be Decimated
- * Picture Buffers, Intermediate Buffers, as deemed necessary for
- * video decoding purposes, for any video decoders on Zeus.
- */
- /* 12MiB */
- PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00c00000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * DOCSIS Subsystem
- */
- /* 7MiB */
- PREALLOC_DOCSIS("Docsis", 0x40100000, 0x40800000-1, IORESOURCE_MEM)
-
- /*
- * GHW HAL Driver
- */
- /* PowerTV Graphics Heap (14MiB) */
- PREALLOC_NORMAL("GraphicsHeap", 0x46900000, 0x47700000-1,
- IORESOURCE_MEM)
-
- /*
- * multi com buffer area
- */
- /* 128KiB */
- PREALLOC_NORMAL("MulticomSHM", 0x47900000, 0x47920000-1,
- IORESOURCE_MEM)
-
- /*
- * DMA Ring buffer
- */
- /* 2.5MiB */
- PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x00280000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit0
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit1
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins1", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * ITFS
- */
- /* 815,104 bytes each for 2 ITFS partitions. */
- PREALLOC_NORMAL("ITFS", 0x00000000, 0x0018E000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * AVFS
- */
- /* (945K * 8) = (128K * 3) 5 playbacks / 3 server */
- PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x007c2000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* 4KiB */
- PREALLOC_NORMAL("AvfsFileSys", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * PMEM
- */
- /* Persistent memory for diagnostics (64KiB) */
- PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Smartcard
- */
- /* Read and write buffers for Internal/External cards (10KiB) */
- PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * TFTPBuffer
- *
- * This buffer is used in some minimal configurations (e.g. two-way
- * loader) for storing software images
- */
- PREALLOC_TFTP("TFTPBuffer", 0x00000000, MEBIBYTE(80)-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Add other resources here
- */
-
- /*
- * End of Resource marker
- */
- {
- .flags = 0,
- },
-};
-
-/*
- * NON_DVR_CAPABLE ZEUS RESOURCES
- */
-struct resource non_dvr_zeus_resources[] __initdata =
-{
- /*
- * VIDEO1 / LX1
- */
- /* Delta-Mu 1 image (2MiB) */
- PREALLOC_NORMAL("ST231aImage", 0x20000000, 0x20200000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 monitor (8KiB) */
- PREALLOC_NORMAL("ST231aMonitor", 0x20200000, 0x20202000-1,
- IORESOURCE_MEM)
- /* Delta-Mu 1 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
- PREALLOC_NORMAL("MediaMemory1", 0x20202000, 0x22000000-1,
- IORESOURCE_MEM)
-
- /*
- * Sysaudio Driver
- */
- /* DSP code and data images (1MiB) */
- PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC CPU PCM buffer (40KiB) */
- PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC AUX buffer (16KiB) */
- PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00004000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
- /* ADSC Main buffer (16KiB) */
- PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00004000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * STAVEM driver/STAPI
- */
- /* 6MiB */
- PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00600000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * DOCSIS Subsystem
- */
- /* 7MiB */
- PREALLOC_DOCSIS("Docsis", 0x40100000, 0x40800000-1, IORESOURCE_MEM)
-
- /*
- * GHW HAL Driver
- */
- /* PowerTV Graphics Heap (14MiB) */
- PREALLOC_NORMAL("GraphicsHeap", 0x46900000, 0x47700000-1,
- IORESOURCE_MEM)
-
- /*
- * multi com buffer area
- */
- /* 128KiB */
- PREALLOC_NORMAL("MulticomSHM", 0x47900000, 0x47920000-1,
- IORESOURCE_MEM)
-
- /*
- * DMA Ring buffer
- */
- /* 2.5MiB */
- PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x00280000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Display bins buffer for unit0
- */
- /* 4KiB */
- PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * AVFS: player HAL memory
- */
- /* 945K * 3 for playback */
- PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x002c4c00-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * PMEM
- */
- /* Persistent memory for diagnostics (64KiB) */
- PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Smartcard
- */
- /* Read and write buffers for Internal/External cards (10KiB) */
- PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * NAND Flash
- */
- /* 10KiB */
- PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
- IORESOURCE_MEM)
-
- /*
- * TFTPBuffer
- *
- * This buffer is used in some minimal configurations (e.g. two-way
- * loader) for storing software images
- */
- PREALLOC_TFTP("TFTPBuffer", 0x00000000, MEBIBYTE(80)-1,
- (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
- /*
- * Add other resources here
- */
-
- /*
- * End of Resource marker
- */
- {
- .flags = 0,
- },
-};
diff --git a/arch/mips/powertv/asic/prealloc.h b/arch/mips/powertv/asic/prealloc.h
deleted file mode 100644
index 8e682df17856..000000000000
--- a/arch/mips/powertv/asic/prealloc.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Definitions for memory preallocations
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _ARCH_MIPS_POWERTV_ASIC_PREALLOC_H
-#define _ARCH_MIPS_POWERTV_ASIC_PREALLOC_H
-
-#define KIBIBYTE(n) ((n) * 1024) /* Number of kibibytes */
-#define MEBIBYTE(n) ((n) * KIBIBYTE(1024)) /* Number of mebibytes */
-
-/* "struct resource" array element definition */
-#define PREALLOC(NAME, START, END, FLAGS) { \
- .name = (NAME), \
- .start = (START), \
- .end = (END), \
- .flags = (FLAGS) \
- },
-
-/* Individual resources in the preallocated resource arrays are defined using
- * macros. These macros are conditionally defined based on their
- * corresponding kernel configuration flag:
- * - CONFIG_PREALLOC_NORMAL: preallocate resources for a normal settop box
- * - CONFIG_PREALLOC_TFTP: preallocate the TFTP download resource
- * - CONFIG_PREALLOC_DOCSIS: preallocate the DOCSIS resource
- * - CONFIG_PREALLOC_PMEM: reserve space for persistent memory
- */
-#ifdef CONFIG_PREALLOC_NORMAL
-#define PREALLOC_NORMAL(name, start, end, flags) \
- PREALLOC(name, start, end, flags)
-#else
-#define PREALLOC_NORMAL(name, start, end, flags)
-#endif
-
-#ifdef CONFIG_PREALLOC_TFTP
-#define PREALLOC_TFTP(name, start, end, flags) \
- PREALLOC(name, start, end, flags)
-#else
-#define PREALLOC_TFTP(name, start, end, flags)
-#endif
-
-#ifdef CONFIG_PREALLOC_DOCSIS
-#define PREALLOC_DOCSIS(name, start, end, flags) \
- PREALLOC(name, start, end, flags)
-#else
-#define PREALLOC_DOCSIS(name, start, end, flags)
-#endif
-
-#ifdef CONFIG_PREALLOC_PMEM
-#define PREALLOC_PMEM(name, start, end, flags) \
- PREALLOC(name, start, end, flags)
-#else
-#define PREALLOC_PMEM(name, start, end, flags)
-#endif
-#endif
diff --git a/arch/mips/powertv/init.c b/arch/mips/powertv/init.c
deleted file mode 100644
index 498926377e51..000000000000
--- a/arch/mips/powertv/init.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 1999, 2000, 2004, 2005 MIPS Technologies, Inc.
- * All rights reserved.
- * Authors: Carsten Langgaard <carstenl@mips.com>
- * Maciej W. Rozycki <macro@mips.com>
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- * This program is free software; you can distribute 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 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.
- *
- * PROM library initialisation code.
- */
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-#include <asm/bootinfo.h>
-#include <linux/io.h>
-#include <asm/cacheflush.h>
-#include <asm/traps.h>
-
-#include <asm/mips-boards/generic.h>
-#include <asm/mach-powertv/asic.h>
-
-#include "init.h"
-
-static int *_prom_envp;
-unsigned long _prom_memsize;
-
-/*
- * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
- * This macro take care of sign extension, if running in 64-bit mode.
- */
-#define prom_envp(index) ((char *)(long)_prom_envp[(index)])
-
-char *prom_getenv(char *envname)
-{
- char *result = NULL;
-
- if (_prom_envp != NULL) {
- /*
- * Return a pointer to the given environment variable.
- * In 64-bit mode: we're using 64-bit pointers, but all pointers
- * in the PROM structures are only 32-bit, so we need some
- * workarounds, if we are running in 64-bit mode.
- */
- int i, index = 0;
-
- i = strlen(envname);
-
- while (prom_envp(index)) {
- if (strncmp(envname, prom_envp(index), i) == 0) {
- result = prom_envp(index + 1);
- break;
- }
- index += 2;
- }
- }
-
- return result;
-}
-
-void __init prom_init(void)
-{
- int prom_argc;
- char *prom_argv;
-
- prom_argc = fw_arg0;
- prom_argv = (char *) fw_arg1;
- _prom_envp = (int *) fw_arg2;
- _prom_memsize = (unsigned long) fw_arg3;
-
- if (prom_argc == 1) {
- strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
- strlcat(arcs_cmdline, prom_argv, COMMAND_LINE_SIZE);
- }
-
- configure_platform();
- prom_meminit();
-}
diff --git a/arch/mips/powertv/init.h b/arch/mips/powertv/init.h
deleted file mode 100644
index c1a8bd0dbe4b..000000000000
--- a/arch/mips/powertv/init.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Definitions from powertv init.c file
- *
- * Copyright (C) 2009 Cisco Systems, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: David VomLehn
- */
-
-#ifndef _POWERTV_INIT_H
-#define _POWERTV_INIT_H
-extern unsigned long _prom_memsize;
-extern void prom_meminit(void);
-extern char *prom_getenv(char *name);
-#endif
diff --git a/arch/mips/powertv/ioremap.c b/arch/mips/powertv/ioremap.c
deleted file mode 100644
index d060478aab03..000000000000
--- a/arch/mips/powertv/ioremap.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * ioremap.c
- *
- * Support for mapping between dma_addr_t values a phys_addr_t values.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: David VomLehn <dvomlehn@cisco.com>
- *
- * Description: Defines the platform resources for the SA settop.
- *
- * NOTE: The bootloader allocates persistent memory at an address which is
- * 16 MiB below the end of the highest address in KSEG0. All fixed
- * address memory reservations must avoid this region.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include <asm/mach-powertv/ioremap.h>
-
-/*
- * Define the sizes of and masks for grains in physical and DMA space. The
- * values are the same but the types are not.
- */
-#define IOR_PHYS_GRAIN ((phys_addr_t) 1 << IOR_LSBITS)
-#define IOR_PHYS_GRAIN_MASK (IOR_PHYS_GRAIN - 1)
-
-#define IOR_DMA_GRAIN ((dma_addr_t) 1 << IOR_LSBITS)
-#define IOR_DMA_GRAIN_MASK (IOR_DMA_GRAIN - 1)
-
-/*
- * Values that, when accessed by an index derived from a phys_addr_t and
- * added to phys_addr_t value, yield a DMA address
- */
-struct ior_phys_to_dma _ior_phys_to_dma[IOR_NUM_PHYS_TO_DMA];
-EXPORT_SYMBOL(_ior_phys_to_dma);
-
-/*
- * Values that, when accessed by an index derived from a dma_addr_t and
- * added to that dma_addr_t value, yield a physical address
- */
-struct ior_dma_to_phys _ior_dma_to_phys[IOR_NUM_DMA_TO_PHYS];
-EXPORT_SYMBOL(_ior_dma_to_phys);
-
-/**
- * setup_dma_to_phys - set up conversion from DMA to physical addresses
- * @dma_idx: Top IOR_LSBITS bits of the DMA address, i.e. an index
- * into the array _dma_to_phys.
- * @delta: Value that, when added to the DMA address, will yield the
- * physical address
- * @s: Number of bytes in the section of memory with the given delta
- * between DMA and physical addresses.
- */
-static void setup_dma_to_phys(dma_addr_t dma, phys_addr_t delta, dma_addr_t s)
-{
- int dma_idx, first_idx, last_idx;
- phys_addr_t first, last;
-
- /*
- * Calculate the first and last indices, rounding the first up and
- * the second down.
- */
- first = dma & ~IOR_DMA_GRAIN_MASK;
- last = (dma + s - 1) & ~IOR_DMA_GRAIN_MASK;
- first_idx = first >> IOR_LSBITS; /* Convert to indices */
- last_idx = last >> IOR_LSBITS;
-
- for (dma_idx = first_idx; dma_idx <= last_idx; dma_idx++)
- _ior_dma_to_phys[dma_idx].offset = delta >> IOR_DMA_SHIFT;
-}
-
-/**
- * setup_phys_to_dma - set up conversion from DMA to physical addresses
- * @phys_idx: Top IOR_LSBITS bits of the DMA address, i.e. an index
- * into the array _phys_to_dma.
- * @delta: Value that, when added to the DMA address, will yield the
- * physical address
- * @s: Number of bytes in the section of memory with the given delta
- * between DMA and physical addresses.
- */
-static void setup_phys_to_dma(phys_addr_t phys, dma_addr_t delta, phys_addr_t s)
-{
- int phys_idx, first_idx, last_idx;
- phys_addr_t first, last;
-
- /*
- * Calculate the first and last indices, rounding the first up and
- * the second down.
- */
- first = phys & ~IOR_PHYS_GRAIN_MASK;
- last = (phys + s - 1) & ~IOR_PHYS_GRAIN_MASK;
- first_idx = first >> IOR_LSBITS; /* Convert to indices */
- last_idx = last >> IOR_LSBITS;
-
- for (phys_idx = first_idx; phys_idx <= last_idx; phys_idx++)
- _ior_phys_to_dma[phys_idx].offset = delta >> IOR_PHYS_SHIFT;
-}
-
-/**
- * ioremap_add_map - add to the physical and DMA address conversion arrays
- * @phys: Process's view of the address of the start of the memory chunk
- * @dma: DMA address of the start of the memory chunk
- * @size: Size, in bytes, of the chunk of memory
- *
- * NOTE: It might be obvious, but the assumption is that all @size bytes have
- * the same offset between the physical address and the DMA address.
- */
-void ioremap_add_map(phys_addr_t phys, phys_addr_t dma, phys_addr_t size)
-{
- if (size == 0)
- return;
-
- if ((dma & IOR_DMA_GRAIN_MASK) != 0 ||
- (phys & IOR_PHYS_GRAIN_MASK) != 0 ||
- (size & IOR_PHYS_GRAIN_MASK) != 0)
- pr_crit("Memory allocation must be in chunks of 0x%x bytes\n",
- IOR_PHYS_GRAIN);
-
- setup_dma_to_phys(dma, phys - dma, size);
- setup_phys_to_dma(phys, dma - phys, size);
-}
diff --git a/arch/mips/powertv/memory.c b/arch/mips/powertv/memory.c
deleted file mode 100644
index bc2f3ca22b41..000000000000
--- a/arch/mips/powertv/memory.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- * This program is free software; you can distribute 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 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.
- *
- * Apparently originally from arch/mips/malta-memory.c. Modified to work
- * with the PowerTV bootloader.
- */
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/pfn.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/sections.h>
-
-#include <asm/mach-powertv/asic.h>
-#include <asm/mach-powertv/ioremap.h>
-
-#include "init.h"
-
-/* Memory constants */
-#define KIBIBYTE(n) ((n) * 1024) /* Number of kibibytes */
-#define MEBIBYTE(n) ((n) * KIBIBYTE(1024)) /* Number of mebibytes */
-#define DEFAULT_MEMSIZE MEBIBYTE(128) /* If no memsize provided */
-
-#define BLDR_SIZE KIBIBYTE(256) /* Memory reserved for bldr */
-#define RV_SIZE MEBIBYTE(4) /* Size of reset vector */
-
-#define LOW_MEM_END 0x20000000 /* Highest low memory address */
-#define BLDR_ALIAS 0x10000000 /* Bootloader address */
-#define RV_PHYS 0x1fc00000 /* Reset vector address */
-#define LOW_RAM_END RV_PHYS /* End of real RAM in low mem */
-
-/*
- * Very low-level conversion from processor physical address to device
- * DMA address for the first bank of memory.
- */
-#define PHYS_TO_DMA(paddr) ((paddr) + (CONFIG_LOW_RAM_DMA - LOW_RAM_ALIAS))
-
-unsigned long ptv_memsize;
-
-/*
- * struct low_mem_reserved - Items in low memory that are reserved
- * @start: Physical address of item
- * @size: Size, in bytes, of this item
- * @is_aliased: True if this is RAM aliased from another location. If false,
- * it is something other than aliased RAM and the RAM in the
- * unaliased address is still visible outside of low memory.
- */
-struct low_mem_reserved {
- phys_addr_t start;
- phys_addr_t size;
- bool is_aliased;
-};
-
-/*
- * Must be in ascending address order
- */
-struct low_mem_reserved low_mem_reserved[] = {
- {BLDR_ALIAS, BLDR_SIZE, true}, /* Bootloader RAM */
- {RV_PHYS, RV_SIZE, false}, /* Reset vector */
-};
-
-/*
- * struct mem_layout - layout of a piece of the system RAM
- * @phys: Physical address of the start of this piece of RAM. This is the
- * address at which both the processor and I/O devices see the
- * RAM.
- * @alias: Alias of this piece of memory in order to make it appear in
- * the low memory part of the processor's address space. I/O
- * devices don't see anything here.
- * @size: Size, in bytes, of this piece of RAM
- */
-struct mem_layout {
- phys_addr_t phys;
- phys_addr_t alias;
- phys_addr_t size;
-};
-
-/*
- * struct mem_layout_list - list descriptor for layouts of system RAM pieces
- * @family: Specifies the family being described
- * @n: Number of &struct mem_layout elements
- * @layout: Pointer to the list of &mem_layout structures
- */
-struct mem_layout_list {
- enum family_type family;
- size_t n;
- struct mem_layout *layout;
-};
-
-static struct mem_layout f1500_layout[] = {
- {0x20000000, 0x10000000, MEBIBYTE(256)},
-};
-
-static struct mem_layout f4500_layout[] = {
- {0x40000000, 0x10000000, MEBIBYTE(256)},
- {0x20000000, 0x20000000, MEBIBYTE(32)},
-};
-
-static struct mem_layout f8500_layout[] = {
- {0x40000000, 0x10000000, MEBIBYTE(256)},
- {0x20000000, 0x20000000, MEBIBYTE(32)},
- {0x30000000, 0x30000000, MEBIBYTE(32)},
-};
-
-static struct mem_layout fx600_layout[] = {
- {0x20000000, 0x10000000, MEBIBYTE(256)},
- {0x60000000, 0x60000000, MEBIBYTE(128)},
-};
-
-static struct mem_layout_list layout_list[] = {
- {FAMILY_1500, ARRAY_SIZE(f1500_layout), f1500_layout},
- {FAMILY_1500VZE, ARRAY_SIZE(f1500_layout), f1500_layout},
- {FAMILY_1500VZF, ARRAY_SIZE(f1500_layout), f1500_layout},
- {FAMILY_4500, ARRAY_SIZE(f4500_layout), f4500_layout},
- {FAMILY_8500, ARRAY_SIZE(f8500_layout), f8500_layout},
- {FAMILY_8500RNG, ARRAY_SIZE(f8500_layout), f8500_layout},
- {FAMILY_4600, ARRAY_SIZE(fx600_layout), fx600_layout},
- {FAMILY_4600VZA, ARRAY_SIZE(fx600_layout), fx600_layout},
- {FAMILY_8600, ARRAY_SIZE(fx600_layout), fx600_layout},
- {FAMILY_8600VZB, ARRAY_SIZE(fx600_layout), fx600_layout},
-};
-
-/* If we can't determine the layout, use this */
-static struct mem_layout default_layout[] = {
- {0x20000000, 0x10000000, MEBIBYTE(128)},
-};
-
-/**
- * register_non_ram - register low memory not available for RAM usage
- */
-static __init void register_non_ram(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(low_mem_reserved); i++)
- add_memory_region(low_mem_reserved[i].start,
- low_mem_reserved[i].size, BOOT_MEM_RESERVED);
-}
-
-/**
- * get_memsize - get the size of memory as a single bank
- */
-static phys_addr_t get_memsize(void)
-{
- static char cmdline[COMMAND_LINE_SIZE] __initdata;
- phys_addr_t memsize = 0;
- char *memsize_str;
- char *ptr;
-
- /* Check the command line first for a memsize directive */
- strcpy(cmdline, arcs_cmdline);
- ptr = strstr(cmdline, "memsize=");
- if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
- ptr = strstr(ptr, " memsize=");
-
- if (ptr) {
- memsize = memparse(ptr + 8, &ptr);
- } else {
- /* otherwise look in the environment */
- memsize_str = prom_getenv("memsize");
-
- if (memsize_str != NULL) {
- pr_info("prom memsize = %s\n", memsize_str);
- memsize = simple_strtol(memsize_str, NULL, 0);
- }
-
- if (memsize == 0) {
- if (_prom_memsize != 0) {
- memsize = _prom_memsize;
- pr_info("_prom_memsize = 0x%x\n", memsize);
- /* add in memory that the bootloader doesn't
- * report */
- memsize += BLDR_SIZE;
- } else {
- memsize = DEFAULT_MEMSIZE;
- pr_info("Memsize not passed by bootloader, "
- "defaulting to 0x%x\n", memsize);
- }
- }
- }
-
- return memsize;
-}
-
-/**
- * register_low_ram - register an aliased section of RAM
- * @p: Alias address of memory
- * @n: Number of bytes in this section of memory
- *
- * Returns the number of bytes registered
- *
- */
-static __init phys_addr_t register_low_ram(phys_addr_t p, phys_addr_t n)
-{
- phys_addr_t s;
- int i;
- phys_addr_t orig_n;
-
- orig_n = n;
-
- BUG_ON(p + n > RV_PHYS);
-
- for (i = 0; n != 0 && i < ARRAY_SIZE(low_mem_reserved); i++) {
- phys_addr_t start;
- phys_addr_t size;
-
- start = low_mem_reserved[i].start;
- size = low_mem_reserved[i].size;
-
- /* Handle memory before this low memory section */
- if (p < start) {
- phys_addr_t s;
- s = min(n, start - p);
- add_memory_region(p, s, BOOT_MEM_RAM);
- p += s;
- n -= s;
- }
-
- /* Handle the low memory section itself. If it's aliased,
- * we reduce the number of byes left, but if not, the RAM
- * is available elsewhere and we don't reduce the number of
- * bytes remaining. */
- if (p == start) {
- if (low_mem_reserved[i].is_aliased) {
- s = min(n, size);
- n -= s;
- p += s;
- } else
- p += n;
- }
- }
-
- return orig_n - n;
-}
-
-/*
- * register_ram - register real RAM
- * @p: Address of memory as seen by devices
- * @alias: If the memory is seen at an additional address by the processor,
- * this will be the address, otherwise it is the same as @p.
- * @n: Number of bytes in this section of memory
- */
-static __init void register_ram(phys_addr_t p, phys_addr_t alias,
- phys_addr_t n)
-{
- /*
- * If some or all of this memory has an alias, break it into the
- * aliased and non-aliased portion.
- */
- if (p != alias) {
- phys_addr_t alias_size;
- phys_addr_t registered;
-
- alias_size = min(n, LOW_RAM_END - alias);
- registered = register_low_ram(alias, alias_size);
- ioremap_add_map(alias, p, n);
- n -= registered;
- p += registered;
- }
-
-#ifdef CONFIG_HIGHMEM
- if (n != 0) {
- add_memory_region(p, n, BOOT_MEM_RAM);
- ioremap_add_map(p, p, n);
- }
-#endif
-}
-
-/**
- * register_address_space - register things in the address space
- * @memsize: Number of bytes of RAM installed
- *
- * Takes the given number of bytes of RAM and registers as many of the regions,
- * or partial regions, as it can. So, the default configuration might have
- * two regions with 256 MiB each. If the memsize passed in on the command line
- * is 384 MiB, it will register the first region with 256 MiB and the second
- * with 128 MiB.
- */
-static __init void register_address_space(phys_addr_t memsize)
-{
- int i;
- phys_addr_t size;
- size_t n;
- struct mem_layout *layout;
- enum family_type family;
-
- /*
- * Register all of the things that aren't available to the kernel as
- * memory.
- */
- register_non_ram();
-
- /* Find the appropriate memory description */
- family = platform_get_family();
-
- for (i = 0; i < ARRAY_SIZE(layout_list); i++) {
- if (layout_list[i].family == family)
- break;
- }
-
- if (i == ARRAY_SIZE(layout_list)) {
- n = ARRAY_SIZE(default_layout);
- layout = default_layout;
- } else {
- n = layout_list[i].n;
- layout = layout_list[i].layout;
- }
-
- for (i = 0; memsize != 0 && i < n; i++) {
- size = min(memsize, layout[i].size);
- register_ram(layout[i].phys, layout[i].alias, size);
- memsize -= size;
- }
-}
-
-void __init prom_meminit(void)
-{
- ptv_memsize = get_memsize();
- register_address_space(ptv_memsize);
-}
-
-void __init prom_free_prom_memory(void)
-{
- unsigned long addr;
- int i;
-
- for (i = 0; i < boot_mem_map.nr_map; i++) {
- if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
- continue;
-
- addr = boot_mem_map.map[i].addr;
- free_init_pages("prom memory",
- addr, addr + boot_mem_map.map[i].size);
- }
-}
diff --git a/arch/mips/powertv/pci/Makefile b/arch/mips/powertv/pci/Makefile
deleted file mode 100644
index 2610a6af5b2c..000000000000
--- a/arch/mips/powertv/pci/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Copyright (C) 2009 Scientific-Atlanta, Inc.
-#
-# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
-
-obj-$(CONFIG_PCI) += fixup-powertv.o
diff --git a/arch/mips/powertv/pci/fixup-powertv.c b/arch/mips/powertv/pci/fixup-powertv.c
deleted file mode 100644
index d7ecbae64a6e..000000000000
--- a/arch/mips/powertv/pci/fixup-powertv.c
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <linux/init.h>
-#include <linux/export.h>
-#include <linux/pci.h>
-#include <asm/mach-powertv/interrupts.h>
-#include "powertv-pci.h"
-
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- return asic_pcie_map_irq(dev, slot, pin);
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
- return 0;
-}
-
-/*
- * asic_pcie_map_irq
- *
- * Parameters:
- * *dev - pointer to a pci_dev structure (not used)
- * slot - slot number (not used)
- * pin - pin number (not used)
- *
- * Return Value:
- * Returns: IRQ number (always the PCI Express IRQ number)
- *
- * Description:
- * asic_pcie_map_irq will return the IRQ number of the PCI Express interrupt.
- *
- */
-int asic_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- return irq_pciexp;
-}
-EXPORT_SYMBOL(asic_pcie_map_irq);
diff --git a/arch/mips/powertv/pci/powertv-pci.h b/arch/mips/powertv/pci/powertv-pci.h
deleted file mode 100644
index 1b5886bbd759..000000000000
--- a/arch/mips/powertv/pci/powertv-pci.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * powertv-pci.c
- *
- * Copyright (C) 2009 Cisco Systems, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-/*
- * Local definitions for the powertv PCI code
- */
-
-#ifndef _POWERTV_PCI_POWERTV_PCI_H_
-#define _POWERTV_PCI_POWERTV_PCI_H_
-extern int asic_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
-extern int asic_pcie_init(void);
-extern int asic_pcie_init(void);
-
-extern int log_level;
-#endif
diff --git a/arch/mips/powertv/powertv-clock.h b/arch/mips/powertv/powertv-clock.h
deleted file mode 100644
index d94c54311485..000000000000
--- a/arch/mips/powertv/powertv-clock.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2009 Cisco Systems, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: David VomLehn
- */
-
-#ifndef _POWERTV_POWERTV_CLOCK_H
-#define _POWERTV_POWERTV_CLOCK_H
-extern int powertv_clockevent_init(void);
-extern void powertv_clocksource_init(void);
-extern unsigned int mips_get_pll_freq(void);
-#endif
diff --git a/arch/mips/powertv/powertv-usb.c b/arch/mips/powertv/powertv-usb.c
deleted file mode 100644
index d845eace58e9..000000000000
--- a/arch/mips/powertv/powertv-usb.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * powertv-usb.c
- *
- * Description: ASIC-specific USB device setup and shutdown
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- * Copyright (C) 2009 Cisco Systems, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: Ken Eppinett
- * David Schleef <ds@schleef.org>
- *
- * NOTE: The bootloader allocates persistent memory at an address which is
- * 16 MiB below the end of the highest address in KSEG0. All fixed
- * address memory reservations must avoid this region.
- */
-
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <asm/mach-powertv/asic.h>
-#include <asm/mach-powertv/interrupts.h>
-
-/* misc_clk_ctl1 values */
-#define MCC1_30MHZ_POWERUP_SELECT (1 << 14)
-#define MCC1_DIV9 (1 << 13)
-#define MCC1_ETHMIPS_POWERUP_SELECT (1 << 11)
-#define MCC1_USB_POWERUP_SELECT (1 << 1)
-#define MCC1_CLOCK108_POWERUP_SELECT (1 << 0)
-
-/* Possible values for clock select */
-#define MCC1_USB_CLOCK_HIGH_Z (0 << 4)
-#define MCC1_USB_CLOCK_48MHZ (1 << 4)
-#define MCC1_USB_CLOCK_24MHZ (2 << 4)
-#define MCC1_USB_CLOCK_6MHZ (3 << 4)
-
-#define MCC1_CONFIG (MCC1_30MHZ_POWERUP_SELECT | \
- MCC1_DIV9 | \
- MCC1_ETHMIPS_POWERUP_SELECT | \
- MCC1_USB_POWERUP_SELECT | \
- MCC1_CLOCK108_POWERUP_SELECT)
-
-/* misc_clk_ctl2 values */
-#define MCC2_GMII_GCLK_TO_PAD (1 << 31)
-#define MCC2_ETHER125_0_CLOCK_SELECT (1 << 29)
-#define MCC2_RMII_0_CLOCK_SELECT (1 << 28)
-#define MCC2_GMII_TX0_CLOCK_SELECT (1 << 27)
-#define MCC2_GMII_RX0_CLOCK_SELECT (1 << 26)
-#define MCC2_ETHER125_1_CLOCK_SELECT (1 << 24)
-#define MCC2_RMII_1_CLOCK_SELECT (1 << 23)
-#define MCC2_GMII_TX1_CLOCK_SELECT (1 << 22)
-#define MCC2_GMII_RX1_CLOCK_SELECT (1 << 21)
-#define MCC2_ETHER125_2_CLOCK_SELECT (1 << 19)
-#define MCC2_RMII_2_CLOCK_SELECT (1 << 18)
-#define MCC2_GMII_TX2_CLOCK_SELECT (1 << 17)
-#define MCC2_GMII_RX2_CLOCK_SELECT (1 << 16)
-
-#define ETHER_CLK_CONFIG (MCC2_GMII_GCLK_TO_PAD | \
- MCC2_ETHER125_0_CLOCK_SELECT | \
- MCC2_RMII_0_CLOCK_SELECT | \
- MCC2_GMII_TX0_CLOCK_SELECT | \
- MCC2_GMII_RX0_CLOCK_SELECT | \
- MCC2_ETHER125_1_CLOCK_SELECT | \
- MCC2_RMII_1_CLOCK_SELECT | \
- MCC2_GMII_TX1_CLOCK_SELECT | \
- MCC2_GMII_RX1_CLOCK_SELECT | \
- MCC2_ETHER125_2_CLOCK_SELECT | \
- MCC2_RMII_2_CLOCK_SELECT | \
- MCC2_GMII_TX2_CLOCK_SELECT | \
- MCC2_GMII_RX2_CLOCK_SELECT)
-
-/* misc_clk_ctl2 definitions for Gaia */
-#define FSX4A_REF_SELECT (1 << 16)
-#define FSX4B_REF_SELECT (1 << 17)
-#define FSX4C_REF_SELECT (1 << 18)
-#define DDR_PLL_REF_SELECT (1 << 19)
-#define MIPS_PLL_REF_SELECT (1 << 20)
-
-/* Definitions for the QAM frequency select register FS432X4A4_QAM_CTL */
-#define QAM_FS_SDIV_SHIFT 29
-#define QAM_FS_MD_SHIFT 24
-#define QAM_FS_MD_MASK 0x1f /* Cut down to 5 bits */
-#define QAM_FS_PE_SHIFT 8
-
-#define QAM_FS_DISABLE_DIVIDE_BY_3 (1 << 5)
-#define QAM_FS_ENABLE_PROGRAM (1 << 4)
-#define QAM_FS_ENABLE_OUTPUT (1 << 3)
-#define QAM_FS_SELECT_TEST_BYPASS (1 << 2)
-#define QAM_FS_DISABLE_DIGITAL_STANDBY (1 << 1)
-#define QAM_FS_CHOOSE_FS (1 << 0)
-
-/* Definitions for fs432x4a_ctl register */
-#define QAM_FS_NSDIV_54MHZ (1 << 2)
-
-/* Definitions for bcm1_usb2_ctl register */
-#define BCM1_USB2_CTL_BISTOK (1 << 11)
-#define BCM1_USB2_CTL_PORT2_SHIFT_JK (1 << 7)
-#define BCM1_USB2_CTL_PORT1_SHIFT_JK (1 << 6)
-#define BCM1_USB2_CTL_PORT2_FAST_EDGE (1 << 5)
-#define BCM1_USB2_CTL_PORT1_FAST_EDGE (1 << 4)
-#define BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH (1 << 1)
-#define BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH (1 << 0)
-
-/* Definitions for crt_spare register */
-#define CRT_SPARE_PORT2_SHIFT_JK (1 << 21)
-#define CRT_SPARE_PORT1_SHIFT_JK (1 << 20)
-#define CRT_SPARE_PORT2_FAST_EDGE (1 << 19)
-#define CRT_SPARE_PORT1_FAST_EDGE (1 << 18)
-#define CRT_SPARE_DIVIDE_BY_9_FROM_432 (1 << 17)
-#define CRT_SPARE_USB_DIVIDE_BY_9 (1 << 16)
-
-/* Definitions for usb2_stbus_obc register */
-#define USB_STBUS_OBC_STORE32_LOAD32 0x3
-
-/* Definitions for usb2_stbus_mess_size register */
-#define USB2_STBUS_MESS_SIZE_2 0x1 /* 2 packets */
-
-/* Definitions for usb2_stbus_chunk_size register */
-#define USB2_STBUS_CHUNK_SIZE_2 0x1 /* 2 packets */
-
-/* Definitions for usb2_strap register */
-#define USB2_STRAP_HFREQ_SELECT 0x1
-
-/*
- * USB Host Resource Definition
- */
-
-static struct resource ehci_resources[] = {
- {
- .parent = &asic_resource,
- .start = 0,
- .end = 0xff,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = irq_usbehci,
- .end = irq_usbehci,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static u64 ehci_dmamask = 0xffffffffULL;
-
-static struct platform_device ehci_device = {
- .name = "powertv-ehci",
- .id = 0,
- .num_resources = 2,
- .resource = ehci_resources,
- .dev = {
- .dma_mask = &ehci_dmamask,
- .coherent_dma_mask = 0xffffffff,
- },
-};
-
-static struct resource ohci_resources[] = {
- {
- .parent = &asic_resource,
- .start = 0,
- .end = 0xff,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = irq_usbohci,
- .end = irq_usbohci,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static u64 ohci_dmamask = 0xffffffffULL;
-
-static struct platform_device ohci_device = {
- .name = "powertv-ohci",
- .id = 0,
- .num_resources = 2,
- .resource = ohci_resources,
- .dev = {
- .dma_mask = &ohci_dmamask,
- .coherent_dma_mask = 0xffffffff,
- },
-};
-
-static unsigned usb_users;
-static DEFINE_SPINLOCK(usb_regs_lock);
-
-/*
- *
- * fs_update - set frequency synthesizer for USB
- * @pe_bits Phase tap setting
- * @md_bits Coarse selector bus for algorithm of phase tap
- * @sdiv_bits Output divider setting
- * @disable_div_by_3 Either QAM_FS_DISABLE_DIVIDE_BY_3 or zero
- * @standby Either QAM_FS_DISABLE_DIGITAL_STANDBY or zero
- *
- * QAM frequency selection code, which affects the frequency at which USB
- * runs. The frequency is calculated as:
- * 2^15 * ndiv * Fin
- * Fout = ------------------------------------------------------------
- * (sdiv * (ipe * (1 + md/32) - (ipe - 2^15)*(1 + (md + 1)/32)))
- * where:
- * Fin 54 MHz
- * ndiv QAM_FS_NSDIV_54MHZ ? 8 : 16
- * sdiv 1 << (sdiv_bits + 1)
- * ipe Same as pe_bits
- * md A five-bit, two's-complement integer (range [-16, 15]), which
- * is the lower 5 bits of md_bits.
- */
-static void fs_update(u32 pe_bits, int md_bits, u32 sdiv_bits,
- u32 disable_div_by_3, u32 standby)
-{
- u32 val;
-
- val = ((sdiv_bits << QAM_FS_SDIV_SHIFT) |
- ((md_bits & QAM_FS_MD_MASK) << QAM_FS_MD_SHIFT) |
- (pe_bits << QAM_FS_PE_SHIFT) |
- QAM_FS_ENABLE_OUTPUT |
- standby |
- disable_div_by_3);
- asic_write(val, fs432x4b4_usb_ctl);
- asic_write(val | QAM_FS_ENABLE_PROGRAM, fs432x4b4_usb_ctl);
- asic_write(val | QAM_FS_ENABLE_PROGRAM | QAM_FS_CHOOSE_FS,
- fs432x4b4_usb_ctl);
-}
-
-/*
- * usb_eye_configure - for optimizing the shape USB eye waveform
- * @set: Bits to set in the register
- * @clear: Bits to clear in the register; each bit with a one will
- * be set in the register, zero bits will not be modified
- */
-static void usb_eye_configure(u32 set, u32 clear)
-{
- u32 old;
-
- old = asic_read(crt_spare);
- old |= set;
- old &= ~clear;
- asic_write(old, crt_spare);
-}
-
-/*
- * platform_configure_usb - usb configuration based on platform type.
- */
-static void platform_configure_usb(void)
-{
- u32 bcm1_usb2_ctl_value;
- enum asic_type asic_type;
- unsigned long flags;
-
- spin_lock_irqsave(&usb_regs_lock, flags);
- usb_users++;
-
- if (usb_users != 1) {
- spin_unlock_irqrestore(&usb_regs_lock, flags);
- return;
- }
-
- asic_type = platform_get_asic();
-
- switch (asic_type) {
- case ASIC_ZEUS:
- fs_update(0x0000, -15, 0x02, 0, 0);
- bcm1_usb2_ctl_value = BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH |
- BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH;
- break;
-
- case ASIC_CRONUS:
- case ASIC_CRONUSLITE:
- usb_eye_configure(0, CRT_SPARE_USB_DIVIDE_BY_9);
- fs_update(0x8000, -14, 0x03, QAM_FS_DISABLE_DIVIDE_BY_3,
- QAM_FS_DISABLE_DIGITAL_STANDBY);
- bcm1_usb2_ctl_value = BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH |
- BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH;
- break;
-
- case ASIC_CALLIOPE:
- fs_update(0x0000, -15, 0x02, QAM_FS_DISABLE_DIVIDE_BY_3,
- QAM_FS_DISABLE_DIGITAL_STANDBY);
-
- switch (platform_get_family()) {
- case FAMILY_1500VZE:
- break;
-
- case FAMILY_1500VZF:
- usb_eye_configure(CRT_SPARE_PORT2_SHIFT_JK |
- CRT_SPARE_PORT1_SHIFT_JK |
- CRT_SPARE_PORT2_FAST_EDGE |
- CRT_SPARE_PORT1_FAST_EDGE, 0);
- break;
-
- default:
- usb_eye_configure(CRT_SPARE_PORT2_SHIFT_JK |
- CRT_SPARE_PORT1_SHIFT_JK, 0);
- break;
- }
-
- bcm1_usb2_ctl_value = BCM1_USB2_CTL_BISTOK |
- BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH |
- BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH;
- break;
-
- case ASIC_GAIA:
- fs_update(0x8000, -14, 0x03, QAM_FS_DISABLE_DIVIDE_BY_3,
- QAM_FS_DISABLE_DIGITAL_STANDBY);
- bcm1_usb2_ctl_value = BCM1_USB2_CTL_BISTOK |
- BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH |
- BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH;
- break;
-
- default:
- pr_err("Unknown ASIC type: %d\n", asic_type);
- bcm1_usb2_ctl_value = 0;
- break;
- }
-
- /* turn on USB power */
- asic_write(0, usb2_strap);
- /* Enable all OHCI interrupts */
- asic_write(bcm1_usb2_ctl_value, usb2_control);
- /* usb2_stbus_obc store32/load32 */
- asic_write(USB_STBUS_OBC_STORE32_LOAD32, usb2_stbus_obc);
- /* usb2_stbus_mess_size 2 packets */
- asic_write(USB2_STBUS_MESS_SIZE_2, usb2_stbus_mess_size);
- /* usb2_stbus_chunk_size 2 packets */
- asic_write(USB2_STBUS_CHUNK_SIZE_2, usb2_stbus_chunk_size);
- spin_unlock_irqrestore(&usb_regs_lock, flags);
-}
-
-static void platform_unconfigure_usb(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&usb_regs_lock, flags);
- usb_users--;
- if (usb_users == 0)
- asic_write(USB2_STRAP_HFREQ_SELECT, usb2_strap);
- spin_unlock_irqrestore(&usb_regs_lock, flags);
-}
-
-/*
- * Set up the USB EHCI interface
- */
-void platform_configure_usb_ehci()
-{
- platform_configure_usb();
-}
-EXPORT_SYMBOL(platform_configure_usb_ehci);
-
-/*
- * Set up the USB OHCI interface
- */
-void platform_configure_usb_ohci()
-{
- platform_configure_usb();
-}
-EXPORT_SYMBOL(platform_configure_usb_ohci);
-
-/*
- * Shut the USB EHCI interface down
- */
-void platform_unconfigure_usb_ehci()
-{
- platform_unconfigure_usb();
-}
-EXPORT_SYMBOL(platform_unconfigure_usb_ehci);
-
-/*
- * Shut the USB OHCI interface down
- */
-void platform_unconfigure_usb_ohci()
-{
- platform_unconfigure_usb();
-}
-EXPORT_SYMBOL(platform_unconfigure_usb_ohci);
-
-/**
- * platform_devices_init - sets up USB device resourse.
- */
-int __init platform_usb_devices_init(struct platform_device **ehci_dev,
- struct platform_device **ohci_dev)
-{
- *ehci_dev = &ehci_device;
- ehci_resources[0].start = asic_reg_phys_addr(ehci_hcapbase);
- ehci_resources[0].end += ehci_resources[0].start;
-
- *ohci_dev = &ohci_device;
- ohci_resources[0].start = asic_reg_phys_addr(ohci_hc_revision);
- ohci_resources[0].end += ohci_resources[0].start;
-
- return 0;
-}
diff --git a/arch/mips/powertv/powertv_setup.c b/arch/mips/powertv/powertv_setup.c
deleted file mode 100644
index 24689bff1039..000000000000
--- a/arch/mips/powertv/powertv_setup.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- * This program is free software; you can distribute 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 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/init.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/screen_info.h>
-#include <linux/notifier.h>
-#include <linux/etherdevice.h>
-#include <linux/if_ether.h>
-#include <linux/ctype.h>
-#include <linux/cpu.h>
-#include <linux/time.h>
-
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/mips-boards/generic.h>
-#include <asm/dma.h>
-#include <asm/asm.h>
-#include <asm/traps.h>
-#include <asm/asm-offsets.h>
-#include "reset.h"
-
-#define VAL(n) STR(n)
-
-/*
- * Macros for loading addresses and storing registers:
- * LONG_L_ Stringified version of LONG_L for use in asm() statement
- * LONG_S_ Stringified version of LONG_S for use in asm() statement
- * PTR_LA_ Stringified version of PTR_LA for use in asm() statement
- * REG_SIZE Number of 8-bit bytes in a full width register
- */
-#define LONG_L_ VAL(LONG_L) " "
-#define LONG_S_ VAL(LONG_S) " "
-#define PTR_LA_ VAL(PTR_LA) " "
-
-#ifdef CONFIG_64BIT
-#warning TODO: 64-bit code needs to be verified
-#define REG_SIZE "8" /* In bytes */
-#endif
-
-#ifdef CONFIG_32BIT
-#define REG_SIZE "4" /* In bytes */
-#endif
-
-static void register_panic_notifier(void);
-static int panic_handler(struct notifier_block *notifier_block,
- unsigned long event, void *cause_string);
-
-const char *get_system_type(void)
-{
- return "PowerTV";
-}
-
-void __init plat_mem_setup(void)
-{
- panic_on_oops = 1;
- register_panic_notifier();
-
-#if 0
- mips_pcibios_init();
-#endif
- mips_reboot_setup();
-}
-
-/*
- * Install a panic notifier for platform-specific diagnostics
- */
-static void register_panic_notifier()
-{
- static struct notifier_block panic_notifier = {
- .notifier_call = panic_handler,
- .next = NULL,
- .priority = INT_MAX
- };
- atomic_notifier_chain_register(&panic_notifier_list, &panic_notifier);
-}
-
-static int panic_handler(struct notifier_block *notifier_block,
- unsigned long event, void *cause_string)
-{
- struct pt_regs my_regs;
-
- /* Save all of the registers */
- {
- unsigned long at, v0, v1; /* Must be on the stack */
-
- /* Start by saving $at and v0 on the stack. We use $at
- * ourselves, but it looks like the compiler may use v0 or v1
- * to load the address of the pt_regs structure. We'll come
- * back later to store the registers in the pt_regs
- * structure. */
- __asm__ __volatile__ (
- ".set noat\n"
- LONG_S_ "$at, %[at]\n"
- LONG_S_ "$2, %[v0]\n"
- LONG_S_ "$3, %[v1]\n"
- :
- [at] "=m" (at),
- [v0] "=m" (v0),
- [v1] "=m" (v1)
- :
- : "at"
- );
-
- __asm__ __volatile__ (
- ".set noat\n"
- "move $at, %[pt_regs]\n"
-
- /* Argument registers */
- LONG_S_ "$4, " VAL(PT_R4) "($at)\n"
- LONG_S_ "$5, " VAL(PT_R5) "($at)\n"
- LONG_S_ "$6, " VAL(PT_R6) "($at)\n"
- LONG_S_ "$7, " VAL(PT_R7) "($at)\n"
-
- /* Temporary regs */
- LONG_S_ "$8, " VAL(PT_R8) "($at)\n"
- LONG_S_ "$9, " VAL(PT_R9) "($at)\n"
- LONG_S_ "$10, " VAL(PT_R10) "($at)\n"
- LONG_S_ "$11, " VAL(PT_R11) "($at)\n"
- LONG_S_ "$12, " VAL(PT_R12) "($at)\n"
- LONG_S_ "$13, " VAL(PT_R13) "($at)\n"
- LONG_S_ "$14, " VAL(PT_R14) "($at)\n"
- LONG_S_ "$15, " VAL(PT_R15) "($at)\n"
-
- /* "Saved" registers */
- LONG_S_ "$16, " VAL(PT_R16) "($at)\n"
- LONG_S_ "$17, " VAL(PT_R17) "($at)\n"
- LONG_S_ "$18, " VAL(PT_R18) "($at)\n"
- LONG_S_ "$19, " VAL(PT_R19) "($at)\n"
- LONG_S_ "$20, " VAL(PT_R20) "($at)\n"
- LONG_S_ "$21, " VAL(PT_R21) "($at)\n"
- LONG_S_ "$22, " VAL(PT_R22) "($at)\n"
- LONG_S_ "$23, " VAL(PT_R23) "($at)\n"
-
- /* Add'l temp regs */
- LONG_S_ "$24, " VAL(PT_R24) "($at)\n"
- LONG_S_ "$25, " VAL(PT_R25) "($at)\n"
-
- /* Kernel temp regs */
- LONG_S_ "$26, " VAL(PT_R26) "($at)\n"
- LONG_S_ "$27, " VAL(PT_R27) "($at)\n"
-
- /* Global pointer, stack pointer, frame pointer and
- * return address */
- LONG_S_ "$gp, " VAL(PT_R28) "($at)\n"
- LONG_S_ "$sp, " VAL(PT_R29) "($at)\n"
- LONG_S_ "$fp, " VAL(PT_R30) "($at)\n"
- LONG_S_ "$ra, " VAL(PT_R31) "($at)\n"
-
- /* Now we can get the $at and v0 registers back and
- * store them */
- LONG_L_ "$8, %[at]\n"
- LONG_S_ "$8, " VAL(PT_R1) "($at)\n"
- LONG_L_ "$8, %[v0]\n"
- LONG_S_ "$8, " VAL(PT_R2) "($at)\n"
- LONG_L_ "$8, %[v1]\n"
- LONG_S_ "$8, " VAL(PT_R3) "($at)\n"
- :
- :
- [at] "m" (at),
- [v0] "m" (v0),
- [v1] "m" (v1),
- [pt_regs] "r" (&my_regs)
- : "at", "t0"
- );
-
- /* Set the current EPC value to be the current location in this
- * function */
- __asm__ __volatile__ (
- ".set noat\n"
- "1:\n"
- PTR_LA_ "$at, 1b\n"
- LONG_S_ "$at, %[cp0_epc]\n"
- :
- [cp0_epc] "=m" (my_regs.cp0_epc)
- :
- : "at"
- );
-
- my_regs.cp0_cause = read_c0_cause();
- my_regs.cp0_status = read_c0_status();
- }
-
- pr_crit("I'm feeling a bit sleepy. hmmmmm... perhaps a nap would... "
- "zzzz... \n");
-
- return NOTIFY_DONE;
-}
-
-/* Information about the RF MAC address, if one was supplied on the
- * command line. */
-static bool have_rfmac;
-static u8 rfmac[ETH_ALEN];
-
-static int rfmac_param(char *p)
-{
- u8 *q;
- bool is_high_nibble;
- int c;
-
- /* Skip a leading "0x", if present */
- if (*p == '0' && *(p+1) == 'x')
- p += 2;
-
- q = rfmac;
- is_high_nibble = true;
-
- for (c = (unsigned char) *p++;
- isxdigit(c) && q - rfmac < ETH_ALEN;
- c = (unsigned char) *p++) {
- int nibble;
-
- nibble = (isdigit(c) ? (c - '0') :
- (isupper(c) ? c - 'A' + 10 : c - 'a' + 10));
-
- if (is_high_nibble)
- *q = nibble << 4;
- else
- *q++ |= nibble;
-
- is_high_nibble = !is_high_nibble;
- }
-
- /* If we parsed all the way to the end of the parameter value and
- * parsed all ETH_ALEN bytes, we have a usable RF MAC address */
- have_rfmac = (c == '\0' && q - rfmac == ETH_ALEN);
-
- return 0;
-}
-
-early_param("rfmac", rfmac_param);
-
-/*
- * Generate an Ethernet MAC address that has a good chance of being unique.
- * @addr: Pointer to six-byte array containing the Ethernet address
- * Generates an Ethernet MAC address that is highly likely to be unique for
- * this particular system on a network with other systems of the same type.
- *
- * The problem we are solving is that, when eth_random_addr() is used to
- * generate MAC addresses at startup, there isn't much entropy for the random
- * number generator to use and the addresses it produces are fairly likely to
- * be the same as those of other identical systems on the same local network.
- * This is true even for relatively small numbers of systems (for the reason
- * why, see the Wikipedia entry for "Birthday problem" at:
- * http://en.wikipedia.org/wiki/Birthday_problem
- *
- * The good news is that we already have a MAC address known to be unique, the
- * RF MAC address. The bad news is that this address is already in use on the
- * RF interface. Worse, the obvious trick, taking the RF MAC address and
- * turning on the locally managed bit, has already been used for other devices.
- * Still, this does give us something to work with.
- *
- * The approach we take is:
- * 1. If we can't get the RF MAC Address, just call eth_random_addr.
- * 2. Use the 24-bit NIC-specific bits of the RF MAC address as the last 24
- * bits of the new address. This is very likely to be unique, except for
- * the current box.
- * 3. To avoid using addresses already on the current box, we set the top
- * six bits of the address with a value different from any currently
- * registered Scientific Atlanta organizationally unique identifyer
- * (OUI). This avoids duplication with any addresses on the system that
- * were generated from valid Scientific Atlanta-registered address by
- * simply flipping the locally managed bit.
- * 4. We aren't generating a multicast address, so we leave the multicast
- * bit off. Since we aren't using a registered address, we have to set
- * the locally managed bit.
- * 5. We then randomly generate the remaining 16-bits. This does two
- * things:
- * a. It allows us to call this function for more than one device
- * in this system
- * b. It ensures that things will probably still work even if
- * some device on the device network has a locally managed
- * address that matches the top six bits from step 2.
- */
-void platform_random_ether_addr(u8 addr[ETH_ALEN])
-{
- const int num_random_bytes = 2;
- const unsigned char non_sciatl_oui_bits = 0xc0u;
- const unsigned char mac_addr_locally_managed = (1 << 1);
-
- if (!have_rfmac) {
- pr_warning("rfmac not available on command line; "
- "generating random MAC address\n");
- eth_random_addr(addr);
- }
-
- else {
- int i;
-
- /* Set the first byte to something that won't match a Scientific
- * Atlanta OUI, is locally managed, and isn't a multicast
- * address */
- addr[0] = non_sciatl_oui_bits | mac_addr_locally_managed;
-
- /* Get some bytes of random address information */
- get_random_bytes(&addr[1], num_random_bytes);
-
- /* Copy over the NIC-specific bits of the RF MAC address */
- for (i = 1 + num_random_bytes; i < ETH_ALEN; i++)
- addr[i] = rfmac[i];
- }
-}
diff --git a/arch/mips/powertv/reset.c b/arch/mips/powertv/reset.c
deleted file mode 100644
index 11c32fbf2784..000000000000
--- a/arch/mips/powertv/reset.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- * This program is free software; you can distribute 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 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/pm.h>
-
-#include <linux/io.h>
-#include <asm/reboot.h> /* Not included by linux/reboot.h */
-
-#include <asm/mach-powertv/asic_regs.h>
-#include "reset.h"
-
-static void mips_machine_restart(char *command)
-{
- writel(0x1, asic_reg_addr(watchdog));
-}
-
-void mips_reboot_setup(void)
-{
- _machine_restart = mips_machine_restart;
-}
diff --git a/arch/mips/powertv/reset.h b/arch/mips/powertv/reset.h
deleted file mode 100644
index 888fd09e2620..000000000000
--- a/arch/mips/powertv/reset.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Definitions from powertv reset.c file
- *
- * Copyright (C) 2009 Cisco Systems, Inc.
- *
- * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: David VomLehn
- */
-
-#ifndef _POWERTV_POWERTV_RESET_H
-#define _POWERTV_POWERTV_RESET_H
-extern void mips_reboot_setup(void);
-#endif
diff --git a/arch/mips/powertv/time.c b/arch/mips/powertv/time.c
deleted file mode 100644
index f38b0d45eca9..000000000000
--- a/arch/mips/powertv/time.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- * This program is free software; you can distribute 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 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.
- *
- * Setting up the clock on the MIPS boards.
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/interrupts.h>
-#include <asm/time.h>
-
-#include "powertv-clock.h"
-
-unsigned int get_c0_compare_int(void)
-{
- return irq_mips_timer;
-}
-
-void __init plat_time_init(void)
-{
- powertv_clocksource_init();
-}
diff --git a/arch/mips/ralink/clk.c b/arch/mips/ralink/clk.c
index bba0cdfd83bc..5d0983d47161 100644
--- a/arch/mips/ralink/clk.c
+++ b/arch/mips/ralink/clk.c
@@ -26,7 +26,7 @@ void ralink_clk_add(const char *dev, unsigned long rate)
struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
if (!clk)
- panic("failed to add clock\n");
+ panic("failed to add clock");
clk->cl.dev_id = dev;
clk->cl.clk = clk;
diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c
index d217509e5300..a3ad56c2372d 100644
--- a/arch/mips/ralink/mt7620.c
+++ b/arch/mips/ralink/mt7620.c
@@ -350,7 +350,7 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
name = "MT7620A";
soc_info->compatible = "ralink,mt7620a-soc";
} else {
- panic("mt7620: unknown SoC, n0:%08x n1:%08x\n", n0, n1);
+ panic("mt7620: unknown SoC, n0:%08x n1:%08x", n0, n1);
}
rev = __raw_readl(sysc + SYSC_REG_CHIP_REV);
diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c
index ce38d11f9da5..15f21ea96121 100644
--- a/arch/mips/ralink/of.c
+++ b/arch/mips/ralink/of.c
@@ -108,7 +108,7 @@ static int __init plat_of_setup(void)
strncpy(of_ids[1].compatible, "palmbus", len);
if (of_platform_populate(NULL, of_ids, NULL, NULL))
- panic("failed to populate DT\n");
+ panic("failed to populate DT");
/* make sure ithat the reset controller is setup early */
ralink_rst_init();
diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c
index ca7ee3a33790..bb82a82da9e7 100644
--- a/arch/mips/ralink/rt305x.c
+++ b/arch/mips/ralink/rt305x.c
@@ -276,7 +276,7 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
name = "RT5350";
soc_info->compatible = "ralink,rt5350-soc";
} else {
- panic("rt305x: unknown SoC, n0:%08x n1:%08x\n", n0, n1);
+ panic("rt305x: unknown SoC, n0:%08x n1:%08x", n0, n1);
}
id = __raw_readl(sysc + SYSC_REG_CHIP_ID);
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index c5d767028306..74742dc6a3da 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -2,3 +2,4 @@
generic-y += clkdev.h
generic-y += exec.h
generic-y += trace_clock.h
+generic-y += preempt.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 195653e851da..78405625e799 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -67,3 +67,4 @@ generic-y += ucontext.h
generic-y += user.h
generic-y += word-at-a-time.h
generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/parisc/configs/generic-32bit_defconfig b/arch/parisc/configs/generic-32bit_defconfig
new file mode 100644
index 000000000000..7f0361490a2f
--- /dev/null
+++ b/arch/parisc/configs/generic-32bit_defconfig
@@ -0,0 +1,340 @@
+CONFIG_LOCALVERSION="-32bit"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_LZO=y
+CONFIG_EXPERT=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_PERF_EVENTS=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PA7100LC=y
+CONFIG_SMP=y
+CONFIG_HZ_100=y
+CONFIG_IOMMU_CCIO=y
+CONFIG_GSC_LASI=y
+CONFIG_GSC_WAX=y
+CONFIG_EISA=y
+CONFIG_PCI=y
+CONFIG_GSC_DINO=y
+CONFIG_PCI_LBA=y
+CONFIG_PCCARD=m
+CONFIG_YENTA=m
+CONFIG_PD6729=m
+CONFIG_I82092=m
+# CONFIG_PDC_CHASSIS is not set
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=m
+CONFIG_LLC2=m
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_1284=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=6144
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_GENERIC=y
+CONFIG_BLK_DEV_NS87415=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_LASI700=y
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_ZALON=y
+CONFIG_SCSI_DH=y
+CONFIG_ATA=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_UEVENT=y
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_DUMMY=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+CONFIG_NET_TULIP=y
+CONFIG_TULIP=y
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_NET_VENDOR_FUJITSU is not set
+# CONFIG_NET_VENDOR_HP is not set
+CONFIG_LASI_82596=y
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_NET_PACKET_ENGINE is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_XIRCOM is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+# CONFIG_WLAN is not set
+CONFIG_INPUT_POLLDEV=y
+CONFIG_KEYBOARD_HIL_OLD=m
+CONFIG_KEYBOARD_HIL=m
+CONFIG_MOUSE_SERIAL=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_LEGACY_PTY_COUNT=64
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=8
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_PRINTER=m
+CONFIG_PPDEV=m
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_HWMON is not set
+CONFIG_AGP=y
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FB_FOREIGN_ENDIAN=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_VOODOO1=m
+CONFIG_DUMMY_CONSOLE_COLUMNS=128
+CONFIG_DUMMY_CONSOLE_ROWS=48
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_SOUND=m
+CONFIG_SND=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_AD1889=m
+# CONFIG_SND_PCMCIA is not set
+CONFIG_SND_HARMONY=m
+CONFIG_HIDRAW=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_KYE=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=m
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_ORTEK=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_UHCI_HCD=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_DMADEVICES=y
+CONFIG_AUXDISPLAY=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V2=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_NFS_FS=m
+# CONFIG_NFS_V2 is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_CIFS=m
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_RT_MUTEX_TESTER=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_LATENCYTOP=y
+CONFIG_LKDTM=m
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_T10DIF=y
+CONFIG_FONTS=y
diff --git a/arch/parisc/configs/generic-64bit_defconfig b/arch/parisc/configs/generic-64bit_defconfig
new file mode 100644
index 000000000000..6952cb58411a
--- /dev/null
+++ b/arch/parisc/configs/generic-64bit_defconfig
@@ -0,0 +1,350 @@
+CONFIG_LOCALVERSION="-64bit"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_BLK_DEV_INTEGRITY=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_PA8X00=y
+CONFIG_MLONGCALLS=y
+CONFIG_64BIT=y
+CONFIG_SMP=y
+# CONFIG_COMPACTION is not set
+CONFIG_HPPB=y
+CONFIG_IOMMU_CCIO=y
+CONFIG_GSC_LASI=y
+CONFIG_GSC_WAX=y
+CONFIG_PCI=y
+CONFIG_PCI_STUB=m
+CONFIG_PCI_IOV=y
+CONFIG_GSC_DINO=y
+CONFIG_PCI_LBA=y
+CONFIG_BINFMT_MISC=m
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=m
+CONFIG_INET_DIAG=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_ADVANCED is not set
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_DCB=y
+CONFIG_AF_RXRPC=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_IDE=y
+CONFIG_IDE_GD=m
+CONFIG_IDE_GD_ATAPI=y
+CONFIG_BLK_DEV_IDECD=m
+CONFIG_BLK_DEV_NS87415=y
+CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_SCSI_ISCSI_ATTRS=y
+CONFIG_SCSI_SRP_ATTRS=y
+CONFIG_ISCSI_BOOT_SYSFS=y
+CONFIG_SCSI_MPT2SAS=y
+CONFIG_SCSI_LASI700=m
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_ZALON=y
+CONFIG_SCSI_QLA_ISCSI=m
+CONFIG_SCSI_DH=y
+CONFIG_ATA=y
+CONFIG_ATA_GENERIC=y
+CONFIG_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_RAID=m
+CONFIG_DM_UEVENT=y
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=y
+CONFIG_FUSION_SAS=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_TUN=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+CONFIG_NET_TULIP=y
+CONFIG_TULIP=y
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+CONFIG_HP100=m
+CONFIG_E1000=y
+CONFIG_LASI_82596=y
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+CONFIG_QLA3XXX=m
+CONFIG_QLCNIC=m
+CONFIG_QLGE=m
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PHYLIB=y
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_BROADCOM_PHY=m
+CONFIG_ICPLUS_PHY=m
+CONFIG_REALTEK_PHY=m
+CONFIG_NATIONAL_PHY=m
+CONFIG_STE10XP=m
+CONFIG_LSI_ET1011C_PHY=m
+CONFIG_MDIO_BITBANG=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_HIL_OLD is not set
+# CONFIG_KEYBOARD_HIL is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_HP_SDC_RTC=m
+CONFIG_SERIO_SERPORT=m
+CONFIG_HP_SDC=m
+CONFIG_HIL_MLC=m
+CONFIG_SERIO_RAW=m
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_NOZOMI=m
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=8
+CONFIG_SERIAL_8250_RUNTIME_UARTS=8
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_JSM=m
+CONFIG_HW_RANDOM_TIMERIOMEM=m
+CONFIG_TCG_TPM=m
+CONFIG_TCG_ATMEL=m
+CONFIG_PTP_1588_CLOCK=m
+CONFIG_SENSORS_I5K_AMB=m
+CONFIG_SENSORS_F71882FG=m
+CONFIG_SENSORS_PC87427=m
+CONFIG_SENSORS_VT1211=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_WATCHDOG=y
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_SSB=m
+CONFIG_SSB_DRIVER_PCICORE=y
+CONFIG_HTC_PASIC3=m
+CONFIG_LPC_SCH=m
+CONFIG_MFD_SM501=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=m
+CONFIG_REGULATOR_USERSPACE_CONSUMER=m
+CONFIG_MEDIA_SUPPORT=m
+CONFIG_AGP=y
+CONFIG_AGP_PARISC=y
+CONFIG_DRM=y
+CONFIG_DRM_RADEON=y
+CONFIG_DRM_RADEON_UMS=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+CONFIG_HID=m
+CONFIG_HIDRAW=y
+CONFIG_HID_DRAGONRISE=m
+CONFIG_DRAGONRISE_FF=y
+CONFIG_HID_KYE=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_TWINHAN=m
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_HID_NTRIG=m
+CONFIG_HID_PANTHERLORD=m
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_HID_GREENASIA=m
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_SMARTJOYPLUS=m
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_HID_TOPSEED=m
+CONFIG_HID_THRUSTMASTER=m
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_HID_ZEROPLUS=m
+CONFIG_ZEROPLUS_FF=y
+CONFIG_USB_HID=m
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DYNAMIC_MINORS=y
+CONFIG_USB_MON=m
+CONFIG_USB_WUSB_CBAF=m
+CONFIG_USB_XHCI_HCD=m
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_R8A66597_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_UIO=y
+CONFIG_UIO_PDRV_GENIRQ=m
+CONFIG_UIO_AEC=m
+CONFIG_UIO_SERCOS3=m
+CONFIG_UIO_PCI_GENERIC=m
+CONFIG_STAGING=y
+# CONFIG_NET_VENDOR_SILICOM is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_XFS_FS=m
+CONFIG_BTRFS_FS=m
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V2=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_ISO9660_FS=y
+CONFIG_UDF_FS=y
+CONFIG_VFAT_FS=m
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_SYSV_FS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V4=m
+CONFIG_NFS_V4_1=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V4=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_UTF8=m
+CONFIG_PRINTK_TIME=y
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=m
+CONFIG_LIBCRC32C=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index ff4c9faed546..a603b9ebe54c 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -4,3 +4,4 @@ generic-y += word-at-a-time.h auxvec.h user.h cputime.h emergency-restart.h \
div64.h irq_regs.h kdebug.h kvm_para.h local64.h local.h param.h \
poll.h xor.h clkdev.h exec.h
generic-y += trace_clock.h
+generic-y += preempt.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 704e6f10ae80..d8f9d2f18a23 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -2,4 +2,5 @@
generic-y += clkdev.h
generic-y += rwsem.h
generic-y += trace_clock.h
+generic-y += preempt.h
generic-y += vtime.h \ No newline at end of file
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 55593ee2d5aa..6ebbe545b7a5 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -189,8 +189,7 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len)
}
/* If PCI-E capable, dump PCI-E cap 10, and the AER */
- cap = pci_find_capability(dev, PCI_CAP_ID_EXP);
- if (cap) {
+ if (pci_is_pcie(dev)) {
n += scnprintf(buf+n, len-n, "pci-e cap10:\n");
printk(KERN_WARNING
"EEH: PCI-E capabilities and status follow:\n");
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 16a7c2326d48..1114d13ac19f 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -292,6 +292,7 @@ out:
return rc;
return count;
}
+static BUS_ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe);
static ssize_t ibmebus_store_remove(struct bus_type *bus,
const char *buf, size_t count)
@@ -317,13 +318,14 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus,
return -ENODEV;
}
}
+static BUS_ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove);
-
-static struct bus_attribute ibmebus_bus_attrs[] = {
- __ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe),
- __ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove),
- __ATTR_NULL
+static struct attribute *ibmbus_bus_attrs[] = {
+ &bus_attr_probe.attr,
+ &bus_attr_remove.attr,
+ NULL,
};
+ATTRIBUTE_GROUPS(ibmbus_bus);
static int ibmebus_bus_bus_match(struct device *dev, struct device_driver *drv)
{
@@ -713,7 +715,7 @@ static struct dev_pm_ops ibmebus_bus_dev_pm_ops = {
struct bus_type ibmebus_bus_type = {
.name = "ibmebus",
.uevent = of_device_uevent_modalias,
- .bus_attrs = ibmebus_bus_attrs,
+ .bus_groups = ibmbus_bus_groups,
.match = ibmebus_bus_bus_match,
.probe = ibmebus_bus_device_probe,
.remove = ibmebus_bus_device_remove,
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 78a350670de3..0126c297fe88 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -997,21 +997,36 @@ static struct device_attribute vio_cmo_dev_attrs[] = {
/* sysfs bus functions and data structures for CMO */
#define viobus_cmo_rd_attr(name) \
-static ssize_t \
-viobus_cmo_##name##_show(struct bus_type *bt, char *buf) \
+static ssize_t cmo_##name##_show(struct bus_type *bt, char *buf) \
{ \
return sprintf(buf, "%lu\n", vio_cmo.name); \
-}
+} \
+static BUS_ATTR_RO(cmo_##name)
#define viobus_cmo_pool_rd_attr(name, var) \
static ssize_t \
-viobus_cmo_##name##_pool_show_##var(struct bus_type *bt, char *buf) \
+cmo_##name##_##var##_show(struct bus_type *bt, char *buf) \
{ \
return sprintf(buf, "%lu\n", vio_cmo.name.var); \
+} \
+static BUS_ATTR_RO(cmo_##name##_##var)
+
+viobus_cmo_rd_attr(entitled);
+viobus_cmo_rd_attr(spare);
+viobus_cmo_rd_attr(min);
+viobus_cmo_rd_attr(desired);
+viobus_cmo_rd_attr(curr);
+viobus_cmo_pool_rd_attr(reserve, size);
+viobus_cmo_pool_rd_attr(excess, size);
+viobus_cmo_pool_rd_attr(excess, free);
+
+static ssize_t cmo_high_show(struct bus_type *bt, char *buf)
+{
+ return sprintf(buf, "%lu\n", vio_cmo.high);
}
-static ssize_t viobus_cmo_high_reset(struct bus_type *bt, const char *buf,
- size_t count)
+static ssize_t cmo_high_store(struct bus_type *bt, const char *buf,
+ size_t count)
{
unsigned long flags;
@@ -1021,35 +1036,26 @@ static ssize_t viobus_cmo_high_reset(struct bus_type *bt, const char *buf,
return count;
}
-
-viobus_cmo_rd_attr(entitled);
-viobus_cmo_pool_rd_attr(reserve, size);
-viobus_cmo_pool_rd_attr(excess, size);
-viobus_cmo_pool_rd_attr(excess, free);
-viobus_cmo_rd_attr(spare);
-viobus_cmo_rd_attr(min);
-viobus_cmo_rd_attr(desired);
-viobus_cmo_rd_attr(curr);
-viobus_cmo_rd_attr(high);
-
-static struct bus_attribute vio_cmo_bus_attrs[] = {
- __ATTR(cmo_entitled, S_IRUGO, viobus_cmo_entitled_show, NULL),
- __ATTR(cmo_reserve_size, S_IRUGO, viobus_cmo_reserve_pool_show_size, NULL),
- __ATTR(cmo_excess_size, S_IRUGO, viobus_cmo_excess_pool_show_size, NULL),
- __ATTR(cmo_excess_free, S_IRUGO, viobus_cmo_excess_pool_show_free, NULL),
- __ATTR(cmo_spare, S_IRUGO, viobus_cmo_spare_show, NULL),
- __ATTR(cmo_min, S_IRUGO, viobus_cmo_min_show, NULL),
- __ATTR(cmo_desired, S_IRUGO, viobus_cmo_desired_show, NULL),
- __ATTR(cmo_curr, S_IRUGO, viobus_cmo_curr_show, NULL),
- __ATTR(cmo_high, S_IWUSR|S_IRUSR|S_IWGRP|S_IRGRP|S_IROTH,
- viobus_cmo_high_show, viobus_cmo_high_reset),
- __ATTR_NULL
+static BUS_ATTR_RW(cmo_high);
+
+static struct attribute *vio_bus_attrs[] = {
+ &bus_attr_cmo_entitled.attr,
+ &bus_attr_cmo_spare.attr,
+ &bus_attr_cmo_min.attr,
+ &bus_attr_cmo_desired.attr,
+ &bus_attr_cmo_curr.attr,
+ &bus_attr_cmo_high.attr,
+ &bus_attr_cmo_reserve_size.attr,
+ &bus_attr_cmo_excess_size.attr,
+ &bus_attr_cmo_excess_free.attr,
+ NULL,
};
+ATTRIBUTE_GROUPS(vio_bus);
static void vio_cmo_sysfs_init(void)
{
vio_bus_type.dev_attrs = vio_cmo_dev_attrs;
- vio_bus_type.bus_attrs = vio_cmo_bus_attrs;
+ vio_bus_type.bus_groups = vio_bus_groups;
}
#else /* CONFIG_PPC_SMLPAR */
int vio_cmo_entitlement_update(size_t new_entitlement) { return 0; }
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index ccfb50ddfe38..92e7258478d8 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -45,7 +45,7 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev)
u8 hdr_type;
/* if we aren't a PCIe don't bother */
- if (!pci_find_capability(dev, PCI_CAP_ID_EXP))
+ if (!pci_is_pcie(dev))
return;
/* if we aren't in host mode don't bother */
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index dcc6ac2d8026..71a7f09df6f2 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -98,6 +98,7 @@ config S390
select CLONE_BACKWARDS2
select GENERIC_CLOCKEVENTS
select GENERIC_CPU_DEVICES if !SMP
+ select GENERIC_FIND_FIRST_BIT
select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL_OLD
select HAVE_ALIGNED_STRUCT_PAGE if SLUB
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index a7d68a467ce8..ecc9d4f73cc6 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -35,13 +35,13 @@ endif
export LD_BFD
-cflags-$(CONFIG_MARCH_G5) += $(call cc-option,-march=g5)
-cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900)
-cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990)
-cflags-$(CONFIG_MARCH_Z9_109) += $(call cc-option,-march=z9-109)
-cflags-$(CONFIG_MARCH_Z10) += $(call cc-option,-march=z10)
-cflags-$(CONFIG_MARCH_Z196) += $(call cc-option,-march=z196)
-cflags-$(CONFIG_MARCH_ZEC12) += $(call cc-option,-march=zEC12)
+cflags-$(CONFIG_MARCH_G5) += -march=g5
+cflags-$(CONFIG_MARCH_Z900) += -march=z900
+cflags-$(CONFIG_MARCH_Z990) += -march=z990
+cflags-$(CONFIG_MARCH_Z9_109) += -march=z9-109
+cflags-$(CONFIG_MARCH_Z10) += -march=z10
+cflags-$(CONFIG_MARCH_Z196) += -march=z196
+cflags-$(CONFIG_MARCH_ZEC12) += -march=zEC12
#KBUILD_IMAGE is necessary for make rpm
KBUILD_IMAGE :=arch/s390/boot/image
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index f313f9cbcf44..7a5288f3479a 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -2,3 +2,4 @@
generic-y += clkdev.h
generic-y += trace_clock.h
+generic-y += preempt.h
diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h
index c797832daa5f..a62ed2d6b17a 100644
--- a/arch/s390/include/asm/atomic.h
+++ b/arch/s390/include/asm/atomic.h
@@ -19,21 +19,50 @@
#define ATOMIC_INIT(i) { (i) }
-#define __CS_LOOP(ptr, op_val, op_string) ({ \
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+
+#define __ATOMIC_OR "lao"
+#define __ATOMIC_AND "lan"
+#define __ATOMIC_ADD "laa"
+
+#define __ATOMIC_LOOP(ptr, op_val, op_string) \
+({ \
+ int old_val; \
+ \
+ typecheck(atomic_t *, ptr); \
+ asm volatile( \
+ op_string " %0,%2,%1\n" \
+ : "=d" (old_val), "+Q" ((ptr)->counter) \
+ : "d" (op_val) \
+ : "cc", "memory"); \
+ old_val; \
+})
+
+#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */
+
+#define __ATOMIC_OR "or"
+#define __ATOMIC_AND "nr"
+#define __ATOMIC_ADD "ar"
+
+#define __ATOMIC_LOOP(ptr, op_val, op_string) \
+({ \
int old_val, new_val; \
+ \
+ typecheck(atomic_t *, ptr); \
asm volatile( \
" l %0,%2\n" \
"0: lr %1,%0\n" \
op_string " %1,%3\n" \
" cs %0,%1,%2\n" \
" jl 0b" \
- : "=&d" (old_val), "=&d" (new_val), \
- "=Q" (((atomic_t *)(ptr))->counter) \
- : "d" (op_val), "Q" (((atomic_t *)(ptr))->counter) \
+ : "=&d" (old_val), "=&d" (new_val), "+Q" ((ptr)->counter)\
+ : "d" (op_val) \
: "cc", "memory"); \
- new_val; \
+ old_val; \
})
+#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */
+
static inline int atomic_read(const atomic_t *v)
{
int c;
@@ -53,32 +82,45 @@ static inline void atomic_set(atomic_t *v, int i)
static inline int atomic_add_return(int i, atomic_t *v)
{
- return __CS_LOOP(v, i, "ar");
+ return __ATOMIC_LOOP(v, i, __ATOMIC_ADD) + i;
}
-#define atomic_add(_i, _v) atomic_add_return(_i, _v)
-#define atomic_add_negative(_i, _v) (atomic_add_return(_i, _v) < 0)
-#define atomic_inc(_v) atomic_add_return(1, _v)
-#define atomic_inc_return(_v) atomic_add_return(1, _v)
-#define atomic_inc_and_test(_v) (atomic_add_return(1, _v) == 0)
-static inline int atomic_sub_return(int i, atomic_t *v)
+static inline void atomic_add(int i, atomic_t *v)
{
- return __CS_LOOP(v, i, "sr");
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+ if (__builtin_constant_p(i) && (i > -129) && (i < 128)) {
+ asm volatile(
+ "asi %0,%1\n"
+ : "+Q" (v->counter)
+ : "i" (i)
+ : "cc", "memory");
+ } else {
+ atomic_add_return(i, v);
+ }
+#else
+ atomic_add_return(i, v);
+#endif
}
-#define atomic_sub(_i, _v) atomic_sub_return(_i, _v)
+
+#define atomic_add_negative(_i, _v) (atomic_add_return(_i, _v) < 0)
+#define atomic_inc(_v) atomic_add(1, _v)
+#define atomic_inc_return(_v) atomic_add_return(1, _v)
+#define atomic_inc_and_test(_v) (atomic_add_return(1, _v) == 0)
+#define atomic_sub(_i, _v) atomic_add(-(int)_i, _v)
+#define atomic_sub_return(_i, _v) atomic_add_return(-(int)(_i), _v)
#define atomic_sub_and_test(_i, _v) (atomic_sub_return(_i, _v) == 0)
-#define atomic_dec(_v) atomic_sub_return(1, _v)
+#define atomic_dec(_v) atomic_sub(1, _v)
#define atomic_dec_return(_v) atomic_sub_return(1, _v)
#define atomic_dec_and_test(_v) (atomic_sub_return(1, _v) == 0)
static inline void atomic_clear_mask(unsigned long mask, atomic_t *v)
{
- __CS_LOOP(v, ~mask, "nr");
+ __ATOMIC_LOOP(v, ~mask, __ATOMIC_AND);
}
static inline void atomic_set_mask(unsigned long mask, atomic_t *v)
{
- __CS_LOOP(v, mask, "or");
+ __ATOMIC_LOOP(v, mask, __ATOMIC_OR);
}
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
@@ -87,8 +129,8 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
{
asm volatile(
" cs %0,%2,%1"
- : "+d" (old), "=Q" (v->counter)
- : "d" (new), "Q" (v->counter)
+ : "+d" (old), "+Q" (v->counter)
+ : "d" (new)
: "cc", "memory");
return old;
}
@@ -109,27 +151,56 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u)
}
-#undef __CS_LOOP
+#undef __ATOMIC_LOOP
#define ATOMIC64_INIT(i) { (i) }
#ifdef CONFIG_64BIT
-#define __CSG_LOOP(ptr, op_val, op_string) ({ \
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+
+#define __ATOMIC64_OR "laog"
+#define __ATOMIC64_AND "lang"
+#define __ATOMIC64_ADD "laag"
+
+#define __ATOMIC64_LOOP(ptr, op_val, op_string) \
+({ \
+ long long old_val; \
+ \
+ typecheck(atomic64_t *, ptr); \
+ asm volatile( \
+ op_string " %0,%2,%1\n" \
+ : "=d" (old_val), "+Q" ((ptr)->counter) \
+ : "d" (op_val) \
+ : "cc", "memory"); \
+ old_val; \
+})
+
+#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */
+
+#define __ATOMIC64_OR "ogr"
+#define __ATOMIC64_AND "ngr"
+#define __ATOMIC64_ADD "agr"
+
+#define __ATOMIC64_LOOP(ptr, op_val, op_string) \
+({ \
long long old_val, new_val; \
+ \
+ typecheck(atomic64_t *, ptr); \
asm volatile( \
" lg %0,%2\n" \
"0: lgr %1,%0\n" \
op_string " %1,%3\n" \
" csg %0,%1,%2\n" \
" jl 0b" \
- : "=&d" (old_val), "=&d" (new_val), \
- "=Q" (((atomic_t *)(ptr))->counter) \
- : "d" (op_val), "Q" (((atomic_t *)(ptr))->counter) \
+ : "=&d" (old_val), "=&d" (new_val), "+Q" ((ptr)->counter)\
+ : "d" (op_val) \
: "cc", "memory"); \
- new_val; \
+ old_val; \
})
+#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */
+
static inline long long atomic64_read(const atomic64_t *v)
{
long long c;
@@ -149,22 +220,17 @@ static inline void atomic64_set(atomic64_t *v, long long i)
static inline long long atomic64_add_return(long long i, atomic64_t *v)
{
- return __CSG_LOOP(v, i, "agr");
-}
-
-static inline long long atomic64_sub_return(long long i, atomic64_t *v)
-{
- return __CSG_LOOP(v, i, "sgr");
+ return __ATOMIC64_LOOP(v, i, __ATOMIC64_ADD) + i;
}
static inline void atomic64_clear_mask(unsigned long mask, atomic64_t *v)
{
- __CSG_LOOP(v, ~mask, "ngr");
+ __ATOMIC64_LOOP(v, ~mask, __ATOMIC64_AND);
}
static inline void atomic64_set_mask(unsigned long mask, atomic64_t *v)
{
- __CSG_LOOP(v, mask, "ogr");
+ __ATOMIC64_LOOP(v, mask, __ATOMIC64_OR);
}
#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
@@ -174,13 +240,13 @@ static inline long long atomic64_cmpxchg(atomic64_t *v,
{
asm volatile(
" csg %0,%2,%1"
- : "+d" (old), "=Q" (v->counter)
- : "d" (new), "Q" (v->counter)
+ : "+d" (old), "+Q" (v->counter)
+ : "d" (new)
: "cc", "memory");
return old;
}
-#undef __CSG_LOOP
+#undef __ATOMIC64_LOOP
#else /* CONFIG_64BIT */
@@ -216,8 +282,8 @@ static inline long long atomic64_xchg(atomic64_t *v, long long new)
" lm %0,%N0,%1\n"
"0: cds %0,%2,%1\n"
" jl 0b\n"
- : "=&d" (rp_old), "=Q" (v->counter)
- : "d" (rp_new), "Q" (v->counter)
+ : "=&d" (rp_old), "+Q" (v->counter)
+ : "d" (rp_new)
: "cc");
return rp_old.pair;
}
@@ -230,8 +296,8 @@ static inline long long atomic64_cmpxchg(atomic64_t *v,
asm volatile(
" cds %0,%2,%1"
- : "+&d" (rp_old), "=Q" (v->counter)
- : "d" (rp_new), "Q" (v->counter)
+ : "+&d" (rp_old), "+Q" (v->counter)
+ : "d" (rp_new)
: "cc");
return rp_old.pair;
}
@@ -248,17 +314,6 @@ static inline long long atomic64_add_return(long long i, atomic64_t *v)
return new;
}
-static inline long long atomic64_sub_return(long long i, atomic64_t *v)
-{
- long long old, new;
-
- do {
- old = atomic64_read(v);
- new = old - i;
- } while (atomic64_cmpxchg(v, old, new) != old);
- return new;
-}
-
static inline void atomic64_set_mask(unsigned long long mask, atomic64_t *v)
{
long long old, new;
@@ -281,7 +336,24 @@ static inline void atomic64_clear_mask(unsigned long long mask, atomic64_t *v)
#endif /* CONFIG_64BIT */
-static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u)
+static inline void atomic64_add(long long i, atomic64_t *v)
+{
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+ if (__builtin_constant_p(i) && (i > -129) && (i < 128)) {
+ asm volatile(
+ "agsi %0,%1\n"
+ : "+Q" (v->counter)
+ : "i" (i)
+ : "cc", "memory");
+ } else {
+ atomic64_add_return(i, v);
+ }
+#else
+ atomic64_add_return(i, v);
+#endif
+}
+
+static inline int atomic64_add_unless(atomic64_t *v, long long i, long long u)
{
long long c, old;
@@ -289,7 +361,7 @@ static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u)
for (;;) {
if (unlikely(c == u))
break;
- old = atomic64_cmpxchg(v, c, c + a);
+ old = atomic64_cmpxchg(v, c, c + i);
if (likely(old == c))
break;
c = old;
@@ -314,14 +386,14 @@ static inline long long atomic64_dec_if_positive(atomic64_t *v)
return dec;
}
-#define atomic64_add(_i, _v) atomic64_add_return(_i, _v)
#define atomic64_add_negative(_i, _v) (atomic64_add_return(_i, _v) < 0)
-#define atomic64_inc(_v) atomic64_add_return(1, _v)
+#define atomic64_inc(_v) atomic64_add(1, _v)
#define atomic64_inc_return(_v) atomic64_add_return(1, _v)
#define atomic64_inc_and_test(_v) (atomic64_add_return(1, _v) == 0)
-#define atomic64_sub(_i, _v) atomic64_sub_return(_i, _v)
+#define atomic64_sub_return(_i, _v) atomic64_add_return(-(long long)(_i), _v)
+#define atomic64_sub(_i, _v) atomic64_add(-(long long)_i, _v)
#define atomic64_sub_and_test(_i, _v) (atomic64_sub_return(_i, _v) == 0)
-#define atomic64_dec(_v) atomic64_sub_return(1, _v)
+#define atomic64_dec(_v) atomic64_sub(1, _v)
#define atomic64_dec_return(_v) atomic64_sub_return(1, _v)
#define atomic64_dec_and_test(_v) (atomic64_sub_return(1, _v) == 0)
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index 10135a38673c..6e6ad0680829 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/arch/s390/include/asm/bitops.h
@@ -1,10 +1,40 @@
/*
- * S390 version
- * Copyright IBM Corp. 1999
- * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ * Copyright IBM Corp. 1999,2013
*
- * Derived from "include/asm-i386/bitops.h"
- * Copyright (C) 1992, Linus Torvalds
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
+ *
+ * The description below was taken in large parts from the powerpc
+ * bitops header file:
+ * Within a word, bits are numbered LSB first. Lot's of places make
+ * this assumption by directly testing bits with (val & (1<<nr)).
+ * This can cause confusion for large (> 1 word) bitmaps on a
+ * big-endian system because, unlike little endian, the number of each
+ * bit depends on the word size.
+ *
+ * The bitop functions are defined to work on unsigned longs, so for an
+ * s390x system the bits end up numbered:
+ * |63..............0|127............64|191...........128|255...........196|
+ * and on s390:
+ * |31.....0|63....31|95....64|127...96|159..128|191..160|223..192|255..224|
+ *
+ * There are a few little-endian macros used mostly for filesystem
+ * bitmaps, these work on similar bit arrays layouts, but
+ * byte-oriented:
+ * |7...0|15...8|23...16|31...24|39...32|47...40|55...48|63...56|
+ *
+ * The main difference is that bit 3-5 (64b) or 3-4 (32b) in the bit
+ * number field needs to be reversed compared to the big-endian bit
+ * fields. This can be achieved by XOR with 0x38 (64b) or 0x18 (32b).
+ *
+ * We also have special functions which work with an MSB0 encoding:
+ * on an s390x system the bits are numbered:
+ * |0..............63|64............127|128...........191|192...........255|
+ * and on s390:
+ * |0.....31|31....63|64....95|96...127|128..159|160..191|192..223|224..255|
+ *
+ * The main difference is that bit 0-63 (64b) or 0-31 (32b) in the bit
+ * number field needs to be reversed compared to the LSB0 encoded bit
+ * fields. This can be achieved by XOR with 0x3f (64b) or 0x1f (32b).
*
*/
@@ -15,556 +45,348 @@
#error only <linux/bitops.h> can be included directly
#endif
+#include <linux/typecheck.h>
#include <linux/compiler.h>
-/*
- * 32 bit bitops format:
- * bit 0 is the LSB of *addr; bit 31 is the MSB of *addr;
- * bit 32 is the LSB of *(addr+4). That combined with the
- * big endian byte order on S390 give the following bit
- * order in memory:
- * 1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10 \
- * 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
- * after that follows the next long with bit numbers
- * 3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30
- * 2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20
- * The reason for this bit ordering is the fact that
- * in the architecture independent code bits operations
- * of the form "flags |= (1 << bitnr)" are used INTERMIXED
- * with operation of the form "set_bit(bitnr, flags)".
- *
- * 64 bit bitops format:
- * bit 0 is the LSB of *addr; bit 63 is the MSB of *addr;
- * bit 64 is the LSB of *(addr+8). That combined with the
- * big endian byte order on S390 give the following bit
- * order in memory:
- * 3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30
- * 2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20
- * 1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10
- * 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
- * after that follows the next long with bit numbers
- * 7f 7e 7d 7c 7b 7a 79 78 77 76 75 74 73 72 71 70
- * 6f 6e 6d 6c 6b 6a 69 68 67 66 65 64 63 62 61 60
- * 5f 5e 5d 5c 5b 5a 59 58 57 56 55 54 53 52 51 50
- * 4f 4e 4d 4c 4b 4a 49 48 47 46 45 44 43 42 41 40
- * The reason for this bit ordering is the fact that
- * in the architecture independent code bits operations
- * of the form "flags |= (1 << bitnr)" are used INTERMIXED
- * with operation of the form "set_bit(bitnr, flags)".
- */
-
-/* bitmap tables from arch/s390/kernel/bitmap.c */
-extern const char _oi_bitmap[];
-extern const char _ni_bitmap[];
-extern const char _zb_findmap[];
-extern const char _sb_findmap[];
-
#ifndef CONFIG_64BIT
#define __BITOPS_OR "or"
#define __BITOPS_AND "nr"
#define __BITOPS_XOR "xr"
-#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string) \
+#define __BITOPS_LOOP(__addr, __val, __op_string) \
+({ \
+ unsigned long __old, __new; \
+ \
+ typecheck(unsigned long *, (__addr)); \
asm volatile( \
" l %0,%2\n" \
"0: lr %1,%0\n" \
__op_string " %1,%3\n" \
" cs %0,%1,%2\n" \
" jl 0b" \
- : "=&d" (__old), "=&d" (__new), \
- "=Q" (*(unsigned long *) __addr) \
- : "d" (__val), "Q" (*(unsigned long *) __addr) \
- : "cc");
+ : "=&d" (__old), "=&d" (__new), "+Q" (*(__addr))\
+ : "d" (__val) \
+ : "cc"); \
+ __old; \
+})
#else /* CONFIG_64BIT */
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+
+#define __BITOPS_OR "laog"
+#define __BITOPS_AND "lang"
+#define __BITOPS_XOR "laxg"
+
+#define __BITOPS_LOOP(__addr, __val, __op_string) \
+({ \
+ unsigned long __old; \
+ \
+ typecheck(unsigned long *, (__addr)); \
+ asm volatile( \
+ __op_string " %0,%2,%1\n" \
+ : "=d" (__old), "+Q" (*(__addr)) \
+ : "d" (__val) \
+ : "cc"); \
+ __old; \
+})
+
+#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */
+
#define __BITOPS_OR "ogr"
#define __BITOPS_AND "ngr"
#define __BITOPS_XOR "xgr"
-#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string) \
+#define __BITOPS_LOOP(__addr, __val, __op_string) \
+({ \
+ unsigned long __old, __new; \
+ \
+ typecheck(unsigned long *, (__addr)); \
asm volatile( \
" lg %0,%2\n" \
"0: lgr %1,%0\n" \
__op_string " %1,%3\n" \
" csg %0,%1,%2\n" \
" jl 0b" \
- : "=&d" (__old), "=&d" (__new), \
- "=Q" (*(unsigned long *) __addr) \
- : "d" (__val), "Q" (*(unsigned long *) __addr) \
- : "cc");
+ : "=&d" (__old), "=&d" (__new), "+Q" (*(__addr))\
+ : "d" (__val) \
+ : "cc"); \
+ __old; \
+})
+
+#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */
#endif /* CONFIG_64BIT */
#define __BITOPS_WORDS(bits) (((bits) + BITS_PER_LONG - 1) / BITS_PER_LONG)
-#ifdef CONFIG_SMP
-/*
- * SMP safe set_bit routine based on compare and swap (CS)
- */
-static inline void set_bit_cs(unsigned long nr, volatile unsigned long *ptr)
+static inline unsigned long *
+__bitops_word(unsigned long nr, volatile unsigned long *ptr)
+{
+ unsigned long addr;
+
+ addr = (unsigned long)ptr + ((nr ^ (nr & (BITS_PER_LONG - 1))) >> 3);
+ return (unsigned long *)addr;
+}
+
+static inline unsigned char *
+__bitops_byte(unsigned long nr, volatile unsigned long *ptr)
{
- unsigned long addr, old, new, mask;
+ return ((unsigned char *)ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
+}
+
+static inline void set_bit(unsigned long nr, volatile unsigned long *ptr)
+{
+ unsigned long *addr = __bitops_word(nr, ptr);
+ unsigned long mask;
- addr = (unsigned long) ptr;
- /* calculate address for CS */
- addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
- /* make OR mask */
+#ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES
+ if (__builtin_constant_p(nr)) {
+ unsigned char *caddr = __bitops_byte(nr, ptr);
+
+ asm volatile(
+ "oi %0,%b1\n"
+ : "+Q" (*caddr)
+ : "i" (1 << (nr & 7))
+ : "cc");
+ return;
+ }
+#endif
mask = 1UL << (nr & (BITS_PER_LONG - 1));
- /* Do the atomic update. */
- __BITOPS_LOOP(old, new, addr, mask, __BITOPS_OR);
+ __BITOPS_LOOP(addr, mask, __BITOPS_OR);
}
-/*
- * SMP safe clear_bit routine based on compare and swap (CS)
- */
-static inline void clear_bit_cs(unsigned long nr, volatile unsigned long *ptr)
+static inline void clear_bit(unsigned long nr, volatile unsigned long *ptr)
{
- unsigned long addr, old, new, mask;
+ unsigned long *addr = __bitops_word(nr, ptr);
+ unsigned long mask;
+
+#ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES
+ if (__builtin_constant_p(nr)) {
+ unsigned char *caddr = __bitops_byte(nr, ptr);
- addr = (unsigned long) ptr;
- /* calculate address for CS */
- addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
- /* make AND mask */
+ asm volatile(
+ "ni %0,%b1\n"
+ : "+Q" (*caddr)
+ : "i" (~(1 << (nr & 7)))
+ : "cc");
+ return;
+ }
+#endif
mask = ~(1UL << (nr & (BITS_PER_LONG - 1)));
- /* Do the atomic update. */
- __BITOPS_LOOP(old, new, addr, mask, __BITOPS_AND);
+ __BITOPS_LOOP(addr, mask, __BITOPS_AND);
}
-/*
- * SMP safe change_bit routine based on compare and swap (CS)
- */
-static inline void change_bit_cs(unsigned long nr, volatile unsigned long *ptr)
+static inline void change_bit(unsigned long nr, volatile unsigned long *ptr)
{
- unsigned long addr, old, new, mask;
+ unsigned long *addr = __bitops_word(nr, ptr);
+ unsigned long mask;
+
+#ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES
+ if (__builtin_constant_p(nr)) {
+ unsigned char *caddr = __bitops_byte(nr, ptr);
- addr = (unsigned long) ptr;
- /* calculate address for CS */
- addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
- /* make XOR mask */
+ asm volatile(
+ "xi %0,%b1\n"
+ : "+Q" (*caddr)
+ : "i" (1 << (nr & 7))
+ : "cc");
+ return;
+ }
+#endif
mask = 1UL << (nr & (BITS_PER_LONG - 1));
- /* Do the atomic update. */
- __BITOPS_LOOP(old, new, addr, mask, __BITOPS_XOR);
+ __BITOPS_LOOP(addr, mask, __BITOPS_XOR);
}
-/*
- * SMP safe test_and_set_bit routine based on compare and swap (CS)
- */
static inline int
-test_and_set_bit_cs(unsigned long nr, volatile unsigned long *ptr)
+test_and_set_bit(unsigned long nr, volatile unsigned long *ptr)
{
- unsigned long addr, old, new, mask;
+ unsigned long *addr = __bitops_word(nr, ptr);
+ unsigned long old, mask;
- addr = (unsigned long) ptr;
- /* calculate address for CS */
- addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
- /* make OR/test mask */
mask = 1UL << (nr & (BITS_PER_LONG - 1));
- /* Do the atomic update. */
- __BITOPS_LOOP(old, new, addr, mask, __BITOPS_OR);
+ old = __BITOPS_LOOP(addr, mask, __BITOPS_OR);
barrier();
return (old & mask) != 0;
}
-/*
- * SMP safe test_and_clear_bit routine based on compare and swap (CS)
- */
static inline int
-test_and_clear_bit_cs(unsigned long nr, volatile unsigned long *ptr)
+test_and_clear_bit(unsigned long nr, volatile unsigned long *ptr)
{
- unsigned long addr, old, new, mask;
+ unsigned long *addr = __bitops_word(nr, ptr);
+ unsigned long old, mask;
- addr = (unsigned long) ptr;
- /* calculate address for CS */
- addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
- /* make AND/test mask */
mask = ~(1UL << (nr & (BITS_PER_LONG - 1)));
- /* Do the atomic update. */
- __BITOPS_LOOP(old, new, addr, mask, __BITOPS_AND);
+ old = __BITOPS_LOOP(addr, mask, __BITOPS_AND);
barrier();
- return (old ^ new) != 0;
+ return (old & ~mask) != 0;
}
-/*
- * SMP safe test_and_change_bit routine based on compare and swap (CS)
- */
static inline int
-test_and_change_bit_cs(unsigned long nr, volatile unsigned long *ptr)
+test_and_change_bit(unsigned long nr, volatile unsigned long *ptr)
{
- unsigned long addr, old, new, mask;
+ unsigned long *addr = __bitops_word(nr, ptr);
+ unsigned long old, mask;
- addr = (unsigned long) ptr;
- /* calculate address for CS */
- addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
- /* make XOR/test mask */
mask = 1UL << (nr & (BITS_PER_LONG - 1));
- /* Do the atomic update. */
- __BITOPS_LOOP(old, new, addr, mask, __BITOPS_XOR);
+ old = __BITOPS_LOOP(addr, mask, __BITOPS_XOR);
barrier();
return (old & mask) != 0;
}
-#endif /* CONFIG_SMP */
-/*
- * fast, non-SMP set_bit routine
- */
static inline void __set_bit(unsigned long nr, volatile unsigned long *ptr)
{
- unsigned long addr;
-
- addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
- asm volatile(
- " oc %O0(1,%R0),%1"
- : "+Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7]) : "cc");
-}
-
-static inline void
-__constant_set_bit(const unsigned long nr, volatile unsigned long *ptr)
-{
- unsigned long addr;
+ unsigned char *addr = __bitops_byte(nr, ptr);
- addr = ((unsigned long) ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
- *(unsigned char *) addr |= 1 << (nr & 7);
+ *addr |= 1 << (nr & 7);
}
-#define set_bit_simple(nr,addr) \
-(__builtin_constant_p((nr)) ? \
- __constant_set_bit((nr),(addr)) : \
- __set_bit((nr),(addr)) )
-
-/*
- * fast, non-SMP clear_bit routine
- */
static inline void
__clear_bit(unsigned long nr, volatile unsigned long *ptr)
{
- unsigned long addr;
-
- addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
- asm volatile(
- " nc %O0(1,%R0),%1"
- : "+Q" (*(char *) addr) : "Q" (_ni_bitmap[nr & 7]) : "cc");
-}
-
-static inline void
-__constant_clear_bit(const unsigned long nr, volatile unsigned long *ptr)
-{
- unsigned long addr;
+ unsigned char *addr = __bitops_byte(nr, ptr);
- addr = ((unsigned long) ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
- *(unsigned char *) addr &= ~(1 << (nr & 7));
+ *addr &= ~(1 << (nr & 7));
}
-#define clear_bit_simple(nr,addr) \
-(__builtin_constant_p((nr)) ? \
- __constant_clear_bit((nr),(addr)) : \
- __clear_bit((nr),(addr)) )
-
-/*
- * fast, non-SMP change_bit routine
- */
static inline void __change_bit(unsigned long nr, volatile unsigned long *ptr)
{
- unsigned long addr;
-
- addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
- asm volatile(
- " xc %O0(1,%R0),%1"
- : "+Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7]) : "cc");
-}
-
-static inline void
-__constant_change_bit(const unsigned long nr, volatile unsigned long *ptr)
-{
- unsigned long addr;
+ unsigned char *addr = __bitops_byte(nr, ptr);
- addr = ((unsigned long) ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
- *(unsigned char *) addr ^= 1 << (nr & 7);
+ *addr ^= 1 << (nr & 7);
}
-#define change_bit_simple(nr,addr) \
-(__builtin_constant_p((nr)) ? \
- __constant_change_bit((nr),(addr)) : \
- __change_bit((nr),(addr)) )
-
-/*
- * fast, non-SMP test_and_set_bit routine
- */
static inline int
-test_and_set_bit_simple(unsigned long nr, volatile unsigned long *ptr)
+__test_and_set_bit(unsigned long nr, volatile unsigned long *ptr)
{
- unsigned long addr;
+ unsigned char *addr = __bitops_byte(nr, ptr);
unsigned char ch;
- addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
- ch = *(unsigned char *) addr;
- asm volatile(
- " oc %O0(1,%R0),%1"
- : "+Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7])
- : "cc", "memory");
+ ch = *addr;
+ *addr |= 1 << (nr & 7);
return (ch >> (nr & 7)) & 1;
}
-#define __test_and_set_bit(X,Y) test_and_set_bit_simple(X,Y)
-/*
- * fast, non-SMP test_and_clear_bit routine
- */
static inline int
-test_and_clear_bit_simple(unsigned long nr, volatile unsigned long *ptr)
+__test_and_clear_bit(unsigned long nr, volatile unsigned long *ptr)
{
- unsigned long addr;
+ unsigned char *addr = __bitops_byte(nr, ptr);
unsigned char ch;
- addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
- ch = *(unsigned char *) addr;
- asm volatile(
- " nc %O0(1,%R0),%1"
- : "+Q" (*(char *) addr) : "Q" (_ni_bitmap[nr & 7])
- : "cc", "memory");
+ ch = *addr;
+ *addr &= ~(1 << (nr & 7));
return (ch >> (nr & 7)) & 1;
}
-#define __test_and_clear_bit(X,Y) test_and_clear_bit_simple(X,Y)
-/*
- * fast, non-SMP test_and_change_bit routine
- */
static inline int
-test_and_change_bit_simple(unsigned long nr, volatile unsigned long *ptr)
+__test_and_change_bit(unsigned long nr, volatile unsigned long *ptr)
{
- unsigned long addr;
+ unsigned char *addr = __bitops_byte(nr, ptr);
unsigned char ch;
- addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
- ch = *(unsigned char *) addr;
- asm volatile(
- " xc %O0(1,%R0),%1"
- : "+Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7])
- : "cc", "memory");
+ ch = *addr;
+ *addr ^= 1 << (nr & 7);
return (ch >> (nr & 7)) & 1;
}
-#define __test_and_change_bit(X,Y) test_and_change_bit_simple(X,Y)
-
-#ifdef CONFIG_SMP
-#define set_bit set_bit_cs
-#define clear_bit clear_bit_cs
-#define change_bit change_bit_cs
-#define test_and_set_bit test_and_set_bit_cs
-#define test_and_clear_bit test_and_clear_bit_cs
-#define test_and_change_bit test_and_change_bit_cs
-#else
-#define set_bit set_bit_simple
-#define clear_bit clear_bit_simple
-#define change_bit change_bit_simple
-#define test_and_set_bit test_and_set_bit_simple
-#define test_and_clear_bit test_and_clear_bit_simple
-#define test_and_change_bit test_and_change_bit_simple
-#endif
-
-
-/*
- * This routine doesn't need to be atomic.
- */
-static inline int __test_bit(unsigned long nr, const volatile unsigned long *ptr)
+static inline int test_bit(unsigned long nr, const volatile unsigned long *ptr)
{
- unsigned long addr;
- unsigned char ch;
-
- addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
- ch = *(volatile unsigned char *) addr;
- return (ch >> (nr & 7)) & 1;
-}
+ const volatile unsigned char *addr;
-static inline int
-__constant_test_bit(unsigned long nr, const volatile unsigned long *addr) {
- return (((volatile char *) addr)
- [(nr^(BITS_PER_LONG-8))>>3] & (1<<(nr&7))) != 0;
+ addr = ((const volatile unsigned char *)ptr);
+ addr += (nr ^ (BITS_PER_LONG - 8)) >> 3;
+ return (*addr >> (nr & 7)) & 1;
}
-#define test_bit(nr,addr) \
-(__builtin_constant_p((nr)) ? \
- __constant_test_bit((nr),(addr)) : \
- __test_bit((nr),(addr)) )
-
/*
- * Optimized find bit helper functions.
- */
-
-/**
- * __ffz_word_loop - find byte offset of first long != -1UL
- * @addr: pointer to array of unsigned long
- * @size: size of the array in bits
+ * Functions which use MSB0 bit numbering.
+ * On an s390x system the bits are numbered:
+ * |0..............63|64............127|128...........191|192...........255|
+ * and on s390:
+ * |0.....31|31....63|64....95|96...127|128..159|160..191|192..223|224..255|
*/
-static inline unsigned long __ffz_word_loop(const unsigned long *addr,
- unsigned long size)
-{
- typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype;
- unsigned long bytes = 0;
-
- asm volatile(
-#ifndef CONFIG_64BIT
- " ahi %1,-1\n"
- " sra %1,5\n"
- " jz 1f\n"
- "0: c %2,0(%0,%3)\n"
- " jne 1f\n"
- " la %0,4(%0)\n"
- " brct %1,0b\n"
- "1:\n"
-#else
- " aghi %1,-1\n"
- " srag %1,%1,6\n"
- " jz 1f\n"
- "0: cg %2,0(%0,%3)\n"
- " jne 1f\n"
- " la %0,8(%0)\n"
- " brct %1,0b\n"
- "1:\n"
-#endif
- : "+&a" (bytes), "+&d" (size)
- : "d" (-1UL), "a" (addr), "m" (*(addrtype *) addr)
- : "cc" );
- return bytes;
-}
+unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size);
+unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size,
+ unsigned long offset);
-/**
- * __ffs_word_loop - find byte offset of first long != 0UL
- * @addr: pointer to array of unsigned long
- * @size: size of the array in bits
- */
-static inline unsigned long __ffs_word_loop(const unsigned long *addr,
- unsigned long size)
+static inline void set_bit_inv(unsigned long nr, volatile unsigned long *ptr)
{
- typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype;
- unsigned long bytes = 0;
-
- asm volatile(
-#ifndef CONFIG_64BIT
- " ahi %1,-1\n"
- " sra %1,5\n"
- " jz 1f\n"
- "0: c %2,0(%0,%3)\n"
- " jne 1f\n"
- " la %0,4(%0)\n"
- " brct %1,0b\n"
- "1:\n"
-#else
- " aghi %1,-1\n"
- " srag %1,%1,6\n"
- " jz 1f\n"
- "0: cg %2,0(%0,%3)\n"
- " jne 1f\n"
- " la %0,8(%0)\n"
- " brct %1,0b\n"
- "1:\n"
-#endif
- : "+&a" (bytes), "+&a" (size)
- : "d" (0UL), "a" (addr), "m" (*(addrtype *) addr)
- : "cc" );
- return bytes;
+ return set_bit(nr ^ (BITS_PER_LONG - 1), ptr);
}
-/**
- * __ffz_word - add number of the first unset bit
- * @nr: base value the bit number is added to
- * @word: the word that is searched for unset bits
- */
-static inline unsigned long __ffz_word(unsigned long nr, unsigned long word)
+static inline void clear_bit_inv(unsigned long nr, volatile unsigned long *ptr)
{
-#ifdef CONFIG_64BIT
- if ((word & 0xffffffff) == 0xffffffff) {
- word >>= 32;
- nr += 32;
- }
-#endif
- if ((word & 0xffff) == 0xffff) {
- word >>= 16;
- nr += 16;
- }
- if ((word & 0xff) == 0xff) {
- word >>= 8;
- nr += 8;
- }
- return nr + _zb_findmap[(unsigned char) word];
+ return clear_bit(nr ^ (BITS_PER_LONG - 1), ptr);
}
-/**
- * __ffs_word - add number of the first set bit
- * @nr: base value the bit number is added to
- * @word: the word that is searched for set bits
- */
-static inline unsigned long __ffs_word(unsigned long nr, unsigned long word)
+static inline void __set_bit_inv(unsigned long nr, volatile unsigned long *ptr)
{
-#ifdef CONFIG_64BIT
- if ((word & 0xffffffff) == 0) {
- word >>= 32;
- nr += 32;
- }
-#endif
- if ((word & 0xffff) == 0) {
- word >>= 16;
- nr += 16;
- }
- if ((word & 0xff) == 0) {
- word >>= 8;
- nr += 8;
- }
- return nr + _sb_findmap[(unsigned char) word];
+ return __set_bit(nr ^ (BITS_PER_LONG - 1), ptr);
}
-
-/**
- * __load_ulong_be - load big endian unsigned long
- * @p: pointer to array of unsigned long
- * @offset: byte offset of source value in the array
- */
-static inline unsigned long __load_ulong_be(const unsigned long *p,
- unsigned long offset)
+static inline void __clear_bit_inv(unsigned long nr, volatile unsigned long *ptr)
{
- p = (unsigned long *)((unsigned long) p + offset);
- return *p;
+ return __clear_bit(nr ^ (BITS_PER_LONG - 1), ptr);
}
-/**
- * __load_ulong_le - load little endian unsigned long
- * @p: pointer to array of unsigned long
- * @offset: byte offset of source value in the array
- */
-static inline unsigned long __load_ulong_le(const unsigned long *p,
- unsigned long offset)
+static inline int test_bit_inv(unsigned long nr,
+ const volatile unsigned long *ptr)
{
- unsigned long word;
-
- p = (unsigned long *)((unsigned long) p + offset);
-#ifndef CONFIG_64BIT
- asm volatile(
- " ic %0,%O1(%R1)\n"
- " icm %0,2,%O1+1(%R1)\n"
- " icm %0,4,%O1+2(%R1)\n"
- " icm %0,8,%O1+3(%R1)"
- : "=&d" (word) : "Q" (*p) : "cc");
-#else
- asm volatile(
- " lrvg %0,%1"
- : "=d" (word) : "m" (*p) );
-#endif
- return word;
+ return test_bit(nr ^ (BITS_PER_LONG - 1), ptr);
}
-/*
- * The various find bit functions.
- */
+#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
-/*
- * ffz - find first zero in word.
- * @word: The word to search
+/**
+ * __flogr - find leftmost one
+ * @word - The word to search
*
- * Undefined if no zero exists, so code should check against ~0UL first.
- */
-static inline unsigned long ffz(unsigned long word)
-{
- return __ffz_word(0, word);
+ * Returns the bit number of the most significant bit set,
+ * where the most significant bit has bit number 0.
+ * If no bit is set this function returns 64.
+ */
+static inline unsigned char __flogr(unsigned long word)
+{
+ if (__builtin_constant_p(word)) {
+ unsigned long bit = 0;
+
+ if (!word)
+ return 64;
+ if (!(word & 0xffffffff00000000UL)) {
+ word <<= 32;
+ bit += 32;
+ }
+ if (!(word & 0xffff000000000000UL)) {
+ word <<= 16;
+ bit += 16;
+ }
+ if (!(word & 0xff00000000000000UL)) {
+ word <<= 8;
+ bit += 8;
+ }
+ if (!(word & 0xf000000000000000UL)) {
+ word <<= 4;
+ bit += 4;
+ }
+ if (!(word & 0xc000000000000000UL)) {
+ word <<= 2;
+ bit += 2;
+ }
+ if (!(word & 0x8000000000000000UL)) {
+ word <<= 1;
+ bit += 1;
+ }
+ return bit;
+ } else {
+ register unsigned long bit asm("4") = word;
+ register unsigned long out asm("5");
+
+ asm volatile(
+ " flogr %[bit],%[bit]\n"
+ : [bit] "+d" (bit), [out] "=d" (out) : : "cc");
+ return bit;
+ }
}
/**
@@ -573,337 +395,83 @@ static inline unsigned long ffz(unsigned long word)
*
* Undefined if no bit exists, so code should check against 0 first.
*/
-static inline unsigned long __ffs (unsigned long word)
+static inline unsigned long __ffs(unsigned long word)
{
- return __ffs_word(0, word);
+ return __flogr(-word & word) ^ (BITS_PER_LONG - 1);
}
/**
* ffs - find first bit set
- * @x: the word to search
+ * @word: the word to search
*
- * This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
+ * This is defined the same way as the libc and
+ * compiler builtin ffs routines (man ffs).
*/
-static inline int ffs(int x)
+static inline int ffs(int word)
{
- if (!x)
- return 0;
- return __ffs_word(1, x);
+ unsigned long mask = 2 * BITS_PER_LONG - 1;
+ unsigned int val = (unsigned int)word;
+
+ return (1 + (__flogr(-val & val) ^ (BITS_PER_LONG - 1))) & mask;
}
/**
- * find_first_zero_bit - find the first zero bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
+ * __fls - find last (most-significant) set bit in a long word
+ * @word: the word to search
*
- * Returns the bit-number of the first zero bit, not the number of the byte
- * containing a bit.
+ * Undefined if no set bit exists, so code should check against 0 first.
*/
-static inline unsigned long find_first_zero_bit(const unsigned long *addr,
- unsigned long size)
+static inline unsigned long __fls(unsigned long word)
{
- unsigned long bytes, bits;
-
- if (!size)
- return 0;
- bytes = __ffz_word_loop(addr, size);
- bits = __ffz_word(bytes*8, __load_ulong_be(addr, bytes));
- return (bits < size) ? bits : size;
+ return __flogr(word) ^ (BITS_PER_LONG - 1);
}
-#define find_first_zero_bit find_first_zero_bit
/**
- * find_first_bit - find the first set bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
+ * fls64 - find last set bit in a 64-bit word
+ * @word: the word to search
*
- * Returns the bit-number of the first set bit, not the number of the byte
- * containing a bit.
- */
-static inline unsigned long find_first_bit(const unsigned long * addr,
- unsigned long size)
-{
- unsigned long bytes, bits;
-
- if (!size)
- return 0;
- bytes = __ffs_word_loop(addr, size);
- bits = __ffs_word(bytes*8, __load_ulong_be(addr, bytes));
- return (bits < size) ? bits : size;
-}
-#define find_first_bit find_first_bit
-
-/*
- * Big endian variant whichs starts bit counting from left using
- * the flogr (find leftmost one) instruction.
- */
-static inline unsigned long __flo_word(unsigned long nr, unsigned long val)
-{
- register unsigned long bit asm("2") = val;
- register unsigned long out asm("3");
-
- asm volatile (
- " .insn rre,0xb9830000,%[bit],%[bit]\n"
- : [bit] "+d" (bit), [out] "=d" (out) : : "cc");
- return nr + bit;
-}
-
-/*
- * 64 bit special left bitops format:
- * order in memory:
- * 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
- * 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
- * 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
- * 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
- * after that follows the next long with bit numbers
- * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
- * 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
- * 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
- * 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
- * The reason for this bit ordering is the fact that
- * the hardware sets bits in a bitmap starting at bit 0
- * and we don't want to scan the bitmap from the 'wrong
- * end'.
+ * This is defined in a similar way as the libc and compiler builtin
+ * ffsll, but returns the position of the most significant set bit.
+ *
+ * fls64(value) returns 0 if value is 0 or the position of the last
+ * set bit if value is nonzero. The last (most significant) bit is
+ * at position 64.
*/
-static inline unsigned long find_first_bit_left(const unsigned long *addr,
- unsigned long size)
-{
- unsigned long bytes, bits;
-
- if (!size)
- return 0;
- bytes = __ffs_word_loop(addr, size);
- bits = __flo_word(bytes * 8, __load_ulong_be(addr, bytes));
- return (bits < size) ? bits : size;
-}
-
-static inline int find_next_bit_left(const unsigned long *addr,
- unsigned long size,
- unsigned long offset)
+static inline int fls64(unsigned long word)
{
- const unsigned long *p;
- unsigned long bit, set;
-
- if (offset >= size)
- return size;
- bit = offset & (BITS_PER_LONG - 1);
- offset -= bit;
- size -= offset;
- p = addr + offset / BITS_PER_LONG;
- if (bit) {
- set = __flo_word(0, *p & (~0UL >> bit));
- if (set >= size)
- return size + offset;
- if (set < BITS_PER_LONG)
- return set + offset;
- offset += BITS_PER_LONG;
- size -= BITS_PER_LONG;
- p++;
- }
- return offset + find_first_bit_left(p, size);
-}
-
-#define for_each_set_bit_left(bit, addr, size) \
- for ((bit) = find_first_bit_left((addr), (size)); \
- (bit) < (size); \
- (bit) = find_next_bit_left((addr), (size), (bit) + 1))
-
-/* same as for_each_set_bit() but use bit as value to start with */
-#define for_each_set_bit_left_cont(bit, addr, size) \
- for ((bit) = find_next_bit_left((addr), (size), (bit)); \
- (bit) < (size); \
- (bit) = find_next_bit_left((addr), (size), (bit) + 1))
+ unsigned long mask = 2 * BITS_PER_LONG - 1;
-/**
- * find_next_zero_bit - find the first zero bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-static inline int find_next_zero_bit (const unsigned long * addr,
- unsigned long size,
- unsigned long offset)
-{
- const unsigned long *p;
- unsigned long bit, set;
-
- if (offset >= size)
- return size;
- bit = offset & (BITS_PER_LONG - 1);
- offset -= bit;
- size -= offset;
- p = addr + offset / BITS_PER_LONG;
- if (bit) {
- /*
- * __ffz_word returns BITS_PER_LONG
- * if no zero bit is present in the word.
- */
- set = __ffz_word(bit, *p >> bit);
- if (set >= size)
- return size + offset;
- if (set < BITS_PER_LONG)
- return set + offset;
- offset += BITS_PER_LONG;
- size -= BITS_PER_LONG;
- p++;
- }
- return offset + find_first_zero_bit(p, size);
+ return (1 + (__flogr(word) ^ (BITS_PER_LONG - 1))) & mask;
}
-#define find_next_zero_bit find_next_zero_bit
/**
- * find_next_bit - find the first set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
+ * fls - find last (most-significant) bit set
+ * @word: the word to search
+ *
+ * This is defined the same way as ffs.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
*/
-static inline int find_next_bit (const unsigned long * addr,
- unsigned long size,
- unsigned long offset)
+static inline int fls(int word)
{
- const unsigned long *p;
- unsigned long bit, set;
-
- if (offset >= size)
- return size;
- bit = offset & (BITS_PER_LONG - 1);
- offset -= bit;
- size -= offset;
- p = addr + offset / BITS_PER_LONG;
- if (bit) {
- /*
- * __ffs_word returns BITS_PER_LONG
- * if no one bit is present in the word.
- */
- set = __ffs_word(0, *p & (~0UL << bit));
- if (set >= size)
- return size + offset;
- if (set < BITS_PER_LONG)
- return set + offset;
- offset += BITS_PER_LONG;
- size -= BITS_PER_LONG;
- p++;
- }
- return offset + find_first_bit(p, size);
+ return fls64((unsigned int)word);
}
-#define find_next_bit find_next_bit
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
- */
-static inline int sched_find_first_bit(unsigned long *b)
-{
- return find_first_bit(b, 140);
-}
+#else /* CONFIG_HAVE_MARCH_Z9_109_FEATURES */
-#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/ffs.h>
#include <asm-generic/bitops/__fls.h>
+#include <asm-generic/bitops/fls.h>
#include <asm-generic/bitops/fls64.h>
+#endif /* CONFIG_HAVE_MARCH_Z9_109_FEATURES */
+
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/hweight.h>
#include <asm-generic/bitops/lock.h>
-
-/*
- * ATTENTION: intel byte ordering convention for ext2 and minix !!
- * bit 0 is the LSB of addr; bit 31 is the MSB of addr;
- * bit 32 is the LSB of (addr+4).
- * That combined with the little endian byte order of Intel gives the
- * following bit order in memory:
- * 07 06 05 04 03 02 01 00 15 14 13 12 11 10 09 08 \
- * 23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24
- */
-
-static inline int find_first_zero_bit_le(void *vaddr, unsigned int size)
-{
- unsigned long bytes, bits;
-
- if (!size)
- return 0;
- bytes = __ffz_word_loop(vaddr, size);
- bits = __ffz_word(bytes*8, __load_ulong_le(vaddr, bytes));
- return (bits < size) ? bits : size;
-}
-#define find_first_zero_bit_le find_first_zero_bit_le
-
-static inline int find_next_zero_bit_le(void *vaddr, unsigned long size,
- unsigned long offset)
-{
- unsigned long *addr = vaddr, *p;
- unsigned long bit, set;
-
- if (offset >= size)
- return size;
- bit = offset & (BITS_PER_LONG - 1);
- offset -= bit;
- size -= offset;
- p = addr + offset / BITS_PER_LONG;
- if (bit) {
- /*
- * s390 version of ffz returns BITS_PER_LONG
- * if no zero bit is present in the word.
- */
- set = __ffz_word(bit, __load_ulong_le(p, 0) >> bit);
- if (set >= size)
- return size + offset;
- if (set < BITS_PER_LONG)
- return set + offset;
- offset += BITS_PER_LONG;
- size -= BITS_PER_LONG;
- p++;
- }
- return offset + find_first_zero_bit_le(p, size);
-}
-#define find_next_zero_bit_le find_next_zero_bit_le
-
-static inline unsigned long find_first_bit_le(void *vaddr, unsigned long size)
-{
- unsigned long bytes, bits;
-
- if (!size)
- return 0;
- bytes = __ffs_word_loop(vaddr, size);
- bits = __ffs_word(bytes*8, __load_ulong_le(vaddr, bytes));
- return (bits < size) ? bits : size;
-}
-#define find_first_bit_le find_first_bit_le
-
-static inline int find_next_bit_le(void *vaddr, unsigned long size,
- unsigned long offset)
-{
- unsigned long *addr = vaddr, *p;
- unsigned long bit, set;
-
- if (offset >= size)
- return size;
- bit = offset & (BITS_PER_LONG - 1);
- offset -= bit;
- size -= offset;
- p = addr + offset / BITS_PER_LONG;
- if (bit) {
- /*
- * s390 version of ffz returns BITS_PER_LONG
- * if no zero bit is present in the word.
- */
- set = __ffs_word(0, __load_ulong_le(p, 0) & (~0UL << bit));
- if (set >= size)
- return size + offset;
- if (set < BITS_PER_LONG)
- return set + offset;
- offset += BITS_PER_LONG;
- size -= BITS_PER_LONG;
- p++;
- }
- return offset + find_first_bit_le(p, size);
-}
-#define find_next_bit_le find_next_bit_le
-
+#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/le.h>
-
#include <asm-generic/bitops/ext2-atomic-setbit.h>
#endif /* _S390_BITOPS_H */
diff --git a/arch/s390/include/asm/debug.h b/arch/s390/include/asm/debug.h
index 188c5052a20a..530c15eb01e9 100644
--- a/arch/s390/include/asm/debug.h
+++ b/arch/s390/include/asm/debug.h
@@ -107,6 +107,11 @@ void debug_set_level(debug_info_t* id, int new_level);
void debug_set_critical(void);
void debug_stop_all(void);
+static inline bool debug_level_enabled(debug_info_t* id, int level)
+{
+ return level <= id->level;
+}
+
static inline debug_entry_t*
debug_event(debug_info_t* id, int level, void* data, int length)
{
diff --git a/arch/s390/include/asm/dis.h b/arch/s390/include/asm/dis.h
new file mode 100644
index 000000000000..04a83f5773cd
--- /dev/null
+++ b/arch/s390/include/asm/dis.h
@@ -0,0 +1,52 @@
+/*
+ * Disassemble s390 instructions.
+ *
+ * Copyright IBM Corp. 2007
+ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+#ifndef __ASM_S390_DIS_H__
+#define __ASM_S390_DIS_H__
+
+/* Type of operand */
+#define OPERAND_GPR 0x1 /* Operand printed as %rx */
+#define OPERAND_FPR 0x2 /* Operand printed as %fx */
+#define OPERAND_AR 0x4 /* Operand printed as %ax */
+#define OPERAND_CR 0x8 /* Operand printed as %cx */
+#define OPERAND_DISP 0x10 /* Operand printed as displacement */
+#define OPERAND_BASE 0x20 /* Operand printed as base register */
+#define OPERAND_INDEX 0x40 /* Operand printed as index register */
+#define OPERAND_PCREL 0x80 /* Operand printed as pc-relative symbol */
+#define OPERAND_SIGNED 0x100 /* Operand printed as signed value */
+#define OPERAND_LENGTH 0x200 /* Operand printed as length (+1) */
+
+
+struct s390_operand {
+ int bits; /* The number of bits in the operand. */
+ int shift; /* The number of bits to shift. */
+ int flags; /* One bit syntax flags. */
+};
+
+struct s390_insn {
+ const char name[5];
+ unsigned char opfrag;
+ unsigned char format;
+};
+
+
+static inline int insn_length(unsigned char code)
+{
+ return ((((int) code + 64) >> 7) + 1) << 1;
+}
+
+void show_code(struct pt_regs *regs);
+void print_fn_code(unsigned char *code, unsigned long len);
+int insn_to_mnemonic(unsigned char *instruction, char *buf, unsigned int len);
+struct s390_insn *find_insn(unsigned char *code);
+
+static inline int is_known_insn(unsigned char *code)
+{
+ return !!find_insn(code);
+}
+
+#endif /* __ASM_S390_DIS_H__ */
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index e87ecaa2c569..6a0e27be6305 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -220,7 +220,6 @@ struct kvm_s390_interrupt_info {
/* for local_interrupt.action_flags */
#define ACTION_STORE_ON_STOP (1<<0)
#define ACTION_STOP_ON_STOP (1<<1)
-#define ACTION_RELOADVCPU_ON_STOP (1<<2)
struct kvm_s390_local_interrupt {
spinlock_t lock;
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h
index 9f973d8de90e..5d1f950704dc 100644
--- a/arch/s390/include/asm/mmu_context.h
+++ b/arch/s390/include/asm/mmu_context.h
@@ -40,14 +40,8 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk)
pgd_t *pgd = mm->pgd;
S390_lowcore.user_asce = mm->context.asce_bits | __pa(pgd);
- if (s390_user_mode != HOME_SPACE_MODE) {
- /* Load primary space page table origin. */
- asm volatile(LCTL_OPCODE" 1,1,%0\n"
- : : "m" (S390_lowcore.user_asce) );
- } else
- /* Load home space page table origin. */
- asm volatile(LCTL_OPCODE" 13,13,%0"
- : : "m" (S390_lowcore.user_asce) );
+ /* Load primary space page table origin. */
+ asm volatile(LCTL_OPCODE" 1,1,%0\n" : : "m" (S390_lowcore.user_asce));
set_fs(current->thread.mm_segment);
}
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 0eb37505cab1..0f9f5a1bea00 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -134,14 +134,14 @@ struct stack_frame {
* Do necessary setup to start up a new thread.
*/
#define start_thread(regs, new_psw, new_stackp) do { \
- regs->psw.mask = psw_user_bits | PSW_MASK_EA | PSW_MASK_BA; \
+ regs->psw.mask = PSW_USER_BITS | PSW_MASK_EA | PSW_MASK_BA; \
regs->psw.addr = new_psw | PSW_ADDR_AMODE; \
regs->gprs[15] = new_stackp; \
execve_tail(); \
} while (0)
#define start_thread31(regs, new_psw, new_stackp) do { \
- regs->psw.mask = psw_user_bits | PSW_MASK_BA; \
+ regs->psw.mask = PSW_USER_BITS | PSW_MASK_BA; \
regs->psw.addr = new_psw | PSW_ADDR_AMODE; \
regs->gprs[15] = new_stackp; \
__tlb_flush_mm(current->mm); \
@@ -169,11 +169,6 @@ extern void release_thread(struct task_struct *);
*/
extern unsigned long thread_saved_pc(struct task_struct *t);
-extern void show_code(struct pt_regs *regs);
-extern void print_fn_code(unsigned char *code, unsigned long len);
-extern int insn_to_mnemonic(unsigned char *instruction, char *buf,
- unsigned int len);
-
unsigned long get_wchan(struct task_struct *p);
#define task_pt_regs(tsk) ((struct pt_regs *) \
(task_stack_page(tsk) + THREAD_SIZE) - 1)
@@ -346,9 +341,9 @@ __set_psw_mask(unsigned long mask)
}
#define local_mcck_enable() \
- __set_psw_mask(psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK)
+ __set_psw_mask(PSW_KERNEL_BITS | PSW_MASK_DAT | PSW_MASK_MCHECK)
#define local_mcck_disable() \
- __set_psw_mask(psw_kernel_bits | PSW_MASK_DAT)
+ __set_psw_mask(PSW_KERNEL_BITS | PSW_MASK_DAT)
/*
* Basic Machine Check/Program Check Handler.
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index 52b56533c57c..9c82cebddabd 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -10,8 +10,11 @@
#ifndef __ASSEMBLY__
-extern long psw_kernel_bits;
-extern long psw_user_bits;
+#define PSW_KERNEL_BITS (PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_HOME | \
+ PSW_MASK_EA | PSW_MASK_BA)
+#define PSW_USER_BITS (PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | \
+ PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_MCHECK | \
+ PSW_MASK_PSTATE | PSW_ASC_PRIMARY)
/*
* The pt_regs struct defines the way the registers are stored on
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index 59880dbaf360..df802ee14af6 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -48,13 +48,6 @@ void detect_memory_layout(struct mem_chunk chunk[], unsigned long maxsize);
void create_mem_hole(struct mem_chunk mem_chunk[], unsigned long addr,
unsigned long size);
-#define PRIMARY_SPACE_MODE 0
-#define ACCESS_REGISTER_MODE 1
-#define SECONDARY_SPACE_MODE 2
-#define HOME_SPACE_MODE 3
-
-extern unsigned int s390_user_mode;
-
/*
* Machine features detected in head.S
*/
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index 9c33ed4e666f..79330af9a5f8 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -94,9 +94,7 @@ static inline unsigned long extable_fixup(const struct exception_table_entry *x)
struct uaccess_ops {
size_t (*copy_from_user)(size_t, const void __user *, void *);
- size_t (*copy_from_user_small)(size_t, const void __user *, void *);
size_t (*copy_to_user)(size_t, void __user *, const void *);
- size_t (*copy_to_user_small)(size_t, void __user *, const void *);
size_t (*copy_in_user)(size_t, void __user *, const void __user *);
size_t (*clear_user)(size_t, void __user *);
size_t (*strnlen_user)(size_t, const char __user *);
@@ -106,22 +104,20 @@ struct uaccess_ops {
};
extern struct uaccess_ops uaccess;
-extern struct uaccess_ops uaccess_std;
extern struct uaccess_ops uaccess_mvcos;
-extern struct uaccess_ops uaccess_mvcos_switch;
extern struct uaccess_ops uaccess_pt;
extern int __handle_fault(unsigned long, unsigned long, int);
static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
{
- size = uaccess.copy_to_user_small(size, ptr, x);
+ size = uaccess.copy_to_user(size, ptr, x);
return size ? -EFAULT : size;
}
static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
{
- size = uaccess.copy_from_user_small(size, ptr, x);
+ size = uaccess.copy_from_user(size, ptr, x);
return size ? -EFAULT : size;
}
@@ -226,10 +222,7 @@ extern int __get_user_bad(void) __attribute__((noreturn));
static inline unsigned long __must_check
__copy_to_user(void __user *to, const void *from, unsigned long n)
{
- if (__builtin_constant_p(n) && (n <= 256))
- return uaccess.copy_to_user_small(n, to, from);
- else
- return uaccess.copy_to_user(n, to, from);
+ return uaccess.copy_to_user(n, to, from);
}
#define __copy_to_user_inatomic __copy_to_user
@@ -275,10 +268,7 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
static inline unsigned long __must_check
__copy_from_user(void *to, const void __user *from, unsigned long n)
{
- if (__builtin_constant_p(n) && (n <= 256))
- return uaccess.copy_from_user_small(n, from, to);
- else
- return uaccess.copy_from_user(n, from, to);
+ return uaccess.copy_from_user(n, from, to);
}
extern void copy_from_user_overflow(void)
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 4bb2a4656163..2403303cfed7 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -28,7 +28,7 @@ CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"'
CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
-obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o
+obj-y := traps.o time.o process.o base.o early.o setup.o vtime.o
obj-y += processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o
obj-y += debug.o irq.o ipl.o dis.o diag.o sclp.o vdso.o
obj-y += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
diff --git a/arch/s390/kernel/bitmap.c b/arch/s390/kernel/bitmap.c
deleted file mode 100644
index 102da5e23037..000000000000
--- a/arch/s390/kernel/bitmap.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Bitmaps for set_bit, clear_bit, test_and_set_bit, ...
- * See include/asm/{bitops.h|posix_types.h} for details
- *
- * Copyright IBM Corp. 1999, 2009
- * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
- */
-
-#include <linux/bitops.h>
-#include <linux/module.h>
-
-const char _oi_bitmap[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
-EXPORT_SYMBOL(_oi_bitmap);
-
-const char _ni_bitmap[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f };
-EXPORT_SYMBOL(_ni_bitmap);
-
-const char _zb_findmap[] = {
- 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
- 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
- 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
- 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
- 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
- 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
- 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
- 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,
- 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
- 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
- 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
- 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
- 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
- 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
- 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
- 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8 };
-EXPORT_SYMBOL(_zb_findmap);
-
-const char _sb_findmap[] = {
- 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
-EXPORT_SYMBOL(_sb_findmap);
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index 1389b637dae5..e8fd90eb2b59 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -188,8 +188,8 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
(__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 |
(__u64)(regs32.psw.addr & PSW32_ADDR_AMODE);
/* Check for invalid user address space control. */
- if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
- regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
+ if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_HOME)
+ regs->psw.mask = PSW_ASC_PRIMARY |
(regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
for (i = 0; i < NUM_GPRS; i++)
@@ -348,7 +348,7 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
regs->gprs[15] = (__force __u64) frame;
/* Force 31 bit amode and default user address space control. */
regs->psw.mask = PSW_MASK_BA |
- (psw_user_bits & PSW_MASK_ASC) |
+ (PSW_USER_BITS & PSW_MASK_ASC) |
(regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (__force __u64) ka->sa.sa_handler;
@@ -415,7 +415,7 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->gprs[15] = (__force __u64) frame;
/* Force 31 bit amode and default user address space control. */
regs->psw.mask = PSW_MASK_BA |
- (psw_user_bits & PSW_MASK_ASC) |
+ (PSW_USER_BITS & PSW_MASK_ASC) |
(regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (__u64 __force) ka->sa.sa_handler;
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index be87d3e05a5b..993efe6a887c 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -23,6 +23,7 @@
#include <linux/kdebug.h>
#include <asm/uaccess.h>
+#include <asm/dis.h>
#include <asm/io.h>
#include <linux/atomic.h>
#include <asm/mathemu.h>
@@ -37,17 +38,6 @@
#define ONELONG "%016lx: "
#endif /* CONFIG_64BIT */
-#define OPERAND_GPR 0x1 /* Operand printed as %rx */
-#define OPERAND_FPR 0x2 /* Operand printed as %fx */
-#define OPERAND_AR 0x4 /* Operand printed as %ax */
-#define OPERAND_CR 0x8 /* Operand printed as %cx */
-#define OPERAND_DISP 0x10 /* Operand printed as displacement */
-#define OPERAND_BASE 0x20 /* Operand printed as base register */
-#define OPERAND_INDEX 0x40 /* Operand printed as index register */
-#define OPERAND_PCREL 0x80 /* Operand printed as pc-relative symbol */
-#define OPERAND_SIGNED 0x100 /* Operand printed as signed value */
-#define OPERAND_LENGTH 0x200 /* Operand printed as length (+1) */
-
enum {
UNUSED, /* Indicates the end of the operand list */
R_8, /* GPR starting at position 8 */
@@ -155,19 +145,7 @@ enum {
INSTR_S_00, INSTR_S_RD,
};
-struct operand {
- int bits; /* The number of bits in the operand. */
- int shift; /* The number of bits to shift. */
- int flags; /* One bit syntax flags. */
-};
-
-struct insn {
- const char name[5];
- unsigned char opfrag;
- unsigned char format;
-};
-
-static const struct operand operands[] =
+static const struct s390_operand operands[] =
{
[UNUSED] = { 0, 0, 0 },
[R_8] = { 4, 8, OPERAND_GPR },
@@ -479,7 +457,7 @@ static char *long_insn_name[] = {
[LONG_INSN_PCISTB] = "pcistb",
};
-static struct insn opcode[] = {
+static struct s390_insn opcode[] = {
#ifdef CONFIG_64BIT
{ "bprp", 0xc5, INSTR_MII_UPI },
{ "bpp", 0xc7, INSTR_SMI_U0RDP },
@@ -668,7 +646,7 @@ static struct insn opcode[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_01[] = {
+static struct s390_insn opcode_01[] = {
#ifdef CONFIG_64BIT
{ "ptff", 0x04, INSTR_E },
{ "pfpo", 0x0a, INSTR_E },
@@ -684,7 +662,7 @@ static struct insn opcode_01[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_a5[] = {
+static struct s390_insn opcode_a5[] = {
#ifdef CONFIG_64BIT
{ "iihh", 0x00, INSTR_RI_RU },
{ "iihl", 0x01, INSTR_RI_RU },
@@ -706,7 +684,7 @@ static struct insn opcode_a5[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_a7[] = {
+static struct s390_insn opcode_a7[] = {
#ifdef CONFIG_64BIT
{ "tmhh", 0x02, INSTR_RI_RU },
{ "tmhl", 0x03, INSTR_RI_RU },
@@ -728,7 +706,7 @@ static struct insn opcode_a7[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_aa[] = {
+static struct s390_insn opcode_aa[] = {
#ifdef CONFIG_64BIT
{ { 0, LONG_INSN_RINEXT }, 0x00, INSTR_RI_RI },
{ "rion", 0x01, INSTR_RI_RI },
@@ -739,7 +717,7 @@ static struct insn opcode_aa[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_b2[] = {
+static struct s390_insn opcode_b2[] = {
#ifdef CONFIG_64BIT
{ "stckf", 0x7c, INSTR_S_RD },
{ "lpp", 0x80, INSTR_S_RD },
@@ -851,7 +829,7 @@ static struct insn opcode_b2[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_b3[] = {
+static struct s390_insn opcode_b3[] = {
#ifdef CONFIG_64BIT
{ "maylr", 0x38, INSTR_RRF_F0FF },
{ "mylr", 0x39, INSTR_RRF_F0FF },
@@ -1034,7 +1012,7 @@ static struct insn opcode_b3[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_b9[] = {
+static struct s390_insn opcode_b9[] = {
#ifdef CONFIG_64BIT
{ "lpgr", 0x00, INSTR_RRE_RR },
{ "lngr", 0x01, INSTR_RRE_RR },
@@ -1167,7 +1145,7 @@ static struct insn opcode_b9[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_c0[] = {
+static struct s390_insn opcode_c0[] = {
#ifdef CONFIG_64BIT
{ "lgfi", 0x01, INSTR_RIL_RI },
{ "xihf", 0x06, INSTR_RIL_RU },
@@ -1187,7 +1165,7 @@ static struct insn opcode_c0[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_c2[] = {
+static struct s390_insn opcode_c2[] = {
#ifdef CONFIG_64BIT
{ "msgfi", 0x00, INSTR_RIL_RI },
{ "msfi", 0x01, INSTR_RIL_RI },
@@ -1205,7 +1183,7 @@ static struct insn opcode_c2[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_c4[] = {
+static struct s390_insn opcode_c4[] = {
#ifdef CONFIG_64BIT
{ "llhrl", 0x02, INSTR_RIL_RP },
{ "lghrl", 0x04, INSTR_RIL_RP },
@@ -1222,7 +1200,7 @@ static struct insn opcode_c4[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_c6[] = {
+static struct s390_insn opcode_c6[] = {
#ifdef CONFIG_64BIT
{ "exrl", 0x00, INSTR_RIL_RP },
{ "pfdrl", 0x02, INSTR_RIL_UP },
@@ -1240,7 +1218,7 @@ static struct insn opcode_c6[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_c8[] = {
+static struct s390_insn opcode_c8[] = {
#ifdef CONFIG_64BIT
{ "mvcos", 0x00, INSTR_SSF_RRDRD },
{ "ectg", 0x01, INSTR_SSF_RRDRD },
@@ -1251,7 +1229,7 @@ static struct insn opcode_c8[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_cc[] = {
+static struct s390_insn opcode_cc[] = {
#ifdef CONFIG_64BIT
{ "brcth", 0x06, INSTR_RIL_RP },
{ "aih", 0x08, INSTR_RIL_RI },
@@ -1263,7 +1241,7 @@ static struct insn opcode_cc[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_e3[] = {
+static struct s390_insn opcode_e3[] = {
#ifdef CONFIG_64BIT
{ "ltg", 0x02, INSTR_RXY_RRRD },
{ "lrag", 0x03, INSTR_RXY_RRRD },
@@ -1369,7 +1347,7 @@ static struct insn opcode_e3[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_e5[] = {
+static struct s390_insn opcode_e5[] = {
#ifdef CONFIG_64BIT
{ "strag", 0x02, INSTR_SSE_RDRD },
{ "mvhhi", 0x44, INSTR_SIL_RDI },
@@ -1391,7 +1369,7 @@ static struct insn opcode_e5[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_eb[] = {
+static struct s390_insn opcode_eb[] = {
#ifdef CONFIG_64BIT
{ "lmg", 0x04, INSTR_RSY_RRRD },
{ "srag", 0x0a, INSTR_RSY_RRRD },
@@ -1465,7 +1443,7 @@ static struct insn opcode_eb[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_ec[] = {
+static struct s390_insn opcode_ec[] = {
#ifdef CONFIG_64BIT
{ "brxhg", 0x44, INSTR_RIE_RRP },
{ "brxlg", 0x45, INSTR_RIE_RRP },
@@ -1504,7 +1482,7 @@ static struct insn opcode_ec[] = {
{ "", 0, INSTR_INVALID }
};
-static struct insn opcode_ed[] = {
+static struct s390_insn opcode_ed[] = {
#ifdef CONFIG_64BIT
{ "mayl", 0x38, INSTR_RXF_FRRDF },
{ "myl", 0x39, INSTR_RXF_FRRDF },
@@ -1572,7 +1550,7 @@ static struct insn opcode_ed[] = {
/* Extracts an operand value from an instruction. */
static unsigned int extract_operand(unsigned char *code,
- const struct operand *operand)
+ const struct s390_operand *operand)
{
unsigned int val;
int bits;
@@ -1608,16 +1586,11 @@ static unsigned int extract_operand(unsigned char *code,
return val;
}
-static inline int insn_length(unsigned char code)
-{
- return ((((int) code + 64) >> 7) + 1) << 1;
-}
-
-static struct insn *find_insn(unsigned char *code)
+struct s390_insn *find_insn(unsigned char *code)
{
unsigned char opfrag = code[1];
unsigned char opmask;
- struct insn *table;
+ struct s390_insn *table;
switch (code[0]) {
case 0x01:
@@ -1706,7 +1679,7 @@ static struct insn *find_insn(unsigned char *code)
*/
int insn_to_mnemonic(unsigned char *instruction, char *buf, unsigned int len)
{
- struct insn *insn;
+ struct s390_insn *insn;
insn = find_insn(instruction);
if (!insn)
@@ -1722,9 +1695,9 @@ EXPORT_SYMBOL_GPL(insn_to_mnemonic);
static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
{
- struct insn *insn;
+ struct s390_insn *insn;
const unsigned char *ops;
- const struct operand *operand;
+ const struct s390_operand *operand;
unsigned int value;
char separator;
char *ptr;
diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c
index 99e7f6035895..e6af9406987c 100644
--- a/arch/s390/kernel/dumpstack.c
+++ b/arch/s390/kernel/dumpstack.c
@@ -15,6 +15,7 @@
#include <linux/sched.h>
#include <asm/processor.h>
#include <asm/debug.h>
+#include <asm/dis.h>
#include <asm/ipl.h>
#ifndef CONFIG_64BIT
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index fd8db63dfc94..429afcc480cb 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -437,7 +437,7 @@ ENTRY(startup_kdump)
#if defined(CONFIG_64BIT)
#if defined(CONFIG_MARCH_ZEC12)
- .long 3, 0xc100efe3, 0xf46ce000, 0x00400000
+ .long 3, 0xc100efe3, 0xf46ce800, 0x00400000
#elif defined(CONFIG_MARCH_Z196)
.long 2, 0xc100efe3, 0xf46c0000
#elif defined(CONFIG_MARCH_Z10)
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index feb719d3c851..633ca7504536 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -2051,12 +2051,12 @@ void s390_reset_system(void (*func)(void *), void *data)
__ctl_clear_bit(0,28);
/* Set new machine check handler */
- S390_lowcore.mcck_new_psw.mask = psw_kernel_bits | PSW_MASK_DAT;
+ S390_lowcore.mcck_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT;
S390_lowcore.mcck_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
/* Set new program check handler */
- S390_lowcore.program_new_psw.mask = psw_kernel_bits | PSW_MASK_DAT;
+ S390_lowcore.program_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT;
S390_lowcore.program_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 0ce9fb245034..59a9c35c4598 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -26,11 +26,12 @@
#include <linux/stop_machine.h>
#include <linux/kdebug.h>
#include <linux/uaccess.h>
-#include <asm/cacheflush.h>
-#include <asm/sections.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/hardirq.h>
+#include <asm/cacheflush.h>
+#include <asm/sections.h>
+#include <asm/dis.h>
DEFINE_PER_CPU(struct kprobe *, current_kprobe);
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
@@ -59,6 +60,8 @@ struct kprobe_insn_cache kprobe_dmainsn_slots = {
static int __kprobes is_prohibited_opcode(kprobe_opcode_t *insn)
{
+ if (!is_known_insn((unsigned char *)insn))
+ return -EINVAL;
switch (insn[0] >> 8) {
case 0x0c: /* bassm */
case 0x0b: /* bsm */
@@ -67,6 +70,11 @@ static int __kprobes is_prohibited_opcode(kprobe_opcode_t *insn)
case 0xac: /* stnsm */
case 0xad: /* stosm */
return -EINVAL;
+ case 0xc6:
+ switch (insn[0] & 0x0f) {
+ case 0x00: /* exrl */
+ return -EINVAL;
+ }
}
switch (insn[0]) {
case 0x0101: /* pr */
@@ -180,7 +188,6 @@ static int __kprobes is_insn_relative_long(kprobe_opcode_t *insn)
break;
case 0xc6:
switch (insn[0] & 0x0f) {
- case 0x00: /* exrl */
case 0x02: /* pfdrl */
case 0x04: /* cghrl */
case 0x05: /* chrl */
@@ -204,7 +211,7 @@ static void __kprobes copy_instruction(struct kprobe *p)
s64 disp, new_disp;
u64 addr, new_addr;
- memcpy(p->ainsn.insn, p->addr, ((p->opcode >> 14) + 3) & -2);
+ memcpy(p->ainsn.insn, p->addr, insn_length(p->opcode >> 8));
if (!is_insn_relative_long(p->ainsn.insn))
return;
/*
@@ -248,7 +255,7 @@ static int __kprobes s390_get_insn_slot(struct kprobe *p)
p->ainsn.insn = NULL;
if (is_kernel_addr(p->addr))
p->ainsn.insn = get_dmainsn_slot();
- if (is_module_addr(p->addr))
+ else if (is_module_addr(p->addr))
p->ainsn.insn = get_insn_slot();
return p->ainsn.insn ? 0 : -ENOMEM;
}
@@ -604,7 +611,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
ip += (unsigned long) p->addr - (unsigned long) p->ainsn.insn;
if (fixup & FIXUP_BRANCH_NOT_TAKEN) {
- int ilen = ((p->ainsn.insn[0] >> 14) + 3) & -2;
+ int ilen = insn_length(p->ainsn.insn[0] >> 8);
if (ip - (unsigned long) p->ainsn.insn == ilen)
ip = (unsigned long) p->addr + ilen;
}
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index c5dbb335716d..e1cdd31acabb 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -139,7 +139,7 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
if (unlikely(p->flags & PF_KTHREAD)) {
/* kernel thread */
memset(&frame->childregs, 0, sizeof(struct pt_regs));
- frame->childregs.psw.mask = psw_kernel_bits | PSW_MASK_DAT |
+ frame->childregs.psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT |
PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
frame->childregs.psw.addr = PSW_ADDR_AMODE |
(unsigned long) kernel_thread_starter;
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 9556905bd3ce..e6abd5bd31b0 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -200,7 +200,7 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr)
tmp = *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr);
if (addr == (addr_t) &dummy->regs.psw.mask)
/* Return a clean psw mask. */
- tmp = psw_user_bits | (tmp & PSW_MASK_USER);
+ tmp = PSW_USER_BITS | (tmp & PSW_MASK_USER);
} else if (addr < (addr_t) &dummy->regs.orig_gpr2) {
/*
@@ -322,7 +322,7 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
* psw and gprs are stored on the stack
*/
if (addr == (addr_t) &dummy->regs.psw.mask &&
- ((data & ~PSW_MASK_USER) != psw_user_bits ||
+ ((data & ~PSW_MASK_USER) != PSW_USER_BITS ||
((data & PSW_MASK_EA) && !(data & PSW_MASK_BA))))
/* Invalid psw mask. */
return -EINVAL;
diff --git a/arch/s390/kernel/runtime_instr.c b/arch/s390/kernel/runtime_instr.c
index e1c9d1c292fa..d817cce7e72d 100644
--- a/arch/s390/kernel/runtime_instr.c
+++ b/arch/s390/kernel/runtime_instr.c
@@ -40,8 +40,6 @@ static void disable_runtime_instr(void)
static void init_runtime_instr_cb(struct runtime_instr_cb *cb)
{
cb->buf_limit = 0xfff;
- if (s390_user_mode == HOME_SPACE_MODE)
- cb->home_space = 1;
cb->int_requested = 1;
cb->pstate = 1;
cb->pstate_set_buf = 1;
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index aeed8a61fa0d..ffe1c53264a7 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -64,12 +64,6 @@
#include <asm/sclp.h>
#include "entry.h"
-long psw_kernel_bits = PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_PRIMARY |
- PSW_MASK_EA | PSW_MASK_BA;
-long psw_user_bits = PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT |
- PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_MCHECK |
- PSW_MASK_PSTATE | PSW_ASC_HOME;
-
/*
* User copy operations.
*/
@@ -300,43 +294,14 @@ static int __init parse_vmalloc(char *arg)
}
early_param("vmalloc", parse_vmalloc);
-unsigned int s390_user_mode = PRIMARY_SPACE_MODE;
-EXPORT_SYMBOL_GPL(s390_user_mode);
-
-static void __init set_user_mode_primary(void)
-{
- psw_kernel_bits = (psw_kernel_bits & ~PSW_MASK_ASC) | PSW_ASC_HOME;
- psw_user_bits = (psw_user_bits & ~PSW_MASK_ASC) | PSW_ASC_PRIMARY;
-#ifdef CONFIG_COMPAT
- psw32_user_bits =
- (psw32_user_bits & ~PSW32_MASK_ASC) | PSW32_ASC_PRIMARY;
-#endif
- uaccess = MACHINE_HAS_MVCOS ? uaccess_mvcos_switch : uaccess_pt;
-}
-
static int __init early_parse_user_mode(char *p)
{
- if (p && strcmp(p, "primary") == 0)
- s390_user_mode = PRIMARY_SPACE_MODE;
- else if (!p || strcmp(p, "home") == 0)
- s390_user_mode = HOME_SPACE_MODE;
- else
- return 1;
- return 0;
+ if (!p || strcmp(p, "primary") == 0)
+ return 0;
+ return 1;
}
early_param("user_mode", early_parse_user_mode);
-static void __init setup_addressing_mode(void)
-{
- if (s390_user_mode != PRIMARY_SPACE_MODE)
- return;
- set_user_mode_primary();
- if (MACHINE_HAS_MVCOS)
- pr_info("Address spaces switched, mvcos available\n");
- else
- pr_info("Address spaces switched, mvcos not available\n");
-}
-
void *restart_stack __attribute__((__section__(".data")));
static void __init setup_lowcore(void)
@@ -348,24 +313,24 @@ static void __init setup_lowcore(void)
*/
BUILD_BUG_ON(sizeof(struct _lowcore) != LC_PAGES * 4096);
lc = __alloc_bootmem_low(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0);
- lc->restart_psw.mask = psw_kernel_bits;
+ lc->restart_psw.mask = PSW_KERNEL_BITS;
lc->restart_psw.addr =
PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
- lc->external_new_psw.mask = psw_kernel_bits |
+ lc->external_new_psw.mask = PSW_KERNEL_BITS |
PSW_MASK_DAT | PSW_MASK_MCHECK;
lc->external_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) ext_int_handler;
- lc->svc_new_psw.mask = psw_kernel_bits |
+ lc->svc_new_psw.mask = PSW_KERNEL_BITS |
PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call;
- lc->program_new_psw.mask = psw_kernel_bits |
+ lc->program_new_psw.mask = PSW_KERNEL_BITS |
PSW_MASK_DAT | PSW_MASK_MCHECK;
lc->program_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) pgm_check_handler;
- lc->mcck_new_psw.mask = psw_kernel_bits;
+ lc->mcck_new_psw.mask = PSW_KERNEL_BITS;
lc->mcck_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
- lc->io_new_psw.mask = psw_kernel_bits |
+ lc->io_new_psw.mask = PSW_KERNEL_BITS |
PSW_MASK_DAT | PSW_MASK_MCHECK;
lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
lc->clock_comparator = -1ULL;
@@ -1043,10 +1008,7 @@ void __init setup_arch(char **cmdline_p)
init_mm.end_data = (unsigned long) &_edata;
init_mm.brk = (unsigned long) &_end;
- if (MACHINE_HAS_MVCOS)
- memcpy(&uaccess, &uaccess_mvcos, sizeof(uaccess));
- else
- memcpy(&uaccess, &uaccess_std, sizeof(uaccess));
+ uaccess = MACHINE_HAS_MVCOS ? uaccess_mvcos : uaccess_pt;
parse_early_param();
detect_memory_layout(memory_chunk, memory_end);
@@ -1054,7 +1016,6 @@ void __init setup_arch(char **cmdline_p)
setup_ipl();
reserve_oldmem();
setup_memory_end();
- setup_addressing_mode();
reserve_crashkernel();
setup_memory();
setup_resources();
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index c45becf82e01..b4fa7c0223e5 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -57,7 +57,7 @@ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
/* Copy a 'clean' PSW mask to the user to avoid leaking
information about whether PER is currently on. */
- user_sregs.regs.psw.mask = psw_user_bits |
+ user_sregs.regs.psw.mask = PSW_USER_BITS |
(regs->psw.mask & PSW_MASK_USER);
user_sregs.regs.psw.addr = regs->psw.addr;
memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs));
@@ -85,12 +85,12 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs));
if (err)
return err;
- /* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */
+ /* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */
regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
(user_sregs.regs.psw.mask & PSW_MASK_USER);
/* Check for invalid user address space control. */
- if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
- regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
+ if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_HOME)
+ regs->psw.mask = PSW_ASC_PRIMARY |
(regs->psw.mask & ~PSW_MASK_ASC);
/* Check for invalid amode */
if (regs->psw.mask & PSW_MASK_EA)
@@ -224,7 +224,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
regs->gprs[15] = (unsigned long) frame;
/* Force default amode and default user address space control. */
regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
- (psw_user_bits & PSW_MASK_ASC) |
+ (PSW_USER_BITS & PSW_MASK_ASC) |
(regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
@@ -295,7 +295,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->gprs[15] = (unsigned long) frame;
/* Force default amode and default user address space control. */
regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
- (psw_user_bits & PSW_MASK_ASC) |
+ (PSW_USER_BITS & PSW_MASK_ASC) |
(regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 1a4313a1b60f..cca6cf6abacc 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -283,7 +283,7 @@ static void pcpu_delegate(struct pcpu *pcpu, void (*func)(void *),
struct _lowcore *lc = lowcore_ptr[pcpu - pcpu_devices];
unsigned long source_cpu = stap();
- __load_psw_mask(psw_kernel_bits);
+ __load_psw_mask(PSW_KERNEL_BITS);
if (pcpu->address == source_cpu)
func(data); /* should not return */
/* Stop target cpu (if func returns this stops the current cpu). */
@@ -395,7 +395,7 @@ void smp_send_stop(void)
int cpu;
/* Disable all interrupts/machine checks */
- __load_psw_mask(psw_kernel_bits | PSW_MASK_DAT);
+ __load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_DAT);
trace_hardirqs_off();
debug_set_critical();
@@ -693,7 +693,7 @@ static void smp_start_secondary(void *cpuvoid)
S390_lowcore.restart_source = -1UL;
restore_access_regs(S390_lowcore.access_regs_save_area);
__ctl_load(S390_lowcore.cregs_save_area, 0, 15);
- __load_psw_mask(psw_kernel_bits | PSW_MASK_DAT);
+ __load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_DAT);
cpu_init();
preempt_disable();
init_cpu_timer();
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c
index 05d75c413137..a84476f2a9bb 100644
--- a/arch/s390/kernel/vdso.c
+++ b/arch/s390/kernel/vdso.c
@@ -84,8 +84,7 @@ struct vdso_data *vdso_data = &vdso_data_store.data;
*/
static void vdso_init_data(struct vdso_data *vd)
{
- vd->ectg_available =
- s390_user_mode != HOME_SPACE_MODE && test_facility(31);
+ vd->ectg_available = test_facility(31);
}
#ifdef CONFIG_64BIT
@@ -102,7 +101,7 @@ int vdso_alloc_per_cpu(struct _lowcore *lowcore)
lowcore->vdso_per_cpu_data = __LC_PASTE;
- if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled)
+ if (!vdso_enabled)
return 0;
segment_table = __get_free_pages(GFP_KERNEL, SEGMENT_ORDER);
@@ -147,7 +146,7 @@ void vdso_free_per_cpu(struct _lowcore *lowcore)
unsigned long segment_table, page_table, page_frame;
u32 *psal, *aste;
- if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled)
+ if (!vdso_enabled)
return;
psal = (u32 *)(addr_t) lowcore->paste[4];
@@ -165,7 +164,7 @@ static void vdso_init_cr5(void)
{
unsigned long cr5;
- if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled)
+ if (!vdso_enabled)
return;
cr5 = offsetof(struct _lowcore, paste);
__ctl_load(cr5, 5, 5);
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index abcfab55f99b..e312c48a1c40 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -161,7 +161,7 @@ void __kprobes vtime_stop_cpu(void)
trace_hardirqs_on();
/* Wait for external, I/O or machine check interrupt. */
- psw_mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_DAT |
+ psw_mask = PSW_KERNEL_BITS | PSW_MASK_WAIT | PSW_MASK_DAT |
PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
idle->nohz_delay = 0;
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c
index 3a74d8af0d69..78d967f180f4 100644
--- a/arch/s390/kvm/diag.c
+++ b/arch/s390/kvm/diag.c
@@ -107,14 +107,13 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu)
{
- int ret, idx;
+ int ret;
/* No virtio-ccw notification? Get out quickly. */
if (!vcpu->kvm->arch.css_support ||
(vcpu->run->s.regs.gprs[1] != KVM_S390_VIRTIO_CCW_NOTIFY))
return -EOPNOTSUPP;
- idx = srcu_read_lock(&vcpu->kvm->srcu);
/*
* The layout is as follows:
* - gpr 2 contains the subchannel id (passed as addr)
@@ -125,7 +124,6 @@ static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu)
vcpu->run->s.regs.gprs[2],
8, &vcpu->run->s.regs.gprs[3],
vcpu->run->s.regs.gprs[4]);
- srcu_read_unlock(&vcpu->kvm->srcu, idx);
/*
* Return cookie in gpr 2, but don't overwrite the register if the
diff --git a/arch/s390/kvm/gaccess.h b/arch/s390/kvm/gaccess.h
index 99d789e8a018..374a439ccc60 100644
--- a/arch/s390/kvm/gaccess.h
+++ b/arch/s390/kvm/gaccess.h
@@ -18,20 +18,27 @@
#include <asm/uaccess.h>
#include "kvm-s390.h"
+/* Convert real to absolute address by applying the prefix of the CPU */
+static inline unsigned long kvm_s390_real_to_abs(struct kvm_vcpu *vcpu,
+ unsigned long gaddr)
+{
+ unsigned long prefix = vcpu->arch.sie_block->prefix;
+ if (gaddr < 2 * PAGE_SIZE)
+ gaddr += prefix;
+ else if (gaddr >= prefix && gaddr < prefix + 2 * PAGE_SIZE)
+ gaddr -= prefix;
+ return gaddr;
+}
+
static inline void __user *__gptr_to_uptr(struct kvm_vcpu *vcpu,
void __user *gptr,
int prefixing)
{
- unsigned long prefix = vcpu->arch.sie_block->prefix;
unsigned long gaddr = (unsigned long) gptr;
unsigned long uaddr;
- if (prefixing) {
- if (gaddr < 2 * PAGE_SIZE)
- gaddr += prefix;
- else if ((gaddr >= prefix) && (gaddr < prefix + 2 * PAGE_SIZE))
- gaddr -= prefix;
- }
+ if (prefixing)
+ gaddr = kvm_s390_real_to_abs(vcpu, gaddr);
uaddr = gmap_fault(gaddr, vcpu->arch.gmap);
if (IS_ERR_VALUE(uaddr))
uaddr = -EFAULT;
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index 5ee56e5acc23..5ddbbde6f65c 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -62,12 +62,6 @@ static int handle_stop(struct kvm_vcpu *vcpu)
trace_kvm_s390_stop_request(vcpu->arch.local_int.action_bits);
- if (vcpu->arch.local_int.action_bits & ACTION_RELOADVCPU_ON_STOP) {
- vcpu->arch.local_int.action_bits &= ~ACTION_RELOADVCPU_ON_STOP;
- rc = SIE_INTERCEPT_RERUNVCPU;
- vcpu->run->exit_reason = KVM_EXIT_INTR;
- }
-
if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) {
atomic_set_mask(CPUSTAT_STOPPED,
&vcpu->arch.sie_block->cpuflags);
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 7f35cb33e510..e7323cd9f109 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -436,6 +436,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL);
VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime);
no_timer:
+ srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
spin_lock(&vcpu->arch.local_int.float_int->lock);
spin_lock_bh(&vcpu->arch.local_int.lock);
add_wait_queue(&vcpu->wq, &wait);
@@ -455,6 +456,8 @@ no_timer:
remove_wait_queue(&vcpu->wq, &wait);
spin_unlock_bh(&vcpu->arch.local_int.lock);
spin_unlock(&vcpu->arch.local_int.float_int->lock);
+ vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
+
hrtimer_try_to_cancel(&vcpu->arch.ckc_timer);
return 0;
}
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 776dafe918db..1e4e7b97337a 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -689,9 +689,9 @@ static int kvm_s390_handle_requests(struct kvm_vcpu *vcpu)
return 0;
}
-static int __vcpu_run(struct kvm_vcpu *vcpu)
+static int vcpu_pre_run(struct kvm_vcpu *vcpu)
{
- int rc;
+ int rc, cpuflags;
memcpy(&vcpu->arch.sie_block->gg14, &vcpu->run->s.regs.gprs[14], 16);
@@ -709,28 +709,24 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
return rc;
vcpu->arch.sie_block->icptcode = 0;
- VCPU_EVENT(vcpu, 6, "entering sie flags %x",
- atomic_read(&vcpu->arch.sie_block->cpuflags));
- trace_kvm_s390_sie_enter(vcpu,
- atomic_read(&vcpu->arch.sie_block->cpuflags));
+ cpuflags = atomic_read(&vcpu->arch.sie_block->cpuflags);
+ VCPU_EVENT(vcpu, 6, "entering sie flags %x", cpuflags);
+ trace_kvm_s390_sie_enter(vcpu, cpuflags);
- /*
- * As PF_VCPU will be used in fault handler, between guest_enter
- * and guest_exit should be no uaccess.
- */
- preempt_disable();
- kvm_guest_enter();
- preempt_enable();
- rc = sie64a(vcpu->arch.sie_block, vcpu->run->s.regs.gprs);
- kvm_guest_exit();
+ return 0;
+}
+
+static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)
+{
+ int rc;
VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
vcpu->arch.sie_block->icptcode);
trace_kvm_s390_sie_exit(vcpu, vcpu->arch.sie_block->icptcode);
- if (rc > 0)
+ if (exit_reason >= 0) {
rc = 0;
- if (rc < 0) {
+ } else {
if (kvm_is_ucontrol(vcpu->kvm)) {
rc = SIE_INTERCEPT_UCONTROL;
} else {
@@ -741,6 +737,49 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
}
memcpy(&vcpu->run->s.regs.gprs[14], &vcpu->arch.sie_block->gg14, 16);
+
+ if (rc == 0) {
+ if (kvm_is_ucontrol(vcpu->kvm))
+ rc = -EOPNOTSUPP;
+ else
+ rc = kvm_handle_sie_intercept(vcpu);
+ }
+
+ return rc;
+}
+
+static int __vcpu_run(struct kvm_vcpu *vcpu)
+{
+ int rc, exit_reason;
+
+ /*
+ * We try to hold kvm->srcu during most of vcpu_run (except when run-
+ * ning the guest), so that memslots (and other stuff) are protected
+ */
+ vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
+
+ do {
+ rc = vcpu_pre_run(vcpu);
+ if (rc)
+ break;
+
+ srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
+ /*
+ * As PF_VCPU will be used in fault handler, between
+ * guest_enter and guest_exit should be no uaccess.
+ */
+ preempt_disable();
+ kvm_guest_enter();
+ preempt_enable();
+ exit_reason = sie64a(vcpu->arch.sie_block,
+ vcpu->run->s.regs.gprs);
+ kvm_guest_exit();
+ vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
+
+ rc = vcpu_post_run(vcpu, exit_reason);
+ } while (!signal_pending(current) && !rc);
+
+ srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
return rc;
}
@@ -749,7 +788,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
int rc;
sigset_t sigsaved;
-rerun_vcpu:
if (vcpu->sigset_active)
sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
@@ -782,19 +820,7 @@ rerun_vcpu:
}
might_fault();
-
- do {
- rc = __vcpu_run(vcpu);
- if (rc)
- break;
- if (kvm_is_ucontrol(vcpu->kvm))
- rc = -EOPNOTSUPP;
- else
- rc = kvm_handle_sie_intercept(vcpu);
- } while (!signal_pending(current) && !rc);
-
- if (rc == SIE_INTERCEPT_RERUNVCPU)
- goto rerun_vcpu;
+ rc = __vcpu_run(vcpu);
if (signal_pending(current) && !rc) {
kvm_run->exit_reason = KVM_EXIT_INTR;
@@ -951,6 +977,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
{
struct kvm_vcpu *vcpu = filp->private_data;
void __user *argp = (void __user *)arg;
+ int idx;
long r;
switch (ioctl) {
@@ -964,7 +991,9 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
break;
}
case KVM_S390_STORE_STATUS:
+ idx = srcu_read_lock(&vcpu->kvm->srcu);
r = kvm_s390_vcpu_store_status(vcpu, arg);
+ srcu_read_unlock(&vcpu->kvm->srcu, idx);
break;
case KVM_S390_SET_INITIAL_PSW: {
psw_t psw;
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index dc99f1ca4267..b44912a32949 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -28,8 +28,7 @@ typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu);
extern unsigned long *vfacilities;
/* negativ values are error codes, positive values for internal conditions */
-#define SIE_INTERCEPT_RERUNVCPU (1<<0)
-#define SIE_INTERCEPT_UCONTROL (1<<1)
+#define SIE_INTERCEPT_UCONTROL (1<<0)
int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu);
#define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\
@@ -91,8 +90,10 @@ static inline void kvm_s390_get_base_disp_sse(struct kvm_vcpu *vcpu,
static inline void kvm_s390_get_regs_rre(struct kvm_vcpu *vcpu, int *r1, int *r2)
{
- *r1 = (vcpu->arch.sie_block->ipb & 0x00f00000) >> 20;
- *r2 = (vcpu->arch.sie_block->ipb & 0x000f0000) >> 16;
+ if (r1)
+ *r1 = (vcpu->arch.sie_block->ipb & 0x00f00000) >> 20;
+ if (r2)
+ *r2 = (vcpu->arch.sie_block->ipb & 0x000f0000) >> 16;
}
static inline u64 kvm_s390_get_base_disp_rsy(struct kvm_vcpu *vcpu)
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 59200ee275e5..2440602e6df1 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -30,6 +30,38 @@
#include "kvm-s390.h"
#include "trace.h"
+/* Handle SCK (SET CLOCK) interception */
+static int handle_set_clock(struct kvm_vcpu *vcpu)
+{
+ struct kvm_vcpu *cpup;
+ s64 hostclk, val;
+ u64 op2;
+ int i;
+
+ if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
+ return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
+
+ op2 = kvm_s390_get_base_disp_s(vcpu);
+ if (op2 & 7) /* Operand must be on a doubleword boundary */
+ return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
+ if (get_guest(vcpu, val, (u64 __user *) op2))
+ return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+
+ if (store_tod_clock(&hostclk)) {
+ kvm_s390_set_psw_cc(vcpu, 3);
+ return 0;
+ }
+ val = (val - hostclk) & ~0x3fUL;
+
+ mutex_lock(&vcpu->kvm->lock);
+ kvm_for_each_vcpu(i, cpup, vcpu->kvm)
+ cpup->arch.sie_block->epoch = val;
+ mutex_unlock(&vcpu->kvm->lock);
+
+ kvm_s390_set_psw_cc(vcpu, 0);
+ return 0;
+}
+
static int handle_set_prefix(struct kvm_vcpu *vcpu)
{
u64 operand2;
@@ -128,6 +160,33 @@ static int handle_skey(struct kvm_vcpu *vcpu)
return 0;
}
+static int handle_test_block(struct kvm_vcpu *vcpu)
+{
+ unsigned long hva;
+ gpa_t addr;
+ int reg2;
+
+ if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
+ return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
+
+ kvm_s390_get_regs_rre(vcpu, NULL, &reg2);
+ addr = vcpu->run->s.regs.gprs[reg2] & PAGE_MASK;
+ addr = kvm_s390_real_to_abs(vcpu, addr);
+
+ hva = gfn_to_hva(vcpu->kvm, gpa_to_gfn(addr));
+ if (kvm_is_error_hva(hva))
+ return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+ /*
+ * We don't expect errors on modern systems, and do not care
+ * about storage keys (yet), so let's just clear the page.
+ */
+ if (clear_user((void __user *)hva, PAGE_SIZE) != 0)
+ return -EFAULT;
+ kvm_s390_set_psw_cc(vcpu, 0);
+ vcpu->run->s.regs.gprs[0] = 0;
+ return 0;
+}
+
static int handle_tpi(struct kvm_vcpu *vcpu)
{
struct kvm_s390_interrupt_info *inti;
@@ -438,12 +497,14 @@ out_exception:
static const intercept_handler_t b2_handlers[256] = {
[0x02] = handle_stidp,
+ [0x04] = handle_set_clock,
[0x10] = handle_set_prefix,
[0x11] = handle_store_prefix,
[0x12] = handle_store_cpu_address,
[0x29] = handle_skey,
[0x2a] = handle_skey,
[0x2b] = handle_skey,
+ [0x2c] = handle_test_block,
[0x30] = handle_io_inst,
[0x31] = handle_io_inst,
[0x32] = handle_io_inst,
diff --git a/arch/s390/kvm/trace.h b/arch/s390/kvm/trace.h
index c2f582bb1cb2..0c991c6748ab 100644
--- a/arch/s390/kvm/trace.h
+++ b/arch/s390/kvm/trace.h
@@ -4,6 +4,7 @@
#include <linux/tracepoint.h>
#include <asm/sigp.h>
#include <asm/debug.h>
+#include <asm/dis.h>
#undef TRACE_SYSTEM
#define TRACE_SYSTEM kvm
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index 20b0e97a7df2..b068729e50ac 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -2,7 +2,7 @@
# Makefile for s390-specific library files..
#
-lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
+lib-y += delay.o string.o uaccess_pt.o find.o
obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o mem32.o
obj-$(CONFIG_64BIT) += mem64.o
lib-$(CONFIG_64BIT) += uaccess_mvcos.o
diff --git a/arch/s390/lib/find.c b/arch/s390/lib/find.c
new file mode 100644
index 000000000000..620d34d6487e
--- /dev/null
+++ b/arch/s390/lib/find.c
@@ -0,0 +1,77 @@
+/*
+ * MSB0 numbered special bitops handling.
+ *
+ * On s390x the bits are numbered:
+ * |0..............63|64............127|128...........191|192...........255|
+ * and on s390:
+ * |0.....31|31....63|64....95|96...127|128..159|160..191|192..223|224..255|
+ *
+ * The reason for this bit numbering is the fact that the hardware sets bits
+ * in a bitmap starting at bit 0 (MSB) and we don't want to scan the bitmap
+ * from the 'wrong end'.
+ */
+
+#include <linux/compiler.h>
+#include <linux/bitops.h>
+#include <linux/export.h>
+
+unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size)
+{
+ const unsigned long *p = addr;
+ unsigned long result = 0;
+ unsigned long tmp;
+
+ while (size & ~(BITS_PER_LONG - 1)) {
+ if ((tmp = *(p++)))
+ goto found;
+ result += BITS_PER_LONG;
+ size -= BITS_PER_LONG;
+ }
+ if (!size)
+ return result;
+ tmp = (*p) & (~0UL << (BITS_PER_LONG - size));
+ if (!tmp) /* Are any bits set? */
+ return result + size; /* Nope. */
+found:
+ return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
+}
+EXPORT_SYMBOL(find_first_bit_inv);
+
+unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size,
+ unsigned long offset)
+{
+ const unsigned long *p = addr + (offset / BITS_PER_LONG);
+ unsigned long result = offset & ~(BITS_PER_LONG - 1);
+ unsigned long tmp;
+
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset %= BITS_PER_LONG;
+ if (offset) {
+ tmp = *(p++);
+ tmp &= (~0UL >> offset);
+ if (size < BITS_PER_LONG)
+ goto found_first;
+ if (tmp)
+ goto found_middle;
+ size -= BITS_PER_LONG;
+ result += BITS_PER_LONG;
+ }
+ while (size & ~(BITS_PER_LONG-1)) {
+ if ((tmp = *(p++)))
+ goto found_middle;
+ result += BITS_PER_LONG;
+ size -= BITS_PER_LONG;
+ }
+ if (!size)
+ return result;
+ tmp = *p;
+found_first:
+ tmp &= (~0UL << (BITS_PER_LONG - size));
+ if (!tmp) /* Are any bits set? */
+ return result + size; /* Nope. */
+found_middle:
+ return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
+}
+EXPORT_SYMBOL(find_next_bit_inv);
diff --git a/arch/s390/lib/uaccess_mvcos.c b/arch/s390/lib/uaccess_mvcos.c
index 1829742bf479..4b7993bf69b9 100644
--- a/arch/s390/lib/uaccess_mvcos.c
+++ b/arch/s390/lib/uaccess_mvcos.c
@@ -65,13 +65,6 @@ static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
return size;
}
-static size_t copy_from_user_mvcos_check(size_t size, const void __user *ptr, void *x)
-{
- if (size <= 256)
- return copy_from_user_std(size, ptr, x);
- return copy_from_user_mvcos(size, ptr, x);
-}
-
static size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
{
register unsigned long reg0 asm("0") = 0x810000UL;
@@ -101,14 +94,6 @@ static size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
return size;
}
-static size_t copy_to_user_mvcos_check(size_t size, void __user *ptr,
- const void *x)
-{
- if (size <= 256)
- return copy_to_user_std(size, ptr, x);
- return copy_to_user_mvcos(size, ptr, x);
-}
-
static size_t copy_in_user_mvcos(size_t size, void __user *to,
const void __user *from)
{
@@ -201,23 +186,8 @@ static size_t strncpy_from_user_mvcos(size_t count, const char __user *src,
}
struct uaccess_ops uaccess_mvcos = {
- .copy_from_user = copy_from_user_mvcos_check,
- .copy_from_user_small = copy_from_user_std,
- .copy_to_user = copy_to_user_mvcos_check,
- .copy_to_user_small = copy_to_user_std,
- .copy_in_user = copy_in_user_mvcos,
- .clear_user = clear_user_mvcos,
- .strnlen_user = strnlen_user_std,
- .strncpy_from_user = strncpy_from_user_std,
- .futex_atomic_op = futex_atomic_op_std,
- .futex_atomic_cmpxchg = futex_atomic_cmpxchg_std,
-};
-
-struct uaccess_ops uaccess_mvcos_switch = {
.copy_from_user = copy_from_user_mvcos,
- .copy_from_user_small = copy_from_user_mvcos,
.copy_to_user = copy_to_user_mvcos,
- .copy_to_user_small = copy_to_user_mvcos,
.copy_in_user = copy_in_user_mvcos,
.clear_user = clear_user_mvcos,
.strnlen_user = strnlen_user_mvcos,
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 1694d738b175..97e03caf7825 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -461,9 +461,7 @@ int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
struct uaccess_ops uaccess_pt = {
.copy_from_user = copy_from_user_pt,
- .copy_from_user_small = copy_from_user_pt,
.copy_to_user = copy_to_user_pt,
- .copy_to_user_small = copy_to_user_pt,
.copy_in_user = copy_in_user_pt,
.clear_user = clear_user_pt,
.strnlen_user = strnlen_user_pt,
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
deleted file mode 100644
index 4a75d475b06a..000000000000
--- a/arch/s390/lib/uaccess_std.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Standard user space access functions based on mvcp/mvcs and doing
- * interesting things in the secondary space mode.
- *
- * Copyright IBM Corp. 2006
- * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
- * Gerald Schaefer (gerald.schaefer@de.ibm.com)
- */
-
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/uaccess.h>
-#include <asm/futex.h>
-#include "uaccess.h"
-
-#ifndef CONFIG_64BIT
-#define AHI "ahi"
-#define ALR "alr"
-#define CLR "clr"
-#define LHI "lhi"
-#define SLR "slr"
-#else
-#define AHI "aghi"
-#define ALR "algr"
-#define CLR "clgr"
-#define LHI "lghi"
-#define SLR "slgr"
-#endif
-
-size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
-{
- unsigned long tmp1, tmp2;
-
- tmp1 = -256UL;
- asm volatile(
- "0: mvcp 0(%0,%2),0(%1),%3\n"
- "10:jz 8f\n"
- "1:"ALR" %0,%3\n"
- " la %1,256(%1)\n"
- " la %2,256(%2)\n"
- "2: mvcp 0(%0,%2),0(%1),%3\n"
- "11:jnz 1b\n"
- " j 8f\n"
- "3: la %4,255(%1)\n" /* %4 = ptr + 255 */
- " "LHI" %3,-4096\n"
- " nr %4,%3\n" /* %4 = (ptr + 255) & -4096 */
- " "SLR" %4,%1\n"
- " "CLR" %0,%4\n" /* copy crosses next page boundary? */
- " jnh 5f\n"
- "4: mvcp 0(%4,%2),0(%1),%3\n"
- "12:"SLR" %0,%4\n"
- " "ALR" %2,%4\n"
- "5:"LHI" %4,-1\n"
- " "ALR" %4,%0\n" /* copy remaining size, subtract 1 */
- " bras %3,7f\n" /* memset loop */
- " xc 0(1,%2),0(%2)\n"
- "6: xc 0(256,%2),0(%2)\n"
- " la %2,256(%2)\n"
- "7:"AHI" %4,-256\n"
- " jnm 6b\n"
- " ex %4,0(%3)\n"
- " j 9f\n"
- "8:"SLR" %0,%0\n"
- "9: \n"
- EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,5b)
- EX_TABLE(10b,3b) EX_TABLE(11b,3b) EX_TABLE(12b,5b)
- : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
- : : "cc", "memory");
- return size;
-}
-
-static size_t copy_from_user_std_check(size_t size, const void __user *ptr,
- void *x)
-{
- if (size <= 1024)
- return copy_from_user_std(size, ptr, x);
- return copy_from_user_pt(size, ptr, x);
-}
-
-size_t copy_to_user_std(size_t size, void __user *ptr, const void *x)
-{
- unsigned long tmp1, tmp2;
-
- tmp1 = -256UL;
- asm volatile(
- "0: mvcs 0(%0,%1),0(%2),%3\n"
- "7: jz 5f\n"
- "1:"ALR" %0,%3\n"
- " la %1,256(%1)\n"
- " la %2,256(%2)\n"
- "2: mvcs 0(%0,%1),0(%2),%3\n"
- "8: jnz 1b\n"
- " j 5f\n"
- "3: la %4,255(%1)\n" /* %4 = ptr + 255 */
- " "LHI" %3,-4096\n"
- " nr %4,%3\n" /* %4 = (ptr + 255) & -4096 */
- " "SLR" %4,%1\n"
- " "CLR" %0,%4\n" /* copy crosses next page boundary? */
- " jnh 6f\n"
- "4: mvcs 0(%4,%1),0(%2),%3\n"
- "9:"SLR" %0,%4\n"
- " j 6f\n"
- "5:"SLR" %0,%0\n"
- "6: \n"
- EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,6b)
- EX_TABLE(7b,3b) EX_TABLE(8b,3b) EX_TABLE(9b,6b)
- : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
- : : "cc", "memory");
- return size;
-}
-
-static size_t copy_to_user_std_check(size_t size, void __user *ptr,
- const void *x)
-{
- if (size <= 1024)
- return copy_to_user_std(size, ptr, x);
- return copy_to_user_pt(size, ptr, x);
-}
-
-static size_t copy_in_user_std(size_t size, void __user *to,
- const void __user *from)
-{
- unsigned long tmp1;
-
- asm volatile(
- " sacf 256\n"
- " "AHI" %0,-1\n"
- " jo 5f\n"
- " bras %3,3f\n"
- "0:"AHI" %0,257\n"
- "1: mvc 0(1,%1),0(%2)\n"
- " la %1,1(%1)\n"
- " la %2,1(%2)\n"
- " "AHI" %0,-1\n"
- " jnz 1b\n"
- " j 5f\n"
- "2: mvc 0(256,%1),0(%2)\n"
- " la %1,256(%1)\n"
- " la %2,256(%2)\n"
- "3:"AHI" %0,-256\n"
- " jnm 2b\n"
- "4: ex %0,1b-0b(%3)\n"
- "5: "SLR" %0,%0\n"
- "6: sacf 0\n"
- EX_TABLE(1b,6b) EX_TABLE(2b,0b) EX_TABLE(4b,0b)
- : "+a" (size), "+a" (to), "+a" (from), "=a" (tmp1)
- : : "cc", "memory");
- return size;
-}
-
-static size_t clear_user_std(size_t size, void __user *to)
-{
- unsigned long tmp1, tmp2;
-
- asm volatile(
- " sacf 256\n"
- " "AHI" %0,-1\n"
- " jo 5f\n"
- " bras %3,3f\n"
- " xc 0(1,%1),0(%1)\n"
- "0:"AHI" %0,257\n"
- " la %2,255(%1)\n" /* %2 = ptr + 255 */
- " srl %2,12\n"
- " sll %2,12\n" /* %2 = (ptr + 255) & -4096 */
- " "SLR" %2,%1\n"
- " "CLR" %0,%2\n" /* clear crosses next page boundary? */
- " jnh 5f\n"
- " "AHI" %2,-1\n"
- "1: ex %2,0(%3)\n"
- " "AHI" %2,1\n"
- " "SLR" %0,%2\n"
- " j 5f\n"
- "2: xc 0(256,%1),0(%1)\n"
- " la %1,256(%1)\n"
- "3:"AHI" %0,-256\n"
- " jnm 2b\n"
- "4: ex %0,0(%3)\n"
- "5: "SLR" %0,%0\n"
- "6: sacf 0\n"
- EX_TABLE(1b,6b) EX_TABLE(2b,0b) EX_TABLE(4b,0b)
- : "+a" (size), "+a" (to), "=a" (tmp1), "=a" (tmp2)
- : : "cc", "memory");
- return size;
-}
-
-size_t strnlen_user_std(size_t size, const char __user *src)
-{
- register unsigned long reg0 asm("0") = 0UL;
- unsigned long tmp1, tmp2;
-
- if (unlikely(!size))
- return 0;
- asm volatile(
- " la %2,0(%1)\n"
- " la %3,0(%0,%1)\n"
- " "SLR" %0,%0\n"
- " sacf 256\n"
- "0: srst %3,%2\n"
- " jo 0b\n"
- " la %0,1(%3)\n" /* strnlen_user results includes \0 */
- " "SLR" %0,%1\n"
- "1: sacf 0\n"
- EX_TABLE(0b,1b)
- : "+a" (size), "+a" (src), "=a" (tmp1), "=a" (tmp2)
- : "d" (reg0) : "cc", "memory");
- return size;
-}
-
-size_t strncpy_from_user_std(size_t count, const char __user *src, char *dst)
-{
- size_t done, len, offset, len_str;
-
- if (unlikely(!count))
- return 0;
- done = 0;
- do {
- offset = (size_t)src & ~PAGE_MASK;
- len = min(count - done, PAGE_SIZE - offset);
- if (copy_from_user_std(len, src, dst))
- return -EFAULT;
- len_str = strnlen(dst, len);
- done += len_str;
- src += len_str;
- dst += len_str;
- } while ((len_str == len) && (done < count));
- return done;
-}
-
-#define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg) \
- asm volatile( \
- " sacf 256\n" \
- "0: l %1,0(%6)\n" \
- "1:"insn \
- "2: cs %1,%2,0(%6)\n" \
- "3: jl 1b\n" \
- " lhi %0,0\n" \
- "4: sacf 0\n" \
- EX_TABLE(0b,4b) EX_TABLE(2b,4b) EX_TABLE(3b,4b) \
- : "=d" (ret), "=&d" (oldval), "=&d" (newval), \
- "=m" (*uaddr) \
- : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \
- "m" (*uaddr) : "cc");
-
-int futex_atomic_op_std(int op, u32 __user *uaddr, int oparg, int *old)
-{
- int oldval = 0, newval, ret;
-
- switch (op) {
- case FUTEX_OP_SET:
- __futex_atomic_op("lr %2,%5\n",
- ret, oldval, newval, uaddr, oparg);
- break;
- case FUTEX_OP_ADD:
- __futex_atomic_op("lr %2,%1\nar %2,%5\n",
- ret, oldval, newval, uaddr, oparg);
- break;
- case FUTEX_OP_OR:
- __futex_atomic_op("lr %2,%1\nor %2,%5\n",
- ret, oldval, newval, uaddr, oparg);
- break;
- case FUTEX_OP_ANDN:
- __futex_atomic_op("lr %2,%1\nnr %2,%5\n",
- ret, oldval, newval, uaddr, oparg);
- break;
- case FUTEX_OP_XOR:
- __futex_atomic_op("lr %2,%1\nxr %2,%5\n",
- ret, oldval, newval, uaddr, oparg);
- break;
- default:
- ret = -ENOSYS;
- }
- *old = oldval;
- return ret;
-}
-
-int futex_atomic_cmpxchg_std(u32 *uval, u32 __user *uaddr,
- u32 oldval, u32 newval)
-{
- int ret;
-
- asm volatile(
- " sacf 256\n"
- "0: cs %1,%4,0(%5)\n"
- "1: la %0,0\n"
- "2: sacf 0\n"
- EX_TABLE(0b,2b) EX_TABLE(1b,2b)
- : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
- : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
- : "cc", "memory" );
- *uval = oldval;
- return ret;
-}
-
-struct uaccess_ops uaccess_std = {
- .copy_from_user = copy_from_user_std_check,
- .copy_from_user_small = copy_from_user_std,
- .copy_to_user = copy_to_user_std_check,
- .copy_to_user_small = copy_to_user_std,
- .copy_in_user = copy_in_user_std,
- .clear_user = clear_user_std,
- .strnlen_user = strnlen_user_std,
- .strncpy_from_user = strncpy_from_user_std,
- .futex_atomic_op = futex_atomic_op_std,
- .futex_atomic_cmpxchg = futex_atomic_cmpxchg_std,
-};
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index fc6679210d83..8f29762671cf 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -115,13 +115,8 @@ static inline int user_space_fault(unsigned long trans_exc_code)
if (trans_exc_code == 2)
/* Access via secondary space, set_fs setting decides */
return current->thread.mm_segment.ar4;
- if (s390_user_mode == HOME_SPACE_MODE)
- /* User space if the access has been done via home space. */
- return trans_exc_code == 3;
/*
- * If the user space is not the home space the kernel runs in home
- * space. Access via secondary space has already been covered,
- * access via primary space or access register is from user space
+ * Access via primary space or access register is from user space
* and access via home space is from the kernel.
*/
return trans_exc_code != 3;
@@ -471,7 +466,7 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write)
int access, fault;
/* Emulate a uaccess fault from kernel mode. */
- regs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK;
+ regs.psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT | PSW_MASK_MCHECK;
if (!irqs_disabled())
regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT;
regs.psw.addr = (unsigned long) __builtin_return_address(0);
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index de8cbc30dcd1..94f37a9fb1e5 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -1157,10 +1157,6 @@ int s390_enable_sie(void)
struct mm_struct *mm = tsk->mm;
struct mmu_gather tlb;
- /* Do we have switched amode? If no, we cannot do sie */
- if (s390_user_mode == HOME_SPACE_MODE)
- return -EINVAL;
-
/* Do we have pgstes? if yes, we are done */
if (mm_has_pgste(tsk->mm))
return 0;
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 709239285869..b3444b44c4e6 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -12,8 +12,8 @@
#include <linux/random.h>
#include <linux/init.h>
#include <asm/cacheflush.h>
-#include <asm/processor.h>
#include <asm/facility.h>
+#include <asm/dis.h>
/*
* Conventions:
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index e1c7bb999b06..f3414ade77a3 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -4,3 +4,4 @@ header-y +=
generic-y += clkdev.h
generic-y += trace_clock.h
generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 1fa8be409771..122f737a901f 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -15,6 +15,7 @@
#include <linux/mmc/sh_mmcif.h>
#include <linux/mmc/sh_mobile_sdhi.h>
#include <linux/mtd/physmap.h>
+#include <linux/mfd/tmio.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/io.h>
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 280bea9e5e2b..231efbb68108 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += termios.h
generic-y += trace_clock.h
generic-y += ucontext.h
generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/sh/include/asm/hw_breakpoint.h b/arch/sh/include/asm/hw_breakpoint.h
index ec9ad593c3da..01a38696137e 100644
--- a/arch/sh/include/asm/hw_breakpoint.h
+++ b/arch/sh/include/asm/hw_breakpoint.h
@@ -7,6 +7,7 @@
#include <linux/kdebug.h>
#include <linux/types.h>
+#include <cpu/ubc.h>
struct arch_hw_breakpoint {
char *name; /* Contains name of the symbol to set bkpt */
@@ -15,17 +16,6 @@ struct arch_hw_breakpoint {
u16 type;
};
-enum {
- SH_BREAKPOINT_READ = (1 << 1),
- SH_BREAKPOINT_WRITE = (1 << 2),
- SH_BREAKPOINT_RW = SH_BREAKPOINT_READ | SH_BREAKPOINT_WRITE,
-
- SH_BREAKPOINT_LEN_1 = (1 << 12),
- SH_BREAKPOINT_LEN_2 = (1 << 13),
- SH_BREAKPOINT_LEN_4 = SH_BREAKPOINT_LEN_1 | SH_BREAKPOINT_LEN_2,
- SH_BREAKPOINT_LEN_8 = (1 << 14),
-};
-
struct sh_ubc {
const char *name;
unsigned int num_events;
diff --git a/arch/sh/include/cpu-common/cpu/ubc.h b/arch/sh/include/cpu-common/cpu/ubc.h
new file mode 100644
index 000000000000..b60461930a32
--- /dev/null
+++ b/arch/sh/include/cpu-common/cpu/ubc.h
@@ -0,0 +1,17 @@
+#ifndef __ARCH_SH_CPU_UBC_H__
+#define __ARCH_SH_CPU_UBC_H__
+
+enum {
+ SH_BREAKPOINT_READ = (1 << 1),
+ SH_BREAKPOINT_WRITE = (1 << 2),
+ SH_BREAKPOINT_RW = SH_BREAKPOINT_READ | SH_BREAKPOINT_WRITE,
+
+ SH_BREAKPOINT_LEN_1 = (1 << 12),
+ SH_BREAKPOINT_LEN_2 = (1 << 13),
+ SH_BREAKPOINT_LEN_4 = SH_BREAKPOINT_LEN_1 | SH_BREAKPOINT_LEN_2,
+ SH_BREAKPOINT_LEN_8 = (1 << 14),
+};
+
+#define UBC_64BIT 1
+
+#endif /* __ARCH_SH_CPU_UBC_H__ */
diff --git a/arch/sh/include/cpu-sh2a/cpu/ubc.h b/arch/sh/include/cpu-sh2a/cpu/ubc.h
new file mode 100644
index 000000000000..3371f9042184
--- /dev/null
+++ b/arch/sh/include/cpu-sh2a/cpu/ubc.h
@@ -0,0 +1,14 @@
+#ifndef __ARCH_SH_CPU_UBC_H__
+#define __ARCH_SH_CPU_UBC_H__
+
+enum {
+ SH_BREAKPOINT_READ = (1 << 2),
+ SH_BREAKPOINT_WRITE = (1 << 3),
+ SH_BREAKPOINT_RW = SH_BREAKPOINT_READ | SH_BREAKPOINT_WRITE,
+
+ SH_BREAKPOINT_LEN_1 = (1 << 0),
+ SH_BREAKPOINT_LEN_2 = (1 << 1),
+ SH_BREAKPOINT_LEN_4 = SH_BREAKPOINT_LEN_1 | SH_BREAKPOINT_LEN_2,
+};
+
+#endif /* __ARCH_SH_CPU_UBC_H__ */
diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile
index 990195d98456..92f0da4c86a7 100644
--- a/arch/sh/kernel/cpu/sh2a/Makefile
+++ b/arch/sh/kernel/cpu/sh2a/Makefile
@@ -22,3 +22,4 @@ pinmux-$(CONFIG_CPU_SUBTYPE_SH7264) := pinmux-sh7264.o
pinmux-$(CONFIG_CPU_SUBTYPE_SH7269) := pinmux-sh7269.o
obj-$(CONFIG_GPIOLIB) += $(pinmux-y)
+obj-$(CONFIG_HAVE_HW_BREAKPOINT) += ubc.o
diff --git a/arch/sh/kernel/cpu/sh2a/ubc.c b/arch/sh/kernel/cpu/sh2a/ubc.c
new file mode 100644
index 000000000000..ef95a9b483e4
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/ubc.c
@@ -0,0 +1,154 @@
+/*
+ * arch/sh/kernel/cpu/sh2a/ubc.c
+ *
+ * On-chip UBC support for SH-2A CPUs.
+ *
+ * Copyright (C) 2009 - 2010 Paul Mundt
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <asm/hw_breakpoint.h>
+
+#define UBC_BAR(idx) (0xfffc0400 + (0x10 * idx))
+#define UBC_BAMR(idx) (0xfffc0404 + (0x10 * idx))
+#define UBC_BBR(idx) (0xfffc04A0 + (0x10 * idx))
+#define UBC_BDR(idx) (0xfffc0408 + (0x10 * idx))
+#define UBC_BDMR(idx) (0xfffc040C + (0x10 * idx))
+
+#define UBC_BRCR 0xfffc04C0
+
+/* BBR */
+#define UBC_BBR_UBID (1 << 13) /* User Break Interrupt Disable */
+#define UBC_BBR_DBE (1 << 12) /* Data Break Enable */
+#define UBC_BBR_CD_C (1 << 6) /* C Bus Cycle */
+#define UBC_BBR_CD_I (2 << 6) /* I Bus Cycle */
+#define UBC_BBR_ID_I (1 << 4) /* Break Condition is instruction fetch cycle */
+#define UBC_BBR_ID_D (2 << 4) /* Break Condition is data access cycle */
+#define UBC_BBR_ID_ID (3 << 4) /* Break Condition is instruction fetch or data access cycle */
+
+#define UBC_CRR_BIE (1 << 0)
+
+/* CBR */
+#define UBC_CBR_CE (1 << 0)
+
+static struct sh_ubc sh2a_ubc;
+
+static void sh2a_ubc_enable(struct arch_hw_breakpoint *info, int idx)
+{
+ __raw_writel(UBC_BBR_DBE | UBC_BBR_CD_C | UBC_BBR_ID_ID |
+ info->len | info->type, UBC_BBR(idx));
+ __raw_writel(info->address, UBC_BAR(idx));
+}
+
+static void sh2a_ubc_disable(struct arch_hw_breakpoint *info, int idx)
+{
+ __raw_writel(UBC_BBR_UBID, UBC_BBR(idx));
+ __raw_writel(0, UBC_BAR(idx));
+}
+
+static void sh2a_ubc_enable_all(unsigned long mask)
+{
+ int i;
+
+ for (i = 0; i < sh2a_ubc.num_events; i++)
+ if (mask & (1 << i))
+ __raw_writel(__raw_readl(UBC_BBR(i)) & ~UBC_BBR_UBID,
+ UBC_BBR(i));
+}
+
+static void sh2a_ubc_disable_all(void)
+{
+ int i;
+
+ for (i = 0; i < sh2a_ubc.num_events; i++)
+ __raw_writel(__raw_readl(UBC_BBR(i)) | UBC_BBR_UBID,
+ UBC_BBR(i));
+}
+
+static unsigned long sh2a_ubc_active_mask(void)
+{
+ unsigned long active = 0;
+ int i;
+
+ for (i = 0; i < sh2a_ubc.num_events; i++)
+ if (!(__raw_readl(UBC_BBR(i)) & UBC_BBR_UBID))
+ active |= (1 << i);
+
+ return active;
+}
+
+static unsigned long sh2a_ubc_triggered_mask(void)
+{
+ unsigned int ret, mask;
+
+ mask = 0;
+ ret = __raw_readl(UBC_BRCR);
+ if ((ret & (1 << 15)) || (ret & (1 << 13))) {
+ mask |= (1 << 0); /* Match condition for channel 0 */
+ } else
+ mask &= ~(1 << 0);
+
+ if ((ret & (1 << 14)) || (ret & (1 << 12))) {
+ mask |= (1 << 1); /* Match condition for channel 1 */
+ } else
+ mask &= ~(1 << 1);
+
+ return mask;
+}
+
+static void sh2a_ubc_clear_triggered_mask(unsigned long mask)
+{
+ if (mask & (1 << 0)) /* Channel 0 statisfied break condition */
+ __raw_writel(__raw_readl(UBC_BRCR) &
+ ~((1 << 15) | (1 << 13)), UBC_BRCR);
+
+ if (mask & (1 << 1)) /* Channel 1 statisfied break condition */
+ __raw_writel(__raw_readl(UBC_BRCR) &
+ ~((1 << 14) | (1 << 12)), UBC_BRCR);
+}
+
+static struct sh_ubc sh2a_ubc = {
+ .name = "SH-2A",
+ .num_events = 2,
+ .trap_nr = 0x1e0,
+ .enable = sh2a_ubc_enable,
+ .disable = sh2a_ubc_disable,
+ .enable_all = sh2a_ubc_enable_all,
+ .disable_all = sh2a_ubc_disable_all,
+ .active_mask = sh2a_ubc_active_mask,
+ .triggered_mask = sh2a_ubc_triggered_mask,
+ .clear_triggered_mask = sh2a_ubc_clear_triggered_mask,
+};
+
+static int __init sh2a_ubc_init(void)
+{
+ struct clk *ubc_iclk = clk_get(NULL, "ubc0");
+ int i;
+
+ /*
+ * The UBC MSTP bit is optional, as not all platforms will have
+ * it. Just ignore it if we can't find it.
+ */
+ if (IS_ERR(ubc_iclk))
+ ubc_iclk = NULL;
+
+ clk_enable(ubc_iclk);
+
+ for (i = 0; i < sh2a_ubc.num_events; i++) {
+ __raw_writel(0, UBC_BAMR(i));
+ __raw_writel(0, UBC_BBR(i));
+ }
+
+ clk_disable(ubc_iclk);
+
+ sh2a_ubc.clk = ubc_iclk;
+
+ return register_sh_ubc(&sh2a_ubc);
+}
+arch_initcall(sh2a_ubc_init);
diff --git a/arch/sh/kernel/hw_breakpoint.c b/arch/sh/kernel/hw_breakpoint.c
index f9173766ec4b..ac4922ad3c14 100644
--- a/arch/sh/kernel/hw_breakpoint.c
+++ b/arch/sh/kernel/hw_breakpoint.c
@@ -113,9 +113,11 @@ static int get_hbp_len(u16 hbp_len)
case SH_BREAKPOINT_LEN_4:
len_in_bytes = 4;
break;
+#ifdef UBC_64BIT
case SH_BREAKPOINT_LEN_8:
len_in_bytes = 8;
break;
+#endif
}
return len_in_bytes;
}
@@ -149,9 +151,11 @@ int arch_bp_generic_fields(int sh_len, int sh_type,
case SH_BREAKPOINT_LEN_4:
*gen_len = HW_BREAKPOINT_LEN_4;
break;
+#ifdef UBC_64BIT
case SH_BREAKPOINT_LEN_8:
*gen_len = HW_BREAKPOINT_LEN_8;
break;
+#endif
default:
return -EINVAL;
}
@@ -190,9 +194,11 @@ static int arch_build_bp_info(struct perf_event *bp)
case HW_BREAKPOINT_LEN_4:
info->len = SH_BREAKPOINT_LEN_4;
break;
+#ifdef UBC_64BIT
case HW_BREAKPOINT_LEN_8:
info->len = SH_BREAKPOINT_LEN_8;
break;
+#endif
default:
return -EINVAL;
}
@@ -240,9 +246,11 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
case SH_BREAKPOINT_LEN_4:
align = 3;
break;
+#ifdef UBC_64BIT
case SH_BREAKPOINT_LEN_8:
align = 7;
break;
+#endif
default:
return ret;
}
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 7e4a97fbded4..bf390667657a 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -16,3 +16,4 @@ generic-y += serial.h
generic-y += trace_clock.h
generic-y += types.h
generic-y += word-at-a-time.h
+generic-y += preempt.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 664d6ad23f80..22f3bd147fa7 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -38,3 +38,4 @@ generic-y += termios.h
generic-y += trace_clock.h
generic-y += types.h
generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index b30f34a79882..fdde187e6087 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -3,3 +3,4 @@ generic-y += hw_irq.h irq_regs.h kdebug.h percpu.h sections.h topology.h xor.h
generic-y += ftrace.h pci.h io.h param.h delay.h mutex.h current.h exec.h
generic-y += switch_to.h clkdev.h
generic-y += trace_clock.h
+generic-y += preempt.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 89d8b6c4e39a..00045cbe5c63 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
generic-y += user.h
generic-y += vga.h
generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ee2fb9d37745..dcdb5130cf85 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -254,10 +254,6 @@ config ARCH_HWEIGHT_CFLAGS
default "-fcall-saved-ecx -fcall-saved-edx" if X86_32
default "-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" if X86_64
-config ARCH_CPU_PROBE_RELEASE
- def_bool y
- depends on HOTPLUG_CPU
-
config ARCH_SUPPORTS_UPROBES
def_bool y
diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
index 7d6ba9db1be9..e0fc24db234a 100644
--- a/arch/x86/crypto/Makefile
+++ b/arch/x86/crypto/Makefile
@@ -3,8 +3,9 @@
#
avx_supported := $(call as-instr,vpxor %xmm0$(comma)%xmm0$(comma)%xmm0,yes,no)
+avx2_supported := $(call as-instr,vpgatherdd %ymm0$(comma)(%eax$(comma)%ymm1\
+ $(comma)4)$(comma)%ymm2,yes,no)
-obj-$(CONFIG_CRYPTO_ABLK_HELPER_X86) += ablk_helper.o
obj-$(CONFIG_CRYPTO_GLUE_HELPER_X86) += glue_helper.o
obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
index f80e668785c0..835488b745ee 100644
--- a/arch/x86/crypto/aesni-intel_glue.c
+++ b/arch/x86/crypto/aesni-intel_glue.c
@@ -34,7 +34,7 @@
#include <asm/cpu_device_id.h>
#include <asm/i387.h>
#include <asm/crypto/aes.h>
-#include <asm/crypto/ablk_helper.h>
+#include <crypto/ablk_helper.h>
#include <crypto/scatterwalk.h>
#include <crypto/internal/aead.h>
#include <linux/workqueue.h>
diff --git a/arch/x86/crypto/camellia_aesni_avx2_glue.c b/arch/x86/crypto/camellia_aesni_avx2_glue.c
index 414fe5d7946b..4209a76fcdaa 100644
--- a/arch/x86/crypto/camellia_aesni_avx2_glue.c
+++ b/arch/x86/crypto/camellia_aesni_avx2_glue.c
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/crypto.h>
#include <linux/err.h>
+#include <crypto/ablk_helper.h>
#include <crypto/algapi.h>
#include <crypto/ctr.h>
#include <crypto/lrw.h>
@@ -21,7 +22,6 @@
#include <asm/xcr.h>
#include <asm/xsave.h>
#include <asm/crypto/camellia.h>
-#include <asm/crypto/ablk_helper.h>
#include <asm/crypto/glue_helper.h>
#define CAMELLIA_AESNI_PARALLEL_BLOCKS 16
diff --git a/arch/x86/crypto/camellia_aesni_avx_glue.c b/arch/x86/crypto/camellia_aesni_avx_glue.c
index 37fd0c0a81ea..87a041a10f4a 100644
--- a/arch/x86/crypto/camellia_aesni_avx_glue.c
+++ b/arch/x86/crypto/camellia_aesni_avx_glue.c
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/crypto.h>
#include <linux/err.h>
+#include <crypto/ablk_helper.h>
#include <crypto/algapi.h>
#include <crypto/ctr.h>
#include <crypto/lrw.h>
@@ -21,7 +22,6 @@
#include <asm/xcr.h>
#include <asm/xsave.h>
#include <asm/crypto/camellia.h>
-#include <asm/crypto/ablk_helper.h>
#include <asm/crypto/glue_helper.h>
#define CAMELLIA_AESNI_PARALLEL_BLOCKS 16
diff --git a/arch/x86/crypto/cast5_avx_glue.c b/arch/x86/crypto/cast5_avx_glue.c
index c6631813dc11..e6a3700489b9 100644
--- a/arch/x86/crypto/cast5_avx_glue.c
+++ b/arch/x86/crypto/cast5_avx_glue.c
@@ -26,13 +26,13 @@
#include <linux/types.h>
#include <linux/crypto.h>
#include <linux/err.h>
+#include <crypto/ablk_helper.h>
#include <crypto/algapi.h>
#include <crypto/cast5.h>
#include <crypto/cryptd.h>
#include <crypto/ctr.h>
#include <asm/xcr.h>
#include <asm/xsave.h>
-#include <asm/crypto/ablk_helper.h>
#include <asm/crypto/glue_helper.h>
#define CAST5_PARALLEL_BLOCKS 16
diff --git a/arch/x86/crypto/cast6_avx_glue.c b/arch/x86/crypto/cast6_avx_glue.c
index 8d0dfb86a559..09f3677393e4 100644
--- a/arch/x86/crypto/cast6_avx_glue.c
+++ b/arch/x86/crypto/cast6_avx_glue.c
@@ -28,6 +28,7 @@
#include <linux/types.h>
#include <linux/crypto.h>
#include <linux/err.h>
+#include <crypto/ablk_helper.h>
#include <crypto/algapi.h>
#include <crypto/cast6.h>
#include <crypto/cryptd.h>
@@ -37,7 +38,6 @@
#include <crypto/xts.h>
#include <asm/xcr.h>
#include <asm/xsave.h>
-#include <asm/crypto/ablk_helper.h>
#include <asm/crypto/glue_helper.h>
#define CAST6_PARALLEL_BLOCKS 8
diff --git a/arch/x86/crypto/serpent_avx2_glue.c b/arch/x86/crypto/serpent_avx2_glue.c
index 23aabc6c20a5..2fae489b1524 100644
--- a/arch/x86/crypto/serpent_avx2_glue.c
+++ b/arch/x86/crypto/serpent_avx2_glue.c
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/crypto.h>
#include <linux/err.h>
+#include <crypto/ablk_helper.h>
#include <crypto/algapi.h>
#include <crypto/ctr.h>
#include <crypto/lrw.h>
@@ -22,7 +23,6 @@
#include <asm/xcr.h>
#include <asm/xsave.h>
#include <asm/crypto/serpent-avx.h>
-#include <asm/crypto/ablk_helper.h>
#include <asm/crypto/glue_helper.h>
#define SERPENT_AVX2_PARALLEL_BLOCKS 16
diff --git a/arch/x86/crypto/serpent_avx_glue.c b/arch/x86/crypto/serpent_avx_glue.c
index 9ae83cf8d21e..ff4870870972 100644
--- a/arch/x86/crypto/serpent_avx_glue.c
+++ b/arch/x86/crypto/serpent_avx_glue.c
@@ -28,6 +28,7 @@
#include <linux/types.h>
#include <linux/crypto.h>
#include <linux/err.h>
+#include <crypto/ablk_helper.h>
#include <crypto/algapi.h>
#include <crypto/serpent.h>
#include <crypto/cryptd.h>
@@ -38,7 +39,6 @@
#include <asm/xcr.h>
#include <asm/xsave.h>
#include <asm/crypto/serpent-avx.h>
-#include <asm/crypto/ablk_helper.h>
#include <asm/crypto/glue_helper.h>
/* 8-way parallel cipher functions */
diff --git a/arch/x86/crypto/serpent_sse2_glue.c b/arch/x86/crypto/serpent_sse2_glue.c
index 97a356ece24d..8c95f8637306 100644
--- a/arch/x86/crypto/serpent_sse2_glue.c
+++ b/arch/x86/crypto/serpent_sse2_glue.c
@@ -34,6 +34,7 @@
#include <linux/types.h>
#include <linux/crypto.h>
#include <linux/err.h>
+#include <crypto/ablk_helper.h>
#include <crypto/algapi.h>
#include <crypto/serpent.h>
#include <crypto/cryptd.h>
@@ -42,7 +43,6 @@
#include <crypto/lrw.h>
#include <crypto/xts.h>
#include <asm/crypto/serpent-sse2.h>
-#include <asm/crypto/ablk_helper.h>
#include <asm/crypto/glue_helper.h>
static void serpent_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src)
diff --git a/arch/x86/crypto/sha256_ssse3_glue.c b/arch/x86/crypto/sha256_ssse3_glue.c
index 50226c4b86ed..85021a4a8e0c 100644
--- a/arch/x86/crypto/sha256_ssse3_glue.c
+++ b/arch/x86/crypto/sha256_ssse3_glue.c
@@ -319,4 +319,4 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm, Supplemental SSE3 accelerated");
MODULE_ALIAS("sha256");
-MODULE_ALIAS("sha384");
+MODULE_ALIAS("sha224");
diff --git a/arch/x86/crypto/twofish_avx_glue.c b/arch/x86/crypto/twofish_avx_glue.c
index a62ba541884e..4e3c665be129 100644
--- a/arch/x86/crypto/twofish_avx_glue.c
+++ b/arch/x86/crypto/twofish_avx_glue.c
@@ -28,6 +28,7 @@
#include <linux/types.h>
#include <linux/crypto.h>
#include <linux/err.h>
+#include <crypto/ablk_helper.h>
#include <crypto/algapi.h>
#include <crypto/twofish.h>
#include <crypto/cryptd.h>
@@ -39,7 +40,6 @@
#include <asm/xcr.h>
#include <asm/xsave.h>
#include <asm/crypto/twofish.h>
-#include <asm/crypto/ablk_helper.h>
#include <asm/crypto/glue_helper.h>
#include <crypto/scatterwalk.h>
#include <linux/workqueue.h>
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index b1977bad5435..c8c1e700c26e 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -26,6 +26,7 @@
#include <acpi/pdc_intel.h>
#include <asm/numa.h>
+#include <asm/fixmap.h>
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/mpspec.h>
diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h
index 722aa3b04624..da31c8b8a92d 100644
--- a/arch/x86/include/asm/atomic.h
+++ b/arch/x86/include/asm/atomic.h
@@ -6,6 +6,7 @@
#include <asm/processor.h>
#include <asm/alternative.h>
#include <asm/cmpxchg.h>
+#include <asm/rmwcc.h>
/*
* Atomic operations that C can't guarantee us. Useful for
@@ -76,12 +77,7 @@ static inline void atomic_sub(int i, atomic_t *v)
*/
static inline int atomic_sub_and_test(int i, atomic_t *v)
{
- unsigned char c;
-
- asm volatile(LOCK_PREFIX "subl %2,%0; sete %1"
- : "+m" (v->counter), "=qm" (c)
- : "ir" (i) : "memory");
- return c;
+ GEN_BINARY_RMWcc(LOCK_PREFIX "subl", v->counter, i, "%0", "e");
}
/**
@@ -118,12 +114,7 @@ static inline void atomic_dec(atomic_t *v)
*/
static inline int atomic_dec_and_test(atomic_t *v)
{
- unsigned char c;
-
- asm volatile(LOCK_PREFIX "decl %0; sete %1"
- : "+m" (v->counter), "=qm" (c)
- : : "memory");
- return c != 0;
+ GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", "e");
}
/**
@@ -136,12 +127,7 @@ static inline int atomic_dec_and_test(atomic_t *v)
*/
static inline int atomic_inc_and_test(atomic_t *v)
{
- unsigned char c;
-
- asm volatile(LOCK_PREFIX "incl %0; sete %1"
- : "+m" (v->counter), "=qm" (c)
- : : "memory");
- return c != 0;
+ GEN_UNARY_RMWcc(LOCK_PREFIX "incl", v->counter, "%0", "e");
}
/**
@@ -155,12 +141,7 @@ static inline int atomic_inc_and_test(atomic_t *v)
*/
static inline int atomic_add_negative(int i, atomic_t *v)
{
- unsigned char c;
-
- asm volatile(LOCK_PREFIX "addl %2,%0; sets %1"
- : "+m" (v->counter), "=qm" (c)
- : "ir" (i) : "memory");
- return c;
+ GEN_BINARY_RMWcc(LOCK_PREFIX "addl", v->counter, i, "%0", "s");
}
/**
diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h
index 0e1cbfc8ee06..3f065c985aee 100644
--- a/arch/x86/include/asm/atomic64_64.h
+++ b/arch/x86/include/asm/atomic64_64.h
@@ -72,12 +72,7 @@ static inline void atomic64_sub(long i, atomic64_t *v)
*/
static inline int atomic64_sub_and_test(long i, atomic64_t *v)
{
- unsigned char c;
-
- asm volatile(LOCK_PREFIX "subq %2,%0; sete %1"
- : "=m" (v->counter), "=qm" (c)
- : "er" (i), "m" (v->counter) : "memory");
- return c;
+ GEN_BINARY_RMWcc(LOCK_PREFIX "subq", v->counter, i, "%0", "e");
}
/**
@@ -116,12 +111,7 @@ static inline void atomic64_dec(atomic64_t *v)
*/
static inline int atomic64_dec_and_test(atomic64_t *v)
{
- unsigned char c;
-
- asm volatile(LOCK_PREFIX "decq %0; sete %1"
- : "=m" (v->counter), "=qm" (c)
- : "m" (v->counter) : "memory");
- return c != 0;
+ GEN_UNARY_RMWcc(LOCK_PREFIX "decq", v->counter, "%0", "e");
}
/**
@@ -134,12 +124,7 @@ static inline int atomic64_dec_and_test(atomic64_t *v)
*/
static inline int atomic64_inc_and_test(atomic64_t *v)
{
- unsigned char c;
-
- asm volatile(LOCK_PREFIX "incq %0; sete %1"
- : "=m" (v->counter), "=qm" (c)
- : "m" (v->counter) : "memory");
- return c != 0;
+ GEN_UNARY_RMWcc(LOCK_PREFIX "incq", v->counter, "%0", "e");
}
/**
@@ -153,12 +138,7 @@ static inline int atomic64_inc_and_test(atomic64_t *v)
*/
static inline int atomic64_add_negative(long i, atomic64_t *v)
{
- unsigned char c;
-
- asm volatile(LOCK_PREFIX "addq %2,%0; sets %1"
- : "=m" (v->counter), "=qm" (c)
- : "er" (i), "m" (v->counter) : "memory");
- return c;
+ GEN_BINARY_RMWcc(LOCK_PREFIX "addq", v->counter, i, "%0", "s");
}
/**
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index 41639ce8fd63..6d76d0935989 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -14,6 +14,7 @@
#include <linux/compiler.h>
#include <asm/alternative.h>
+#include <asm/rmwcc.h>
#if BITS_PER_LONG == 32
# define _BITOPS_LONG_SHIFT 5
@@ -204,12 +205,7 @@ static inline void change_bit(long nr, volatile unsigned long *addr)
*/
static inline int test_and_set_bit(long nr, volatile unsigned long *addr)
{
- int oldbit;
-
- asm volatile(LOCK_PREFIX "bts %2,%1\n\t"
- "sbb %0,%0" : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
-
- return oldbit;
+ GEN_BINARY_RMWcc(LOCK_PREFIX "bts", *addr, nr, "%0", "c");
}
/**
@@ -255,13 +251,7 @@ static inline int __test_and_set_bit(long nr, volatile unsigned long *addr)
*/
static inline int test_and_clear_bit(long nr, volatile unsigned long *addr)
{
- int oldbit;
-
- asm volatile(LOCK_PREFIX "btr %2,%1\n\t"
- "sbb %0,%0"
- : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
-
- return oldbit;
+ GEN_BINARY_RMWcc(LOCK_PREFIX "btr", *addr, nr, "%0", "c");
}
/**
@@ -314,13 +304,7 @@ static inline int __test_and_change_bit(long nr, volatile unsigned long *addr)
*/
static inline int test_and_change_bit(long nr, volatile unsigned long *addr)
{
- int oldbit;
-
- asm volatile(LOCK_PREFIX "btc %2,%1\n\t"
- "sbb %0,%0"
- : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
-
- return oldbit;
+ GEN_BINARY_RMWcc(LOCK_PREFIX "btc", *addr, nr, "%0", "c");
}
static __always_inline int constant_test_bit(long nr, const volatile unsigned long *addr)
diff --git a/arch/x86/include/asm/calling.h b/arch/x86/include/asm/calling.h
index 0fa675033912..cb4c73bfeb48 100644
--- a/arch/x86/include/asm/calling.h
+++ b/arch/x86/include/asm/calling.h
@@ -48,6 +48,8 @@ For 32-bit we have the following conventions - kernel is built with
#include <asm/dwarf2.h>
+#ifdef CONFIG_X86_64
+
/*
* 64-bit system call stack frame layout defines and helpers,
* for assembly code:
@@ -192,3 +194,51 @@ For 32-bit we have the following conventions - kernel is built with
.macro icebp
.byte 0xf1
.endm
+
+#else /* CONFIG_X86_64 */
+
+/*
+ * For 32bit only simplified versions of SAVE_ALL/RESTORE_ALL. These
+ * are different from the entry_32.S versions in not changing the segment
+ * registers. So only suitable for in kernel use, not when transitioning
+ * from or to user space. The resulting stack frame is not a standard
+ * pt_regs frame. The main use case is calling C code from assembler
+ * when all the registers need to be preserved.
+ */
+
+ .macro SAVE_ALL
+ pushl_cfi %eax
+ CFI_REL_OFFSET eax, 0
+ pushl_cfi %ebp
+ CFI_REL_OFFSET ebp, 0
+ pushl_cfi %edi
+ CFI_REL_OFFSET edi, 0
+ pushl_cfi %esi
+ CFI_REL_OFFSET esi, 0
+ pushl_cfi %edx
+ CFI_REL_OFFSET edx, 0
+ pushl_cfi %ecx
+ CFI_REL_OFFSET ecx, 0
+ pushl_cfi %ebx
+ CFI_REL_OFFSET ebx, 0
+ .endm
+
+ .macro RESTORE_ALL
+ popl_cfi %ebx
+ CFI_RESTORE ebx
+ popl_cfi %ecx
+ CFI_RESTORE ecx
+ popl_cfi %edx
+ CFI_RESTORE edx
+ popl_cfi %esi
+ CFI_RESTORE esi
+ popl_cfi %edi
+ CFI_RESTORE edi
+ popl_cfi %ebp
+ CFI_RESTORE ebp
+ popl_cfi %eax
+ CFI_RESTORE eax
+ .endm
+
+#endif /* CONFIG_X86_64 */
+
diff --git a/arch/x86/include/asm/local.h b/arch/x86/include/asm/local.h
index 2d89e3980cbd..5b23e605e707 100644
--- a/arch/x86/include/asm/local.h
+++ b/arch/x86/include/asm/local.h
@@ -52,12 +52,7 @@ static inline void local_sub(long i, local_t *l)
*/
static inline int local_sub_and_test(long i, local_t *l)
{
- unsigned char c;
-
- asm volatile(_ASM_SUB "%2,%0; sete %1"
- : "+m" (l->a.counter), "=qm" (c)
- : "ir" (i) : "memory");
- return c;
+ GEN_BINARY_RMWcc(_ASM_SUB, l->a.counter, i, "%0", "e");
}
/**
@@ -70,12 +65,7 @@ static inline int local_sub_and_test(long i, local_t *l)
*/
static inline int local_dec_and_test(local_t *l)
{
- unsigned char c;
-
- asm volatile(_ASM_DEC "%0; sete %1"
- : "+m" (l->a.counter), "=qm" (c)
- : : "memory");
- return c != 0;
+ GEN_UNARY_RMWcc(_ASM_DEC, l->a.counter, "%0", "e");
}
/**
@@ -88,12 +78,7 @@ static inline int local_dec_and_test(local_t *l)
*/
static inline int local_inc_and_test(local_t *l)
{
- unsigned char c;
-
- asm volatile(_ASM_INC "%0; sete %1"
- : "+m" (l->a.counter), "=qm" (c)
- : : "memory");
- return c != 0;
+ GEN_UNARY_RMWcc(_ASM_INC, l->a.counter, "%0", "e");
}
/**
@@ -107,12 +92,7 @@ static inline int local_inc_and_test(local_t *l)
*/
static inline int local_add_negative(long i, local_t *l)
{
- unsigned char c;
-
- asm volatile(_ASM_ADD "%2,%0; sets %1"
- : "+m" (l->a.counter), "=qm" (c)
- : "ir" (i) : "memory");
- return c;
+ GEN_BINARY_RMWcc(_ASM_ADD, l->a.counter, i, "%0", "s");
}
/**
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
index 626cf70082d7..3142a94c7b4b 100644
--- a/arch/x86/include/asm/mpspec.h
+++ b/arch/x86/include/asm/mpspec.h
@@ -94,7 +94,7 @@ static inline void early_reserve_e820_mpc_new(void) { }
#define default_get_smp_config x86_init_uint_noop
#endif
-void generic_processor_info(int apicid, int version);
+int generic_processor_info(int apicid, int version);
#ifdef CONFIG_ACPI
extern void mp_register_ioapic(int id, u32 address, u32 gsi_base);
extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
diff --git a/arch/x86/include/asm/preempt.h b/arch/x86/include/asm/preempt.h
new file mode 100644
index 000000000000..1de41690ff99
--- /dev/null
+++ b/arch/x86/include/asm/preempt.h
@@ -0,0 +1,108 @@
+#ifndef __ASM_PREEMPT_H
+#define __ASM_PREEMPT_H
+
+#include <asm/rmwcc.h>
+#include <asm/percpu.h>
+#include <linux/thread_info.h>
+
+DECLARE_PER_CPU(int, __preempt_count);
+
+/*
+ * We mask the PREEMPT_NEED_RESCHED bit so as not to confuse all current users
+ * that think a non-zero value indicates we cannot preempt.
+ */
+static __always_inline int preempt_count(void)
+{
+ return __this_cpu_read_4(__preempt_count) & ~PREEMPT_NEED_RESCHED;
+}
+
+static __always_inline void preempt_count_set(int pc)
+{
+ __this_cpu_write_4(__preempt_count, pc);
+}
+
+/*
+ * must be macros to avoid header recursion hell
+ */
+#define task_preempt_count(p) \
+ (task_thread_info(p)->saved_preempt_count & ~PREEMPT_NEED_RESCHED)
+
+#define init_task_preempt_count(p) do { \
+ task_thread_info(p)->saved_preempt_count = PREEMPT_DISABLED; \
+} while (0)
+
+#define init_idle_preempt_count(p, cpu) do { \
+ task_thread_info(p)->saved_preempt_count = PREEMPT_ENABLED; \
+ per_cpu(__preempt_count, (cpu)) = PREEMPT_ENABLED; \
+} while (0)
+
+/*
+ * We fold the NEED_RESCHED bit into the preempt count such that
+ * preempt_enable() can decrement and test for needing to reschedule with a
+ * single instruction.
+ *
+ * We invert the actual bit, so that when the decrement hits 0 we know we both
+ * need to resched (the bit is cleared) and can resched (no preempt count).
+ */
+
+static __always_inline void set_preempt_need_resched(void)
+{
+ __this_cpu_and_4(__preempt_count, ~PREEMPT_NEED_RESCHED);
+}
+
+static __always_inline void clear_preempt_need_resched(void)
+{
+ __this_cpu_or_4(__preempt_count, PREEMPT_NEED_RESCHED);
+}
+
+static __always_inline bool test_preempt_need_resched(void)
+{
+ return !(__this_cpu_read_4(__preempt_count) & PREEMPT_NEED_RESCHED);
+}
+
+/*
+ * The various preempt_count add/sub methods
+ */
+
+static __always_inline void __preempt_count_add(int val)
+{
+ __this_cpu_add_4(__preempt_count, val);
+}
+
+static __always_inline void __preempt_count_sub(int val)
+{
+ __this_cpu_add_4(__preempt_count, -val);
+}
+
+static __always_inline bool __preempt_count_dec_and_test(void)
+{
+ GEN_UNARY_RMWcc("decl", __preempt_count, __percpu_arg(0), "e");
+}
+
+/*
+ * Returns true when we need to resched -- even if we can not.
+ */
+static __always_inline bool need_resched(void)
+{
+ return unlikely(test_preempt_need_resched());
+}
+
+/*
+ * Returns true when we need to resched and can (barring IRQ state).
+ */
+static __always_inline bool should_resched(void)
+{
+ return unlikely(!__this_cpu_read_4(__preempt_count));
+}
+
+#ifdef CONFIG_PREEMPT
+ extern asmlinkage void ___preempt_schedule(void);
+# define __preempt_schedule() asm ("call ___preempt_schedule")
+ extern asmlinkage void preempt_schedule(void);
+# ifdef CONFIG_CONTEXT_TRACKING
+ extern asmlinkage void ___preempt_schedule_context(void);
+# define __preempt_schedule_context() asm ("call ___preempt_schedule_context")
+# endif
+#endif
+
+#endif /* __ASM_PREEMPT_H */
diff --git a/arch/x86/include/asm/rmwcc.h b/arch/x86/include/asm/rmwcc.h
new file mode 100644
index 000000000000..735f1849795f
--- /dev/null
+++ b/arch/x86/include/asm/rmwcc.h
@@ -0,0 +1,41 @@
+#ifndef _ASM_X86_RMWcc
+#define _ASM_X86_RMWcc
+
+#ifdef CC_HAVE_ASM_GOTO
+
+#define __GEN_RMWcc(fullop, var, cc, ...) \
+do { \
+ asm volatile goto (fullop "; j" cc " %l[cc_label]" \
+ : : "m" (var), ## __VA_ARGS__ \
+ : "memory" : cc_label); \
+ return 0; \
+cc_label: \
+ return 1; \
+} while (0)
+
+#define GEN_UNARY_RMWcc(op, var, arg0, cc) \
+ __GEN_RMWcc(op " " arg0, var, cc)
+
+#define GEN_BINARY_RMWcc(op, var, val, arg0, cc) \
+ __GEN_RMWcc(op " %1, " arg0, var, cc, "er" (val))
+
+#else /* !CC_HAVE_ASM_GOTO */
+
+#define __GEN_RMWcc(fullop, var, cc, ...) \
+do { \
+ char c; \
+ asm volatile (fullop "; set" cc " %1" \
+ : "+m" (var), "=qm" (c) \
+ : __VA_ARGS__ : "memory"); \
+ return c != 0; \
+} while (0)
+
+#define GEN_UNARY_RMWcc(op, var, arg0, cc) \
+ __GEN_RMWcc(op " " arg0, var, cc)
+
+#define GEN_BINARY_RMWcc(op, var, val, arg0, cc) \
+ __GEN_RMWcc(op " %2, " arg0, var, cc, "er" (val))
+
+#endif /* CC_HAVE_ASM_GOTO */
+
+#endif /* _ASM_X86_RMWcc */
diff --git a/arch/x86/include/asm/simd.h b/arch/x86/include/asm/simd.h
new file mode 100644
index 000000000000..ee80b92f0096
--- /dev/null
+++ b/arch/x86/include/asm/simd.h
@@ -0,0 +1,11 @@
+
+#include <asm/i387.h>
+
+/*
+ * may_use_simd - whether it is allowable at this time to issue SIMD
+ * instructions or access the SIMD register file
+ */
+static __must_check inline bool may_use_simd(void)
+{
+ return irq_fpu_usable();
+}
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index 27811190cbd7..c46a46be1ec6 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -28,8 +28,7 @@ struct thread_info {
__u32 flags; /* low level flags */
__u32 status; /* thread synchronous flags */
__u32 cpu; /* current CPU */
- int preempt_count; /* 0 => preemptable,
- <0 => BUG */
+ int saved_preempt_count;
mm_segment_t addr_limit;
struct restart_block restart_block;
void __user *sysenter_return;
@@ -49,7 +48,7 @@ struct thread_info {
.exec_domain = &default_exec_domain, \
.flags = 0, \
.cpu = 0, \
- .preempt_count = INIT_PREEMPT_COUNT, \
+ .saved_preempt_count = INIT_PREEMPT_COUNT, \
.addr_limit = KERNEL_DS, \
.restart_block = { \
.fn = do_no_restart_syscall, \
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h
index 4f7923dd0007..64476bb2a146 100644
--- a/arch/x86/include/asm/uaccess_64.h
+++ b/arch/x86/include/asm/uaccess_64.h
@@ -77,11 +77,10 @@ int copy_to_user(void __user *dst, const void *src, unsigned size)
}
static __always_inline __must_check
-int __copy_from_user(void *dst, const void __user *src, unsigned size)
+int __copy_from_user_nocheck(void *dst, const void __user *src, unsigned size)
{
int ret = 0;
- might_fault();
if (!__builtin_constant_p(size))
return copy_user_generic(dst, (__force void *)src, size);
switch (size) {
@@ -121,11 +120,17 @@ int __copy_from_user(void *dst, const void __user *src, unsigned size)
}
static __always_inline __must_check
-int __copy_to_user(void __user *dst, const void *src, unsigned size)
+int __copy_from_user(void *dst, const void __user *src, unsigned size)
+{
+ might_fault();
+ return __copy_from_user_nocheck(dst, src, size);
+}
+
+static __always_inline __must_check
+int __copy_to_user_nocheck(void __user *dst, const void *src, unsigned size)
{
int ret = 0;
- might_fault();
if (!__builtin_constant_p(size))
return copy_user_generic((__force void *)dst, src, size);
switch (size) {
@@ -165,6 +170,13 @@ int __copy_to_user(void __user *dst, const void *src, unsigned size)
}
static __always_inline __must_check
+int __copy_to_user(void __user *dst, const void *src, unsigned size)
+{
+ might_fault();
+ return __copy_to_user_nocheck(dst, src, size);
+}
+
+static __always_inline __must_check
int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
{
int ret = 0;
@@ -220,13 +232,13 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
static __must_check __always_inline int
__copy_from_user_inatomic(void *dst, const void __user *src, unsigned size)
{
- return copy_user_generic(dst, (__force const void *)src, size);
+ return __copy_from_user_nocheck(dst, (__force const void *)src, size);
}
static __must_check __always_inline int
__copy_to_user_inatomic(void __user *dst, const void *src, unsigned size)
{
- return copy_user_generic((__force void *)dst, src, size);
+ return __copy_to_user_nocheck((__force void *)dst, src, size);
}
extern long __copy_user_nocache(void *dst, const void __user *src,
diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h
index 062921ef34e9..8b1283daa332 100644
--- a/arch/x86/include/asm/uv/uv.h
+++ b/arch/x86/include/asm/uv/uv.h
@@ -12,7 +12,15 @@ extern enum uv_system_type get_uv_system_type(void);
extern int is_uv_system(void);
extern void uv_cpu_init(void);
extern void uv_nmi_init(void);
+extern void uv_register_nmi_notifier(void);
extern void uv_system_init(void);
+extern void (*uv_trace_nmi_func)(unsigned int reason, struct pt_regs *regs);
+extern void (*uv_trace_func)(const char *f, const int l, const char *fmt, ...);
+#define uv_trace(fmt, ...) \
+do { \
+ if (unlikely(uv_trace_func)) \
+ (uv_trace_func)(__func__, __LINE__, fmt, ##__VA_ARGS__);\
+} while (0)
extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
struct mm_struct *mm,
unsigned long start,
@@ -25,6 +33,8 @@ static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; }
static inline int is_uv_system(void) { return 0; }
static inline void uv_cpu_init(void) { }
static inline void uv_system_init(void) { }
+static inline void uv_trace(void *fmt, ...) { }
+static inline void uv_register_nmi_notifier(void) { }
static inline const struct cpumask *
uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm,
unsigned long start, unsigned long end, unsigned int cpu)
diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h
index 2c32df95bb78..a30836c8ac4d 100644
--- a/arch/x86/include/asm/uv/uv_hub.h
+++ b/arch/x86/include/asm/uv/uv_hub.h
@@ -502,8 +502,8 @@ struct uv_blade_info {
unsigned short nr_online_cpus;
unsigned short pnode;
short memory_nid;
- spinlock_t nmi_lock;
- unsigned long nmi_count;
+ spinlock_t nmi_lock; /* obsolete, see uv_hub_nmi */
+ unsigned long nmi_count; /* obsolete, see uv_hub_nmi */
};
extern struct uv_blade_info *uv_blade_info;
extern short *uv_node_to_blade;
@@ -576,6 +576,59 @@ static inline int uv_num_possible_blades(void)
return uv_possible_blades;
}
+/* Per Hub NMI support */
+extern void uv_nmi_setup(void);
+
+/* BMC sets a bit this MMR non-zero before sending an NMI */
+#define UVH_NMI_MMR UVH_SCRATCH5
+#define UVH_NMI_MMR_CLEAR UVH_SCRATCH5_ALIAS
+#define UVH_NMI_MMR_SHIFT 63
+#define UVH_NMI_MMR_TYPE "SCRATCH5"
+
+/* Newer SMM NMI handler, not present in all systems */
+#define UVH_NMI_MMRX UVH_EVENT_OCCURRED0
+#define UVH_NMI_MMRX_CLEAR UVH_EVENT_OCCURRED0_ALIAS
+#define UVH_NMI_MMRX_SHIFT (is_uv1_hub() ? \
+ UV1H_EVENT_OCCURRED0_EXTIO_INT0_SHFT :\
+ UVXH_EVENT_OCCURRED0_EXTIO_INT0_SHFT)
+#define UVH_NMI_MMRX_TYPE "EXTIO_INT0"
+
+/* Non-zero indicates newer SMM NMI handler present */
+#define UVH_NMI_MMRX_SUPPORTED UVH_EXTIO_INT0_BROADCAST
+
+/* Indicates to BIOS that we want to use the newer SMM NMI handler */
+#define UVH_NMI_MMRX_REQ UVH_SCRATCH5_ALIAS_2
+#define UVH_NMI_MMRX_REQ_SHIFT 62
+
+struct uv_hub_nmi_s {
+ raw_spinlock_t nmi_lock;
+ atomic_t in_nmi; /* flag this node in UV NMI IRQ */
+ atomic_t cpu_owner; /* last locker of this struct */
+ atomic_t read_mmr_count; /* count of MMR reads */
+ atomic_t nmi_count; /* count of true UV NMIs */
+ unsigned long nmi_value; /* last value read from NMI MMR */
+};
+
+struct uv_cpu_nmi_s {
+ struct uv_hub_nmi_s *hub;
+ atomic_t state;
+ atomic_t pinging;
+ int queries;
+ int pings;
+};
+
+DECLARE_PER_CPU(struct uv_cpu_nmi_s, __uv_cpu_nmi);
+#define uv_cpu_nmi (__get_cpu_var(__uv_cpu_nmi))
+#define uv_hub_nmi (uv_cpu_nmi.hub)
+#define uv_cpu_nmi_per(cpu) (per_cpu(__uv_cpu_nmi, cpu))
+#define uv_hub_nmi_per(cpu) (uv_cpu_nmi_per(cpu).hub)
+
+/* uv_cpu_nmi_states */
+#define UV_NMI_STATE_OUT 0
+#define UV_NMI_STATE_IN 1
+#define UV_NMI_STATE_DUMP 2
+#define UV_NMI_STATE_DUMP_DONE 3
+
/* Update SCIR state */
static inline void uv_set_scir_bits(unsigned char value)
{
diff --git a/arch/x86/include/asm/uv/uv_mmrs.h b/arch/x86/include/asm/uv/uv_mmrs.h
index bd5f80e58a23..e42249bcf7e1 100644
--- a/arch/x86/include/asm/uv/uv_mmrs.h
+++ b/arch/x86/include/asm/uv/uv_mmrs.h
@@ -461,6 +461,23 @@ union uvh_event_occurred0_u {
/* ========================================================================= */
+/* UVH_EXTIO_INT0_BROADCAST */
+/* ========================================================================= */
+#define UVH_EXTIO_INT0_BROADCAST 0x61448UL
+#define UVH_EXTIO_INT0_BROADCAST_32 0x3f0
+
+#define UVH_EXTIO_INT0_BROADCAST_ENABLE_SHFT 0
+#define UVH_EXTIO_INT0_BROADCAST_ENABLE_MASK 0x0000000000000001UL
+
+union uvh_extio_int0_broadcast_u {
+ unsigned long v;
+ struct uvh_extio_int0_broadcast_s {
+ unsigned long enable:1; /* RW */
+ unsigned long rsvd_1_63:63;
+ } s;
+};
+
+/* ========================================================================= */
/* UVH_GR0_TLB_INT0_CONFIG */
/* ========================================================================= */
#define UVH_GR0_TLB_INT0_CONFIG 0x61b00UL
@@ -2606,6 +2623,20 @@ union uvh_scratch5_u {
};
/* ========================================================================= */
+/* UVH_SCRATCH5_ALIAS */
+/* ========================================================================= */
+#define UVH_SCRATCH5_ALIAS 0x2d0208UL
+#define UVH_SCRATCH5_ALIAS_32 0x780
+
+
+/* ========================================================================= */
+/* UVH_SCRATCH5_ALIAS_2 */
+/* ========================================================================= */
+#define UVH_SCRATCH5_ALIAS_2 0x2d0210UL
+#define UVH_SCRATCH5_ALIAS_2_32 0x788
+
+
+/* ========================================================================= */
/* UVXH_EVENT_OCCURRED2 */
/* ========================================================================= */
#define UVXH_EVENT_OCCURRED2 0x70100UL
diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h
index bb0465090ae5..940ed3fd889a 100644
--- a/arch/x86/include/uapi/asm/msr-index.h
+++ b/arch/x86/include/uapi/asm/msr-index.h
@@ -147,6 +147,8 @@
#define MSR_PP1_ENERGY_STATUS 0x00000641
#define MSR_PP1_POLICY 0x00000642
+#define MSR_CORE_C1_RES 0x00000660
+
#define MSR_AMD64_MC0_MASK 0xc0010044
#define MSR_IA32_MCx_CTL(x) (MSR_IA32_MC0_CTL + 4*(x))
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index a5408b965c9d..9b0a34e2cd79 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -36,6 +36,8 @@ obj-y += tsc.o io_delay.o rtc.o
obj-y += pci-iommu_table.o
obj-y += resource.o
+obj-$(CONFIG_PREEMPT) += preempt.o
+
obj-y += process.o
obj-y += i387.o xsave.o
obj-y += ptrace.o
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 40c76604199f..1f7c0746611f 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -189,24 +189,31 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
return 0;
}
-static void acpi_register_lapic(int id, u8 enabled)
+/**
+ * acpi_register_lapic - register a local apic and generates a logic cpu number
+ * @id: local apic id to register
+ * @enabled: this cpu is enabled or not
+ *
+ * Returns the logic cpu number which maps to the local apic
+ */
+static int acpi_register_lapic(int id, u8 enabled)
{
unsigned int ver = 0;
if (id >= MAX_LOCAL_APIC) {
printk(KERN_INFO PREFIX "skipped apicid that is too big\n");
- return;
+ return -EINVAL;
}
if (!enabled) {
++disabled_cpus;
- return;
+ return -EINVAL;
}
if (boot_cpu_physical_apicid != -1U)
ver = apic_version[boot_cpu_physical_apicid];
- generic_processor_info(id, ver);
+ return generic_processor_info(id, ver);
}
static int __init
@@ -614,84 +621,27 @@ static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
#endif
}
-static int _acpi_map_lsapic(acpi_handle handle, int *pcpu)
+static int _acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu)
{
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- union acpi_object *obj;
- struct acpi_madt_local_apic *lapic;
- cpumask_var_t tmp_map, new_map;
- u8 physid;
int cpu;
- int retval = -ENOMEM;
-
- if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
- return -EINVAL;
-
- if (!buffer.length || !buffer.pointer)
- return -EINVAL;
-
- obj = buffer.pointer;
- if (obj->type != ACPI_TYPE_BUFFER ||
- obj->buffer.length < sizeof(*lapic)) {
- kfree(buffer.pointer);
- return -EINVAL;
- }
- lapic = (struct acpi_madt_local_apic *)obj->buffer.pointer;
-
- if (lapic->header.type != ACPI_MADT_TYPE_LOCAL_APIC ||
- !(lapic->lapic_flags & ACPI_MADT_ENABLED)) {
- kfree(buffer.pointer);
- return -EINVAL;
- }
-
- physid = lapic->id;
-
- kfree(buffer.pointer);
- buffer.length = ACPI_ALLOCATE_BUFFER;
- buffer.pointer = NULL;
- lapic = NULL;
-
- if (!alloc_cpumask_var(&tmp_map, GFP_KERNEL))
- goto out;
-
- if (!alloc_cpumask_var(&new_map, GFP_KERNEL))
- goto free_tmp_map;
-
- cpumask_copy(tmp_map, cpu_present_mask);
- acpi_register_lapic(physid, ACPI_MADT_ENABLED);
-
- /*
- * If acpi_register_lapic successfully generates a new logical cpu
- * number, then the following will get us exactly what was mapped
- */
- cpumask_andnot(new_map, cpu_present_mask, tmp_map);
- if (cpumask_empty(new_map)) {
- printk ("Unable to map lapic to logical cpu number\n");
- retval = -EINVAL;
- goto free_new_map;
+ cpu = acpi_register_lapic(physid, ACPI_MADT_ENABLED);
+ if (cpu < 0) {
+ pr_info(PREFIX "Unable to map lapic to logical cpu number\n");
+ return cpu;
}
acpi_processor_set_pdc(handle);
-
- cpu = cpumask_first(new_map);
acpi_map_cpu2node(handle, cpu, physid);
*pcpu = cpu;
- retval = 0;
-
-free_new_map:
- free_cpumask_var(new_map);
-free_tmp_map:
- free_cpumask_var(tmp_map);
-out:
- return retval;
+ return 0;
}
/* wrapper to silence section mismatch warning */
-int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu)
+int __ref acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu)
{
- return _acpi_map_lsapic(handle, pcpu);
+ return _acpi_map_lsapic(handle, physid, pcpu);
}
EXPORT_SYMBOL(acpi_map_lsapic);
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index a7eb82d9b012..ed165d657380 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -2107,7 +2107,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
apic_write(APIC_LVT1, value);
}
-void generic_processor_info(int apicid, int version)
+int generic_processor_info(int apicid, int version)
{
int cpu, max = nr_cpu_ids;
bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid,
@@ -2127,7 +2127,7 @@ void generic_processor_info(int apicid, int version)
" Processor %d/0x%x ignored.\n", max, thiscpu, apicid);
disabled_cpus++;
- return;
+ return -ENODEV;
}
if (num_processors >= nr_cpu_ids) {
@@ -2138,7 +2138,7 @@ void generic_processor_info(int apicid, int version)
" Processor %d/0x%x ignored.\n", max, thiscpu, apicid);
disabled_cpus++;
- return;
+ return -EINVAL;
}
num_processors++;
@@ -2183,6 +2183,8 @@ void generic_processor_info(int apicid, int version)
#endif
set_cpu_possible(cpu, true);
set_cpu_present(cpu, true);
+
+ return cpu;
}
int hard_smp_processor_id(void)
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 1191ac1c9d25..0a5a4b8ae36c 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -39,12 +39,6 @@
#include <asm/x86_init.h>
#include <asm/nmi.h>
-/* BMC sets a bit this MMR non-zero before sending an NMI */
-#define UVH_NMI_MMR UVH_SCRATCH5
-#define UVH_NMI_MMR_CLEAR (UVH_NMI_MMR + 8)
-#define UV_NMI_PENDING_MASK (1UL << 63)
-DEFINE_PER_CPU(unsigned long, cpu_last_nmi_count);
-
DEFINE_PER_CPU(int, x2apic_extra_bits);
#define PR_DEVEL(fmt, args...) pr_devel("%s: " fmt, __func__, args)
@@ -58,7 +52,6 @@ int uv_min_hub_revision_id;
EXPORT_SYMBOL_GPL(uv_min_hub_revision_id);
unsigned int uv_apicid_hibits;
EXPORT_SYMBOL_GPL(uv_apicid_hibits);
-static DEFINE_SPINLOCK(uv_nmi_lock);
static struct apic apic_x2apic_uv_x;
@@ -847,68 +840,6 @@ void uv_cpu_init(void)
set_x2apic_extra_bits(uv_hub_info->pnode);
}
-/*
- * When NMI is received, print a stack trace.
- */
-int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
-{
- unsigned long real_uv_nmi;
- int bid;
-
- /*
- * Each blade has an MMR that indicates when an NMI has been sent
- * to cpus on the blade. If an NMI is detected, atomically
- * clear the MMR and update a per-blade NMI count used to
- * cause each cpu on the blade to notice a new NMI.
- */
- bid = uv_numa_blade_id();
- real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK);
-
- if (unlikely(real_uv_nmi)) {
- spin_lock(&uv_blade_info[bid].nmi_lock);
- real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK);
- if (real_uv_nmi) {
- uv_blade_info[bid].nmi_count++;
- uv_write_local_mmr(UVH_NMI_MMR_CLEAR, UV_NMI_PENDING_MASK);
- }
- spin_unlock(&uv_blade_info[bid].nmi_lock);
- }
-
- if (likely(__get_cpu_var(cpu_last_nmi_count) == uv_blade_info[bid].nmi_count))
- return NMI_DONE;
-
- __get_cpu_var(cpu_last_nmi_count) = uv_blade_info[bid].nmi_count;
-
- /*
- * Use a lock so only one cpu prints at a time.
- * This prevents intermixed output.
- */
- spin_lock(&uv_nmi_lock);
- pr_info("UV NMI stack dump cpu %u:\n", smp_processor_id());
- dump_stack();
- spin_unlock(&uv_nmi_lock);
-
- return NMI_HANDLED;
-}
-
-void uv_register_nmi_notifier(void)
-{
- if (register_nmi_handler(NMI_UNKNOWN, uv_handle_nmi, 0, "uv"))
- printk(KERN_WARNING "UV NMI handler failed to register\n");
-}
-
-void uv_nmi_init(void)
-{
- unsigned int value;
-
- /*
- * Unmask NMI on all cpus
- */
- value = apic_read(APIC_LVT1) | APIC_DM_NMI;
- value &= ~APIC_LVT_MASKED;
- apic_write(APIC_LVT1, value);
-}
-
void __init uv_system_init(void)
{
union uvh_rh_gam_config_mmr_u m_n_config;
@@ -1046,6 +977,7 @@ void __init uv_system_init(void)
map_mmr_high(max_pnode);
map_mmioh_high(min_pnode, max_pnode);
+ uv_nmi_setup();
uv_cpu_init();
uv_scir_register_cpu_notifier();
uv_register_nmi_notifier();
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index 28610822fb3c..9f6b9341950f 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -32,7 +32,6 @@ void common(void) {
OFFSET(TI_flags, thread_info, flags);
OFFSET(TI_status, thread_info, status);
OFFSET(TI_addr_limit, thread_info, addr_limit);
- OFFSET(TI_preempt_count, thread_info, preempt_count);
BLANK();
OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 2793d1f095a2..5223fe6dec7b 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1095,6 +1095,9 @@ DEFINE_PER_CPU(char *, irq_stack_ptr) =
DEFINE_PER_CPU(unsigned int, irq_count) __visible = -1;
+DEFINE_PER_CPU(int, __preempt_count) = INIT_PREEMPT_COUNT;
+EXPORT_PER_CPU_SYMBOL(__preempt_count);
+
DEFINE_PER_CPU(struct task_struct *, fpu_owner_task);
/*
@@ -1169,6 +1172,8 @@ void debug_stack_reset(void)
DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task;
EXPORT_PER_CPU_SYMBOL(current_task);
+DEFINE_PER_CPU(int, __preempt_count) = INIT_PREEMPT_COUNT;
+EXPORT_PER_CPU_SYMBOL(__preempt_count);
DEFINE_PER_CPU(struct task_struct *, fpu_owner_task);
#ifdef CONFIG_CC_STACKPROTECTOR
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index cc16faae0538..ce84edeeae27 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -164,6 +164,11 @@ struct cpu_hw_events {
struct perf_guest_switch_msr guest_switch_msrs[X86_PMC_IDX_MAX];
/*
+ * Intel checkpoint mask
+ */
+ u64 intel_cp_status;
+
+ /*
* manage shared (per-core, per-cpu) registers
* used on Intel NHM/WSM/SNB
*/
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index f31a1655d1ff..36b5ab884c15 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -190,9 +190,9 @@ static struct extra_reg intel_snbep_extra_regs[] __read_mostly = {
EVENT_EXTRA_END
};
-EVENT_ATTR_STR(mem-loads, mem_ld_nhm, "event=0x0b,umask=0x10,ldlat=3");
-EVENT_ATTR_STR(mem-loads, mem_ld_snb, "event=0xcd,umask=0x1,ldlat=3");
-EVENT_ATTR_STR(mem-stores, mem_st_snb, "event=0xcd,umask=0x2");
+EVENT_ATTR_STR(mem-loads, mem_ld_nhm, "event=0x0b,umask=0x10,ldlat=3");
+EVENT_ATTR_STR(mem-loads, mem_ld_snb, "event=0xcd,umask=0x1,ldlat=3");
+EVENT_ATTR_STR(mem-stores, mem_st_snb, "event=0xcd,umask=0x2");
struct attribute *nhm_events_attrs[] = {
EVENT_PTR(mem_ld_nhm),
@@ -1184,6 +1184,11 @@ static void intel_pmu_disable_fixed(struct hw_perf_event *hwc)
wrmsrl(hwc->config_base, ctrl_val);
}
+static inline bool event_is_checkpointed(struct perf_event *event)
+{
+ return (event->hw.config & HSW_IN_TX_CHECKPOINTED) != 0;
+}
+
static void intel_pmu_disable_event(struct perf_event *event)
{
struct hw_perf_event *hwc = &event->hw;
@@ -1197,6 +1202,7 @@ static void intel_pmu_disable_event(struct perf_event *event)
cpuc->intel_ctrl_guest_mask &= ~(1ull << hwc->idx);
cpuc->intel_ctrl_host_mask &= ~(1ull << hwc->idx);
+ cpuc->intel_cp_status &= ~(1ull << hwc->idx);
/*
* must disable before any actual event
@@ -1271,6 +1277,9 @@ static void intel_pmu_enable_event(struct perf_event *event)
if (event->attr.exclude_guest)
cpuc->intel_ctrl_host_mask |= (1ull << hwc->idx);
+ if (unlikely(event_is_checkpointed(event)))
+ cpuc->intel_cp_status |= (1ull << hwc->idx);
+
if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
intel_pmu_enable_fixed(hwc);
return;
@@ -1289,6 +1298,17 @@ static void intel_pmu_enable_event(struct perf_event *event)
int intel_pmu_save_and_restart(struct perf_event *event)
{
x86_perf_event_update(event);
+ /*
+ * For a checkpointed counter always reset back to 0. This
+ * avoids a situation where the counter overflows, aborts the
+ * transaction and is then set back to shortly before the
+ * overflow, and overflows and aborts again.
+ */
+ if (unlikely(event_is_checkpointed(event))) {
+ /* No race with NMIs because the counter should not be armed */
+ wrmsrl(event->hw.event_base, 0);
+ local64_set(&event->hw.prev_count, 0);
+ }
return x86_perf_event_set_period(event);
}
@@ -1372,6 +1392,13 @@ again:
x86_pmu.drain_pebs(regs);
}
+ /*
+ * Checkpointed counters can lead to 'spurious' PMIs because the
+ * rollback caused by the PMI will have cleared the overflow status
+ * bit. Therefore always force probe these counters.
+ */
+ status |= cpuc->intel_cp_status;
+
for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
struct perf_event *event = cpuc->events[bit];
@@ -1837,6 +1864,20 @@ static int hsw_hw_config(struct perf_event *event)
event->attr.precise_ip > 0))
return -EOPNOTSUPP;
+ if (event_is_checkpointed(event)) {
+ /*
+ * Sampling of checkpointed events can cause situations where
+ * the CPU constantly aborts because of a overflow, which is
+ * then checkpointed back and ignored. Forbid checkpointing
+ * for sampling.
+ *
+ * But still allow a long sampling period, so that perf stat
+ * from KVM works.
+ */
+ if (event->attr.sample_period > 0 &&
+ event->attr.sample_period < 0x7fffffff)
+ return -EOPNOTSUPP;
+ }
return 0;
}
@@ -2182,10 +2223,36 @@ static __init void intel_nehalem_quirk(void)
}
}
-EVENT_ATTR_STR(mem-loads, mem_ld_hsw, "event=0xcd,umask=0x1,ldlat=3");
-EVENT_ATTR_STR(mem-stores, mem_st_hsw, "event=0xd0,umask=0x82")
+EVENT_ATTR_STR(mem-loads, mem_ld_hsw, "event=0xcd,umask=0x1,ldlat=3");
+EVENT_ATTR_STR(mem-stores, mem_st_hsw, "event=0xd0,umask=0x82")
+
+/* Haswell special events */
+EVENT_ATTR_STR(tx-start, tx_start, "event=0xc9,umask=0x1");
+EVENT_ATTR_STR(tx-commit, tx_commit, "event=0xc9,umask=0x2");
+EVENT_ATTR_STR(tx-abort, tx_abort, "event=0xc9,umask=0x4");
+EVENT_ATTR_STR(tx-capacity, tx_capacity, "event=0x54,umask=0x2");
+EVENT_ATTR_STR(tx-conflict, tx_conflict, "event=0x54,umask=0x1");
+EVENT_ATTR_STR(el-start, el_start, "event=0xc8,umask=0x1");
+EVENT_ATTR_STR(el-commit, el_commit, "event=0xc8,umask=0x2");
+EVENT_ATTR_STR(el-abort, el_abort, "event=0xc8,umask=0x4");
+EVENT_ATTR_STR(el-capacity, el_capacity, "event=0x54,umask=0x2");
+EVENT_ATTR_STR(el-conflict, el_conflict, "event=0x54,umask=0x1");
+EVENT_ATTR_STR(cycles-t, cycles_t, "event=0x3c,in_tx=1");
+EVENT_ATTR_STR(cycles-ct, cycles_ct, "event=0x3c,in_tx=1,in_tx_cp=1");
static struct attribute *hsw_events_attrs[] = {
+ EVENT_PTR(tx_start),
+ EVENT_PTR(tx_commit),
+ EVENT_PTR(tx_abort),
+ EVENT_PTR(tx_capacity),
+ EVENT_PTR(tx_conflict),
+ EVENT_PTR(el_start),
+ EVENT_PTR(el_commit),
+ EVENT_PTR(el_abort),
+ EVENT_PTR(el_capacity),
+ EVENT_PTR(el_conflict),
+ EVENT_PTR(cycles_t),
+ EVENT_PTR(cycles_ct),
EVENT_PTR(mem_ld_hsw),
EVENT_PTR(mem_st_hsw),
NULL
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index ab3ba1c1b7dd..07d9a052ee72 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -182,16 +182,28 @@ struct pebs_record_nhm {
* Same as pebs_record_nhm, with two additional fields.
*/
struct pebs_record_hsw {
- struct pebs_record_nhm nhm;
- /*
- * Real IP of the event. In the Intel documentation this
- * is called eventingrip.
- */
- u64 real_ip;
- /*
- * TSX tuning information field: abort cycles and abort flags.
- */
- u64 tsx_tuning;
+ u64 flags, ip;
+ u64 ax, bx, cx, dx;
+ u64 si, di, bp, sp;
+ u64 r8, r9, r10, r11;
+ u64 r12, r13, r14, r15;
+ u64 status, dla, dse, lat;
+ u64 real_ip, tsx_tuning;
+};
+
+union hsw_tsx_tuning {
+ struct {
+ u32 cycles_last_block : 32,
+ hle_abort : 1,
+ rtm_abort : 1,
+ instruction_abort : 1,
+ non_instruction_abort : 1,
+ retry : 1,
+ data_conflict : 1,
+ capacity_writes : 1,
+ capacity_reads : 1;
+ };
+ u64 value;
};
void init_debug_store_on_cpu(int cpu)
@@ -786,16 +798,24 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
return 0;
}
+static inline u64 intel_hsw_weight(struct pebs_record_hsw *pebs)
+{
+ if (pebs->tsx_tuning) {
+ union hsw_tsx_tuning tsx = { .value = pebs->tsx_tuning };
+ return tsx.cycles_last_block;
+ }
+ return 0;
+}
+
static void __intel_pmu_pebs_event(struct perf_event *event,
struct pt_regs *iregs, void *__pebs)
{
/*
- * We cast to pebs_record_nhm to get the load latency data
- * if extra_reg MSR_PEBS_LD_LAT_THRESHOLD used
+ * We cast to the biggest pebs_record but are careful not to
+ * unconditionally access the 'extra' entries.
*/
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
- struct pebs_record_nhm *pebs = __pebs;
- struct pebs_record_hsw *pebs_hsw = __pebs;
+ struct pebs_record_hsw *pebs = __pebs;
struct perf_sample_data data;
struct pt_regs regs;
u64 sample_type;
@@ -854,7 +874,7 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
regs.sp = pebs->sp;
if (event->attr.precise_ip > 1 && x86_pmu.intel_cap.pebs_format >= 2) {
- regs.ip = pebs_hsw->real_ip;
+ regs.ip = pebs->real_ip;
regs.flags |= PERF_EFLAGS_EXACT;
} else if (event->attr.precise_ip > 1 && intel_pmu_pebs_fixup_ip(&regs))
regs.flags |= PERF_EFLAGS_EXACT;
@@ -862,9 +882,14 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
regs.flags &= ~PERF_EFLAGS_EXACT;
if ((event->attr.sample_type & PERF_SAMPLE_ADDR) &&
- x86_pmu.intel_cap.pebs_format >= 1)
+ x86_pmu.intel_cap.pebs_format >= 1)
data.addr = pebs->dla;
+ /* Only set the TSX weight when no memory weight was requested. */
+ if ((event->attr.sample_type & PERF_SAMPLE_WEIGHT) && !fll &&
+ (x86_pmu.intel_cap.pebs_format >= 2))
+ data.weight = intel_hsw_weight(pebs);
+
if (has_branch_stack(event))
data.br_stack = &cpuc->lbr_stack;
@@ -913,17 +938,34 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
__intel_pmu_pebs_event(event, iregs, at);
}
-static void __intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, void *at,
- void *top)
+static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
struct debug_store *ds = cpuc->ds;
struct perf_event *event = NULL;
+ void *at, *top;
u64 status = 0;
int bit;
+ if (!x86_pmu.pebs_active)
+ return;
+
+ at = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base;
+ top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index;
+
ds->pebs_index = ds->pebs_buffer_base;
+ if (unlikely(at > top))
+ return;
+
+ /*
+ * Should not happen, we program the threshold at 1 and do not
+ * set a reset value.
+ */
+ WARN_ONCE(top - at > x86_pmu.max_pebs_events * x86_pmu.pebs_record_size,
+ "Unexpected number of pebs records %ld\n",
+ (long)(top - at) / x86_pmu.pebs_record_size);
+
for (; at < top; at += x86_pmu.pebs_record_size) {
struct pebs_record_nhm *p = at;
@@ -951,61 +993,6 @@ static void __intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, void *at,
}
}
-static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
-{
- struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
- struct debug_store *ds = cpuc->ds;
- struct pebs_record_nhm *at, *top;
- int n;
-
- if (!x86_pmu.pebs_active)
- return;
-
- at = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base;
- top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index;
-
- ds->pebs_index = ds->pebs_buffer_base;
-
- n = top - at;
- if (n <= 0)
- return;
-
- /*
- * Should not happen, we program the threshold at 1 and do not
- * set a reset value.
- */
- WARN_ONCE(n > x86_pmu.max_pebs_events,
- "Unexpected number of pebs records %d\n", n);
-
- return __intel_pmu_drain_pebs_nhm(iregs, at, top);
-}
-
-static void intel_pmu_drain_pebs_hsw(struct pt_regs *iregs)
-{
- struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
- struct debug_store *ds = cpuc->ds;
- struct pebs_record_hsw *at, *top;
- int n;
-
- if (!x86_pmu.pebs_active)
- return;
-
- at = (struct pebs_record_hsw *)(unsigned long)ds->pebs_buffer_base;
- top = (struct pebs_record_hsw *)(unsigned long)ds->pebs_index;
-
- n = top - at;
- if (n <= 0)
- return;
- /*
- * Should not happen, we program the threshold at 1 and do not
- * set a reset value.
- */
- WARN_ONCE(n > x86_pmu.max_pebs_events,
- "Unexpected number of pebs records %d\n", n);
-
- return __intel_pmu_drain_pebs_nhm(iregs, at, top);
-}
-
/*
* BTS, PEBS probe and setup
*/
@@ -1040,7 +1027,7 @@ void intel_ds_init(void)
case 2:
pr_cont("PEBS fmt2%c, ", pebs_type);
x86_pmu.pebs_record_size = sizeof(struct pebs_record_hsw);
- x86_pmu.drain_pebs = intel_pmu_drain_pebs_hsw;
+ x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm;
break;
default:
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index f0dcb0ceb6a2..fd1bc1b15e6d 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -362,12 +362,9 @@ END(ret_from_exception)
#ifdef CONFIG_PREEMPT
ENTRY(resume_kernel)
DISABLE_INTERRUPTS(CLBR_ANY)
- cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ?
- jnz restore_all
need_resched:
- movl TI_flags(%ebp), %ecx # need_resched set ?
- testb $_TIF_NEED_RESCHED, %cl
- jz restore_all
+ cmpl $0,PER_CPU_VAR(__preempt_count)
+ jnz restore_all
testl $X86_EFLAGS_IF,PT_EFLAGS(%esp) # interrupts off (exception path) ?
jz restore_all
call preempt_schedule_irq
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index b077f4cc225a..1a2cc64abcd7 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1103,10 +1103,8 @@ retint_signal:
/* Returning to kernel space. Check if we need preemption */
/* rcx: threadinfo. interrupts off. */
ENTRY(retint_kernel)
- cmpl $0,TI_preempt_count(%rcx)
+ cmpl $0,PER_CPU_VAR(__preempt_count)
jnz retint_restore_args
- bt $TIF_NEED_RESCHED,TI_flags(%rcx)
- jnc retint_restore_args
bt $9,EFLAGS-ARGOFFSET(%rsp) /* interrupts off? */
jnc retint_restore_args
call preempt_schedule_irq
diff --git a/arch/x86/kernel/i386_ksyms_32.c b/arch/x86/kernel/i386_ksyms_32.c
index 0fa69127209a..05fd74f537d6 100644
--- a/arch/x86/kernel/i386_ksyms_32.c
+++ b/arch/x86/kernel/i386_ksyms_32.c
@@ -37,3 +37,10 @@ EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL(empty_zero_page);
+
+#ifdef CONFIG_PREEMPT
+EXPORT_SYMBOL(___preempt_schedule);
+#ifdef CONFIG_CONTEXT_TRACKING
+EXPORT_SYMBOL(___preempt_schedule_context);
+#endif
+#endif
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
index 9a5c460404dc..2e977b5d61dd 100644
--- a/arch/x86/kernel/i8259.c
+++ b/arch/x86/kernel/i8259.c
@@ -312,8 +312,7 @@ static void init_8259A(int auto_eoi)
*/
outb_pic(0x11, PIC_MASTER_CMD); /* ICW1: select 8259A-1 init */
- /* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 on x86-64,
- to 0x20-0x27 on i386 */
+ /* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 */
outb_pic(IRQ0_VECTOR, PIC_MASTER_IMR);
/* 8259A-1 (the master) has a slave on IR2 */
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index 4186755f1d7c..3fe066359ac0 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -100,9 +100,6 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)
irqctx->tinfo.task = curctx->tinfo.task;
irqctx->tinfo.previous_esp = current_stack_pointer;
- /* Copy the preempt_count so that the [soft]irq checks work. */
- irqctx->tinfo.preempt_count = curctx->tinfo.preempt_count;
-
if (unlikely(overflow))
call_on_stack(print_stack_overflow, isp);
@@ -131,7 +128,6 @@ void irq_ctx_init(int cpu)
THREAD_SIZE_ORDER));
memset(&irqctx->tinfo, 0, sizeof(struct thread_info));
irqctx->tinfo.cpu = cpu;
- irqctx->tinfo.preempt_count = HARDIRQ_OFFSET;
irqctx->tinfo.addr_limit = MAKE_MM_SEG(0);
per_cpu(hardirq_ctx, cpu) = irqctx;
diff --git a/arch/x86/kernel/preempt.S b/arch/x86/kernel/preempt.S
new file mode 100644
index 000000000000..ca7f0d58a87d
--- /dev/null
+++ b/arch/x86/kernel/preempt.S
@@ -0,0 +1,25 @@
+
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+#include <asm/asm.h>
+#include <asm/calling.h>
+
+ENTRY(___preempt_schedule)
+ CFI_STARTPROC
+ SAVE_ALL
+ call preempt_schedule
+ RESTORE_ALL
+ ret
+ CFI_ENDPROC
+
+#ifdef CONFIG_CONTEXT_TRACKING
+
+ENTRY(___preempt_schedule_context)
+ CFI_STARTPROC
+ SAVE_ALL
+ call preempt_schedule_context
+ RESTORE_ALL
+ ret
+ CFI_ENDPROC
+
+#endif
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index c83516be1052..3fb8d95ab8b5 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -391,9 +391,9 @@ static void amd_e400_idle(void)
* The switch back from broadcast mode needs to be
* called with interrupts disabled.
*/
- local_irq_disable();
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
- local_irq_enable();
+ local_irq_disable();
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+ local_irq_enable();
} else
default_idle();
}
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 884f98f69354..c2ec1aa6d454 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -292,6 +292,14 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
set_iopl_mask(next->iopl);
/*
+ * If it were not for PREEMPT_ACTIVE we could guarantee that the
+ * preempt_count of all tasks was equal here and this would not be
+ * needed.
+ */
+ task_thread_info(prev_p)->saved_preempt_count = this_cpu_read(__preempt_count);
+ this_cpu_write(__preempt_count, task_thread_info(next_p)->saved_preempt_count);
+
+ /*
* Now maybe handle debug registers and/or IO bitmaps
*/
if (unlikely(task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV ||
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index bb1dc51bab05..45ab4d6fc8a7 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -363,6 +363,14 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
this_cpu_write(old_rsp, next->usersp);
this_cpu_write(current_task, next_p);
+ /*
+ * If it were not for PREEMPT_ACTIVE we could guarantee that the
+ * preempt_count of all tasks was equal here and this would not be
+ * needed.
+ */
+ task_thread_info(prev_p)->saved_preempt_count = this_cpu_read(__preempt_count);
+ this_cpu_write(__preempt_count, task_thread_info(next_p)->saved_preempt_count);
+
this_cpu_write(kernel_stack,
(unsigned long)task_stack_page(next_p) +
THREAD_SIZE - KERNEL_STACK_OFFSET);
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index e643e744e4d8..f0783a68db11 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -527,10 +527,13 @@ static void native_machine_emergency_restart(void)
case BOOT_CF9_COND:
if (port_cf9_safe) {
- u8 cf9 = inb(0xcf9) & ~6;
+ u8 reboot_code = reboot_mode == REBOOT_WARM ?
+ 0x06 : 0x0E;
+ u8 cf9 = inb(0xcf9) & ~reboot_code;
outb(cf9|2, 0xcf9); /* Request hard reset */
udelay(50);
- outb(cf9|6, 0xcf9); /* Actually do the reset */
+ /* Actually do the reset */
+ outb(cf9|reboot_code, 0xcf9);
udelay(50);
}
reboot_type = BOOT_KBD;
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 6cacab671f9b..e73b3f53310c 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -82,27 +82,6 @@
/* State of each CPU */
DEFINE_PER_CPU(int, cpu_state) = { 0 };
-#ifdef CONFIG_HOTPLUG_CPU
-/*
- * We need this for trampoline_base protection from concurrent accesses when
- * off- and onlining cores wildly.
- */
-static DEFINE_MUTEX(x86_cpu_hotplug_driver_mutex);
-
-void cpu_hotplug_driver_lock(void)
-{
- mutex_lock(&x86_cpu_hotplug_driver_mutex);
-}
-
-void cpu_hotplug_driver_unlock(void)
-{
- mutex_unlock(&x86_cpu_hotplug_driver_mutex);
-}
-
-ssize_t arch_cpu_probe(const char *buf, size_t count) { return -1; }
-ssize_t arch_cpu_release(const char *buf, size_t count) { return -1; }
-#endif
-
/* Number of siblings per CPU package */
int smp_num_siblings = 1;
EXPORT_SYMBOL(smp_num_siblings);
diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c
index 6e60b5fe2244..a3f35ebb3b52 100644
--- a/arch/x86/kernel/topology.c
+++ b/arch/x86/kernel/topology.c
@@ -65,6 +65,7 @@ int __ref _debug_hotplug_cpu(int cpu, int action)
if (!cpu_is_hotpluggable(cpu))
return -EINVAL;
+ lock_device_hotplug();
cpu_hotplug_driver_lock();
switch (action) {
@@ -72,22 +73,26 @@ int __ref _debug_hotplug_cpu(int cpu, int action)
ret = cpu_down(cpu);
if (!ret) {
pr_info("CPU %u is now offline\n", cpu);
+ dev->offline = true;
kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
} else
pr_debug("Can't offline CPU%d.\n", cpu);
break;
case 1:
ret = cpu_up(cpu);
- if (!ret)
+ if (!ret) {
+ dev->offline = false;
kobject_uevent(&dev->kobj, KOBJ_ONLINE);
- else
+ } else {
pr_debug("Can't online CPU%d.\n", cpu);
+ }
break;
default:
ret = -EINVAL;
}
cpu_hotplug_driver_unlock();
+ unlock_device_hotplug();
return ret;
}
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 8c8093b146ca..729aa779ff75 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -88,7 +88,7 @@ static inline void conditional_sti(struct pt_regs *regs)
static inline void preempt_conditional_sti(struct pt_regs *regs)
{
- inc_preempt_count();
+ preempt_count_inc();
if (regs->flags & X86_EFLAGS_IF)
local_irq_enable();
}
@@ -103,7 +103,7 @@ static inline void preempt_conditional_cli(struct pt_regs *regs)
{
if (regs->flags & X86_EFLAGS_IF)
local_irq_disable();
- dec_preempt_count();
+ preempt_count_dec();
}
static int __kprobes
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index b014d9414d08..040681928e9d 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -66,3 +66,10 @@ EXPORT_SYMBOL(empty_zero_page);
#ifndef CONFIG_PARAVIRT
EXPORT_SYMBOL(native_load_gs_index);
#endif
+
+#ifdef CONFIG_PREEMPT
+EXPORT_SYMBOL(___preempt_schedule);
+#ifdef CONFIG_CONTEXT_TRACKING
+EXPORT_SYMBOL(___preempt_schedule_context);
+#endif
+#endif
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index a1216de9ffda..e6e8fbc02d5e 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2206,7 +2206,7 @@ static __init void nested_vmx_setup_ctls_msrs(void)
#endif
VM_EXIT_LOAD_IA32_PAT | VM_EXIT_SAVE_IA32_PAT;
nested_vmx_exit_ctls_high |= (VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR |
- VM_EXIT_LOAD_IA32_EFER);
+ VM_EXIT_LOAD_IA32_EFER | VM_EXIT_SAVE_IA32_EFER);
/* entry controls */
rdmsr(MSR_IA32_VMX_ENTRY_CTLS,
@@ -2252,6 +2252,7 @@ static __init void nested_vmx_setup_ctls_msrs(void)
nested_vmx_secondary_ctls_low = 0;
nested_vmx_secondary_ctls_high &=
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
+ SECONDARY_EXEC_UNRESTRICTED_GUEST |
SECONDARY_EXEC_WBINVD_EXITING;
if (enable_ept) {
@@ -3376,8 +3377,10 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
if (enable_ept) {
eptp = construct_eptp(cr3);
vmcs_write64(EPT_POINTER, eptp);
- guest_cr3 = is_paging(vcpu) ? kvm_read_cr3(vcpu) :
- vcpu->kvm->arch.ept_identity_map_addr;
+ if (is_paging(vcpu) || is_guest_mode(vcpu))
+ guest_cr3 = kvm_read_cr3(vcpu);
+ else
+ guest_cr3 = vcpu->kvm->arch.ept_identity_map_addr;
ept_load_pdptrs(vcpu);
}
@@ -4875,6 +4878,17 @@ vmx_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall)
hypercall[2] = 0xc1;
}
+static bool nested_cr0_valid(struct vmcs12 *vmcs12, unsigned long val)
+{
+ unsigned long always_on = VMXON_CR0_ALWAYSON;
+
+ if (nested_vmx_secondary_ctls_high &
+ SECONDARY_EXEC_UNRESTRICTED_GUEST &&
+ nested_cpu_has2(vmcs12, SECONDARY_EXEC_UNRESTRICTED_GUEST))
+ always_on &= ~(X86_CR0_PE | X86_CR0_PG);
+ return (val & always_on) == always_on;
+}
+
/* called to set cr0 as appropriate for a mov-to-cr0 exit. */
static int handle_set_cr0(struct kvm_vcpu *vcpu, unsigned long val)
{
@@ -4893,9 +4907,7 @@ static int handle_set_cr0(struct kvm_vcpu *vcpu, unsigned long val)
val = (val & ~vmcs12->cr0_guest_host_mask) |
(vmcs12->guest_cr0 & vmcs12->cr0_guest_host_mask);
- /* TODO: will have to take unrestricted guest mode into
- * account */
- if ((val & VMXON_CR0_ALWAYSON) != VMXON_CR0_ALWAYSON)
+ if (!nested_cr0_valid(vmcs12, val))
return 1;
if (kvm_set_cr0(vcpu, val))
@@ -7874,7 +7886,7 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
return 1;
}
- if (((vmcs12->guest_cr0 & VMXON_CR0_ALWAYSON) != VMXON_CR0_ALWAYSON) ||
+ if (!nested_cr0_valid(vmcs12, vmcs12->guest_cr0) ||
((vmcs12->guest_cr4 & VMXON_CR4_ALWAYSON) != VMXON_CR4_ALWAYSON)) {
nested_vmx_entry_failure(vcpu, vmcs12,
EXIT_REASON_INVALID_STATE, ENTRY_FAIL_DEFAULT);
@@ -8128,6 +8140,8 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
vmcs12->guest_ia32_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_IA32_PAT)
vmcs12->guest_ia32_pat = vmcs_read64(GUEST_IA32_PAT);
+ if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_IA32_EFER)
+ vmcs12->guest_ia32_efer = vcpu->arch.efer;
vmcs12->guest_sysenter_cs = vmcs_read32(GUEST_SYSENTER_CS);
vmcs12->guest_sysenter_esp = vmcs_readl(GUEST_SYSENTER_ESP);
vmcs12->guest_sysenter_eip = vmcs_readl(GUEST_SYSENTER_EIP);
@@ -8199,7 +8213,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
* fpu_active (which may have changed).
* Note that vmx_set_cr0 refers to efer set above.
*/
- kvm_set_cr0(vcpu, vmcs12->host_cr0);
+ vmx_set_cr0(vcpu, vmcs12->host_cr0);
/*
* If we did fpu_activate()/fpu_deactivate() during L2's run, we need
* to apply the same changes to L1's vmcs. We just set cr0 correctly,
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index d35363e38fe3..58bb4e96800f 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -399,8 +399,24 @@ static unsigned long __init init_range_memory_mapping(
return mapped_ram_size;
}
-/* (PUD_SHIFT-PMD_SHIFT)/2 */
-#define STEP_SIZE_SHIFT 5
+static unsigned long __init get_new_step_size(unsigned long step_size)
+{
+ /*
+ * Explain why we shift by 5 and why we don't have to worry about
+ * 'step_size << 5' overflowing:
+ *
+ * initial mapped size is PMD_SIZE (2M).
+ * We can not set step_size to be PUD_SIZE (1G) yet.
+ * In worse case, when we cross the 1G boundary, and
+ * PG_LEVEL_2M is not set, we will need 1+1+512 pages (2M + 8k)
+ * to map 1G range with PTE. Use 5 as shift for now.
+ *
+ * Don't need to worry about overflow, on 32bit, when step_size
+ * is 0, round_down() returns 0 for start, and that turns it
+ * into 0x100000000ULL.
+ */
+ return step_size << 5;
+}
/**
* memory_map_top_down - Map [map_start, map_end) top down
@@ -448,7 +464,7 @@ static void __init memory_map_top_down(unsigned long map_start,
min_pfn_mapped = last_start >> PAGE_SHIFT;
/* only increase step_size after big range get mapped */
if (new_mapped_ram_size > mapped_ram_size)
- step_size <<= STEP_SIZE_SHIFT;
+ step_size = get_new_step_size(step_size);
mapped_ram_size += new_mapped_ram_size;
}
@@ -493,7 +509,7 @@ static void __init memory_map_bottom_up(unsigned long map_start,
start = next;
if (new_mapped_ram_size > mapped_ram_size)
- step_size <<= STEP_SIZE_SHIFT;
+ step_size = get_new_step_size(step_size);
mapped_ram_size += new_mapped_ram_size;
}
}
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index f5809fa2753e..b046e070e088 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -231,7 +231,7 @@ static int quirk_pcie_aspm_write(struct pci_bus *bus, unsigned int devfn, int wh
offset = quirk_aspm_offset[GET_INDEX(bus->self->device, devfn)];
if ((offset) && (where == offset))
- value = value & 0xfffffffc;
+ value = value & ~PCI_EXP_LNKCTL_ASPMC;
return raw_pci_write(pci_domain_nr(bus), bus->number,
devfn, where, size, value);
@@ -252,7 +252,7 @@ static struct pci_ops quirk_pcie_aspm_ops = {
*/
static void pcie_rootport_aspm_quirk(struct pci_dev *pdev)
{
- int cap_base, i;
+ int i;
struct pci_bus *pbus;
struct pci_dev *dev;
@@ -278,7 +278,7 @@ static void pcie_rootport_aspm_quirk(struct pci_dev *pdev)
for (i = GET_INDEX(pdev->device, 0); i <= GET_INDEX(pdev->device, 7); ++i)
quirk_aspm_offset[i] = 0;
- pbus->ops = pbus->parent->ops;
+ pci_bus_set_ops(pbus, pbus->parent->ops);
} else {
/*
* If devices are attached to the root port at power-up or
@@ -286,13 +286,15 @@ static void pcie_rootport_aspm_quirk(struct pci_dev *pdev)
* each root port to save the register offsets and replace the
* bus ops.
*/
- list_for_each_entry(dev, &pbus->devices, bus_list) {
+ list_for_each_entry(dev, &pbus->devices, bus_list)
/* There are 0 to 8 devices attached to this bus */
- cap_base = pci_find_capability(dev, PCI_CAP_ID_EXP);
- quirk_aspm_offset[GET_INDEX(pdev->device, dev->devfn)] = cap_base + 0x10;
- }
- pbus->ops = &quirk_pcie_aspm_ops;
+ quirk_aspm_offset[GET_INDEX(pdev->device, dev->devfn)] =
+ dev->pcie_cap + PCI_EXP_LNKCTL;
+
+ pci_bus_set_ops(pbus, &quirk_pcie_aspm_ops);
+ dev_info(&pbus->dev, "writes to ASPM control bits will be ignored\n");
}
+
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PA, pcie_rootport_aspm_quirk);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PA1, pcie_rootport_aspm_quirk);
diff --git a/arch/x86/platform/olpc/olpc-xo15-sci.c b/arch/x86/platform/olpc/olpc-xo15-sci.c
index fef7d0ba7e3a..649a12befba9 100644
--- a/arch/x86/platform/olpc/olpc-xo15-sci.c
+++ b/arch/x86/platform/olpc/olpc-xo15-sci.c
@@ -40,16 +40,9 @@ static bool lid_wake_on_close;
*/
static int set_lid_wake_behavior(bool wake_on_close)
{
- struct acpi_object_list arg_list;
- union acpi_object arg;
acpi_status status;
- arg_list.count = 1;
- arg_list.pointer = &arg;
- arg.type = ACPI_TYPE_INTEGER;
- arg.integer.value = wake_on_close;
-
- status = acpi_evaluate_object(NULL, "\\_SB.PCI0.LID.LIDW", &arg_list, NULL);
+ status = acpi_execute_simple_method(NULL, "\\_SB.PCI0.LID.LIDW", wake_on_close);
if (ACPI_FAILURE(status)) {
pr_warning(PFX "failed to set lid behavior\n");
return 1;
diff --git a/arch/x86/platform/uv/Makefile b/arch/x86/platform/uv/Makefile
index 6c40995fefb8..52079bebd014 100644
--- a/arch/x86/platform/uv/Makefile
+++ b/arch/x86/platform/uv/Makefile
@@ -1 +1 @@
-obj-$(CONFIG_X86_UV) += tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o
+obj-$(CONFIG_X86_UV) += tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o uv_nmi.o
diff --git a/arch/x86/platform/uv/uv_nmi.c b/arch/x86/platform/uv/uv_nmi.c
new file mode 100644
index 000000000000..9126dfb6dbfc
--- /dev/null
+++ b/arch/x86/platform/uv/uv_nmi.c
@@ -0,0 +1,666 @@
+/*
+ * SGI NMI/TRACE support routines
+ *
+ * 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
+ *
+ * Copyright (c) 2009-2013 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) Mike Travis
+ */
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/kexec.h>
+#include <linux/module.h>
+#include <linux/nmi.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <asm/apic.h>
+#include <asm/current.h>
+#include <asm/kdebug.h>
+#include <asm/local64.h>
+#include <asm/nmi.h>
+#include <asm/uv/uv.h>
+#include <asm/uv/uv_hub.h>
+#include <asm/uv/uv_mmrs.h>
+
+void (*uv_trace_func)(const char *f, const int l, const char *fmt, ...);
+EXPORT_SYMBOL(uv_trace_func);
+
+void (*uv_trace_nmi_func)(unsigned int reason, struct pt_regs *regs);
+EXPORT_SYMBOL(uv_trace_nmi_func);
+
+
+/*
+ * UV handler for NMI
+ *
+ * Handle system-wide NMI events generated by the global 'power nmi' command.
+ *
+ * Basic operation is to field the NMI interrupt on each cpu and wait
+ * until all cpus have arrived into the nmi handler. If some cpus do not
+ * make it into the handler, try and force them in with the IPI(NMI) signal.
+ *
+ * We also have to lessen UV Hub MMR accesses as much as possible as this
+ * disrupts the UV Hub's primary mission of directing NumaLink traffic and
+ * can cause system problems to occur.
+ *
+ * To do this we register our primary NMI notifier on the NMI_UNKNOWN
+ * chain. This reduces the number of false NMI calls when the perf
+ * tools are running which generate an enormous number of NMIs per
+ * second (~4M/s for 1024 cpu threads). Our secondary NMI handler is
+ * very short as it only checks that if it has been "pinged" with the
+ * IPI(NMI) signal as mentioned above, and does not read the UV Hub's MMR.
+ *
+ */
+
+static struct uv_hub_nmi_s **uv_hub_nmi_list;
+
+DEFINE_PER_CPU(struct uv_cpu_nmi_s, __uv_cpu_nmi);
+EXPORT_PER_CPU_SYMBOL_GPL(__uv_cpu_nmi);
+
+static unsigned long nmi_mmr;
+static unsigned long nmi_mmr_clear;
+static unsigned long nmi_mmr_pending;
+
+static atomic_t uv_in_nmi;
+static atomic_t uv_nmi_cpu = ATOMIC_INIT(-1);
+static atomic_t uv_nmi_cpus_in_nmi = ATOMIC_INIT(-1);
+static atomic_t uv_nmi_slave_continue;
+static atomic_t uv_nmi_kexec_failed;
+static cpumask_var_t uv_nmi_cpu_mask;
+
+/* Values for uv_nmi_slave_continue */
+#define SLAVE_CLEAR 0
+#define SLAVE_CONTINUE 1
+#define SLAVE_EXIT 2
+
+/*
+ * Default is all stack dumps go to the console and buffer.
+ * Lower level to send to log buffer only.
+ */
+static int uv_nmi_loglevel = 7;
+module_param_named(dump_loglevel, uv_nmi_loglevel, int, 0644);
+
+/*
+ * The following values show statistics on how perf events are affecting
+ * this system.
+ */
+static int param_get_local64(char *buffer, const struct kernel_param *kp)
+{
+ return sprintf(buffer, "%lu\n", local64_read((local64_t *)kp->arg));
+}
+
+static int param_set_local64(const char *val, const struct kernel_param *kp)
+{
+ /* clear on any write */
+ local64_set((local64_t *)kp->arg, 0);
+ return 0;
+}
+
+static struct kernel_param_ops param_ops_local64 = {
+ .get = param_get_local64,
+ .set = param_set_local64,
+};
+#define param_check_local64(name, p) __param_check(name, p, local64_t)
+
+static local64_t uv_nmi_count;
+module_param_named(nmi_count, uv_nmi_count, local64, 0644);
+
+static local64_t uv_nmi_misses;
+module_param_named(nmi_misses, uv_nmi_misses, local64, 0644);
+
+static local64_t uv_nmi_ping_count;
+module_param_named(ping_count, uv_nmi_ping_count, local64, 0644);
+
+static local64_t uv_nmi_ping_misses;
+module_param_named(ping_misses, uv_nmi_ping_misses, local64, 0644);
+
+/*
+ * Following values allow tuning for large systems under heavy loading
+ */
+static int uv_nmi_initial_delay = 100;
+module_param_named(initial_delay, uv_nmi_initial_delay, int, 0644);
+
+static int uv_nmi_slave_delay = 100;
+module_param_named(slave_delay, uv_nmi_slave_delay, int, 0644);
+
+static int uv_nmi_loop_delay = 100;
+module_param_named(loop_delay, uv_nmi_loop_delay, int, 0644);
+
+static int uv_nmi_trigger_delay = 10000;
+module_param_named(trigger_delay, uv_nmi_trigger_delay, int, 0644);
+
+static int uv_nmi_wait_count = 100;
+module_param_named(wait_count, uv_nmi_wait_count, int, 0644);
+
+static int uv_nmi_retry_count = 500;
+module_param_named(retry_count, uv_nmi_retry_count, int, 0644);
+
+/*
+ * Valid NMI Actions:
+ * "dump" - dump process stack for each cpu
+ * "ips" - dump IP info for each cpu
+ * "kdump" - do crash dump
+ */
+static char uv_nmi_action[8] = "dump";
+module_param_string(action, uv_nmi_action, sizeof(uv_nmi_action), 0644);
+
+static inline bool uv_nmi_action_is(const char *action)
+{
+ return (strncmp(uv_nmi_action, action, strlen(action)) == 0);
+}
+
+/* Setup which NMI support is present in system */
+static void uv_nmi_setup_mmrs(void)
+{
+ if (uv_read_local_mmr(UVH_NMI_MMRX_SUPPORTED)) {
+ uv_write_local_mmr(UVH_NMI_MMRX_REQ,
+ 1UL << UVH_NMI_MMRX_REQ_SHIFT);
+ nmi_mmr = UVH_NMI_MMRX;
+ nmi_mmr_clear = UVH_NMI_MMRX_CLEAR;
+ nmi_mmr_pending = 1UL << UVH_NMI_MMRX_SHIFT;
+ pr_info("UV: SMI NMI support: %s\n", UVH_NMI_MMRX_TYPE);
+ } else {
+ nmi_mmr = UVH_NMI_MMR;
+ nmi_mmr_clear = UVH_NMI_MMR_CLEAR;
+ nmi_mmr_pending = 1UL << UVH_NMI_MMR_SHIFT;
+ pr_info("UV: SMI NMI support: %s\n", UVH_NMI_MMR_TYPE);
+ }
+}
+
+/* Read NMI MMR and check if NMI flag was set by BMC. */
+static inline int uv_nmi_test_mmr(struct uv_hub_nmi_s *hub_nmi)
+{
+ hub_nmi->nmi_value = uv_read_local_mmr(nmi_mmr);
+ atomic_inc(&hub_nmi->read_mmr_count);
+ return !!(hub_nmi->nmi_value & nmi_mmr_pending);
+}
+
+static inline void uv_local_mmr_clear_nmi(void)
+{
+ uv_write_local_mmr(nmi_mmr_clear, nmi_mmr_pending);
+}
+
+/*
+ * If first cpu in on this hub, set hub_nmi "in_nmi" and "owner" values and
+ * return true. If first cpu in on the system, set global "in_nmi" flag.
+ */
+static int uv_set_in_nmi(int cpu, struct uv_hub_nmi_s *hub_nmi)
+{
+ int first = atomic_add_unless(&hub_nmi->in_nmi, 1, 1);
+
+ if (first) {
+ atomic_set(&hub_nmi->cpu_owner, cpu);
+ if (atomic_add_unless(&uv_in_nmi, 1, 1))
+ atomic_set(&uv_nmi_cpu, cpu);
+
+ atomic_inc(&hub_nmi->nmi_count);
+ }
+ return first;
+}
+
+/* Check if this is a system NMI event */
+static int uv_check_nmi(struct uv_hub_nmi_s *hub_nmi)
+{
+ int cpu = smp_processor_id();
+ int nmi = 0;
+
+ local64_inc(&uv_nmi_count);
+ uv_cpu_nmi.queries++;
+
+ do {
+ nmi = atomic_read(&hub_nmi->in_nmi);
+ if (nmi)
+ break;
+
+ if (raw_spin_trylock(&hub_nmi->nmi_lock)) {
+
+ /* check hub MMR NMI flag */
+ if (uv_nmi_test_mmr(hub_nmi)) {
+ uv_set_in_nmi(cpu, hub_nmi);
+ nmi = 1;
+ break;
+ }
+
+ /* MMR NMI flag is clear */
+ raw_spin_unlock(&hub_nmi->nmi_lock);
+
+ } else {
+ /* wait a moment for the hub nmi locker to set flag */
+ cpu_relax();
+ udelay(uv_nmi_slave_delay);
+
+ /* re-check hub in_nmi flag */
+ nmi = atomic_read(&hub_nmi->in_nmi);
+ if (nmi)
+ break;
+ }
+
+ /* check if this BMC missed setting the MMR NMI flag */
+ if (!nmi) {
+ nmi = atomic_read(&uv_in_nmi);
+ if (nmi)
+ uv_set_in_nmi(cpu, hub_nmi);
+ }
+
+ } while (0);
+
+ if (!nmi)
+ local64_inc(&uv_nmi_misses);
+
+ return nmi;
+}
+
+/* Need to reset the NMI MMR register, but only once per hub. */
+static inline void uv_clear_nmi(int cpu)
+{
+ struct uv_hub_nmi_s *hub_nmi = uv_hub_nmi;
+
+ if (cpu == atomic_read(&hub_nmi->cpu_owner)) {
+ atomic_set(&hub_nmi->cpu_owner, -1);
+ atomic_set(&hub_nmi->in_nmi, 0);
+ uv_local_mmr_clear_nmi();
+ raw_spin_unlock(&hub_nmi->nmi_lock);
+ }
+}
+
+/* Print non-responding cpus */
+static void uv_nmi_nr_cpus_pr(char *fmt)
+{
+ static char cpu_list[1024];
+ int len = sizeof(cpu_list);
+ int c = cpumask_weight(uv_nmi_cpu_mask);
+ int n = cpulist_scnprintf(cpu_list, len, uv_nmi_cpu_mask);
+
+ if (n >= len-1)
+ strcpy(&cpu_list[len - 6], "...\n");
+
+ printk(fmt, c, cpu_list);
+}
+
+/* Ping non-responding cpus attemping to force them into the NMI handler */
+static void uv_nmi_nr_cpus_ping(void)
+{
+ int cpu;
+
+ for_each_cpu(cpu, uv_nmi_cpu_mask)
+ atomic_set(&uv_cpu_nmi_per(cpu).pinging, 1);
+
+ apic->send_IPI_mask(uv_nmi_cpu_mask, APIC_DM_NMI);
+}
+
+/* Clean up flags for cpus that ignored both NMI and ping */
+static void uv_nmi_cleanup_mask(void)
+{
+ int cpu;
+
+ for_each_cpu(cpu, uv_nmi_cpu_mask) {
+ atomic_set(&uv_cpu_nmi_per(cpu).pinging, 0);
+ atomic_set(&uv_cpu_nmi_per(cpu).state, UV_NMI_STATE_OUT);
+ cpumask_clear_cpu(cpu, uv_nmi_cpu_mask);
+ }
+}
+
+/* Loop waiting as cpus enter nmi handler */
+static int uv_nmi_wait_cpus(int first)
+{
+ int i, j, k, n = num_online_cpus();
+ int last_k = 0, waiting = 0;
+
+ if (first) {
+ cpumask_copy(uv_nmi_cpu_mask, cpu_online_mask);
+ k = 0;
+ } else {
+ k = n - cpumask_weight(uv_nmi_cpu_mask);
+ }
+
+ udelay(uv_nmi_initial_delay);
+ for (i = 0; i < uv_nmi_retry_count; i++) {
+ int loop_delay = uv_nmi_loop_delay;
+
+ for_each_cpu(j, uv_nmi_cpu_mask) {
+ if (atomic_read(&uv_cpu_nmi_per(j).state)) {
+ cpumask_clear_cpu(j, uv_nmi_cpu_mask);
+ if (++k >= n)
+ break;
+ }
+ }
+ if (k >= n) { /* all in? */
+ k = n;
+ break;
+ }
+ if (last_k != k) { /* abort if no new cpus coming in */
+ last_k = k;
+ waiting = 0;
+ } else if (++waiting > uv_nmi_wait_count)
+ break;
+
+ /* extend delay if waiting only for cpu 0 */
+ if (waiting && (n - k) == 1 &&
+ cpumask_test_cpu(0, uv_nmi_cpu_mask))
+ loop_delay *= 100;
+
+ udelay(loop_delay);
+ }
+ atomic_set(&uv_nmi_cpus_in_nmi, k);
+ return n - k;
+}
+
+/* Wait until all slave cpus have entered UV NMI handler */
+static void uv_nmi_wait(int master)
+{
+ /* indicate this cpu is in */
+ atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_IN);
+
+ /* if not the first cpu in (the master), then we are a slave cpu */
+ if (!master)
+ return;
+
+ do {
+ /* wait for all other cpus to gather here */
+ if (!uv_nmi_wait_cpus(1))
+ break;
+
+ /* if not all made it in, send IPI NMI to them */
+ uv_nmi_nr_cpus_pr(KERN_ALERT
+ "UV: Sending NMI IPI to %d non-responding CPUs: %s\n");
+ uv_nmi_nr_cpus_ping();
+
+ /* if all cpus are in, then done */
+ if (!uv_nmi_wait_cpus(0))
+ break;
+
+ uv_nmi_nr_cpus_pr(KERN_ALERT
+ "UV: %d CPUs not in NMI loop: %s\n");
+ } while (0);
+
+ pr_alert("UV: %d of %d CPUs in NMI\n",
+ atomic_read(&uv_nmi_cpus_in_nmi), num_online_cpus());
+}
+
+static void uv_nmi_dump_cpu_ip_hdr(void)
+{
+ printk(KERN_DEFAULT
+ "\nUV: %4s %6s %-32s %s (Note: PID 0 not listed)\n",
+ "CPU", "PID", "COMMAND", "IP");
+}
+
+static void uv_nmi_dump_cpu_ip(int cpu, struct pt_regs *regs)
+{
+ printk(KERN_DEFAULT "UV: %4d %6d %-32.32s ",
+ cpu, current->pid, current->comm);
+
+ printk_address(regs->ip, 1);
+}
+
+/* Dump this cpu's state */
+static void uv_nmi_dump_state_cpu(int cpu, struct pt_regs *regs)
+{
+ const char *dots = " ................................. ";
+
+ if (uv_nmi_action_is("ips")) {
+ if (cpu == 0)
+ uv_nmi_dump_cpu_ip_hdr();
+
+ if (current->pid != 0)
+ uv_nmi_dump_cpu_ip(cpu, regs);
+
+ } else if (uv_nmi_action_is("dump")) {
+ printk(KERN_DEFAULT
+ "UV:%sNMI process trace for CPU %d\n", dots, cpu);
+ show_regs(regs);
+ }
+ atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_DUMP_DONE);
+}
+
+/* Trigger a slave cpu to dump it's state */
+static void uv_nmi_trigger_dump(int cpu)
+{
+ int retry = uv_nmi_trigger_delay;
+
+ if (atomic_read(&uv_cpu_nmi_per(cpu).state) != UV_NMI_STATE_IN)
+ return;
+
+ atomic_set(&uv_cpu_nmi_per(cpu).state, UV_NMI_STATE_DUMP);
+ do {
+ cpu_relax();
+ udelay(10);
+ if (atomic_read(&uv_cpu_nmi_per(cpu).state)
+ != UV_NMI_STATE_DUMP)
+ return;
+ } while (--retry > 0);
+
+ pr_crit("UV: CPU %d stuck in process dump function\n", cpu);
+ atomic_set(&uv_cpu_nmi_per(cpu).state, UV_NMI_STATE_DUMP_DONE);
+}
+
+/* Wait until all cpus ready to exit */
+static void uv_nmi_sync_exit(int master)
+{
+ atomic_dec(&uv_nmi_cpus_in_nmi);
+ if (master) {
+ while (atomic_read(&uv_nmi_cpus_in_nmi) > 0)
+ cpu_relax();
+ atomic_set(&uv_nmi_slave_continue, SLAVE_CLEAR);
+ } else {
+ while (atomic_read(&uv_nmi_slave_continue))
+ cpu_relax();
+ }
+}
+
+/* Walk through cpu list and dump state of each */
+static void uv_nmi_dump_state(int cpu, struct pt_regs *regs, int master)
+{
+ if (master) {
+ int tcpu;
+ int ignored = 0;
+ int saved_console_loglevel = console_loglevel;
+
+ pr_alert("UV: tracing %s for %d CPUs from CPU %d\n",
+ uv_nmi_action_is("ips") ? "IPs" : "processes",
+ atomic_read(&uv_nmi_cpus_in_nmi), cpu);
+
+ console_loglevel = uv_nmi_loglevel;
+ atomic_set(&uv_nmi_slave_continue, SLAVE_EXIT);
+ for_each_online_cpu(tcpu) {
+ if (cpumask_test_cpu(tcpu, uv_nmi_cpu_mask))
+ ignored++;
+ else if (tcpu == cpu)
+ uv_nmi_dump_state_cpu(tcpu, regs);
+ else
+ uv_nmi_trigger_dump(tcpu);
+ }
+ if (ignored)
+ printk(KERN_DEFAULT "UV: %d CPUs ignored NMI\n",
+ ignored);
+
+ console_loglevel = saved_console_loglevel;
+ pr_alert("UV: process trace complete\n");
+ } else {
+ while (!atomic_read(&uv_nmi_slave_continue))
+ cpu_relax();
+ while (atomic_read(&uv_cpu_nmi.state) != UV_NMI_STATE_DUMP)
+ cpu_relax();
+ uv_nmi_dump_state_cpu(cpu, regs);
+ }
+ uv_nmi_sync_exit(master);
+}
+
+static void uv_nmi_touch_watchdogs(void)
+{
+ touch_softlockup_watchdog_sync();
+ clocksource_touch_watchdog();
+ rcu_cpu_stall_reset();
+ touch_nmi_watchdog();
+}
+
+#if defined(CONFIG_KEXEC)
+static void uv_nmi_kdump(int cpu, int master, struct pt_regs *regs)
+{
+ /* Call crash to dump system state */
+ if (master) {
+ pr_emerg("UV: NMI executing crash_kexec on CPU%d\n", cpu);
+ crash_kexec(regs);
+
+ pr_emerg("UV: crash_kexec unexpectedly returned, ");
+ if (!kexec_crash_image) {
+ pr_cont("crash kernel not loaded\n");
+ atomic_set(&uv_nmi_kexec_failed, 1);
+ uv_nmi_sync_exit(1);
+ return;
+ }
+ pr_cont("kexec busy, stalling cpus while waiting\n");
+ }
+
+ /* If crash exec fails the slaves should return, otherwise stall */
+ while (atomic_read(&uv_nmi_kexec_failed) == 0)
+ mdelay(10);
+
+ /* Crash kernel most likely not loaded, return in an orderly fashion */
+ uv_nmi_sync_exit(0);
+}
+
+#else /* !CONFIG_KEXEC */
+static inline void uv_nmi_kdump(int cpu, int master, struct pt_regs *regs)
+{
+ if (master)
+ pr_err("UV: NMI kdump: KEXEC not supported in this kernel\n");
+}
+#endif /* !CONFIG_KEXEC */
+
+/*
+ * UV NMI handler
+ */
+int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
+{
+ struct uv_hub_nmi_s *hub_nmi = uv_hub_nmi;
+ int cpu = smp_processor_id();
+ int master = 0;
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ /* If not a UV System NMI, ignore */
+ if (!atomic_read(&uv_cpu_nmi.pinging) && !uv_check_nmi(hub_nmi)) {
+ local_irq_restore(flags);
+ return NMI_DONE;
+ }
+
+ /* Call possible NMI trace function */
+ if (unlikely(uv_trace_nmi_func))
+ (uv_trace_nmi_func)(reason, regs);
+
+ /* Indicate we are the first CPU into the NMI handler */
+ master = (atomic_read(&uv_nmi_cpu) == cpu);
+
+ /* If NMI action is "kdump", then attempt to do it */
+ if (uv_nmi_action_is("kdump"))
+ uv_nmi_kdump(cpu, master, regs);
+
+ /* Pause as all cpus enter the NMI handler */
+ uv_nmi_wait(master);
+
+ /* Dump state of each cpu */
+ if (uv_nmi_action_is("ips") || uv_nmi_action_is("dump"))
+ uv_nmi_dump_state(cpu, regs, master);
+
+ /* Clear per_cpu "in nmi" flag */
+ atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_OUT);
+
+ /* Clear MMR NMI flag on each hub */
+ uv_clear_nmi(cpu);
+
+ /* Clear global flags */
+ if (master) {
+ if (cpumask_weight(uv_nmi_cpu_mask))
+ uv_nmi_cleanup_mask();
+ atomic_set(&uv_nmi_cpus_in_nmi, -1);
+ atomic_set(&uv_nmi_cpu, -1);
+ atomic_set(&uv_in_nmi, 0);
+ }
+
+ uv_nmi_touch_watchdogs();
+ local_irq_restore(flags);
+
+ return NMI_HANDLED;
+}
+
+/*
+ * NMI handler for pulling in CPUs when perf events are grabbing our NMI
+ */
+int uv_handle_nmi_ping(unsigned int reason, struct pt_regs *regs)
+{
+ int ret;
+
+ uv_cpu_nmi.queries++;
+ if (!atomic_read(&uv_cpu_nmi.pinging)) {
+ local64_inc(&uv_nmi_ping_misses);
+ return NMI_DONE;
+ }
+
+ uv_cpu_nmi.pings++;
+ local64_inc(&uv_nmi_ping_count);
+ ret = uv_handle_nmi(reason, regs);
+ atomic_set(&uv_cpu_nmi.pinging, 0);
+ return ret;
+}
+
+void uv_register_nmi_notifier(void)
+{
+ if (register_nmi_handler(NMI_UNKNOWN, uv_handle_nmi, 0, "uv"))
+ pr_warn("UV: NMI handler failed to register\n");
+
+ if (register_nmi_handler(NMI_LOCAL, uv_handle_nmi_ping, 0, "uvping"))
+ pr_warn("UV: PING NMI handler failed to register\n");
+}
+
+void uv_nmi_init(void)
+{
+ unsigned int value;
+
+ /*
+ * Unmask NMI on all cpus
+ */
+ value = apic_read(APIC_LVT1) | APIC_DM_NMI;
+ value &= ~APIC_LVT_MASKED;
+ apic_write(APIC_LVT1, value);
+}
+
+void uv_nmi_setup(void)
+{
+ int size = sizeof(void *) * (1 << NODES_SHIFT);
+ int cpu, nid;
+
+ /* Setup hub nmi info */
+ uv_nmi_setup_mmrs();
+ uv_hub_nmi_list = kzalloc(size, GFP_KERNEL);
+ pr_info("UV: NMI hub list @ 0x%p (%d)\n", uv_hub_nmi_list, size);
+ BUG_ON(!uv_hub_nmi_list);
+ size = sizeof(struct uv_hub_nmi_s);
+ for_each_present_cpu(cpu) {
+ nid = cpu_to_node(cpu);
+ if (uv_hub_nmi_list[nid] == NULL) {
+ uv_hub_nmi_list[nid] = kzalloc_node(size,
+ GFP_KERNEL, nid);
+ BUG_ON(!uv_hub_nmi_list[nid]);
+ raw_spin_lock_init(&(uv_hub_nmi_list[nid]->nmi_lock));
+ atomic_set(&uv_hub_nmi_list[nid]->cpu_owner, -1);
+ }
+ uv_hub_nmi_per(cpu) = uv_hub_nmi_list[nid];
+ }
+ BUG_ON(!alloc_cpumask_var(&uv_nmi_cpu_mask, GFP_KERNEL));
+}
+
+
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 1b982641ec35..228d6aee3a16 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += termios.h
generic-y += topology.h
generic-y += trace_clock.h
generic-y += xor.h
+generic-y += preempt.h
diff --git a/block/partitions/Makefile b/block/partitions/Makefile
index 37a95270503c..3a484689073f 100644
--- a/block/partitions/Makefile
+++ b/block/partitions/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_IBM_PARTITION) += ibm.o
obj-$(CONFIG_EFI_PARTITION) += efi.o
obj-$(CONFIG_KARMA_PARTITION) += karma.o
obj-$(CONFIG_SYSV68_PARTITION) += sysv68.o
+obj-$(CONFIG_BLOCKCONSOLE) += blockconsole.o
diff --git a/block/partitions/blockconsole.c b/block/partitions/blockconsole.c
new file mode 100644
index 000000000000..79796a8799e9
--- /dev/null
+++ b/block/partitions/blockconsole.c
@@ -0,0 +1,22 @@
+#include <linux/blockconsole.h>
+
+#include "check.h"
+
+int blockconsole_partition(struct parsed_partitions *state)
+{
+ Sector sect;
+ void *data;
+ int err = 0;
+
+ data = read_part_sector(state, 0, &sect);
+ if (!data)
+ return -EIO;
+ if (!bcon_magic_present(data))
+ goto out;
+
+ bcon_add(state->name);
+ err = 1;
+out:
+ put_dev_sector(sect);
+ return err;
+}
diff --git a/block/partitions/check.c b/block/partitions/check.c
index 9ac1df74f699..ca671199cea0 100644
--- a/block/partitions/check.c
+++ b/block/partitions/check.c
@@ -43,6 +43,9 @@ static int (*check_part[])(struct parsed_partitions *) = {
* Probe partition formats with tables at disk address 0
* that also have an ADFS boot block at 0xdc0.
*/
+#ifdef CONFIG_BLOCKCONSOLE
+ blockconsole_partition,
+#endif
#ifdef CONFIG_ACORN_PARTITION_ICS
adfspart_check_ICS,
#endif
diff --git a/block/partitions/check.h b/block/partitions/check.h
index eade17ea910b..bca962498642 100644
--- a/block/partitions/check.h
+++ b/block/partitions/check.h
@@ -52,3 +52,6 @@ put_partition(struct parsed_partitions *p, int n, sector_t from, sector_t size)
extern int warn_no_part;
+#ifdef CONFIG_BLOCKCONSOLE
+int blockconsole_partition(struct parsed_partitions *state);
+#endif
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 69ce573f1224..7c0a4c5de075 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -174,9 +174,8 @@ config CRYPTO_TEST
help
Quick & dirty crypto test module.
-config CRYPTO_ABLK_HELPER_X86
+config CRYPTO_ABLK_HELPER
tristate
- depends on X86
select CRYPTO_CRYPTD
config CRYPTO_GLUE_HELPER_X86
@@ -695,7 +694,7 @@ config CRYPTO_AES_NI_INTEL
select CRYPTO_AES_X86_64 if 64BIT
select CRYPTO_AES_586 if !64BIT
select CRYPTO_CRYPTD
- select CRYPTO_ABLK_HELPER_X86
+ select CRYPTO_ABLK_HELPER
select CRYPTO_ALGAPI
select CRYPTO_GLUE_HELPER_X86 if 64BIT
select CRYPTO_LRW
@@ -879,7 +878,7 @@ config CRYPTO_CAMELLIA_AESNI_AVX_X86_64
depends on CRYPTO
select CRYPTO_ALGAPI
select CRYPTO_CRYPTD
- select CRYPTO_ABLK_HELPER_X86
+ select CRYPTO_ABLK_HELPER
select CRYPTO_GLUE_HELPER_X86
select CRYPTO_CAMELLIA_X86_64
select CRYPTO_LRW
@@ -901,7 +900,7 @@ config CRYPTO_CAMELLIA_AESNI_AVX2_X86_64
depends on CRYPTO
select CRYPTO_ALGAPI
select CRYPTO_CRYPTD
- select CRYPTO_ABLK_HELPER_X86
+ select CRYPTO_ABLK_HELPER
select CRYPTO_GLUE_HELPER_X86
select CRYPTO_CAMELLIA_X86_64
select CRYPTO_CAMELLIA_AESNI_AVX_X86_64
@@ -953,7 +952,7 @@ config CRYPTO_CAST5_AVX_X86_64
depends on X86 && 64BIT
select CRYPTO_ALGAPI
select CRYPTO_CRYPTD
- select CRYPTO_ABLK_HELPER_X86
+ select CRYPTO_ABLK_HELPER
select CRYPTO_CAST_COMMON
select CRYPTO_CAST5
help
@@ -976,7 +975,7 @@ config CRYPTO_CAST6_AVX_X86_64
depends on X86 && 64BIT
select CRYPTO_ALGAPI
select CRYPTO_CRYPTD
- select CRYPTO_ABLK_HELPER_X86
+ select CRYPTO_ABLK_HELPER
select CRYPTO_GLUE_HELPER_X86
select CRYPTO_CAST_COMMON
select CRYPTO_CAST6
@@ -1094,7 +1093,7 @@ config CRYPTO_SERPENT_SSE2_X86_64
depends on X86 && 64BIT
select CRYPTO_ALGAPI
select CRYPTO_CRYPTD
- select CRYPTO_ABLK_HELPER_X86
+ select CRYPTO_ABLK_HELPER
select CRYPTO_GLUE_HELPER_X86
select CRYPTO_SERPENT
select CRYPTO_LRW
@@ -1116,7 +1115,7 @@ config CRYPTO_SERPENT_SSE2_586
depends on X86 && !64BIT
select CRYPTO_ALGAPI
select CRYPTO_CRYPTD
- select CRYPTO_ABLK_HELPER_X86
+ select CRYPTO_ABLK_HELPER
select CRYPTO_GLUE_HELPER_X86
select CRYPTO_SERPENT
select CRYPTO_LRW
@@ -1138,7 +1137,7 @@ config CRYPTO_SERPENT_AVX_X86_64
depends on X86 && 64BIT
select CRYPTO_ALGAPI
select CRYPTO_CRYPTD
- select CRYPTO_ABLK_HELPER_X86
+ select CRYPTO_ABLK_HELPER
select CRYPTO_GLUE_HELPER_X86
select CRYPTO_SERPENT
select CRYPTO_LRW
@@ -1160,7 +1159,7 @@ config CRYPTO_SERPENT_AVX2_X86_64
depends on X86 && 64BIT
select CRYPTO_ALGAPI
select CRYPTO_CRYPTD
- select CRYPTO_ABLK_HELPER_X86
+ select CRYPTO_ABLK_HELPER
select CRYPTO_GLUE_HELPER_X86
select CRYPTO_SERPENT
select CRYPTO_SERPENT_AVX_X86_64
@@ -1276,7 +1275,7 @@ config CRYPTO_TWOFISH_AVX_X86_64
depends on X86 && 64BIT
select CRYPTO_ALGAPI
select CRYPTO_CRYPTD
- select CRYPTO_ABLK_HELPER_X86
+ select CRYPTO_ABLK_HELPER
select CRYPTO_GLUE_HELPER_X86
select CRYPTO_TWOFISH_COMMON
select CRYPTO_TWOFISH_X86_64
diff --git a/crypto/Makefile b/crypto/Makefile
index 80019ba8da3a..5e1bdb1b6e5e 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -104,3 +104,4 @@ obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o
obj-$(CONFIG_XOR_BLOCKS) += xor.o
obj-$(CONFIG_ASYNC_CORE) += async_tx/
obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/
+obj-$(CONFIG_CRYPTO_ABLK_HELPER) += ablk_helper.o
diff --git a/arch/x86/crypto/ablk_helper.c b/crypto/ablk_helper.c
index 43282fe04a8b..62568b1fc885 100644
--- a/arch/x86/crypto/ablk_helper.c
+++ b/crypto/ablk_helper.c
@@ -28,10 +28,11 @@
#include <linux/crypto.h>
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/hardirq.h>
#include <crypto/algapi.h>
#include <crypto/cryptd.h>
-#include <asm/i387.h>
-#include <asm/crypto/ablk_helper.h>
+#include <crypto/ablk_helper.h>
+#include <asm/simd.h>
int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key,
unsigned int key_len)
@@ -70,7 +71,7 @@ int ablk_encrypt(struct ablkcipher_request *req)
struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm);
- if (!irq_fpu_usable()) {
+ if (!may_use_simd()) {
struct ablkcipher_request *cryptd_req =
ablkcipher_request_ctx(req);
@@ -89,7 +90,7 @@ int ablk_decrypt(struct ablkcipher_request *req)
struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
struct async_helper_ctx *ctx = crypto_ablkcipher_ctx(tfm);
- if (!irq_fpu_usable()) {
+ if (!may_use_simd()) {
struct ablkcipher_request *cryptd_req =
ablkcipher_request_ctx(req);
diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c
index c0bb3778f1ae..666f1962a160 100644
--- a/crypto/ansi_cprng.c
+++ b/crypto/ansi_cprng.c
@@ -230,11 +230,11 @@ remainder:
*/
if (byte_count < DEFAULT_BLK_SZ) {
empty_rbuf:
- for (; ctx->rand_data_valid < DEFAULT_BLK_SZ;
- ctx->rand_data_valid++) {
+ while (ctx->rand_data_valid < DEFAULT_BLK_SZ) {
*ptr = ctx->rand_data[ctx->rand_data_valid];
ptr++;
byte_count--;
+ ctx->rand_data_valid++;
if (byte_count == 0)
goto done;
}
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 22327e6a7236..d130e2c115cc 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -175,9 +175,10 @@ config ACPI_PROCESSOR
To compile this driver as a module, choose M here:
the module will be called processor.
+
config ACPI_IPMI
tristate "IPMI"
- depends on IPMI_SI && IPMI_HANDLER
+ depends on IPMI_SI
default n
help
This driver enables the ACPI to access the BMC controller. And it
diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c
index f40acef80269..ac0f52f6df2b 100644
--- a/drivers/acpi/acpi_ipmi.c
+++ b/drivers/acpi/acpi_ipmi.c
@@ -1,8 +1,9 @@
/*
* acpi_ipmi.c - ACPI IPMI opregion
*
- * Copyright (C) 2010 Intel Corporation
- * Copyright (C) 2010 Zhao Yakui <yakui.zhao@intel.com>
+ * Copyright (C) 2010, 2013 Intel Corporation
+ * Author: Zhao Yakui <yakui.zhao@intel.com>
+ * Lv Zheng <lv.zheng@intel.com>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
@@ -23,59 +24,58 @@
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
-#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
#include <linux/ipmi.h>
-#include <linux/device.h>
-#include <linux/pnp.h>
+#include <linux/spinlock.h>
MODULE_AUTHOR("Zhao Yakui");
MODULE_DESCRIPTION("ACPI IPMI Opregion driver");
MODULE_LICENSE("GPL");
-#define IPMI_FLAGS_HANDLER_INSTALL 0
-
#define ACPI_IPMI_OK 0
#define ACPI_IPMI_TIMEOUT 0x10
#define ACPI_IPMI_UNKNOWN 0x07
/* the IPMI timeout is 5s */
-#define IPMI_TIMEOUT (5 * HZ)
+#define IPMI_TIMEOUT (5000)
+#define ACPI_IPMI_MAX_MSG_LENGTH 64
struct acpi_ipmi_device {
/* the device list attached to driver_data.ipmi_devices */
struct list_head head;
+
/* the IPMI request message list */
struct list_head tx_msg_list;
- struct mutex tx_msg_lock;
+
+ spinlock_t tx_msg_lock;
acpi_handle handle;
- struct pnp_dev *pnp_dev;
- ipmi_user_t user_interface;
+ struct device *dev;
+ ipmi_user_t user_interface;
int ipmi_ifnum; /* IPMI interface number */
long curr_msgid;
- unsigned long flags;
- struct ipmi_smi_info smi_data;
+ bool dead;
+ struct kref kref;
};
struct ipmi_driver_data {
- struct list_head ipmi_devices;
- struct ipmi_smi_watcher bmc_events;
- struct ipmi_user_hndl ipmi_hndlrs;
- struct mutex ipmi_lock;
+ struct list_head ipmi_devices;
+ struct ipmi_smi_watcher bmc_events;
+ struct ipmi_user_hndl ipmi_hndlrs;
+ struct mutex ipmi_lock;
+
+ /*
+ * NOTE: IPMI System Interface Selection
+ * There is no system interface specified by the IPMI operation
+ * region access. We try to select one system interface with ACPI
+ * handle set. IPMI messages passed from the ACPI codes are sent
+ * to this selected global IPMI system interface.
+ */
+ struct acpi_ipmi_device *selected_smi;
};
struct acpi_ipmi_msg {
struct list_head head;
+
/*
* General speaking the addr type should be SI_ADDR_TYPE. And
* the addr channel should be BMC.
@@ -85,30 +85,31 @@ struct acpi_ipmi_msg {
*/
struct ipmi_addr addr;
long tx_msgid;
+
/* it is used to track whether the IPMI message is finished */
struct completion tx_complete;
+
struct kernel_ipmi_msg tx_message;
- int msg_done;
- /* tx data . And copy it from ACPI object buffer */
- u8 tx_data[64];
- int tx_len;
- u8 rx_data[64];
- int rx_len;
+ int msg_done;
+
+ /* tx/rx data . And copy it from/to ACPI object buffer */
+ u8 data[ACPI_IPMI_MAX_MSG_LENGTH];
+ u8 rx_len;
+
struct acpi_ipmi_device *device;
+ struct kref kref;
};
/* IPMI request/response buffer per ACPI 4.0, sec 5.5.2.4.3.2 */
struct acpi_ipmi_buffer {
u8 status;
u8 length;
- u8 data[64];
+ u8 data[ACPI_IPMI_MAX_MSG_LENGTH];
};
static void ipmi_register_bmc(int iface, struct device *dev);
static void ipmi_bmc_gone(int iface);
static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data);
-static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device);
-static void acpi_remove_ipmi_device(struct acpi_ipmi_device *ipmi_device);
static struct ipmi_driver_data driver_data = {
.ipmi_devices = LIST_HEAD_INIT(driver_data.ipmi_devices),
@@ -120,50 +121,174 @@ static struct ipmi_driver_data driver_data = {
.ipmi_hndlrs = {
.ipmi_recv_hndl = ipmi_msg_handler,
},
+ .ipmi_lock = __MUTEX_INITIALIZER(driver_data.ipmi_lock)
};
-static struct acpi_ipmi_msg *acpi_alloc_ipmi_msg(struct acpi_ipmi_device *ipmi)
+static struct acpi_ipmi_device *
+ipmi_dev_alloc(int iface, struct device *dev, acpi_handle handle)
{
+ struct acpi_ipmi_device *ipmi_device;
+ int err;
+ ipmi_user_t user;
+
+ ipmi_device = kzalloc(sizeof(*ipmi_device), GFP_KERNEL);
+ if (!ipmi_device)
+ return NULL;
+
+ kref_init(&ipmi_device->kref);
+ INIT_LIST_HEAD(&ipmi_device->head);
+ INIT_LIST_HEAD(&ipmi_device->tx_msg_list);
+ spin_lock_init(&ipmi_device->tx_msg_lock);
+ ipmi_device->handle = handle;
+ ipmi_device->dev = get_device(dev);
+ ipmi_device->ipmi_ifnum = iface;
+
+ err = ipmi_create_user(iface, &driver_data.ipmi_hndlrs,
+ ipmi_device, &user);
+ if (err) {
+ put_device(dev);
+ kfree(ipmi_device);
+ return NULL;
+ }
+ ipmi_device->user_interface = user;
+
+ return ipmi_device;
+}
+
+static void ipmi_dev_release(struct acpi_ipmi_device *ipmi_device)
+{
+ ipmi_destroy_user(ipmi_device->user_interface);
+ put_device(ipmi_device->dev);
+ kfree(ipmi_device);
+}
+
+static void ipmi_dev_release_kref(struct kref *kref)
+{
+ struct acpi_ipmi_device *ipmi =
+ container_of(kref, struct acpi_ipmi_device, kref);
+
+ ipmi_dev_release(ipmi);
+}
+
+static void __ipmi_dev_kill(struct acpi_ipmi_device *ipmi_device)
+{
+ list_del(&ipmi_device->head);
+ if (driver_data.selected_smi == ipmi_device)
+ driver_data.selected_smi = NULL;
+
+ /*
+ * Always setting dead flag after deleting from the list or
+ * list_for_each_entry() codes must get changed.
+ */
+ ipmi_device->dead = true;
+}
+
+static struct acpi_ipmi_device *acpi_ipmi_dev_get(void)
+{
+ struct acpi_ipmi_device *ipmi_device = NULL;
+
+ mutex_lock(&driver_data.ipmi_lock);
+ if (driver_data.selected_smi) {
+ ipmi_device = driver_data.selected_smi;
+ kref_get(&ipmi_device->kref);
+ }
+ mutex_unlock(&driver_data.ipmi_lock);
+
+ return ipmi_device;
+}
+
+static void acpi_ipmi_dev_put(struct acpi_ipmi_device *ipmi_device)
+{
+ kref_put(&ipmi_device->kref, ipmi_dev_release_kref);
+}
+
+static struct acpi_ipmi_msg *ipmi_msg_alloc(void)
+{
+ struct acpi_ipmi_device *ipmi;
struct acpi_ipmi_msg *ipmi_msg;
- struct pnp_dev *pnp_dev = ipmi->pnp_dev;
+
+ ipmi = acpi_ipmi_dev_get();
+ if (!ipmi)
+ return NULL;
ipmi_msg = kzalloc(sizeof(struct acpi_ipmi_msg), GFP_KERNEL);
- if (!ipmi_msg) {
- dev_warn(&pnp_dev->dev, "Can't allocate memory for ipmi_msg\n");
+ if (!ipmi_msg) {
+ acpi_ipmi_dev_put(ipmi);
return NULL;
}
+
+ kref_init(&ipmi_msg->kref);
init_completion(&ipmi_msg->tx_complete);
INIT_LIST_HEAD(&ipmi_msg->head);
ipmi_msg->device = ipmi;
+ ipmi_msg->msg_done = ACPI_IPMI_UNKNOWN;
+
return ipmi_msg;
}
-#define IPMI_OP_RGN_NETFN(offset) ((offset >> 8) & 0xff)
-#define IPMI_OP_RGN_CMD(offset) (offset & 0xff)
-static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
- acpi_physical_address address,
- acpi_integer *value)
+static void ipmi_msg_release(struct acpi_ipmi_msg *tx_msg)
+{
+ acpi_ipmi_dev_put(tx_msg->device);
+ kfree(tx_msg);
+}
+
+static void ipmi_msg_release_kref(struct kref *kref)
+{
+ struct acpi_ipmi_msg *tx_msg =
+ container_of(kref, struct acpi_ipmi_msg, kref);
+
+ ipmi_msg_release(tx_msg);
+}
+
+static struct acpi_ipmi_msg *acpi_ipmi_msg_get(struct acpi_ipmi_msg *tx_msg)
+{
+ kref_get(&tx_msg->kref);
+
+ return tx_msg;
+}
+
+static void acpi_ipmi_msg_put(struct acpi_ipmi_msg *tx_msg)
+{
+ kref_put(&tx_msg->kref, ipmi_msg_release_kref);
+}
+
+#define IPMI_OP_RGN_NETFN(offset) ((offset >> 8) & 0xff)
+#define IPMI_OP_RGN_CMD(offset) (offset & 0xff)
+static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg,
+ acpi_physical_address address,
+ acpi_integer *value)
{
struct kernel_ipmi_msg *msg;
struct acpi_ipmi_buffer *buffer;
struct acpi_ipmi_device *device;
+ unsigned long flags;
msg = &tx_msg->tx_message;
+
/*
* IPMI network function and command are encoded in the address
* within the IPMI OpRegion; see ACPI 4.0, sec 5.5.2.4.3.
*/
msg->netfn = IPMI_OP_RGN_NETFN(address);
msg->cmd = IPMI_OP_RGN_CMD(address);
- msg->data = tx_msg->tx_data;
+ msg->data = tx_msg->data;
+
/*
* value is the parameter passed by the IPMI opregion space handler.
* It points to the IPMI request message buffer
*/
buffer = (struct acpi_ipmi_buffer *)value;
+
/* copy the tx message data */
+ if (buffer->length > ACPI_IPMI_MAX_MSG_LENGTH) {
+ dev_WARN_ONCE(tx_msg->device->dev, true,
+ "Unexpected request (msg len %d).\n",
+ buffer->length);
+ return -EINVAL;
+ }
msg->data_len = buffer->length;
- memcpy(tx_msg->tx_data, buffer->data, msg->data_len);
+ memcpy(tx_msg->data, buffer->data, msg->data_len);
+
/*
* now the default type is SYSTEM_INTERFACE and channel type is BMC.
* If the netfn is APP_REQUEST and the cmd is SEND_MESSAGE,
@@ -177,14 +302,17 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
/* Get the msgid */
device = tx_msg->device;
- mutex_lock(&device->tx_msg_lock);
+
+ spin_lock_irqsave(&device->tx_msg_lock, flags);
device->curr_msgid++;
tx_msg->tx_msgid = device->curr_msgid;
- mutex_unlock(&device->tx_msg_lock);
+ spin_unlock_irqrestore(&device->tx_msg_lock, flags);
+
+ return 0;
}
static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg,
- acpi_integer *value, int rem_time)
+ acpi_integer *value)
{
struct acpi_ipmi_buffer *buffer;
@@ -193,109 +321,158 @@ static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg,
* IPMI message returned by IPMI command.
*/
buffer = (struct acpi_ipmi_buffer *)value;
- if (!rem_time && !msg->msg_done) {
- buffer->status = ACPI_IPMI_TIMEOUT;
- return;
- }
+
/*
- * If the flag of msg_done is not set or the recv length is zero, it
- * means that the IPMI command is not executed correctly.
- * The status code will be ACPI_IPMI_UNKNOWN.
+ * If the flag of msg_done is not set, it means that the IPMI command is
+ * not executed correctly.
*/
- if (!msg->msg_done || !msg->rx_len) {
- buffer->status = ACPI_IPMI_UNKNOWN;
+ buffer->status = msg->msg_done;
+ if (msg->msg_done != ACPI_IPMI_OK)
return;
- }
+
/*
* If the IPMI response message is obtained correctly, the status code
* will be ACPI_IPMI_OK
*/
- buffer->status = ACPI_IPMI_OK;
buffer->length = msg->rx_len;
- memcpy(buffer->data, msg->rx_data, msg->rx_len);
+ memcpy(buffer->data, msg->data, msg->rx_len);
}
static void ipmi_flush_tx_msg(struct acpi_ipmi_device *ipmi)
{
- struct acpi_ipmi_msg *tx_msg, *temp;
- int count = HZ / 10;
- struct pnp_dev *pnp_dev = ipmi->pnp_dev;
+ struct acpi_ipmi_msg *tx_msg;
+ unsigned long flags;
+
+ /*
+ * NOTE: On-going ipmi_recv_msg
+ * ipmi_msg_handler() may still be invoked by ipmi_si after
+ * flushing. But it is safe to do a fast flushing on module_exit()
+ * without waiting for all ipmi_recv_msg(s) to complete from
+ * ipmi_msg_handler() as it is ensured by ipmi_si that all
+ * ipmi_recv_msg(s) are freed after invoking ipmi_destroy_user().
+ */
+ spin_lock_irqsave(&ipmi->tx_msg_lock, flags);
+ while (!list_empty(&ipmi->tx_msg_list)) {
+ tx_msg = list_first_entry(&ipmi->tx_msg_list,
+ struct acpi_ipmi_msg,
+ head);
+ list_del(&tx_msg->head);
+ spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags);
- list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) {
/* wake up the sleep thread on the Tx msg */
complete(&tx_msg->tx_complete);
+ acpi_ipmi_msg_put(tx_msg);
+ spin_lock_irqsave(&ipmi->tx_msg_lock, flags);
}
+ spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags);
+}
- /* wait for about 100ms to flush the tx message list */
- while (count--) {
- if (list_empty(&ipmi->tx_msg_list))
+static void ipmi_cancel_tx_msg(struct acpi_ipmi_device *ipmi,
+ struct acpi_ipmi_msg *msg)
+{
+ struct acpi_ipmi_msg *tx_msg, *temp;
+ bool msg_found = false;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ipmi->tx_msg_lock, flags);
+ list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) {
+ if (msg == tx_msg) {
+ msg_found = true;
+ list_del(&tx_msg->head);
break;
- schedule_timeout(1);
+ }
}
- if (!list_empty(&ipmi->tx_msg_list))
- dev_warn(&pnp_dev->dev, "tx msg list is not NULL\n");
+ spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags);
+
+ if (msg_found)
+ acpi_ipmi_msg_put(tx_msg);
}
static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
{
struct acpi_ipmi_device *ipmi_device = user_msg_data;
- int msg_found = 0;
- struct acpi_ipmi_msg *tx_msg;
- struct pnp_dev *pnp_dev = ipmi_device->pnp_dev;
+ bool msg_found = false;
+ struct acpi_ipmi_msg *tx_msg, *temp;
+ struct device *dev = ipmi_device->dev;
+ unsigned long flags;
if (msg->user != ipmi_device->user_interface) {
- dev_warn(&pnp_dev->dev, "Unexpected response is returned. "
- "returned user %p, expected user %p\n",
- msg->user, ipmi_device->user_interface);
- ipmi_free_recv_msg(msg);
- return;
+ dev_warn(dev,
+ "Unexpected response is returned. returned user %p, expected user %p\n",
+ msg->user, ipmi_device->user_interface);
+ goto out_msg;
}
- mutex_lock(&ipmi_device->tx_msg_lock);
- list_for_each_entry(tx_msg, &ipmi_device->tx_msg_list, head) {
+
+ spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
+ list_for_each_entry_safe(tx_msg, temp, &ipmi_device->tx_msg_list, head) {
if (msg->msgid == tx_msg->tx_msgid) {
- msg_found = 1;
+ msg_found = true;
+ list_del(&tx_msg->head);
break;
}
}
+ spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
- mutex_unlock(&ipmi_device->tx_msg_lock);
if (!msg_found) {
- dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is "
- "returned.\n", msg->msgid);
- ipmi_free_recv_msg(msg);
- return;
+ dev_warn(dev,
+ "Unexpected response (msg id %ld) is returned.\n",
+ msg->msgid);
+ goto out_msg;
+ }
+
+ /* copy the response data to Rx_data buffer */
+ if (msg->msg.data_len > ACPI_IPMI_MAX_MSG_LENGTH) {
+ dev_WARN_ONCE(dev, true,
+ "Unexpected response (msg len %d).\n",
+ msg->msg.data_len);
+ goto out_comp;
}
- if (msg->msg.data_len) {
- /* copy the response data to Rx_data buffer */
- memcpy(tx_msg->rx_data, msg->msg_data, msg->msg.data_len);
- tx_msg->rx_len = msg->msg.data_len;
- tx_msg->msg_done = 1;
+ /* response msg is an error msg */
+ msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
+ if (msg->recv_type == IPMI_RESPONSE_RECV_TYPE &&
+ msg->msg.data_len == 1) {
+ if (msg->msg.data[0] == IPMI_TIMEOUT_COMPLETION_CODE) {
+ dev_WARN_ONCE(dev, true,
+ "Unexpected response (timeout).\n");
+ tx_msg->msg_done = ACPI_IPMI_TIMEOUT;
+ }
+ goto out_comp;
}
+
+ tx_msg->rx_len = msg->msg.data_len;
+ memcpy(tx_msg->data, msg->msg.data, tx_msg->rx_len);
+ tx_msg->msg_done = ACPI_IPMI_OK;
+
+out_comp:
complete(&tx_msg->tx_complete);
+ acpi_ipmi_msg_put(tx_msg);
+out_msg:
ipmi_free_recv_msg(msg);
-};
+}
static void ipmi_register_bmc(int iface, struct device *dev)
{
struct acpi_ipmi_device *ipmi_device, *temp;
- struct pnp_dev *pnp_dev;
- ipmi_user_t user;
int err;
struct ipmi_smi_info smi_data;
acpi_handle handle;
err = ipmi_get_smi_info(iface, &smi_data);
-
if (err)
return;
- if (smi_data.addr_src != SI_ACPI) {
- put_device(smi_data.dev);
- return;
- }
-
+ if (smi_data.addr_src != SI_ACPI)
+ goto err_ref;
handle = smi_data.addr_info.acpi_info.acpi_handle;
+ if (!handle)
+ goto err_ref;
+
+ ipmi_device = ipmi_dev_alloc(iface, smi_data.dev, handle);
+ if (!ipmi_device) {
+ dev_warn(smi_data.dev, "Can't create IPMI user interface\n");
+ goto err_ref;
+ }
mutex_lock(&driver_data.ipmi_lock);
list_for_each_entry(temp, &driver_data.ipmi_devices, head) {
@@ -304,34 +481,20 @@ static void ipmi_register_bmc(int iface, struct device *dev)
* to the device list, don't add it again.
*/
if (temp->handle == handle)
- goto out;
- }
-
- ipmi_device = kzalloc(sizeof(*ipmi_device), GFP_KERNEL);
-
- if (!ipmi_device)
- goto out;
-
- pnp_dev = to_pnp_dev(smi_data.dev);
- ipmi_device->handle = handle;
- ipmi_device->pnp_dev = pnp_dev;
-
- err = ipmi_create_user(iface, &driver_data.ipmi_hndlrs,
- ipmi_device, &user);
- if (err) {
- dev_warn(&pnp_dev->dev, "Can't create IPMI user interface\n");
- kfree(ipmi_device);
- goto out;
+ goto err_lock;
}
- acpi_add_ipmi_device(ipmi_device);
- ipmi_device->user_interface = user;
- ipmi_device->ipmi_ifnum = iface;
+ if (!driver_data.selected_smi)
+ driver_data.selected_smi = ipmi_device;
+ list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices);
mutex_unlock(&driver_data.ipmi_lock);
- memcpy(&ipmi_device->smi_data, &smi_data, sizeof(struct ipmi_smi_info));
+
+ put_device(smi_data.dev);
return;
-out:
+err_lock:
mutex_unlock(&driver_data.ipmi_lock);
+ ipmi_dev_release(ipmi_device);
+err_ref:
put_device(smi_data.dev);
return;
}
@@ -339,23 +502,29 @@ out:
static void ipmi_bmc_gone(int iface)
{
struct acpi_ipmi_device *ipmi_device, *temp;
+ bool dev_found = false;
mutex_lock(&driver_data.ipmi_lock);
list_for_each_entry_safe(ipmi_device, temp,
- &driver_data.ipmi_devices, head) {
- if (ipmi_device->ipmi_ifnum != iface)
- continue;
-
- acpi_remove_ipmi_device(ipmi_device);
- put_device(ipmi_device->smi_data.dev);
- kfree(ipmi_device);
- break;
+ &driver_data.ipmi_devices, head) {
+ if (ipmi_device->ipmi_ifnum != iface) {
+ dev_found = true;
+ __ipmi_dev_kill(ipmi_device);
+ break;
+ }
}
+ if (!driver_data.selected_smi)
+ driver_data.selected_smi = list_first_entry_or_null(
+ &driver_data.ipmi_devices,
+ struct acpi_ipmi_device, head);
mutex_unlock(&driver_data.ipmi_lock);
+
+ if (dev_found) {
+ ipmi_flush_tx_msg(ipmi_device);
+ acpi_ipmi_dev_put(ipmi_device);
+ }
}
-/* --------------------------------------------------------------------------
- * Address Space Management
- * -------------------------------------------------------------------------- */
+
/*
* This is the IPMI opregion space handler.
* @function: indicates the read/write. In fact as the IPMI message is driven
@@ -368,16 +537,17 @@ static void ipmi_bmc_gone(int iface)
* the response IPMI message returned by IPMI command.
* @handler_context: IPMI device context.
*/
-
static acpi_status
acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
- u32 bits, acpi_integer *value,
- void *handler_context, void *region_context)
+ u32 bits, acpi_integer *value,
+ void *handler_context, void *region_context)
{
struct acpi_ipmi_msg *tx_msg;
- struct acpi_ipmi_device *ipmi_device = handler_context;
- int err, rem_time;
+ struct acpi_ipmi_device *ipmi_device;
+ int err;
acpi_status status;
+ unsigned long flags;
+
/*
* IPMI opregion message.
* IPMI message is firstly written to the BMC and system software
@@ -387,118 +557,75 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
if ((function & ACPI_IO_MASK) == ACPI_READ)
return AE_TYPE;
- if (!ipmi_device->user_interface)
+ tx_msg = ipmi_msg_alloc();
+ if (!tx_msg)
return AE_NOT_EXIST;
+ ipmi_device = tx_msg->device;
- tx_msg = acpi_alloc_ipmi_msg(ipmi_device);
- if (!tx_msg)
- return AE_NO_MEMORY;
+ if (acpi_format_ipmi_request(tx_msg, address, value) != 0) {
+ ipmi_msg_release(tx_msg);
+ return AE_TYPE;
+ }
- acpi_format_ipmi_msg(tx_msg, address, value);
- mutex_lock(&ipmi_device->tx_msg_lock);
+ acpi_ipmi_msg_get(tx_msg);
+ mutex_lock(&driver_data.ipmi_lock);
+ /* Do not add a tx_msg that can not be flushed. */
+ if (ipmi_device->dead) {
+ mutex_unlock(&driver_data.ipmi_lock);
+ ipmi_msg_release(tx_msg);
+ return AE_NOT_EXIST;
+ }
+ spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list);
- mutex_unlock(&ipmi_device->tx_msg_lock);
+ spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
+ mutex_unlock(&driver_data.ipmi_lock);
+
err = ipmi_request_settime(ipmi_device->user_interface,
- &tx_msg->addr,
- tx_msg->tx_msgid,
- &tx_msg->tx_message,
- NULL, 0, 0, 0);
+ &tx_msg->addr,
+ tx_msg->tx_msgid,
+ &tx_msg->tx_message,
+ NULL, 0, 0, IPMI_TIMEOUT);
if (err) {
status = AE_ERROR;
- goto end_label;
+ goto out_msg;
}
- rem_time = wait_for_completion_timeout(&tx_msg->tx_complete,
- IPMI_TIMEOUT);
- acpi_format_ipmi_response(tx_msg, value, rem_time);
+ wait_for_completion(&tx_msg->tx_complete);
+
+ acpi_format_ipmi_response(tx_msg, value);
status = AE_OK;
-end_label:
- mutex_lock(&ipmi_device->tx_msg_lock);
- list_del(&tx_msg->head);
- mutex_unlock(&ipmi_device->tx_msg_lock);
- kfree(tx_msg);
+out_msg:
+ ipmi_cancel_tx_msg(ipmi_device, tx_msg);
+ acpi_ipmi_msg_put(tx_msg);
return status;
}
-static void ipmi_remove_space_handler(struct acpi_ipmi_device *ipmi)
-{
- if (!test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags))
- return;
-
- acpi_remove_address_space_handler(ipmi->handle,
- ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler);
-
- clear_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags);
-}
-
-static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi)
+static int __init acpi_ipmi_init(void)
{
+ int result;
acpi_status status;
- if (test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags))
+ if (acpi_disabled)
return 0;
- status = acpi_install_address_space_handler(ipmi->handle,
+ status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
ACPI_ADR_SPACE_IPMI,
&acpi_ipmi_space_handler,
- NULL, ipmi);
+ NULL, NULL);
if (ACPI_FAILURE(status)) {
- struct pnp_dev *pnp_dev = ipmi->pnp_dev;
- dev_warn(&pnp_dev->dev, "Can't register IPMI opregion space "
- "handle\n");
+ pr_warn("Can't register IPMI opregion space handle\n");
return -EINVAL;
}
- set_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags);
- return 0;
-}
-
-static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device)
-{
-
- INIT_LIST_HEAD(&ipmi_device->head);
-
- mutex_init(&ipmi_device->tx_msg_lock);
- INIT_LIST_HEAD(&ipmi_device->tx_msg_list);
- ipmi_install_space_handler(ipmi_device);
-
- list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices);
-}
-
-static void acpi_remove_ipmi_device(struct acpi_ipmi_device *ipmi_device)
-{
- /*
- * If the IPMI user interface is created, it should be
- * destroyed.
- */
- if (ipmi_device->user_interface) {
- ipmi_destroy_user(ipmi_device->user_interface);
- ipmi_device->user_interface = NULL;
- }
- /* flush the Tx_msg list */
- if (!list_empty(&ipmi_device->tx_msg_list))
- ipmi_flush_tx_msg(ipmi_device);
-
- list_del(&ipmi_device->head);
- ipmi_remove_space_handler(ipmi_device);
-}
-
-static int __init acpi_ipmi_init(void)
-{
- int result = 0;
-
- if (acpi_disabled)
- return result;
-
- mutex_init(&driver_data.ipmi_lock);
-
result = ipmi_smi_watcher_register(&driver_data.bmc_events);
+ if (result)
+ pr_err("Can't register IPMI system interface watcher\n");
return result;
}
static void __exit acpi_ipmi_exit(void)
{
- struct acpi_ipmi_device *ipmi_device, *temp;
+ struct acpi_ipmi_device *ipmi_device;
if (acpi_disabled)
return;
@@ -512,13 +639,22 @@ static void __exit acpi_ipmi_exit(void)
* handler and free it.
*/
mutex_lock(&driver_data.ipmi_lock);
- list_for_each_entry_safe(ipmi_device, temp,
- &driver_data.ipmi_devices, head) {
- acpi_remove_ipmi_device(ipmi_device);
- put_device(ipmi_device->smi_data.dev);
- kfree(ipmi_device);
+ while (!list_empty(&driver_data.ipmi_devices)) {
+ ipmi_device = list_first_entry(&driver_data.ipmi_devices,
+ struct acpi_ipmi_device,
+ head);
+ __ipmi_dev_kill(ipmi_device);
+ mutex_unlock(&driver_data.ipmi_lock);
+
+ ipmi_flush_tx_msg(ipmi_device);
+ acpi_ipmi_dev_put(ipmi_device);
+
+ mutex_lock(&driver_data.ipmi_lock);
}
mutex_unlock(&driver_data.ipmi_lock);
+ acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
+ ACPI_ADR_SPACE_IPMI,
+ &acpi_ipmi_space_handler);
}
module_init(acpi_ipmi_init);
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 999adb5499c7..c00a3a73409b 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -281,7 +281,7 @@ static void acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
if (!info->enabled)
continue;
- if (nid < 0)
+ if (nid == NUMA_NO_NODE)
nid = memory_add_physaddr_to_nid(info->start_addr);
acpi_unbind_memory_blocks(info, handle);
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c
index f29e06efa479..3c1d6b0c09a4 100644
--- a/drivers/acpi/acpi_processor.c
+++ b/drivers/acpi/acpi_processor.c
@@ -140,15 +140,11 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev)
return 0;
}
-static int acpi_processor_errata(struct acpi_processor *pr)
+static int acpi_processor_errata(void)
{
int result = 0;
struct pci_dev *dev = NULL;
-
- if (!pr)
- return -EINVAL;
-
/*
* PIIX4
*/
@@ -181,7 +177,7 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr)
cpu_maps_update_begin();
cpu_hotplug_begin();
- ret = acpi_map_lsapic(pr->handle, &pr->id);
+ ret = acpi_map_lsapic(pr->handle, pr->apic_id, &pr->id);
if (ret)
goto out;
@@ -219,11 +215,9 @@ static int acpi_processor_get_info(struct acpi_device *device)
int cpu_index, device_declaration = 0;
acpi_status status = AE_OK;
static int cpu0_initialized;
+ unsigned long long value;
- if (num_online_cpus() > 1)
- errata.smp = TRUE;
-
- acpi_processor_errata(pr);
+ acpi_processor_errata();
/*
* Check to see if we have bus mastering arbitration control. This
@@ -247,18 +241,12 @@ static int acpi_processor_get_info(struct acpi_device *device)
return -ENODEV;
}
- /*
- * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
- * >>> 'acpi_get_processor_id(acpi_id, &id)' in
- * arch/xxx/acpi.c
- */
pr->acpi_id = object.processor.proc_id;
} else {
/*
* Declared with "Device" statement; match _UID.
* Note that we don't handle string _UIDs yet.
*/
- unsigned long long value;
status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
NULL, &value);
if (ACPI_FAILURE(status)) {
@@ -270,7 +258,9 @@ static int acpi_processor_get_info(struct acpi_device *device)
device_declaration = 1;
pr->acpi_id = value;
}
- cpu_index = acpi_get_cpuid(pr->handle, device_declaration, pr->acpi_id);
+ pr->apic_id = acpi_get_apicid(pr->handle, device_declaration,
+ pr->acpi_id);
+ cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id);
/* Handle UP system running SMP kernel, with no LAPIC in MADT */
if (!cpu0_initialized && (cpu_index == -1) &&
@@ -332,9 +322,9 @@ static int acpi_processor_get_info(struct acpi_device *device)
* ensure we get the right value in the "physical id" field
* of /proc/cpuinfo
*/
- status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer);
+ status = acpi_evaluate_integer(pr->handle, "_SUN", NULL, &value);
if (ACPI_SUCCESS(status))
- arch_fix_phys_package_id(pr->id, object.integer.value);
+ arch_fix_phys_package_id(pr->id, value);
return 0;
}
diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h
index 9feba08c29fe..27c36a5251b5 100644
--- a/drivers/acpi/acpica/acdebug.h
+++ b/drivers/acpi/acpica/acdebug.h
@@ -113,11 +113,12 @@ void acpi_db_display_handlers(void);
ACPI_HW_DEPENDENT_RETURN_VOID(void
acpi_db_generate_gpe(char *gpe_arg,
char *block_arg))
+ ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_sci(void))
/*
* dbconvert - miscellaneous conversion routines
*/
- acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value);
+acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value);
acpi_status acpi_db_convert_to_package(char *string, union acpi_object *object);
@@ -154,6 +155,8 @@ void acpi_db_set_scope(char *name);
void acpi_db_dump_namespace(char *start_arg, char *depth_arg);
+void acpi_db_dump_namespace_paths(void);
+
void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg);
acpi_status acpi_db_find_name_in_namespace(char *name_arg);
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index ab0e97710381..3ae5fd02ae64 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -242,11 +242,11 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
*/
u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context);
-u32 acpi_ev_install_sci_handler(void);
+u32 acpi_ev_sci_dispatch(void);
-acpi_status acpi_ev_remove_sci_handler(void);
+u32 acpi_ev_install_sci_handler(void);
-u32 acpi_ev_initialize_SCI(u32 program_SCI);
+acpi_status acpi_ev_remove_all_sci_handlers(void);
ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_ev_terminate(void))
#endif /* __ACEVENTS_H__ */
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 90e846f985fa..0fba431f4fcb 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -269,6 +269,7 @@ ACPI_EXTERN acpi_table_handler acpi_gbl_table_handler;
ACPI_EXTERN void *acpi_gbl_table_handler_context;
ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk;
ACPI_EXTERN acpi_interface_handler acpi_gbl_interface_handler;
+ACPI_EXTERN struct acpi_sci_handler_info *acpi_gbl_sci_handler_list;
/* Owner ID support */
@@ -445,13 +446,6 @@ ACPI_EXTERN u8 acpi_gbl_db_opt_tables;
ACPI_EXTERN u8 acpi_gbl_db_opt_stats;
ACPI_EXTERN u8 acpi_gbl_db_opt_ini_methods;
ACPI_EXTERN u8 acpi_gbl_db_opt_no_region_support;
-
-ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS];
-ACPI_EXTERN acpi_object_type acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS];
-ACPI_EXTERN char acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE];
-ACPI_EXTERN char acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE];
-ACPI_EXTERN char acpi_gbl_db_scope_buf[80];
-ACPI_EXTERN char acpi_gbl_db_debug_filename[80];
ACPI_EXTERN u8 acpi_gbl_db_output_to_file;
ACPI_EXTERN char *acpi_gbl_db_buffer;
ACPI_EXTERN char *acpi_gbl_db_filename;
@@ -459,6 +453,16 @@ ACPI_EXTERN u32 acpi_gbl_db_debug_level;
ACPI_EXTERN u32 acpi_gbl_db_console_debug_level;
ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_db_scope_node;
+ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS];
+ACPI_EXTERN acpi_object_type acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS];
+
+/* These buffers should all be the same size */
+
+ACPI_EXTERN char acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE];
+ACPI_EXTERN char acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE];
+ACPI_EXTERN char acpi_gbl_db_scope_buf[ACPI_DB_LINE_BUFFER_SIZE];
+ACPI_EXTERN char acpi_gbl_db_debug_filename[ACPI_DB_LINE_BUFFER_SIZE];
+
/*
* Statistic globals
*/
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 0ed00669cd21..be9e30ee6048 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -398,6 +398,14 @@ struct acpi_simple_repair_info {
*
****************************************************************************/
+/* Dispatch info for each host-installed SCI handler */
+
+struct acpi_sci_handler_info {
+ struct acpi_sci_handler_info *next;
+ acpi_sci_handler address; /* Address of handler */
+ void *context; /* Context to be passed to handler */
+};
+
/* Dispatch info for each GPE -- either a method or handler, cannot be both */
struct acpi_gpe_handler_info {
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h
index 40b04bd5579e..e6138ac4a160 100644
--- a/drivers/acpi/acpica/acnamesp.h
+++ b/drivers/acpi/acpica/acnamesp.h
@@ -213,6 +213,12 @@ acpi_ns_dump_objects(acpi_object_type type,
u8 display_type,
u32 max_depth,
acpi_owner_id owner_id, acpi_handle start_handle);
+
+void
+acpi_ns_dump_object_paths(acpi_object_type type,
+ u8 display_type,
+ u32 max_depth,
+ acpi_owner_id owner_id, acpi_handle start_handle);
#endif /* ACPI_FUTURE_USAGE */
/*
diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c
index b24dbb80fab8..d52339090b60 100644
--- a/drivers/acpi/acpica/evgpeutil.c
+++ b/drivers/acpi/acpica/evgpeutil.c
@@ -196,7 +196,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
*
* FUNCTION: acpi_ev_get_gpe_xrupt_block
*
- * PARAMETERS: interrupt_number - Interrupt for a GPE block
+ * PARAMETERS: interrupt_number - Interrupt for a GPE block
*
* RETURN: A GPE interrupt block
*
diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c
index 1b111ef74903..a5687540e9a6 100644
--- a/drivers/acpi/acpica/evmisc.c
+++ b/drivers/acpi/acpica/evmisc.c
@@ -264,13 +264,6 @@ void acpi_ev_terminate(void)
status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
- /* Remove SCI handler */
-
- status = acpi_ev_remove_sci_handler();
- if (ACPI_FAILURE(status)) {
- ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
- }
-
status = acpi_ev_remove_global_lock_handler();
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO,
@@ -280,6 +273,13 @@ void acpi_ev_terminate(void)
acpi_gbl_events_initialized = FALSE;
}
+ /* Remove SCI handlers */
+
+ status = acpi_ev_remove_all_sci_handlers();
+ if (ACPI_FAILURE(status)) {
+ ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
+ }
+
/* Deallocate all handler objects installed within GPE info structs */
status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers, NULL);
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c
index cea14d6fc76c..6293d6bb6fe1 100644
--- a/drivers/acpi/acpica/evregion.c
+++ b/drivers/acpi/acpica/evregion.c
@@ -217,16 +217,11 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;
- if (region_obj2->extra.region_context) {
-
- /* The handler for this region was already installed */
-
- ACPI_FREE(region_context);
- } else {
- /*
- * Save the returned context for use in all accesses to
- * this particular region
- */
+ /*
+ * Save the returned context for use in all accesses to
+ * the handler for this particular region
+ */
+ if (!(region_obj2->extra.region_context)) {
region_obj2->extra.region_context =
region_context;
}
@@ -402,6 +397,14 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj,
handler_obj->address_space.
context, region_context);
+ /*
+ * region_context should have been released by the deactivate
+ * operation. We don't need access to it anymore here.
+ */
+ if (region_context) {
+ *region_context = NULL;
+ }
+
/* Init routine may fail, Just ignore errors */
if (ACPI_FAILURE(status)) {
diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c
index b905acf7aacd..94d9ebddf575 100644
--- a/drivers/acpi/acpica/evsci.c
+++ b/drivers/acpi/acpica/evsci.c
@@ -54,6 +54,50 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context);
/*******************************************************************************
*
+ * FUNCTION: acpi_ev_sci_dispatch
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status code indicates whether interrupt was handled.
+ *
+ * DESCRIPTION: Dispatch the SCI to all host-installed SCI handlers.
+ *
+ ******************************************************************************/
+
+u32 acpi_ev_sci_dispatch(void)
+{
+ struct acpi_sci_handler_info *sci_handler;
+ acpi_cpu_flags flags;
+ u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
+
+ ACPI_FUNCTION_NAME(ev_sci_dispatch);
+
+ /* Are there any host-installed SCI handlers? */
+
+ if (!acpi_gbl_sci_handler_list) {
+ return (int_status);
+ }
+
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+ /* Invoke all host-installed SCI handlers */
+
+ sci_handler = acpi_gbl_sci_handler_list;
+ while (sci_handler) {
+
+ /* Invoke the installed handler (at interrupt level) */
+
+ int_status |= sci_handler->address(sci_handler->context);
+
+ sci_handler = sci_handler->next;
+ }
+
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+ return (int_status);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ev_sci_xrupt_handler
*
* PARAMETERS: context - Calling Context
@@ -89,6 +133,10 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context)
*/
interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
+ /* Invoke all host-installed SCI handlers */
+
+ interrupt_handled |= acpi_ev_sci_dispatch();
+
return_UINT32(interrupt_handled);
}
@@ -112,14 +160,13 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context)
ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler);
/*
- * We are guaranteed by the ACPI CA initialization/shutdown code that
+ * We are guaranteed by the ACPICA initialization/shutdown code that
* if this interrupt handler is installed, ACPI is enabled.
*/
/* GPEs: Check for and dispatch any GPEs that have occurred */
interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
-
return_UINT32(interrupt_handled);
}
@@ -150,15 +197,15 @@ u32 acpi_ev_install_sci_handler(void)
/******************************************************************************
*
- * FUNCTION: acpi_ev_remove_sci_handler
+ * FUNCTION: acpi_ev_remove_all_sci_handlers
*
* PARAMETERS: none
*
- * RETURN: E_OK if handler uninstalled OK, E_ERROR if handler was not
+ * RETURN: AE_OK if handler uninstalled, AE_ERROR if handler was not
* installed to begin with
*
* DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be
- * taken.
+ * taken. Remove all host-installed SCI handlers.
*
* Note: It doesn't seem important to disable all events or set the event
* enable registers to their original values. The OS should disable
@@ -167,11 +214,13 @@ u32 acpi_ev_install_sci_handler(void)
*
******************************************************************************/
-acpi_status acpi_ev_remove_sci_handler(void)
+acpi_status acpi_ev_remove_all_sci_handlers(void)
{
+ struct acpi_sci_handler_info *sci_handler;
+ acpi_cpu_flags flags;
acpi_status status;
- ACPI_FUNCTION_TRACE(ev_remove_sci_handler);
+ ACPI_FUNCTION_TRACE(ev_remove_all_sci_handlers);
/* Just let the OS remove the handler and disable the level */
@@ -179,6 +228,21 @@ acpi_status acpi_ev_remove_sci_handler(void)
acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
acpi_ev_sci_xrupt_handler);
+ if (!acpi_gbl_sci_handler_list) {
+ return (status);
+ }
+
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+ /* Free all host-installed SCI handlers */
+
+ while (acpi_gbl_sci_handler_list) {
+ sci_handler = acpi_gbl_sci_handler_list;
+ acpi_gbl_sci_handler_list = sci_handler->next;
+ ACPI_FREE(sci_handler);
+ }
+
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index ca5fba99c33b..6f56146a6f88 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -385,6 +385,144 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
#if (!ACPI_REDUCED_HARDWARE)
/*******************************************************************************
*
+ * FUNCTION: acpi_install_sci_handler
+ *
+ * PARAMETERS: address - Address of the handler
+ * context - Value passed to the handler on each SCI
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Install a handler for a System Control Interrupt.
+ *
+ ******************************************************************************/
+acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context)
+{
+ struct acpi_sci_handler_info *new_sci_handler;
+ struct acpi_sci_handler_info *sci_handler;
+ acpi_cpu_flags flags;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(acpi_install_sci_handler);
+
+ if (!address) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
+ /* Allocate and init a handler object */
+
+ new_sci_handler = ACPI_ALLOCATE(sizeof(struct acpi_sci_handler_info));
+ if (!new_sci_handler) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
+
+ new_sci_handler->address = address;
+ new_sci_handler->context = context;
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /* Lock list during installation */
+
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+ sci_handler = acpi_gbl_sci_handler_list;
+
+ /* Ensure handler does not already exist */
+
+ while (sci_handler) {
+ if (address == sci_handler->address) {
+ status = AE_ALREADY_EXISTS;
+ goto unlock_and_exit;
+ }
+
+ sci_handler = sci_handler->next;
+ }
+
+ /* Install the new handler into the global list (at head) */
+
+ new_sci_handler->next = acpi_gbl_sci_handler_list;
+ acpi_gbl_sci_handler_list = new_sci_handler;
+
+ unlock_and_exit:
+
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+
+ exit:
+ if (ACPI_FAILURE(status)) {
+ ACPI_FREE(new_sci_handler);
+ }
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_remove_sci_handler
+ *
+ * PARAMETERS: address - Address of the handler
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Remove a handler for a System Control Interrupt.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_remove_sci_handler(acpi_sci_handler address)
+{
+ struct acpi_sci_handler_info *prev_sci_handler;
+ struct acpi_sci_handler_info *next_sci_handler;
+ acpi_cpu_flags flags;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(acpi_remove_sci_handler);
+
+ if (!address) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* Remove the SCI handler with lock */
+
+ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+ prev_sci_handler = NULL;
+ next_sci_handler = acpi_gbl_sci_handler_list;
+ while (next_sci_handler) {
+ if (next_sci_handler->address == address) {
+
+ /* Unlink and free the SCI handler info block */
+
+ if (prev_sci_handler) {
+ prev_sci_handler->next = next_sci_handler->next;
+ } else {
+ acpi_gbl_sci_handler_list =
+ next_sci_handler->next;
+ }
+
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+ ACPI_FREE(next_sci_handler);
+ goto unlock_and_exit;
+ }
+
+ prev_sci_handler = next_sci_handler;
+ next_sci_handler = next_sci_handler->next;
+ }
+
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+ status = AE_NOT_EXIST;
+
+ unlock_and_exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_install_global_event_handler
*
* PARAMETERS: handler - Pointer to the global event handler function
@@ -398,6 +536,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
* Can be used to update event counters, etc.
*
******************************************************************************/
+
acpi_status
acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context)
{
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c
index 5ee7a814cd92..f81fb068d20e 100644
--- a/drivers/acpi/acpica/hwxface.c
+++ b/drivers/acpi/acpica/hwxface.c
@@ -119,7 +119,8 @@ ACPI_EXPORT_SYMBOL(acpi_reset)
******************************************************************************/
acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
{
- u32 value;
+ u32 value_lo;
+ u32 value_hi;
u32 width;
u64 address;
acpi_status status;
@@ -137,13 +138,8 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
return (status);
}
- /* Initialize entire 64-bit return value to zero */
-
- *return_value = 0;
- value = 0;
-
/*
- * Two address spaces supported: Memory or IO. PCI_Config is
+ * Two address spaces supported: Memory or I/O. PCI_Config is
* not supported here because the GAS structure is insufficient
*/
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
@@ -155,29 +151,35 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
}
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
+ value_lo = 0;
+ value_hi = 0;
+
width = reg->bit_width;
if (width == 64) {
width = 32; /* Break into two 32-bit transfers */
}
status = acpi_hw_read_port((acpi_io_address)
- address, &value, width);
+ address, &value_lo, width);
if (ACPI_FAILURE(status)) {
return (status);
}
- *return_value = value;
if (reg->bit_width == 64) {
/* Read the top 32 bits */
status = acpi_hw_read_port((acpi_io_address)
- (address + 4), &value, 32);
+ (address + 4), &value_hi,
+ 32);
if (ACPI_FAILURE(status)) {
return (status);
}
- *return_value |= ((u64)value << 32);
}
+
+ /* Set the return value only if status is AE_OK */
+
+ *return_value = (value_lo | ((u64)value_hi << 32));
}
ACPI_DEBUG_PRINT((ACPI_DB_IO,
@@ -186,7 +188,7 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
ACPI_FORMAT_UINT64(address),
acpi_ut_get_region_name(reg->space_id)));
- return (status);
+ return (AE_OK);
}
ACPI_EXPORT_SYMBOL(acpi_read)
diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c
index c5316e5bd4ab..aff79c7392ff 100644
--- a/drivers/acpi/acpica/nsaccess.c
+++ b/drivers/acpi/acpica/nsaccess.c
@@ -424,8 +424,9 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
/* Current scope has no parent scope */
ACPI_ERROR((AE_INFO,
- "ACPI path has too many parent prefixes (^) "
- "- reached beyond root node"));
+ "%s: Path has too many parent prefixes (^) "
+ "- reached beyond root node",
+ pathname));
return_ACPI_STATUS(AE_NOT_FOUND);
}
}
diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c
index 7418c77fde8c..80633851cb2f 100644
--- a/drivers/acpi/acpica/nsdump.c
+++ b/drivers/acpi/acpica/nsdump.c
@@ -59,6 +59,17 @@ acpi_ns_dump_one_device(acpi_handle obj_handle,
#endif
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
+
+#ifdef ACPI_FUTURE_USAGE
+static acpi_status
+acpi_ns_dump_one_object_path(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value);
+
+static acpi_status
+acpi_ns_get_max_depth(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value);
+#endif /* ACPI_FUTURE_USAGE */
+
/*******************************************************************************
*
* FUNCTION: acpi_ns_print_pathname
@@ -671,6 +682,129 @@ acpi_ns_dump_objects(acpi_object_type type,
}
#endif /* ACPI_FUTURE_USAGE */
+#ifdef ACPI_FUTURE_USAGE
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ns_dump_one_object_path, acpi_ns_get_max_depth
+ *
+ * PARAMETERS: obj_handle - Node to be dumped
+ * level - Nesting level of the handle
+ * context - Passed into walk_namespace
+ * return_value - Not used
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Dump the full pathname to a namespace object. acp_ns_get_max_depth
+ * computes the maximum nesting depth in the namespace tree, in
+ * order to simplify formatting in acpi_ns_dump_one_object_path.
+ * These procedures are user_functions called by acpi_ns_walk_namespace.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ns_dump_one_object_path(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value)
+{
+ u32 max_level = *((u32 *)context);
+ char *pathname;
+ struct acpi_namespace_node *node;
+ int path_indent;
+
+ if (!obj_handle) {
+ return (AE_OK);
+ }
+
+ node = acpi_ns_validate_handle(obj_handle);
+ pathname = acpi_ns_get_external_pathname(node);
+
+ path_indent = 1;
+ if (level <= max_level) {
+ path_indent = max_level - level + 1;
+ }
+
+ acpi_os_printf("%2d%*s%-12s%*s",
+ level, level, " ", acpi_ut_get_type_name(node->type),
+ path_indent, " ");
+
+ acpi_os_printf("%s\n", &pathname[1]);
+ ACPI_FREE(pathname);
+ return (AE_OK);
+}
+
+static acpi_status
+acpi_ns_get_max_depth(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value)
+{
+ u32 *max_level = (u32 *)context;
+
+ if (level > *max_level) {
+ *max_level = level;
+ }
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ns_dump_object_paths
+ *
+ * PARAMETERS: type - Object type to be dumped
+ * display_type - 0 or ACPI_DISPLAY_SUMMARY
+ * max_depth - Maximum depth of dump. Use ACPI_UINT32_MAX
+ * for an effectively unlimited depth.
+ * owner_id - Dump only objects owned by this ID. Use
+ * ACPI_UINT32_MAX to match all owners.
+ * start_handle - Where in namespace to start/end search
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Dump full object pathnames within the loaded namespace. Uses
+ * acpi_ns_walk_namespace in conjunction with acpi_ns_dump_one_object_path.
+ *
+ ******************************************************************************/
+
+void
+acpi_ns_dump_object_paths(acpi_object_type type,
+ u8 display_type,
+ u32 max_depth,
+ acpi_owner_id owner_id, acpi_handle start_handle)
+{
+ acpi_status status;
+ u32 max_level = 0;
+
+ ACPI_FUNCTION_ENTRY();
+
+ /*
+ * Just lock the entire namespace for the duration of the dump.
+ * We don't want any changes to the namespace during this time,
+ * especially the temporary nodes since we are going to display
+ * them also.
+ */
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ acpi_os_printf("Could not acquire namespace mutex\n");
+ return;
+ }
+
+ /* Get the max depth of the namespace tree, for formatting later */
+
+ (void)acpi_ns_walk_namespace(type, start_handle, max_depth,
+ ACPI_NS_WALK_NO_UNLOCK |
+ ACPI_NS_WALK_TEMP_NODES,
+ acpi_ns_get_max_depth, NULL,
+ (void *)&max_level, NULL);
+
+ /* Now dump the entire namespace */
+
+ (void)acpi_ns_walk_namespace(type, start_handle, max_depth,
+ ACPI_NS_WALK_NO_UNLOCK |
+ ACPI_NS_WALK_TEMP_NODES,
+ acpi_ns_dump_one_object_path, NULL,
+ (void *)&max_level, NULL);
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+}
+#endif /* ACPI_FUTURE_USAGE */
+
/*******************************************************************************
*
* FUNCTION: acpi_ns_dump_entry
diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c
index b38b4b07f86e..481a6b4a9b2f 100644
--- a/drivers/acpi/acpica/nsxfeval.c
+++ b/drivers/acpi/acpica/nsxfeval.c
@@ -605,11 +605,19 @@ acpi_walk_namespace(acpi_object_type type,
goto unlock_and_exit;
}
+ /* Now we can validate the starting node */
+
+ if (!acpi_ns_validate_handle(start_object)) {
+ status = AE_BAD_PARAMETER;
+ goto unlock_and_exit2;
+ }
+
status = acpi_ns_walk_namespace(type, start_object, max_depth,
ACPI_NS_WALK_UNLOCK,
descending_callback, ascending_callback,
context, return_value);
+ unlock_and_exit2:
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
unlock_and_exit:
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c
index 42a13c0d7015..9e6788f9ba0f 100644
--- a/drivers/acpi/acpica/tbinstal.c
+++ b/drivers/acpi/acpica/tbinstal.c
@@ -80,16 +80,10 @@ acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc)
}
}
- /* FACS is the odd table, has no standard ACPI header and no checksum */
+ /* Always calculate checksum, ignore bad checksum if requested */
- if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) {
-
- /* Always calculate checksum, ignore bad checksum if requested */
-
- status =
- acpi_tb_verify_checksum(table_desc->pointer,
- table_desc->length);
- }
+ status =
+ acpi_tb_verify_checksum(table_desc->pointer, table_desc->length);
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c
index dc963f823d2c..9a47715af1f3 100644
--- a/drivers/acpi/acpica/tbprint.c
+++ b/drivers/acpi/acpica/tbprint.c
@@ -138,7 +138,7 @@ acpi_tb_print_table_header(acpi_physical_address address,
ACPI_INFO((AE_INFO, "%4.4s %p %05X",
header->signature, ACPI_CAST_PTR(void, address),
header->length));
- } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) {
+ } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) {
/* RSDP has no common fields */
@@ -190,6 +190,16 @@ acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length)
{
u8 checksum;
+ /*
+ * FACS/S3PT:
+ * They are the odd tables, have no standard ACPI header and no checksum
+ */
+
+ if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_S3PT) ||
+ ACPI_COMPARE_NAME(table->signature, ACPI_SIG_FACS)) {
+ return (AE_OK);
+ }
+
/* Compute the checksum on the table */
checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length);
diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c
index 948c95e80d44..1c95fabbe6a4 100644
--- a/drivers/acpi/acpica/tbxfroot.c
+++ b/drivers/acpi/acpica/tbxfroot.c
@@ -68,8 +68,7 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
* Note: Sometimes there exists more than one RSDP in memory; the valid
* RSDP has a valid checksum, all others have an invalid checksum.
*/
- if (ACPI_STRNCMP((char *)rsdp->signature, ACPI_SIG_RSDP,
- sizeof(ACPI_SIG_RSDP) - 1) != 0) {
+ if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) {
/* Nope, BAD Signature */
diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c
index 5796e11a0671..ffd0db509d34 100644
--- a/drivers/acpi/acpica/utdebug.c
+++ b/drivers/acpi/acpica/utdebug.c
@@ -190,7 +190,7 @@ acpi_debug_print(u32 requested_debug_level,
* Display the module name, current line number, thread ID (if requested),
* current procedure nesting level, and the current procedure name
*/
- acpi_os_printf("%8s-%04ld ", module_name, line_number);
+ acpi_os_printf("%9s-%04ld ", module_name, line_number);
if (ACPI_LV_THREADS & acpi_dbg_level) {
acpi_os_printf("[%u] ", (u32)thread_id);
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c
index d6f26bf8a062..046d5b059c07 100644
--- a/drivers/acpi/acpica/utglobal.c
+++ b/drivers/acpi/acpica/utglobal.c
@@ -291,7 +291,7 @@ acpi_status acpi_ut_init_globals(void)
#if (!ACPI_REDUCED_HARDWARE)
- /* GPE support */
+ /* GPE/SCI support */
acpi_gbl_all_gpes_initialized = FALSE;
acpi_gbl_gpe_xrupt_list_head = NULL;
@@ -300,6 +300,7 @@ acpi_status acpi_ut_init_globals(void)
acpi_current_gpe_count = 0;
acpi_gbl_global_event_handler = NULL;
+ acpi_gbl_sci_handler_list = NULL;
#endif /* !ACPI_REDUCED_HARDWARE */
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index 46f80e2c92f7..6d2c49b86b7f 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -758,9 +758,9 @@ int apei_osc_setup(void)
.cap.pointer = capbuf,
};
- capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
- capbuf[OSC_SUPPORT_TYPE] = 1;
- capbuf[OSC_CONTROL_TYPE] = 0;
+ capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE;
+ capbuf[OSC_SUPPORT_DWORD] = 1;
+ capbuf[OSC_CONTROL_DWORD] = 0;
if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))
|| ACPI_FAILURE(acpi_run_osc(handle, &context)))
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index b587ec8257b2..fbcfaa682c15 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -255,7 +255,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
acpi_print_osc_error(handle, context,
"_OSC invalid revision");
if (errors & OSC_CAPABILITIES_MASK_ERROR) {
- if (((u32 *)context->cap.pointer)[OSC_QUERY_TYPE]
+ if (((u32 *)context->cap.pointer)[OSC_QUERY_DWORD]
& OSC_QUERY_ENABLE)
goto out_success;
status = AE_SUPPORT;
@@ -295,30 +295,30 @@ static void acpi_bus_osc_support(void)
};
acpi_handle handle;
- capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
- capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
+ capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE;
+ capbuf[OSC_SUPPORT_DWORD] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\
defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
- capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT;
+ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT;
#endif
#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
- capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT;
+ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT;
#endif
#ifdef ACPI_HOTPLUG_OST
- capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_HOTPLUG_OST_SUPPORT;
+ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT;
#endif
if (!ghes_disable)
- capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_APEI_SUPPORT;
+ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT;
if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
return;
if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) {
u32 *capbuf_ret = context.ret.pointer;
- if (context.ret.length > OSC_SUPPORT_TYPE)
+ if (context.ret.length > OSC_SUPPORT_DWORD)
osc_sb_apei_support_acked =
- capbuf_ret[OSC_SUPPORT_TYPE] & OSC_SB_APEI_SUPPORT;
+ capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT;
kfree(context.ret.pointer);
}
/* do we need to check other returned cap? Sounds no */
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index a55773801c5f..c971929d75c2 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -383,18 +383,15 @@ static int acpi_button_add(struct acpi_device *device)
switch (button->type) {
case ACPI_BUTTON_TYPE_POWER:
- input->evbit[0] = BIT_MASK(EV_KEY);
- set_bit(KEY_POWER, input->keybit);
+ input_set_capability(input, EV_KEY, KEY_POWER);
break;
case ACPI_BUTTON_TYPE_SLEEP:
- input->evbit[0] = BIT_MASK(EV_KEY);
- set_bit(KEY_SLEEP, input->keybit);
+ input_set_capability(input, EV_KEY, KEY_SLEEP);
break;
case ACPI_BUTTON_TYPE_LID:
- input->evbit[0] = BIT_MASK(EV_SW);
- set_bit(SW_LID, input->swbit);
+ input_set_capability(input, EV_SW, SW_LID);
break;
}
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 05ea4be01a83..ca86c1ce7c8a 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -441,7 +441,7 @@ static void handle_dock(struct dock_station *ds, int dock)
acpi_status status;
struct acpi_object_list arg_list;
union acpi_object arg;
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ unsigned long long value;
acpi_handle_info(ds->handle, "%s\n", dock ? "docking" : "undocking");
@@ -450,12 +450,10 @@ static void handle_dock(struct dock_station *ds, int dock)
arg_list.pointer = &arg;
arg.type = ACPI_TYPE_INTEGER;
arg.integer.value = dock;
- status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer);
+ status = acpi_evaluate_integer(ds->handle, "_DCK", &arg_list, &value);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
acpi_handle_err(ds->handle, "Failed to execute _DCK (0x%x)\n",
status);
-
- kfree(buffer.pointer);
}
static inline void dock(struct dock_station *ds)
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index a06d98374705..d5309fd49458 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -28,6 +28,7 @@
/* Uncomment next line to get verbose printout */
/* #define DEBUG */
+#define pr_fmt(fmt) "ACPI : EC: " fmt
#include <linux/kernel.h>
#include <linux/module.h>
@@ -49,9 +50,6 @@
#define ACPI_EC_DEVICE_NAME "Embedded Controller"
#define ACPI_EC_FILE_INFO "info"
-#undef PREFIX
-#define PREFIX "ACPI: EC: "
-
/* EC status register */
#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */
#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */
@@ -131,26 +129,26 @@ static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
{
u8 x = inb(ec->command_addr);
- pr_debug(PREFIX "---> status = 0x%2.2x\n", x);
+ pr_debug("---> status = 0x%2.2x\n", x);
return x;
}
static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
{
u8 x = inb(ec->data_addr);
- pr_debug(PREFIX "---> data = 0x%2.2x\n", x);
+ pr_debug("---> data = 0x%2.2x\n", x);
return x;
}
static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command)
{
- pr_debug(PREFIX "<--- command = 0x%2.2x\n", command);
+ pr_debug("<--- command = 0x%2.2x\n", command);
outb(command, ec->command_addr);
}
static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
{
- pr_debug(PREFIX "<--- data = 0x%2.2x\n", data);
+ pr_debug("<--- data = 0x%2.2x\n", data);
outb(data, ec->data_addr);
}
@@ -241,7 +239,7 @@ static int ec_poll(struct acpi_ec *ec)
}
advance_transaction(ec, acpi_ec_read_status(ec));
} while (time_before(jiffies, delay));
- pr_debug(PREFIX "controller reset, restart transaction\n");
+ pr_debug("controller reset, restart transaction\n");
spin_lock_irqsave(&ec->lock, flags);
start_transaction(ec);
spin_unlock_irqrestore(&ec->lock, flags);
@@ -309,12 +307,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
}
}
if (ec_wait_ibf0(ec)) {
- pr_err(PREFIX "input buffer is not empty, "
+ pr_err("input buffer is not empty, "
"aborting transaction\n");
status = -ETIME;
goto end;
}
- pr_debug(PREFIX "transaction start (cmd=0x%02x, addr=0x%02x)\n",
+ pr_debug("transaction start (cmd=0x%02x, addr=0x%02x)\n",
t->command, t->wdata ? t->wdata[0] : 0);
/* disable GPE during transaction if storm is detected */
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
@@ -331,12 +329,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
/* It is safe to enable the GPE outside of the transaction. */
acpi_enable_gpe(NULL, ec->gpe);
} else if (t->irq_count > ec_storm_threshold) {
- pr_info(PREFIX "GPE storm detected(%d GPEs), "
+ pr_info("GPE storm detected(%d GPEs), "
"transactions will use polling mode\n",
t->irq_count);
set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
}
- pr_debug(PREFIX "transaction end\n");
+ pr_debug("transaction end\n");
end:
if (ec->global_lock)
acpi_release_global_lock(glk);
@@ -570,12 +568,12 @@ static void acpi_ec_run(void *cxt)
struct acpi_ec_query_handler *handler = cxt;
if (!handler)
return;
- pr_debug(PREFIX "start query execution\n");
+ pr_debug("start query execution\n");
if (handler->func)
handler->func(handler->data);
else if (handler->handle)
acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
- pr_debug(PREFIX "stop query execution\n");
+ pr_debug("stop query execution\n");
kfree(handler);
}
@@ -593,7 +591,8 @@ static int acpi_ec_sync_query(struct acpi_ec *ec)
if (!copy)
return -ENOMEM;
memcpy(copy, handler, sizeof(*copy));
- pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value);
+ pr_debug("push query execution (0x%2x) on queue\n",
+ value);
return acpi_os_execute((copy->func) ?
OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER,
acpi_ec_run, copy);
@@ -616,7 +615,7 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state)
{
if (state & ACPI_EC_FLAG_SCI) {
if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
- pr_debug(PREFIX "push gpe query to the queue\n");
+ pr_debug("push gpe query to the queue\n");
return acpi_os_execute(OSL_NOTIFY_HANDLER,
acpi_ec_gpe_query, ec);
}
@@ -630,7 +629,7 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
struct acpi_ec *ec = data;
u8 status = acpi_ec_read_status(ec);
- pr_debug(PREFIX "~~~> interrupt, status:0x%02x\n", status);
+ pr_debug("~~~> interrupt, status:0x%02x\n", status);
advance_transaction(ec, status);
if (ec_transaction_done(ec) &&
@@ -776,7 +775,7 @@ static int ec_install_handlers(struct acpi_ec *ec)
* The AE_NOT_FOUND error will be ignored and OS
* continue to initialize EC.
*/
- printk(KERN_ERR "Fail in evaluating the _REG object"
+ pr_err("Fail in evaluating the _REG object"
" of EC device. Broken bios is suspected.\n");
} else {
acpi_remove_gpe_handler(NULL, ec->gpe,
@@ -795,10 +794,10 @@ static void ec_remove_handlers(struct acpi_ec *ec)
acpi_disable_gpe(NULL, ec->gpe);
if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
- pr_err(PREFIX "failed to remove space handler\n");
+ pr_err("failed to remove space handler\n");
if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
&acpi_ec_gpe_handler)))
- pr_err(PREFIX "failed to remove gpe handler\n");
+ pr_err("failed to remove gpe handler\n");
clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
}
@@ -840,7 +839,7 @@ static int acpi_ec_add(struct acpi_device *device)
ret = !!request_region(ec->command_addr, 1, "EC cmd");
WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr);
- pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
+ pr_info("GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
ec->gpe, ec->command_addr, ec->data_addr);
ret = ec_install_handlers(ec);
@@ -931,7 +930,7 @@ static int ec_validate_ecdt(const struct dmi_system_id *id)
/* MSI EC needs special treatment, enable it */
static int ec_flag_msi(const struct dmi_system_id *id)
{
- printk(KERN_DEBUG PREFIX "Detected MSI hardware, enabling workarounds.\n");
+ pr_debug("Detected MSI hardware, enabling workarounds.\n");
EC_FLAGS_MSI = 1;
EC_FLAGS_VALIDATE_ECDT = 1;
return 0;
@@ -1010,7 +1009,7 @@ int __init acpi_ec_ecdt_probe(void)
status = acpi_get_table(ACPI_SIG_ECDT, 1,
(struct acpi_table_header **)&ecdt_ptr);
if (ACPI_SUCCESS(status)) {
- pr_info(PREFIX "EC description table is found, configuring boot EC\n");
+ pr_info("EC description table is found, configuring boot EC\n");
boot_ec->command_addr = ecdt_ptr->control.address;
boot_ec->data_addr = ecdt_ptr->data.address;
boot_ec->gpe = ecdt_ptr->gpe;
@@ -1030,7 +1029,7 @@ int __init acpi_ec_ecdt_probe(void)
/* This workaround is needed only on some broken machines,
* which require early EC, but fail to provide ECDT */
- printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n");
+ pr_debug("Look up EC in DSDT\n");
status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
boot_ec, NULL);
/* Check that acpi_get_devices actually find something */
@@ -1042,7 +1041,7 @@ int __init acpi_ec_ecdt_probe(void)
saved_ec->data_addr != boot_ec->data_addr ||
saved_ec->gpe != boot_ec->gpe ||
saved_ec->handle != boot_ec->handle)
- pr_info(PREFIX "ASUSTek keeps feeding us with broken "
+ pr_info("ASUSTek keeps feeding us with broken "
"ECDT tables, which are very hard to workaround. "
"Trying to use DSDT EC info instead. Please send "
"output of acpidump to linux-acpi@vger.kernel.org\n");
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 41ade6570bc0..ba3da88cee45 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -168,7 +168,7 @@ static int acpi_fan_add(struct acpi_device *device)
acpi_device_name(device), acpi_device_bid(device),
!device->power.state ? "on" : "off");
- end:
+end:
return result;
}
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 2e82e5d76930..a2343a1d9e0b 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -73,7 +73,7 @@ int acpi_map_pxm_to_node(int pxm)
{
int node = pxm_to_node_map[pxm];
- if (node < 0) {
+ if (node == NUMA_NO_NODE) {
if (nodes_weight(nodes_found_map) >= MAX_NUMNODES)
return NUMA_NO_NODE;
node = first_unset_node(nodes_found_map);
@@ -334,7 +334,7 @@ int acpi_get_pxm(acpi_handle h)
int acpi_get_node(acpi_handle *handle)
{
- int pxm, node = -1;
+ int pxm, node = NUMA_NO_NODE;
pxm = acpi_get_pxm(handle);
if (pxm >= 0 && pxm < MAX_PXM_DOMAINS)
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index e5f416c7f66e..50d40e58bb54 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -569,8 +569,10 @@ static const char * const table_sigs[] = {
#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
-/* Must not increase 10 or needs code modification below */
-#define ACPI_OVERRIDE_TABLES 10
+#define ACPI_OVERRIDE_TABLES 64
+static struct cpio_data __initdata acpi_initrd_files[ACPI_OVERRIDE_TABLES];
+
+#define MAP_CHUNK_SIZE (NR_FIX_BTMAPS << PAGE_SHIFT)
void __init acpi_initrd_override(void *data, size_t size)
{
@@ -579,8 +581,6 @@ void __init acpi_initrd_override(void *data, size_t size)
struct acpi_table_header *table;
char cpio_path[32] = "kernel/firmware/acpi/";
struct cpio_data file;
- struct cpio_data early_initrd_files[ACPI_OVERRIDE_TABLES];
- char *p;
if (data == NULL || size == 0)
return;
@@ -625,8 +625,8 @@ void __init acpi_initrd_override(void *data, size_t size)
table->signature, cpio_path, file.name, table->length);
all_tables_size += table->length;
- early_initrd_files[table_nr].data = file.data;
- early_initrd_files[table_nr].size = file.size;
+ acpi_initrd_files[table_nr].data = file.data;
+ acpi_initrd_files[table_nr].size = file.size;
table_nr++;
}
if (table_nr == 0)
@@ -652,14 +652,34 @@ void __init acpi_initrd_override(void *data, size_t size)
memblock_reserve(acpi_tables_addr, all_tables_size);
arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
- p = early_ioremap(acpi_tables_addr, all_tables_size);
-
+ /*
+ * early_ioremap only can remap 256k one time. If we map all
+ * tables one time, we will hit the limit. Need to map chunks
+ * one by one during copying the same as that in relocate_initrd().
+ */
for (no = 0; no < table_nr; no++) {
- memcpy(p + total_offset, early_initrd_files[no].data,
- early_initrd_files[no].size);
- total_offset += early_initrd_files[no].size;
+ unsigned char *src_p = acpi_initrd_files[no].data;
+ phys_addr_t size = acpi_initrd_files[no].size;
+ phys_addr_t dest_addr = acpi_tables_addr + total_offset;
+ phys_addr_t slop, clen;
+ char *dest_p;
+
+ total_offset += size;
+
+ while (size) {
+ slop = dest_addr & ~PAGE_MASK;
+ clen = size;
+ if (clen > MAP_CHUNK_SIZE - slop)
+ clen = MAP_CHUNK_SIZE - slop;
+ dest_p = early_ioremap(dest_addr & PAGE_MASK,
+ clen + slop);
+ memcpy(dest_p + slop, src_p, clen);
+ early_iounmap(dest_p, clen + slop);
+ src_p += clen;
+ dest_addr += clen;
+ size -= clen;
+ }
}
- early_iounmap(p, all_tables_size);
}
#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */
@@ -820,7 +840,7 @@ acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
void acpi_os_sleep(u64 ms)
{
- schedule_timeout_interruptible(msecs_to_jiffies(ms));
+ msleep(ms);
}
void acpi_os_stall(u32 us)
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index d3874f425653..924ad92852c1 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -49,10 +49,10 @@ static int acpi_pci_root_add(struct acpi_device *device,
const struct acpi_device_id *not_used);
static void acpi_pci_root_remove(struct acpi_device *device);
-#define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \
- | OSC_ACTIVE_STATE_PWR_SUPPORT \
- | OSC_CLOCK_PWR_CAPABILITY_SUPPORT \
- | OSC_MSI_SUPPORT)
+#define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \
+ | OSC_PCI_ASPM_SUPPORT \
+ | OSC_PCI_CLOCK_PM_SUPPORT \
+ | OSC_PCI_MSI_SUPPORT)
static const struct acpi_device_id root_device_ids[] = {
{"PNP0A03", 0},
@@ -127,6 +127,55 @@ static acpi_status try_get_root_bridge_busnr(acpi_handle handle,
return AE_OK;
}
+struct pci_osc_bit_struct {
+ u32 bit;
+ char *desc;
+};
+
+static struct pci_osc_bit_struct pci_osc_support_bit[] = {
+ { OSC_PCI_EXT_CONFIG_SUPPORT, "ExtendedConfig" },
+ { OSC_PCI_ASPM_SUPPORT, "ASPM" },
+ { OSC_PCI_CLOCK_PM_SUPPORT, "ClockPM" },
+ { OSC_PCI_SEGMENT_GROUPS_SUPPORT, "Segments" },
+ { OSC_PCI_MSI_SUPPORT, "MSI" },
+};
+
+static struct pci_osc_bit_struct pci_osc_control_bit[] = {
+ { OSC_PCI_EXPRESS_NATIVE_HP_CONTROL, "PCIeHotplug" },
+ { OSC_PCI_SHPC_NATIVE_HP_CONTROL, "SHPCHotplug" },
+ { OSC_PCI_EXPRESS_PME_CONTROL, "PME" },
+ { OSC_PCI_EXPRESS_AER_CONTROL, "AER" },
+ { OSC_PCI_EXPRESS_CAPABILITY_CONTROL, "PCIeCapability" },
+};
+
+static void decode_osc_bits(struct acpi_pci_root *root, char *msg, u32 word,
+ struct pci_osc_bit_struct *table, int size)
+{
+ char buf[80];
+ int i, len = 0;
+ struct pci_osc_bit_struct *entry;
+
+ buf[0] = '\0';
+ for (i = 0, entry = table; i < size; i++, entry++)
+ if (word & entry->bit)
+ len += snprintf(buf + len, sizeof(buf) - len, "%s%s",
+ len ? " " : "", entry->desc);
+
+ dev_info(&root->device->dev, "_OSC: %s [%s]\n", msg, buf);
+}
+
+static void decode_osc_support(struct acpi_pci_root *root, char *msg, u32 word)
+{
+ decode_osc_bits(root, msg, word, pci_osc_support_bit,
+ ARRAY_SIZE(pci_osc_support_bit));
+}
+
+static void decode_osc_control(struct acpi_pci_root *root, char *msg, u32 word)
+{
+ decode_osc_bits(root, msg, word, pci_osc_control_bit,
+ ARRAY_SIZE(pci_osc_control_bit));
+}
+
static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766";
static acpi_status acpi_pci_run_osc(acpi_handle handle,
@@ -158,14 +207,14 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root,
support &= OSC_PCI_SUPPORT_MASKS;
support |= root->osc_support_set;
- capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
- capbuf[OSC_SUPPORT_TYPE] = support;
+ capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE;
+ capbuf[OSC_SUPPORT_DWORD] = support;
if (control) {
*control &= OSC_PCI_CONTROL_MASKS;
- capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set;
+ capbuf[OSC_CONTROL_DWORD] = *control | root->osc_control_set;
} else {
/* Run _OSC query only with existing controls. */
- capbuf[OSC_CONTROL_TYPE] = root->osc_control_set;
+ capbuf[OSC_CONTROL_DWORD] = root->osc_control_set;
}
status = acpi_pci_run_osc(root->device->handle, capbuf, &result);
@@ -180,11 +229,7 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root,
static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags)
{
acpi_status status;
- acpi_handle tmp;
- status = acpi_get_handle(root->device->handle, "_OSC", &tmp);
- if (ACPI_FAILURE(status))
- return status;
mutex_lock(&osc_lock);
status = acpi_pci_query_osc(root, flags, NULL);
mutex_unlock(&osc_lock);
@@ -316,9 +361,8 @@ EXPORT_SYMBOL_GPL(acpi_get_pci_dev);
acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req)
{
struct acpi_pci_root *root;
- acpi_status status;
+ acpi_status status = AE_OK;
u32 ctrl, capbuf[3];
- acpi_handle tmp;
if (!mask)
return AE_BAD_PARAMETER;
@@ -331,10 +375,6 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req)
if (!root)
return AE_NOT_EXIST;
- status = acpi_get_handle(handle, "_OSC", &tmp);
- if (ACPI_FAILURE(status))
- return status;
-
mutex_lock(&osc_lock);
*mask = ctrl | root->osc_control_set;
@@ -349,17 +389,21 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req)
goto out;
if (ctrl == *mask)
break;
+ decode_osc_control(root, "platform does not support",
+ ctrl & ~(*mask));
ctrl = *mask;
}
if ((ctrl & req) != req) {
+ decode_osc_control(root, "not requesting control; platform does not support",
+ req & ~(ctrl));
status = AE_SUPPORT;
goto out;
}
- capbuf[OSC_QUERY_TYPE] = 0;
- capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set;
- capbuf[OSC_CONTROL_TYPE] = ctrl;
+ capbuf[OSC_QUERY_DWORD] = 0;
+ capbuf[OSC_SUPPORT_DWORD] = root->osc_support_set;
+ capbuf[OSC_CONTROL_DWORD] = ctrl;
status = acpi_pci_run_osc(handle, capbuf, mask);
if (ACPI_SUCCESS(status))
root->osc_control_set = *mask;
@@ -369,6 +413,87 @@ out:
}
EXPORT_SYMBOL(acpi_pci_osc_control_set);
+static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm,
+ int *clear_aspm)
+{
+ u32 support, control, requested;
+ acpi_status status;
+ struct acpi_device *device = root->device;
+ acpi_handle handle = device->handle;
+
+ /*
+ * All supported architectures that use ACPI have support for
+ * PCI domains, so we indicate this in _OSC support capabilities.
+ */
+ support = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
+ if (pci_ext_cfg_avail())
+ support |= OSC_PCI_EXT_CONFIG_SUPPORT;
+ if (pcie_aspm_support_enabled())
+ support |= OSC_PCI_ASPM_SUPPORT | OSC_PCI_CLOCK_PM_SUPPORT;
+ if (pci_msi_enabled())
+ support |= OSC_PCI_MSI_SUPPORT;
+
+ decode_osc_support(root, "OS supports", support);
+ status = acpi_pci_osc_support(root, support);
+ if (ACPI_FAILURE(status)) {
+ dev_info(&device->dev, "_OSC failed (%s); disabling ASPM\n",
+ acpi_format_exception(status));
+ *no_aspm = 1;
+ return;
+ }
+
+ if (pcie_ports_disabled) {
+ dev_info(&device->dev, "PCIe port services disabled; not requesting _OSC control\n");
+ return;
+ }
+
+ if ((support & ACPI_PCIE_REQ_SUPPORT) != ACPI_PCIE_REQ_SUPPORT) {
+ decode_osc_support(root, "not requesting OS control; OS requires",
+ ACPI_PCIE_REQ_SUPPORT);
+ return;
+ }
+
+ control = OSC_PCI_EXPRESS_CAPABILITY_CONTROL
+ | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL
+ | OSC_PCI_EXPRESS_PME_CONTROL;
+
+ if (pci_aer_available()) {
+ if (aer_acpi_firmware_first())
+ dev_info(&device->dev,
+ "PCIe AER handled by firmware\n");
+ else
+ control |= OSC_PCI_EXPRESS_AER_CONTROL;
+ }
+
+ requested = control;
+ status = acpi_pci_osc_control_set(handle, &control,
+ OSC_PCI_EXPRESS_CAPABILITY_CONTROL);
+ if (ACPI_SUCCESS(status)) {
+ decode_osc_control(root, "OS now controls", control);
+ if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
+ /*
+ * We have ASPM control, but the FADT indicates
+ * that it's unsupported. Clear it.
+ */
+ *clear_aspm = 1;
+ }
+ } else {
+ decode_osc_control(root, "OS requested", requested);
+ decode_osc_control(root, "platform willing to grant", control);
+ dev_info(&device->dev, "_OSC failed (%s); disabling ASPM\n",
+ acpi_format_exception(status));
+
+ /*
+ * We want to disable ASPM here, but aspm_disabled
+ * needs to remain in its state from boot so that we
+ * properly handle PCIe 1.1 devices. So we set this
+ * flag here, to defer the action until after the ACPI
+ * root scan.
+ */
+ *no_aspm = 1;
+ }
+}
+
static int acpi_pci_root_add(struct acpi_device *device,
const struct acpi_device_id *not_used)
{
@@ -376,9 +501,8 @@ static int acpi_pci_root_add(struct acpi_device *device,
acpi_status status;
int result;
struct acpi_pci_root *root;
- u32 flags, base_flags;
acpi_handle handle = device->handle;
- bool no_aspm = false, clear_aspm = false;
+ int no_aspm = 0, clear_aspm = 0;
root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
if (!root)
@@ -431,81 +555,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
root->mcfg_addr = acpi_pci_root_get_mcfg_addr(handle);
- /*
- * All supported architectures that use ACPI have support for
- * PCI domains, so we indicate this in _OSC support capabilities.
- */
- flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
- acpi_pci_osc_support(root, flags);
-
- if (pci_ext_cfg_avail())
- flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
- if (pcie_aspm_support_enabled()) {
- flags |= OSC_ACTIVE_STATE_PWR_SUPPORT |
- OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
- }
- if (pci_msi_enabled())
- flags |= OSC_MSI_SUPPORT;
- if (flags != base_flags) {
- status = acpi_pci_osc_support(root, flags);
- if (ACPI_FAILURE(status)) {
- dev_info(&device->dev, "ACPI _OSC support "
- "notification failed, disabling PCIe ASPM\n");
- no_aspm = true;
- flags = base_flags;
- }
- }
-
- if (!pcie_ports_disabled
- && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) {
- flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL
- | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL
- | OSC_PCI_EXPRESS_PME_CONTROL;
-
- if (pci_aer_available()) {
- if (aer_acpi_firmware_first())
- dev_dbg(&device->dev,
- "PCIe errors handled by BIOS.\n");
- else
- flags |= OSC_PCI_EXPRESS_AER_CONTROL;
- }
-
- dev_info(&device->dev,
- "Requesting ACPI _OSC control (0x%02x)\n", flags);
-
- status = acpi_pci_osc_control_set(handle, &flags,
- OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
- if (ACPI_SUCCESS(status)) {
- dev_info(&device->dev,
- "ACPI _OSC control (0x%02x) granted\n", flags);
- if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
- /*
- * We have ASPM control, but the FADT indicates
- * that it's unsupported. Clear it.
- */
- clear_aspm = true;
- }
- } else {
- dev_info(&device->dev,
- "ACPI _OSC request failed (%s), "
- "returned control mask: 0x%02x\n",
- acpi_format_exception(status), flags);
- dev_info(&device->dev,
- "ACPI _OSC control for PCIe not granted, disabling ASPM\n");
- /*
- * We want to disable ASPM here, but aspm_disabled
- * needs to remain in its state from boot so that we
- * properly handle PCIe 1.1 devices. So we set this
- * flag here, to defer the action until after the ACPI
- * root scan.
- */
- no_aspm = true;
- }
- } else {
- dev_info(&device->dev,
- "Unable to request _OSC control "
- "(_OSC support mask: 0x%02x)\n", flags);
- }
+ negotiate_os_control(root, &no_aspm, &clear_aspm);
/*
* TBD: Need PCI interface for enumeration/configuration of roots.
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index cf34d903f4fb..b3171f30b319 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -162,16 +162,23 @@ exit:
return apic_id;
}
-int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
+int acpi_get_apicid(acpi_handle handle, int type, u32 acpi_id)
{
-#ifdef CONFIG_SMP
- int i;
-#endif
- int apic_id = -1;
+ int apic_id;
apic_id = map_mat_entry(handle, type, acpi_id);
if (apic_id == -1)
apic_id = map_madt_entry(type, acpi_id);
+
+ return apic_id;
+}
+
+int acpi_map_cpuid(int apic_id, u32 acpi_id)
+{
+#ifdef CONFIG_SMP
+ int i;
+#endif
+
if (apic_id == -1) {
/*
* On UP processor, there is no _MAT or MADT table.
@@ -211,6 +218,15 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
#endif
return -1;
}
+
+int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
+{
+ int apic_id;
+
+ apic_id = acpi_get_apicid(handle, type, acpi_id);
+
+ return acpi_map_cpuid(apic_id, acpi_id);
+}
EXPORT_SYMBOL_GPL(acpi_get_cpuid);
static bool __init processor_physically_present(acpi_handle handle)
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index f98dd00b51a9..644516d9bde6 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -119,17 +119,10 @@ static struct dmi_system_id processor_power_dmi_table[] = {
*/
static void acpi_safe_halt(void)
{
- current_thread_info()->status &= ~TS_POLLING;
- /*
- * TS_POLLING-cleared state must be visible before we
- * test NEED_RESCHED:
- */
- smp_mb();
- if (!need_resched()) {
+ if (!tif_need_resched()) {
safe_halt();
local_irq_disable();
}
- current_thread_info()->status |= TS_POLLING;
}
#ifdef ARCH_APICTIMER_STOPS_ON_C3
@@ -272,9 +265,6 @@ static void tsc_check_state(int state) { return; }
static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
{
- if (!pr)
- return -EINVAL;
-
if (!pr->pblk)
return -ENODEV;
@@ -737,6 +727,11 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
if (unlikely(!pr))
return -EINVAL;
+ if (cx->entry_method == ACPI_CSTATE_FFH) {
+ if (current_set_polling_and_test())
+ return -EINVAL;
+ }
+
lapic_timer_state_broadcast(pr, cx, 1);
acpi_idle_do_entry(cx);
@@ -790,18 +785,9 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
if (unlikely(!pr))
return -EINVAL;
- if (cx->entry_method != ACPI_CSTATE_FFH) {
- current_thread_info()->status &= ~TS_POLLING;
- /*
- * TS_POLLING-cleared state must be visible before we test
- * NEED_RESCHED:
- */
- smp_mb();
-
- if (unlikely(need_resched())) {
- current_thread_info()->status |= TS_POLLING;
+ if (cx->entry_method == ACPI_CSTATE_FFH) {
+ if (current_set_polling_and_test())
return -EINVAL;
- }
}
/*
@@ -819,9 +805,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
sched_clock_idle_wakeup_event(0);
- if (cx->entry_method != ACPI_CSTATE_FFH)
- current_thread_info()->status |= TS_POLLING;
-
lapic_timer_state_broadcast(pr, cx, 0);
return index;
}
@@ -858,18 +841,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
}
}
- if (cx->entry_method != ACPI_CSTATE_FFH) {
- current_thread_info()->status &= ~TS_POLLING;
- /*
- * TS_POLLING-cleared state must be visible before we test
- * NEED_RESCHED:
- */
- smp_mb();
-
- if (unlikely(need_resched())) {
- current_thread_info()->status |= TS_POLLING;
+ if (cx->entry_method == ACPI_CSTATE_FFH) {
+ if (current_set_polling_and_test())
return -EINVAL;
- }
}
acpi_unlazy_tlb(smp_processor_id());
@@ -915,9 +889,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
sched_clock_idle_wakeup_event(0);
- if (cx->entry_method != ACPI_CSTATE_FFH)
- current_thread_info()->status |= TS_POLLING;
-
lapic_timer_state_broadcast(pr, cx, 0);
return index;
}
@@ -1076,12 +1047,8 @@ int acpi_processor_hotplug(struct acpi_processor *pr)
if (disabled_by_idle_boot_param())
return 0;
- if (!pr)
- return -EINVAL;
-
- if (nocst) {
+ if (nocst)
return -ENODEV;
- }
if (!pr->flags.power_setup_done)
return -ENODEV;
@@ -1108,9 +1075,6 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
if (disabled_by_idle_boot_param())
return 0;
- if (!pr)
- return -EINVAL;
-
if (nocst)
return -ENODEV;
@@ -1183,9 +1147,6 @@ int acpi_processor_power_init(struct acpi_processor *pr)
first_run++;
}
- if (!pr)
- return -EINVAL;
-
if (acpi_gbl_FADT.cst_control && !nocst) {
status =
acpi_os_write_port(acpi_gbl_FADT.smi_command, acpi_gbl_FADT.cst_control, 8);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index fbdb82e70d10..611ce9061dc5 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1121,7 +1121,7 @@ int acpi_bus_register_driver(struct acpi_driver *driver)
EXPORT_SYMBOL(acpi_bus_register_driver);
/**
- * acpi_bus_unregister_driver - unregisters a driver with the APIC bus
+ * acpi_bus_unregister_driver - unregisters a driver with the ACPI bus
* @driver: driver to unregister
*
* Unregisters a driver with the ACPI bus. Searches the namespace for all
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 05306a59aedc..b55778704444 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -564,6 +564,7 @@ static ssize_t counter_set(struct kobject *kobj,
acpi_event_status status;
acpi_handle handle;
int result = 0;
+ unsigned long tmp;
if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) {
int i;
@@ -596,8 +597,10 @@ static ssize_t counter_set(struct kobject *kobj,
else if (!strcmp(buf, "clear\n") &&
(status & ACPI_EVENT_FLAG_SET))
result = acpi_clear_gpe(handle, index);
+ else if (!kstrtoul(buf, 0, &tmp))
+ all_counters[index].count = tmp;
else
- all_counters[index].count = strtoul(buf, NULL, 0);
+ result = -EINVAL;
} else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) {
int event = index - num_gpes;
if (!strcmp(buf, "disable\n") &&
@@ -609,8 +612,10 @@ static ssize_t counter_set(struct kobject *kobj,
else if (!strcmp(buf, "clear\n") &&
(status & ACPI_EVENT_FLAG_SET))
result = acpi_clear_event(event);
+ else if (!kstrtoul(buf, 0, &tmp))
+ all_counters[index].count = tmp;
else
- all_counters[index].count = strtoul(buf, NULL, 0);
+ result = -EINVAL;
} else
all_counters[index].count = strtoul(buf, NULL, 0);
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index acfd0f711069..b67086fde1f1 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -189,14 +189,15 @@ struct ata_port_operations ahci_pmp_retry_srst_ops = {
};
EXPORT_SYMBOL_GPL(ahci_pmp_retry_srst_ops);
-int ahci_em_messages = 1;
+static bool ahci_em_messages __read_mostly = true;
EXPORT_SYMBOL_GPL(ahci_em_messages);
-module_param(ahci_em_messages, int, 0444);
+module_param(ahci_em_messages, bool, 0444);
/* add other LED protocol types when they become supported */
MODULE_PARM_DESC(ahci_em_messages,
"AHCI Enclosure Management Message control (0 = off, 1 = on)");
-int devslp_idle_timeout = 1000; /* device sleep idle timeout in ms */
+/* device sleep idle timeout in ms */
+static int devslp_idle_timeout __read_mostly = 1000;
module_param(devslp_idle_timeout, int, 0644);
MODULE_PARM_DESC(devslp_idle_timeout, "device sleep idle timeout");
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
index 4bceb8803a10..b33d1f99b3a4 100644
--- a/drivers/ata/pata_isapnp.c
+++ b/drivers/ata/pata_isapnp.c
@@ -78,7 +78,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
ap->ioaddr.cmd_addr = cmd_addr;
- if (pnp_port_valid(idev, 1) == 0) {
+ if (pnp_port_valid(idev, 1)) {
ctl_addr = devm_ioport_map(&idev->dev,
pnp_port_start(idev, 1), 1);
ap->ioaddr.altstatus_addr = ctl_addr;
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 8b7818b80056..f96f70419a78 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -47,18 +47,6 @@ static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr,
return ret;
}
-static const void *class_attr_namespace(struct kobject *kobj,
- const struct attribute *attr)
-{
- struct class_attribute *class_attr = to_class_attr(attr);
- struct subsys_private *cp = to_subsys_private(kobj);
- const void *ns = NULL;
-
- if (class_attr->namespace)
- ns = class_attr->namespace(cp->class, class_attr);
- return ns;
-}
-
static void class_release(struct kobject *kobj)
{
struct subsys_private *cp = to_subsys_private(kobj);
@@ -86,7 +74,6 @@ static const struct kobj_ns_type_operations *class_child_ns_type(struct kobject
static const struct sysfs_ops class_sysfs_ops = {
.show = class_attr_show,
.store = class_attr_store,
- .namespace = class_attr_namespace,
};
static struct kobj_type class_ktype = {
@@ -99,21 +86,23 @@ static struct kobj_type class_ktype = {
static struct kset *class_kset;
-int class_create_file(struct class *cls, const struct class_attribute *attr)
+int class_create_file_ns(struct class *cls, const struct class_attribute *attr,
+ const void *ns)
{
int error;
if (cls)
- error = sysfs_create_file(&cls->p->subsys.kobj,
- &attr->attr);
+ error = sysfs_create_file_ns(&cls->p->subsys.kobj,
+ &attr->attr, ns);
else
error = -EINVAL;
return error;
}
-void class_remove_file(struct class *cls, const struct class_attribute *attr)
+void class_remove_file_ns(struct class *cls, const struct class_attribute *attr,
+ const void *ns)
{
if (cls)
- sysfs_remove_file(&cls->p->subsys.kobj, &attr->attr);
+ sysfs_remove_file_ns(&cls->p->subsys.kobj, &attr->attr, ns);
}
static struct class *class_get(struct class *cls)
@@ -600,8 +589,8 @@ int __init classes_init(void)
return 0;
}
-EXPORT_SYMBOL_GPL(class_create_file);
-EXPORT_SYMBOL_GPL(class_remove_file);
+EXPORT_SYMBOL_GPL(class_create_file_ns);
+EXPORT_SYMBOL_GPL(class_remove_file_ns);
EXPORT_SYMBOL_GPL(class_unregister);
EXPORT_SYMBOL_GPL(class_destroy);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index c7cfadcf6752..319c2c594ac6 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1881,6 +1881,7 @@ EXPORT_SYMBOL_GPL(device_destroy);
*/
int device_rename(struct device *dev, const char *new_name)
{
+ struct kobject *kobj = &dev->kobj;
char *old_device_name = NULL;
int error;
@@ -1898,13 +1899,14 @@ int device_rename(struct device *dev, const char *new_name)
}
if (dev->class) {
- error = sysfs_rename_link(&dev->class->p->subsys.kobj,
- &dev->kobj, old_device_name, new_name);
+ error = sysfs_rename_link_ns(&dev->class->p->subsys.kobj,
+ kobj, old_device_name,
+ new_name, kobject_namespace(kobj));
if (error)
goto out;
}
- error = kobject_rename(&dev->kobj, new_name);
+ error = kobject_rename(kobj, new_name);
if (error)
goto out;
@@ -2017,7 +2019,7 @@ EXPORT_SYMBOL_GPL(device_move);
*/
void device_shutdown(void)
{
- struct device *dev;
+ struct device *dev, *parent;
spin_lock(&devices_kset->list_lock);
/*
@@ -2034,7 +2036,7 @@ void device_shutdown(void)
* prevent it from being freed because parent's
* lock is to be held
*/
- get_device(dev->parent);
+ parent = get_device(dev->parent);
get_device(dev);
/*
* Make sure the device is off the kset list, in the
@@ -2044,8 +2046,8 @@ void device_shutdown(void)
spin_unlock(&devices_kset->list_lock);
/* hold lock to avoid race with probe/release */
- if (dev->parent)
- device_lock(dev->parent);
+ if (parent)
+ device_lock(parent);
device_lock(dev);
/* Don't allow any more runtime suspends */
@@ -2063,11 +2065,11 @@ void device_shutdown(void)
}
device_unlock(dev);
- if (dev->parent)
- device_unlock(dev->parent);
+ if (parent)
+ device_unlock(parent);
put_device(dev);
- put_device(dev->parent);
+ put_device(parent);
spin_lock(&devices_kset->list_lock);
}
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 848ebbd25717..51f5d7fe2f0b 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -93,7 +93,17 @@ static ssize_t cpu_probe_store(struct device *dev,
const char *buf,
size_t count)
{
- return arch_cpu_probe(buf, count);
+ ssize_t cnt;
+ int ret;
+
+ ret = lock_device_hotplug_sysfs();
+ if (ret)
+ return ret;
+
+ cnt = arch_cpu_probe(buf, count);
+
+ unlock_device_hotplug();
+ return cnt;
}
static ssize_t cpu_release_store(struct device *dev,
@@ -101,7 +111,17 @@ static ssize_t cpu_release_store(struct device *dev,
const char *buf,
size_t count)
{
- return arch_cpu_release(buf, count);
+ ssize_t cnt;
+ int ret;
+
+ ret = lock_device_hotplug_sysfs();
+ if (ret)
+ return ret;
+
+ cnt = arch_cpu_release(buf, count);
+
+ unlock_device_hotplug();
+ return cnt;
}
static DEVICE_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 10a4467c63f1..eb8fb94ae2c5 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -282,31 +282,35 @@ static noinline_for_stack long fw_file_size(struct file *file)
return st.size;
}
-static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
+static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
{
long size;
char *buf;
+ int rc;
size = fw_file_size(file);
if (size <= 0)
- return false;
+ return -EINVAL;
buf = vmalloc(size);
if (!buf)
- return false;
- if (kernel_read(file, 0, buf, size) != size) {
+ return -ENOMEM;
+ rc = kernel_read(file, 0, buf, size);
+ if (rc != size) {
+ if (rc > 0)
+ rc = -EIO;
vfree(buf);
- return false;
+ return rc;
}
fw_buf->data = buf;
fw_buf->size = size;
- return true;
+ return 0;
}
-static bool fw_get_filesystem_firmware(struct device *device,
+static int fw_get_filesystem_firmware(struct device *device,
struct firmware_buf *buf)
{
int i;
- bool success = false;
+ int rc = -ENOENT;
char *path = __getname();
for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
@@ -321,14 +325,17 @@ static bool fw_get_filesystem_firmware(struct device *device,
file = filp_open(path, O_RDONLY, 0);
if (IS_ERR(file))
continue;
- success = fw_read_file_contents(file, buf);
+ rc = fw_read_file_contents(file, buf);
fput(file);
- if (success)
+ if (rc)
+ dev_warn(device, "firmware, attempted to load %s, but failed with error %d\n",
+ path, rc);
+ else
break;
}
__putname(path);
- if (success) {
+ if (!rc) {
dev_dbg(device, "firmware: direct-loading firmware %s\n",
buf->fw_id);
mutex_lock(&fw_lock);
@@ -337,7 +344,7 @@ static bool fw_get_filesystem_firmware(struct device *device,
mutex_unlock(&fw_lock);
}
- return success;
+ return rc;
}
/* firmware holds the ownership of pages */
@@ -1086,9 +1093,14 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
}
}
- if (!fw_get_filesystem_firmware(device, fw->priv))
+ ret = fw_get_filesystem_firmware(device, fw->priv);
+ if (ret) {
+ dev_warn(device, "Direct firmware load failed with error %d\n",
+ ret);
+ dev_warn(device, "Falling back to user helper\n");
ret = fw_load_from_user_helper(fw, name, device,
uevent, nowait, timeout);
+ }
/* don't cache firmware handled without uevent */
if (!ret)
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 4f8bef3eb5a8..47051cd25113 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -488,6 +488,11 @@ static int platform_drv_probe(struct device *_dev)
if (ret && ACPI_HANDLE(_dev))
acpi_dev_pm_detach(_dev, true);
+ if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
+ dev_warn(_dev, "probe deferral not supported\n");
+ ret = -ENXIO;
+ }
+
return ret;
}
@@ -553,8 +558,7 @@ EXPORT_SYMBOL_GPL(platform_driver_unregister);
/**
* platform_driver_probe - register driver for non-hotpluggable device
* @drv: platform driver structure
- * @probe: the driver probe routine, probably from an __init section,
- * must not return -EPROBE_DEFER.
+ * @probe: the driver probe routine, probably from an __init section
*
* Use this instead of platform_driver_register() when you know the device
* is not hotpluggable and has already been registered, and you want to
@@ -565,8 +569,7 @@ EXPORT_SYMBOL_GPL(platform_driver_unregister);
* into system-on-chip processors, where the controller devices have been
* configured as part of board setup.
*
- * This is incompatible with deferred probing so probe() must not
- * return -EPROBE_DEFER.
+ * Note that this is incompatible with deferred probing.
*
* Returns zero if the driver registered and bound to a device, else returns
* a negative error code and with the driver not registered.
@@ -576,6 +579,12 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv,
{
int retval, code;
+ /*
+ * Prevent driver from requesting probe deferral to avoid further
+ * futile probe attempts.
+ */
+ drv->prevent_deferred_probe = true;
+
/* make sure driver won't have bind/unbind attributes */
drv->driver.suppress_bind_attrs = true;
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 57f777835d97..9010614f7793 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -179,6 +179,9 @@ struct regmap_field {
/* lsb */
unsigned int shift;
unsigned int reg;
+
+ unsigned int id_size;
+ unsigned int id_offset;
};
#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 7d689a15c500..00152bf7ab12 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -821,6 +821,8 @@ static void regmap_field_init(struct regmap_field *rm_field,
rm_field->reg = reg_field.reg;
rm_field->shift = reg_field.lsb;
rm_field->mask = ((BIT(field_bits) - 1) << reg_field.lsb);
+ rm_field->id_size = reg_field.id_size;
+ rm_field->id_offset = reg_field.id_offset;
}
/**
@@ -1369,6 +1371,74 @@ int regmap_field_write(struct regmap_field *field, unsigned int val)
}
EXPORT_SYMBOL_GPL(regmap_field_write);
+/**
+ * regmap_field_update_bits(): Perform a read/modify/write cycle
+ * on the register field
+ *
+ * @field: Register field to write to
+ * @mask: Bitmask to change
+ * @val: Value to be written
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_field_update_bits(struct regmap_field *field, unsigned int mask, unsigned int val)
+{
+ mask = (mask << field->shift) & field->mask;
+
+ return regmap_update_bits(field->regmap, field->reg,
+ mask, val << field->shift);
+}
+EXPORT_SYMBOL_GPL(regmap_field_update_bits);
+
+/**
+ * regmap_fields_write(): Write a value to a single register field with port ID
+ *
+ * @field: Register field to write to
+ * @id: port ID
+ * @val: Value to be written
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_fields_write(struct regmap_field *field, unsigned int id,
+ unsigned int val)
+{
+ if (id >= field->id_size)
+ return -EINVAL;
+
+ return regmap_update_bits(field->regmap,
+ field->reg + (field->id_offset * id),
+ field->mask, val << field->shift);
+}
+EXPORT_SYMBOL_GPL(regmap_fields_write);
+
+/**
+ * regmap_fields_update_bits(): Perform a read/modify/write cycle
+ * on the register field
+ *
+ * @field: Register field to write to
+ * @id: port ID
+ * @mask: Bitmask to change
+ * @val: Value to be written
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_fields_update_bits(struct regmap_field *field, unsigned int id,
+ unsigned int mask, unsigned int val)
+{
+ if (id >= field->id_size)
+ return -EINVAL;
+
+ mask = (mask << field->shift) & field->mask;
+
+ return regmap_update_bits(field->regmap,
+ field->reg + (field->id_offset * id),
+ mask, val << field->shift);
+}
+EXPORT_SYMBOL_GPL(regmap_fields_update_bits);
+
/*
* regmap_bulk_write(): Write multiple registers to the device
*
@@ -1677,6 +1747,39 @@ int regmap_field_read(struct regmap_field *field, unsigned int *val)
EXPORT_SYMBOL_GPL(regmap_field_read);
/**
+ * regmap_fields_read(): Read a value to a single register field with port ID
+ *
+ * @field: Register field to read from
+ * @id: port ID
+ * @val: Pointer to store read value
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_fields_read(struct regmap_field *field, unsigned int id,
+ unsigned int *val)
+{
+ int ret;
+ unsigned int reg_val;
+
+ if (id >= field->id_size)
+ return -EINVAL;
+
+ ret = regmap_read(field->regmap,
+ field->reg + (field->id_offset * id),
+ &reg_val);
+ if (ret != 0)
+ return ret;
+
+ reg_val &= field->mask;
+ reg_val >>= field->shift;
+ *val = reg_val;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_fields_read);
+
+/**
* regmap_bulk_read(): Read multiple registers from the device
*
* @map: Register map to write to
diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c
index c9fd6943ce45..50329d1057ed 100644
--- a/drivers/bcma/driver_pci.c
+++ b/drivers/bcma/driver_pci.c
@@ -210,25 +210,6 @@ static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc)
}
}
-static void bcma_core_pci_power_save(struct bcma_drv_pci *pc, bool up)
-{
- u16 data;
-
- if (pc->core->id.rev >= 15 && pc->core->id.rev <= 20) {
- data = up ? 0x74 : 0x7C;
- bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
- BCMA_CORE_PCI_MDIO_BLK1_MGMT1, 0x7F64);
- bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
- BCMA_CORE_PCI_MDIO_BLK1_MGMT3, data);
- } else if (pc->core->id.rev >= 21 && pc->core->id.rev <= 22) {
- data = up ? 0x75 : 0x7D;
- bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
- BCMA_CORE_PCI_MDIO_BLK1_MGMT1, 0x7E65);
- bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
- BCMA_CORE_PCI_MDIO_BLK1_MGMT3, data);
- }
-}
-
/**************************************************
* Init.
**************************************************/
@@ -255,6 +236,32 @@ void bcma_core_pci_init(struct bcma_drv_pci *pc)
bcma_core_pci_clientmode_init(pc);
}
+void bcma_core_pci_power_save(struct bcma_bus *bus, bool up)
+{
+ struct bcma_drv_pci *pc;
+ u16 data;
+
+ if (bus->hosttype != BCMA_HOSTTYPE_PCI)
+ return;
+
+ pc = &bus->drv_pci[0];
+
+ if (pc->core->id.rev >= 15 && pc->core->id.rev <= 20) {
+ data = up ? 0x74 : 0x7C;
+ bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
+ BCMA_CORE_PCI_MDIO_BLK1_MGMT1, 0x7F64);
+ bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
+ BCMA_CORE_PCI_MDIO_BLK1_MGMT3, data);
+ } else if (pc->core->id.rev >= 21 && pc->core->id.rev <= 22) {
+ data = up ? 0x75 : 0x7D;
+ bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
+ BCMA_CORE_PCI_MDIO_BLK1_MGMT1, 0x7E65);
+ bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
+ BCMA_CORE_PCI_MDIO_BLK1_MGMT3, data);
+ }
+}
+EXPORT_SYMBOL_GPL(bcma_core_pci_power_save);
+
int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
bool enable)
{
@@ -310,8 +317,6 @@ void bcma_core_pci_up(struct bcma_bus *bus)
pc = &bus->drv_pci[0];
- bcma_core_pci_power_save(pc, true);
-
bcma_core_pci_extend_L1timer(pc, true);
}
EXPORT_SYMBOL_GPL(bcma_core_pci_up);
@@ -326,7 +331,5 @@ void bcma_core_pci_down(struct bcma_bus *bus)
pc = &bus->drv_pci[0];
bcma_core_pci_extend_L1timer(pc, false);
-
- bcma_core_pci_power_save(pc, false);
}
EXPORT_SYMBOL_GPL(bcma_core_pci_down);
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index e07a5fd58ad7..d69967335f8c 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -316,6 +316,16 @@ config BLK_DEV_NVME
To compile this driver as a module, choose M here: the
module will be called nvme.
+config BLK_DEV_SKD
+ tristate "STEC S1120 Block Driver"
+ depends on PCI
+ depends on 64BIT
+ ---help---
+ Saying Y or M here will enable support for the
+ STEC, Inc. S1120 PCIe SSD.
+
+ Use device /dev/skd$N amd /dev/skd$Np$M.
+
config BLK_DEV_OSD
tristate "OSD object-as-blkdev support"
depends on SCSI_OSD_ULD
@@ -505,7 +515,7 @@ config VIRTIO_BLK
config BLK_DEV_HD
bool "Very old hard disk (MFM/RLL/IDE) driver"
depends on HAVE_IDE
- depends on !ARM || ARCH_RPC || ARCH_SHARK || BROKEN
+ depends on !ARM || ARCH_RPC || BROKEN
help
This is a very old hard disk driver that lacks the enhanced
functionality of the newer ones.
@@ -541,4 +551,10 @@ config BLK_DEV_RSXX
To compile this driver as a module, choose M here: the
module will be called rsxx.
+config BLOCKCONSOLE
+ bool "Block device console logging support"
+ help
+ This enables logging to block devices.
+ See <file:Documentation/block/blockconsole.txt> for details.
+
endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index ca07399a8d99..08da80f1a72c 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o
obj-$(CONFIG_MG_DISK) += mg_disk.o
obj-$(CONFIG_SUNVDC) += sunvdc.o
obj-$(CONFIG_BLK_DEV_NVME) += nvme.o
+obj-$(CONFIG_BLK_DEV_SKD) += skd.o
obj-$(CONFIG_BLK_DEV_OSD) += osdblk.o
obj-$(CONFIG_BLK_DEV_UMEM) += umem.o
@@ -39,8 +40,10 @@ obj-$(CONFIG_XEN_BLKDEV_BACKEND) += xen-blkback/
obj-$(CONFIG_BLK_DEV_DRBD) += drbd/
obj-$(CONFIG_BLK_DEV_RBD) += rbd.o
obj-$(CONFIG_BLK_DEV_PCIESSD_MTIP32XX) += mtip32xx/
+obj-$(CONFIG_BLOCKCONSOLE) += blockconsole.o
obj-$(CONFIG_BLK_DEV_RSXX) += rsxx/
nvme-y := nvme-core.o nvme-scsi.o
+skd-y := skd_main.o
swim_mod-y := swim.o swim_asm.o
diff --git a/drivers/block/blockconsole.c b/drivers/block/blockconsole.c
new file mode 100644
index 000000000000..65f8ace6dc02
--- /dev/null
+++ b/drivers/block/blockconsole.c
@@ -0,0 +1,618 @@
+/*
+ * Blockconsole - write kernel console to a block device
+ *
+ * Copyright (C) 2012 Joern Engel <joern@logfs.org>
+ */
+#include <linux/bio.h>
+#include <linux/blockconsole.h>
+#include <linux/console.h>
+#include <linux/fs.h>
+#include <linux/kref.h>
+#include <linux/kthread.h>
+#include <linux/mm.h>
+#include <linux/mount.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/sched/rt.h>
+#include <linux/ctype.h>
+
+#define BLOCKCONSOLE_MAGIC "\nLinux blockconsole version 1.1\n"
+#define BCON_UUID_OFS (32)
+#define BCON_ROUND_OFS (41)
+#define BCON_TILE_OFS (50)
+#define BCON_HEADERSIZE (50)
+#define BCON_LONG_HEADERSIZE (59) /* with tile index */
+
+#define PAGE_COUNT (256)
+#define SECTOR_COUNT (PAGE_COUNT * (PAGE_SIZE >> 9))
+#define CACHE_PAGE_MASK (PAGE_COUNT - 1)
+#define CACHE_SECTOR_MASK (SECTOR_COUNT - 1)
+#define CACHE_SIZE (PAGE_COUNT << PAGE_SHIFT)
+#define CACHE_MASK (CACHE_SIZE - 1)
+#define SECTOR_SHIFT (9)
+#define SECTOR_SIZE (1 << SECTOR_SHIFT)
+#define SECTOR_MASK (~(SECTOR_SIZE-1))
+#define PG_SECTOR_MASK ((PAGE_SIZE >> 9) - 1)
+
+#undef pr_fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+struct bcon_bio {
+ struct bio bio;
+ struct bio_vec bvec;
+ void *sector;
+ int in_flight;
+};
+
+struct blockconsole {
+ char devname[32];
+ spinlock_t end_io_lock;
+ struct timer_list pad_timer;
+ int error_count;
+ struct kref kref;
+ u64 console_bytes;
+ u64 write_bytes;
+ u64 max_bytes;
+ u32 round;
+ u32 uuid;
+ struct bcon_bio bio_array[SECTOR_COUNT];
+ struct page *pages;
+ struct bcon_bio zero_bios[PAGE_COUNT];
+ struct page *zero_page;
+ struct block_device *bdev;
+ struct console console;
+ struct work_struct unregister_work;
+ struct work_struct release_work;
+ struct task_struct *writeback_thread;
+ struct notifier_block panic_block;
+};
+
+static void bcon_get(struct blockconsole *bc)
+{
+ kref_get(&bc->kref);
+}
+
+static void __bcon_release(struct work_struct *work)
+{
+ struct blockconsole *bc = container_of(work, struct blockconsole,
+ release_work);
+
+ __free_pages(bc->zero_page, 0);
+ __free_pages(bc->pages, 8);
+ invalidate_mapping_pages(bc->bdev->bd_inode->i_mapping, 0, -1);
+ blkdev_put(bc->bdev, FMODE_READ|FMODE_WRITE);
+ kfree(bc);
+}
+
+static void bcon_release(struct kref *kref)
+{
+ struct blockconsole *bc = container_of(kref, struct blockconsole, kref);
+
+ /* bcon_release can be called from atomic context */
+ schedule_work(&bc->release_work);
+}
+
+static void bcon_put(struct blockconsole *bc)
+{
+ kref_put(&bc->kref, bcon_release);
+}
+
+static int __bcon_console_ofs(u64 console_bytes)
+{
+ return console_bytes & ~SECTOR_MASK;
+}
+
+static int bcon_console_ofs(struct blockconsole *bc)
+{
+ return __bcon_console_ofs(bc->console_bytes);
+}
+
+static int __bcon_console_sector(u64 console_bytes)
+{
+ return (console_bytes >> SECTOR_SHIFT) & CACHE_SECTOR_MASK;
+}
+
+static int bcon_console_sector(struct blockconsole *bc)
+{
+ return __bcon_console_sector(bc->console_bytes);
+}
+
+static int bcon_write_sector(struct blockconsole *bc)
+{
+ return (bc->write_bytes >> SECTOR_SHIFT) & CACHE_SECTOR_MASK;
+}
+
+static void clear_sector(void *sector)
+{
+ memset(sector, ' ', 511);
+ memset(sector + 511, 10, 1);
+}
+
+static void bcon_init_first_page(struct blockconsole *bc)
+{
+ char *buf = page_address(bc->pages);
+ size_t len = strlen(BLOCKCONSOLE_MAGIC);
+ u32 tile = bc->console_bytes >> 20; /* We overflow after 4TB - fine */
+
+ clear_sector(buf);
+ memcpy(buf, BLOCKCONSOLE_MAGIC, len);
+ sprintf(buf + BCON_UUID_OFS, "%08x", bc->uuid);
+ sprintf(buf + BCON_ROUND_OFS, "%08x", bc->round);
+ sprintf(buf + BCON_TILE_OFS, "%08x", tile);
+ /* replace NUL with newline */
+ buf[BCON_UUID_OFS + 8] = 10;
+ buf[BCON_ROUND_OFS + 8] = 10;
+ buf[BCON_TILE_OFS + 8] = 10;
+}
+
+static void bcon_advance_console_bytes(struct blockconsole *bc, int bytes)
+{
+ u64 old, new;
+
+ do {
+ old = bc->console_bytes;
+ new = old + bytes;
+ if (new >= bc->max_bytes)
+ new = 0;
+ if ((new & CACHE_MASK) == 0) {
+ bcon_init_first_page(bc);
+ new += BCON_LONG_HEADERSIZE;
+ }
+ } while (cmpxchg64(&bc->console_bytes, old, new) != old);
+}
+
+static void request_complete(struct bio *bio, int err)
+{
+ complete((struct completion *)bio->bi_private);
+}
+
+static int sync_read(struct blockconsole *bc, u64 ofs)
+{
+ struct bio bio;
+ struct bio_vec bio_vec;
+ struct completion complete;
+
+ bio_init(&bio);
+ bio.bi_io_vec = &bio_vec;
+ bio_vec.bv_page = bc->pages;
+ bio_vec.bv_len = SECTOR_SIZE;
+ bio_vec.bv_offset = 0;
+ bio.bi_vcnt = 1;
+ bio.bi_idx = 0;
+ bio.bi_size = SECTOR_SIZE;
+ bio.bi_bdev = bc->bdev;
+ bio.bi_sector = ofs >> SECTOR_SHIFT;
+ init_completion(&complete);
+ bio.bi_private = &complete;
+ bio.bi_end_io = request_complete;
+
+ submit_bio(READ, &bio);
+ wait_for_completion(&complete);
+ return test_bit(BIO_UPTODATE, &bio.bi_flags) ? 0 : -EIO;
+}
+
+static void bcon_erase_segment(struct blockconsole *bc)
+{
+ int i;
+
+ for (i = 0; i < PAGE_COUNT; i++) {
+ struct bcon_bio *bcon_bio = bc->zero_bios + i;
+ struct bio *bio = &bcon_bio->bio;
+
+ /*
+ * If the last erase hasn't finished yet, just skip it. The log
+ * will look messy, but that's all.
+ */
+ rmb();
+ if (bcon_bio->in_flight)
+ continue;
+ bio_init(bio);
+ bio->bi_io_vec = &bcon_bio->bvec;
+ bio->bi_vcnt = 1;
+ bio->bi_size = PAGE_SIZE;
+ bio->bi_bdev = bc->bdev;
+ bio->bi_private = bc;
+ bio->bi_idx = 0;
+ bio->bi_sector = (bc->write_bytes + i * PAGE_SIZE) >> 9;
+ bcon_bio->in_flight = 1;
+ wmb();
+ /* We want the erase to go to the device first somehow */
+ submit_bio(WRITE | REQ_SOFTBARRIER, bio);
+ }
+}
+
+static void bcon_advance_write_bytes(struct blockconsole *bc, int bytes)
+{
+ bc->write_bytes += bytes;
+ if (bc->write_bytes >= bc->max_bytes) {
+ bc->write_bytes = 0;
+ bc->round++;
+ bcon_init_first_page(bc);
+ }
+}
+
+static int bcon_find_end_of_log(struct blockconsole *bc)
+{
+ u64 start = 0, end = bc->max_bytes, middle;
+ void *sec0 = bc->bio_array[0].sector;
+ void *sec1 = bc->bio_array[1].sector;
+ int err, version;
+
+ err = sync_read(bc, 0);
+ if (err)
+ return err;
+ /* Second sanity check, out of sheer paranoia */
+ version = bcon_magic_present(sec0);
+ if (!version)
+ return -EINVAL;
+
+ bc->uuid = simple_strtoull(sec0 + BCON_UUID_OFS, NULL, 16);
+ bc->round = simple_strtoull(sec0 + BCON_ROUND_OFS, NULL, 16);
+
+ memcpy(sec1, sec0, BCON_HEADERSIZE);
+ for (;;) {
+ middle = (start + end) / 2;
+ middle &= ~CACHE_MASK;
+ if (middle == start)
+ break;
+ err = sync_read(bc, middle);
+ if (err)
+ return err;
+ if (memcmp(sec1, sec0, BCON_HEADERSIZE)) {
+ /* If the two differ, we haven't written that far yet */
+ end = middle;
+ } else {
+ start = middle;
+ }
+ }
+ bc->console_bytes = bc->write_bytes = end;
+ bcon_advance_console_bytes(bc, 0); /* To skip the header */
+ bcon_advance_write_bytes(bc, 0); /* To wrap around, if necessary */
+ bcon_erase_segment(bc);
+ return 0;
+}
+
+static void bcon_unregister(struct work_struct *work)
+{
+ struct blockconsole *bc = container_of(work, struct blockconsole,
+ unregister_work);
+
+ atomic_notifier_chain_unregister(&panic_notifier_list, &bc->panic_block);
+ unregister_console(&bc->console);
+ del_timer_sync(&bc->pad_timer);
+ kthread_stop(bc->writeback_thread);
+ /* No new io will be scheduled anymore now */
+ bcon_put(bc);
+}
+
+#define BCON_MAX_ERRORS 10
+static void bcon_end_io(struct bio *bio, int err)
+{
+ struct bcon_bio *bcon_bio = container_of(bio, struct bcon_bio, bio);
+ struct blockconsole *bc = bio->bi_private;
+ unsigned long flags;
+
+ /*
+ * We want to assume the device broken and free this console if
+ * we accumulate too many errors. But if errors are transient,
+ * we also want to forget about them once writes succeed again.
+ * Oh, and we only want to reset the counter if it hasn't reached
+ * the limit yet, so we don't bcon_put() twice from here.
+ */
+ spin_lock_irqsave(&bc->end_io_lock, flags);
+ if (err) {
+ if (bc->error_count++ == BCON_MAX_ERRORS) {
+ pr_info("no longer logging to %s\n", bc->devname);
+ schedule_work(&bc->unregister_work);
+ }
+ } else {
+ if (bc->error_count && bc->error_count < BCON_MAX_ERRORS)
+ bc->error_count = 0;
+ }
+ /*
+ * Add padding (a bunch of spaces and a newline) early so bcon_pad
+ * only has to advance a pointer.
+ */
+ clear_sector(bcon_bio->sector);
+ bcon_bio->in_flight = 0;
+ spin_unlock_irqrestore(&bc->end_io_lock, flags);
+ bcon_put(bc);
+}
+
+static void bcon_writesector(struct blockconsole *bc, int index)
+{
+ struct bcon_bio *bcon_bio = bc->bio_array + index;
+ struct bio *bio = &bcon_bio->bio;
+
+ rmb();
+ if (bcon_bio->in_flight)
+ return;
+ bcon_get(bc);
+
+ bio_init(bio);
+ bio->bi_io_vec = &bcon_bio->bvec;
+ bio->bi_vcnt = 1;
+ bio->bi_size = SECTOR_SIZE;
+ bio->bi_bdev = bc->bdev;
+ bio->bi_private = bc;
+ bio->bi_end_io = bcon_end_io;
+
+ bio->bi_idx = 0;
+ bio->bi_sector = bc->write_bytes >> 9;
+ bcon_bio->in_flight = 1;
+ wmb();
+ submit_bio(WRITE, bio);
+}
+
+static int bcon_writeback(void *_bc)
+{
+ struct blockconsole *bc = _bc;
+ struct sched_param(sp);
+
+ sp.sched_priority = MAX_RT_PRIO - 1; /* Highest realtime prio */
+ sched_setscheduler_nocheck(current, SCHED_FIFO, &sp);
+ for (;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ if (kthread_should_stop())
+ break;
+ while (bcon_write_sector(bc) != bcon_console_sector(bc)) {
+ bcon_writesector(bc, bcon_write_sector(bc));
+ bcon_advance_write_bytes(bc, SECTOR_SIZE);
+ if (bcon_write_sector(bc) == 0)
+ bcon_erase_segment(bc);
+ }
+ }
+ return 0;
+}
+
+static void bcon_pad(unsigned long data)
+{
+ struct blockconsole *bc = (void *)data;
+ unsigned int n;
+
+ /*
+ * We deliberately race against bcon_write here. If we lose the race,
+ * our padding is no longer where we expected it to be, i.e. it is
+ * no longer a bunch of spaces with a newline at the end. There could
+ * not be a newline at all or it could be somewhere in the middle.
+ * Either way, the log corruption is fairly obvious to spot and ignore
+ * for human readers.
+ */
+ n = SECTOR_SIZE - bcon_console_ofs(bc);
+ if (n != SECTOR_SIZE) {
+ bcon_advance_console_bytes(bc, n);
+ wake_up_process(bc->writeback_thread);
+ }
+}
+
+static void bcon_write(struct console *console, const char *msg,
+ unsigned int len)
+{
+ struct blockconsole *bc = container_of(console, struct blockconsole,
+ console);
+ unsigned int n;
+ u64 console_bytes;
+ int i;
+
+ while (len) {
+ console_bytes = bc->console_bytes;
+ i = __bcon_console_sector(console_bytes);
+ rmb();
+ if (bc->bio_array[i].in_flight)
+ break;
+ n = min_t(int, len, SECTOR_SIZE -
+ __bcon_console_ofs(console_bytes));
+ memcpy(bc->bio_array[i].sector +
+ __bcon_console_ofs(console_bytes), msg, n);
+ len -= n;
+ msg += n;
+ bcon_advance_console_bytes(bc, n);
+ }
+ wake_up_process(bc->writeback_thread);
+ mod_timer(&bc->pad_timer, jiffies + HZ);
+}
+
+static void bcon_init_bios(struct blockconsole *bc)
+{
+ int i;
+
+ for (i = 0; i < SECTOR_COUNT; i++) {
+ int page_index = i >> (PAGE_SHIFT - SECTOR_SHIFT);
+ struct page *page = bc->pages + page_index;
+ struct bcon_bio *bcon_bio = bc->bio_array + i;
+ struct bio_vec *bvec = &bcon_bio->bvec;
+
+ bcon_bio->in_flight = 0;
+ bcon_bio->sector = page_address(bc->pages + page_index)
+ + SECTOR_SIZE * (i & PG_SECTOR_MASK);
+ clear_sector(bcon_bio->sector);
+ bvec->bv_page = page;
+ bvec->bv_len = SECTOR_SIZE;
+ bvec->bv_offset = SECTOR_SIZE * (i & PG_SECTOR_MASK);
+ }
+}
+
+static void bcon_init_zero_bio(struct blockconsole *bc)
+{
+ int i;
+
+ memset(page_address(bc->zero_page), 0, PAGE_SIZE);
+ for (i = 0; i < PAGE_COUNT; i++) {
+ struct bcon_bio *bcon_bio = bc->zero_bios + i;
+ struct bio_vec *bvec = &bcon_bio->bvec;
+
+ bcon_bio->in_flight = 0;
+ bvec->bv_page = bc->zero_page;
+ bvec->bv_len = PAGE_SIZE;
+ bvec->bv_offset = 0;
+ }
+}
+
+static int blockconsole_panic(struct notifier_block *this, unsigned long event,
+ void *ptr)
+{
+ struct blockconsole *bc = container_of(this, struct blockconsole,
+ panic_block);
+ unsigned int n;
+
+ n = SECTOR_SIZE - bcon_console_ofs(bc);
+ if (n != SECTOR_SIZE)
+ bcon_advance_console_bytes(bc, n);
+ bcon_writeback(bc);
+ return NOTIFY_DONE;
+}
+
+static int bcon_create(const char *devname)
+{
+ const fmode_t mode = FMODE_READ | FMODE_WRITE;
+ struct blockconsole *bc;
+ int err;
+
+ bc = kzalloc(sizeof(*bc), GFP_KERNEL);
+ if (!bc)
+ return -ENOMEM;
+ memset(bc->devname, ' ', sizeof(bc->devname));
+ strlcpy(bc->devname, devname, sizeof(bc->devname));
+ spin_lock_init(&bc->end_io_lock);
+ strcpy(bc->console.name, "bcon");
+ bc->console.flags = CON_PRINTBUFFER | CON_ENABLED | CON_ALLDATA;
+ bc->console.write = bcon_write;
+ bc->bdev = blkdev_get_by_path(devname, mode, NULL);
+#ifndef MODULE
+ if (IS_ERR(bc->bdev)) {
+ dev_t devt = name_to_dev_t(devname);
+ if (devt)
+ bc->bdev = blkdev_get_by_dev(devt, mode, NULL);
+ }
+#endif
+ if (IS_ERR(bc->bdev))
+ goto out;
+ bc->pages = alloc_pages(GFP_KERNEL, 8);
+ if (!bc->pages)
+ goto out;
+ bc->zero_page = alloc_pages(GFP_KERNEL, 0);
+ if (!bc->zero_page)
+ goto out1;
+ bcon_init_bios(bc);
+ bcon_init_zero_bio(bc);
+ setup_timer(&bc->pad_timer, bcon_pad, (unsigned long)bc);
+ bc->max_bytes = bc->bdev->bd_inode->i_size & ~CACHE_MASK;
+ err = bcon_find_end_of_log(bc);
+ if (err)
+ goto out2;
+ kref_init(&bc->kref); /* This reference gets freed on errors */
+ bc->writeback_thread = kthread_run(bcon_writeback, bc, "bcon_%s",
+ devname);
+ if (IS_ERR(bc->writeback_thread))
+ goto out2;
+ INIT_WORK(&bc->unregister_work, bcon_unregister);
+ INIT_WORK(&bc->release_work, __bcon_release);
+ register_console(&bc->console);
+ bc->panic_block.notifier_call = blockconsole_panic;
+ bc->panic_block.priority = INT_MAX;
+ atomic_notifier_chain_register(&panic_notifier_list, &bc->panic_block);
+ pr_info("now logging to %s at %llx\n", devname, bc->console_bytes >> 20);
+
+ return 0;
+
+out2:
+ __free_pages(bc->zero_page, 0);
+out1:
+ __free_pages(bc->pages, 8);
+out:
+ kfree(bc);
+ /* Not strictly correct, be the caller doesn't care */
+ return -ENOMEM;
+}
+
+static void bcon_create_fuzzy(const char *name)
+{
+ char *longname;
+ int err;
+
+ err = bcon_create(name);
+ if (err) {
+ longname = kzalloc(strlen(name) + 6, GFP_KERNEL);
+ if (!longname)
+ return;
+ strcpy(longname, "/dev/");
+ strcat(longname, name);
+ bcon_create(longname);
+ kfree(longname);
+ }
+}
+
+static DEFINE_SPINLOCK(bcon_device_lock);
+static char scanned_devices[80];
+
+static void bcon_do_add(struct work_struct *work)
+{
+ char local_devices[80], *name, *remainder = local_devices;
+
+ spin_lock(&bcon_device_lock);
+ memcpy(local_devices, scanned_devices, sizeof(local_devices));
+ memset(scanned_devices, 0, sizeof(scanned_devices));
+ spin_unlock(&bcon_device_lock);
+
+ while (remainder && remainder[0]) {
+ name = strsep(&remainder, ",");
+ bcon_create_fuzzy(name);
+ }
+}
+
+static DECLARE_WORK(bcon_add_work, bcon_do_add);
+
+void bcon_add(const char *name)
+{
+ /*
+ * We add each name to a small static buffer and ask for a workqueue
+ * to go pick it up asap. Once it is picked up, the buffer is empty
+ * again, so hopefully it will suffice for all sane users.
+ */
+ spin_lock(&bcon_device_lock);
+ if (scanned_devices[0])
+ strncat(scanned_devices, ",", sizeof(scanned_devices));
+ strncat(scanned_devices, name, sizeof(scanned_devices));
+ spin_unlock(&bcon_device_lock);
+ schedule_work(&bcon_add_work);
+}
+
+/*
+ * Check if we have an 8-digit hex number followed by newline
+ */
+static bool is_four_byte_hex(const void *data)
+{
+ const char *str = data;
+ int len = 0;
+
+ while (isxdigit(*str) && len++ < 9)
+ str++;
+
+ if (len != 8)
+ return false;
+
+ /* str should point to a \n now */
+ if (*str != 0xa)
+ return false;
+
+ return true;
+}
+
+int bcon_magic_present(const void *data)
+{
+ size_t len = strlen(BLOCKCONSOLE_MAGIC);
+
+ if (memcmp(data, BLOCKCONSOLE_MAGIC, len))
+ return 0;
+ if (!is_four_byte_hex(data + BCON_UUID_OFS))
+ return 0;
+ if (!is_four_byte_hex(data + BCON_ROUND_OFS))
+ return 0;
+ if (!is_four_byte_hex(data + BCON_TILE_OFS))
+ return 0;
+ return 11;
+}
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 40e715531aa6..12326ff6f57d 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -75,6 +75,7 @@
#include <linux/sysfs.h>
#include <linux/miscdevice.h>
#include <linux/falloc.h>
+#include <linux/aio.h>
#include "loop.h"
#include <asm/uaccess.h>
@@ -218,6 +219,48 @@ lo_do_transfer(struct loop_device *lo, int cmd,
return lo->transfer(lo, cmd, rpage, roffs, lpage, loffs, size, rblock);
}
+#ifdef CONFIG_AIO
+static void lo_rw_aio_complete(u64 data, long res)
+{
+ struct bio *bio = (struct bio *)(uintptr_t)data;
+
+ if (res > 0)
+ res = 0;
+ else if (res < 0)
+ res = -EIO;
+
+ bio_endio(bio, res);
+}
+
+static int lo_rw_aio(struct loop_device *lo, struct bio *bio)
+{
+ struct file *file = lo->lo_backing_file;
+ struct kiocb *iocb;
+ unsigned int op;
+ struct iov_iter iter;
+ struct bio_vec *bvec;
+ size_t nr_segs;
+ loff_t pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset;
+
+ iocb = aio_kernel_alloc(GFP_NOIO);
+ if (!iocb)
+ return -ENOMEM;
+
+ if (bio_rw(bio) & WRITE)
+ op = IOCB_CMD_WRITE_ITER;
+ else
+ op = IOCB_CMD_READ_ITER;
+
+ bvec = bio_iovec_idx(bio, bio->bi_idx);
+ nr_segs = bio_segments(bio);
+ iov_iter_init_bvec(&iter, bvec, nr_segs, bvec_length(bvec, nr_segs), 0);
+ aio_kernel_init_rw(iocb, file, iov_iter_count(&iter), pos);
+ aio_kernel_init_callback(iocb, lo_rw_aio_complete, (u64)(uintptr_t)bio);
+
+ return aio_kernel_submit(iocb, op, &iter);
+}
+#endif /* CONFIG_AIO */
+
/**
* __do_lo_send_write - helper for writing data to a loop device
*
@@ -418,50 +461,33 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset;
if (bio_rw(bio) == WRITE) {
- struct file *file = lo->lo_backing_file;
-
- if (bio->bi_rw & REQ_FLUSH) {
- ret = vfs_fsync(file, 0);
- if (unlikely(ret && ret != -EINVAL)) {
- ret = -EIO;
- goto out;
- }
- }
+ ret = lo_send(lo, bio, pos);
+ } else
+ ret = lo_receive(lo, bio, lo->lo_blocksize, pos);
- /*
- * We use punch hole to reclaim the free space used by the
- * image a.k.a. discard. However we do not support discard if
- * encryption is enabled, because it may give an attacker
- * useful information.
- */
- if (bio->bi_rw & REQ_DISCARD) {
- struct file *file = lo->lo_backing_file;
- int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
+ return ret;
+}
- if ((!file->f_op->fallocate) ||
- lo->lo_encrypt_key_size) {
- ret = -EOPNOTSUPP;
- goto out;
- }
- ret = file->f_op->fallocate(file, mode, pos,
- bio->bi_size);
- if (unlikely(ret && ret != -EINVAL &&
- ret != -EOPNOTSUPP))
- ret = -EIO;
- goto out;
- }
+static int lo_discard(struct loop_device *lo, struct bio *bio)
+{
+ struct file *file = lo->lo_backing_file;
+ int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
+ loff_t pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset;
+ int ret;
- ret = lo_send(lo, bio, pos);
+ /*
+ * We use punch hole to reclaim the free space used by the
+ * image a.k.a. discard. However we do not support discard if
+ * encryption is enabled, because it may give an attacker
+ * useful information.
+ */
- if ((bio->bi_rw & REQ_FUA) && !ret) {
- ret = vfs_fsync(file, 0);
- if (unlikely(ret && ret != -EINVAL))
- ret = -EIO;
- }
- } else
- ret = lo_receive(lo, bio, lo->lo_blocksize, pos);
+ if ((!file->f_op->fallocate) || lo->lo_encrypt_key_size)
+ return -EOPNOTSUPP;
-out:
+ ret = file->f_op->fallocate(file, mode, pos, bio->bi_size);
+ if (unlikely(ret && ret != -EINVAL && ret != -EOPNOTSUPP))
+ ret = -EIO;
return ret;
}
@@ -525,7 +551,35 @@ static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio)
do_loop_switch(lo, bio->bi_private);
bio_put(bio);
} else {
- int ret = do_bio_filebacked(lo, bio);
+ int ret;
+
+ if (bio_rw(bio) == WRITE) {
+ if (bio->bi_rw & REQ_FLUSH) {
+ ret = vfs_fsync(lo->lo_backing_file, 1);
+ if (unlikely(ret && ret != -EINVAL))
+ goto out;
+ }
+ if (bio->bi_rw & REQ_DISCARD) {
+ ret = lo_discard(lo, bio);
+ goto out;
+ }
+ }
+#ifdef CONFIG_AIO
+ if (lo->lo_flags & LO_FLAGS_USE_AIO &&
+ lo->transfer == transfer_none) {
+ ret = lo_rw_aio(lo, bio);
+ if (ret == 0)
+ return;
+ } else
+#endif
+ ret = do_bio_filebacked(lo, bio);
+
+ if ((bio_rw(bio) == WRITE) && bio->bi_rw & REQ_FUA && !ret) {
+ ret = vfs_fsync(lo->lo_backing_file, 0);
+ if (unlikely(ret && ret != -EINVAL))
+ ret = -EIO;
+ }
+out:
bio_endio(bio, ret);
}
}
@@ -547,6 +601,12 @@ static int loop_thread(void *data)
struct loop_device *lo = data;
struct bio *bio;
+ /*
+ * In cases where the underlying filesystem calls balance_dirty_pages()
+ * we want less throttling to avoid lock ups trying to write dirty
+ * pages through the loop device
+ */
+ current->flags |= PF_LESS_THROTTLE;
set_user_nice(current, -20);
while (!kthread_should_stop() || !bio_list_empty(&lo->lo_bio_list)) {
@@ -869,6 +929,14 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
!file->f_op->write)
lo_flags |= LO_FLAGS_READ_ONLY;
+#ifdef CONFIG_AIO
+ if (file->f_op->write_iter && file->f_op->read_iter &&
+ mapping->a_ops->direct_IO) {
+ file->f_flags |= O_DIRECT;
+ lo_flags |= LO_FLAGS_USE_AIO;
+ }
+#endif
+
lo_blocksize = S_ISBLK(inode->i_mode) ?
inode->i_bdev->bd_block_size : PAGE_SIZE;
@@ -894,13 +962,6 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
bio_list_init(&lo->lo_bio_list);
- /*
- * set queue make_request_fn, and add limits based on lower level
- * device
- */
- blk_queue_make_request(lo->lo_queue, loop_make_request);
- lo->lo_queue->queuedata = lo;
-
if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync)
blk_queue_flush(lo->lo_queue, REQ_FLUSH);
@@ -1618,6 +1679,8 @@ static int loop_add(struct loop_device **l, int i)
if (!lo)
goto out;
+ lo->lo_state = Lo_unbound;
+
/* allocate id, if @id >= 0, we're requesting that specific id */
if (i >= 0) {
err = idr_alloc(&loop_index_idr, lo, i, i + 1, GFP_KERNEL);
@@ -1635,6 +1698,12 @@ static int loop_add(struct loop_device **l, int i)
if (!lo->lo_queue)
goto out_free_dev;
+ /*
+ * set queue make_request_fn
+ */
+ blk_queue_make_request(lo->lo_queue, loop_make_request);
+ lo->lo_queue->queuedata = lo;
+
disk = lo->lo_disk = alloc_disk(1 << part_shift);
if (!disk)
goto out_free_queue;
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 952dbfe22126..050c71267f14 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -126,64 +126,30 @@ struct mtip_compat_ide_task_request_s {
static bool mtip_check_surprise_removal(struct pci_dev *pdev)
{
u16 vendor_id = 0;
+ struct driver_data *dd = pci_get_drvdata(pdev);
+
+ if (dd->sr)
+ return true;
/* Read the vendorID from the configuration space */
pci_read_config_word(pdev, 0x00, &vendor_id);
- if (vendor_id == 0xFFFF)
+ if (vendor_id == 0xFFFF) {
+ dd->sr = true;
+ if (dd->queue)
+ set_bit(QUEUE_FLAG_DEAD, &dd->queue->queue_flags);
+ else
+ dev_warn(&dd->pdev->dev,
+ "%s: dd->queue is NULL\n", __func__);
+ if (dd->port) {
+ set_bit(MTIP_PF_SR_CLEANUP_BIT, &dd->port->flags);
+ wake_up_interruptible(&dd->port->svc_wait);
+ } else
+ dev_warn(&dd->pdev->dev,
+ "%s: dd->port is NULL\n", __func__);
return true; /* device removed */
-
- return false; /* device present */
-}
-
-/*
- * This function is called for clean the pending command in the
- * command slot during the surprise removal of device and return
- * error to the upper layer.
- *
- * @dd Pointer to the DRIVER_DATA structure.
- *
- * return value
- * None
- */
-static void mtip_command_cleanup(struct driver_data *dd)
-{
- int group = 0, commandslot = 0, commandindex = 0;
- struct mtip_cmd *command;
- struct mtip_port *port = dd->port;
- static int in_progress;
-
- if (in_progress)
- return;
-
- in_progress = 1;
-
- for (group = 0; group < 4; group++) {
- for (commandslot = 0; commandslot < 32; commandslot++) {
- if (!(port->allocated[group] & (1 << commandslot)))
- continue;
-
- commandindex = group << 5 | commandslot;
- command = &port->commands[commandindex];
-
- if (atomic_read(&command->active)
- && (command->async_callback)) {
- command->async_callback(command->async_data,
- -ENODEV);
- command->async_callback = NULL;
- command->async_data = NULL;
- }
-
- dma_unmap_sg(&port->dd->pdev->dev,
- command->sg,
- command->scatter_ents,
- command->direction);
- }
}
- up(&port->cmd_slot);
-
- set_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag);
- in_progress = 0;
+ return false; /* device present */
}
/*
@@ -222,10 +188,7 @@ static int get_slot(struct mtip_port *port)
}
dev_warn(&port->dd->pdev->dev, "Failed to get a tag.\n");
- if (mtip_check_surprise_removal(port->dd->pdev)) {
- /* Device not present, clean outstanding commands */
- mtip_command_cleanup(port->dd);
- }
+ mtip_check_surprise_removal(port->dd->pdev);
return -1;
}
@@ -246,6 +209,107 @@ static inline void release_slot(struct mtip_port *port, int tag)
}
/*
+ * IO completion function.
+ *
+ * This completion function is called by the driver ISR when a
+ * command that was issued by the kernel completes. It first calls the
+ * asynchronous completion function which normally calls back into the block
+ * layer passing the asynchronous callback data, then unmaps the
+ * scatter list associated with the completed command, and finally
+ * clears the allocated bit associated with the completed command.
+ *
+ * @port Pointer to the port data structure.
+ * @tag Tag of the command.
+ * @data Pointer to driver_data.
+ * @status Completion status.
+ *
+ * return value
+ * None
+ */
+static void mtip_async_complete(struct mtip_port *port,
+ int tag,
+ void *data,
+ int status)
+{
+ struct mtip_cmd *command;
+ struct driver_data *dd = data;
+ int cb_status = status ? -EIO : 0;
+
+ if (unlikely(!dd) || unlikely(!port))
+ return;
+
+ command = &port->commands[tag];
+
+ if (unlikely(status == PORT_IRQ_TF_ERR)) {
+ dev_warn(&port->dd->pdev->dev,
+ "Command tag %d failed due to TFE\n", tag);
+ }
+
+ /* Upper layer callback */
+ if (likely(command->async_callback))
+ command->async_callback(command->async_data, cb_status);
+
+ command->async_callback = NULL;
+ command->comp_func = NULL;
+
+ /* Unmap the DMA scatter list entries */
+ dma_unmap_sg(&dd->pdev->dev,
+ command->sg,
+ command->scatter_ents,
+ command->direction);
+
+ /* Clear the allocated and active bits for the command */
+ atomic_set(&port->commands[tag].active, 0);
+ release_slot(port, tag);
+
+ up(&port->cmd_slot);
+}
+
+/*
+ * This function is called for clean the pending command in the
+ * command slot during the surprise removal of device and return
+ * error to the upper layer.
+ *
+ * @dd Pointer to the DRIVER_DATA structure.
+ *
+ * return value
+ * None
+ */
+static void mtip_command_cleanup(struct driver_data *dd)
+{
+ int tag = 0;
+ struct mtip_cmd *cmd;
+ struct mtip_port *port = dd->port;
+ unsigned int num_cmd_slots = dd->slot_groups * 32;
+
+ if (!test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag))
+ return;
+
+ if (!port)
+ return;
+
+ cmd = &port->commands[MTIP_TAG_INTERNAL];
+ if (atomic_read(&cmd->active))
+ if (readl(port->cmd_issue[MTIP_TAG_INTERNAL]) &
+ (1 << MTIP_TAG_INTERNAL))
+ if (cmd->comp_func)
+ cmd->comp_func(port, MTIP_TAG_INTERNAL,
+ cmd->comp_data, -ENODEV);
+
+ while (1) {
+ tag = find_next_bit(port->allocated, num_cmd_slots, tag);
+ if (tag >= num_cmd_slots)
+ break;
+
+ cmd = &port->commands[tag];
+ if (atomic_read(&cmd->active))
+ mtip_async_complete(port, tag, dd, -ENODEV);
+ }
+
+ set_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag);
+}
+
+/*
* Reset the HBA (without sleeping)
*
* @dd Pointer to the driver data structure.
@@ -584,6 +648,9 @@ static void mtip_timeout_function(unsigned long int data)
if (unlikely(!port))
return;
+ if (unlikely(port->dd->sr))
+ return;
+
if (test_bit(MTIP_DDF_RESUME_BIT, &port->dd->dd_flag)) {
mod_timer(&port->cmd_timer,
jiffies + msecs_to_jiffies(30000));
@@ -675,66 +742,6 @@ static void mtip_timeout_function(unsigned long int data)
}
/*
- * IO completion function.
- *
- * This completion function is called by the driver ISR when a
- * command that was issued by the kernel completes. It first calls the
- * asynchronous completion function which normally calls back into the block
- * layer passing the asynchronous callback data, then unmaps the
- * scatter list associated with the completed command, and finally
- * clears the allocated bit associated with the completed command.
- *
- * @port Pointer to the port data structure.
- * @tag Tag of the command.
- * @data Pointer to driver_data.
- * @status Completion status.
- *
- * return value
- * None
- */
-static void mtip_async_complete(struct mtip_port *port,
- int tag,
- void *data,
- int status)
-{
- struct mtip_cmd *command;
- struct driver_data *dd = data;
- int cb_status = status ? -EIO : 0;
-
- if (unlikely(!dd) || unlikely(!port))
- return;
-
- command = &port->commands[tag];
-
- if (unlikely(status == PORT_IRQ_TF_ERR)) {
- dev_warn(&port->dd->pdev->dev,
- "Command tag %d failed due to TFE\n", tag);
- }
-
- /* Upper layer callback */
- if (likely(command->async_callback))
- command->async_callback(command->async_data, cb_status);
-
- command->async_callback = NULL;
- command->comp_func = NULL;
-
- /* Unmap the DMA scatter list entries */
- dma_unmap_sg(&dd->pdev->dev,
- command->sg,
- command->scatter_ents,
- command->direction);
-
- /* Clear the allocated and active bits for the command */
- atomic_set(&port->commands[tag].active, 0);
- release_slot(port, tag);
-
- if (unlikely(command->unaligned))
- up(&port->cmd_slot_unal);
- else
- up(&port->cmd_slot);
-}
-
-/*
* Internal command completion callback function.
*
* This function is normally called by the driver ISR when an internal
@@ -854,7 +861,6 @@ static void mtip_handle_tfe(struct driver_data *dd)
"Missing completion func for tag %d",
tag);
if (mtip_check_surprise_removal(dd->pdev)) {
- mtip_command_cleanup(dd);
/* don't proceed further */
return;
}
@@ -1018,14 +1024,12 @@ static inline void mtip_workq_sdbfx(struct mtip_port *port, int group,
command->comp_data,
0);
} else {
- dev_warn(&dd->pdev->dev,
- "Null completion "
- "for tag %d",
+ dev_dbg(&dd->pdev->dev,
+ "Null completion for tag %d",
tag);
if (mtip_check_surprise_removal(
dd->pdev)) {
- mtip_command_cleanup(dd);
return;
}
}
@@ -1145,7 +1149,6 @@ static inline irqreturn_t mtip_handle_irq(struct driver_data *data)
if (unlikely(port_stat & PORT_IRQ_ERR)) {
if (unlikely(mtip_check_surprise_removal(dd->pdev))) {
- mtip_command_cleanup(dd);
/* don't proceed further */
return IRQ_HANDLED;
}
@@ -2806,34 +2809,51 @@ static ssize_t show_device_status(struct device_driver *drv, char *buf)
static ssize_t mtip_hw_read_device_status(struct file *f, char __user *ubuf,
size_t len, loff_t *offset)
{
+ struct driver_data *dd = (struct driver_data *)f->private_data;
int size = *offset;
- char buf[MTIP_DFS_MAX_BUF_SIZE];
+ char *buf;
+ int rv = 0;
if (!len || *offset)
return 0;
+ buf = kzalloc(MTIP_DFS_MAX_BUF_SIZE, GFP_KERNEL);
+ if (!buf) {
+ dev_err(&dd->pdev->dev,
+ "Memory allocation: status buffer\n");
+ return -ENOMEM;
+ }
+
size += show_device_status(NULL, buf);
*offset = size <= len ? size : len;
size = copy_to_user(ubuf, buf, *offset);
if (size)
- return -EFAULT;
+ rv = -EFAULT;
- return *offset;
+ kfree(buf);
+ return rv ? rv : *offset;
}
static ssize_t mtip_hw_read_registers(struct file *f, char __user *ubuf,
size_t len, loff_t *offset)
{
struct driver_data *dd = (struct driver_data *)f->private_data;
- char buf[MTIP_DFS_MAX_BUF_SIZE];
+ char *buf;
u32 group_allocated;
int size = *offset;
- int n;
+ int n, rv = 0;
if (!len || size)
return 0;
+ buf = kzalloc(MTIP_DFS_MAX_BUF_SIZE, GFP_KERNEL);
+ if (!buf) {
+ dev_err(&dd->pdev->dev,
+ "Memory allocation: register buffer\n");
+ return -ENOMEM;
+ }
+
size += sprintf(&buf[size], "H/ S ACTive : [ 0x");
for (n = dd->slot_groups-1; n >= 0; n--)
@@ -2888,21 +2908,30 @@ static ssize_t mtip_hw_read_registers(struct file *f, char __user *ubuf,
*offset = size <= len ? size : len;
size = copy_to_user(ubuf, buf, *offset);
if (size)
- return -EFAULT;
+ rv = -EFAULT;
- return *offset;
+ kfree(buf);
+ return rv ? rv : *offset;
}
static ssize_t mtip_hw_read_flags(struct file *f, char __user *ubuf,
size_t len, loff_t *offset)
{
struct driver_data *dd = (struct driver_data *)f->private_data;
- char buf[MTIP_DFS_MAX_BUF_SIZE];
+ char *buf;
int size = *offset;
+ int rv = 0;
if (!len || size)
return 0;
+ buf = kzalloc(MTIP_DFS_MAX_BUF_SIZE, GFP_KERNEL);
+ if (!buf) {
+ dev_err(&dd->pdev->dev,
+ "Memory allocation: flag buffer\n");
+ return -ENOMEM;
+ }
+
size += sprintf(&buf[size], "Flag-port : [ %08lX ]\n",
dd->port->flags);
size += sprintf(&buf[size], "Flag-dd : [ %08lX ]\n",
@@ -2911,9 +2940,10 @@ static ssize_t mtip_hw_read_flags(struct file *f, char __user *ubuf,
*offset = size <= len ? size : len;
size = copy_to_user(ubuf, buf, *offset);
if (size)
- return -EFAULT;
+ rv = -EFAULT;
- return *offset;
+ kfree(buf);
+ return rv ? rv : *offset;
}
static const struct file_operations mtip_device_status_fops = {
@@ -3006,6 +3036,46 @@ static void mtip_hw_debugfs_exit(struct driver_data *dd)
debugfs_remove_recursive(dd->dfs_node);
}
+static int mtip_free_orphan(struct driver_data *dd)
+{
+ struct kobject *kobj;
+
+ if (dd->bdev) {
+ if (dd->bdev->bd_holders >= 1)
+ return -2;
+
+ bdput(dd->bdev);
+ dd->bdev = NULL;
+ }
+
+ mtip_hw_debugfs_exit(dd);
+
+ spin_lock(&rssd_index_lock);
+ ida_remove(&rssd_index_ida, dd->index);
+ spin_unlock(&rssd_index_lock);
+
+ if (!test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag) &&
+ test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag)) {
+ put_disk(dd->disk);
+ } else {
+ if (dd->disk) {
+ kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
+ if (kobj) {
+ mtip_hw_sysfs_exit(dd, kobj);
+ kobject_put(kobj);
+ }
+ del_gendisk(dd->disk);
+ dd->disk = NULL;
+ }
+ if (dd->queue) {
+ dd->queue->queuedata = NULL;
+ blk_cleanup_queue(dd->queue);
+ dd->queue = NULL;
+ }
+ }
+ kfree(dd);
+ return 0;
+}
/*
* Perform any init/resume time hardware setup
@@ -3154,6 +3224,7 @@ static int mtip_service_thread(void *data)
unsigned long slot, slot_start, slot_wrap;
unsigned int num_cmd_slots = dd->slot_groups * 32;
struct mtip_port *port = dd->port;
+ int ret;
while (1) {
/*
@@ -3164,13 +3235,18 @@ static int mtip_service_thread(void *data)
!(port->flags & MTIP_PF_PAUSE_IO));
if (kthread_should_stop())
+ goto st_out;
+
+ set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags);
+
+ /* If I am an orphan, start self cleanup */
+ if (test_bit(MTIP_PF_SR_CLEANUP_BIT, &port->flags))
break;
if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
&dd->dd_flag)))
- break;
+ goto st_out;
- set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags);
if (test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) {
slot = 1;
/* used to restrict the loop to one iteration */
@@ -3201,7 +3277,7 @@ static int mtip_service_thread(void *data)
clear_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags);
} else if (test_bit(MTIP_PF_REBUILD_BIT, &port->flags)) {
- if (!mtip_ftl_rebuild_poll(dd))
+ if (mtip_ftl_rebuild_poll(dd) < 0)
set_bit(MTIP_DDF_REBUILD_FAILED_BIT,
&dd->dd_flag);
clear_bit(MTIP_PF_REBUILD_BIT, &port->flags);
@@ -3209,8 +3285,30 @@ static int mtip_service_thread(void *data)
clear_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags);
if (test_bit(MTIP_PF_SVC_THD_STOP_BIT, &port->flags))
+ goto st_out;
+ }
+
+ /* wait for pci remove to exit */
+ while (1) {
+ if (test_bit(MTIP_DDF_REMOVE_DONE_BIT, &dd->dd_flag))
break;
+ msleep_interruptible(1000);
+ if (kthread_should_stop())
+ goto st_out;
+ }
+
+ while (1) {
+ ret = mtip_free_orphan(dd);
+ if (!ret) {
+ /* NOTE: All data structures are invalid, do not
+ * access any here */
+ return 0;
+ }
+ msleep_interruptible(1000);
+ if (kthread_should_stop())
+ goto st_out;
}
+st_out:
return 0;
}
@@ -3437,13 +3535,13 @@ static int mtip_hw_init(struct driver_data *dd)
rv = -EFAULT;
goto out3;
}
+ mtip_dump_identify(dd->port);
if (*(dd->port->identify + MTIP_FTL_REBUILD_OFFSET) ==
MTIP_FTL_REBUILD_MAGIC) {
set_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags);
return MTIP_FTL_REBUILD_MAGIC;
}
- mtip_dump_identify(dd->port);
/* check write protect, over temp and rebuild statuses */
rv = mtip_read_log_page(dd->port, ATA_LOG_SATA_NCQ,
@@ -3467,8 +3565,8 @@ static int mtip_hw_init(struct driver_data *dd)
}
if (buf[288] == 0xBF) {
dev_info(&dd->pdev->dev,
- "Drive indicates rebuild has failed.\n");
- /* TODO */
+ "Drive is in security locked state.\n");
+ set_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag);
}
}
@@ -3523,9 +3621,8 @@ static int mtip_hw_exit(struct driver_data *dd)
* Send standby immediate (E0h) to the drive so that it
* saves its state.
*/
- if (!test_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag)) {
-
- if (!test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags))
+ if (!dd->sr) {
+ if (!test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag))
if (mtip_standby_immediate(dd->port))
dev_warn(&dd->pdev->dev,
"STANDBY IMMEDIATE failed\n");
@@ -3551,6 +3648,7 @@ static int mtip_hw_exit(struct driver_data *dd)
dd->port->command_list_dma);
/* Free the memory allocated for the for structure. */
kfree(dd->port);
+ dd->port = NULL;
return 0;
}
@@ -3572,7 +3670,8 @@ static int mtip_hw_shutdown(struct driver_data *dd)
* Send standby immediate (E0h) to the drive so that it
* saves its state.
*/
- mtip_standby_immediate(dd->port);
+ if (!dd->sr && dd->port)
+ mtip_standby_immediate(dd->port);
return 0;
}
@@ -3887,6 +3986,10 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
bio_endio(bio, -ENODATA);
return;
}
+ if (test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag)) {
+ bio_endio(bio, -ENXIO);
+ return;
+ }
}
if (unlikely(bio->bi_rw & REQ_DISCARD)) {
@@ -4010,6 +4113,8 @@ static int mtip_block_initialize(struct driver_data *dd)
dd->disk->private_data = dd;
dd->index = index;
+ mtip_hw_debugfs_init(dd);
+
/*
* if rebuild pending, start the service thread, and delay the block
* queue creation and add_disk()
@@ -4068,6 +4173,7 @@ skip_create_disk:
/* Enable the block device and add it to /dev */
add_disk(dd->disk);
+ dd->bdev = bdget_disk(dd->disk, 0);
/*
* Now that the disk is active, initialize any sysfs attributes
* managed by the protocol layer.
@@ -4077,7 +4183,6 @@ skip_create_disk:
mtip_hw_sysfs_init(dd, kobj);
kobject_put(kobj);
}
- mtip_hw_debugfs_init(dd);
if (dd->mtip_svc_handler) {
set_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag);
@@ -4103,7 +4208,8 @@ start_service_thread:
return rv;
kthread_run_error:
- mtip_hw_debugfs_exit(dd);
+ bdput(dd->bdev);
+ dd->bdev = NULL;
/* Delete our gendisk. This also removes the device from /dev */
del_gendisk(dd->disk);
@@ -4112,6 +4218,7 @@ read_capacity_error:
blk_cleanup_queue(dd->queue);
block_queue_alloc_init_error:
+ mtip_hw_debugfs_exit(dd);
disk_index_error:
spin_lock(&rssd_index_lock);
ida_remove(&rssd_index_ida, index);
@@ -4141,40 +4248,48 @@ static int mtip_block_remove(struct driver_data *dd)
{
struct kobject *kobj;
- if (dd->mtip_svc_handler) {
- set_bit(MTIP_PF_SVC_THD_STOP_BIT, &dd->port->flags);
- wake_up_interruptible(&dd->port->svc_wait);
- kthread_stop(dd->mtip_svc_handler);
- }
+ if (!dd->sr) {
+ mtip_hw_debugfs_exit(dd);
- /* Clean up the sysfs attributes, if created */
- if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) {
- kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
- if (kobj) {
- mtip_hw_sysfs_exit(dd, kobj);
- kobject_put(kobj);
+ if (dd->mtip_svc_handler) {
+ set_bit(MTIP_PF_SVC_THD_STOP_BIT, &dd->port->flags);
+ wake_up_interruptible(&dd->port->svc_wait);
+ kthread_stop(dd->mtip_svc_handler);
}
- }
- mtip_hw_debugfs_exit(dd);
- /*
- * Delete our gendisk structure. This also removes the device
- * from /dev
- */
- if (dd->disk) {
- if (dd->disk->queue)
- del_gendisk(dd->disk);
- else
- put_disk(dd->disk);
- }
-
- spin_lock(&rssd_index_lock);
- ida_remove(&rssd_index_ida, dd->index);
- spin_unlock(&rssd_index_lock);
+ /* Clean up the sysfs attributes, if created */
+ if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) {
+ kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
+ if (kobj) {
+ mtip_hw_sysfs_exit(dd, kobj);
+ kobject_put(kobj);
+ }
+ }
+ /*
+ * Delete our gendisk structure. This also removes the device
+ * from /dev
+ */
+ if (dd->bdev) {
+ bdput(dd->bdev);
+ dd->bdev = NULL;
+ }
+ if (dd->disk) {
+ if (dd->disk->queue) {
+ del_gendisk(dd->disk);
+ blk_cleanup_queue(dd->queue);
+ dd->queue = NULL;
+ } else
+ put_disk(dd->disk);
+ }
+ dd->disk = NULL;
- blk_cleanup_queue(dd->queue);
- dd->disk = NULL;
- dd->queue = NULL;
+ spin_lock(&rssd_index_lock);
+ ida_remove(&rssd_index_ida, dd->index);
+ spin_unlock(&rssd_index_lock);
+ } else {
+ dev_info(&dd->pdev->dev, "device %s surprise removal\n",
+ dd->disk->disk_name);
+ }
/* De-initialize the protocol layer. */
mtip_hw_exit(dd);
@@ -4490,8 +4605,7 @@ done:
static void mtip_pci_remove(struct pci_dev *pdev)
{
struct driver_data *dd = pci_get_drvdata(pdev);
- int counter = 0;
- unsigned long flags;
+ unsigned long flags, to;
set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);
@@ -4500,17 +4614,22 @@ static void mtip_pci_remove(struct pci_dev *pdev)
list_add(&dd->remove_list, &removing_list);
spin_unlock_irqrestore(&dev_lock, flags);
- if (mtip_check_surprise_removal(pdev)) {
- while (!test_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag)) {
- counter++;
- msleep(20);
- if (counter == 10) {
- /* Cleanup the outstanding commands */
- mtip_command_cleanup(dd);
- break;
- }
- }
+ mtip_check_surprise_removal(pdev);
+ synchronize_irq(dd->pdev->irq);
+
+ /* Spin until workers are done */
+ to = jiffies + msecs_to_jiffies(4000);
+ do {
+ msleep(20);
+ } while (atomic_read(&dd->irq_workers_active) != 0 &&
+ time_before(jiffies, to));
+
+ if (atomic_read(&dd->irq_workers_active) != 0) {
+ dev_warn(&dd->pdev->dev,
+ "Completion workers still active!\n");
}
+ /* Cleanup the outstanding commands */
+ mtip_command_cleanup(dd);
/* Clean up the block layer. */
mtip_block_remove(dd);
@@ -4529,8 +4648,15 @@ static void mtip_pci_remove(struct pci_dev *pdev)
list_del_init(&dd->remove_list);
spin_unlock_irqrestore(&dev_lock, flags);
- kfree(dd);
+ if (!dd->sr)
+ kfree(dd);
+ else
+ set_bit(MTIP_DDF_REMOVE_DONE_BIT, &dd->dd_flag);
+
pcim_iounmap_regions(pdev, 1 << MTIP_ABAR);
+ pci_set_drvdata(pdev, NULL);
+ pci_dev_put(pdev);
+
}
/*
diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h
index 3bb8a295fbe4..9be7a1582ad3 100644
--- a/drivers/block/mtip32xx/mtip32xx.h
+++ b/drivers/block/mtip32xx/mtip32xx.h
@@ -140,6 +140,7 @@ enum {
MTIP_PF_SVC_THD_ACTIVE_BIT = 4,
MTIP_PF_ISSUE_CMDS_BIT = 5,
MTIP_PF_REBUILD_BIT = 6,
+ MTIP_PF_SR_CLEANUP_BIT = 7,
MTIP_PF_SVC_THD_STOP_BIT = 8,
/* below are bit numbers in 'dd_flag' defined in driver_data */
@@ -147,15 +148,18 @@ enum {
MTIP_DDF_REMOVE_PENDING_BIT = 1,
MTIP_DDF_OVER_TEMP_BIT = 2,
MTIP_DDF_WRITE_PROTECT_BIT = 3,
- MTIP_DDF_STOP_IO = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) |
- (1 << MTIP_DDF_SEC_LOCK_BIT) |
- (1 << MTIP_DDF_OVER_TEMP_BIT) |
- (1 << MTIP_DDF_WRITE_PROTECT_BIT)),
-
+ MTIP_DDF_REMOVE_DONE_BIT = 4,
MTIP_DDF_CLEANUP_BIT = 5,
MTIP_DDF_RESUME_BIT = 6,
MTIP_DDF_INIT_DONE_BIT = 7,
MTIP_DDF_REBUILD_FAILED_BIT = 8,
+
+ MTIP_DDF_STOP_IO = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) |
+ (1 << MTIP_DDF_SEC_LOCK_BIT) |
+ (1 << MTIP_DDF_OVER_TEMP_BIT) |
+ (1 << MTIP_DDF_WRITE_PROTECT_BIT) |
+ (1 << MTIP_DDF_REBUILD_FAILED_BIT)),
+
};
struct smart_attr {
@@ -499,6 +503,8 @@ struct driver_data {
bool trim_supp; /* flag indicating trim support */
+ bool sr;
+
int numa_node; /* NUMA support */
char workq_name[32];
@@ -511,6 +517,8 @@ struct driver_data {
int isr_binding;
+ struct block_device *bdev;
+
int unal_qdepth; /* qdepth of unaligned IO queue */
struct list_head online_list; /* linkage for online list */
diff --git a/drivers/block/rsxx/core.c b/drivers/block/rsxx/core.c
index 6e85e21445eb..a8de2eec6ff3 100644
--- a/drivers/block/rsxx/core.c
+++ b/drivers/block/rsxx/core.c
@@ -654,7 +654,8 @@ static void rsxx_eeh_failure(struct pci_dev *dev)
for (i = 0; i < card->n_targets; i++) {
spin_lock_bh(&card->ctrl[i].queue_lock);
cnt = rsxx_cleanup_dma_queue(&card->ctrl[i],
- &card->ctrl[i].queue);
+ &card->ctrl[i].queue,
+ COMPLETE_DMA);
spin_unlock_bh(&card->ctrl[i].queue_lock);
cnt += rsxx_dma_cancel(&card->ctrl[i]);
@@ -748,10 +749,6 @@ static pci_ers_result_t rsxx_slot_reset(struct pci_dev *dev)
card->eeh_state = 0;
- st = rsxx_eeh_remap_dmas(card);
- if (st)
- goto failed_remap_dmas;
-
spin_lock_irqsave(&card->irq_lock, flags);
if (card->n_targets & RSXX_MAX_TARGETS)
rsxx_enable_ier_and_isr(card, CR_INTR_ALL_G);
@@ -778,7 +775,6 @@ static pci_ers_result_t rsxx_slot_reset(struct pci_dev *dev)
return PCI_ERS_RESULT_RECOVERED;
failed_hw_buffers_init:
-failed_remap_dmas:
for (i = 0; i < card->n_targets; i++) {
if (card->ctrl[i].status.buf)
pci_free_consistent(card->dev,
diff --git a/drivers/block/rsxx/dma.c b/drivers/block/rsxx/dma.c
index bed32f16b084..34fd1018c8e5 100644
--- a/drivers/block/rsxx/dma.c
+++ b/drivers/block/rsxx/dma.c
@@ -221,6 +221,19 @@ static void dma_intr_coal_auto_tune(struct rsxx_cardinfo *card)
}
/*----------------- RSXX DMA Handling -------------------*/
+static void rsxx_free_dma(struct rsxx_dma_ctrl *ctrl, struct rsxx_dma *dma)
+{
+ if (!pci_dma_mapping_error(ctrl->card->dev, dma->dma_addr)) {
+ pci_unmap_page(ctrl->card->dev, dma->dma_addr,
+ get_dma_size(dma),
+ dma->cmd == HW_CMD_BLK_WRITE ?
+ PCI_DMA_TODEVICE :
+ PCI_DMA_FROMDEVICE);
+ }
+
+ kmem_cache_free(rsxx_dma_pool, dma);
+}
+
static void rsxx_complete_dma(struct rsxx_dma_ctrl *ctrl,
struct rsxx_dma *dma,
unsigned int status)
@@ -232,21 +245,14 @@ static void rsxx_complete_dma(struct rsxx_dma_ctrl *ctrl,
if (status & DMA_CANCELLED)
ctrl->stats.dma_cancelled++;
- if (dma->dma_addr)
- pci_unmap_page(ctrl->card->dev, dma->dma_addr,
- get_dma_size(dma),
- dma->cmd == HW_CMD_BLK_WRITE ?
- PCI_DMA_TODEVICE :
- PCI_DMA_FROMDEVICE);
-
if (dma->cb)
dma->cb(ctrl->card, dma->cb_data, status ? 1 : 0);
- kmem_cache_free(rsxx_dma_pool, dma);
+ rsxx_free_dma(ctrl, dma);
}
int rsxx_cleanup_dma_queue(struct rsxx_dma_ctrl *ctrl,
- struct list_head *q)
+ struct list_head *q, unsigned int done)
{
struct rsxx_dma *dma;
struct rsxx_dma *tmp;
@@ -254,7 +260,10 @@ int rsxx_cleanup_dma_queue(struct rsxx_dma_ctrl *ctrl,
list_for_each_entry_safe(dma, tmp, q, list) {
list_del(&dma->list);
- rsxx_complete_dma(ctrl, dma, DMA_CANCELLED);
+ if (done & COMPLETE_DMA)
+ rsxx_complete_dma(ctrl, dma, DMA_CANCELLED);
+ else
+ rsxx_free_dma(ctrl, dma);
cnt++;
}
@@ -370,7 +379,7 @@ static void dma_engine_stalled(unsigned long data)
/* Clean up the DMA queue */
spin_lock(&ctrl->queue_lock);
- cnt = rsxx_cleanup_dma_queue(ctrl, &ctrl->queue);
+ cnt = rsxx_cleanup_dma_queue(ctrl, &ctrl->queue, COMPLETE_DMA);
spin_unlock(&ctrl->queue_lock);
cnt += rsxx_dma_cancel(ctrl);
@@ -388,6 +397,7 @@ static void rsxx_issue_dmas(struct rsxx_dma_ctrl *ctrl)
int tag;
int cmds_pending = 0;
struct hw_cmd *hw_cmd_buf;
+ int dir;
hw_cmd_buf = ctrl->cmd.buf;
@@ -424,6 +434,28 @@ static void rsxx_issue_dmas(struct rsxx_dma_ctrl *ctrl)
continue;
}
+ if (dma->cmd == HW_CMD_BLK_WRITE)
+ dir = PCI_DMA_TODEVICE;
+ else
+ dir = PCI_DMA_FROMDEVICE;
+
+ /*
+ * The function pci_map_page is placed here because we can
+ * only, by design, issue up to 255 commands to the hardware
+ * at one time per DMA channel. So the maximum amount of mapped
+ * memory would be 255 * 4 channels * 4096 Bytes which is less
+ * than 2GB, the limit of a x8 Non-HWWD PCIe slot. This way the
+ * pci_map_page function should never fail because of a
+ * lack of mappable memory.
+ */
+ dma->dma_addr = pci_map_page(ctrl->card->dev, dma->page,
+ dma->pg_off, dma->sub_page.cnt << 9, dir);
+ if (pci_dma_mapping_error(ctrl->card->dev, dma->dma_addr)) {
+ push_tracker(ctrl->trackers, tag);
+ rsxx_complete_dma(ctrl, dma, DMA_CANCELLED);
+ continue;
+ }
+
set_tracker_dma(ctrl->trackers, tag, dma);
hw_cmd_buf[ctrl->cmd.idx].command = dma->cmd;
hw_cmd_buf[ctrl->cmd.idx].tag = tag;
@@ -620,14 +652,6 @@ static int rsxx_queue_dma(struct rsxx_cardinfo *card,
if (!dma)
return -ENOMEM;
- dma->dma_addr = pci_map_page(card->dev, page, pg_off, dma_len,
- dir ? PCI_DMA_TODEVICE :
- PCI_DMA_FROMDEVICE);
- if (!dma->dma_addr) {
- kmem_cache_free(rsxx_dma_pool, dma);
- return -ENOMEM;
- }
-
dma->cmd = dir ? HW_CMD_BLK_WRITE : HW_CMD_BLK_READ;
dma->laddr = laddr;
dma->sub_page.off = (dma_off >> 9);
@@ -736,11 +760,9 @@ int rsxx_dma_queue_bio(struct rsxx_cardinfo *card,
return 0;
bvec_err:
- for (i = 0; i < card->n_targets; i++) {
- spin_lock_bh(&card->ctrl[i].queue_lock);
- rsxx_cleanup_dma_queue(&card->ctrl[i], &dma_list[i]);
- spin_unlock_bh(&card->ctrl[i].queue_lock);
- }
+ for (i = 0; i < card->n_targets; i++)
+ rsxx_cleanup_dma_queue(&card->ctrl[i], &dma_list[i],
+ FREE_DMA);
return st;
}
@@ -990,7 +1012,7 @@ void rsxx_dma_destroy(struct rsxx_cardinfo *card)
/* Clean up the DMA queue */
spin_lock_bh(&ctrl->queue_lock);
- rsxx_cleanup_dma_queue(ctrl, &ctrl->queue);
+ rsxx_cleanup_dma_queue(ctrl, &ctrl->queue, COMPLETE_DMA);
spin_unlock_bh(&ctrl->queue_lock);
rsxx_dma_cancel(ctrl);
@@ -1032,6 +1054,11 @@ int rsxx_eeh_save_issued_dmas(struct rsxx_cardinfo *card)
else
card->ctrl[i].stats.reads_issued--;
+ pci_unmap_page(card->dev, dma->dma_addr,
+ get_dma_size(dma),
+ dma->cmd == HW_CMD_BLK_WRITE ?
+ PCI_DMA_TODEVICE :
+ PCI_DMA_FROMDEVICE);
list_add_tail(&dma->list, &issued_dmas[i]);
push_tracker(card->ctrl[i].trackers, j);
cnt++;
@@ -1043,15 +1070,6 @@ int rsxx_eeh_save_issued_dmas(struct rsxx_cardinfo *card)
atomic_sub(cnt, &card->ctrl[i].stats.hw_q_depth);
card->ctrl[i].stats.sw_q_depth += cnt;
card->ctrl[i].e_cnt = 0;
-
- list_for_each_entry(dma, &card->ctrl[i].queue, list) {
- if (dma->dma_addr)
- pci_unmap_page(card->dev, dma->dma_addr,
- get_dma_size(dma),
- dma->cmd == HW_CMD_BLK_WRITE ?
- PCI_DMA_TODEVICE :
- PCI_DMA_FROMDEVICE);
- }
spin_unlock_bh(&card->ctrl[i].queue_lock);
}
@@ -1060,31 +1078,6 @@ int rsxx_eeh_save_issued_dmas(struct rsxx_cardinfo *card)
return 0;
}
-int rsxx_eeh_remap_dmas(struct rsxx_cardinfo *card)
-{
- struct rsxx_dma *dma;
- int i;
-
- for (i = 0; i < card->n_targets; i++) {
- spin_lock_bh(&card->ctrl[i].queue_lock);
- list_for_each_entry(dma, &card->ctrl[i].queue, list) {
- dma->dma_addr = pci_map_page(card->dev, dma->page,
- dma->pg_off, get_dma_size(dma),
- dma->cmd == HW_CMD_BLK_WRITE ?
- PCI_DMA_TODEVICE :
- PCI_DMA_FROMDEVICE);
- if (!dma->dma_addr) {
- spin_unlock_bh(&card->ctrl[i].queue_lock);
- kmem_cache_free(rsxx_dma_pool, dma);
- return -ENOMEM;
- }
- }
- spin_unlock_bh(&card->ctrl[i].queue_lock);
- }
-
- return 0;
-}
-
int rsxx_dma_init(void)
{
rsxx_dma_pool = KMEM_CACHE(rsxx_dma, SLAB_HWCACHE_ALIGN);
diff --git a/drivers/block/rsxx/rsxx_priv.h b/drivers/block/rsxx/rsxx_priv.h
index 5ad5055a4104..82779058e8ec 100644
--- a/drivers/block/rsxx/rsxx_priv.h
+++ b/drivers/block/rsxx/rsxx_priv.h
@@ -345,6 +345,11 @@ enum rsxx_creg_stat {
CREG_STAT_TAG_MASK = 0x0000ff00,
};
+enum rsxx_dma_finish {
+ FREE_DMA = 0x0,
+ COMPLETE_DMA = 0x1,
+};
+
static inline unsigned int CREG_DATA(int N)
{
return CREG_DATA0 + (N << 2);
@@ -379,7 +384,9 @@ typedef void (*rsxx_dma_cb)(struct rsxx_cardinfo *card,
int rsxx_dma_setup(struct rsxx_cardinfo *card);
void rsxx_dma_destroy(struct rsxx_cardinfo *card);
int rsxx_dma_init(void);
-int rsxx_cleanup_dma_queue(struct rsxx_dma_ctrl *ctrl, struct list_head *q);
+int rsxx_cleanup_dma_queue(struct rsxx_dma_ctrl *ctrl,
+ struct list_head *q,
+ unsigned int done);
int rsxx_dma_cancel(struct rsxx_dma_ctrl *ctrl);
void rsxx_dma_cleanup(void);
void rsxx_dma_queue_reset(struct rsxx_cardinfo *card);
diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c
new file mode 100644
index 000000000000..3110f68ecedd
--- /dev/null
+++ b/drivers/block/skd_main.c
@@ -0,0 +1,5817 @@
+/* Copyright 2012 STEC, Inc.
+ *
+ * This file is licensed under the terms of the 3-clause
+ * BSD License (http://opensource.org/licenses/BSD-3-Clause)
+ * or the GNU GPL-2.0 (http://www.gnu.org/licenses/gpl-2.0.html),
+ * at your option. Both licenses are also available in the LICENSE file
+ * distributed with this project. This file may not be copied, modified,
+ * or distributed except in accordance with those terms.
+ * Gordoni Waidhofer <gwaidhofer@stec-inc.com>
+ * Initial Driver Design!
+ * Thomas Swann <tswann@stec-inc.com>
+ * Interrupt handling.
+ * Ramprasad Chinthekindi <rchinthekindi@stec-inc.com>
+ * biomode implementation.
+ * Akhil Bhansali <abhansali@stec-inc.com>
+ * Added support for DISCARD / FLUSH and FUA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/blkdev.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/compiler.h>
+#include <linux/workqueue.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <linux/hdreg.h>
+#include <linux/dma-mapping.h>
+#include <linux/completion.h>
+#include <linux/scatterlist.h>
+#include <linux/version.h>
+#include <linux/err.h>
+#include <linux/scatterlist.h>
+#include <linux/aer.h>
+#include <linux/ctype.h>
+#include <linux/wait.h>
+#include <linux/uio.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/sg.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <asm-generic/unaligned.h>
+
+#include "skd_s1120.h"
+
+static int skd_dbg_level;
+static int skd_isr_comp_limit = 4;
+
+enum {
+ STEC_LINK_2_5GTS = 0,
+ STEC_LINK_5GTS = 1,
+ STEC_LINK_8GTS = 2,
+ STEC_LINK_UNKNOWN = 0xFF
+};
+
+enum {
+ SKD_FLUSH_INITIALIZER,
+ SKD_FLUSH_ZERO_SIZE_FIRST,
+ SKD_FLUSH_DATA_SECOND,
+};
+
+#define DPRINTK(skdev, fmt, args ...) \
+ do { \
+ if (unlikely((skdev)->dbg_level > 0)) { \
+ pr_err("%s:%s:%d " fmt, (skdev)->name, \
+ __func__, __LINE__, ## args); \
+ } \
+ } while (0)
+
+#define SKD_ASSERT(expr) \
+ do { \
+ if (unlikely(!(expr))) { \
+ pr_err("Assertion failed! %s,%s,%s,line=%d\n", \
+ # expr, __FILE__, __func__, __LINE__); \
+ } \
+ } while (0)
+
+#define VPRINTK(skdev, fmt, args ...) \
+ do { \
+ if (unlikely((skdev)->dbg_level > 1)) { \
+ pr_err("%s:%s:%d " fmt, (skdev)->name, \
+ __func__, __LINE__, ## args); \
+ } \
+ } while (0)
+
+
+#define DRV_NAME "skd"
+#define DRV_VERSION "2.2.1"
+#define DRV_BUILD_ID "0260"
+#define PFX DRV_NAME ": "
+#define DRV_BIN_VERSION 0x100
+#define DRV_VER_COMPL "2.2.1." DRV_BUILD_ID
+
+MODULE_AUTHOR("bug-reports: support@stec-inc.com");
+MODULE_LICENSE("Dual BSD/GPL");
+
+MODULE_DESCRIPTION("STEC s1120 PCIe SSD block/BIO driver (b" DRV_BUILD_ID ")");
+MODULE_VERSION(DRV_VERSION "-" DRV_BUILD_ID);
+
+#define PCI_VENDOR_ID_STEC 0x1B39
+#define PCI_DEVICE_ID_S1120 0x0001
+
+#define SKD_FUA_NV (1 << 1)
+#define SKD_MINORS_PER_DEVICE 16
+
+#define SKD_MAX_QUEUE_DEPTH 200u
+
+#define SKD_PAUSE_TIMEOUT (5 * 1000)
+
+#define SKD_N_FITMSG_BYTES (512u)
+
+#define SKD_N_SPECIAL_CONTEXT 32u
+#define SKD_N_SPECIAL_FITMSG_BYTES (128u)
+
+/* SG elements are 32 bytes, so we can make this 4096 and still be under the
+ * 128KB limit. That allows 4096*4K = 16M xfer size
+ */
+#define SKD_N_SG_PER_REQ_DEFAULT 256u
+#define SKD_N_SG_PER_SPECIAL 256u
+
+#define SKD_N_COMPLETION_ENTRY 256u
+#define SKD_N_READ_CAP_BYTES (8u)
+
+#define SKD_N_INTERNAL_BYTES (512u)
+
+/* 5 bits of uniqifier, 0xF800 */
+#define SKD_ID_INCR (0x400)
+#define SKD_ID_TABLE_MASK (3u << 8u)
+#define SKD_ID_RW_REQUEST (0u << 8u)
+#define SKD_ID_INTERNAL (1u << 8u)
+#define SKD_ID_SPECIAL_REQUEST (2u << 8u)
+#define SKD_ID_FIT_MSG (3u << 8u)
+#define SKD_ID_SLOT_MASK 0x00FFu
+#define SKD_ID_SLOT_AND_TABLE_MASK 0x03FFu
+
+#define SKD_N_TIMEOUT_SLOT 4u
+#define SKD_TIMEOUT_SLOT_MASK 3u
+
+#define SKD_N_MAX_SECTORS 2048u
+
+#define SKD_MAX_RETRIES 2u
+
+#define SKD_TIMER_SECONDS(seconds) (seconds)
+#define SKD_TIMER_MINUTES(minutes) ((minutes) * (60))
+
+#define INQ_STD_NBYTES 36
+#define SKD_DISCARD_CDB_LENGTH 24
+
+enum skd_drvr_state {
+ SKD_DRVR_STATE_LOAD,
+ SKD_DRVR_STATE_IDLE,
+ SKD_DRVR_STATE_BUSY,
+ SKD_DRVR_STATE_STARTING,
+ SKD_DRVR_STATE_ONLINE,
+ SKD_DRVR_STATE_PAUSING,
+ SKD_DRVR_STATE_PAUSED,
+ SKD_DRVR_STATE_DRAINING_TIMEOUT,
+ SKD_DRVR_STATE_RESTARTING,
+ SKD_DRVR_STATE_RESUMING,
+ SKD_DRVR_STATE_STOPPING,
+ SKD_DRVR_STATE_FAULT,
+ SKD_DRVR_STATE_DISAPPEARED,
+ SKD_DRVR_STATE_PROTOCOL_MISMATCH,
+ SKD_DRVR_STATE_BUSY_ERASE,
+ SKD_DRVR_STATE_BUSY_SANITIZE,
+ SKD_DRVR_STATE_BUSY_IMMINENT,
+ SKD_DRVR_STATE_WAIT_BOOT,
+ SKD_DRVR_STATE_SYNCING,
+};
+
+#define SKD_WAIT_BOOT_TIMO SKD_TIMER_SECONDS(90u)
+#define SKD_STARTING_TIMO SKD_TIMER_SECONDS(8u)
+#define SKD_RESTARTING_TIMO SKD_TIMER_MINUTES(4u)
+#define SKD_DRAINING_TIMO SKD_TIMER_SECONDS(6u)
+#define SKD_BUSY_TIMO SKD_TIMER_MINUTES(20u)
+#define SKD_STARTED_BUSY_TIMO SKD_TIMER_SECONDS(60u)
+#define SKD_START_WAIT_SECONDS 90u
+
+enum skd_req_state {
+ SKD_REQ_STATE_IDLE,
+ SKD_REQ_STATE_SETUP,
+ SKD_REQ_STATE_BUSY,
+ SKD_REQ_STATE_COMPLETED,
+ SKD_REQ_STATE_TIMEOUT,
+ SKD_REQ_STATE_ABORTED,
+};
+
+enum skd_fit_msg_state {
+ SKD_MSG_STATE_IDLE,
+ SKD_MSG_STATE_BUSY,
+};
+
+enum skd_check_status_action {
+ SKD_CHECK_STATUS_REPORT_GOOD,
+ SKD_CHECK_STATUS_REPORT_SMART_ALERT,
+ SKD_CHECK_STATUS_REQUEUE_REQUEST,
+ SKD_CHECK_STATUS_REPORT_ERROR,
+ SKD_CHECK_STATUS_BUSY_IMMINENT,
+};
+
+struct skd_fitmsg_context {
+ enum skd_fit_msg_state state;
+
+ struct skd_fitmsg_context *next;
+
+ u32 id;
+ u16 outstanding;
+
+ u32 length;
+ u32 offset;
+
+ u8 *msg_buf;
+ dma_addr_t mb_dma_address;
+};
+
+struct skd_request_context {
+ enum skd_req_state state;
+
+ struct skd_request_context *next;
+
+ u16 id;
+ u32 fitmsg_id;
+
+ struct request *req;
+ struct bio *bio;
+ unsigned long start_time;
+ u8 flush_cmd;
+ u8 discard_page;
+
+ u32 timeout_stamp;
+ u8 sg_data_dir;
+ struct scatterlist *sg;
+ u32 n_sg;
+ u32 sg_byte_count;
+
+ struct fit_sg_descriptor *sksg_list;
+ dma_addr_t sksg_dma_address;
+
+ struct fit_completion_entry_v1 completion;
+
+ struct fit_comp_error_info err_info;
+
+};
+#define SKD_DATA_DIR_HOST_TO_CARD 1
+#define SKD_DATA_DIR_CARD_TO_HOST 2
+#define SKD_DATA_DIR_NONE 3 /* especially for DISCARD requests. */
+
+struct skd_special_context {
+ struct skd_request_context req;
+
+ u8 orphaned;
+
+ void *data_buf;
+ dma_addr_t db_dma_address;
+
+ u8 *msg_buf;
+ dma_addr_t mb_dma_address;
+};
+
+struct skd_sg_io {
+ fmode_t mode;
+ void __user *argp;
+
+ struct sg_io_hdr sg;
+
+ u8 cdb[16];
+
+ u32 dxfer_len;
+ u32 iovcnt;
+ struct sg_iovec *iov;
+ struct sg_iovec no_iov_iov;
+
+ struct skd_special_context *skspcl;
+};
+
+typedef enum skd_irq_type {
+ SKD_IRQ_LEGACY,
+ SKD_IRQ_MSI,
+ SKD_IRQ_MSIX
+} skd_irq_type_t;
+
+#define SKD_MAX_BARS 2
+
+struct skd_device {
+ volatile void __iomem *mem_map[SKD_MAX_BARS];
+ resource_size_t mem_phys[SKD_MAX_BARS];
+ u32 mem_size[SKD_MAX_BARS];
+
+ skd_irq_type_t irq_type;
+ u32 msix_count;
+ struct skd_msix_entry *msix_entries;
+
+ struct pci_dev *pdev;
+ int pcie_error_reporting_is_enabled;
+
+ spinlock_t lock;
+ struct gendisk *disk;
+ struct request_queue *queue;
+ struct device *class_dev;
+ int gendisk_on;
+ int sync_done;
+
+ atomic_t device_count;
+ u32 devno;
+ u32 major;
+ char name[32];
+ char isr_name[30];
+
+ enum skd_drvr_state state;
+ u32 drive_state;
+
+ u32 in_flight;
+ u32 cur_max_queue_depth;
+ u32 queue_low_water_mark;
+ u32 dev_max_queue_depth;
+
+ u32 num_fitmsg_context;
+ u32 num_req_context;
+
+ u32 timeout_slot[SKD_N_TIMEOUT_SLOT];
+ u32 timeout_stamp;
+ struct skd_fitmsg_context *skmsg_free_list;
+ struct skd_fitmsg_context *skmsg_table;
+
+ struct skd_request_context *skreq_free_list;
+ struct skd_request_context *skreq_table;
+
+ struct skd_special_context *skspcl_free_list;
+ struct skd_special_context *skspcl_table;
+
+ struct skd_special_context internal_skspcl;
+ u32 read_cap_blocksize;
+ u32 read_cap_last_lba;
+ int read_cap_is_valid;
+ int inquiry_is_valid;
+ u8 inq_serial_num[13]; /*12 chars plus null term */
+ u8 id_str[80]; /* holds a composite name (pci + sernum) */
+
+ u8 skcomp_cycle;
+ u32 skcomp_ix;
+ struct fit_completion_entry_v1 *skcomp_table;
+ struct fit_comp_error_info *skerr_table;
+ dma_addr_t cq_dma_address;
+
+ wait_queue_head_t waitq;
+
+ struct timer_list timer;
+ u32 timer_countdown;
+ u32 timer_substate;
+
+ int n_special;
+ int sgs_per_request;
+ u32 last_mtd;
+
+ u32 proto_ver;
+
+ int dbg_level;
+ u32 connect_time_stamp;
+ int connect_retries;
+#define SKD_MAX_CONNECT_RETRIES 16
+ u32 drive_jiffies;
+
+ u32 timo_slot;
+
+
+ struct work_struct completion_worker;
+
+ struct bio_list bio_queue;
+ int queue_stopped;
+
+ struct list_head flush_list;
+};
+
+#define SKD_FLUSH_JOB "skd-flush-jobs"
+struct kmem_cache *skd_flush_slab;
+
+/*
+ * These commands hold "nonzero size FLUSH bios",
+ * which are enqueud in skdev->flush_list during
+ * completion of "zero size FLUSH commands".
+ * It will be active in biomode.
+ */
+struct skd_flush_cmd {
+ void *cmd;
+ struct list_head flist;
+};
+
+#define SKD_WRITEL(DEV, VAL, OFF) skd_reg_write32(DEV, VAL, OFF)
+#define SKD_READL(DEV, OFF) skd_reg_read32(DEV, OFF)
+#define SKD_WRITEQ(DEV, VAL, OFF) skd_reg_write64(DEV, VAL, OFF)
+
+static inline u32 skd_reg_read32(struct skd_device *skdev, u32 offset)
+{
+ u32 val;
+
+ if (likely(skdev->dbg_level < 2))
+ return readl(skdev->mem_map[1] + offset);
+ else {
+ barrier();
+ val = readl(skdev->mem_map[1] + offset);
+ barrier();
+ VPRINTK(skdev, "offset %x = %x\n", offset, val);
+ return val;
+ }
+
+}
+
+static inline void skd_reg_write32(struct skd_device *skdev, u32 val,
+ u32 offset)
+{
+ if (likely(skdev->dbg_level < 2)) {
+ writel(val, skdev->mem_map[1] + offset);
+ barrier();
+ readl(skdev->mem_map[1] + offset);
+ barrier();
+ } else {
+ barrier();
+ writel(val, skdev->mem_map[1] + offset);
+ barrier();
+ readl(skdev->mem_map[1] + offset);
+ barrier();
+ VPRINTK(skdev, "offset %x = %x\n", offset, val);
+ }
+}
+
+static inline void skd_reg_write64(struct skd_device *skdev, u64 val,
+ u32 offset)
+{
+ if (likely(skdev->dbg_level < 2)) {
+ writeq(val, skdev->mem_map[1] + offset);
+ barrier();
+ readq(skdev->mem_map[1] + offset);
+ barrier();
+ } else {
+ barrier();
+ writeq(val, skdev->mem_map[1] + offset);
+ barrier();
+ readq(skdev->mem_map[1] + offset);
+ barrier();
+ VPRINTK(skdev, "offset %x = %016llx\n", offset, val);
+ }
+}
+
+
+#define SKD_IRQ_DEFAULT SKD_IRQ_MSI
+static int skd_isr_type = SKD_IRQ_DEFAULT;
+
+module_param(skd_isr_type, int, 0444);
+MODULE_PARM_DESC(skd_isr_type, "Interrupt type capability."
+ " (0==legacy, 1==MSI, 2==MSI-X, default==1)");
+
+#define SKD_MAX_REQ_PER_MSG_DEFAULT 1
+static int skd_max_req_per_msg = SKD_MAX_REQ_PER_MSG_DEFAULT;
+
+module_param(skd_max_req_per_msg, int, 0444);
+MODULE_PARM_DESC(skd_max_req_per_msg,
+ "Maximum SCSI requests packed in a single message."
+ " (1-14, default==1)");
+
+#define SKD_MAX_QUEUE_DEPTH_DEFAULT 64
+#define SKD_MAX_QUEUE_DEPTH_DEFAULT_STR "64"
+static int skd_max_queue_depth = SKD_MAX_QUEUE_DEPTH_DEFAULT;
+
+module_param(skd_max_queue_depth, int, 0444);
+MODULE_PARM_DESC(skd_max_queue_depth,
+ "Maximum SCSI requests issued to s1120."
+ " (1-200, default==" SKD_MAX_QUEUE_DEPTH_DEFAULT_STR ")");
+
+static int skd_sgs_per_request = SKD_N_SG_PER_REQ_DEFAULT;
+module_param(skd_sgs_per_request, int, 0444);
+MODULE_PARM_DESC(skd_sgs_per_request,
+ "Maximum SG elements per block request."
+ " (1-4096, default==256)");
+
+static int skd_max_pass_thru = SKD_N_SPECIAL_CONTEXT;
+module_param(skd_max_pass_thru, int, 0444);
+MODULE_PARM_DESC(skd_max_pass_thru,
+ "Maximum SCSI pass-thru at a time." " (1-50, default==32)");
+
+module_param(skd_dbg_level, int, 0444);
+MODULE_PARM_DESC(skd_dbg_level, "s1120 debug level (0,1,2)");
+
+module_param(skd_isr_comp_limit, int, 0444);
+MODULE_PARM_DESC(skd_isr_comp_limit, "s1120 isr comp limit (0=none) default=4");
+
+static int skd_bio;
+module_param(skd_bio, int, 0444);
+MODULE_PARM_DESC(skd_bio,
+ "Register as a bio device instead of block (0, 1) default=0");
+
+/* Major device number dynamically assigned. */
+static u32 skd_major;
+
+static struct skd_device *skd_construct(struct pci_dev *pdev);
+static void skd_destruct(struct skd_device *skdev);
+static const struct block_device_operations skd_blockdev_ops;
+static void skd_send_fitmsg(struct skd_device *skdev,
+ struct skd_fitmsg_context *skmsg);
+static void skd_send_special_fitmsg(struct skd_device *skdev,
+ struct skd_special_context *skspcl);
+static void skd_request_fn(struct request_queue *rq);
+static void skd_end_request(struct skd_device *skdev,
+ struct skd_request_context *skreq, int error);
+static int skd_preop_sg_list(struct skd_device *skdev,
+ struct skd_request_context *skreq);
+static void skd_postop_sg_list(struct skd_device *skdev,
+ struct skd_request_context *skreq);
+
+static void skd_restart_device(struct skd_device *skdev);
+static int skd_quiesce_dev(struct skd_device *skdev);
+static int skd_unquiesce_dev(struct skd_device *skdev);
+static void skd_release_special(struct skd_device *skdev,
+ struct skd_special_context *skspcl);
+static void skd_disable_interrupts(struct skd_device *skdev);
+static void skd_isr_fwstate(struct skd_device *skdev);
+static void skd_recover_requests(struct skd_device *skdev, int requeue);
+static void skd_soft_reset(struct skd_device *skdev);
+
+static const char *skd_name(struct skd_device *skdev);
+const char *skd_drive_state_to_str(int state);
+const char *skd_skdev_state_to_str(enum skd_drvr_state state);
+static void skd_log_skdev(struct skd_device *skdev, const char *event);
+static void skd_log_skmsg(struct skd_device *skdev,
+ struct skd_fitmsg_context *skmsg, const char *event);
+static void skd_log_skreq(struct skd_device *skdev,
+ struct skd_request_context *skreq, const char *event);
+
+/* FLUSH FUA flag handling. */
+static int skd_flush_cmd_enqueue(struct skd_device *, void *);
+static void *skd_flush_cmd_dequeue(struct skd_device *);
+
+
+/*
+ *****************************************************************************
+ * READ/WRITE REQUESTS
+ *****************************************************************************
+ */
+static void skd_stop_queue(struct skd_device *skdev)
+{
+ if (!skd_bio)
+ blk_stop_queue(skdev->queue);
+ else
+ skdev->queue_stopped = 1;
+}
+
+static void skd_unstop_queue(struct skd_device *skdev)
+{
+ if (!skd_bio)
+ queue_flag_clear(QUEUE_FLAG_STOPPED, skdev->queue);
+ else
+ skdev->queue_stopped = 0;
+}
+
+static void skd_start_queue(struct skd_device *skdev)
+{
+ if (!skd_bio) {
+ blk_start_queue(skdev->queue);
+ } else {
+ pr_err("(%s): Starting queue\n", skd_name(skdev));
+ skdev->queue_stopped = 0;
+ skd_request_fn(skdev->queue);
+ }
+}
+
+static int skd_queue_stopped(struct skd_device *skdev)
+{
+ if (!skd_bio)
+ return blk_queue_stopped(skdev->queue);
+ else
+ return skdev->queue_stopped;
+}
+
+static void skd_fail_all_pending_blk(struct skd_device *skdev)
+{
+ struct request_queue *q = skdev->queue;
+ struct request *req;
+
+ for (;; ) {
+ req = blk_peek_request(q);
+ if (req == NULL)
+ break;
+ blk_start_request(req);
+ __blk_end_request_all(req, -EIO);
+ }
+}
+
+static void skd_fail_all_pending_bio(struct skd_device *skdev)
+{
+ struct bio *bio;
+ int error = -EIO;
+
+ for (;; ) {
+ bio = bio_list_pop(&skdev->bio_queue);
+
+ if (bio == NULL)
+ break;
+
+ bio_endio(bio, error);
+ }
+}
+
+static void skd_fail_all_pending(struct skd_device *skdev)
+{
+ if (!skd_bio)
+ skd_fail_all_pending_blk(skdev);
+ else
+ skd_fail_all_pending_bio(skdev);
+}
+
+static void skd_make_request(struct request_queue *q, struct bio *bio)
+{
+ struct skd_device *skdev = q->queuedata;
+ unsigned long flags;
+
+ spin_lock_irqsave(&skdev->lock, flags);
+
+ bio_list_add(&skdev->bio_queue, bio);
+ skd_request_fn(skdev->queue);
+
+ spin_unlock_irqrestore(&skdev->lock, flags);
+}
+
+static void
+skd_prep_rw_cdb(struct skd_scsi_request *scsi_req,
+ int data_dir, unsigned lba,
+ unsigned count)
+{
+ if (data_dir == READ)
+ scsi_req->cdb[0] = 0x28;
+ else
+ scsi_req->cdb[0] = 0x2a;
+
+ scsi_req->cdb[1] = 0;
+ scsi_req->cdb[2] = (lba & 0xff000000) >> 24;
+ scsi_req->cdb[3] = (lba & 0xff0000) >> 16;
+ scsi_req->cdb[4] = (lba & 0xff00) >> 8;
+ scsi_req->cdb[5] = (lba & 0xff);
+ scsi_req->cdb[6] = 0;
+ scsi_req->cdb[7] = (count & 0xff00) >> 8;
+ scsi_req->cdb[8] = count & 0xff;
+ scsi_req->cdb[9] = 0;
+}
+
+static void
+skd_prep_zerosize_flush_cdb(struct skd_scsi_request *scsi_req,
+ struct skd_request_context *skreq)
+{
+ skreq->flush_cmd = 1;
+
+ scsi_req->cdb[0] = 0x35;
+ scsi_req->cdb[1] = 0;
+ scsi_req->cdb[2] = 0;
+ scsi_req->cdb[3] = 0;
+ scsi_req->cdb[4] = 0;
+ scsi_req->cdb[5] = 0;
+ scsi_req->cdb[6] = 0;
+ scsi_req->cdb[7] = 0;
+ scsi_req->cdb[8] = 0;
+ scsi_req->cdb[9] = 0;
+}
+
+static void
+skd_prep_discard_cdb(struct skd_scsi_request *scsi_req,
+ struct skd_request_context *skreq,
+ struct page *page,
+ u32 lba, u32 count)
+{
+ char *buf;
+ unsigned long len;
+ struct request *req;
+
+ buf = page_address(page);
+ len = SKD_DISCARD_CDB_LENGTH;
+
+ scsi_req->cdb[0] = UNMAP;
+ scsi_req->cdb[8] = len;
+
+ put_unaligned_be16(6 + 16, &buf[0]);
+ put_unaligned_be16(16, &buf[2]);
+ put_unaligned_be64(lba, &buf[8]);
+ put_unaligned_be32(count, &buf[16]);
+
+ if (!skd_bio) {
+ req = skreq->req;
+ blk_add_request_payload(req, page, len);
+ req->buffer = buf;
+ } else {
+ skreq->bio->bi_io_vec->bv_page = page;
+ skreq->bio->bi_io_vec->bv_offset = 0;
+ skreq->bio->bi_io_vec->bv_len = len;
+
+ skreq->bio->bi_vcnt = 1;
+ skreq->bio->bi_phys_segments = 1;
+ }
+}
+
+static void skd_request_fn_not_online(struct request_queue *q);
+
+static void skd_request_fn(struct request_queue *q)
+{
+ struct skd_device *skdev = q->queuedata;
+ struct skd_fitmsg_context *skmsg = NULL;
+ struct fit_msg_hdr *fmh = NULL;
+ struct skd_request_context *skreq;
+ struct request *req = NULL;
+ struct bio *bio = NULL;
+ struct skd_scsi_request *scsi_req;
+ struct page *page;
+ unsigned long io_flags;
+ int error;
+ u32 lba;
+ u32 count;
+ int data_dir;
+ u32 be_lba;
+ u32 be_count;
+ u64 be_dmaa;
+ u64 cmdctxt;
+ u32 timo_slot;
+ void *cmd_ptr;
+ int flush, fua;
+
+ if (skdev->state != SKD_DRVR_STATE_ONLINE) {
+ skd_request_fn_not_online(q);
+ return;
+ }
+
+ if (skd_queue_stopped(skdev)) {
+ if (skdev->skmsg_free_list == NULL ||
+ skdev->skreq_free_list == NULL ||
+ skdev->in_flight >= skdev->queue_low_water_mark)
+ /* There is still some kind of shortage */
+ return;
+
+ skd_unstop_queue(skdev);
+ }
+
+ /*
+ * Stop conditions:
+ * - There are no more native requests
+ * - There are already the maximum number of requests in progress
+ * - There are no more skd_request_context entries
+ * - There are no more FIT msg buffers
+ */
+ for (;; ) {
+
+ flush = fua = 0;
+
+ if (!skd_bio) {
+ req = blk_peek_request(q);
+
+ /* Are there any native requests to start? */
+ if (req == NULL)
+ break;
+
+ lba = (u32)blk_rq_pos(req);
+ count = blk_rq_sectors(req);
+ data_dir = rq_data_dir(req);
+ io_flags = req->cmd_flags;
+
+ if (io_flags & REQ_FLUSH)
+ flush++;
+
+ if (io_flags & REQ_FUA)
+ fua++;
+
+ VPRINTK(skdev,
+ "new req=%p lba=%u(0x%x) count=%u(0x%x) dir=%d\n",
+ req, lba, lba, count, count, data_dir);
+ } else {
+ if (!list_empty(&skdev->flush_list)) {
+ /* Process data part of FLUSH request. */
+ bio = (struct bio *)skd_flush_cmd_dequeue(skdev);
+ flush++;
+ VPRINTK(skdev, "processing FLUSH request with data.\n");
+ } else {
+ /* peek at our bio queue */
+ bio = bio_list_peek(&skdev->bio_queue);
+ }
+
+ /* Are there any native requests to start? */
+ if (bio == NULL)
+ break;
+
+ lba = (u32)bio->bi_sector;
+ count = bio_sectors(bio);
+ data_dir = bio_data_dir(bio);
+ io_flags = bio->bi_rw;
+
+ VPRINTK(skdev,
+ "new bio=%p lba=%u(0x%x) count=%u(0x%x) dir=%d\n",
+ bio, lba, lba, count, count, data_dir);
+
+ if (io_flags & REQ_FLUSH)
+ flush++;
+
+ if (io_flags & REQ_FUA)
+ fua++;
+ }
+
+ /* At this point we know there is a request
+ * (from our bio q or req q depending on the way
+ * the driver is built do checks for resources.
+ */
+
+ /* Are too many requets already in progress? */
+ if (skdev->in_flight >= skdev->cur_max_queue_depth) {
+ VPRINTK(skdev, "qdepth %d, limit %d\n",
+ skdev->in_flight, skdev->cur_max_queue_depth);
+ break;
+ }
+
+ /* Is a skd_request_context available? */
+ skreq = skdev->skreq_free_list;
+ if (skreq == NULL) {
+ VPRINTK(skdev, "Out of req=%p\n", q);
+ break;
+ }
+ SKD_ASSERT(skreq->state == SKD_REQ_STATE_IDLE);
+ SKD_ASSERT((skreq->id & SKD_ID_INCR) == 0);
+
+ /* Now we check to see if we can get a fit msg */
+ if (skmsg == NULL) {
+ if (skdev->skmsg_free_list == NULL) {
+ VPRINTK(skdev, "Out of msg\n");
+ break;
+ }
+ }
+
+ skreq->flush_cmd = 0;
+ skreq->n_sg = 0;
+ skreq->sg_byte_count = 0;
+ skreq->discard_page = 0;
+
+ /*
+ * OK to now dequeue request from either bio or q.
+ *
+ * At this point we are comitted to either start or reject
+ * the native request. Note that skd_request_context is
+ * available but is still at the head of the free list.
+ */
+ if (!skd_bio) {
+ blk_start_request(req);
+ skreq->req = req;
+ skreq->fitmsg_id = 0;
+ } else {
+ if (unlikely(flush == SKD_FLUSH_DATA_SECOND)) {
+ skreq->bio = bio;
+ } else {
+ skreq->bio = bio_list_pop(&skdev->bio_queue);
+ SKD_ASSERT(skreq->bio == bio);
+ skreq->start_time = jiffies;
+ part_inc_in_flight(&skdev->disk->part0,
+ bio_data_dir(bio));
+ }
+
+ skreq->fitmsg_id = 0;
+ }
+
+ /* Either a FIT msg is in progress or we have to start one. */
+ if (skmsg == NULL) {
+ /* Are there any FIT msg buffers available? */
+ skmsg = skdev->skmsg_free_list;
+ if (skmsg == NULL) {
+ VPRINTK(skdev, "Out of msg skdev=%p\n", skdev);
+ break;
+ }
+ SKD_ASSERT(skmsg->state == SKD_MSG_STATE_IDLE);
+ SKD_ASSERT((skmsg->id & SKD_ID_INCR) == 0);
+
+ skdev->skmsg_free_list = skmsg->next;
+
+ skmsg->state = SKD_MSG_STATE_BUSY;
+ skmsg->id += SKD_ID_INCR;
+
+ /* Initialize the FIT msg header */
+ fmh = (struct fit_msg_hdr *)skmsg->msg_buf;
+ memset(fmh, 0, sizeof(*fmh));
+ fmh->protocol_id = FIT_PROTOCOL_ID_SOFIT;
+ skmsg->length = sizeof(*fmh);
+ }
+
+ skreq->fitmsg_id = skmsg->id;
+
+ /*
+ * Note that a FIT msg may have just been started
+ * but contains no SoFIT requests yet.
+ */
+
+ /*
+ * Transcode the request, checking as we go. The outcome of
+ * the transcoding is represented by the error variable.
+ */
+ cmd_ptr = &skmsg->msg_buf[skmsg->length];
+ memset(cmd_ptr, 0, 32);
+
+ be_lba = cpu_to_be32(lba);
+ be_count = cpu_to_be32(count);
+ be_dmaa = cpu_to_be64((u64)skreq->sksg_dma_address);
+ cmdctxt = skreq->id + SKD_ID_INCR;
+
+ scsi_req = cmd_ptr;
+ scsi_req->hdr.tag = cmdctxt;
+ scsi_req->hdr.sg_list_dma_address = be_dmaa;
+
+ if (data_dir == READ)
+ skreq->sg_data_dir = SKD_DATA_DIR_CARD_TO_HOST;
+ else
+ skreq->sg_data_dir = SKD_DATA_DIR_HOST_TO_CARD;
+
+ if (io_flags & REQ_DISCARD) {
+ page = alloc_page(GFP_ATOMIC | __GFP_ZERO);
+ if (!page) {
+ pr_err("request_fn:Page allocation failed.\n");
+ skd_end_request(skdev, skreq, -ENOMEM);
+ break;
+ }
+ skreq->discard_page = 1;
+ skd_prep_discard_cdb(scsi_req, skreq, page, lba, count);
+
+ } else if (flush == SKD_FLUSH_ZERO_SIZE_FIRST) {
+ skd_prep_zerosize_flush_cdb(scsi_req, skreq);
+ SKD_ASSERT(skreq->flush_cmd == 1);
+
+ } else {
+ skd_prep_rw_cdb(scsi_req, data_dir, lba, count);
+ }
+
+ if (fua)
+ scsi_req->cdb[1] |= SKD_FUA_NV;
+
+ if ((!skd_bio && !req->bio) ||
+ (skd_bio && flush == SKD_FLUSH_ZERO_SIZE_FIRST))
+ goto skip_sg;
+
+ error = skd_preop_sg_list(skdev, skreq);
+
+ if (error != 0) {
+ /*
+ * Complete the native request with error.
+ * Note that the request context is still at the
+ * head of the free list, and that the SoFIT request
+ * was encoded into the FIT msg buffer but the FIT
+ * msg length has not been updated. In short, the
+ * only resource that has been allocated but might
+ * not be used is that the FIT msg could be empty.
+ */
+ DPRINTK(skdev, "error Out\n");
+ skd_end_request(skdev, skreq, error);
+ continue;
+ }
+
+skip_sg:
+ scsi_req->hdr.sg_list_len_bytes =
+ cpu_to_be32(skreq->sg_byte_count);
+
+ /* Complete resource allocations. */
+ skdev->skreq_free_list = skreq->next;
+ skreq->state = SKD_REQ_STATE_BUSY;
+ skreq->id += SKD_ID_INCR;
+
+ skmsg->length += sizeof(struct skd_scsi_request);
+ fmh->num_protocol_cmds_coalesced++;
+
+ /*
+ * Update the active request counts.
+ * Capture the timeout timestamp.
+ */
+ skreq->timeout_stamp = skdev->timeout_stamp;
+ timo_slot = skreq->timeout_stamp & SKD_TIMEOUT_SLOT_MASK;
+ skdev->timeout_slot[timo_slot]++;
+ skdev->in_flight++;
+ VPRINTK(skdev, "req=0x%x busy=%d\n",
+ skreq->id, skdev->in_flight);
+
+ /*
+ * If the FIT msg buffer is full send it.
+ */
+ if (skmsg->length >= SKD_N_FITMSG_BYTES ||
+ fmh->num_protocol_cmds_coalesced >= skd_max_req_per_msg) {
+ skd_send_fitmsg(skdev, skmsg);
+ skmsg = NULL;
+ fmh = NULL;
+ }
+ }
+
+ /*
+ * Is a FIT msg in progress? If it is empty put the buffer back
+ * on the free list. If it is non-empty send what we got.
+ * This minimizes latency when there are fewer requests than
+ * what fits in a FIT msg.
+ */
+ if (skmsg != NULL) {
+ /* Bigger than just a FIT msg header? */
+ if (skmsg->length > sizeof(struct fit_msg_hdr)) {
+ VPRINTK(skdev, "sending msg=%p, len %d\n",
+ skmsg, skmsg->length);
+ skd_send_fitmsg(skdev, skmsg);
+ } else {
+ /*
+ * The FIT msg is empty. It means we got started
+ * on the msg, but the requests were rejected.
+ */
+ skmsg->state = SKD_MSG_STATE_IDLE;
+ skmsg->id += SKD_ID_INCR;
+ skmsg->next = skdev->skmsg_free_list;
+ skdev->skmsg_free_list = skmsg;
+ }
+ skmsg = NULL;
+ fmh = NULL;
+ }
+
+ /*
+ * If req is non-NULL it means there is something to do but
+ * we are out of a resource.
+ */
+ if (((!skd_bio) && req) ||
+ ((skd_bio) && bio_list_peek(&skdev->bio_queue)))
+ skd_stop_queue(skdev);
+}
+
+static void skd_end_request_blk(struct skd_device *skdev,
+ struct skd_request_context *skreq, int error)
+{
+ struct request *req = skreq->req;
+ unsigned int io_flags = req->cmd_flags;
+
+ if ((io_flags & REQ_DISCARD) &&
+ (skreq->discard_page == 1)) {
+ VPRINTK(skdev, "skd_end_request_blk, free the page!");
+ free_page((unsigned long)req->buffer);
+ req->buffer = NULL;
+ }
+
+ if (unlikely(error)) {
+ struct request *req = skreq->req;
+ char *cmd = (rq_data_dir(req) == READ) ? "read" : "write";
+ u32 lba = (u32)blk_rq_pos(req);
+ u32 count = blk_rq_sectors(req);
+
+ pr_err("(%s): Error cmd=%s sect=%u count=%u id=0x%x\n",
+ skd_name(skdev), cmd, lba, count, skreq->id);
+ } else
+ VPRINTK(skdev, "id=0x%x error=%d\n", skreq->id, error);
+
+ __blk_end_request_all(skreq->req, error);
+}
+
+static int skd_preop_sg_list_blk(struct skd_device *skdev,
+ struct skd_request_context *skreq)
+{
+ struct request *req = skreq->req;
+ int writing = skreq->sg_data_dir == SKD_DATA_DIR_HOST_TO_CARD;
+ int pci_dir = writing ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE;
+ struct scatterlist *sg = &skreq->sg[0];
+ int n_sg;
+ int i;
+
+ skreq->sg_byte_count = 0;
+
+ /* SKD_ASSERT(skreq->sg_data_dir == SKD_DATA_DIR_HOST_TO_CARD ||
+ skreq->sg_data_dir == SKD_DATA_DIR_CARD_TO_HOST); */
+
+ n_sg = blk_rq_map_sg(skdev->queue, req, sg);
+ if (n_sg <= 0)
+ return -EINVAL;
+
+ /*
+ * Map scatterlist to PCI bus addresses.
+ * Note PCI might change the number of entries.
+ */
+ n_sg = pci_map_sg(skdev->pdev, sg, n_sg, pci_dir);
+ if (n_sg <= 0)
+ return -EINVAL;
+
+ SKD_ASSERT(n_sg <= skdev->sgs_per_request);
+
+ skreq->n_sg = n_sg;
+
+ for (i = 0; i < n_sg; i++) {
+ struct fit_sg_descriptor *sgd = &skreq->sksg_list[i];
+ u32 cnt = sg_dma_len(&sg[i]);
+ uint64_t dma_addr = sg_dma_address(&sg[i]);
+
+ sgd->control = FIT_SGD_CONTROL_NOT_LAST;
+ sgd->byte_count = cnt;
+ skreq->sg_byte_count += cnt;
+ sgd->host_side_addr = dma_addr;
+ sgd->dev_side_addr = 0;
+ }
+
+ skreq->sksg_list[n_sg - 1].next_desc_ptr = 0LL;
+ skreq->sksg_list[n_sg - 1].control = FIT_SGD_CONTROL_LAST;
+
+ if (unlikely(skdev->dbg_level > 1)) {
+ VPRINTK(skdev, "skreq=%x sksg_list=%p sksg_dma=%llx\n",
+ skreq->id, skreq->sksg_list, skreq->sksg_dma_address);
+ for (i = 0; i < n_sg; i++) {
+ struct fit_sg_descriptor *sgd = &skreq->sksg_list[i];
+ VPRINTK(skdev, " sg[%d] count=%u ctrl=0x%x "
+ "addr=0x%llx next=0x%llx\n",
+ i, sgd->byte_count, sgd->control,
+ sgd->host_side_addr, sgd->next_desc_ptr);
+ }
+ }
+
+ return 0;
+}
+
+static void skd_postop_sg_list_blk(struct skd_device *skdev,
+ struct skd_request_context *skreq)
+{
+ int writing = skreq->sg_data_dir == SKD_DATA_DIR_HOST_TO_CARD;
+ int pci_dir = writing ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE;
+
+ /*
+ * restore the next ptr for next IO request so we
+ * don't have to set it every time.
+ */
+ skreq->sksg_list[skreq->n_sg - 1].next_desc_ptr =
+ skreq->sksg_dma_address +
+ ((skreq->n_sg) * sizeof(struct fit_sg_descriptor));
+ pci_unmap_sg(skdev->pdev, &skreq->sg[0], skreq->n_sg, pci_dir);
+}
+
+static void skd_end_request_bio(struct skd_device *skdev,
+ struct skd_request_context *skreq, int error)
+{
+ struct bio *bio = skreq->bio;
+ int rw = bio_data_dir(bio);
+ unsigned long io_flags = bio->bi_rw;
+
+ if ((io_flags & REQ_DISCARD) &&
+ (skreq->discard_page == 1)) {
+ VPRINTK(skdev, "biomode: skd_end_request: freeing DISCARD page.\n");
+ free_page((unsigned long)page_address(bio->bi_io_vec->bv_page));
+ }
+
+ if (unlikely(error)) {
+ u32 lba = (u32)skreq->bio->bi_sector;
+ u32 count = bio_sectors(skreq->bio);
+ char *cmd = (rw == WRITE) ? "write" : "read";
+ pr_err("(%s): Error cmd=%s sect=%u count=%u id=0x%x\n",
+ skd_name(skdev), cmd, lba, count, skreq->id);
+ }
+ {
+ int cpu = part_stat_lock();
+
+ if (likely(!error)) {
+ part_stat_inc(cpu, &skdev->disk->part0, ios[rw]);
+ part_stat_add(cpu, &skdev->disk->part0, sectors[rw],
+ bio_sectors(bio));
+ }
+ part_stat_add(cpu, &skdev->disk->part0, ticks[rw],
+ jiffies - skreq->start_time);
+ part_dec_in_flight(&skdev->disk->part0, rw);
+ part_stat_unlock();
+ }
+
+ VPRINTK(skdev, "id=0x%x error=%d\n", skreq->id, error);
+
+ bio_endio(skreq->bio, error);
+}
+
+static int skd_preop_sg_list_bio(struct skd_device *skdev,
+ struct skd_request_context *skreq)
+{
+ struct bio *bio = skreq->bio;
+ int writing = skreq->sg_data_dir == SKD_DATA_DIR_HOST_TO_CARD;
+ int pci_dir = writing ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE;
+ int n_sg;
+ int i;
+ struct bio_vec *vec;
+ struct fit_sg_descriptor *sgd;
+ u64 dma_addr;
+ u32 count;
+ int errs = 0;
+ unsigned int io_flags = 0;
+ io_flags |= bio->bi_rw;
+
+ skreq->sg_byte_count = 0;
+ n_sg = skreq->n_sg = skreq->bio->bi_vcnt;
+
+ if (n_sg <= 0)
+ return -EINVAL;
+
+ if (n_sg > skdev->sgs_per_request) {
+ pr_err("(%s): sg overflow n=%d\n",
+ skd_name(skdev), n_sg);
+ skreq->n_sg = 0;
+ return -EIO;
+ }
+
+ for (i = 0; i < skreq->n_sg; i++) {
+ vec = bio_iovec_idx(bio, i);
+ dma_addr = pci_map_page(skdev->pdev,
+ vec->bv_page,
+ vec->bv_offset, vec->bv_len, pci_dir);
+ count = vec->bv_len;
+
+ if (count == 0 || count > 64u * 1024u || (count & 3) != 0
+ || (dma_addr & 3) != 0) {
+ pr_err(
+ "(%s): Bad sg ix=%d count=%d addr=0x%llx\n",
+ skd_name(skdev), i, count, dma_addr);
+ errs++;
+ }
+
+ sgd = &skreq->sksg_list[i];
+
+ sgd->control = FIT_SGD_CONTROL_NOT_LAST;
+ sgd->byte_count = vec->bv_len;
+ skreq->sg_byte_count += vec->bv_len;
+ sgd->host_side_addr = dma_addr;
+ sgd->dev_side_addr = 0; /* not used */
+ }
+
+ skreq->sksg_list[n_sg - 1].next_desc_ptr = 0LL;
+ skreq->sksg_list[n_sg - 1].control = FIT_SGD_CONTROL_LAST;
+
+
+ if (!(io_flags & REQ_DISCARD)) {
+ count = bio_sectors(bio) << 9u;
+ if (count != skreq->sg_byte_count) {
+ pr_err("(%s): mismatch count sg=%d req=%d\n",
+ skd_name(skdev), skreq->sg_byte_count, count);
+ errs++;
+ }
+ }
+
+ if (unlikely(skdev->dbg_level > 1)) {
+ VPRINTK(skdev, "skreq=%x sksg_list=%p sksg_dma=%llx\n",
+ skreq->id, skreq->sksg_list, skreq->sksg_dma_address);
+ for (i = 0; i < n_sg; i++) {
+ struct fit_sg_descriptor *sgd = &skreq->sksg_list[i];
+ VPRINTK(skdev, " sg[%d] count=%u ctrl=0x%x "
+ "addr=0x%llx next=0x%llx\n",
+ i, sgd->byte_count, sgd->control,
+ sgd->host_side_addr, sgd->next_desc_ptr);
+ }
+ }
+
+ if (errs != 0) {
+ skd_postop_sg_list(skdev, skreq);
+ skreq->n_sg = 0;
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int skd_preop_sg_list(struct skd_device *skdev,
+ struct skd_request_context *skreq)
+{
+ if (!skd_bio)
+ return skd_preop_sg_list_blk(skdev, skreq);
+ else
+ return skd_preop_sg_list_bio(skdev, skreq);
+}
+
+static void skd_postop_sg_list_bio(struct skd_device *skdev,
+ struct skd_request_context *skreq)
+{
+ int writing = skreq->sg_data_dir == SKD_DATA_DIR_HOST_TO_CARD;
+ int pci_dir = writing ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE;
+ int i;
+ struct fit_sg_descriptor *sgd;
+
+ /*
+ * restore the next ptr for next IO request so we
+ * don't have to set it every time.
+ */
+ skreq->sksg_list[skreq->n_sg - 1].next_desc_ptr =
+ skreq->sksg_dma_address +
+ ((skreq->n_sg) * sizeof(struct fit_sg_descriptor));
+
+ for (i = 0; i < skreq->n_sg; i++) {
+ sgd = &skreq->sksg_list[i];
+ pci_unmap_page(skdev->pdev, sgd->host_side_addr,
+ sgd->byte_count, pci_dir);
+ }
+}
+
+static void skd_postop_sg_list(struct skd_device *skdev,
+ struct skd_request_context *skreq)
+{
+ if (!skd_bio)
+ skd_postop_sg_list_blk(skdev, skreq);
+ else
+ skd_postop_sg_list_bio(skdev, skreq);
+}
+
+static void skd_end_request(struct skd_device *skdev,
+ struct skd_request_context *skreq, int error)
+{
+ if (likely(!skd_bio))
+ skd_end_request_blk(skdev, skreq, error);
+ else
+ skd_end_request_bio(skdev, skreq, error);
+}
+
+static void skd_request_fn_not_online(struct request_queue *q)
+{
+ struct skd_device *skdev = q->queuedata;
+ int error;
+
+ SKD_ASSERT(skdev->state != SKD_DRVR_STATE_ONLINE);
+
+ skd_log_skdev(skdev, "req_not_online");
+ switch (skdev->state) {
+ case SKD_DRVR_STATE_PAUSING:
+ case SKD_DRVR_STATE_PAUSED:
+ case SKD_DRVR_STATE_STARTING:
+ case SKD_DRVR_STATE_RESTARTING:
+ case SKD_DRVR_STATE_WAIT_BOOT:
+ /* In case of starting, we haven't started the queue,
+ * so we can't get here... but requests are
+ * possibly hanging out waiting for us because we
+ * reported the dev/skd0 already. They'll wait
+ * forever if connect doesn't complete.
+ * What to do??? delay dev/skd0 ??
+ */
+ case SKD_DRVR_STATE_BUSY:
+ case SKD_DRVR_STATE_BUSY_IMMINENT:
+ case SKD_DRVR_STATE_BUSY_ERASE:
+ case SKD_DRVR_STATE_DRAINING_TIMEOUT:
+ return;
+
+ case SKD_DRVR_STATE_BUSY_SANITIZE:
+ case SKD_DRVR_STATE_STOPPING:
+ case SKD_DRVR_STATE_SYNCING:
+ case SKD_DRVR_STATE_FAULT:
+ case SKD_DRVR_STATE_DISAPPEARED:
+ default:
+ error = -EIO;
+ break;
+ }
+
+ /* If we get here, terminate all pending block requeusts
+ * with EIO and any scsi pass thru with appropriate sense
+ */
+
+ skd_fail_all_pending(skdev);
+}
+
+/*
+ *****************************************************************************
+ * TIMER
+ *****************************************************************************
+ */
+
+static void skd_timer_tick_not_online(struct skd_device *skdev);
+
+static void skd_timer_tick(ulong arg)
+{
+ struct skd_device *skdev = (struct skd_device *)arg;
+
+ u32 timo_slot;
+ u32 overdue_timestamp;
+ unsigned long reqflags;
+ u32 state;
+
+ if (skdev->state == SKD_DRVR_STATE_FAULT)
+ /* The driver has declared fault, and we want it to
+ * stay that way until driver is reloaded.
+ */
+ return;
+
+ spin_lock_irqsave(&skdev->lock, reqflags);
+
+ state = SKD_READL(skdev, FIT_STATUS);
+ state &= FIT_SR_DRIVE_STATE_MASK;
+ if (state != skdev->drive_state)
+ skd_isr_fwstate(skdev);
+
+ if (skdev->state != SKD_DRVR_STATE_ONLINE) {
+ skd_timer_tick_not_online(skdev);
+ goto timer_func_out;
+ }
+ skdev->timeout_stamp++;
+ timo_slot = skdev->timeout_stamp & SKD_TIMEOUT_SLOT_MASK;
+
+ /*
+ * All requests that happened during the previous use of
+ * this slot should be done by now. The previous use was
+ * over 7 seconds ago.
+ */
+ if (skdev->timeout_slot[timo_slot] == 0)
+ goto timer_func_out;
+
+ /* Something is overdue */
+ overdue_timestamp = skdev->timeout_stamp - SKD_N_TIMEOUT_SLOT;
+
+ DPRINTK(skdev, "found %d timeouts, draining busy=%d\n",
+ skdev->timeout_slot[timo_slot], skdev->in_flight);
+ pr_err("(%s): Overdue IOs (%d), busy %d\n",
+ skd_name(skdev), skdev->timeout_slot[timo_slot],
+ skdev->in_flight);
+
+ skdev->timer_countdown = SKD_DRAINING_TIMO;
+ skdev->state = SKD_DRVR_STATE_DRAINING_TIMEOUT;
+ skdev->timo_slot = timo_slot;
+ skd_stop_queue(skdev);
+
+timer_func_out:
+ mod_timer(&skdev->timer, (jiffies + HZ));
+
+ spin_unlock_irqrestore(&skdev->lock, reqflags);
+}
+
+static void skd_timer_tick_not_online(struct skd_device *skdev)
+{
+ switch (skdev->state) {
+ case SKD_DRVR_STATE_IDLE:
+ case SKD_DRVR_STATE_LOAD:
+ break;
+ case SKD_DRVR_STATE_BUSY_SANITIZE:
+ VPRINTK(skdev, "drive busy sanitize[%x], driver[%x]\n",
+ skdev->drive_state, skdev->state);
+ /* If we've been in sanitize for 3 seconds, we figure we're not
+ * going to get anymore completions, so recover requests now
+ */
+ if (skdev->timer_countdown > 0) {
+ skdev->timer_countdown--;
+ return;
+ }
+ skd_recover_requests(skdev, 0);
+ break;
+
+ case SKD_DRVR_STATE_BUSY:
+ case SKD_DRVR_STATE_BUSY_IMMINENT:
+ case SKD_DRVR_STATE_BUSY_ERASE:
+ VPRINTK(skdev, "busy[%x], countdown=%d\n",
+ skdev->state, skdev->timer_countdown);
+ if (skdev->timer_countdown > 0) {
+ skdev->timer_countdown--;
+ return;
+ }
+ DPRINTK(skdev, "busy[%x], timedout=%d, restarting device.",
+ skdev->state, skdev->timer_countdown);
+ skd_restart_device(skdev);
+ break;
+
+ case SKD_DRVR_STATE_WAIT_BOOT:
+ case SKD_DRVR_STATE_STARTING:
+ if (skdev->timer_countdown > 0) {
+ skdev->timer_countdown--;
+ return;
+ }
+ /* For now, we fault the drive. Could attempt resets to
+ * revcover at some point. */
+ skdev->state = SKD_DRVR_STATE_FAULT;
+
+ pr_err("(%s): DriveFault Connect Timeout (%x)\n",
+ skd_name(skdev), skdev->drive_state);
+
+ /*start the queue so we can respond with error to requests */
+ /* wakeup anyone waiting for startup complete */
+ skd_start_queue(skdev);
+ skdev->gendisk_on = -1;
+ wake_up_interruptible(&skdev->waitq);
+ break;
+
+ case SKD_DRVR_STATE_ONLINE:
+ /* shouldn't get here. */
+ break;
+
+ case SKD_DRVR_STATE_PAUSING:
+ case SKD_DRVR_STATE_PAUSED:
+ break;
+
+ case SKD_DRVR_STATE_DRAINING_TIMEOUT:
+ DPRINTK(skdev,
+ "draining busy [%d] tick[%d] qdb[%d] tmls[%d]\n",
+ skdev->timo_slot,
+ skdev->timer_countdown,
+ skdev->in_flight,
+ skdev->timeout_slot[skdev->timo_slot]);
+ /* if the slot has cleared we can let the I/O continue */
+ if (skdev->timeout_slot[skdev->timo_slot] == 0) {
+ DPRINTK(skdev, "Slot drained, starting queue.\n");
+ skdev->state = SKD_DRVR_STATE_ONLINE;
+ skd_start_queue(skdev);
+ return;
+ }
+ if (skdev->timer_countdown > 0) {
+ skdev->timer_countdown--;
+ return;
+ }
+ skd_restart_device(skdev);
+ break;
+
+ case SKD_DRVR_STATE_RESTARTING:
+ if (skdev->timer_countdown > 0) {
+ skdev->timer_countdown--;
+ return;
+ }
+ /* For now, we fault the drive. Could attempt resets to
+ * revcover at some point. */
+ skdev->state = SKD_DRVR_STATE_FAULT;
+ pr_err("(%s): DriveFault Reconnect Timeout (%x)\n",
+ skd_name(skdev), skdev->drive_state);
+
+ /*
+ * Recovering does two things:
+ * 1. completes IO with error
+ * 2. reclaims dma resources
+ * When is it safe to recover requests?
+ * - if the drive state is faulted
+ * - if the state is still soft reset after out timeout
+ * - if the drive registers are dead (state = FF)
+ * If it is "unsafe", we still need to recover, so we will
+ * disable pci bus mastering and disable our interrupts.
+ */
+
+ if ((skdev->drive_state == FIT_SR_DRIVE_SOFT_RESET) ||
+ (skdev->drive_state == FIT_SR_DRIVE_FAULT) ||
+ (skdev->drive_state == FIT_SR_DRIVE_STATE_MASK))
+ /* It never came out of soft reset. Try to
+ * recover the requests and then let them
+ * fail. This is to mitigate hung processes. */
+ skd_recover_requests(skdev, 0);
+ else {
+ pr_err("(%s): Disable BusMaster (%x)\n",
+ skd_name(skdev), skdev->drive_state);
+ pci_disable_device(skdev->pdev);
+ skd_disable_interrupts(skdev);
+ skd_recover_requests(skdev, 0);
+ }
+
+ /*start the queue so we can respond with error to requests */
+ /* wakeup anyone waiting for startup complete */
+ skd_start_queue(skdev);
+ skdev->gendisk_on = -1;
+ wake_up_interruptible(&skdev->waitq);
+ break;
+
+ case SKD_DRVR_STATE_RESUMING:
+ case SKD_DRVR_STATE_STOPPING:
+ case SKD_DRVR_STATE_SYNCING:
+ case SKD_DRVR_STATE_FAULT:
+ case SKD_DRVR_STATE_DISAPPEARED:
+ default:
+ break;
+ }
+}
+
+static int skd_start_timer(struct skd_device *skdev)
+{
+ int rc;
+
+ init_timer(&skdev->timer);
+ setup_timer(&skdev->timer, skd_timer_tick, (ulong)skdev);
+
+ rc = mod_timer(&skdev->timer, (jiffies + HZ));
+ if (rc)
+ pr_err("%s: failed to start timer %d\n",
+ __func__, rc);
+ return rc;
+}
+
+static void skd_kill_timer(struct skd_device *skdev)
+{
+ del_timer_sync(&skdev->timer);
+}
+
+/*
+ *****************************************************************************
+ * IOCTL
+ *****************************************************************************
+ */
+static int skd_ioctl_sg_io(struct skd_device *skdev,
+ fmode_t mode, void __user *argp);
+static int skd_sg_io_get_and_check_args(struct skd_device *skdev,
+ struct skd_sg_io *sksgio);
+static int skd_sg_io_obtain_skspcl(struct skd_device *skdev,
+ struct skd_sg_io *sksgio);
+static int skd_sg_io_prep_buffering(struct skd_device *skdev,
+ struct skd_sg_io *sksgio);
+static int skd_sg_io_copy_buffer(struct skd_device *skdev,
+ struct skd_sg_io *sksgio, int dxfer_dir);
+static int skd_sg_io_send_fitmsg(struct skd_device *skdev,
+ struct skd_sg_io *sksgio);
+static int skd_sg_io_await(struct skd_device *skdev, struct skd_sg_io *sksgio);
+static int skd_sg_io_release_skspcl(struct skd_device *skdev,
+ struct skd_sg_io *sksgio);
+static int skd_sg_io_put_status(struct skd_device *skdev,
+ struct skd_sg_io *sksgio);
+
+static void skd_complete_special(struct skd_device *skdev,
+ volatile struct fit_completion_entry_v1
+ *skcomp,
+ volatile struct fit_comp_error_info *skerr,
+ struct skd_special_context *skspcl);
+
+static int skd_bdev_ioctl(struct block_device *bdev, fmode_t mode,
+ uint cmd_in, ulong arg)
+{
+ int rc = 0;
+ struct gendisk *disk = bdev->bd_disk;
+ struct skd_device *skdev = disk->private_data;
+ void __user *p = (void *)arg;
+
+ DPRINTK(skdev, "%s: CMD[%s] ioctl mode 0x%x, cmd 0x%x arg %0lx\n",
+ disk->disk_name, current->comm, mode, cmd_in, arg);
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ switch (cmd_in) {
+ case SG_SET_TIMEOUT:
+ case SG_GET_TIMEOUT:
+ case SG_GET_VERSION_NUM:
+ rc = scsi_cmd_ioctl(disk->queue, disk, mode, cmd_in, p);
+ break;
+ case SG_IO:
+ rc = skd_ioctl_sg_io(skdev, mode, p);
+ break;
+
+ default:
+ rc = -ENOTTY;
+ break;
+ }
+
+ DPRINTK(skdev, "%s: completion rc %d\n", disk->disk_name, rc);
+ return rc;
+}
+
+static int skd_ioctl_sg_io(struct skd_device *skdev, fmode_t mode,
+ void __user *argp)
+{
+ int rc;
+ struct skd_sg_io sksgio;
+
+ memset(&sksgio, 0, sizeof(sksgio));
+ sksgio.mode = mode;
+ sksgio.argp = argp;
+ sksgio.iov = &sksgio.no_iov_iov;
+
+ switch (skdev->state) {
+ case SKD_DRVR_STATE_ONLINE:
+ case SKD_DRVR_STATE_BUSY_IMMINENT:
+ break;
+
+ default:
+ DPRINTK(skdev, "drive not online\n");
+ rc = -ENXIO;
+ goto out;
+ }
+
+ if ((rc = skd_sg_io_get_and_check_args(skdev, &sksgio)) ||
+ (rc = skd_sg_io_obtain_skspcl(skdev, &sksgio)) ||
+ (rc = skd_sg_io_prep_buffering(skdev, &sksgio)) ||
+ (rc = skd_sg_io_copy_buffer(skdev, &sksgio, SG_DXFER_TO_DEV)))
+ goto out;
+
+ if ((rc = skd_sg_io_send_fitmsg(skdev, &sksgio)) ||
+ (rc = skd_sg_io_await(skdev, &sksgio)))
+ goto out;
+
+ if ((rc = skd_sg_io_copy_buffer(skdev, &sksgio, SG_DXFER_FROM_DEV)) ||
+ (rc = skd_sg_io_put_status(skdev, &sksgio)))
+ goto out;
+
+ rc = 0;
+
+out:
+ skd_sg_io_release_skspcl(skdev, &sksgio);
+
+ if (sksgio.iov != NULL && sksgio.iov != &sksgio.no_iov_iov)
+ kfree(sksgio.iov);
+ return rc;
+}
+
+static int skd_sg_io_get_and_check_args(struct skd_device *skdev,
+ struct skd_sg_io *sksgio)
+{
+ struct sg_io_hdr *sgp = &sksgio->sg;
+ int i, acc;
+
+ if (!access_ok(VERIFY_WRITE, sksgio->argp, sizeof(sg_io_hdr_t))) {
+ DPRINTK(skdev, "access sg failed %p\n", sksgio->argp);
+ return -EFAULT;
+ }
+
+ if (__copy_from_user(sgp, sksgio->argp, sizeof(sg_io_hdr_t))) {
+ DPRINTK(skdev, "copy_from_user sg failed %p\n", sksgio->argp);
+ return -EFAULT;
+ }
+
+ if (sgp->interface_id != SG_INTERFACE_ID_ORIG) {
+ DPRINTK(skdev, "interface_id invalid 0x%x\n",
+ sgp->interface_id);
+ return -EINVAL;
+ }
+
+ if (sgp->cmd_len > sizeof(sksgio->cdb)) {
+ DPRINTK(skdev, "cmd_len invalid %d\n", sgp->cmd_len);
+ return -EINVAL;
+ }
+
+ if (sgp->iovec_count > 256) {
+ DPRINTK(skdev, "iovec_count invalid %d\n", sgp->iovec_count);
+ return -EINVAL;
+ }
+
+ if (sgp->dxfer_len > (PAGE_SIZE * SKD_N_SG_PER_SPECIAL)) {
+ DPRINTK(skdev, "dxfer_len invalid %d\n", sgp->dxfer_len);
+ return -EINVAL;
+ }
+
+ switch (sgp->dxfer_direction) {
+ case SG_DXFER_NONE:
+ acc = -1;
+ break;
+
+ case SG_DXFER_TO_DEV:
+ acc = VERIFY_READ;
+ break;
+
+ case SG_DXFER_FROM_DEV:
+ case SG_DXFER_TO_FROM_DEV:
+ acc = VERIFY_WRITE;
+ break;
+
+ default:
+ DPRINTK(skdev, "dxfer_dir invalid %d\n", sgp->dxfer_direction);
+ return -EINVAL;
+ }
+
+ if (copy_from_user(sksgio->cdb, sgp->cmdp, sgp->cmd_len)) {
+ DPRINTK(skdev, "copy_from_user cmdp failed %p\n", sgp->cmdp);
+ return -EFAULT;
+ }
+
+ if (sgp->mx_sb_len != 0) {
+ if (!access_ok(VERIFY_WRITE, sgp->sbp, sgp->mx_sb_len)) {
+ DPRINTK(skdev, "access sbp failed %p\n", sgp->sbp);
+ return -EFAULT;
+ }
+ }
+
+ if (sgp->iovec_count == 0) {
+ sksgio->iov[0].iov_base = sgp->dxferp;
+ sksgio->iov[0].iov_len = sgp->dxfer_len;
+ sksgio->iovcnt = 1;
+ sksgio->dxfer_len = sgp->dxfer_len;
+ } else {
+ struct sg_iovec *iov;
+ uint nbytes = sizeof(*iov) * sgp->iovec_count;
+ size_t iov_data_len;
+
+ iov = kmalloc(nbytes, GFP_KERNEL);
+ if (iov == NULL) {
+ DPRINTK(skdev, "alloc iovec failed %d\n",
+ sgp->iovec_count);
+ return -ENOMEM;
+ }
+ sksgio->iov = iov;
+ sksgio->iovcnt = sgp->iovec_count;
+
+ if (copy_from_user(iov, sgp->dxferp, nbytes)) {
+ DPRINTK(skdev, "copy_from_user iovec failed %p\n",
+ sgp->dxferp);
+ return -EFAULT;
+ }
+
+ /*
+ * Sum up the vecs, making sure they don't overflow
+ */
+ iov_data_len = 0;
+ for (i = 0; i < sgp->iovec_count; i++) {
+ if (iov_data_len + iov[i].iov_len < iov_data_len)
+ return -EINVAL;
+ iov_data_len += iov[i].iov_len;
+ }
+
+ /* SG_IO howto says that the shorter of the two wins */
+ if (sgp->dxfer_len < iov_data_len) {
+ sksgio->iovcnt = iov_shorten((struct iovec *)iov,
+ sgp->iovec_count,
+ sgp->dxfer_len);
+ sksgio->dxfer_len = sgp->dxfer_len;
+ } else
+ sksgio->dxfer_len = iov_data_len;
+ }
+
+ if (sgp->dxfer_direction != SG_DXFER_NONE) {
+ struct sg_iovec *iov = sksgio->iov;
+ for (i = 0; i < sksgio->iovcnt; i++, iov++) {
+ if (!access_ok(acc, iov->iov_base, iov->iov_len)) {
+ DPRINTK(skdev, "access data failed %p/%d\n",
+ iov->iov_base, (int)iov->iov_len);
+ return -EFAULT;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int skd_sg_io_obtain_skspcl(struct skd_device *skdev,
+ struct skd_sg_io *sksgio)
+{
+ struct skd_special_context *skspcl = NULL;
+ int rc;
+
+ for (;; ) {
+ ulong flags;
+
+ spin_lock_irqsave(&skdev->lock, flags);
+ skspcl = skdev->skspcl_free_list;
+ if (skspcl != NULL) {
+ skdev->skspcl_free_list =
+ (struct skd_special_context *)skspcl->req.next;
+ skspcl->req.id += SKD_ID_INCR;
+ skspcl->req.state = SKD_REQ_STATE_SETUP;
+ skspcl->orphaned = 0;
+ skspcl->req.n_sg = 0;
+ }
+ spin_unlock_irqrestore(&skdev->lock, flags);
+
+ if (skspcl != NULL) {
+ rc = 0;
+ break;
+ }
+
+ DPRINTK(skdev, "blocking\n");
+
+ rc = wait_event_interruptible_timeout(
+ skdev->waitq,
+ (skdev->skspcl_free_list != NULL),
+ msecs_to_jiffies(sksgio->sg.timeout));
+
+ DPRINTK(skdev, "unblocking, rc=%d\n", rc);
+
+ if (rc <= 0) {
+ if (rc == 0)
+ rc = -ETIMEDOUT;
+ else
+ rc = -EINTR;
+ break;
+ }
+ /*
+ * If we get here rc > 0 meaning the timeout to
+ * wait_event_interruptible_timeout() had time left, hence the
+ * sought event -- non-empty free list -- happened.
+ * Retry the allocation.
+ */
+ }
+ sksgio->skspcl = skspcl;
+
+ return rc;
+}
+
+static int skd_skreq_prep_buffering(struct skd_device *skdev,
+ struct skd_request_context *skreq,
+ u32 dxfer_len)
+{
+ u32 resid = dxfer_len;
+
+ /*
+ * The DMA engine must have aligned addresses and byte counts.
+ */
+ resid += (-resid) & 3;
+ skreq->sg_byte_count = resid;
+
+ skreq->n_sg = 0;
+
+ while (resid > 0) {
+ u32 nbytes = PAGE_SIZE;
+ u32 ix = skreq->n_sg;
+ struct scatterlist *sg = &skreq->sg[ix];
+ struct fit_sg_descriptor *sksg = &skreq->sksg_list[ix];
+ struct page *page;
+
+ if (nbytes > resid)
+ nbytes = resid;
+
+ page = alloc_page(GFP_KERNEL);
+ if (page == NULL)
+ return -ENOMEM;
+
+ sg_set_page(sg, page, nbytes, 0);
+
+ /* TODO: This should be going through a pci_???()
+ * routine to do proper mapping. */
+ sksg->control = FIT_SGD_CONTROL_NOT_LAST;
+ sksg->byte_count = nbytes;
+
+ sksg->host_side_addr = sg_phys(sg);
+
+ sksg->dev_side_addr = 0;
+ sksg->next_desc_ptr = skreq->sksg_dma_address +
+ (ix + 1) * sizeof(*sksg);
+
+ skreq->n_sg++;
+ resid -= nbytes;
+ }
+
+ if (skreq->n_sg > 0) {
+ u32 ix = skreq->n_sg - 1;
+ struct fit_sg_descriptor *sksg = &skreq->sksg_list[ix];
+
+ sksg->control = FIT_SGD_CONTROL_LAST;
+ sksg->next_desc_ptr = 0;
+ }
+
+ if (unlikely(skdev->dbg_level > 1)) {
+ u32 i;
+
+ VPRINTK(skdev, "skreq=%x sksg_list=%p sksg_dma=%llx\n",
+ skreq->id, skreq->sksg_list, skreq->sksg_dma_address);
+ for (i = 0; i < skreq->n_sg; i++) {
+ struct fit_sg_descriptor *sgd = &skreq->sksg_list[i];
+
+ VPRINTK(skdev, " sg[%d] count=%u ctrl=0x%x "
+ "addr=0x%llx next=0x%llx\n",
+ i, sgd->byte_count, sgd->control,
+ sgd->host_side_addr, sgd->next_desc_ptr);
+ }
+ }
+
+ return 0;
+}
+
+static int skd_sg_io_prep_buffering(struct skd_device *skdev,
+ struct skd_sg_io *sksgio)
+{
+ struct skd_special_context *skspcl = sksgio->skspcl;
+ struct skd_request_context *skreq = &skspcl->req;
+ u32 dxfer_len = sksgio->dxfer_len;
+ int rc;
+
+ rc = skd_skreq_prep_buffering(skdev, skreq, dxfer_len);
+ /*
+ * Eventually, errors or not, skd_release_special() is called
+ * to recover allocations including partial allocations.
+ */
+ return rc;
+}
+
+static int skd_sg_io_copy_buffer(struct skd_device *skdev,
+ struct skd_sg_io *sksgio, int dxfer_dir)
+{
+ struct skd_special_context *skspcl = sksgio->skspcl;
+ u32 iov_ix = 0;
+ struct sg_iovec curiov;
+ u32 sksg_ix = 0;
+ u8 *bufp = NULL;
+ u32 buf_len = 0;
+ u32 resid = sksgio->dxfer_len;
+ int rc;
+
+ curiov.iov_len = 0;
+ curiov.iov_base = NULL;
+
+ if (dxfer_dir != sksgio->sg.dxfer_direction) {
+ if (dxfer_dir != SG_DXFER_TO_DEV ||
+ sksgio->sg.dxfer_direction != SG_DXFER_TO_FROM_DEV)
+ return 0;
+ }
+
+ while (resid > 0) {
+ u32 nbytes = PAGE_SIZE;
+
+ if (curiov.iov_len == 0) {
+ curiov = sksgio->iov[iov_ix++];
+ continue;
+ }
+
+ if (buf_len == 0) {
+ struct page *page;
+ page = sg_page(&skspcl->req.sg[sksg_ix++]);
+ bufp = page_address(page);
+ buf_len = PAGE_SIZE;
+ }
+
+ nbytes = min_t(u32, nbytes, resid);
+ nbytes = min_t(u32, nbytes, curiov.iov_len);
+ nbytes = min_t(u32, nbytes, buf_len);
+
+ if (dxfer_dir == SG_DXFER_TO_DEV)
+ rc = __copy_from_user(bufp, curiov.iov_base, nbytes);
+ else
+ rc = __copy_to_user(curiov.iov_base, bufp, nbytes);
+
+ if (rc)
+ return -EFAULT;
+
+ resid -= nbytes;
+ curiov.iov_len -= nbytes;
+ curiov.iov_base += nbytes;
+ buf_len -= nbytes;
+ }
+
+ return 0;
+}
+
+static int skd_sg_io_send_fitmsg(struct skd_device *skdev,
+ struct skd_sg_io *sksgio)
+{
+ struct skd_special_context *skspcl = sksgio->skspcl;
+ struct fit_msg_hdr *fmh = (struct fit_msg_hdr *)skspcl->msg_buf;
+ struct skd_scsi_request *scsi_req = (struct skd_scsi_request *)&fmh[1];
+
+ memset(skspcl->msg_buf, 0, SKD_N_SPECIAL_FITMSG_BYTES);
+
+ /* Initialize the FIT msg header */
+ fmh->protocol_id = FIT_PROTOCOL_ID_SOFIT;
+ fmh->num_protocol_cmds_coalesced = 1;
+
+ /* Initialize the SCSI request */
+ if (sksgio->sg.dxfer_direction != SG_DXFER_NONE)
+ scsi_req->hdr.sg_list_dma_address =
+ cpu_to_be64(skspcl->req.sksg_dma_address);
+ scsi_req->hdr.tag = skspcl->req.id;
+ scsi_req->hdr.sg_list_len_bytes =
+ cpu_to_be32(skspcl->req.sg_byte_count);
+ memcpy(scsi_req->cdb, sksgio->cdb, sizeof(scsi_req->cdb));
+
+ skspcl->req.state = SKD_REQ_STATE_BUSY;
+ skd_send_special_fitmsg(skdev, skspcl);
+
+ return 0;
+}
+
+static int skd_sg_io_await(struct skd_device *skdev, struct skd_sg_io *sksgio)
+{
+ unsigned long flags;
+ int rc;
+
+ rc = wait_event_interruptible_timeout(skdev->waitq,
+ (sksgio->skspcl->req.state !=
+ SKD_REQ_STATE_BUSY),
+ msecs_to_jiffies(sksgio->sg.
+ timeout));
+
+ spin_lock_irqsave(&skdev->lock, flags);
+
+ if (sksgio->skspcl->req.state == SKD_REQ_STATE_ABORTED) {
+ DPRINTK(skdev, "skspcl %p aborted\n", sksgio->skspcl);
+
+ /* Build check cond, sense and let command finish. */
+ /* For a timeout, we must fabricate completion and sense
+ * data to complete the command */
+ sksgio->skspcl->req.completion.status =
+ SAM_STAT_CHECK_CONDITION;
+
+ memset(&sksgio->skspcl->req.err_info, 0,
+ sizeof(sksgio->skspcl->req.err_info));
+ sksgio->skspcl->req.err_info.type = 0x70;
+ sksgio->skspcl->req.err_info.key = ABORTED_COMMAND;
+ sksgio->skspcl->req.err_info.code = 0x44;
+ sksgio->skspcl->req.err_info.qual = 0;
+ rc = 0;
+ } else if (sksgio->skspcl->req.state != SKD_REQ_STATE_BUSY)
+ /* No longer on the adapter. We finish. */
+ rc = 0;
+ else {
+ /* Something's gone wrong. Still busy. Timeout or
+ * user interrupted (control-C). Mark as an orphan
+ * so it will be disposed when completed. */
+ sksgio->skspcl->orphaned = 1;
+ sksgio->skspcl = NULL;
+ if (rc == 0) {
+ DPRINTK(skdev, "timed out %p (%u ms)\n", sksgio,
+ sksgio->sg.timeout);
+ rc = -ETIMEDOUT;
+ } else {
+ DPRINTK(skdev, "cntlc %p\n", sksgio);
+ rc = -EINTR;
+ }
+ }
+
+ spin_unlock_irqrestore(&skdev->lock, flags);
+
+ return rc;
+}
+
+static int skd_sg_io_put_status(struct skd_device *skdev,
+ struct skd_sg_io *sksgio)
+{
+ struct sg_io_hdr *sgp = &sksgio->sg;
+ struct skd_special_context *skspcl = sksgio->skspcl;
+ int resid = 0;
+
+ u32 nb = be32_to_cpu(skspcl->req.completion.num_returned_bytes);
+
+ sgp->status = skspcl->req.completion.status;
+ resid = sksgio->dxfer_len - nb;
+
+ sgp->masked_status = sgp->status & STATUS_MASK;
+ sgp->msg_status = 0;
+ sgp->host_status = 0;
+ sgp->driver_status = 0;
+ sgp->resid = resid;
+ if (sgp->masked_status || sgp->host_status || sgp->driver_status)
+ sgp->info |= SG_INFO_CHECK;
+
+ DPRINTK(skdev, "status %x masked %x resid 0x%x\n", sgp->status,
+ sgp->masked_status, sgp->resid);
+
+ if (sgp->masked_status == SAM_STAT_CHECK_CONDITION) {
+ if (sgp->mx_sb_len > 0) {
+ struct fit_comp_error_info *ei = &skspcl->req.err_info;
+ u32 nbytes = sizeof(*ei);
+
+ nbytes = min_t(u32, nbytes, sgp->mx_sb_len);
+
+ sgp->sb_len_wr = nbytes;
+
+ if (__copy_to_user(sgp->sbp, ei, nbytes)) {
+ DPRINTK(skdev, "copy_to_user sense failed %p\n",
+ sgp->sbp);
+ return -EFAULT;
+ }
+ }
+ }
+
+ if (__copy_to_user(sksgio->argp, sgp, sizeof(sg_io_hdr_t))) {
+ DPRINTK(skdev, "copy_to_user sg failed %p\n", sksgio->argp);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int skd_sg_io_release_skspcl(struct skd_device *skdev,
+ struct skd_sg_io *sksgio)
+{
+ struct skd_special_context *skspcl = sksgio->skspcl;
+
+ if (skspcl != NULL) {
+ ulong flags;
+
+ sksgio->skspcl = NULL;
+
+ spin_lock_irqsave(&skdev->lock, flags);
+ skd_release_special(skdev, skspcl);
+ spin_unlock_irqrestore(&skdev->lock, flags);
+ }
+
+ return 0;
+}
+
+/*
+ *****************************************************************************
+ * INTERNAL REQUESTS -- generated by driver itself
+ *****************************************************************************
+ */
+
+static int skd_format_internal_skspcl(struct skd_device *skdev)
+{
+ struct skd_special_context *skspcl = &skdev->internal_skspcl;
+ struct fit_sg_descriptor *sgd = &skspcl->req.sksg_list[0];
+ struct fit_msg_hdr *fmh;
+ uint64_t dma_address;
+ struct skd_scsi_request *scsi;
+
+ fmh = (struct fit_msg_hdr *)&skspcl->msg_buf[0];
+ fmh->protocol_id = FIT_PROTOCOL_ID_SOFIT;
+ fmh->num_protocol_cmds_coalesced = 1;
+
+ scsi = (struct skd_scsi_request *)&skspcl->msg_buf[64];
+ memset(scsi, 0, sizeof(*scsi));
+ dma_address = skspcl->req.sksg_dma_address;
+ scsi->hdr.sg_list_dma_address = cpu_to_be64(dma_address);
+ sgd->control = FIT_SGD_CONTROL_LAST;
+ sgd->byte_count = 0;
+ sgd->host_side_addr = skspcl->db_dma_address;
+ sgd->dev_side_addr = 0;
+ sgd->next_desc_ptr = 0LL;
+
+ return 1;
+}
+
+#define WR_BUF_SIZE SKD_N_INTERNAL_BYTES
+
+static void skd_send_internal_skspcl(struct skd_device *skdev,
+ struct skd_special_context *skspcl,
+ u8 opcode)
+{
+ struct fit_sg_descriptor *sgd = &skspcl->req.sksg_list[0];
+ struct skd_scsi_request *scsi;
+ unsigned char *buf = skspcl->data_buf;
+ int i;
+
+ if (skspcl->req.state != SKD_REQ_STATE_IDLE)
+ /*
+ * A refresh is already in progress.
+ * Just wait for it to finish.
+ */
+ return;
+
+ SKD_ASSERT((skspcl->req.id & SKD_ID_INCR) == 0);
+ skspcl->req.state = SKD_REQ_STATE_BUSY;
+ skspcl->req.id += SKD_ID_INCR;
+
+ scsi = (struct skd_scsi_request *)&skspcl->msg_buf[64];
+ scsi->hdr.tag = skspcl->req.id;
+
+ memset(scsi->cdb, 0, sizeof(scsi->cdb));
+
+ switch (opcode) {
+ case TEST_UNIT_READY:
+ scsi->cdb[0] = TEST_UNIT_READY;
+ sgd->byte_count = 0;
+ scsi->hdr.sg_list_len_bytes = 0;
+ break;
+
+ case READ_CAPACITY:
+ scsi->cdb[0] = READ_CAPACITY;
+ sgd->byte_count = SKD_N_READ_CAP_BYTES;
+ scsi->hdr.sg_list_len_bytes = cpu_to_be32(sgd->byte_count);
+ break;
+
+ case INQUIRY:
+ scsi->cdb[0] = INQUIRY;
+ scsi->cdb[1] = 0x01; /* evpd */
+ scsi->cdb[2] = 0x80; /* serial number page */
+ scsi->cdb[4] = 0x10;
+ sgd->byte_count = 16;
+ scsi->hdr.sg_list_len_bytes = cpu_to_be32(sgd->byte_count);
+ break;
+
+ case SYNCHRONIZE_CACHE:
+ scsi->cdb[0] = SYNCHRONIZE_CACHE;
+ sgd->byte_count = 0;
+ scsi->hdr.sg_list_len_bytes = 0;
+ break;
+
+ case WRITE_BUFFER:
+ scsi->cdb[0] = WRITE_BUFFER;
+ scsi->cdb[1] = 0x02;
+ scsi->cdb[7] = (WR_BUF_SIZE & 0xFF00) >> 8;
+ scsi->cdb[8] = WR_BUF_SIZE & 0xFF;
+ sgd->byte_count = WR_BUF_SIZE;
+ scsi->hdr.sg_list_len_bytes = cpu_to_be32(sgd->byte_count);
+ /* fill incrementing byte pattern */
+ for (i = 0; i < sgd->byte_count; i++)
+ buf[i] = i & 0xFF;
+ break;
+
+ case READ_BUFFER:
+ scsi->cdb[0] = READ_BUFFER;
+ scsi->cdb[1] = 0x02;
+ scsi->cdb[7] = (WR_BUF_SIZE & 0xFF00) >> 8;
+ scsi->cdb[8] = WR_BUF_SIZE & 0xFF;
+ sgd->byte_count = WR_BUF_SIZE;
+ scsi->hdr.sg_list_len_bytes = cpu_to_be32(sgd->byte_count);
+ memset(skspcl->data_buf, 0, sgd->byte_count);
+ break;
+
+ default:
+ SKD_ASSERT("Don't know what to send");
+ return;
+
+ }
+ skd_send_special_fitmsg(skdev, skspcl);
+}
+
+static void skd_refresh_device_data(struct skd_device *skdev)
+{
+ struct skd_special_context *skspcl = &skdev->internal_skspcl;
+
+ skd_send_internal_skspcl(skdev, skspcl, TEST_UNIT_READY);
+}
+
+static int skd_chk_read_buf(struct skd_device *skdev,
+ struct skd_special_context *skspcl)
+{
+ unsigned char *buf = skspcl->data_buf;
+ int i;
+
+ /* check for incrementing byte pattern */
+ for (i = 0; i < WR_BUF_SIZE; i++)
+ if (buf[i] != (i & 0xFF))
+ return 1;
+
+ return 0;
+}
+
+static void skd_log_check_status(struct skd_device *skdev, u8 status, u8 key,
+ u8 code, u8 qual, u8 fruc)
+{
+ /* If the check condition is of special interest, log a message */
+ if ((status == SAM_STAT_CHECK_CONDITION) && (key == 0x02)
+ && (code == 0x04) && (qual == 0x06)) {
+ pr_err("(%s): *** LOST_WRITE_DATA ERROR *** key/asc/"
+ "ascq/fruc %02x/%02x/%02x/%02x\n",
+ skd_name(skdev), key, code, qual, fruc);
+ }
+}
+
+static void skd_complete_internal(struct skd_device *skdev,
+ volatile struct fit_completion_entry_v1
+ *skcomp,
+ volatile struct fit_comp_error_info *skerr,
+ struct skd_special_context *skspcl)
+{
+ u8 *buf = skspcl->data_buf;
+ u8 status;
+ int i;
+ struct skd_scsi_request *scsi =
+ (struct skd_scsi_request *)&skspcl->msg_buf[64];
+
+ SKD_ASSERT(skspcl == &skdev->internal_skspcl);
+
+ DPRINTK(skdev, "complete internal %x\n", scsi->cdb[0]);
+
+ skspcl->req.completion = *skcomp;
+ skspcl->req.state = SKD_REQ_STATE_IDLE;
+ skspcl->req.id += SKD_ID_INCR;
+
+ status = skspcl->req.completion.status;
+
+ skd_log_check_status(skdev, status, skerr->key, skerr->code,
+ skerr->qual, skerr->fruc);
+
+ switch (scsi->cdb[0]) {
+ case TEST_UNIT_READY:
+ if (status == SAM_STAT_GOOD)
+ skd_send_internal_skspcl(skdev, skspcl, WRITE_BUFFER);
+ else if ((status == SAM_STAT_CHECK_CONDITION) &&
+ (skerr->key == MEDIUM_ERROR))
+ skd_send_internal_skspcl(skdev, skspcl, WRITE_BUFFER);
+ else {
+ if (skdev->state == SKD_DRVR_STATE_STOPPING) {
+ VPRINTK(skdev, "TUR failed, don't send anymore"
+ "state 0x%x\n", skdev->state);
+ return;
+ }
+ DPRINTK(skdev, "**** TUR failed, retry skerr\n");
+ skd_send_internal_skspcl(skdev, skspcl, 0x00);
+ }
+ break;
+
+ case WRITE_BUFFER:
+ if (status == SAM_STAT_GOOD)
+ skd_send_internal_skspcl(skdev, skspcl, READ_BUFFER);
+ else {
+ if (skdev->state == SKD_DRVR_STATE_STOPPING) {
+ VPRINTK(skdev, "write buffer failed, don't send"
+ " anymore state 0x%x\n", skdev->state);
+ return;
+ }
+ DPRINTK(skdev,
+ "**** write buffer failed, retry skerr\n");
+ skd_send_internal_skspcl(skdev, skspcl, 0x00);
+ }
+ break;
+
+ case READ_BUFFER:
+ if (status == SAM_STAT_GOOD) {
+ if (skd_chk_read_buf(skdev, skspcl) == 0)
+ skd_send_internal_skspcl(skdev, skspcl,
+ READ_CAPACITY);
+ else {
+ pr_err(
+ "(%s):*** W/R Buffer mismatch %d ***\n",
+ skd_name(skdev), skdev->connect_retries);
+ if (skdev->connect_retries <
+ SKD_MAX_CONNECT_RETRIES) {
+ skdev->connect_retries++;
+ skd_soft_reset(skdev);
+ } else {
+ pr_err(
+ "(%s): W/R Buffer Connect Error\n",
+ skd_name(skdev));
+ return;
+ }
+ }
+
+ } else {
+ if (skdev->state == SKD_DRVR_STATE_STOPPING) {
+ VPRINTK(skdev,
+ "read buffer failed, don't send anymore"
+ "state 0x%x\n", skdev->state);
+ return;
+ }
+ DPRINTK(skdev,
+ "**** read buffer failed, retry skerr\n");
+ skd_send_internal_skspcl(skdev, skspcl, 0x00);
+ }
+ break;
+
+ case READ_CAPACITY:
+ skdev->read_cap_is_valid = 0;
+ if (status == SAM_STAT_GOOD) {
+ skdev->read_cap_last_lba =
+ (buf[0] << 24) | (buf[1] << 16) |
+ (buf[2] << 8) | buf[3];
+ skdev->read_cap_blocksize =
+ (buf[4] << 24) | (buf[5] << 16) |
+ (buf[6] << 8) | buf[7];
+
+ DPRINTK(skdev, "last lba %d, bs %d\n",
+ skdev->read_cap_last_lba,
+ skdev->read_cap_blocksize);
+
+ set_capacity(skdev->disk, skdev->read_cap_last_lba + 1);
+
+ skdev->read_cap_is_valid = 1;
+
+ skd_send_internal_skspcl(skdev, skspcl, INQUIRY);
+ } else if ((status == SAM_STAT_CHECK_CONDITION) &&
+ (skerr->key == MEDIUM_ERROR)) {
+ skdev->read_cap_last_lba = ~0;
+ set_capacity(skdev->disk, skdev->read_cap_last_lba + 1);
+ DPRINTK(skdev,
+ "**** MEDIUM ERROR caused READCAP to fail, ignore failure and continue to inquiry\n");
+ skd_send_internal_skspcl(skdev, skspcl, INQUIRY);
+ } else {
+ DPRINTK(skdev, "**** READCAP failed, retry TUR\n");
+ skd_send_internal_skspcl(skdev, skspcl,
+ TEST_UNIT_READY);
+ }
+ break;
+
+ case INQUIRY:
+ skdev->inquiry_is_valid = 0;
+ if (status == SAM_STAT_GOOD) {
+ skdev->inquiry_is_valid = 1;
+
+ for (i = 0; i < 12; i++)
+ skdev->inq_serial_num[i] = buf[i + 4];
+ skdev->inq_serial_num[12] = 0;
+ }
+
+ if (skd_unquiesce_dev(skdev) < 0)
+ DPRINTK(skdev, "**** failed, to ONLINE device\n");
+ /* connection is complete */
+ skdev->connect_retries = 0;
+ break;
+
+ case SYNCHRONIZE_CACHE:
+ if (status == SAM_STAT_GOOD)
+ skdev->sync_done = 1;
+ else
+ skdev->sync_done = -1;
+ wake_up_interruptible(&skdev->waitq);
+ break;
+
+ default:
+ SKD_ASSERT("we didn't send this");
+ }
+}
+
+/*
+ *****************************************************************************
+ * FIT MESSAGES
+ *****************************************************************************
+ */
+
+static void skd_send_fitmsg(struct skd_device *skdev,
+ struct skd_fitmsg_context *skmsg)
+{
+ u64 qcmd;
+ struct fit_msg_hdr *fmh;
+
+ VPRINTK(skdev, "dma address 0x%llx, busy=%d\n",
+ skmsg->mb_dma_address, skdev->in_flight);
+ VPRINTK(skdev, "msg_buf 0x%p, offset %x\n",
+ skmsg->msg_buf, skmsg->offset);
+
+ qcmd = skmsg->mb_dma_address;
+ qcmd |= FIT_QCMD_QID_NORMAL;
+
+ fmh = (struct fit_msg_hdr *)skmsg->msg_buf;
+ skmsg->outstanding = fmh->num_protocol_cmds_coalesced;
+
+ if (unlikely(skdev->dbg_level > 1)) {
+ u8 *bp = (u8 *)skmsg->msg_buf;
+ int i;
+ for (i = 0; i < skmsg->length; i += 8) {
+ VPRINTK(skdev, " msg[%2d] %02x %02x %02x %02x "
+ "%02x %02x %02x %02x\n",
+ i, bp[i + 0], bp[i + 1], bp[i + 2],
+ bp[i + 3], bp[i + 4], bp[i + 5],
+ bp[i + 6], bp[i + 7]);
+ if (i == 0)
+ i = 64 - 8;
+ }
+ }
+
+ if (skmsg->length > 256)
+ qcmd |= FIT_QCMD_MSGSIZE_512;
+ else if (skmsg->length > 128)
+ qcmd |= FIT_QCMD_MSGSIZE_256;
+ else if (skmsg->length > 64)
+ qcmd |= FIT_QCMD_MSGSIZE_128;
+ else
+ /*
+ * This makes no sense because the FIT msg header is
+ * 64 bytes. If the msg is only 64 bytes long it has
+ * no payload.
+ */
+ qcmd |= FIT_QCMD_MSGSIZE_64;
+
+ SKD_WRITEQ(skdev, qcmd, FIT_Q_COMMAND);
+
+}
+
+static void skd_send_special_fitmsg(struct skd_device *skdev,
+ struct skd_special_context *skspcl)
+{
+ u64 qcmd;
+
+ if (unlikely(skdev->dbg_level > 1)) {
+ u8 *bp = (u8 *)skspcl->msg_buf;
+ int i;
+
+ for (i = 0; i < SKD_N_SPECIAL_FITMSG_BYTES; i += 8) {
+ VPRINTK(skdev,
+ " spcl[%2d] %02x %02x %02x %02x "
+ "%02x %02x %02x %02x\n", i,
+ bp[i + 0], bp[i + 1], bp[i + 2], bp[i + 3],
+ bp[i + 4], bp[i + 5], bp[i + 6], bp[i + 7]);
+ if (i == 0)
+ i = 64 - 8;
+ }
+
+ VPRINTK(skdev, "skspcl=%p id=%04x sksg_list=%p sksg_dma=%llx\n",
+ skspcl, skspcl->req.id, skspcl->req.sksg_list,
+ skspcl->req.sksg_dma_address);
+ for (i = 0; i < skspcl->req.n_sg; i++) {
+ struct fit_sg_descriptor *sgd =
+ &skspcl->req.sksg_list[i];
+
+ VPRINTK(skdev, " sg[%d] count=%u ctrl=0x%x "
+ "addr=0x%llx next=0x%llx\n",
+ i, sgd->byte_count, sgd->control,
+ sgd->host_side_addr, sgd->next_desc_ptr);
+ }
+ }
+
+ /*
+ * Special FIT msgs are always 128 bytes: a 64-byte FIT hdr
+ * and one 64-byte SSDI command.
+ */
+ qcmd = skspcl->mb_dma_address;
+ qcmd |= FIT_QCMD_QID_NORMAL + FIT_QCMD_MSGSIZE_128;
+
+ SKD_WRITEQ(skdev, qcmd, FIT_Q_COMMAND);
+}
+
+/*
+ *****************************************************************************
+ * COMPLETION QUEUE
+ *****************************************************************************
+ */
+
+static void skd_complete_other(struct skd_device *skdev,
+ volatile struct fit_completion_entry_v1 *skcomp,
+ volatile struct fit_comp_error_info *skerr);
+
+
+static void skd_requeue_request(struct skd_device *skdev,
+ struct skd_request_context *skreq);
+
+struct sns_info {
+ u8 type;
+ u8 stat;
+ u8 key;
+ u8 asc;
+ u8 ascq;
+ u8 mask;
+ enum skd_check_status_action action;
+};
+
+static struct sns_info skd_chkstat_table[] = {
+ /* Good */
+ { 0x70, 0x02, RECOVERED_ERROR, 0, 0, 0x1c,
+ SKD_CHECK_STATUS_REPORT_GOOD },
+
+ /* Smart alerts */
+ { 0x70, 0x02, NO_SENSE, 0x0B, 0x00, 0x1E, /* warnings */
+ SKD_CHECK_STATUS_REPORT_SMART_ALERT },
+ { 0x70, 0x02, NO_SENSE, 0x5D, 0x00, 0x1E, /* thresholds */
+ SKD_CHECK_STATUS_REPORT_SMART_ALERT },
+ { 0x70, 0x02, RECOVERED_ERROR, 0x0B, 0x01, 0x1F, /* temperature over trigger */
+ SKD_CHECK_STATUS_REPORT_SMART_ALERT },
+
+ /* Retry (with limits) */
+ { 0x70, 0x02, 0x0B, 0, 0, 0x1C, /* This one is for DMA ERROR */
+ SKD_CHECK_STATUS_REQUEUE_REQUEST },
+ { 0x70, 0x02, 0x06, 0x0B, 0x00, 0x1E, /* warnings */
+ SKD_CHECK_STATUS_REQUEUE_REQUEST },
+ { 0x70, 0x02, 0x06, 0x5D, 0x00, 0x1E, /* thresholds */
+ SKD_CHECK_STATUS_REQUEUE_REQUEST },
+ { 0x70, 0x02, 0x06, 0x80, 0x30, 0x1F, /* backup power */
+ SKD_CHECK_STATUS_REQUEUE_REQUEST },
+
+ /* Busy (or about to be) */
+ { 0x70, 0x02, 0x06, 0x3f, 0x01, 0x1F, /* fw changed */
+ SKD_CHECK_STATUS_BUSY_IMMINENT },
+};
+
+/*
+ * Look up status and sense data to decide how to handle the error
+ * from the device.
+ * mask says which fields must match e.g., mask=0x18 means check
+ * type and stat, ignore key, asc, ascq.
+ */
+
+static enum skd_check_status_action skd_check_status(struct skd_device *skdev,
+ u8 cmp_status,
+ volatile struct fit_comp_error_info *skerr)
+{
+ int i, n;
+
+ pr_err("(%s): key/asc/ascq/fruc %02x/%02x/%02x/%02x\n",
+ skd_name(skdev), skerr->key, skerr->code, skerr->qual,
+ skerr->fruc);
+
+ VPRINTK(skdev, "stat: t=%02x stat=%02x k=%02x c=%02x q=%02x "
+ "fruc=%02x\n", skerr->type, cmp_status, skerr->key,
+ skerr->code, skerr->qual, skerr->fruc);
+
+ /* Does the info match an entry in the good category? */
+ n = sizeof(skd_chkstat_table) / sizeof(skd_chkstat_table[0]);
+ for (i = 0; i < n; i++) {
+ struct sns_info *sns = &skd_chkstat_table[i];
+
+ if (sns->mask & 0x10)
+ if (skerr->type != sns->type)
+ continue;
+
+ if (sns->mask & 0x08)
+ if (cmp_status != sns->stat)
+ continue;
+
+ if (sns->mask & 0x04)
+ if (skerr->key != sns->key)
+ continue;
+
+ if (sns->mask & 0x02)
+ if (skerr->code != sns->asc)
+ continue;
+
+ if (sns->mask & 0x01)
+ if (skerr->qual != sns->ascq)
+ continue;
+
+ if (sns->action == SKD_CHECK_STATUS_REPORT_SMART_ALERT) {
+ pr_err("(%s): SMART Alert: sense key/asc/ascq "
+ "%02x/%02x/%02x\n",
+ skd_name(skdev), skerr->key,
+ skerr->code, skerr->qual);
+ }
+ return sns->action;
+ }
+
+ /* No other match, so nonzero status means error,
+ * zero status means good
+ */
+ if (cmp_status) {
+ DPRINTK(skdev, "status check: error\n");
+ return SKD_CHECK_STATUS_REPORT_ERROR;
+ }
+
+ DPRINTK(skdev, "status check good default\n");
+ return SKD_CHECK_STATUS_REPORT_GOOD;
+}
+
+static void skd_resolve_req_exception(struct skd_device *skdev,
+ struct skd_request_context *skreq)
+{
+ u8 cmp_status = skreq->completion.status;
+
+ switch (skd_check_status(skdev, cmp_status, &skreq->err_info)) {
+ case SKD_CHECK_STATUS_REPORT_GOOD:
+ case SKD_CHECK_STATUS_REPORT_SMART_ALERT:
+ skd_end_request(skdev, skreq, 0);
+ break;
+
+ case SKD_CHECK_STATUS_BUSY_IMMINENT:
+ skd_log_skreq(skdev, skreq, "retry(busy)");
+ skd_requeue_request(skdev, skreq);
+ pr_info("(%s) drive BUSY imminent\n", skd_name(skdev));
+ skdev->state = SKD_DRVR_STATE_BUSY_IMMINENT;
+ skdev->timer_countdown = SKD_TIMER_MINUTES(20);
+ skd_quiesce_dev(skdev);
+ break;
+
+ case SKD_CHECK_STATUS_REQUEUE_REQUEST:
+ if (!skd_bio) {
+ if ((unsigned long) ++skreq->req->special <
+ SKD_MAX_RETRIES) {
+ skd_log_skreq(skdev, skreq, "retry");
+ skd_requeue_request(skdev, skreq);
+ break;
+ }
+ }
+ /* fall through to report error */
+
+ case SKD_CHECK_STATUS_REPORT_ERROR:
+ default:
+ skd_end_request(skdev, skreq, -EIO);
+ break;
+ }
+}
+
+static void skd_requeue_request(struct skd_device *skdev,
+ struct skd_request_context *skreq)
+{
+ if (!skd_bio) {
+ blk_requeue_request(skdev->queue, skreq->req);
+ } else {
+ bio_list_add_head(&skdev->bio_queue, skreq->bio);
+ skreq->bio = NULL;
+ }
+}
+
+
+
+/* assume spinlock is already held */
+static void skd_release_skreq(struct skd_device *skdev,
+ struct skd_request_context *skreq)
+{
+ u32 msg_slot;
+ struct skd_fitmsg_context *skmsg;
+
+ u32 timo_slot;
+
+ /*
+ * Reclaim the FIT msg buffer if this is
+ * the first of the requests it carried to
+ * be completed. The FIT msg buffer used to
+ * send this request cannot be reused until
+ * we are sure the s1120 card has copied
+ * it to its memory. The FIT msg might have
+ * contained several requests. As soon as
+ * any of them are completed we know that
+ * the entire FIT msg was transferred.
+ * Only the first completed request will
+ * match the FIT msg buffer id. The FIT
+ * msg buffer id is immediately updated.
+ * When subsequent requests complete the FIT
+ * msg buffer id won't match, so we know
+ * quite cheaply that it is already done.
+ */
+ msg_slot = skreq->fitmsg_id & SKD_ID_SLOT_MASK;
+ SKD_ASSERT(msg_slot < skdev->num_fitmsg_context);
+
+ skmsg = &skdev->skmsg_table[msg_slot];
+ if (skmsg->id == skreq->fitmsg_id) {
+ SKD_ASSERT(skmsg->state == SKD_MSG_STATE_BUSY);
+ SKD_ASSERT(skmsg->outstanding > 0);
+ skmsg->outstanding--;
+ if (skmsg->outstanding == 0) {
+ skmsg->state = SKD_MSG_STATE_IDLE;
+ skmsg->id += SKD_ID_INCR;
+ skmsg->next = skdev->skmsg_free_list;
+ skdev->skmsg_free_list = skmsg;
+ }
+ }
+
+ /*
+ * Decrease the number of active requests.
+ * Also decrements the count in the timeout slot.
+ */
+ SKD_ASSERT(skdev->in_flight > 0);
+ skdev->in_flight -= 1;
+
+ timo_slot = skreq->timeout_stamp & SKD_TIMEOUT_SLOT_MASK;
+ SKD_ASSERT(skdev->timeout_slot[timo_slot] > 0);
+ skdev->timeout_slot[timo_slot] -= 1;
+
+ /*
+ * Reset backpointer
+ */
+ if (likely(!skd_bio))
+ skreq->req = NULL;
+ else
+ skreq->bio = NULL;
+
+
+ /*
+ * Reclaim the skd_request_context
+ */
+ skreq->state = SKD_REQ_STATE_IDLE;
+ skreq->id += SKD_ID_INCR;
+ skreq->next = skdev->skreq_free_list;
+ skdev->skreq_free_list = skreq;
+}
+
+#define DRIVER_INQ_EVPD_PAGE_CODE 0xDA
+
+static void skd_do_inq_page_00(struct skd_device *skdev,
+ volatile struct fit_completion_entry_v1 *skcomp,
+ volatile struct fit_comp_error_info *skerr,
+ uint8_t *cdb, uint8_t *buf)
+{
+ uint16_t insert_pt, max_bytes, drive_pages, drive_bytes, new_size;
+
+ /* Caller requested "supported pages". The driver needs to insert
+ * its page.
+ */
+ VPRINTK(skdev, "skd_do_driver_inquiry: modify supported pages.\n");
+
+ /* If the device rejected the request because the CDB was
+ * improperly formed, then just leave.
+ */
+ if (skcomp->status == SAM_STAT_CHECK_CONDITION &&
+ skerr->key == ILLEGAL_REQUEST && skerr->code == 0x24)
+ return;
+
+ /* Get the amount of space the caller allocated */
+ max_bytes = (cdb[3] << 8) | cdb[4];
+
+ /* Get the number of pages actually returned by the device */
+ drive_pages = (buf[2] << 8) | buf[3];
+ drive_bytes = drive_pages + 4;
+ new_size = drive_pages + 1;
+
+ /* Supported pages must be in numerical order, so find where
+ * the driver page needs to be inserted into the list of
+ * pages returned by the device.
+ */
+ for (insert_pt = 4; insert_pt < drive_bytes; insert_pt++) {
+ if (buf[insert_pt] == DRIVER_INQ_EVPD_PAGE_CODE)
+ return; /* Device using this page code. abort */
+ else if (buf[insert_pt] > DRIVER_INQ_EVPD_PAGE_CODE)
+ break;
+ }
+
+ if (insert_pt < max_bytes) {
+ uint16_t u;
+
+ /* Shift everything up one byte to make room. */
+ for (u = new_size + 3; u > insert_pt; u--)
+ buf[u] = buf[u - 1];
+ buf[insert_pt] = DRIVER_INQ_EVPD_PAGE_CODE;
+
+ /* SCSI byte order increment of num_returned_bytes by 1 */
+ skcomp->num_returned_bytes =
+ be32_to_cpu(skcomp->num_returned_bytes) + 1;
+ skcomp->num_returned_bytes =
+ be32_to_cpu(skcomp->num_returned_bytes);
+ }
+
+ /* update page length field to reflect the driver's page too */
+ buf[2] = (uint8_t)((new_size >> 8) & 0xFF);
+ buf[3] = (uint8_t)((new_size >> 0) & 0xFF);
+}
+
+static void skd_get_link_info(struct pci_dev *pdev, u8 *speed, u8 *width)
+{
+ int pcie_reg;
+ u16 pci_bus_speed;
+ u8 pci_lanes;
+
+ pcie_reg = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ if (pcie_reg) {
+ u16 linksta;
+ pci_read_config_word(pdev, pcie_reg + PCI_EXP_LNKSTA, &linksta);
+
+ pci_bus_speed = linksta & 0xF;
+ pci_lanes = (linksta & 0x3F0) >> 4;
+ } else {
+ *speed = STEC_LINK_UNKNOWN;
+ *width = 0xFF;
+ return;
+ }
+
+ switch (pci_bus_speed) {
+ case 1:
+ *speed = STEC_LINK_2_5GTS;
+ break;
+ case 2:
+ *speed = STEC_LINK_5GTS;
+ break;
+ case 3:
+ *speed = STEC_LINK_8GTS;
+ break;
+ default:
+ *speed = STEC_LINK_UNKNOWN;
+ break;
+ }
+
+ if (pci_lanes <= 0x20)
+ *width = pci_lanes;
+ else
+ *width = 0xFF;
+}
+
+static void skd_do_inq_page_da(struct skd_device *skdev,
+ volatile struct fit_completion_entry_v1 *skcomp,
+ volatile struct fit_comp_error_info *skerr,
+ uint8_t *cdb, uint8_t *buf)
+{
+ unsigned max_bytes;
+ struct driver_inquiry_data inq;
+ u16 val;
+
+ VPRINTK(skdev, "skd_do_driver_inquiry: return driver page\n");
+
+ memset(&inq, 0, sizeof(inq));
+
+ inq.page_code = DRIVER_INQ_EVPD_PAGE_CODE;
+
+ if (skdev->pdev && skdev->pdev->bus) {
+ skd_get_link_info(skdev->pdev,
+ &inq.pcie_link_speed, &inq.pcie_link_lanes);
+ inq.pcie_bus_number = cpu_to_be16(skdev->pdev->bus->number);
+ inq.pcie_device_number = PCI_SLOT(skdev->pdev->devfn);
+ inq.pcie_function_number = PCI_FUNC(skdev->pdev->devfn);
+
+ pci_read_config_word(skdev->pdev, PCI_VENDOR_ID, &val);
+ inq.pcie_vendor_id = cpu_to_be16(val);
+
+ pci_read_config_word(skdev->pdev, PCI_DEVICE_ID, &val);
+ inq.pcie_device_id = cpu_to_be16(val);
+
+ pci_read_config_word(skdev->pdev, PCI_SUBSYSTEM_VENDOR_ID,
+ &val);
+ inq.pcie_subsystem_vendor_id = cpu_to_be16(val);
+
+ pci_read_config_word(skdev->pdev, PCI_SUBSYSTEM_ID, &val);
+ inq.pcie_subsystem_device_id = cpu_to_be16(val);
+ } else {
+ inq.pcie_bus_number = 0xFFFF;
+ inq.pcie_device_number = 0xFF;
+ inq.pcie_function_number = 0xFF;
+ inq.pcie_link_speed = 0xFF;
+ inq.pcie_link_lanes = 0xFF;
+ inq.pcie_vendor_id = 0xFFFF;
+ inq.pcie_device_id = 0xFFFF;
+ inq.pcie_subsystem_vendor_id = 0xFFFF;
+ inq.pcie_subsystem_device_id = 0xFFFF;
+ }
+
+ /* Driver version, fixed lenth, padded with spaces on the right */
+ inq.driver_version_length = sizeof(inq.driver_version);
+ memset(&inq.driver_version, ' ', sizeof(inq.driver_version));
+ memcpy(inq.driver_version, DRV_VER_COMPL,
+ min(sizeof(inq.driver_version), strlen(DRV_VER_COMPL)));
+
+ inq.page_length = cpu_to_be16((sizeof(inq) - 4));
+
+ /* Clear the error set by the device */
+ skcomp->status = SAM_STAT_GOOD;
+ memset((void *)skerr, 0, sizeof(*skerr));
+
+ /* copy response into output buffer */
+ max_bytes = (cdb[3] << 8) | cdb[4];
+ memcpy(buf, &inq, min_t(unsigned, max_bytes, sizeof(inq)));
+
+ skcomp->num_returned_bytes =
+ be32_to_cpu(min_t(uint16_t, max_bytes, sizeof(inq)));
+}
+
+static void skd_do_driver_inq(struct skd_device *skdev,
+ volatile struct fit_completion_entry_v1 *skcomp,
+ volatile struct fit_comp_error_info *skerr,
+ uint8_t *cdb, uint8_t *buf)
+{
+ if (!buf)
+ return;
+ else if (cdb[0] != INQUIRY)
+ return; /* Not an INQUIRY */
+ else if ((cdb[1] & 1) == 0)
+ return; /* EVPD not set */
+ else if (cdb[2] == 0)
+ /* Need to add driver's page to supported pages list */
+ skd_do_inq_page_00(skdev, skcomp, skerr, cdb, buf);
+ else if (cdb[2] == DRIVER_INQ_EVPD_PAGE_CODE)
+ /* Caller requested driver's page */
+ skd_do_inq_page_da(skdev, skcomp, skerr, cdb, buf);
+}
+
+static unsigned char *skd_sg_1st_page_ptr(struct scatterlist *sg)
+{
+ if (!sg)
+ return NULL;
+ if (!sg_page(sg))
+ return NULL;
+ return sg_virt(sg);
+}
+
+static void skd_process_scsi_inq(struct skd_device *skdev,
+ volatile struct fit_completion_entry_v1
+ *skcomp,
+ volatile struct fit_comp_error_info *skerr,
+ struct skd_special_context *skspcl)
+{
+ uint8_t *buf;
+ struct fit_msg_hdr *fmh = (struct fit_msg_hdr *)skspcl->msg_buf;
+ struct skd_scsi_request *scsi_req = (struct skd_scsi_request *)&fmh[1];
+
+ dma_sync_sg_for_cpu(skdev->class_dev, skspcl->req.sg, skspcl->req.n_sg,
+ skspcl->req.sg_data_dir);
+ buf = skd_sg_1st_page_ptr(skspcl->req.sg);
+
+ if (buf)
+ skd_do_driver_inq(skdev, skcomp, skerr, scsi_req->cdb, buf);
+}
+
+
+static int skd_isr_completion_posted(struct skd_device *skdev,
+ int limit, int *enqueued)
+{
+ volatile struct fit_completion_entry_v1 *skcmp = NULL;
+ volatile struct fit_comp_error_info *skerr;
+ u16 req_id;
+ u32 req_slot;
+ struct skd_request_context *skreq;
+ u16 cmp_cntxt = 0;
+ u8 cmp_status = 0;
+ u8 cmp_cycle = 0;
+ u32 cmp_bytes = 0;
+ int rc = 0;
+ int processed = 0;
+ int ret;
+
+
+ for (;; ) {
+ SKD_ASSERT(skdev->skcomp_ix < SKD_N_COMPLETION_ENTRY);
+
+ skcmp = &skdev->skcomp_table[skdev->skcomp_ix];
+ cmp_cycle = skcmp->cycle;
+ cmp_cntxt = skcmp->tag;
+ cmp_status = skcmp->status;
+ cmp_bytes = be32_to_cpu(skcmp->num_returned_bytes);
+
+ skerr = &skdev->skerr_table[skdev->skcomp_ix];
+
+ VPRINTK(skdev,
+ "cycle=%d ix=%d got cycle=%d cmdctxt=0x%x stat=%d "
+ "busy=%d rbytes=0x%x proto=%d\n", skdev->skcomp_cycle,
+ skdev->skcomp_ix, cmp_cycle, cmp_cntxt, cmp_status,
+ skdev->in_flight, cmp_bytes, skdev->proto_ver);
+
+ if (cmp_cycle != skdev->skcomp_cycle) {
+ VPRINTK(skdev, "end of completions\n");
+ break;
+ }
+ /*
+ * Update the completion queue head index and possibly
+ * the completion cycle count. 8-bit wrap-around.
+ */
+ skdev->skcomp_ix++;
+ if (skdev->skcomp_ix >= SKD_N_COMPLETION_ENTRY) {
+ skdev->skcomp_ix = 0;
+ skdev->skcomp_cycle++;
+ }
+
+ /*
+ * The command context is a unique 32-bit ID. The low order
+ * bits help locate the request. The request is usually a
+ * r/w request (see skd_start() above) or a special request.
+ */
+ req_id = cmp_cntxt;
+ req_slot = req_id & SKD_ID_SLOT_AND_TABLE_MASK;
+
+ /* Is this other than a r/w request? */
+ if (req_slot >= skdev->num_req_context) {
+ /*
+ * This is not a completion for a r/w request.
+ */
+ skd_complete_other(skdev, skcmp, skerr);
+ continue;
+ }
+
+ skreq = &skdev->skreq_table[req_slot];
+
+ /*
+ * Make sure the request ID for the slot matches.
+ */
+ if (skreq->id != req_id) {
+ DPRINTK(skdev, "mismatch comp_id=0x%x req_id=0x%x\n",
+ req_id, skreq->id);
+ {
+ u16 new_id = cmp_cntxt;
+ pr_err("(%s): Completion mismatch "
+ "comp_id=0x%04x skreq=0x%04x new=0x%04x\n",
+ skd_name(skdev), req_id,
+ skreq->id, new_id);
+
+ continue;
+ }
+ }
+
+ SKD_ASSERT(skreq->state == SKD_REQ_STATE_BUSY);
+
+ if (skreq->state == SKD_REQ_STATE_ABORTED) {
+ DPRINTK(skdev, "reclaim req %p id=%04x\n",
+ skreq, skreq->id);
+ /* a previously timed out command can
+ * now be cleaned up */
+ skd_release_skreq(skdev, skreq);
+ continue;
+ }
+
+ skreq->completion = *skcmp;
+ if (unlikely(cmp_status == SAM_STAT_CHECK_CONDITION)) {
+ skreq->err_info = *skerr;
+ skd_log_check_status(skdev, cmp_status, skerr->key,
+ skerr->code, skerr->qual,
+ skerr->fruc);
+ }
+ /* Release DMA resources for the request. */
+ if (skreq->n_sg > 0)
+ skd_postop_sg_list(skdev, skreq);
+
+ if (((!skd_bio) && !skreq->req) ||
+ ((skd_bio) && !skreq->bio)) {
+ DPRINTK(skdev, "NULL backptr skdreq %p, "
+ "req=0x%x req_id=0x%x\n",
+ skreq, skreq->id, req_id);
+ } else {
+ /*
+ * Capture the outcome and post it back to the
+ * native request.
+ */
+ if (likely(cmp_status == SAM_STAT_GOOD)) {
+ if (unlikely(skreq->flush_cmd)) {
+ if (skd_bio) {
+ /* if empty size bio, we are all done */
+ if (bio_sectors(skreq->bio) == 0) {
+ skd_end_request(skdev, skreq, 0);
+ } else {
+ ret = skd_flush_cmd_enqueue(skdev, (void *)skreq->bio);
+ if (ret != 0) {
+ pr_err("Failed to enqueue flush bio with Data. Err=%d.\n", ret);
+ skd_end_request(skdev, skreq, ret);
+ } else {
+ ((*enqueued)++);
+ }
+ }
+ } else {
+ skd_end_request(skdev, skreq, 0);
+ }
+ } else {
+ skd_end_request(skdev, skreq, 0);
+ }
+ } else {
+ skd_resolve_req_exception(skdev, skreq);
+ }
+ }
+
+ /*
+ * Release the skreq, its FIT msg (if one), timeout slot,
+ * and queue depth.
+ */
+ skd_release_skreq(skdev, skreq);
+
+ /* skd_isr_comp_limit equal zero means no limit */
+ if (limit) {
+ if (++processed >= limit) {
+ rc = 1;
+ break;
+ }
+ }
+ }
+
+ if ((skdev->state == SKD_DRVR_STATE_PAUSING)
+ && (skdev->in_flight) == 0) {
+ skdev->state = SKD_DRVR_STATE_PAUSED;
+ wake_up_interruptible(&skdev->waitq);
+ }
+
+ return rc;
+}
+
+static void skd_complete_other(struct skd_device *skdev,
+ volatile struct fit_completion_entry_v1 *skcomp,
+ volatile struct fit_comp_error_info *skerr)
+{
+ u32 req_id = 0;
+ u32 req_table;
+ u32 req_slot;
+ struct skd_special_context *skspcl;
+
+ req_id = skcomp->tag;
+ req_table = req_id & SKD_ID_TABLE_MASK;
+ req_slot = req_id & SKD_ID_SLOT_MASK;
+
+ DPRINTK(skdev, "table=0x%x id=0x%x slot=%d\n", req_table, req_id,
+ req_slot);
+
+ /*
+ * Based on the request id, determine how to dispatch this completion.
+ * This swich/case is finding the good cases and forwarding the
+ * completion entry. Errors are reported below the switch.
+ */
+ switch (req_table) {
+ case SKD_ID_RW_REQUEST:
+ /*
+ * The caller, skd_completion_posted_isr() above,
+ * handles r/w requests. The only way we get here
+ * is if the req_slot is out of bounds.
+ */
+ break;
+
+ case SKD_ID_SPECIAL_REQUEST:
+ /*
+ * Make sure the req_slot is in bounds and that the id
+ * matches.
+ */
+ if (req_slot < skdev->n_special) {
+ skspcl = &skdev->skspcl_table[req_slot];
+ if (skspcl->req.id == req_id &&
+ skspcl->req.state == SKD_REQ_STATE_BUSY) {
+ skd_complete_special(skdev,
+ skcomp, skerr, skspcl);
+ return;
+ }
+ }
+ break;
+
+ case SKD_ID_INTERNAL:
+ if (req_slot == 0) {
+ skspcl = &skdev->internal_skspcl;
+ if (skspcl->req.id == req_id &&
+ skspcl->req.state == SKD_REQ_STATE_BUSY) {
+ skd_complete_internal(skdev,
+ skcomp, skerr, skspcl);
+ return;
+ }
+ }
+ break;
+
+ case SKD_ID_FIT_MSG:
+ /*
+ * These id's should never appear in a completion record.
+ */
+ break;
+
+ default:
+ /*
+ * These id's should never appear anywhere;
+ */
+ break;
+ }
+
+ /*
+ * If we get here it is a bad or stale id.
+ */
+}
+
+static void skd_complete_special(struct skd_device *skdev,
+ volatile struct fit_completion_entry_v1
+ *skcomp,
+ volatile struct fit_comp_error_info *skerr,
+ struct skd_special_context *skspcl)
+{
+ DPRINTK(skdev, " completing special request %p\n", skspcl);
+ if (skspcl->orphaned) {
+ /* Discard orphaned request */
+ /* ?: Can this release directly or does it need
+ * to use a worker? */
+ DPRINTK(skdev, "release orphaned %p\n", skspcl);
+ skd_release_special(skdev, skspcl);
+ return;
+ }
+
+ skd_process_scsi_inq(skdev, skcomp, skerr, skspcl);
+
+ skspcl->req.state = SKD_REQ_STATE_COMPLETED;
+ skspcl->req.completion = *skcomp;
+ skspcl->req.err_info = *skerr;
+
+ skd_log_check_status(skdev, skspcl->req.completion.status, skerr->key,
+ skerr->code, skerr->qual, skerr->fruc);
+
+ wake_up_interruptible(&skdev->waitq);
+}
+
+/* assume spinlock is already held */
+static void skd_release_special(struct skd_device *skdev,
+ struct skd_special_context *skspcl)
+{
+ int i, was_depleted;
+
+ for (i = 0; i < skspcl->req.n_sg; i++) {
+
+ struct page *page = sg_page(&skspcl->req.sg[i]);
+ __free_page(page);
+ }
+
+ was_depleted = (skdev->skspcl_free_list == NULL);
+
+ skspcl->req.state = SKD_REQ_STATE_IDLE;
+ skspcl->req.id += SKD_ID_INCR;
+ skspcl->req.next =
+ (struct skd_request_context *)skdev->skspcl_free_list;
+ skdev->skspcl_free_list = (struct skd_special_context *)skspcl;
+
+ if (was_depleted) {
+ DPRINTK(skdev, "skspcl was depleted\n");
+ /* Free list was depleted. Their might be waiters. */
+ wake_up_interruptible(&skdev->waitq);
+ }
+}
+
+static void skd_reset_skcomp(struct skd_device *skdev)
+{
+ u32 nbytes;
+ struct fit_completion_entry_v1 *skcomp;
+
+ nbytes = sizeof(*skcomp) * SKD_N_COMPLETION_ENTRY;
+ nbytes += sizeof(struct fit_comp_error_info) * SKD_N_COMPLETION_ENTRY;
+
+ memset(skdev->skcomp_table, 0, nbytes);
+
+ skdev->skcomp_ix = 0;
+ skdev->skcomp_cycle = 1;
+}
+
+/*
+ *****************************************************************************
+ * INTERRUPTS
+ *****************************************************************************
+ */
+static void skd_completion_worker(struct work_struct *work)
+{
+ struct skd_device *skdev =
+ container_of(work, struct skd_device, completion_worker);
+ unsigned long flags;
+ int flush_enqueued = 0;
+
+ spin_lock_irqsave(&skdev->lock, flags);
+
+ /*
+ * pass in limit=0, which means no limit..
+ * process everything in compq
+ */
+ skd_isr_completion_posted(skdev, 0, &flush_enqueued);
+ skd_request_fn(skdev->queue);
+
+ spin_unlock_irqrestore(&skdev->lock, flags);
+}
+
+static void skd_isr_msg_from_dev(struct skd_device *skdev);
+
+irqreturn_t
+static skd_isr(int irq, void *ptr)
+{
+ struct skd_device *skdev;
+ u32 intstat;
+ u32 ack;
+ int rc = 0;
+ int deferred = 0;
+ int flush_enqueued = 0;
+
+ skdev = (struct skd_device *)ptr;
+ spin_lock(&skdev->lock);
+
+ for (;; ) {
+ intstat = SKD_READL(skdev, FIT_INT_STATUS_HOST);
+
+ ack = FIT_INT_DEF_MASK;
+ ack &= intstat;
+
+ VPRINTK(skdev, "intstat=0x%x ack=0x%x\n", intstat, ack);
+
+ /* As long as there is an int pending on device, keep
+ * running loop. When none, get out, but if we've never
+ * done any processing, call completion handler?
+ */
+ if (ack == 0) {
+ /* No interrupts on device, but run the completion
+ * processor anyway?
+ */
+ if (rc == 0)
+ if (likely (skdev->state
+ == SKD_DRVR_STATE_ONLINE))
+ deferred = 1;
+ break;
+ }
+
+ rc = IRQ_HANDLED;
+
+ SKD_WRITEL(skdev, ack, FIT_INT_STATUS_HOST);
+
+ if (likely((skdev->state != SKD_DRVR_STATE_LOAD) &&
+ (skdev->state != SKD_DRVR_STATE_STOPPING))) {
+ if (intstat & FIT_ISH_COMPLETION_POSTED) {
+ /*
+ * If we have already deferred completion
+ * processing, don't bother running it again
+ */
+ if (deferred == 0)
+ deferred =
+ skd_isr_completion_posted(skdev,
+ skd_isr_comp_limit, &flush_enqueued);
+ }
+
+ if (intstat & FIT_ISH_FW_STATE_CHANGE) {
+ skd_isr_fwstate(skdev);
+ if (skdev->state == SKD_DRVR_STATE_FAULT ||
+ skdev->state ==
+ SKD_DRVR_STATE_DISAPPEARED) {
+ spin_unlock(&skdev->lock);
+ return rc;
+ }
+ }
+
+ if (intstat & FIT_ISH_MSG_FROM_DEV)
+ skd_isr_msg_from_dev(skdev);
+ }
+ }
+
+ if (unlikely(flush_enqueued))
+ skd_request_fn(skdev->queue);
+
+ if (deferred)
+ schedule_work(&skdev->completion_worker);
+ else if (!flush_enqueued)
+ skd_request_fn(skdev->queue);
+
+ spin_unlock(&skdev->lock);
+
+ return rc;
+}
+
+
+static void skd_drive_fault(struct skd_device *skdev)
+{
+ skdev->state = SKD_DRVR_STATE_FAULT;
+ pr_err("(%s): Drive FAULT\n", skd_name(skdev));
+}
+
+static void skd_drive_disappeared(struct skd_device *skdev)
+{
+ skdev->state = SKD_DRVR_STATE_DISAPPEARED;
+ pr_err("(%s): Drive DISAPPEARED\n", skd_name(skdev));
+}
+
+static void skd_isr_fwstate(struct skd_device *skdev)
+{
+ u32 sense;
+ u32 state;
+ u32 mtd;
+ int prev_driver_state = skdev->state;
+
+ sense = SKD_READL(skdev, FIT_STATUS);
+ state = sense & FIT_SR_DRIVE_STATE_MASK;
+
+ pr_err("(%s): s1120 state %s(%d)=>%s(%d)\n",
+ skd_name(skdev),
+ skd_drive_state_to_str(skdev->drive_state), skdev->drive_state,
+ skd_drive_state_to_str(state), state);
+
+ skdev->drive_state = state;
+
+ switch (skdev->drive_state) {
+ case FIT_SR_DRIVE_INIT:
+ if (skdev->state == SKD_DRVR_STATE_PROTOCOL_MISMATCH) {
+ skd_disable_interrupts(skdev);
+ break;
+ }
+ if (skdev->state == SKD_DRVR_STATE_RESTARTING)
+ skd_recover_requests(skdev, 0);
+ if (skdev->state == SKD_DRVR_STATE_WAIT_BOOT) {
+ skdev->timer_countdown = SKD_STARTING_TIMO;
+ skdev->state = SKD_DRVR_STATE_STARTING;
+ skd_soft_reset(skdev);
+ break;
+ }
+ mtd = FIT_MXD_CONS(FIT_MTD_FITFW_INIT, 0, 0);
+ SKD_WRITEL(skdev, mtd, FIT_MSG_TO_DEVICE);
+ skdev->last_mtd = mtd;
+ break;
+
+ case FIT_SR_DRIVE_ONLINE:
+ skdev->cur_max_queue_depth = skd_max_queue_depth;
+ if (skdev->cur_max_queue_depth > skdev->dev_max_queue_depth)
+ skdev->cur_max_queue_depth = skdev->dev_max_queue_depth;
+
+ skdev->queue_low_water_mark =
+ skdev->cur_max_queue_depth * 2 / 3 + 1;
+ if (skdev->queue_low_water_mark < 1)
+ skdev->queue_low_water_mark = 1;
+ pr_info(
+ "(%s): Queue depth limit=%d dev=%d lowat=%d\n",
+ skd_name(skdev),
+ skdev->cur_max_queue_depth,
+ skdev->dev_max_queue_depth, skdev->queue_low_water_mark);
+
+ skd_refresh_device_data(skdev);
+ break;
+
+ case FIT_SR_DRIVE_BUSY:
+ skdev->state = SKD_DRVR_STATE_BUSY;
+ skdev->timer_countdown = SKD_BUSY_TIMO;
+ skd_quiesce_dev(skdev);
+ break;
+ case FIT_SR_DRIVE_BUSY_SANITIZE:
+ /* set timer for 3 seconds, we'll abort any unfinished
+ * commands after that expires
+ */
+ skdev->state = SKD_DRVR_STATE_BUSY_SANITIZE;
+ skdev->timer_countdown = SKD_TIMER_SECONDS(3);
+ skd_start_queue(skdev);
+ break;
+ case FIT_SR_DRIVE_BUSY_ERASE:
+ skdev->state = SKD_DRVR_STATE_BUSY_ERASE;
+ skdev->timer_countdown = SKD_BUSY_TIMO;
+ break;
+ case FIT_SR_DRIVE_OFFLINE:
+ skdev->state = SKD_DRVR_STATE_IDLE;
+ break;
+ case FIT_SR_DRIVE_SOFT_RESET:
+ switch (skdev->state) {
+ case SKD_DRVR_STATE_STARTING:
+ case SKD_DRVR_STATE_RESTARTING:
+ /* Expected by a caller of skd_soft_reset() */
+ break;
+ default:
+ skdev->state = SKD_DRVR_STATE_RESTARTING;
+ break;
+ }
+ break;
+ case FIT_SR_DRIVE_FW_BOOTING:
+ VPRINTK(skdev, "ISR FIT_SR_DRIVE_FW_BOOTING %s\n", skdev->name);
+ skdev->state = SKD_DRVR_STATE_WAIT_BOOT;
+ skdev->timer_countdown = SKD_WAIT_BOOT_TIMO;
+ break;
+
+ case FIT_SR_DRIVE_DEGRADED:
+ case FIT_SR_PCIE_LINK_DOWN:
+ case FIT_SR_DRIVE_NEED_FW_DOWNLOAD:
+ break;
+
+ case FIT_SR_DRIVE_FAULT:
+ skd_drive_fault(skdev);
+ skd_recover_requests(skdev, 0);
+ skd_start_queue(skdev);
+ break;
+
+ /* PCIe bus returned all Fs? */
+ case 0xFF:
+ pr_info("(%s): state=0x%x sense=0x%x\n",
+ skd_name(skdev), state, sense);
+ skd_drive_disappeared(skdev);
+ skd_recover_requests(skdev, 0);
+ skd_start_queue(skdev);
+ break;
+ default:
+ /*
+ * Uknown FW State. Wait for a state we recognize.
+ */
+ break;
+ }
+ pr_err("(%s): Driver state %s(%d)=>%s(%d)\n",
+ skd_name(skdev),
+ skd_skdev_state_to_str(prev_driver_state), prev_driver_state,
+ skd_skdev_state_to_str(skdev->state), skdev->state);
+}
+
+static void skd_recover_requests(struct skd_device *skdev, int requeue)
+{
+ int i;
+
+ for (i = 0; i < skdev->num_req_context; i++) {
+ struct skd_request_context *skreq = &skdev->skreq_table[i];
+
+ if (skreq->state == SKD_REQ_STATE_BUSY) {
+ skd_log_skreq(skdev, skreq, "recover");
+
+ SKD_ASSERT((skreq->id & SKD_ID_INCR) != 0);
+ if (!skd_bio)
+ SKD_ASSERT(skreq->req != NULL);
+ else
+ SKD_ASSERT(skreq->bio != NULL);
+
+ /* Release DMA resources for the request. */
+ if (skreq->n_sg > 0)
+ skd_postop_sg_list(skdev, skreq);
+
+ if (!skd_bio) {
+ if (requeue &&
+ (unsigned long) ++skreq->req->special <
+ SKD_MAX_RETRIES)
+ skd_requeue_request(skdev, skreq);
+ else
+ skd_end_request(skdev, skreq, -EIO);
+ } else
+ skd_end_request(skdev, skreq, -EIO);
+
+ if (!skd_bio)
+ skreq->req = NULL;
+ else
+ skreq->bio = NULL;
+
+ skreq->state = SKD_REQ_STATE_IDLE;
+ skreq->id += SKD_ID_INCR;
+
+
+ }
+ if (i > 0)
+ skreq[-1].next = skreq;
+ skreq->next = NULL;
+ }
+ skdev->skreq_free_list = skdev->skreq_table;
+
+ for (i = 0; i < skdev->num_fitmsg_context; i++) {
+ struct skd_fitmsg_context *skmsg = &skdev->skmsg_table[i];
+
+ if (skmsg->state == SKD_MSG_STATE_BUSY) {
+ skd_log_skmsg(skdev, skmsg, "salvaged");
+ SKD_ASSERT((skmsg->id & SKD_ID_INCR) != 0);
+ skmsg->state = SKD_MSG_STATE_IDLE;
+ skmsg->id += SKD_ID_INCR;
+ }
+ if (i > 0)
+ skmsg[-1].next = skmsg;
+ skmsg->next = NULL;
+ }
+ skdev->skmsg_free_list = skdev->skmsg_table;
+
+ for (i = 0; i < skdev->n_special; i++) {
+ struct skd_special_context *skspcl = &skdev->skspcl_table[i];
+
+ /* If orphaned, reclaim it because it has already been reported
+ * to the process as an error (it was just waiting for
+ * a completion that didn't come, and now it will never come)
+ * If busy, change to a state that will cause it to error
+ * out in the wait routine and let it do the normal
+ * reporting and reclaiming
+ */
+ if (skspcl->req.state == SKD_REQ_STATE_BUSY) {
+ if (skspcl->orphaned) {
+ DPRINTK(skdev, "orphaned %p\n", skspcl);
+ skd_release_special(skdev, skspcl);
+ } else {
+ DPRINTK(skdev, "not orphaned %p\n", skspcl);
+ skspcl->req.state = SKD_REQ_STATE_ABORTED;
+ }
+ }
+ }
+ skdev->skspcl_free_list = skdev->skspcl_table;
+
+ for (i = 0; i < SKD_N_TIMEOUT_SLOT; i++)
+ skdev->timeout_slot[i] = 0;
+
+ skdev->in_flight = 0;
+}
+
+static void skd_isr_msg_from_dev(struct skd_device *skdev)
+{
+ u32 mfd;
+ u32 mtd;
+ u32 data;
+
+ mfd = SKD_READL(skdev, FIT_MSG_FROM_DEVICE);
+
+ DPRINTK(skdev, "mfd=0x%x last_mtd=0x%x\n", mfd, skdev->last_mtd);
+
+ /* ignore any mtd that is an ack for something we didn't send */
+ if (FIT_MXD_TYPE(mfd) != FIT_MXD_TYPE(skdev->last_mtd))
+ return;
+
+ switch (FIT_MXD_TYPE(mfd)) {
+ case FIT_MTD_FITFW_INIT:
+ skdev->proto_ver = FIT_PROTOCOL_MAJOR_VER(mfd);
+
+ if (skdev->proto_ver != FIT_PROTOCOL_VERSION_1) {
+ pr_err("(%s): protocol mismatch\n",
+ skdev->name);
+ pr_err("(%s): got=%d support=%d\n",
+ skdev->name, skdev->proto_ver,
+ FIT_PROTOCOL_VERSION_1);
+ pr_err("(%s): please upgrade driver\n",
+ skdev->name);
+ skdev->state = SKD_DRVR_STATE_PROTOCOL_MISMATCH;
+ skd_soft_reset(skdev);
+ break;
+ }
+ mtd = FIT_MXD_CONS(FIT_MTD_GET_CMDQ_DEPTH, 0, 0);
+ SKD_WRITEL(skdev, mtd, FIT_MSG_TO_DEVICE);
+ skdev->last_mtd = mtd;
+ break;
+
+ case FIT_MTD_GET_CMDQ_DEPTH:
+ skdev->dev_max_queue_depth = FIT_MXD_DATA(mfd);
+ mtd = FIT_MXD_CONS(FIT_MTD_SET_COMPQ_DEPTH, 0,
+ SKD_N_COMPLETION_ENTRY);
+ SKD_WRITEL(skdev, mtd, FIT_MSG_TO_DEVICE);
+ skdev->last_mtd = mtd;
+ break;
+
+ case FIT_MTD_SET_COMPQ_DEPTH:
+ SKD_WRITEQ(skdev, skdev->cq_dma_address, FIT_MSG_TO_DEVICE_ARG);
+ mtd = FIT_MXD_CONS(FIT_MTD_SET_COMPQ_ADDR, 0, 0);
+ SKD_WRITEL(skdev, mtd, FIT_MSG_TO_DEVICE);
+ skdev->last_mtd = mtd;
+ break;
+
+ case FIT_MTD_SET_COMPQ_ADDR:
+ skd_reset_skcomp(skdev);
+ mtd = FIT_MXD_CONS(FIT_MTD_CMD_LOG_HOST_ID, 0, skdev->devno);
+ SKD_WRITEL(skdev, mtd, FIT_MSG_TO_DEVICE);
+ skdev->last_mtd = mtd;
+ break;
+
+ case FIT_MTD_CMD_LOG_HOST_ID:
+ skdev->connect_time_stamp = get_seconds();
+ data = skdev->connect_time_stamp & 0xFFFF;
+ mtd = FIT_MXD_CONS(FIT_MTD_CMD_LOG_TIME_STAMP_LO, 0, data);
+ SKD_WRITEL(skdev, mtd, FIT_MSG_TO_DEVICE);
+ skdev->last_mtd = mtd;
+ break;
+
+ case FIT_MTD_CMD_LOG_TIME_STAMP_LO:
+ skdev->drive_jiffies = FIT_MXD_DATA(mfd);
+ data = (skdev->connect_time_stamp >> 16) & 0xFFFF;
+ mtd = FIT_MXD_CONS(FIT_MTD_CMD_LOG_TIME_STAMP_HI, 0, data);
+ SKD_WRITEL(skdev, mtd, FIT_MSG_TO_DEVICE);
+ skdev->last_mtd = mtd;
+ break;
+
+ case FIT_MTD_CMD_LOG_TIME_STAMP_HI:
+ skdev->drive_jiffies |= (FIT_MXD_DATA(mfd) << 16);
+ mtd = FIT_MXD_CONS(FIT_MTD_ARM_QUEUE, 0, 0);
+ SKD_WRITEL(skdev, mtd, FIT_MSG_TO_DEVICE);
+ skdev->last_mtd = mtd;
+
+ pr_err("(%s): Time sync driver=0x%x device=0x%x\n",
+ skd_name(skdev),
+ skdev->connect_time_stamp, skdev->drive_jiffies);
+ break;
+
+ case FIT_MTD_ARM_QUEUE:
+ skdev->last_mtd = 0;
+ /*
+ * State should be, or soon will be, FIT_SR_DRIVE_ONLINE.
+ */
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void skd_disable_interrupts(struct skd_device *skdev)
+{
+ u32 sense;
+
+ sense = SKD_READL(skdev, FIT_CONTROL);
+ sense &= ~FIT_CR_ENABLE_INTERRUPTS;
+ SKD_WRITEL(skdev, sense, FIT_CONTROL);
+ DPRINTK(skdev, "sense 0x%x\n", sense);
+
+ /* Note that the 1s is written. A 1-bit means
+ * disable, a 0 means enable.
+ */
+ SKD_WRITEL(skdev, ~0, FIT_INT_MASK_HOST);
+}
+
+static void skd_enable_interrupts(struct skd_device *skdev)
+{
+ u32 val;
+
+ /* unmask interrupts first */
+ val = FIT_ISH_FW_STATE_CHANGE +
+ FIT_ISH_COMPLETION_POSTED + FIT_ISH_MSG_FROM_DEV;
+
+ /* Note that the compliment of mask is written. A 1-bit means
+ * disable, a 0 means enable. */
+ SKD_WRITEL(skdev, ~val, FIT_INT_MASK_HOST);
+ DPRINTK(skdev, "interrupt mask=0x%x\n", ~val);
+
+ val = SKD_READL(skdev, FIT_CONTROL);
+ val |= FIT_CR_ENABLE_INTERRUPTS;
+ DPRINTK(skdev, "control=0x%x\n", val);
+ SKD_WRITEL(skdev, val, FIT_CONTROL);
+}
+
+/*
+ *****************************************************************************
+ * START, STOP, RESTART, QUIESCE, UNQUIESCE
+ *****************************************************************************
+ */
+
+static void skd_soft_reset(struct skd_device *skdev)
+{
+ u32 val;
+
+ val = SKD_READL(skdev, FIT_CONTROL);
+ val |= (FIT_CR_SOFT_RESET);
+ DPRINTK(skdev, "control=0x%x\n", val);
+ SKD_WRITEL(skdev, val, FIT_CONTROL);
+}
+
+static void skd_start_device(struct skd_device *skdev)
+{
+ unsigned long flags;
+ u32 sense;
+ u32 state;
+
+ spin_lock_irqsave(&skdev->lock, flags);
+
+ /* ack all ghost interrupts */
+ SKD_WRITEL(skdev, FIT_INT_DEF_MASK, FIT_INT_STATUS_HOST);
+
+ sense = SKD_READL(skdev, FIT_STATUS);
+
+ DPRINTK(skdev, "initial status=0x%x\n", sense);
+
+ state = sense & FIT_SR_DRIVE_STATE_MASK;
+ skdev->drive_state = state;
+ skdev->last_mtd = 0;
+
+ skdev->state = SKD_DRVR_STATE_STARTING;
+ skdev->timer_countdown = SKD_STARTING_TIMO;
+
+ skd_enable_interrupts(skdev);
+
+ switch (skdev->drive_state) {
+ case FIT_SR_DRIVE_OFFLINE:
+ pr_err("(%s): Drive offline...\n", skd_name(skdev));
+ break;
+
+ case FIT_SR_DRIVE_FW_BOOTING:
+ VPRINTK(skdev, "FIT_SR_DRIVE_FW_BOOTING %s\n", skdev->name);
+ skdev->state = SKD_DRVR_STATE_WAIT_BOOT;
+ skdev->timer_countdown = SKD_WAIT_BOOT_TIMO;
+ break;
+
+ case FIT_SR_DRIVE_BUSY_SANITIZE:
+ pr_info("(%s): Start: BUSY_SANITIZE\n",
+ skd_name(skdev));
+ skdev->state = SKD_DRVR_STATE_BUSY_SANITIZE;
+ skdev->timer_countdown = SKD_STARTED_BUSY_TIMO;
+ break;
+
+ case FIT_SR_DRIVE_BUSY_ERASE:
+ pr_info("(%s): Start: BUSY_ERASE\n", skd_name(skdev));
+ skdev->state = SKD_DRVR_STATE_BUSY_ERASE;
+ skdev->timer_countdown = SKD_STARTED_BUSY_TIMO;
+ break;
+
+ case FIT_SR_DRIVE_INIT:
+ case FIT_SR_DRIVE_ONLINE:
+ skd_soft_reset(skdev);
+ break;
+
+ case FIT_SR_DRIVE_BUSY:
+ pr_err("(%s): Drive Busy...\n", skd_name(skdev));
+ skdev->state = SKD_DRVR_STATE_BUSY;
+ skdev->timer_countdown = SKD_STARTED_BUSY_TIMO;
+ break;
+
+ case FIT_SR_DRIVE_SOFT_RESET:
+ pr_err("(%s) drive soft reset in prog\n",
+ skd_name(skdev));
+ break;
+
+ case FIT_SR_DRIVE_FAULT:
+ /* Fault state is bad...soft reset won't do it...
+ * Hard reset, maybe, but does it work on device?
+ * For now, just fault so the system doesn't hang.
+ */
+ skd_drive_fault(skdev);
+ /*start the queue so we can respond with error to requests */
+ VPRINTK(skdev, "starting %s queue\n", skdev->name);
+ skd_start_queue(skdev);
+ skdev->gendisk_on = -1;
+ wake_up_interruptible(&skdev->waitq);
+ break;
+
+ case 0xFF:
+ /* Most likely the device isn't there or isn't responding
+ * to the BAR1 addresses. */
+ skd_drive_disappeared(skdev);
+ /*start the queue so we can respond with error to requests */
+ VPRINTK(skdev, "starting %s queue to error-out reqs\n",
+ skdev->name);
+ skd_start_queue(skdev);
+ skdev->gendisk_on = -1;
+ wake_up_interruptible(&skdev->waitq);
+ break;
+
+ default:
+ pr_err("(%s) Start: unknown state %x\n",
+ skd_name(skdev), skdev->drive_state);
+ break;
+ }
+
+ state = SKD_READL(skdev, FIT_CONTROL);
+ DPRINTK(skdev, "FIT Control Status=0x%x\n", state);
+
+ state = SKD_READL(skdev, FIT_INT_STATUS_HOST);
+ DPRINTK(skdev, "Intr Status=0x%x\n", state);
+
+ state = SKD_READL(skdev, FIT_INT_MASK_HOST);
+ DPRINTK(skdev, "Intr Mask=0x%x\n", state);
+
+ state = SKD_READL(skdev, FIT_MSG_FROM_DEVICE);
+ DPRINTK(skdev, "Msg from Dev=0x%x\n", state);
+
+ state = SKD_READL(skdev, FIT_HW_VERSION);
+ DPRINTK(skdev, "HW version=0x%x\n", state);
+
+ spin_unlock_irqrestore(&skdev->lock, flags);
+}
+
+static void skd_stop_device(struct skd_device *skdev)
+{
+ unsigned long flags;
+ struct skd_special_context *skspcl = &skdev->internal_skspcl;
+ u32 dev_state;
+ int i;
+
+ spin_lock_irqsave(&skdev->lock, flags);
+
+ if (skdev->state != SKD_DRVR_STATE_ONLINE) {
+ pr_err("(%s): skd_stop_device not online no sync\n",
+ skd_name(skdev));
+ goto stop_out;
+ }
+
+ if (skspcl->req.state != SKD_REQ_STATE_IDLE) {
+ pr_err("(%s): skd_stop_device no special\n",
+ skd_name(skdev));
+ goto stop_out;
+ }
+
+ skdev->state = SKD_DRVR_STATE_SYNCING;
+ skdev->sync_done = 0;
+
+ skd_send_internal_skspcl(skdev, skspcl, SYNCHRONIZE_CACHE);
+
+ spin_unlock_irqrestore(&skdev->lock, flags);
+
+ wait_event_interruptible_timeout(skdev->waitq,
+ (skdev->sync_done), (10 * HZ));
+
+ spin_lock_irqsave(&skdev->lock, flags);
+
+ switch (skdev->sync_done) {
+ case 0:
+ pr_err("(%s): skd_stop_device no sync\n",
+ skd_name(skdev));
+ break;
+ case 1:
+ pr_err("(%s): skd_stop_device sync done\n",
+ skd_name(skdev));
+ break;
+ default:
+ pr_err("(%s): skd_stop_device sync error\n",
+ skd_name(skdev));
+ }
+
+stop_out:
+ skdev->state = SKD_DRVR_STATE_STOPPING;
+ spin_unlock_irqrestore(&skdev->lock, flags);
+
+ skd_kill_timer(skdev);
+
+ spin_lock_irqsave(&skdev->lock, flags);
+ skd_disable_interrupts(skdev);
+
+ /* ensure all ints on device are cleared */
+ /* soft reset the device to unload with a clean slate */
+ SKD_WRITEL(skdev, FIT_INT_DEF_MASK, FIT_INT_STATUS_HOST);
+ SKD_WRITEL(skdev, FIT_CR_SOFT_RESET, FIT_CONTROL);
+
+ spin_unlock_irqrestore(&skdev->lock, flags);
+
+ /* poll every 100ms, 1 second timeout */
+ for (i = 0; i < 10; i++) {
+ dev_state =
+ SKD_READL(skdev, FIT_STATUS) & FIT_SR_DRIVE_STATE_MASK;
+ if (dev_state == FIT_SR_DRIVE_INIT)
+ break;
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(msecs_to_jiffies(100));
+ }
+
+ if (dev_state != FIT_SR_DRIVE_INIT)
+ pr_err("(%s): skd_stop_device state error 0x%02x\n",
+ skd_name(skdev), dev_state);
+}
+
+/* assume spinlock is held */
+static void skd_restart_device(struct skd_device *skdev)
+{
+ u32 state;
+
+ /* ack all ghost interrupts */
+ SKD_WRITEL(skdev, FIT_INT_DEF_MASK, FIT_INT_STATUS_HOST);
+
+ state = SKD_READL(skdev, FIT_STATUS);
+
+ DPRINTK(skdev, "drive status=0x%x\n", state);
+
+ state &= FIT_SR_DRIVE_STATE_MASK;
+ skdev->drive_state = state;
+ skdev->last_mtd = 0;
+
+ skdev->state = SKD_DRVR_STATE_RESTARTING;
+ skdev->timer_countdown = SKD_RESTARTING_TIMO;
+
+ skd_soft_reset(skdev);
+}
+
+/* assume spinlock is held */
+static int skd_quiesce_dev(struct skd_device *skdev)
+{
+ int rc = 0;
+
+ switch (skdev->state) {
+ case SKD_DRVR_STATE_BUSY:
+ case SKD_DRVR_STATE_BUSY_IMMINENT:
+ VPRINTK(skdev, "stopping %s queue\n", skdev->name);
+ skd_stop_queue(skdev);
+ break;
+ case SKD_DRVR_STATE_ONLINE:
+ case SKD_DRVR_STATE_STOPPING:
+ case SKD_DRVR_STATE_SYNCING:
+ case SKD_DRVR_STATE_PAUSING:
+ case SKD_DRVR_STATE_PAUSED:
+ case SKD_DRVR_STATE_STARTING:
+ case SKD_DRVR_STATE_RESTARTING:
+ case SKD_DRVR_STATE_RESUMING:
+ default:
+ rc = -EINVAL;
+ VPRINTK(skdev, "state [%d] not implemented\n", skdev->state);
+ }
+ return rc;
+}
+
+/* assume spinlock is held */
+static int skd_unquiesce_dev(struct skd_device *skdev)
+{
+ int prev_driver_state = skdev->state;
+
+ skd_log_skdev(skdev, "unquiesce");
+ if (skdev->state == SKD_DRVR_STATE_ONLINE) {
+ DPRINTK(skdev, "**** device already ONLINE\n");
+ return 0;
+ }
+ if (skdev->drive_state != FIT_SR_DRIVE_ONLINE) {
+ /*
+ * If there has been an state change to other than
+ * ONLINE, we will rely on controller state change
+ * to come back online and restart the queue.
+ * The BUSY state means that driver is ready to
+ * continue normal processing but waiting for controller
+ * to become available.
+ */
+ skdev->state = SKD_DRVR_STATE_BUSY;
+ DPRINTK(skdev, "drive BUSY state\n");
+ return 0;
+ }
+
+ /*
+ * Drive has just come online, driver is either in startup,
+ * paused performing a task, or bust waiting for hardware.
+ */
+ switch (skdev->state) {
+ case SKD_DRVR_STATE_PAUSED:
+ case SKD_DRVR_STATE_BUSY:
+ case SKD_DRVR_STATE_BUSY_IMMINENT:
+ case SKD_DRVR_STATE_BUSY_ERASE:
+ case SKD_DRVR_STATE_STARTING:
+ case SKD_DRVR_STATE_RESTARTING:
+ case SKD_DRVR_STATE_FAULT:
+ case SKD_DRVR_STATE_IDLE:
+ case SKD_DRVR_STATE_LOAD:
+ skdev->state = SKD_DRVR_STATE_ONLINE;
+ pr_err("(%s): Driver state %s(%d)=>%s(%d)\n",
+ skd_name(skdev),
+ skd_skdev_state_to_str(prev_driver_state),
+ prev_driver_state, skd_skdev_state_to_str(skdev->state),
+ skdev->state);
+ DPRINTK(skdev, "**** device ONLINE...starting block queue\n");
+ VPRINTK(skdev, "starting %s queue\n", skdev->name);
+ pr_info("(%s): STEC s1120 ONLINE\n", skd_name(skdev));
+ skd_start_queue(skdev);
+ skdev->gendisk_on = 1;
+ wake_up_interruptible(&skdev->waitq);
+ break;
+
+ case SKD_DRVR_STATE_DISAPPEARED:
+ default:
+ DPRINTK(skdev, "**** driver state %d, not implemented \n",
+ skdev->state);
+ return -EBUSY;
+ }
+ return 0;
+}
+
+/*
+ *****************************************************************************
+ * PCIe MSI/MSI-X INTERRUPT HANDLERS
+ *****************************************************************************
+ */
+
+static irqreturn_t skd_reserved_isr(int irq, void *skd_host_data)
+{
+ struct skd_device *skdev = skd_host_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&skdev->lock, flags);
+ VPRINTK(skdev, "MSIX = 0x%x\n", SKD_READL(skdev, FIT_INT_STATUS_HOST));
+ pr_err("(%s): MSIX reserved irq %d = 0x%x\n", skd_name(skdev),
+ irq, SKD_READL(skdev, FIT_INT_STATUS_HOST));
+ SKD_WRITEL(skdev, FIT_INT_RESERVED_MASK, FIT_INT_STATUS_HOST);
+ spin_unlock_irqrestore(&skdev->lock, flags);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t skd_statec_isr(int irq, void *skd_host_data)
+{
+ struct skd_device *skdev = skd_host_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&skdev->lock, flags);
+ VPRINTK(skdev, "MSIX = 0x%x\n", SKD_READL(skdev, FIT_INT_STATUS_HOST));
+ SKD_WRITEL(skdev, FIT_ISH_FW_STATE_CHANGE, FIT_INT_STATUS_HOST);
+ skd_isr_fwstate(skdev);
+ spin_unlock_irqrestore(&skdev->lock, flags);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t skd_comp_q(int irq, void *skd_host_data)
+{
+ struct skd_device *skdev = skd_host_data;
+ unsigned long flags;
+ int flush_enqueued = 0;
+ int deferred;
+
+ spin_lock_irqsave(&skdev->lock, flags);
+ VPRINTK(skdev, "MSIX = 0x%x\n", SKD_READL(skdev, FIT_INT_STATUS_HOST));
+ SKD_WRITEL(skdev, FIT_ISH_COMPLETION_POSTED, FIT_INT_STATUS_HOST);
+ deferred = skd_isr_completion_posted(skdev, skd_isr_comp_limit,
+ &flush_enqueued);
+
+ if (flush_enqueued)
+ skd_request_fn(skdev->queue);
+
+ if (deferred)
+ schedule_work(&skdev->completion_worker);
+ else if (!flush_enqueued)
+ skd_request_fn(skdev->queue);
+
+ spin_unlock_irqrestore(&skdev->lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t skd_msg_isr(int irq, void *skd_host_data)
+{
+ struct skd_device *skdev = skd_host_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&skdev->lock, flags);
+ VPRINTK(skdev, "MSIX = 0x%x\n", SKD_READL(skdev, FIT_INT_STATUS_HOST));
+ SKD_WRITEL(skdev, FIT_ISH_MSG_FROM_DEV, FIT_INT_STATUS_HOST);
+ skd_isr_msg_from_dev(skdev);
+ spin_unlock_irqrestore(&skdev->lock, flags);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t skd_qfull_isr(int irq, void *skd_host_data)
+{
+ struct skd_device *skdev = skd_host_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&skdev->lock, flags);
+ VPRINTK(skdev, "MSIX = 0x%x\n", SKD_READL(skdev, FIT_INT_STATUS_HOST));
+ SKD_WRITEL(skdev, FIT_INT_QUEUE_FULL, FIT_INT_STATUS_HOST);
+ spin_unlock_irqrestore(&skdev->lock, flags);
+ return IRQ_HANDLED;
+}
+
+/*
+ *****************************************************************************
+ * PCIe MSI/MSI-X SETUP
+ *****************************************************************************
+ */
+
+struct skd_msix_entry {
+ int have_irq;
+ u32 vector;
+ u32 entry;
+ struct skd_device *rsp;
+ char isr_name[30];
+};
+
+struct skd_init_msix_entry {
+ const char *name;
+ irq_handler_t handler;
+};
+
+#define SKD_MAX_MSIX_COUNT 13
+#define SKD_MIN_MSIX_COUNT 7
+#define SKD_BASE_MSIX_IRQ 4
+
+static struct skd_init_msix_entry msix_entries[SKD_MAX_MSIX_COUNT] = {
+ { "(DMA 0)", skd_reserved_isr },
+ { "(DMA 1)", skd_reserved_isr },
+ { "(DMA 2)", skd_reserved_isr },
+ { "(DMA 3)", skd_reserved_isr },
+ { "(State Change)", skd_statec_isr },
+ { "(COMPL_Q)", skd_comp_q },
+ { "(MSG)", skd_msg_isr },
+ { "(Reserved)", skd_reserved_isr },
+ { "(Reserved)", skd_reserved_isr },
+ { "(Queue Full 0)", skd_qfull_isr },
+ { "(Queue Full 1)", skd_qfull_isr },
+ { "(Queue Full 2)", skd_qfull_isr },
+ { "(Queue Full 3)", skd_qfull_isr },
+};
+
+static void skd_release_msix(struct skd_device *skdev)
+{
+ struct skd_msix_entry *qentry;
+ int i;
+
+ if (skdev->msix_entries == NULL)
+ return;
+ for (i = 0; i < skdev->msix_count; i++) {
+ qentry = &skdev->msix_entries[i];
+ skdev = qentry->rsp;
+
+ if (qentry->have_irq)
+ devm_free_irq(&skdev->pdev->dev,
+ qentry->vector, qentry->rsp);
+ }
+ pci_disable_msix(skdev->pdev);
+ kfree(skdev->msix_entries);
+ skdev->msix_count = 0;
+ skdev->msix_entries = NULL;
+}
+
+static int skd_acquire_msix(struct skd_device *skdev)
+{
+ int i, rc;
+ struct pci_dev *pdev;
+ struct msix_entry *entries = NULL;
+ struct skd_msix_entry *qentry;
+
+ pdev = skdev->pdev;
+ skdev->msix_count = SKD_MAX_MSIX_COUNT;
+ entries = kzalloc(sizeof(struct msix_entry) * SKD_MAX_MSIX_COUNT,
+ GFP_KERNEL);
+ if (!entries)
+ return -ENOMEM;
+
+ for (i = 0; i < SKD_MAX_MSIX_COUNT; i++)
+ entries[i].entry = i;
+
+ rc = pci_enable_msix(pdev, entries, SKD_MAX_MSIX_COUNT);
+ if (rc < 0)
+ goto msix_out;
+ if (rc) {
+ if (rc < SKD_MIN_MSIX_COUNT) {
+ pr_err("(%s): failed to enable MSI-X %d\n",
+ skd_name(skdev), rc);
+ goto msix_out;
+ }
+ DPRINTK(skdev, "%s: <%s> allocated %d MSI-X vectors\n",
+ pci_name(pdev), skdev->name, rc);
+
+ skdev->msix_count = rc;
+ rc = pci_enable_msix(pdev, entries, skdev->msix_count);
+ if (rc) {
+ pr_err("(%s): failed to enable MSI-X "
+ "support (%d) %d\n",
+ skd_name(skdev), skdev->msix_count, rc);
+ goto msix_out;
+ }
+ }
+ skdev->msix_entries = kzalloc(sizeof(struct skd_msix_entry) *
+ skdev->msix_count, GFP_KERNEL);
+ if (!skdev->msix_entries) {
+ rc = -ENOMEM;
+ skdev->msix_count = 0;
+ pr_err("(%s): msix table allocation error\n",
+ skd_name(skdev));
+ goto msix_out;
+ }
+
+ qentry = skdev->msix_entries;
+ for (i = 0; i < skdev->msix_count; i++) {
+ qentry->vector = entries[i].vector;
+ qentry->entry = entries[i].entry;
+ qentry->rsp = NULL;
+ qentry->have_irq = 0;
+ DPRINTK(skdev, "%s: <%s> msix (%d) vec %d, entry %x\n",
+ pci_name(pdev), skdev->name,
+ i, qentry->vector, qentry->entry);
+ qentry++;
+ }
+
+ /* Enable MSI-X vectors for the base queue */
+ for (i = 0; i < SKD_MAX_MSIX_COUNT; i++) {
+ qentry = &skdev->msix_entries[i];
+ snprintf(qentry->isr_name, sizeof(qentry->isr_name),
+ "%s%d-msix %s", DRV_NAME, skdev->devno,
+ msix_entries[i].name);
+ rc = devm_request_irq(&skdev->pdev->dev, qentry->vector,
+ msix_entries[i].handler, 0,
+ qentry->isr_name, skdev);
+ if (rc) {
+ pr_err("(%s): Unable to register(%d) MSI-X "
+ "handler %d: %s\n",
+ skd_name(skdev), rc, i, qentry->isr_name);
+ goto msix_out;
+ } else {
+ qentry->have_irq = 1;
+ qentry->rsp = skdev;
+ }
+ }
+ DPRINTK(skdev, "%s: <%s> msix %d irq(s) enabled\n",
+ pci_name(pdev), skdev->name, skdev->msix_count);
+ return 0;
+
+msix_out:
+ if (entries)
+ kfree(entries);
+ skd_release_msix(skdev);
+ return rc;
+}
+
+static int skd_acquire_irq(struct skd_device *skdev)
+{
+ int rc;
+ struct pci_dev *pdev;
+
+ pdev = skdev->pdev;
+ skdev->msix_count = 0;
+
+RETRY_IRQ_TYPE:
+ switch (skdev->irq_type) {
+ case SKD_IRQ_MSIX:
+ rc = skd_acquire_msix(skdev);
+ if (!rc)
+ pr_info("(%s): MSI-X %d irqs enabled\n",
+ skd_name(skdev), skdev->msix_count);
+ else {
+ pr_err(
+ "(%s): failed to enable MSI-X, re-trying with MSI %d\n",
+ skd_name(skdev), rc);
+ skdev->irq_type = SKD_IRQ_MSI;
+ goto RETRY_IRQ_TYPE;
+ }
+ break;
+ case SKD_IRQ_MSI:
+ snprintf(skdev->isr_name, sizeof(skdev->isr_name), "%s%d-msi",
+ DRV_NAME, skdev->devno);
+ rc = pci_enable_msi(pdev);
+ if (!rc) {
+ rc = devm_request_irq(&pdev->dev, pdev->irq, skd_isr, 0,
+ skdev->isr_name, skdev);
+ if (rc) {
+ pci_disable_msi(pdev);
+ pr_err(
+ "(%s): failed to allocate the MSI interrupt %d\n",
+ skd_name(skdev), rc);
+ goto RETRY_IRQ_LEGACY;
+ }
+ pr_info("(%s): MSI irq %d enabled\n",
+ skd_name(skdev), pdev->irq);
+ } else {
+RETRY_IRQ_LEGACY:
+ pr_err(
+ "(%s): failed to enable MSI, re-trying with LEGACY %d\n",
+ skd_name(skdev), rc);
+ skdev->irq_type = SKD_IRQ_LEGACY;
+ goto RETRY_IRQ_TYPE;
+ }
+ break;
+ case SKD_IRQ_LEGACY:
+ snprintf(skdev->isr_name, sizeof(skdev->isr_name),
+ "%s%d-legacy", DRV_NAME, skdev->devno);
+ rc = devm_request_irq(&pdev->dev, pdev->irq, skd_isr,
+ IRQF_SHARED, skdev->isr_name, skdev);
+ if (!rc)
+ pr_info("(%s): LEGACY irq %d enabled\n",
+ skd_name(skdev), pdev->irq);
+ else
+ pr_err("(%s): request LEGACY irq error %d\n",
+ skd_name(skdev), rc);
+ break;
+ default:
+ pr_info("(%s): irq_type %d invalid, re-set to %d\n",
+ skd_name(skdev), skdev->irq_type, SKD_IRQ_DEFAULT);
+ skdev->irq_type = SKD_IRQ_LEGACY;
+ goto RETRY_IRQ_TYPE;
+ }
+ return rc;
+}
+
+static void skd_release_irq(struct skd_device *skdev)
+{
+ switch (skdev->irq_type) {
+ case SKD_IRQ_MSIX:
+ skd_release_msix(skdev);
+ break;
+ case SKD_IRQ_MSI:
+ devm_free_irq(&skdev->pdev->dev, skdev->pdev->irq, skdev);
+ pci_disable_msi(skdev->pdev);
+ break;
+ case SKD_IRQ_LEGACY:
+ devm_free_irq(&skdev->pdev->dev, skdev->pdev->irq, skdev);
+ break;
+ default:
+ pr_err("(%s): wrong irq type %d!",
+ skd_name(skdev), skdev->irq_type);
+ break;
+ }
+}
+
+/*
+ *****************************************************************************
+ * CONSTRUCT
+ *****************************************************************************
+ */
+
+static int skd_cons_skcomp(struct skd_device *skdev);
+static int skd_cons_skmsg(struct skd_device *skdev);
+static int skd_cons_skreq(struct skd_device *skdev);
+static int skd_cons_skspcl(struct skd_device *skdev);
+static int skd_cons_sksb(struct skd_device *skdev);
+static struct fit_sg_descriptor *skd_cons_sg_list(struct skd_device *skdev,
+ u32 n_sg,
+ dma_addr_t *ret_dma_addr);
+static int skd_cons_disk(struct skd_device *skdev);
+
+#define SKD_N_DEV_TABLE 16u
+static u32 skd_next_devno;
+
+static struct skd_device *skd_construct(struct pci_dev *pdev)
+{
+ struct skd_device *skdev;
+ int blk_major = skd_major;
+ int rc;
+
+ skdev = kzalloc(sizeof(*skdev), GFP_KERNEL);
+
+ if (!skdev) {
+ pr_err(PFX "(%s): memory alloc failure\n",
+ pci_name(pdev));
+ return NULL;
+ }
+
+ skdev->state = SKD_DRVR_STATE_LOAD;
+ skdev->pdev = pdev;
+ skdev->devno = skd_next_devno++;
+ skdev->major = blk_major;
+ skdev->irq_type = skd_isr_type;
+ sprintf(skdev->name, DRV_NAME "%d", skdev->devno);
+ skdev->dev_max_queue_depth = 0;
+
+ skdev->num_req_context = skd_max_queue_depth;
+ skdev->num_fitmsg_context = skd_max_queue_depth;
+ skdev->n_special = skd_max_pass_thru;
+ skdev->cur_max_queue_depth = 1;
+ skdev->queue_low_water_mark = 1;
+ skdev->proto_ver = 99;
+ skdev->sgs_per_request = skd_sgs_per_request;
+ skdev->dbg_level = skd_dbg_level;
+
+ if (skd_bio)
+ bio_list_init(&skdev->bio_queue);
+
+
+ atomic_set(&skdev->device_count, 0);
+
+ spin_lock_init(&skdev->lock);
+
+ INIT_WORK(&skdev->completion_worker, skd_completion_worker);
+ INIT_LIST_HEAD(&skdev->flush_list);
+
+ VPRINTK(skdev, "skcomp\n");
+ rc = skd_cons_skcomp(skdev);
+ if (rc < 0)
+ goto err_out;
+
+ VPRINTK(skdev, "skmsg\n");
+ rc = skd_cons_skmsg(skdev);
+ if (rc < 0)
+ goto err_out;
+
+ VPRINTK(skdev, "skreq\n");
+ rc = skd_cons_skreq(skdev);
+ if (rc < 0)
+ goto err_out;
+
+ VPRINTK(skdev, "skspcl\n");
+ rc = skd_cons_skspcl(skdev);
+ if (rc < 0)
+ goto err_out;
+
+ VPRINTK(skdev, "sksb\n");
+ rc = skd_cons_sksb(skdev);
+ if (rc < 0)
+ goto err_out;
+
+ VPRINTK(skdev, "disk\n");
+ rc = skd_cons_disk(skdev);
+ if (rc < 0)
+ goto err_out;
+
+
+
+ DPRINTK(skdev, "VICTORY\n");
+ return skdev;
+
+err_out:
+ DPRINTK(skdev, "construct failed\n");
+ skd_destruct(skdev);
+ return NULL;
+}
+
+static int skd_cons_skcomp(struct skd_device *skdev)
+{
+ int rc = 0;
+ struct fit_completion_entry_v1 *skcomp;
+ u32 nbytes;
+
+ nbytes = sizeof(*skcomp) * SKD_N_COMPLETION_ENTRY;
+ nbytes += sizeof(struct fit_comp_error_info) * SKD_N_COMPLETION_ENTRY;
+
+ VPRINTK(skdev, "comp pci_alloc, total bytes %d entries %d\n", nbytes,
+ SKD_N_COMPLETION_ENTRY);
+
+ skcomp = pci_alloc_consistent(skdev->pdev, nbytes,
+ &skdev->cq_dma_address);
+
+ if (skcomp == NULL) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ memset(skcomp, 0, nbytes);
+
+ skdev->skcomp_table = skcomp;
+ skdev->skerr_table = (struct fit_comp_error_info *)((char *)skcomp +
+ sizeof(*skcomp) *
+ SKD_N_COMPLETION_ENTRY);
+
+err_out:
+ return rc;
+}
+
+static int skd_cons_skmsg(struct skd_device *skdev)
+{
+ int rc = 0;
+ u32 i;
+
+ VPRINTK(skdev, "skmsg_table kzalloc, struct %u, count %u total %lu\n",
+ sizeof(struct skd_fitmsg_context),
+ skdev->num_fitmsg_context,
+ (unsigned long) sizeof(struct skd_fitmsg_context) *
+ skdev->num_fitmsg_context);
+
+ skdev->skmsg_table = kzalloc(sizeof(struct skd_fitmsg_context)
+ *skdev->num_fitmsg_context, GFP_KERNEL);
+ if (skdev->skmsg_table == NULL) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ for (i = 0; i < skdev->num_fitmsg_context; i++) {
+ struct skd_fitmsg_context *skmsg;
+
+ skmsg = &skdev->skmsg_table[i];
+
+ skmsg->id = i + SKD_ID_FIT_MSG;
+
+ skmsg->state = SKD_MSG_STATE_IDLE;
+ skmsg->msg_buf = pci_alloc_consistent(skdev->pdev,
+ SKD_N_FITMSG_BYTES + 64,
+ &skmsg->mb_dma_address);
+
+ if (skmsg->msg_buf == NULL) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ skmsg->offset = (u32)((u64)skmsg->msg_buf &
+ (~FIT_QCMD_BASE_ADDRESS_MASK));
+ skmsg->msg_buf += ~FIT_QCMD_BASE_ADDRESS_MASK;
+ skmsg->msg_buf = (u8 *)((u64)skmsg->msg_buf &
+ FIT_QCMD_BASE_ADDRESS_MASK);
+ skmsg->mb_dma_address += ~FIT_QCMD_BASE_ADDRESS_MASK;
+ skmsg->mb_dma_address &= FIT_QCMD_BASE_ADDRESS_MASK;
+ memset(skmsg->msg_buf, 0, SKD_N_FITMSG_BYTES);
+
+ skmsg->next = &skmsg[1];
+ }
+
+ /* Free list is in order starting with the 0th entry. */
+ skdev->skmsg_table[i - 1].next = NULL;
+ skdev->skmsg_free_list = skdev->skmsg_table;
+
+err_out:
+ return rc;
+}
+
+static int skd_cons_skreq(struct skd_device *skdev)
+{
+ int rc = 0;
+ u32 i;
+
+ VPRINTK(skdev, "skreq_table kzalloc, struct %u, count %u total %u\n",
+ sizeof(struct skd_request_context),
+ skdev->num_req_context,
+ sizeof(struct skd_request_context) * skdev->num_req_context);
+
+ skdev->skreq_table = kzalloc(sizeof(struct skd_request_context)
+ * skdev->num_req_context, GFP_KERNEL);
+ if (skdev->skreq_table == NULL) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ VPRINTK(skdev, "alloc sg_table sg_per_req %u scatlist %u total %u\n",
+ skdev->sgs_per_request, sizeof(struct scatterlist),
+ skdev->sgs_per_request * sizeof(struct scatterlist));
+
+ for (i = 0; i < skdev->num_req_context; i++) {
+ struct skd_request_context *skreq;
+
+ skreq = &skdev->skreq_table[i];
+
+ skreq->id = i + SKD_ID_RW_REQUEST;
+ skreq->state = SKD_REQ_STATE_IDLE;
+
+ skreq->sg = kzalloc(sizeof(struct scatterlist) *
+ skdev->sgs_per_request, GFP_KERNEL);
+ if (skreq->sg == NULL) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+ sg_init_table(skreq->sg, skdev->sgs_per_request);
+
+ skreq->sksg_list = skd_cons_sg_list(skdev,
+ skdev->sgs_per_request,
+ &skreq->sksg_dma_address);
+
+ if (skreq->sksg_list == NULL) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ skreq->next = &skreq[1];
+ }
+
+ /* Free list is in order starting with the 0th entry. */
+ skdev->skreq_table[i - 1].next = NULL;
+ skdev->skreq_free_list = skdev->skreq_table;
+
+err_out:
+ return rc;
+}
+
+static int skd_cons_skspcl(struct skd_device *skdev)
+{
+ int rc = 0;
+ u32 i, nbytes;
+
+ VPRINTK(skdev, "skspcl_table kzalloc, struct %u, count %u total %u\n",
+ sizeof(struct skd_special_context),
+ skdev->n_special,
+ sizeof(struct skd_special_context) * skdev->n_special);
+
+ skdev->skspcl_table = kzalloc(sizeof(struct skd_special_context)
+ * skdev->n_special, GFP_KERNEL);
+ if (skdev->skspcl_table == NULL) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ for (i = 0; i < skdev->n_special; i++) {
+ struct skd_special_context *skspcl;
+
+ skspcl = &skdev->skspcl_table[i];
+
+ skspcl->req.id = i + SKD_ID_SPECIAL_REQUEST;
+ skspcl->req.state = SKD_REQ_STATE_IDLE;
+
+ skspcl->req.next = &skspcl[1].req;
+
+ nbytes = SKD_N_SPECIAL_FITMSG_BYTES;
+
+ skspcl->msg_buf = pci_alloc_consistent(skdev->pdev, nbytes,
+ &skspcl->mb_dma_address);
+ if (skspcl->msg_buf == NULL) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ memset(skspcl->msg_buf, 0, nbytes);
+
+ skspcl->req.sg = kzalloc(sizeof(struct scatterlist) *
+ SKD_N_SG_PER_SPECIAL, GFP_KERNEL);
+ if (skspcl->req.sg == NULL) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ skspcl->req.sksg_list = skd_cons_sg_list(skdev,
+ SKD_N_SG_PER_SPECIAL,
+ &skspcl->req.
+ sksg_dma_address);
+ if (skspcl->req.sksg_list == NULL) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+ }
+
+ /* Free list is in order starting with the 0th entry. */
+ skdev->skspcl_table[i - 1].req.next = NULL;
+ skdev->skspcl_free_list = skdev->skspcl_table;
+
+ return rc;
+
+err_out:
+ return rc;
+}
+
+static int skd_cons_sksb(struct skd_device *skdev)
+{
+ int rc = 0;
+ struct skd_special_context *skspcl;
+ u32 nbytes;
+
+ skspcl = &skdev->internal_skspcl;
+
+ skspcl->req.id = 0 + SKD_ID_INTERNAL;
+ skspcl->req.state = SKD_REQ_STATE_IDLE;
+
+ nbytes = SKD_N_INTERNAL_BYTES;
+
+ skspcl->data_buf = pci_alloc_consistent(skdev->pdev, nbytes,
+ &skspcl->db_dma_address);
+ if (skspcl->data_buf == NULL) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ memset(skspcl->data_buf, 0, nbytes);
+
+ nbytes = SKD_N_SPECIAL_FITMSG_BYTES;
+ skspcl->msg_buf = pci_alloc_consistent(skdev->pdev, nbytes,
+ &skspcl->mb_dma_address);
+ if (skspcl->msg_buf == NULL) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ memset(skspcl->msg_buf, 0, nbytes);
+
+ skspcl->req.sksg_list = skd_cons_sg_list(skdev, 1,
+ &skspcl->req.sksg_dma_address);
+ if (skspcl->req.sksg_list == NULL) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ if (!skd_format_internal_skspcl(skdev)) {
+ rc = -EINVAL;
+ goto err_out;
+ }
+
+err_out:
+ return rc;
+}
+
+static struct fit_sg_descriptor *skd_cons_sg_list(struct skd_device *skdev,
+ u32 n_sg,
+ dma_addr_t *ret_dma_addr)
+{
+ struct fit_sg_descriptor *sg_list;
+ u32 nbytes;
+
+ nbytes = sizeof(*sg_list) * n_sg;
+
+ sg_list = pci_alloc_consistent(skdev->pdev, nbytes, ret_dma_addr);
+
+ if (sg_list != NULL) {
+ uint64_t dma_address = *ret_dma_addr;
+ u32 i;
+
+ memset(sg_list, 0, nbytes);
+
+ for (i = 0; i < n_sg - 1; i++) {
+ uint64_t ndp_off;
+ ndp_off = (i + 1) * sizeof(struct fit_sg_descriptor);
+
+ sg_list[i].next_desc_ptr = dma_address + ndp_off;
+ }
+ sg_list[i].next_desc_ptr = 0LL;
+ }
+
+ return sg_list;
+}
+
+static int skd_cons_disk(struct skd_device *skdev)
+{
+ int rc = 0;
+ struct gendisk *disk;
+ struct request_queue *q;
+ unsigned long flags;
+
+ disk = alloc_disk(SKD_MINORS_PER_DEVICE);
+ if (!disk) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ skdev->disk = disk;
+ sprintf(disk->disk_name, DRV_NAME "%u", skdev->devno);
+
+ disk->major = skdev->major;
+ disk->first_minor = skdev->devno * SKD_MINORS_PER_DEVICE;
+ disk->fops = &skd_blockdev_ops;
+ disk->private_data = skdev;
+
+ if (!skd_bio) {
+ q = blk_init_queue(skd_request_fn, &skdev->lock);
+ } else {
+ q = blk_alloc_queue(GFP_KERNEL);
+ q->queue_flags = QUEUE_FLAG_IO_STAT | QUEUE_FLAG_STACKABLE;
+ }
+
+ if (!q) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ skdev->queue = q;
+ disk->queue = q;
+ q->queuedata = skdev;
+
+ if (skd_bio) {
+ q->queue_lock = &skdev->lock;
+ blk_queue_make_request(q, skd_make_request);
+ }
+
+ blk_queue_flush(q, REQ_FLUSH | REQ_FUA);
+ blk_queue_max_segments(q, skdev->sgs_per_request);
+ blk_queue_max_hw_sectors(q, SKD_N_MAX_SECTORS);
+
+ /* set sysfs ptimal_io_size to 8K */
+ blk_queue_io_opt(q, 8192);
+
+ /* DISCARD Flag initialization. */
+ q->limits.discard_granularity = 8192;
+ q->limits.discard_alignment = 0;
+ q->limits.max_discard_sectors = UINT_MAX >> 9;
+ q->limits.discard_zeroes_data = 1;
+ queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
+ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
+
+ spin_lock_irqsave(&skdev->lock, flags);
+ VPRINTK(skdev, "stopping %s queue\n", skdev->name);
+ skd_stop_queue(skdev);
+ spin_unlock_irqrestore(&skdev->lock, flags);
+
+err_out:
+ return rc;
+}
+
+/*
+ *****************************************************************************
+ * DESTRUCT (FREE)
+ *****************************************************************************
+ */
+
+static void skd_free_skcomp(struct skd_device *skdev);
+static void skd_free_skmsg(struct skd_device *skdev);
+static void skd_free_skreq(struct skd_device *skdev);
+static void skd_free_skspcl(struct skd_device *skdev);
+static void skd_free_sksb(struct skd_device *skdev);
+static void skd_free_sg_list(struct skd_device *skdev,
+ struct fit_sg_descriptor *sg_list,
+ u32 n_sg, dma_addr_t dma_addr);
+static void skd_free_disk(struct skd_device *skdev);
+
+static void skd_destruct(struct skd_device *skdev)
+{
+ if (skdev == NULL)
+ return;
+
+
+ VPRINTK(skdev, "disk\n");
+ skd_free_disk(skdev);
+
+ VPRINTK(skdev, "sksb\n");
+ skd_free_sksb(skdev);
+
+ VPRINTK(skdev, "skspcl\n");
+ skd_free_skspcl(skdev);
+
+ VPRINTK(skdev, "skreq\n");
+ skd_free_skreq(skdev);
+
+ VPRINTK(skdev, "skmsg\n");
+ skd_free_skmsg(skdev);
+
+ VPRINTK(skdev, "skcomp\n");
+ skd_free_skcomp(skdev);
+
+ VPRINTK(skdev, "skdev\n");
+ kfree(skdev);
+}
+
+static void skd_free_skcomp(struct skd_device *skdev)
+{
+ if (skdev->skcomp_table != NULL) {
+ u32 nbytes;
+
+ nbytes = sizeof(skdev->skcomp_table[0]) *
+ SKD_N_COMPLETION_ENTRY;
+ pci_free_consistent(skdev->pdev, nbytes,
+ skdev->skcomp_table, skdev->cq_dma_address);
+ }
+
+ skdev->skcomp_table = NULL;
+ skdev->cq_dma_address = 0;
+}
+
+static void skd_free_skmsg(struct skd_device *skdev)
+{
+ u32 i;
+
+ if (skdev->skmsg_table == NULL)
+ return;
+
+ for (i = 0; i < skdev->num_fitmsg_context; i++) {
+ struct skd_fitmsg_context *skmsg;
+
+ skmsg = &skdev->skmsg_table[i];
+
+ if (skmsg->msg_buf != NULL) {
+ skmsg->msg_buf += skmsg->offset;
+ skmsg->mb_dma_address += skmsg->offset;
+ pci_free_consistent(skdev->pdev, SKD_N_FITMSG_BYTES,
+ skmsg->msg_buf,
+ skmsg->mb_dma_address);
+ }
+ skmsg->msg_buf = NULL;
+ skmsg->mb_dma_address = 0;
+ }
+
+ kfree(skdev->skmsg_table);
+ skdev->skmsg_table = NULL;
+}
+
+static void skd_free_skreq(struct skd_device *skdev)
+{
+ u32 i;
+
+ if (skdev->skreq_table == NULL)
+ return;
+
+ for (i = 0; i < skdev->num_req_context; i++) {
+ struct skd_request_context *skreq;
+
+ skreq = &skdev->skreq_table[i];
+
+ skd_free_sg_list(skdev, skreq->sksg_list,
+ skdev->sgs_per_request,
+ skreq->sksg_dma_address);
+
+ skreq->sksg_list = NULL;
+ skreq->sksg_dma_address = 0;
+
+ kfree(skreq->sg);
+ }
+
+ kfree(skdev->skreq_table);
+ skdev->skreq_table = NULL;
+}
+
+static void skd_free_skspcl(struct skd_device *skdev)
+{
+ u32 i;
+ u32 nbytes;
+
+ if (skdev->skspcl_table == NULL)
+ return;
+
+ for (i = 0; i < skdev->n_special; i++) {
+ struct skd_special_context *skspcl;
+
+ skspcl = &skdev->skspcl_table[i];
+
+ if (skspcl->msg_buf != NULL) {
+ nbytes = SKD_N_SPECIAL_FITMSG_BYTES;
+ pci_free_consistent(skdev->pdev, nbytes,
+ skspcl->msg_buf,
+ skspcl->mb_dma_address);
+ }
+
+ skspcl->msg_buf = NULL;
+ skspcl->mb_dma_address = 0;
+
+ skd_free_sg_list(skdev, skspcl->req.sksg_list,
+ SKD_N_SG_PER_SPECIAL,
+ skspcl->req.sksg_dma_address);
+
+ skspcl->req.sksg_list = NULL;
+ skspcl->req.sksg_dma_address = 0;
+
+ kfree(skspcl->req.sg);
+ }
+
+ kfree(skdev->skspcl_table);
+ skdev->skspcl_table = NULL;
+}
+
+static void skd_free_sksb(struct skd_device *skdev)
+{
+ struct skd_special_context *skspcl;
+ u32 nbytes;
+
+ skspcl = &skdev->internal_skspcl;
+
+ if (skspcl->data_buf != NULL) {
+ nbytes = SKD_N_INTERNAL_BYTES;
+
+ pci_free_consistent(skdev->pdev, nbytes,
+ skspcl->data_buf, skspcl->db_dma_address);
+ }
+
+ skspcl->data_buf = NULL;
+ skspcl->db_dma_address = 0;
+
+ if (skspcl->msg_buf != NULL) {
+ nbytes = SKD_N_SPECIAL_FITMSG_BYTES;
+ pci_free_consistent(skdev->pdev, nbytes,
+ skspcl->msg_buf, skspcl->mb_dma_address);
+ }
+
+ skspcl->msg_buf = NULL;
+ skspcl->mb_dma_address = 0;
+
+ skd_free_sg_list(skdev, skspcl->req.sksg_list, 1,
+ skspcl->req.sksg_dma_address);
+
+ skspcl->req.sksg_list = NULL;
+ skspcl->req.sksg_dma_address = 0;
+}
+
+static void skd_free_sg_list(struct skd_device *skdev,
+ struct fit_sg_descriptor *sg_list,
+ u32 n_sg, dma_addr_t dma_addr)
+{
+ if (sg_list != NULL) {
+ u32 nbytes;
+
+ nbytes = sizeof(*sg_list) * n_sg;
+
+ pci_free_consistent(skdev->pdev, nbytes, sg_list, dma_addr);
+ }
+}
+
+static void skd_free_disk(struct skd_device *skdev)
+{
+ struct gendisk *disk = skdev->disk;
+
+ if (disk != NULL) {
+ struct request_queue *q = disk->queue;
+
+ if (disk->flags & GENHD_FL_UP)
+ del_gendisk(disk);
+ if (q)
+ blk_cleanup_queue(q);
+ put_disk(disk);
+ }
+ skdev->disk = NULL;
+}
+
+
+
+/*
+ *****************************************************************************
+ * BLOCK DEVICE (BDEV) GLUE
+ *****************************************************************************
+ */
+
+static int skd_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct skd_device *skdev;
+ u64 capacity;
+
+ skdev = bdev->bd_disk->private_data;
+
+ DPRINTK(skdev, "%s: CMD[%s] getgeo device\n",
+ bdev->bd_disk->disk_name, current->comm);
+
+ if (skdev->read_cap_is_valid) {
+ capacity = get_capacity(skdev->disk);
+ geo->heads = 64;
+ geo->sectors = 255;
+ geo->cylinders = (capacity) / (255 * 64);
+
+ return 0;
+ }
+ return -EIO;
+}
+
+static int skd_bdev_attach(struct skd_device *skdev)
+{
+ DPRINTK(skdev, "add_disk\n");
+ add_disk(skdev->disk);
+ return 0;
+}
+
+static const struct block_device_operations skd_blockdev_ops = {
+ .owner = THIS_MODULE,
+ .ioctl = skd_bdev_ioctl,
+ .getgeo = skd_bdev_getgeo,
+};
+
+
+/*
+ *****************************************************************************
+ * PCIe DRIVER GLUE
+ *****************************************************************************
+ */
+
+static DEFINE_PCI_DEVICE_TABLE(skd_pci_tbl) = {
+ { PCI_VENDOR_ID_STEC, PCI_DEVICE_ID_S1120,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+ { 0 } /* terminate list */
+};
+
+MODULE_DEVICE_TABLE(pci, skd_pci_tbl);
+
+static char *skd_pci_info(struct skd_device *skdev, char *str)
+{
+ int pcie_reg;
+
+ strcpy(str, "PCIe (");
+ pcie_reg = pci_find_capability(skdev->pdev, PCI_CAP_ID_EXP);
+
+ if (pcie_reg) {
+
+ char lwstr[6];
+ uint16_t pcie_lstat, lspeed, lwidth;
+
+ pcie_reg += 0x12;
+ pci_read_config_word(skdev->pdev, pcie_reg, &pcie_lstat);
+ lspeed = pcie_lstat & (0xF);
+ lwidth = (pcie_lstat & 0x3F0) >> 4;
+
+ if (lspeed == 1)
+ strcat(str, "2.5GT/s ");
+ else if (lspeed == 2)
+ strcat(str, "5.0GT/s ");
+ else
+ strcat(str, "<unknown> ");
+ snprintf(lwstr, sizeof(lwstr), "%dX)", lwidth);
+ strcat(str, lwstr);
+ }
+ return str;
+}
+
+static int skd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ int i;
+ int rc = 0;
+ char pci_str[32];
+ struct skd_device *skdev;
+
+ pr_info("STEC s1120 Driver(%s) version %s-b%s\n",
+ DRV_NAME, DRV_VERSION, DRV_BUILD_ID);
+ pr_info("(skd?:??:[%s]): vendor=%04X device=%04x\n",
+ pci_name(pdev), pdev->vendor, pdev->device);
+
+ rc = pci_enable_device(pdev);
+ if (rc)
+ return rc;
+ rc = pci_request_regions(pdev, DRV_NAME);
+ if (rc)
+ goto err_out;
+ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+ if (!rc) {
+ if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
+
+ pr_err("(%s): consistent DMA mask error %d\n",
+ pci_name(pdev), rc);
+ }
+ } else {
+ (rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)));
+ if (rc) {
+
+ pr_err("(%s): DMA mask error %d\n",
+ pci_name(pdev), rc);
+ goto err_out_regions;
+ }
+ }
+
+ skdev = skd_construct(pdev);
+ if (skdev == NULL)
+ goto err_out_regions;
+
+ skd_pci_info(skdev, pci_str);
+ pr_info("(%s): %s 64bit\n", skd_name(skdev), pci_str);
+
+ pci_set_master(pdev);
+ rc = pci_enable_pcie_error_reporting(pdev);
+ if (rc) {
+ pr_err(
+ "(%s): bad enable of PCIe error reporting rc=%d\n",
+ skd_name(skdev), rc);
+ skdev->pcie_error_reporting_is_enabled = 0;
+ } else
+ skdev->pcie_error_reporting_is_enabled = 1;
+
+
+ pci_set_drvdata(pdev, skdev);
+ skdev->pdev = pdev;
+ skdev->disk->driverfs_dev = &pdev->dev;
+
+ for (i = 0; i < SKD_MAX_BARS; i++) {
+ skdev->mem_phys[i] = pci_resource_start(pdev, i);
+ skdev->mem_size[i] = (u32)pci_resource_len(pdev, i);
+ skdev->mem_map[i] = ioremap(skdev->mem_phys[i],
+ skdev->mem_size[i]);
+ if (!skdev->mem_map[i]) {
+ pr_err("(%s): Unable to map adapter memory!\n",
+ skd_name(skdev));
+ rc = -ENODEV;
+ goto err_out_iounmap;
+ }
+ DPRINTK(skdev, "mem_map=%p, phyd=%016llx, size=%d\n",
+ skdev->mem_map[i],
+ (uint64_t)skdev->mem_phys[i], skdev->mem_size[i]);
+ }
+
+ rc = skd_acquire_irq(skdev);
+ if (rc) {
+ pr_err("(%s): interrupt resource error %d\n",
+ skd_name(skdev), rc);
+ goto err_out_iounmap;
+ }
+
+ rc = skd_start_timer(skdev);
+ if (rc)
+ goto err_out_timer;
+
+ init_waitqueue_head(&skdev->waitq);
+
+ skd_start_device(skdev);
+
+ rc = wait_event_interruptible_timeout(skdev->waitq,
+ (skdev->gendisk_on),
+ (SKD_START_WAIT_SECONDS * HZ));
+ if (skdev->gendisk_on > 0) {
+ /* device came on-line after reset */
+ skd_bdev_attach(skdev);
+ rc = 0;
+ } else {
+ /* we timed out, something is wrong with the device,
+ don't add the disk structure */
+ pr_err(
+ "(%s): error: waiting for s1120 timed out %d!\n",
+ skd_name(skdev), rc);
+ /* in case of no error; we timeout with ENXIO */
+ if (!rc)
+ rc = -ENXIO;
+ goto err_out_timer;
+ }
+
+
+#ifdef SKD_VMK_POLL_HANDLER
+ if (skdev->irq_type == SKD_IRQ_MSIX) {
+ /* MSIX completion handler is being used for coredump */
+ vmklnx_scsi_register_poll_handler(skdev->scsi_host,
+ skdev->msix_entries[5].vector,
+ skd_comp_q, skdev);
+ } else {
+ vmklnx_scsi_register_poll_handler(skdev->scsi_host,
+ skdev->pdev->irq, skd_isr,
+ skdev);
+ }
+#endif /* SKD_VMK_POLL_HANDLER */
+
+ return rc;
+
+err_out_timer:
+ skd_stop_device(skdev);
+ skd_release_irq(skdev);
+
+err_out_iounmap:
+ for (i = 0; i < SKD_MAX_BARS; i++)
+ if (skdev->mem_map[i])
+ iounmap(skdev->mem_map[i]);
+
+ if (skdev->pcie_error_reporting_is_enabled)
+ pci_disable_pcie_error_reporting(pdev);
+
+ skd_destruct(skdev);
+
+err_out_regions:
+ pci_release_regions(pdev);
+
+err_out:
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ return rc;
+}
+
+static void skd_pci_remove(struct pci_dev *pdev)
+{
+ int i;
+ struct skd_device *skdev;
+
+ skdev = pci_get_drvdata(pdev);
+ if (!skdev) {
+ pr_err("%s: no device data for PCI\n", pci_name(pdev));
+ return;
+ }
+ skd_stop_device(skdev);
+ skd_release_irq(skdev);
+
+ for (i = 0; i < SKD_MAX_BARS; i++)
+ if (skdev->mem_map[i])
+ iounmap((u32 *)skdev->mem_map[i]);
+
+ if (skdev->pcie_error_reporting_is_enabled)
+ pci_disable_pcie_error_reporting(pdev);
+
+ skd_destruct(skdev);
+
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+
+ return;
+}
+
+static int skd_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ int i;
+ struct skd_device *skdev;
+
+ skdev = pci_get_drvdata(pdev);
+ if (!skdev) {
+ pr_err("%s: no device data for PCI\n", pci_name(pdev));
+ return -EIO;
+ }
+
+ skd_stop_device(skdev);
+
+ skd_release_irq(skdev);
+
+ for (i = 0; i < SKD_MAX_BARS; i++)
+ if (skdev->mem_map[i])
+ iounmap((u32 *)skdev->mem_map[i]);
+
+ if (skdev->pcie_error_reporting_is_enabled)
+ pci_disable_pcie_error_reporting(pdev);
+
+ pci_release_regions(pdev);
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ return 0;
+}
+
+static int skd_pci_resume(struct pci_dev *pdev)
+{
+ int i;
+ int rc = 0;
+ struct skd_device *skdev;
+
+ skdev = pci_get_drvdata(pdev);
+ if (!skdev) {
+ pr_err("%s: no device data for PCI\n", pci_name(pdev));
+ return -1;
+ }
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_enable_wake(pdev, PCI_D0, 0);
+ pci_restore_state(pdev);
+
+ rc = pci_enable_device(pdev);
+ if (rc)
+ return rc;
+ rc = pci_request_regions(pdev, DRV_NAME);
+ if (rc)
+ goto err_out;
+ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+ if (!rc) {
+ if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
+
+ pr_err("(%s): consistent DMA mask error %d\n",
+ pci_name(pdev), rc);
+ }
+ } else {
+ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (rc) {
+
+ pr_err("(%s): DMA mask error %d\n",
+ pci_name(pdev), rc);
+ goto err_out_regions;
+ }
+ }
+
+ pci_set_master(pdev);
+ rc = pci_enable_pcie_error_reporting(pdev);
+ if (rc) {
+ pr_err("(%s): bad enable of PCIe error reporting rc=%d\n",
+ skdev->name, rc);
+ skdev->pcie_error_reporting_is_enabled = 0;
+ } else
+ skdev->pcie_error_reporting_is_enabled = 1;
+
+ for (i = 0; i < SKD_MAX_BARS; i++) {
+
+ skdev->mem_phys[i] = pci_resource_start(pdev, i);
+ skdev->mem_size[i] = (u32)pci_resource_len(pdev, i);
+ skdev->mem_map[i] = ioremap(skdev->mem_phys[i],
+ skdev->mem_size[i]);
+ if (!skdev->mem_map[i]) {
+ pr_err("(%s): Unable to map adapter memory!\n",
+ skd_name(skdev));
+ rc = -ENODEV;
+ goto err_out_iounmap;
+ }
+ DPRINTK(skdev, "mem_map=%p, phyd=%016llx, size=%d\n",
+ skdev->mem_map[i],
+ (uint64_t)skdev->mem_phys[i], skdev->mem_size[i]);
+ }
+ rc = skd_acquire_irq(skdev);
+ if (rc) {
+
+ pr_err("(%s): interrupt resource error %d\n",
+ pci_name(pdev), rc);
+ goto err_out_iounmap;
+ }
+
+ rc = skd_start_timer(skdev);
+ if (rc)
+ goto err_out_timer;
+
+ init_waitqueue_head(&skdev->waitq);
+
+ skd_start_device(skdev);
+
+ return rc;
+
+err_out_timer:
+ skd_stop_device(skdev);
+ skd_release_irq(skdev);
+
+err_out_iounmap:
+ for (i = 0; i < SKD_MAX_BARS; i++)
+ if (skdev->mem_map[i])
+ iounmap(skdev->mem_map[i]);
+
+ if (skdev->pcie_error_reporting_is_enabled)
+ pci_disable_pcie_error_reporting(pdev);
+
+err_out_regions:
+ pci_release_regions(pdev);
+
+err_out:
+ pci_disable_device(pdev);
+ return rc;
+}
+
+static void skd_pci_shutdown(struct pci_dev *pdev)
+{
+ struct skd_device *skdev;
+
+ pr_err("skd_pci_shutdown called\n");
+
+ skdev = pci_get_drvdata(pdev);
+ if (!skdev) {
+ pr_err("%s: no device data for PCI\n", pci_name(pdev));
+ return;
+ }
+
+ pr_err("%s: calling stop\n", skd_name(skdev));
+ skd_stop_device(skdev);
+}
+
+static struct pci_driver skd_driver = {
+ .name = DRV_NAME,
+ .id_table = skd_pci_tbl,
+ .probe = skd_pci_probe,
+ .remove = skd_pci_remove,
+ .suspend = skd_pci_suspend,
+ .resume = skd_pci_resume,
+ .shutdown = skd_pci_shutdown,
+};
+
+/*
+ *****************************************************************************
+ * LOGGING SUPPORT
+ *****************************************************************************
+ */
+
+static const char *skd_name(struct skd_device *skdev)
+{
+ memset(skdev->id_str, 0, sizeof(skdev->id_str));
+
+ if (skdev->inquiry_is_valid)
+ snprintf(skdev->id_str, sizeof(skdev->id_str), "%s:%s:[%s]",
+ skdev->name, skdev->inq_serial_num,
+ pci_name(skdev->pdev));
+ else
+ snprintf(skdev->id_str, sizeof(skdev->id_str), "%s:??:[%s]",
+ skdev->name, pci_name(skdev->pdev));
+
+ return skdev->id_str;
+}
+
+const char *skd_drive_state_to_str(int state)
+{
+ switch (state) {
+ case FIT_SR_DRIVE_OFFLINE:
+ return "OFFLINE";
+ case FIT_SR_DRIVE_INIT:
+ return "INIT";
+ case FIT_SR_DRIVE_ONLINE:
+ return "ONLINE";
+ case FIT_SR_DRIVE_BUSY:
+ return "BUSY";
+ case FIT_SR_DRIVE_FAULT:
+ return "FAULT";
+ case FIT_SR_DRIVE_DEGRADED:
+ return "DEGRADED";
+ case FIT_SR_PCIE_LINK_DOWN:
+ return "INK_DOWN";
+ case FIT_SR_DRIVE_SOFT_RESET:
+ return "SOFT_RESET";
+ case FIT_SR_DRIVE_NEED_FW_DOWNLOAD:
+ return "NEED_FW";
+ case FIT_SR_DRIVE_INIT_FAULT:
+ return "INIT_FAULT";
+ case FIT_SR_DRIVE_BUSY_SANITIZE:
+ return "BUSY_SANITIZE";
+ case FIT_SR_DRIVE_BUSY_ERASE:
+ return "BUSY_ERASE";
+ case FIT_SR_DRIVE_FW_BOOTING:
+ return "FW_BOOTING";
+ default:
+ return "???";
+ }
+}
+
+const char *skd_skdev_state_to_str(enum skd_drvr_state state)
+{
+ switch (state) {
+ case SKD_DRVR_STATE_LOAD:
+ return "LOAD";
+ case SKD_DRVR_STATE_IDLE:
+ return "IDLE";
+ case SKD_DRVR_STATE_BUSY:
+ return "BUSY";
+ case SKD_DRVR_STATE_STARTING:
+ return "STARTING";
+ case SKD_DRVR_STATE_ONLINE:
+ return "ONLINE";
+ case SKD_DRVR_STATE_PAUSING:
+ return "PAUSING";
+ case SKD_DRVR_STATE_PAUSED:
+ return "PAUSED";
+ case SKD_DRVR_STATE_DRAINING_TIMEOUT:
+ return "DRAINING_TIMEOUT";
+ case SKD_DRVR_STATE_RESTARTING:
+ return "RESTARTING";
+ case SKD_DRVR_STATE_RESUMING:
+ return "RESUMING";
+ case SKD_DRVR_STATE_STOPPING:
+ return "STOPPING";
+ case SKD_DRVR_STATE_SYNCING:
+ return "SYNCING";
+ case SKD_DRVR_STATE_FAULT:
+ return "FAULT";
+ case SKD_DRVR_STATE_DISAPPEARED:
+ return "DISAPPEARED";
+ case SKD_DRVR_STATE_BUSY_ERASE:
+ return "BUSY_ERASE";
+ case SKD_DRVR_STATE_BUSY_SANITIZE:
+ return "BUSY_SANITIZE";
+ case SKD_DRVR_STATE_BUSY_IMMINENT:
+ return "BUSY_IMMINENT";
+ case SKD_DRVR_STATE_WAIT_BOOT:
+ return "WAIT_BOOT";
+
+ default:
+ return "???";
+ }
+}
+
+const char *skd_skmsg_state_to_str(enum skd_fit_msg_state state)
+{
+ switch (state) {
+ case SKD_MSG_STATE_IDLE:
+ return "IDLE";
+ case SKD_MSG_STATE_BUSY:
+ return "BUSY";
+ default:
+ return "???";
+ }
+}
+
+const char *skd_skreq_state_to_str(enum skd_req_state state)
+{
+ switch (state) {
+ case SKD_REQ_STATE_IDLE:
+ return "IDLE";
+ case SKD_REQ_STATE_SETUP:
+ return "SETUP";
+ case SKD_REQ_STATE_BUSY:
+ return "BUSY";
+ case SKD_REQ_STATE_COMPLETED:
+ return "COMPLETED";
+ case SKD_REQ_STATE_TIMEOUT:
+ return "TIMEOUT";
+ case SKD_REQ_STATE_ABORTED:
+ return "ABORTED";
+ default:
+ return "???";
+ }
+}
+
+static void skd_log_skdev(struct skd_device *skdev, const char *event)
+{
+ DPRINTK(skdev, "(%s) skdev=%p event='%s'\n", skdev->name, skdev, event);
+ DPRINTK(skdev, " drive_state=%s(%d) driver_state=%s(%d)\n",
+ skd_drive_state_to_str(skdev->drive_state), skdev->drive_state,
+ skd_skdev_state_to_str(skdev->state), skdev->state);
+ DPRINTK(skdev, " busy=%d limit=%d dev=%d lowat=%d\n",
+ skdev->in_flight, skdev->cur_max_queue_depth,
+ skdev->dev_max_queue_depth, skdev->queue_low_water_mark);
+ DPRINTK(skdev, " timestamp=0x%x cycle=%d cycle_ix=%d\n",
+ skdev->timeout_stamp, skdev->skcomp_cycle, skdev->skcomp_ix);
+}
+
+static void skd_log_skmsg(struct skd_device *skdev,
+ struct skd_fitmsg_context *skmsg, const char *event)
+{
+ DPRINTK(skdev, "(%s) skmsg=%p event='%s'\n", skdev->name, skmsg, event);
+ DPRINTK(skdev, " state=%s(%d) id=0x%04x length=%d\n",
+ skd_skmsg_state_to_str(skmsg->state), skmsg->state,
+ skmsg->id, skmsg->length);
+}
+
+static void skd_log_skreq(struct skd_device *skdev,
+ struct skd_request_context *skreq, const char *event)
+{
+ DPRINTK(skdev, "(%s) skreq=%p event='%s'\n", skdev->name, skreq, event);
+ DPRINTK(skdev, " state=%s(%d) id=0x%04x fitmsg=0x%04x\n",
+ skd_skreq_state_to_str(skreq->state), skreq->state,
+ skreq->id, skreq->fitmsg_id);
+ DPRINTK(skdev, " timo=0x%x sg_dir=%d n_sg=%d\n",
+ skreq->timeout_stamp, skreq->sg_data_dir, skreq->n_sg);
+
+ if (!skd_bio) {
+ if (skreq->req != NULL) {
+ struct request *req = skreq->req;
+ u32 lba = (u32)blk_rq_pos(req);
+ u32 count = blk_rq_sectors(req);
+
+ DPRINTK(skdev,
+ " req=%p lba=%u(0x%x) count=%u(0x%x) dir=%d\n",
+ req, lba, lba, count, count,
+ (int)rq_data_dir(req));
+ } else
+ DPRINTK(skdev, " req=NULL\n");
+ } else {
+ if (skreq->bio != NULL) {
+ struct bio *bio = skreq->bio;
+ u32 lba = (u32)bio->bi_sector;
+ u32 count = bio_sectors(bio);
+
+ DPRINTK(skdev,
+ " bio=%p lba=%u(0x%x) count=%u(0x%x) dir=%d\n",
+ bio, lba, lba, count, count,
+ (int)bio_data_dir(bio));
+ } else
+ DPRINTK(skdev, " req=NULL\n");
+ }
+}
+
+/*
+ *****************************************************************************
+ * MODULE GLUE
+ *****************************************************************************
+ */
+
+static int __init skd_init(void)
+{
+ int rc = 0;
+
+ pr_info(PFX " v%s-b%s loaded\n", DRV_VERSION, DRV_BUILD_ID);
+
+ switch (skd_isr_type) {
+ case SKD_IRQ_LEGACY:
+ case SKD_IRQ_MSI:
+ case SKD_IRQ_MSIX:
+ break;
+ default:
+ pr_info("skd_isr_type %d invalid, re-set to %d\n",
+ skd_isr_type, SKD_IRQ_DEFAULT);
+ skd_isr_type = SKD_IRQ_DEFAULT;
+ }
+
+ skd_flush_slab = kmem_cache_create(SKD_FLUSH_JOB,
+ sizeof(struct skd_flush_cmd),
+ 0, 0, NULL);
+
+ if (!skd_flush_slab) {
+ pr_err("failed to allocated flush slab.\n");
+ return -ENOMEM;
+ }
+
+ if (skd_max_queue_depth < 1
+ || skd_max_queue_depth > SKD_MAX_QUEUE_DEPTH) {
+ pr_info(
+ "skd_max_queue_depth %d invalid, re-set to %d\n",
+ skd_max_queue_depth, SKD_MAX_QUEUE_DEPTH_DEFAULT);
+ skd_max_queue_depth = SKD_MAX_QUEUE_DEPTH_DEFAULT;
+ }
+
+ if (skd_max_req_per_msg < 1 || skd_max_req_per_msg > 14) {
+ pr_info(
+ "skd_max_req_per_msg %d invalid, re-set to %d\n",
+ skd_max_req_per_msg, SKD_MAX_REQ_PER_MSG_DEFAULT);
+ skd_max_req_per_msg = SKD_MAX_REQ_PER_MSG_DEFAULT;
+ }
+
+ if (skd_sgs_per_request < 1 || skd_sgs_per_request > 4096) {
+ pr_info(
+ "skd_sg_per_request %d invalid, re-set to %d\n",
+ skd_sgs_per_request, SKD_N_SG_PER_REQ_DEFAULT);
+ skd_sgs_per_request = SKD_N_SG_PER_REQ_DEFAULT;
+ }
+
+ if (skd_dbg_level < 0 || skd_dbg_level > 2) {
+ pr_info("skd_dbg_level %d invalid, re-set to %d\n",
+ skd_dbg_level, 0);
+ skd_dbg_level = 0;
+ }
+
+ if (skd_isr_comp_limit < 0) {
+ pr_info("skd_isr_comp_limit %d invalid, set to %d\n",
+ skd_isr_comp_limit, 0);
+ skd_isr_comp_limit = 0;
+ }
+
+ if (skd_max_pass_thru < 1 || skd_max_pass_thru > 50) {
+ pr_info("skd_max_pass_thru %d invalid, re-set to %d\n",
+ skd_max_pass_thru, SKD_N_SPECIAL_CONTEXT);
+ skd_max_pass_thru = SKD_N_SPECIAL_CONTEXT;
+ }
+
+ /* Obtain major device number. */
+ rc = register_blkdev(0, DRV_NAME);
+ if (rc < 0)
+ return rc;
+
+ skd_major = rc;
+
+ return pci_register_driver(&skd_driver);
+
+}
+
+static void __exit skd_exit(void)
+{
+ pr_info(PFX " v%s-b%s unloading\n", DRV_VERSION, DRV_BUILD_ID);
+
+ unregister_blkdev(skd_major, DRV_NAME);
+ pci_unregister_driver(&skd_driver);
+
+ kmem_cache_destroy(skd_flush_slab);
+}
+
+static int
+skd_flush_cmd_enqueue(struct skd_device *skdev, void *cmd)
+{
+ struct skd_flush_cmd *item;
+
+ item = kmem_cache_zalloc(skd_flush_slab, GFP_ATOMIC);
+ if (!item) {
+ pr_err("skd_flush_cmd_enqueue: Failed to allocated item.\n");
+ return -ENOMEM;
+ }
+
+ item->cmd = cmd;
+ list_add_tail(&item->flist, &skdev->flush_list);
+ return 0;
+}
+
+static void *
+skd_flush_cmd_dequeue(struct skd_device *skdev)
+{
+ void *cmd;
+ struct skd_flush_cmd *item;
+
+ item = list_entry(skdev->flush_list.next, struct skd_flush_cmd, flist);
+ list_del_init(&item->flist);
+ cmd = item->cmd;
+ kmem_cache_free(skd_flush_slab, item);
+ return cmd;
+}
+
+module_init(skd_init);
+module_exit(skd_exit);
diff --git a/drivers/block/skd_s1120.h b/drivers/block/skd_s1120.h
new file mode 100644
index 000000000000..bf01941cdd62
--- /dev/null
+++ b/drivers/block/skd_s1120.h
@@ -0,0 +1,354 @@
+/* Copyright 2012 STEC, Inc.
+ *
+ * This file is licensed under the terms of the 3-clause
+ * BSD License (http://opensource.org/licenses/BSD-3-Clause)
+ * or the GNU GPL-2.0 (http://www.gnu.org/licenses/gpl-2.0.html),
+ * at your option. Both licenses are also available in the LICENSE file
+ * distributed with this project. This file may not be copied, modified,
+ * or distributed except in accordance with those terms.
+ */
+
+
+#ifndef SKD_S1120_H
+#define SKD_S1120_H
+
+#pragma pack(push, s1120_h, 1)
+
+/*
+ * Q-channel, 64-bit r/w
+ */
+#define FIT_Q_COMMAND 0x400u
+#define FIT_QCMD_QID_MASK (0x3 << 1)
+#define FIT_QCMD_QID0 (0x0 << 1)
+#define FIT_QCMD_QID_NORMAL FIT_QCMD_QID0
+#ifndef SKD_OMIT_FROM_SRC_DIST
+#define FIT_QCMD_QID1 (0x1 << 1)
+#define FIT_QCMD_QID2 (0x2 << 1)
+#define FIT_QCMD_QID3 (0x3 << 1)
+#endif /* SKD_OMIT_FROM_SRC_DIST */
+#define FIT_QCMD_FLUSH_QUEUE (0ull) /* add QID */
+#define FIT_QCMD_MSGSIZE_MASK (0x3 << 4)
+#define FIT_QCMD_MSGSIZE_64 (0x0 << 4)
+#define FIT_QCMD_MSGSIZE_128 (0x1 << 4)
+#define FIT_QCMD_MSGSIZE_256 (0x2 << 4)
+#define FIT_QCMD_MSGSIZE_512 (0x3 << 4)
+#define FIT_QCMD_BASE_ADDRESS_MASK (0xFFFFFFFFFFFFFFC0ull)
+
+
+/*
+ * Control, 32-bit r/w
+ */
+#define FIT_CONTROL 0x500u
+#ifndef SKD_OMIT_FROM_SRC_DIST
+#define FIT_CR_HARD_RESET (1u << 0u)
+#endif /* SKD_OMIT_FROM_SRC_DIST */
+#define FIT_CR_SOFT_RESET (1u << 1u)
+#ifndef SKD_OMIT_FROM_SRC_DIST
+#define FIT_CR_DIS_TIMESTAMPS (1u << 6u)
+#endif /* SKD_OMIT_FROM_SRC_DIST */
+#define FIT_CR_ENABLE_INTERRUPTS (1u << 7u)
+
+/*
+ * Status, 32-bit, r/o
+ */
+#define FIT_STATUS 0x510u
+#define FIT_SR_DRIVE_STATE_MASK 0x000000FFu
+#ifndef SKD_OMIT_FROM_SRC_DIST
+#define FIT_SR_SIGNATURE (0xFF << 8)
+#define FIT_SR_PIO_DMA (1 << 16)
+#endif /* SKD_OMIT_FROM_SRC_DIST */
+#define FIT_SR_DRIVE_OFFLINE 0x00
+#define FIT_SR_DRIVE_INIT 0x01
+/* #define FIT_SR_DRIVE_READY 0x02 */
+#define FIT_SR_DRIVE_ONLINE 0x03
+#define FIT_SR_DRIVE_BUSY 0x04
+#define FIT_SR_DRIVE_FAULT 0x05
+#define FIT_SR_DRIVE_DEGRADED 0x06
+#define FIT_SR_PCIE_LINK_DOWN 0x07
+#define FIT_SR_DRIVE_SOFT_RESET 0x08
+#define FIT_SR_DRIVE_INIT_FAULT 0x09
+#define FIT_SR_DRIVE_BUSY_SANITIZE 0x0A
+#define FIT_SR_DRIVE_BUSY_ERASE 0x0B
+#define FIT_SR_DRIVE_FW_BOOTING 0x0C
+#define FIT_SR_DRIVE_NEED_FW_DOWNLOAD 0xFE
+#define FIT_SR_DEVICE_MISSING 0xFF
+#define FIT_SR__RESERVED 0xFFFFFF00u
+
+#ifndef SKD_OMIT_FROM_SRC_DIST
+/*
+ * FIT_STATUS - Status register data definition
+ */
+#define FIT_SR_STATE_MASK (0xFF << 0)
+#define FIT_SR_SIGNATURE (0xFF << 8)
+#define FIT_SR_PIO_DMA (1 << 16)
+#endif /* SKD_OMIT_FROM_SRC_DIST */
+
+
+/*
+ * Interrupt status, 32-bit r/w1c (w1c ==> write 1 to clear)
+ */
+#define FIT_INT_STATUS_HOST 0x520u
+#define FIT_ISH_FW_STATE_CHANGE (1u << 0u)
+#define FIT_ISH_COMPLETION_POSTED (1u << 1u)
+#define FIT_ISH_MSG_FROM_DEV (1u << 2u)
+#define FIT_ISH_UNDEFINED_3 (1u << 3u)
+#define FIT_ISH_UNDEFINED_4 (1u << 4u)
+#define FIT_ISH_Q0_FULL (1u << 5u)
+#define FIT_ISH_Q1_FULL (1u << 6u)
+#define FIT_ISH_Q2_FULL (1u << 7u)
+#define FIT_ISH_Q3_FULL (1u << 8u)
+#define FIT_ISH_QCMD_FIFO_OVERRUN (1u << 9u)
+#define FIT_ISH_BAD_EXP_ROM_READ (1u << 10u)
+
+
+#define FIT_INT_DEF_MASK \
+ (FIT_ISH_FW_STATE_CHANGE | \
+ FIT_ISH_COMPLETION_POSTED | \
+ FIT_ISH_MSG_FROM_DEV | \
+ FIT_ISH_Q0_FULL | \
+ FIT_ISH_Q1_FULL | \
+ FIT_ISH_Q2_FULL | \
+ FIT_ISH_Q3_FULL | \
+ FIT_ISH_QCMD_FIFO_OVERRUN | \
+ FIT_ISH_BAD_EXP_ROM_READ)
+
+#define FIT_INT_QUEUE_FULL \
+ (FIT_ISH_Q0_FULL | \
+ FIT_ISH_Q1_FULL | \
+ FIT_ISH_Q2_FULL | \
+ FIT_ISH_Q3_FULL)
+
+
+#define MSI_MSG_NWL_ERROR_0 0x00000000
+#define MSI_MSG_NWL_ERROR_1 0x00000001
+#define MSI_MSG_NWL_ERROR_2 0x00000002
+#define MSI_MSG_NWL_ERROR_3 0x00000003
+#define MSI_MSG_STATE_CHANGE 0x00000004
+#define MSI_MSG_COMPLETION_POSTED 0x00000005
+#define MSI_MSG_MSG_FROM_DEV 0x00000006
+#define MSI_MSG_RESERVED_0 0x00000007
+#define MSI_MSG_RESERVED_1 0x00000008
+#define MSI_MSG_QUEUE_0_FULL 0x00000009
+#define MSI_MSG_QUEUE_1_FULL 0x0000000A
+#define MSI_MSG_QUEUE_2_FULL 0x0000000B
+#define MSI_MSG_QUEUE_3_FULL 0x0000000C
+
+
+
+#define FIT_INT_RESERVED_MASK \
+ (FIT_ISH_UNDEFINED_3 | \
+ FIT_ISH_UNDEFINED_4)
+/*
+ * Interrupt mask, 32-bit r/w
+ * Bit definitions are the same as FIT_INT_STATUS_HOST
+ */
+#define FIT_INT_MASK_HOST 0x528u
+
+
+/*
+ * Message to device, 32-bit r/w
+ */
+#define FIT_MSG_TO_DEVICE 0x540u
+
+/*
+ * Message from device, 32-bit, r/o
+ */
+#define FIT_MSG_FROM_DEVICE 0x548u
+
+
+/*
+ * 32-bit messages to/from device, composition/extraction macros
+ */
+#define FIT_MXD_CONS(TYPE, PARAM, DATA) \
+ ((((TYPE) & 0xFFu) << 24u) | \
+ (((PARAM) & 0xFFu) << 16u) | \
+ (((DATA) & 0xFFFFu) << 0u))
+#define FIT_MXD_TYPE(MXD) (((MXD) >> 24u) & 0xFFu)
+#define FIT_MXD_PARAM(MXD) (((MXD) >> 16u) & 0xFFu)
+#define FIT_MXD_DATA(MXD) (((MXD) >> 0u) & 0xFFFFu)
+
+
+/*
+ * Types of messages to/from device
+ */
+#define FIT_MTD_FITFW_INIT 0x01u
+#define FIT_MTD_GET_CMDQ_DEPTH 0x02u
+#define FIT_MTD_SET_COMPQ_DEPTH 0x03u
+#define FIT_MTD_SET_COMPQ_ADDR 0x04u
+#define FIT_MTD_ARM_QUEUE 0x05u
+#define FIT_MTD_CMD_LOG_HOST_ID 0x07u
+#define FIT_MTD_CMD_LOG_TIME_STAMP_LO 0x08u
+#define FIT_MTD_CMD_LOG_TIME_STAMP_HI 0x09u
+#define FIT_MFD_SMART_EXCEEDED 0x10u
+#define FIT_MFD_POWER_DOWN 0x11u
+#define FIT_MFD_OFFLINE 0x12u
+#define FIT_MFD_ONLINE 0x13u
+#define FIT_MFD_FW_RESTARTING 0x14u
+#define FIT_MFD_PM_ACTIVE 0x15u
+#define FIT_MFD_PM_STANDBY 0x16u
+#define FIT_MFD_PM_SLEEP 0x17u
+#define FIT_MFD_CMD_PROGRESS 0x18u
+
+#ifndef SKD_OMIT_FROM_SRC_DIST
+#define FIT_MTD_DEBUG 0xFEu
+#define FIT_MFD_DEBUG 0xFFu
+#endif /* SKD_OMIT_FROM_SRC_DIST */
+
+#define FIT_MFD_MASK (0xFFu)
+#define FIT_MFD_DATA_MASK (0xFFu)
+#define FIT_MFD_MSG(x) (((x) >> 24) & FIT_MFD_MASK)
+#define FIT_MFD_DATA(x) ((x) & FIT_MFD_MASK)
+
+
+/*
+ * Extra arg to FIT_MSG_TO_DEVICE, 64-bit r/w
+ * Used to set completion queue address (FIT_MTD_SET_COMPQ_ADDR)
+ * (was Response buffer in docs)
+ */
+#define FIT_MSG_TO_DEVICE_ARG 0x580u
+
+/*
+ * Hardware (ASIC) version, 32-bit r/o
+ */
+#define FIT_HW_VERSION 0x588u
+
+/*
+ * Scatter/gather list descriptor.
+ * 32-bytes and must be aligned on a 32-byte boundary.
+ * All fields are in little endian order.
+ */
+struct fit_sg_descriptor {
+ uint32_t control;
+ uint32_t byte_count;
+ uint64_t host_side_addr;
+ uint64_t dev_side_addr;
+ uint64_t next_desc_ptr;
+};
+
+#define FIT_SGD_CONTROL_NOT_LAST 0x000u
+#define FIT_SGD_CONTROL_LAST 0x40Eu
+
+/*
+ * Header at the beginning of a FIT message. The header
+ * is followed by SSDI requests each 64 bytes.
+ * A FIT message can be up to 512 bytes long and must start
+ * on a 64-byte boundary.
+ */
+struct fit_msg_hdr {
+ uint8_t protocol_id;
+ uint8_t num_protocol_cmds_coalesced;
+ uint8_t _reserved[62];
+};
+
+#define FIT_PROTOCOL_ID_FIT 1
+#define FIT_PROTOCOL_ID_SSDI 2
+#define FIT_PROTOCOL_ID_SOFIT 3
+
+
+#define FIT_PROTOCOL_MINOR_VER(mtd_val) ((mtd_val >> 16) & 0xF)
+#define FIT_PROTOCOL_MAJOR_VER(mtd_val) ((mtd_val >> 20) & 0xF)
+
+#ifndef SKD_OMIT_FROM_SRC_DIST
+/*
+ * Format of a completion entry. The completion queue is circular
+ * and must have at least as many entries as the maximum number
+ * of commands that may be issued to the device.
+ *
+ * There are no head/tail pointers. The cycle value is used to
+ * infer the presence of new completion records.
+ * Initially the cycle in all entries is 0, the index is 0, and
+ * the cycle value to expect is 1. When completions are added
+ * their cycle values are set to 1. When the index wraps the
+ * cycle value to expect is incremented.
+ *
+ * Command_context is opaque and taken verbatim from the SSDI command.
+ * All other fields are big endian.
+ */
+#endif /* SKD_OMIT_FROM_SRC_DIST */
+#define FIT_PROTOCOL_VERSION_0 0
+
+/*
+ * Protocol major version 1 completion entry.
+ * The major protocol version is found in bits
+ * 20-23 of the FIT_MTD_FITFW_INIT response.
+ */
+struct fit_completion_entry_v1 {
+ uint32_t num_returned_bytes;
+ uint16_t tag;
+ uint8_t status; /* SCSI status */
+ uint8_t cycle;
+};
+#define FIT_PROTOCOL_VERSION_1 1
+#define FIT_PROTOCOL_VERSION_CURRENT FIT_PROTOCOL_VERSION_1
+
+struct fit_comp_error_info {
+ uint8_t type:7; /* 00: Bits0-6 indicates the type of sense data. */
+ uint8_t valid:1; /* 00: Bit 7 := 1 ==> info field is valid. */
+ uint8_t reserved0; /* 01: Obsolete field */
+ uint8_t key:4; /* 02: Bits0-3 indicate the sense key. */
+ uint8_t reserved2:1; /* 02: Reserved bit. */
+ uint8_t bad_length:1; /* 02: Incorrect Length Indicator */
+ uint8_t end_medium:1; /* 02: End of Medium */
+ uint8_t file_mark:1; /* 02: Filemark */
+ uint8_t info[4]; /* 03: */
+ uint8_t reserved1; /* 07: Additional Sense Length */
+ uint8_t cmd_spec[4]; /* 08: Command Specific Information */
+ uint8_t code; /* 0C: Additional Sense Code */
+ uint8_t qual; /* 0D: Additional Sense Code Qualifier */
+ uint8_t fruc; /* 0E: Field Replaceable Unit Code */
+ uint8_t sks_high:7; /* 0F: Sense Key Specific (MSB) */
+ uint8_t sks_valid:1; /* 0F: Sense Key Specific Valid */
+ uint16_t sks_low; /* 10: Sense Key Specific (LSW) */
+ uint16_t reserved3; /* 12: Part of additional sense bytes (unused) */
+ uint16_t uec; /* 14: Additional Sense Bytes */
+ uint64_t per; /* 16: Additional Sense Bytes */
+ uint8_t reserved4[2]; /* 1E: Additional Sense Bytes (unused) */
+};
+
+
+/* Task management constants */
+#define SOFT_TASK_SIMPLE 0x00
+#define SOFT_TASK_HEAD_OF_QUEUE 0x01
+#define SOFT_TASK_ORDERED 0x02
+
+
+/* Version zero has the last 32 bits reserved,
+ * Version one has the last 32 bits sg_list_len_bytes;
+ */
+struct skd_command_header {
+ uint64_t sg_list_dma_address;
+ uint16_t tag;
+ uint8_t attribute;
+ uint8_t add_cdb_len; /* In 32 bit words */
+ uint32_t sg_list_len_bytes;
+};
+
+struct skd_scsi_request {
+ struct skd_command_header hdr;
+ unsigned char cdb[16];
+/* unsigned char _reserved[16]; */
+};
+
+struct driver_inquiry_data {
+ uint8_t peripheral_device_type:5;
+ uint8_t qualifier:3;
+ uint8_t page_code;
+ uint16_t page_length;
+ uint16_t pcie_bus_number;
+ uint8_t pcie_device_number;
+ uint8_t pcie_function_number;
+ uint8_t pcie_link_speed;
+ uint8_t pcie_link_lanes;
+ uint16_t pcie_vendor_id;
+ uint16_t pcie_device_id;
+ uint16_t pcie_subsystem_vendor_id;
+ uint16_t pcie_subsystem_device_id;
+ uint8_t reserved1[2];
+ uint8_t reserved2[3];
+ uint8_t driver_version_length;
+ uint8_t driver_version[0x14];
+};
+
+#pragma pack(pop, s1120_h)
+
+#endif /* SKD_S1120_H */
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index bf4b9d282c04..6620b73d0490 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -887,6 +887,8 @@ static int dispatch_discard_io(struct xen_blkif *blkif,
unsigned long secure;
struct phys_req preq;
+ xen_blkif_get(blkif);
+
preq.sector_number = req->u.discard.sector_number;
preq.nr_sects = req->u.discard.nr_sectors;
@@ -899,7 +901,6 @@ static int dispatch_discard_io(struct xen_blkif *blkif,
}
blkif->st_ds_req++;
- xen_blkif_get(blkif);
secure = (blkif->vbd.discard_secure &&
(req->u.discard.flag & BLKIF_DISCARD_SECURE)) ?
BLKDEV_DISCARD_SECURE : 0;
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index a4660bbee8a6..65531331fe9c 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -400,10 +400,13 @@ static int blkif_queue_request(struct request *req)
if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
return 1;
- max_grefs = info->max_indirect_segments ?
- info->max_indirect_segments +
- INDIRECT_GREFS(info->max_indirect_segments) :
- BLKIF_MAX_SEGMENTS_PER_REQUEST;
+ max_grefs = req->nr_phys_segments;
+ if (max_grefs > BLKIF_MAX_SEGMENTS_PER_REQUEST)
+ /*
+ * If we are using indirect segments we need to account
+ * for the indirect grefs used in the request.
+ */
+ max_grefs += INDIRECT_GREFS(req->nr_phys_segments);
/* Check if we have enough grants to allocate a requests */
if (info->persistent_gnts_c < max_grefs) {
@@ -1013,13 +1016,38 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info,
}
/* Add the persistent grant into the list of free grants */
for (i = 0; i < nseg; i++) {
- list_add(&s->grants_used[i]->node, &info->persistent_gnts);
- info->persistent_gnts_c++;
+ if (gnttab_query_foreign_access(s->grants_used[i]->gref)) {
+ /*
+ * If the grant is still mapped by the backend (the
+ * backend has chosen to make this grant persistent)
+ * we add it at the head of the list, so it will be
+ * reused first.
+ */
+ list_add(&s->grants_used[i]->node, &info->persistent_gnts);
+ info->persistent_gnts_c++;
+ } else {
+ /*
+ * If the grant is not mapped by the backend we end the
+ * foreign access and add it to the tail of the list,
+ * so it will not be picked again unless we run out of
+ * persistent grants.
+ */
+ gnttab_end_foreign_access(s->grants_used[i]->gref, 0, 0UL);
+ s->grants_used[i]->gref = GRANT_INVALID_REF;
+ list_add_tail(&s->grants_used[i]->node, &info->persistent_gnts);
+ }
}
if (s->req.operation == BLKIF_OP_INDIRECT) {
for (i = 0; i < INDIRECT_GREFS(nseg); i++) {
- list_add(&s->indirect_grants[i]->node, &info->persistent_gnts);
- info->persistent_gnts_c++;
+ if (gnttab_query_foreign_access(s->indirect_grants[i]->gref)) {
+ list_add(&s->indirect_grants[i]->node, &info->persistent_gnts);
+ info->persistent_gnts_c++;
+ } else {
+ gnttab_end_foreign_access(s->indirect_grants[i]->gref, 0, 0UL);
+ s->indirect_grants[i]->gref = GRANT_INVALID_REF;
+ list_add_tail(&s->indirect_grants[i]->node,
+ &info->persistent_gnts);
+ }
}
}
}
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index a12b923bbaca..0a327f4154a2 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -85,6 +85,7 @@ static struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x04CA, 0x3008) },
{ USB_DEVICE(0x13d3, 0x3362) },
{ USB_DEVICE(0x0CF3, 0xE004) },
+ { USB_DEVICE(0x0CF3, 0xE005) },
{ USB_DEVICE(0x0930, 0x0219) },
{ USB_DEVICE(0x0489, 0xe057) },
{ USB_DEVICE(0x13d3, 0x3393) },
@@ -126,6 +127,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 8e16f0af6358..f3dfc0a88fdc 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -102,6 +102,7 @@ static struct usb_device_id btusb_table[] = {
/* Broadcom BCM20702A0 */
{ USB_DEVICE(0x0b05, 0x17b5) },
+ { USB_DEVICE(0x0b05, 0x17cb) },
{ USB_DEVICE(0x04ca, 0x2003) },
{ USB_DEVICE(0x0489, 0xe042) },
{ USB_DEVICE(0x413c, 0x8197) },
@@ -112,6 +113,9 @@ static struct usb_device_id btusb_table[] = {
/*Broadcom devices with vendor specific id */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
+ /* Belkin F8065bf - Broadcom based */
+ { USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
+
{ } /* Terminating entry */
};
@@ -148,6 +152,7 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index d8b7aed6e4a9..c04a3e6fb37c 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -24,6 +24,7 @@
*/
#include <linux/module.h>
+#include <asm/unaligned.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -39,17 +40,17 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
-#define VERSION "1.3"
+#define VERSION "1.4"
static bool amp;
struct vhci_data {
struct hci_dev *hdev;
- unsigned long flags;
-
wait_queue_head_t read_wait;
struct sk_buff_head readq;
+
+ struct delayed_work open_timeout;
};
static int vhci_open_dev(struct hci_dev *hdev)
@@ -99,16 +100,62 @@ static int vhci_send_frame(struct sk_buff *skb)
skb_queue_tail(&data->readq, skb);
wake_up_interruptible(&data->read_wait);
+ return 0;
+}
+
+static int vhci_create_device(struct vhci_data *data, __u8 dev_type)
+{
+ struct hci_dev *hdev;
+ struct sk_buff *skb;
+
+ skb = bt_skb_alloc(4, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ hdev = hci_alloc_dev();
+ if (!hdev) {
+ kfree_skb(skb);
+ return -ENOMEM;
+ }
+
+ data->hdev = hdev;
+
+ hdev->bus = HCI_VIRTUAL;
+ hdev->dev_type = dev_type;
+ hci_set_drvdata(hdev, data);
+
+ hdev->open = vhci_open_dev;
+ hdev->close = vhci_close_dev;
+ hdev->flush = vhci_flush;
+ hdev->send = vhci_send_frame;
+ if (hci_register_dev(hdev) < 0) {
+ BT_ERR("Can't register HCI device");
+ hci_free_dev(hdev);
+ data->hdev = NULL;
+ kfree_skb(skb);
+ return -EBUSY;
+ }
+
+ bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
+
+ *skb_put(skb, 1) = 0xff;
+ *skb_put(skb, 1) = dev_type;
+ put_unaligned_le16(hdev->id, skb_put(skb, 2));
+ skb_queue_tail(&data->readq, skb);
+
+ wake_up_interruptible(&data->read_wait);
return 0;
}
static inline ssize_t vhci_get_user(struct vhci_data *data,
- const char __user *buf, size_t count)
+ const char __user *buf, size_t count)
{
struct sk_buff *skb;
+ __u8 pkt_type, dev_type;
+ int ret;
- if (count > HCI_MAX_FRAME_SIZE)
+ if (count < 2 || count > HCI_MAX_FRAME_SIZE)
return -EINVAL;
skb = bt_skb_alloc(count, GFP_KERNEL);
@@ -120,27 +167,70 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
return -EFAULT;
}
- skb->dev = (void *) data->hdev;
- bt_cb(skb)->pkt_type = *((__u8 *) skb->data);
+ pkt_type = *((__u8 *) skb->data);
skb_pull(skb, 1);
- hci_recv_frame(skb);
+ switch (pkt_type) {
+ case HCI_EVENT_PKT:
+ case HCI_ACLDATA_PKT:
+ case HCI_SCODATA_PKT:
+ if (!data->hdev) {
+ kfree_skb(skb);
+ return -ENODEV;
+ }
+
+ skb->dev = (void *) data->hdev;
+ bt_cb(skb)->pkt_type = pkt_type;
+
+ ret = hci_recv_frame(skb);
+ break;
+
+ case HCI_VENDOR_PKT:
+ if (data->hdev) {
+ kfree_skb(skb);
+ return -EBADFD;
+ }
- return count;
+ cancel_delayed_work_sync(&data->open_timeout);
+
+ dev_type = *((__u8 *) skb->data);
+ skb_pull(skb, 1);
+
+ if (skb->len > 0) {
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+
+ kfree_skb(skb);
+
+ if (dev_type != HCI_BREDR && dev_type != HCI_AMP)
+ return -EINVAL;
+
+ ret = vhci_create_device(data, dev_type);
+ break;
+
+ default:
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+
+ return (ret < 0) ? ret : count;
}
static inline ssize_t vhci_put_user(struct vhci_data *data,
- struct sk_buff *skb, char __user *buf, int count)
+ struct sk_buff *skb,
+ char __user *buf, int count)
{
char __user *ptr = buf;
- int len, total = 0;
+ int len;
len = min_t(unsigned int, skb->len, count);
if (copy_to_user(ptr, skb->data, len))
return -EFAULT;
- total += len;
+ if (!data->hdev)
+ return len;
data->hdev->stat.byte_tx += len;
@@ -148,21 +238,19 @@ static inline ssize_t vhci_put_user(struct vhci_data *data,
case HCI_COMMAND_PKT:
data->hdev->stat.cmd_tx++;
break;
-
case HCI_ACLDATA_PKT:
data->hdev->stat.acl_tx++;
break;
-
case HCI_SCODATA_PKT:
data->hdev->stat.sco_tx++;
break;
}
- return total;
+ return len;
}
static ssize_t vhci_read(struct file *file,
- char __user *buf, size_t count, loff_t *pos)
+ char __user *buf, size_t count, loff_t *pos)
{
struct vhci_data *data = file->private_data;
struct sk_buff *skb;
@@ -185,7 +273,7 @@ static ssize_t vhci_read(struct file *file,
}
ret = wait_event_interruptible(data->read_wait,
- !skb_queue_empty(&data->readq));
+ !skb_queue_empty(&data->readq));
if (ret < 0)
break;
}
@@ -194,7 +282,7 @@ static ssize_t vhci_read(struct file *file,
}
static ssize_t vhci_write(struct file *file,
- const char __user *buf, size_t count, loff_t *pos)
+ const char __user *buf, size_t count, loff_t *pos)
{
struct vhci_data *data = file->private_data;
@@ -213,10 +301,17 @@ static unsigned int vhci_poll(struct file *file, poll_table *wait)
return POLLOUT | POLLWRNORM;
}
+static void vhci_open_timeout(struct work_struct *work)
+{
+ struct vhci_data *data = container_of(work, struct vhci_data,
+ open_timeout.work);
+
+ vhci_create_device(data, amp ? HCI_AMP : HCI_BREDR);
+}
+
static int vhci_open(struct inode *inode, struct file *file)
{
struct vhci_data *data;
- struct hci_dev *hdev;
data = kzalloc(sizeof(struct vhci_data), GFP_KERNEL);
if (!data)
@@ -225,35 +320,13 @@ static int vhci_open(struct inode *inode, struct file *file)
skb_queue_head_init(&data->readq);
init_waitqueue_head(&data->read_wait);
- hdev = hci_alloc_dev();
- if (!hdev) {
- kfree(data);
- return -ENOMEM;
- }
-
- data->hdev = hdev;
-
- hdev->bus = HCI_VIRTUAL;
- hci_set_drvdata(hdev, data);
-
- if (amp)
- hdev->dev_type = HCI_AMP;
-
- hdev->open = vhci_open_dev;
- hdev->close = vhci_close_dev;
- hdev->flush = vhci_flush;
- hdev->send = vhci_send_frame;
-
- if (hci_register_dev(hdev) < 0) {
- BT_ERR("Can't register HCI device");
- kfree(data);
- hci_free_dev(hdev);
- return -EBUSY;
- }
+ INIT_DELAYED_WORK(&data->open_timeout, vhci_open_timeout);
file->private_data = data;
nonseekable_open(inode, file);
+ schedule_delayed_work(&data->open_timeout, msecs_to_jiffies(1000));
+
return 0;
}
@@ -262,8 +335,12 @@ static int vhci_release(struct inode *inode, struct file *file)
struct vhci_data *data = file->private_data;
struct hci_dev *hdev = data->hdev;
- hci_unregister_dev(hdev);
- hci_free_dev(hdev);
+ cancel_delayed_work_sync(&data->open_timeout);
+
+ if (hdev) {
+ hci_unregister_dev(hdev);
+ hci_free_dev(hdev);
+ }
file->private_data = NULL;
kfree(data);
@@ -309,3 +386,4 @@ MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
+MODULE_ALIAS("devname:vhci");
diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index 200926699778..bb5b90e8e768 100644
--- a/drivers/bus/arm-cci.c
+++ b/drivers/bus/arm-cci.c
@@ -18,11 +18,21 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <linux/spinlock.h>
#include <asm/cacheflush.h>
+#include <asm/irq_regs.h>
+#include <asm/pmu.h>
#include <asm/smp_plat.h>
+#define DRIVER_NAME "CCI-400"
+#define DRIVER_NAME_PMU DRIVER_NAME " PMU"
+#define PMU_NAME "CCI_400"
+
#define CCI_PORT_CTRL 0x0
#define CCI_CTRL_STATUS 0xc
@@ -54,6 +64,568 @@ static unsigned int nb_cci_ports;
static void __iomem *cci_ctrl_base;
static unsigned long cci_ctrl_phys;
+#ifdef CONFIG_HW_PERF_EVENTS
+
+#define CCI_PMCR 0x0100
+#define CCI_PID2 0x0fe8
+
+#define CCI_PMCR_CEN 0x00000001
+#define CCI_PMCR_NCNT_MASK 0x0000f800
+#define CCI_PMCR_NCNT_SHIFT 11
+
+#define CCI_PID2_REV_MASK 0xf0
+#define CCI_PID2_REV_SHIFT 4
+
+/* Port ids */
+#define CCI_PORT_S0 0
+#define CCI_PORT_S1 1
+#define CCI_PORT_S2 2
+#define CCI_PORT_S3 3
+#define CCI_PORT_S4 4
+#define CCI_PORT_M0 5
+#define CCI_PORT_M1 6
+#define CCI_PORT_M2 7
+
+#define CCI_REV_R0 0
+#define CCI_REV_R1 1
+#define CCI_REV_R0_P4 4
+#define CCI_REV_R1_P2 6
+
+#define CCI_PMU_EVT_SEL 0x000
+#define CCI_PMU_CNTR 0x004
+#define CCI_PMU_CNTR_CTRL 0x008
+#define CCI_PMU_OVRFLW 0x00c
+
+#define CCI_PMU_OVRFLW_FLAG 1
+
+#define CCI_PMU_CNTR_BASE(idx) ((idx) * SZ_4K)
+
+/*
+ * Instead of an event id to monitor CCI cycles, a dedicated counter is
+ * provided. Use 0xff to represent CCI cycles and hope that no future revisions
+ * make use of this event in hardware.
+ */
+enum cci400_perf_events {
+ CCI_PMU_CYCLES = 0xff
+};
+
+#define CCI_PMU_EVENT_MASK 0xff
+#define CCI_PMU_EVENT_SOURCE(event) ((event >> 5) & 0x7)
+#define CCI_PMU_EVENT_CODE(event) (event & 0x1f)
+
+#define CCI_PMU_MAX_HW_EVENTS 5 /* CCI PMU has 4 counters + 1 cycle counter */
+
+#define CCI_PMU_CYCLE_CNTR_IDX 0
+#define CCI_PMU_CNTR0_IDX 1
+#define CCI_PMU_CNTR_LAST(cci_pmu) (CCI_PMU_CYCLE_CNTR_IDX + cci_pmu->num_events - 1)
+
+/*
+ * CCI PMU event id is an 8-bit value made of two parts - bits 7:5 for one of 8
+ * ports and bits 4:0 are event codes. There are different event codes
+ * associated with each port type.
+ *
+ * Additionally, the range of events associated with the port types changed
+ * between Rev0 and Rev1.
+ *
+ * The constants below define the range of valid codes for each port type for
+ * the different revisions and are used to validate the event to be monitored.
+ */
+
+#define CCI_REV_R0_SLAVE_PORT_MIN_EV 0x00
+#define CCI_REV_R0_SLAVE_PORT_MAX_EV 0x13
+#define CCI_REV_R0_MASTER_PORT_MIN_EV 0x14
+#define CCI_REV_R0_MASTER_PORT_MAX_EV 0x1a
+
+#define CCI_REV_R1_SLAVE_PORT_MIN_EV 0x00
+#define CCI_REV_R1_SLAVE_PORT_MAX_EV 0x14
+#define CCI_REV_R1_MASTER_PORT_MIN_EV 0x00
+#define CCI_REV_R1_MASTER_PORT_MAX_EV 0x11
+
+struct pmu_port_event_ranges {
+ u8 slave_min;
+ u8 slave_max;
+ u8 master_min;
+ u8 master_max;
+};
+
+static struct pmu_port_event_ranges port_event_range[] = {
+ [CCI_REV_R0] = {
+ .slave_min = CCI_REV_R0_SLAVE_PORT_MIN_EV,
+ .slave_max = CCI_REV_R0_SLAVE_PORT_MAX_EV,
+ .master_min = CCI_REV_R0_MASTER_PORT_MIN_EV,
+ .master_max = CCI_REV_R0_MASTER_PORT_MAX_EV,
+ },
+ [CCI_REV_R1] = {
+ .slave_min = CCI_REV_R1_SLAVE_PORT_MIN_EV,
+ .slave_max = CCI_REV_R1_SLAVE_PORT_MAX_EV,
+ .master_min = CCI_REV_R1_MASTER_PORT_MIN_EV,
+ .master_max = CCI_REV_R1_MASTER_PORT_MAX_EV,
+ },
+};
+
+struct cci_pmu_drv_data {
+ void __iomem *base;
+ struct arm_pmu *cci_pmu;
+ int nr_irqs;
+ int irqs[CCI_PMU_MAX_HW_EVENTS];
+ unsigned long active_irqs;
+ struct perf_event *events[CCI_PMU_MAX_HW_EVENTS];
+ unsigned long used_mask[BITS_TO_LONGS(CCI_PMU_MAX_HW_EVENTS)];
+ struct pmu_port_event_ranges *port_ranges;
+ struct pmu_hw_events hw_events;
+};
+static struct cci_pmu_drv_data *pmu;
+
+static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
+{
+ int i;
+
+ for (i = 0; i < nr_irqs; i++)
+ if (irq == irqs[i])
+ return true;
+
+ return false;
+}
+
+static int probe_cci_revision(void)
+{
+ int rev;
+ rev = readl_relaxed(cci_ctrl_base + CCI_PID2) & CCI_PID2_REV_MASK;
+ rev >>= CCI_PID2_REV_SHIFT;
+
+ if (rev <= CCI_REV_R0_P4)
+ return CCI_REV_R0;
+ else if (rev <= CCI_REV_R1_P2)
+ return CCI_REV_R1;
+
+ return -ENOENT;
+}
+
+static struct pmu_port_event_ranges *port_range_by_rev(void)
+{
+ int rev = probe_cci_revision();
+
+ if (rev < 0)
+ return NULL;
+
+ return &port_event_range[rev];
+}
+
+static int pmu_is_valid_slave_event(u8 ev_code)
+{
+ return pmu->port_ranges->slave_min <= ev_code &&
+ ev_code <= pmu->port_ranges->slave_max;
+}
+
+static int pmu_is_valid_master_event(u8 ev_code)
+{
+ return pmu->port_ranges->master_min <= ev_code &&
+ ev_code <= pmu->port_ranges->master_max;
+}
+
+static int pmu_validate_hw_event(u8 hw_event)
+{
+ u8 ev_source = CCI_PMU_EVENT_SOURCE(hw_event);
+ u8 ev_code = CCI_PMU_EVENT_CODE(hw_event);
+
+ switch (ev_source) {
+ case CCI_PORT_S0:
+ case CCI_PORT_S1:
+ case CCI_PORT_S2:
+ case CCI_PORT_S3:
+ case CCI_PORT_S4:
+ /* Slave Interface */
+ if (pmu_is_valid_slave_event(ev_code))
+ return hw_event;
+ break;
+ case CCI_PORT_M0:
+ case CCI_PORT_M1:
+ case CCI_PORT_M2:
+ /* Master Interface */
+ if (pmu_is_valid_master_event(ev_code))
+ return hw_event;
+ break;
+ }
+
+ return -ENOENT;
+}
+
+static int pmu_is_valid_counter(struct arm_pmu *cci_pmu, int idx)
+{
+ return CCI_PMU_CYCLE_CNTR_IDX <= idx &&
+ idx <= CCI_PMU_CNTR_LAST(cci_pmu);
+}
+
+static u32 pmu_read_register(int idx, unsigned int offset)
+{
+ return readl_relaxed(pmu->base + CCI_PMU_CNTR_BASE(idx) + offset);
+}
+
+static void pmu_write_register(u32 value, int idx, unsigned int offset)
+{
+ return writel_relaxed(value, pmu->base + CCI_PMU_CNTR_BASE(idx) + offset);
+}
+
+static void pmu_disable_counter(int idx)
+{
+ pmu_write_register(0, idx, CCI_PMU_CNTR_CTRL);
+}
+
+static void pmu_enable_counter(int idx)
+{
+ pmu_write_register(1, idx, CCI_PMU_CNTR_CTRL);
+}
+
+static void pmu_set_event(int idx, unsigned long event)
+{
+ event &= CCI_PMU_EVENT_MASK;
+ pmu_write_register(event, idx, CCI_PMU_EVT_SEL);
+}
+
+static u32 pmu_get_max_counters(void)
+{
+ u32 n_cnts = (readl_relaxed(cci_ctrl_base + CCI_PMCR) &
+ CCI_PMCR_NCNT_MASK) >> CCI_PMCR_NCNT_SHIFT;
+
+ /* add 1 for cycle counter */
+ return n_cnts + 1;
+}
+
+static struct pmu_hw_events *pmu_get_hw_events(void)
+{
+ return &pmu->hw_events;
+}
+
+static int pmu_get_event_idx(struct pmu_hw_events *hw, struct perf_event *event)
+{
+ struct arm_pmu *cci_pmu = to_arm_pmu(event->pmu);
+ struct hw_perf_event *hw_event = &event->hw;
+ unsigned long cci_event = hw_event->config_base & CCI_PMU_EVENT_MASK;
+ int idx;
+
+ if (cci_event == CCI_PMU_CYCLES) {
+ if (test_and_set_bit(CCI_PMU_CYCLE_CNTR_IDX, hw->used_mask))
+ return -EAGAIN;
+
+ return CCI_PMU_CYCLE_CNTR_IDX;
+ }
+
+ for (idx = CCI_PMU_CNTR0_IDX; idx <= CCI_PMU_CNTR_LAST(cci_pmu); ++idx)
+ if (!test_and_set_bit(idx, hw->used_mask))
+ return idx;
+
+ /* No counters available */
+ return -EAGAIN;
+}
+
+static int pmu_map_event(struct perf_event *event)
+{
+ int mapping;
+ u8 config = event->attr.config & CCI_PMU_EVENT_MASK;
+
+ if (event->attr.type < PERF_TYPE_MAX)
+ return -ENOENT;
+
+ if (config == CCI_PMU_CYCLES)
+ mapping = config;
+ else
+ mapping = pmu_validate_hw_event(config);
+
+ return mapping;
+}
+
+static int pmu_request_irq(struct arm_pmu *cci_pmu, irq_handler_t handler)
+{
+ int i;
+ struct platform_device *pmu_device = cci_pmu->plat_device;
+
+ if (unlikely(!pmu_device))
+ return -ENODEV;
+
+ if (pmu->nr_irqs < 1) {
+ dev_err(&pmu_device->dev, "no irqs for CCI PMUs defined\n");
+ return -ENODEV;
+ }
+
+ /*
+ * Register all available CCI PMU interrupts. In the interrupt handler
+ * we iterate over the counters checking for interrupt source (the
+ * overflowing counter) and clear it.
+ *
+ * This should allow handling of non-unique interrupt for the counters.
+ */
+ for (i = 0; i < pmu->nr_irqs; i++) {
+ int err = request_irq(pmu->irqs[i], handler, IRQF_SHARED,
+ "arm-cci-pmu", cci_pmu);
+ if (err) {
+ dev_err(&pmu_device->dev, "unable to request IRQ%d for ARM CCI PMU counters\n",
+ pmu->irqs[i]);
+ return err;
+ }
+
+ set_bit(i, &pmu->active_irqs);
+ }
+
+ return 0;
+}
+
+static irqreturn_t pmu_handle_irq(int irq_num, void *dev)
+{
+ unsigned long flags;
+ struct arm_pmu *cci_pmu = (struct arm_pmu *)dev;
+ struct pmu_hw_events *events = cci_pmu->get_hw_events();
+ struct perf_sample_data data;
+ struct pt_regs *regs;
+ int idx, handled = IRQ_NONE;
+
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
+ regs = get_irq_regs();
+ /*
+ * Iterate over counters and update the corresponding perf events.
+ * This should work regardless of whether we have per-counter overflow
+ * interrupt or a combined overflow interrupt.
+ */
+ for (idx = CCI_PMU_CYCLE_CNTR_IDX; idx <= CCI_PMU_CNTR_LAST(cci_pmu); idx++) {
+ struct perf_event *event = events->events[idx];
+ struct hw_perf_event *hw_counter;
+
+ if (!event)
+ continue;
+
+ hw_counter = &event->hw;
+
+ /* Did this counter overflow? */
+ if (!pmu_read_register(idx, CCI_PMU_OVRFLW) & CCI_PMU_OVRFLW_FLAG)
+ continue;
+
+ pmu_write_register(CCI_PMU_OVRFLW_FLAG, idx, CCI_PMU_OVRFLW);
+
+ handled = IRQ_HANDLED;
+
+ armpmu_event_update(event);
+ perf_sample_data_init(&data, 0, hw_counter->last_period);
+ if (!armpmu_event_set_period(event))
+ continue;
+
+ if (perf_event_overflow(event, &data, regs))
+ cci_pmu->disable(event);
+ }
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+
+ return IRQ_RETVAL(handled);
+}
+
+static void pmu_free_irq(struct arm_pmu *cci_pmu)
+{
+ int i;
+
+ for (i = 0; i < pmu->nr_irqs; i++) {
+ if (!test_and_clear_bit(i, &pmu->active_irqs))
+ continue;
+
+ free_irq(pmu->irqs[i], cci_pmu);
+ }
+}
+
+static void pmu_enable_event(struct perf_event *event)
+{
+ unsigned long flags;
+ struct arm_pmu *cci_pmu = to_arm_pmu(event->pmu);
+ struct pmu_hw_events *events = cci_pmu->get_hw_events();
+ struct hw_perf_event *hw_counter = &event->hw;
+ int idx = hw_counter->idx;
+
+ if (unlikely(!pmu_is_valid_counter(cci_pmu, idx))) {
+ dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx);
+ return;
+ }
+
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
+
+ /* Configure the event to count, unless you are counting cycles */
+ if (idx != CCI_PMU_CYCLE_CNTR_IDX)
+ pmu_set_event(idx, hw_counter->config_base);
+
+ pmu_enable_counter(idx);
+
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static void pmu_disable_event(struct perf_event *event)
+{
+ struct arm_pmu *cci_pmu = to_arm_pmu(event->pmu);
+ struct hw_perf_event *hw_counter = &event->hw;
+ int idx = hw_counter->idx;
+
+ if (unlikely(!pmu_is_valid_counter(cci_pmu, idx))) {
+ dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx);
+ return;
+ }
+
+ pmu_disable_counter(idx);
+}
+
+static void pmu_start(struct arm_pmu *cci_pmu)
+{
+ u32 val;
+ unsigned long flags;
+ struct pmu_hw_events *events = cci_pmu->get_hw_events();
+
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
+
+ /* Enable all the PMU counters. */
+ val = readl_relaxed(cci_ctrl_base + CCI_PMCR) | CCI_PMCR_CEN;
+ writel(val, cci_ctrl_base + CCI_PMCR);
+
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static void pmu_stop(struct arm_pmu *cci_pmu)
+{
+ u32 val;
+ unsigned long flags;
+ struct pmu_hw_events *events = cci_pmu->get_hw_events();
+
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
+
+ /* Disable all the PMU counters. */
+ val = readl_relaxed(cci_ctrl_base + CCI_PMCR) & ~CCI_PMCR_CEN;
+ writel(val, cci_ctrl_base + CCI_PMCR);
+
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static u32 pmu_read_counter(struct perf_event *event)
+{
+ struct arm_pmu *cci_pmu = to_arm_pmu(event->pmu);
+ struct hw_perf_event *hw_counter = &event->hw;
+ int idx = hw_counter->idx;
+ u32 value;
+
+ if (unlikely(!pmu_is_valid_counter(cci_pmu, idx))) {
+ dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx);
+ return 0;
+ }
+ value = pmu_read_register(idx, CCI_PMU_CNTR);
+
+ return value;
+}
+
+static void pmu_write_counter(struct perf_event *event, u32 value)
+{
+ struct arm_pmu *cci_pmu = to_arm_pmu(event->pmu);
+ struct hw_perf_event *hw_counter = &event->hw;
+ int idx = hw_counter->idx;
+
+ if (unlikely(!pmu_is_valid_counter(cci_pmu, idx)))
+ dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx);
+ else
+ pmu_write_register(value, idx, CCI_PMU_CNTR);
+}
+
+static int cci_pmu_init(struct arm_pmu *cci_pmu, struct platform_device *pdev)
+{
+ *cci_pmu = (struct arm_pmu){
+ .name = PMU_NAME,
+ .max_period = (1LLU << 32) - 1,
+ .get_hw_events = pmu_get_hw_events,
+ .get_event_idx = pmu_get_event_idx,
+ .map_event = pmu_map_event,
+ .request_irq = pmu_request_irq,
+ .handle_irq = pmu_handle_irq,
+ .free_irq = pmu_free_irq,
+ .enable = pmu_enable_event,
+ .disable = pmu_disable_event,
+ .start = pmu_start,
+ .stop = pmu_stop,
+ .read_counter = pmu_read_counter,
+ .write_counter = pmu_write_counter,
+ };
+
+ cci_pmu->plat_device = pdev;
+ cci_pmu->num_events = pmu_get_max_counters();
+
+ return armpmu_register(cci_pmu, -1);
+}
+
+static const struct of_device_id arm_cci_pmu_matches[] = {
+ {
+ .compatible = "arm,cci-400-pmu",
+ },
+ {},
+};
+
+static int cci_pmu_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int i, ret, irq;
+
+ pmu = devm_kzalloc(&pdev->dev, sizeof(*pmu), GFP_KERNEL);
+ if (!pmu)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pmu->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(pmu->base))
+ return -ENOMEM;
+
+ /*
+ * CCI PMU has 5 overflow signals - one per counter; but some may be tied
+ * together to a common interrupt.
+ */
+ pmu->nr_irqs = 0;
+ for (i = 0; i < CCI_PMU_MAX_HW_EVENTS; i++) {
+ irq = platform_get_irq(pdev, i);
+ if (irq < 0)
+ break;
+
+ if (is_duplicate_irq(irq, pmu->irqs, pmu->nr_irqs))
+ continue;
+
+ pmu->irqs[pmu->nr_irqs++] = irq;
+ }
+
+ /*
+ * Ensure that the device tree has as many interrupts as the number
+ * of counters.
+ */
+ if (i < CCI_PMU_MAX_HW_EVENTS) {
+ dev_warn(&pdev->dev, "In-correct number of interrupts: %d, should be %d\n",
+ i, CCI_PMU_MAX_HW_EVENTS);
+ return -EINVAL;
+ }
+
+ pmu->port_ranges = port_range_by_rev();
+ if (!pmu->port_ranges) {
+ dev_warn(&pdev->dev, "CCI PMU version not supported\n");
+ return -EINVAL;
+ }
+
+ pmu->cci_pmu = devm_kzalloc(&pdev->dev, sizeof(*(pmu->cci_pmu)), GFP_KERNEL);
+ if (!pmu->cci_pmu)
+ return -ENOMEM;
+
+ pmu->hw_events.events = pmu->events;
+ pmu->hw_events.used_mask = pmu->used_mask;
+ raw_spin_lock_init(&pmu->hw_events.pmu_lock);
+
+ ret = cci_pmu_init(pmu->cci_pmu, pdev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int cci_platform_probe(struct platform_device *pdev)
+{
+ if (!cci_probed())
+ return -ENODEV;
+
+ return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+}
+
+#endif /* CONFIG_HW_PERF_EVENTS */
+
struct cpu_port {
u64 mpidr;
u32 port;
@@ -120,7 +692,7 @@ int cci_ace_get_port(struct device_node *dn)
}
EXPORT_SYMBOL_GPL(cci_ace_get_port);
-static void __init cci_ace_init_ports(void)
+static void cci_ace_init_ports(void)
{
int port, cpu;
struct device_node *cpun;
@@ -386,7 +958,7 @@ static const struct of_device_id arm_cci_ctrl_if_matches[] = {
{},
};
-static int __init cci_probe(void)
+static int cci_probe(void)
{
struct cci_nb_ports const *cci_config;
int ret, i, nb_ace = 0, nb_ace_lite = 0;
@@ -490,7 +1062,7 @@ memalloc_err:
static int cci_init_status = -EAGAIN;
static DEFINE_MUTEX(cci_probing);
-static int __init cci_init(void)
+static int cci_init(void)
{
if (cci_init_status != -EAGAIN)
return cci_init_status;
@@ -502,18 +1074,55 @@ static int __init cci_init(void)
return cci_init_status;
}
+#ifdef CONFIG_HW_PERF_EVENTS
+static struct platform_driver cci_pmu_driver = {
+ .driver = {
+ .name = DRIVER_NAME_PMU,
+ .of_match_table = arm_cci_pmu_matches,
+ },
+ .probe = cci_pmu_probe,
+};
+
+static struct platform_driver cci_platform_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = arm_cci_matches,
+ },
+ .probe = cci_platform_probe,
+};
+
+static int __init cci_platform_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&cci_pmu_driver);
+ if (ret)
+ return ret;
+
+ return platform_driver_register(&cci_platform_driver);
+}
+
+#else
+
+static int __init cci_platform_init(void)
+{
+ return 0;
+}
+
+#endif
/*
* To sort out early init calls ordering a helper function is provided to
* check if the CCI driver has beed initialized. Function check if the driver
* has been initialized, if not it calls the init function that probes
* the driver and updates the return value.
*/
-bool __init cci_probed(void)
+bool cci_probed(void)
{
return cci_init() == 0;
}
EXPORT_SYMBOL_GPL(cci_probed);
early_initcall(cci_init);
+core_initcall(cci_platform_init);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("ARM CCI support");
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
index 19ab6ff53d59..553185318963 100644
--- a/drivers/bus/mvebu-mbus.c
+++ b/drivers/bus/mvebu-mbus.c
@@ -700,6 +700,7 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
phys_addr_t sdramwins_phys_base,
size_t sdramwins_size)
{
+ struct device_node *np;
int win;
mbus->mbuswins_base = ioremap(mbuswins_phys_base, mbuswins_size);
@@ -712,8 +713,11 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
return -ENOMEM;
}
- if (of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"))
+ np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric");
+ if (np) {
mbus->hw_io_coherency = 1;
+ of_node_put(np);
+ }
for (win = 0; win < mbus->soc->num_wins; win++)
mvebu_mbus_disable_window(mbus, win);
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 448ce5e29c56..c8f43295d42a 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -971,8 +971,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
struct acpi_resource_fixed_memory32 *fixmem32;
fixmem32 = &res->data.fixed_memory32;
- if (!fixmem32)
- return AE_NO_MEMORY;
hdp->hd_phys_address = fixmem32->address;
hdp->hd_address = ioremap(fixmem32->address,
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c
index e737772ad69a..de5a6dcfb3e2 100644
--- a/drivers/char/hw_random/via-rng.c
+++ b/drivers/char/hw_random/via-rng.c
@@ -221,7 +221,7 @@ static void __exit mod_exit(void)
module_init(mod_init);
module_exit(mod_exit);
-static struct x86_cpu_id via_rng_cpu_id[] = {
+static struct x86_cpu_id __maybe_unused via_rng_cpu_id[] = {
X86_FEATURE_MATCH(X86_FEATURE_XSTORE),
{}
};
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 190d4423653f..2f685f6eda48 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -193,8 +193,8 @@ int misc_register(struct miscdevice * misc)
if (misc->minor == MISC_DYNAMIC_MINOR) {
int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);
if (i >= DYNAMIC_MINORS) {
- mutex_unlock(&misc_mtx);
- return -EBUSY;
+ err = -EBUSY;
+ goto out;
}
misc->minor = DYNAMIC_MINORS - i - 1;
set_bit(i, misc_minors);
@@ -203,8 +203,8 @@ int misc_register(struct miscdevice * misc)
list_for_each_entry(c, &misc_list, list) {
if (c->minor == misc->minor) {
- mutex_unlock(&misc_mtx);
- return -EBUSY;
+ err = -EBUSY;
+ goto out;
}
}
}
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 7737b5bd26af..6f2031795ed7 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -269,14 +269,28 @@
/*
* Configuration information
*/
-#define INPUT_POOL_WORDS 128
-#define OUTPUT_POOL_WORDS 32
-#define SEC_XFER_SIZE 512
-#define EXTRACT_SIZE 10
+#define INPUT_POOL_SHIFT 12
+#define INPUT_POOL_WORDS (1 << (INPUT_POOL_SHIFT-5))
+#define OUTPUT_POOL_SHIFT 10
+#define OUTPUT_POOL_WORDS (1 << (OUTPUT_POOL_SHIFT-5))
+#define SEC_XFER_SIZE 512
+#define EXTRACT_SIZE 10
#define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long))
/*
+ * To allow fractional bits to be tracked, the following fields contain
+ * this many fractional bits:
+ *
+ * entropy_count, trickle_thresh
+ *
+ * 2*(ENTROPY_SHIFT + log2(poolbits)) must <= 31, or the multiply in
+ * credit_entropy_bits() needs to be 64 bits wide.
+ */
+#define ENTROPY_SHIFT 3
+#define ENTROPY_BITS(r) ((r)->entropy_count >> ENTROPY_SHIFT)
+
+/*
* The minimum number of bits of entropy before we wake up a read on
* /dev/random. Should be enough to do a significant reseed.
*/
@@ -290,105 +304,106 @@ static int random_read_wakeup_thresh = 64;
static int random_write_wakeup_thresh = 128;
/*
+ * The minimum number of seconds between urandom pool resending. We
+ * do this to limit the amount of entropy that can be drained from the
+ * input pool even if there are heavy demands on /dev/urandom.
+ */
+static int random_min_urandom_seed = 60;
+
+/*
* When the input pool goes over trickle_thresh, start dropping most
* samples to avoid wasting CPU time and reduce lock contention.
*/
-
-static int trickle_thresh __read_mostly = INPUT_POOL_WORDS * 28;
+static const int trickle_thresh = (INPUT_POOL_WORDS * 28) << ENTROPY_SHIFT;
static DEFINE_PER_CPU(int, trickle_count);
/*
- * A pool of size .poolwords is stirred with a primitive polynomial
- * of degree .poolwords over GF(2). The taps for various sizes are
- * defined below. They are chosen to be evenly spaced (minimum RMS
- * distance from evenly spaced; the numbers in the comments are a
- * scaled squared error sum) except for the last tap, which is 1 to
- * get the twisting happening as fast as possible.
+ * Originally, we used a primitive polynomial of degree .poolwords
+ * over GF(2). The taps for various sizes are defined below. They
+ * were chosen to be evenly spaced except for the last tap, which is 1
+ * to get the twisting happening as fast as possible.
+ *
+ * For the purposes of better mixing, we use the CRC-32 polynomial as
+ * well to make a (modified) twisted Generalized Feedback Shift
+ * Reigster
+ *
+ * (See M. Matsumoto & Y. Kurita, 1992. Twisted GFSR generators. ACM
+ * Transactions on Modeling and Computer Simulation 2(3):179-194.
+ * Also see M. Matsumoto & Y. Kurita, 1994. Twisted GFSR generators
+ * II. ACM Transactions on Mdeling and Computer Simulation 4:254-266)
+ *
+ * Thanks to Colin Plumb for suggesting this.
+ *
+ * The mixing operation is much less sensitive than the output hash,
+ * where we use SHA-1. All that we want of mixing operation is that
+ * it be a good non-cryptographic hash; i.e. it not produce collisions
+ * when fed "random" data of the sort we expect to see. As long as
+ * the pool state differs for different inputs, we have preserved the
+ * input entropy and done a good job. The fact that an intelligent
+ * attacker can construct inputs that will produce controlled
+ * alterations to the pool's state is not important because we don't
+ * consider such inputs to contribute any randomness. The only
+ * property we need with respect to them is that the attacker can't
+ * increase his/her knowledge of the pool's state. Since all
+ * additions are reversible (knowing the final state and the input,
+ * you can reconstruct the initial state), if an attacker has any
+ * uncertainty about the initial state, he/she can only shuffle that
+ * uncertainty about, but never cause any collisions (which would
+ * decrease the uncertainty).
+ *
+ * Our mixing functions were analyzed by Lacharme, Roeck, Strubel, and
+ * Videau in their paper, "The Linux Pseudorandom Number Generator
+ * Revisited" (see: http://eprint.iacr.org/2012/251.pdf). In their
+ * paper, they point out that we are not using a true Twisted GFSR,
+ * since Matsumoto & Kurita used a trinomial feedback polynomial (that
+ * is, with only three taps, instead of the six that we are using).
+ * As a result, the resulting polynomial is neither primitive nor
+ * irreducible, and hence does not have a maximal period over
+ * GF(2**32). They suggest a slight change to the generator
+ * polynomial which improves the resulting TGFSR polynomial to be
+ * irreducible, which we have made here.
*/
static struct poolinfo {
- int poolwords;
+ int poolbitshift, poolwords, poolbytes, poolbits, poolfracbits;
+#define S(x) ilog2(x)+5, (x), (x)*4, (x)*32, (x) << (ENTROPY_SHIFT+5)
int tap1, tap2, tap3, tap4, tap5;
} poolinfo_table[] = {
- /* x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 -- 105 */
- { 128, 103, 76, 51, 25, 1 },
- /* x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 -- 15 */
- { 32, 26, 20, 14, 7, 1 },
+ /* was: x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 */
+ /* x^128 + x^104 + x^76 + x^51 +x^25 + x + 1 */
+ { S(128), 104, 76, 51, 25, 1 },
+ /* was: x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 */
+ /* x^32 + x^26 + x^19 + x^14 + x^7 + x + 1 */
+ { S(32), 26, 19, 14, 7, 1 },
#if 0
/* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1 -- 115 */
- { 2048, 1638, 1231, 819, 411, 1 },
+ { S(2048), 1638, 1231, 819, 411, 1 },
/* x^1024 + x^817 + x^615 + x^412 + x^204 + x + 1 -- 290 */
- { 1024, 817, 615, 412, 204, 1 },
+ { S(1024), 817, 615, 412, 204, 1 },
/* x^1024 + x^819 + x^616 + x^410 + x^207 + x^2 + 1 -- 115 */
- { 1024, 819, 616, 410, 207, 2 },
+ { S(1024), 819, 616, 410, 207, 2 },
/* x^512 + x^411 + x^308 + x^208 + x^104 + x + 1 -- 225 */
- { 512, 411, 308, 208, 104, 1 },
+ { S(512), 411, 308, 208, 104, 1 },
/* x^512 + x^409 + x^307 + x^206 + x^102 + x^2 + 1 -- 95 */
- { 512, 409, 307, 206, 102, 2 },
+ { S(512), 409, 307, 206, 102, 2 },
/* x^512 + x^409 + x^309 + x^205 + x^103 + x^2 + 1 -- 95 */
- { 512, 409, 309, 205, 103, 2 },
+ { S(512), 409, 309, 205, 103, 2 },
/* x^256 + x^205 + x^155 + x^101 + x^52 + x + 1 -- 125 */
- { 256, 205, 155, 101, 52, 1 },
+ { S(256), 205, 155, 101, 52, 1 },
/* x^128 + x^103 + x^78 + x^51 + x^27 + x^2 + 1 -- 70 */
- { 128, 103, 78, 51, 27, 2 },
+ { S(128), 103, 78, 51, 27, 2 },
/* x^64 + x^52 + x^39 + x^26 + x^14 + x + 1 -- 15 */
- { 64, 52, 39, 26, 14, 1 },
+ { S(64), 52, 39, 26, 14, 1 },
#endif
};
-#define POOLBITS poolwords*32
-#define POOLBYTES poolwords*4
-
-/*
- * For the purposes of better mixing, we use the CRC-32 polynomial as
- * well to make a twisted Generalized Feedback Shift Reigster
- *
- * (See M. Matsumoto & Y. Kurita, 1992. Twisted GFSR generators. ACM
- * Transactions on Modeling and Computer Simulation 2(3):179-194.
- * Also see M. Matsumoto & Y. Kurita, 1994. Twisted GFSR generators
- * II. ACM Transactions on Mdeling and Computer Simulation 4:254-266)
- *
- * Thanks to Colin Plumb for suggesting this.
- *
- * We have not analyzed the resultant polynomial to prove it primitive;
- * in fact it almost certainly isn't. Nonetheless, the irreducible factors
- * of a random large-degree polynomial over GF(2) are more than large enough
- * that periodicity is not a concern.
- *
- * The input hash is much less sensitive than the output hash. All
- * that we want of it is that it be a good non-cryptographic hash;
- * i.e. it not produce collisions when fed "random" data of the sort
- * we expect to see. As long as the pool state differs for different
- * inputs, we have preserved the input entropy and done a good job.
- * The fact that an intelligent attacker can construct inputs that
- * will produce controlled alterations to the pool's state is not
- * important because we don't consider such inputs to contribute any
- * randomness. The only property we need with respect to them is that
- * the attacker can't increase his/her knowledge of the pool's state.
- * Since all additions are reversible (knowing the final state and the
- * input, you can reconstruct the initial state), if an attacker has
- * any uncertainty about the initial state, he/she can only shuffle
- * that uncertainty about, but never cause any collisions (which would
- * decrease the uncertainty).
- *
- * The chosen system lets the state of the pool be (essentially) the input
- * modulo the generator polymnomial. Now, for random primitive polynomials,
- * this is a universal class of hash functions, meaning that the chance
- * of a collision is limited by the attacker's knowledge of the generator
- * polynomail, so if it is chosen at random, an attacker can never force
- * a collision. Here, we use a fixed polynomial, but we *can* assume that
- * ###--> it is unknown to the processes generating the input entropy. <-###
- * Because of this important property, this is a good, collision-resistant
- * hash; hash collisions will occur no more often than chance.
- */
-
/*
* Static global variables
*/
@@ -417,20 +432,21 @@ module_param(debug, bool, 0644);
struct entropy_store;
struct entropy_store {
/* read-only data: */
- struct poolinfo *poolinfo;
+ const struct poolinfo *poolinfo;
__u32 *pool;
const char *name;
struct entropy_store *pull;
- int limit;
/* read-write data: */
+ unsigned long last_pulled;
spinlock_t lock;
- unsigned add_ptr;
- unsigned input_rotate;
+ unsigned short add_ptr;
+ unsigned short input_rotate;
int entropy_count;
int entropy_total;
unsigned int initialized:1;
- bool last_data_init;
+ unsigned int limit:1;
+ unsigned int last_data_init:1;
__u8 last_data[EXTRACT_SIZE];
};
@@ -498,7 +514,7 @@ static void _mix_pool_bytes(struct entropy_store *r, const void *in,
/* mix one byte at a time to simplify size handling and churn faster */
while (nbytes--) {
- w = rol32(*bytes++, input_rotate & 31);
+ w = rol32(*bytes++, input_rotate);
i = (i - 1) & wordmask;
/* XOR in the various taps */
@@ -518,7 +534,7 @@ static void _mix_pool_bytes(struct entropy_store *r, const void *in,
* rotation, so that successive passes spread the
* input bits across the pool evenly.
*/
- input_rotate += i ? 7 : 14;
+ input_rotate = (input_rotate + (i ? 7 : 14)) & 31;
}
ACCESS_ONCE(r->input_rotate) = input_rotate;
@@ -561,29 +577,38 @@ struct fast_pool {
* collector. It's hardcoded for an 128 bit pool and assumes that any
* locks that might be needed are taken by the caller.
*/
-static void fast_mix(struct fast_pool *f, const void *in, int nbytes)
+static void fast_mix(struct fast_pool *f, __u32 input[4])
{
- const char *bytes = in;
__u32 w;
- unsigned i = f->count;
unsigned input_rotate = f->rotate;
- while (nbytes--) {
- w = rol32(*bytes++, input_rotate & 31) ^ f->pool[i & 3] ^
- f->pool[(i + 1) & 3];
- f->pool[i & 3] = (w >> 3) ^ twist_table[w & 7];
- input_rotate += (i++ & 3) ? 7 : 14;
- }
- f->count = i;
+ w = rol32(input[0], input_rotate) ^ f->pool[0] ^ f->pool[3];
+ f->pool[0] = (w >> 3) ^ twist_table[w & 7];
+ input_rotate = (input_rotate + 14) & 31;
+ w = rol32(input[1], input_rotate) ^ f->pool[1] ^ f->pool[0];
+ f->pool[1] = (w >> 3) ^ twist_table[w & 7];
+ input_rotate = (input_rotate + 7) & 31;
+ w = rol32(input[2], input_rotate) ^ f->pool[2] ^ f->pool[1];
+ f->pool[2] = (w >> 3) ^ twist_table[w & 7];
+ input_rotate = (input_rotate + 7) & 31;
+ w = rol32(input[3], input_rotate) ^ f->pool[3] ^ f->pool[2];
+ f->pool[3] = (w >> 3) ^ twist_table[w & 7];
+ input_rotate = (input_rotate + 7) & 31;
+
f->rotate = input_rotate;
+ f->count++;
}
/*
- * Credit (or debit) the entropy store with n bits of entropy
+ * Credit (or debit) the entropy store with n bits of entropy.
+ * Use credit_entropy_bits_safe() if the value comes from userspace
+ * or otherwise should be checked for extreme values.
*/
static void credit_entropy_bits(struct entropy_store *r, int nbits)
{
int entropy_count, orig;
+ const int pool_size = r->poolinfo->poolfracbits;
+ int nfrac = nbits << ENTROPY_SHIFT;
if (!nbits)
return;
@@ -591,13 +616,50 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
retry:
entropy_count = orig = ACCESS_ONCE(r->entropy_count);
- entropy_count += nbits;
+ if (nfrac < 0) {
+ /* Debit */
+ entropy_count += nfrac;
+ } else {
+ /*
+ * Credit: we have to account for the possibility of
+ * overwriting already present entropy. Even in the
+ * ideal case of pure Shannon entropy, new contributions
+ * approach the full value asymptotically:
+ *
+ * entropy <- entropy + (pool_size - entropy) *
+ * (1 - exp(-add_entropy/pool_size))
+ *
+ * For add_entropy <= pool_size/2 then
+ * (1 - exp(-add_entropy/pool_size)) >=
+ * (add_entropy/pool_size)*0.7869...
+ * so we can approximate the exponential with
+ * 3/4*add_entropy/pool_size and still be on the
+ * safe side by adding at most pool_size/2 at a time.
+ *
+ * The use of pool_size-2 in the while statement is to
+ * prevent rounding artifacts from making the loop
+ * arbitrarily long; this limits the loop to log2(pool_size)*2
+ * turns no matter how large nbits is.
+ */
+ int pnfrac = nfrac;
+ const int s = r->poolinfo->poolbitshift + ENTROPY_SHIFT + 2;
+ /* The +2 corresponds to the /4 in the denominator */
+
+ do {
+ unsigned int anfrac = min(pnfrac, pool_size/2);
+ unsigned int add =
+ ((pool_size - entropy_count)*anfrac*3) >> s;
+
+ entropy_count += add;
+ pnfrac -= anfrac;
+ } while (unlikely(entropy_count < pool_size-2 && pnfrac));
+ }
if (entropy_count < 0) {
DEBUG_ENT("negative entropy/overflow\n");
entropy_count = 0;
- } else if (entropy_count > r->poolinfo->POOLBITS)
- entropy_count = r->poolinfo->POOLBITS;
+ } else if (entropy_count > pool_size)
+ entropy_count = pool_size;
if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
goto retry;
@@ -607,16 +669,29 @@ retry:
r->initialized = 1;
}
- trace_credit_entropy_bits(r->name, nbits, entropy_count,
+ trace_credit_entropy_bits(r->name, nbits,
+ entropy_count >> ENTROPY_SHIFT,
r->entropy_total, _RET_IP_);
/* should we wake readers? */
- if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) {
+ if (r == &input_pool &&
+ (entropy_count >> ENTROPY_SHIFT) >= random_read_wakeup_thresh) {
wake_up_interruptible(&random_read_wait);
kill_fasync(&fasync, SIGIO, POLL_IN);
}
}
+static void credit_entropy_bits_safe(struct entropy_store *r, int nbits)
+{
+ const int nbits_max = (int)(~0U >> (ENTROPY_SHIFT + 1));
+
+ /* Cap the value to avoid overflows */
+ nbits = min(nbits, nbits_max);
+ nbits = max(nbits, -nbits_max);
+
+ credit_entropy_bits(r, nbits);
+}
+
/*********************************************************************
*
* Entropy input management
@@ -640,12 +715,19 @@ struct timer_rand_state {
*/
void add_device_randomness(const void *buf, unsigned int size)
{
- unsigned long time = get_cycles() ^ jiffies;
+ unsigned long time = random_get_entropy() ^ jiffies;
+ unsigned long flags;
+
+ trace_add_device_randomness(size, _RET_IP_);
+ spin_lock_irqsave(&input_pool.lock, flags);
+ _mix_pool_bytes(&input_pool, buf, size, NULL);
+ _mix_pool_bytes(&input_pool, &time, sizeof(time), NULL);
+ spin_unlock_irqrestore(&input_pool.lock, flags);
- mix_pool_bytes(&input_pool, buf, size, NULL);
- mix_pool_bytes(&input_pool, &time, sizeof(time), NULL);
- mix_pool_bytes(&nonblocking_pool, buf, size, NULL);
- mix_pool_bytes(&nonblocking_pool, &time, sizeof(time), NULL);
+ spin_lock_irqsave(&nonblocking_pool.lock, flags);
+ _mix_pool_bytes(&nonblocking_pool, buf, size, NULL);
+ _mix_pool_bytes(&nonblocking_pool, &time, sizeof(time), NULL);
+ spin_unlock_irqrestore(&nonblocking_pool.lock, flags);
}
EXPORT_SYMBOL(add_device_randomness);
@@ -672,12 +754,12 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
preempt_disable();
/* if over the trickle threshold, use only 1 in 4096 samples */
- if (input_pool.entropy_count > trickle_thresh &&
+ if (ENTROPY_BITS(&input_pool) > trickle_thresh &&
((__this_cpu_inc_return(trickle_count) - 1) & 0xfff))
goto out;
sample.jiffies = jiffies;
- sample.cycles = get_cycles();
+ sample.cycles = random_get_entropy();
sample.num = num;
mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL);
@@ -744,20 +826,21 @@ void add_interrupt_randomness(int irq, int irq_flags)
struct fast_pool *fast_pool = &__get_cpu_var(irq_randomness);
struct pt_regs *regs = get_irq_regs();
unsigned long now = jiffies;
- __u32 input[4], cycles = get_cycles();
-
- input[0] = cycles ^ jiffies;
- input[1] = irq;
- if (regs) {
- __u64 ip = instruction_pointer(regs);
- input[2] = ip;
- input[3] = ip >> 32;
- }
+ cycles_t cycles = random_get_entropy();
+ __u32 input[4], c_high, j_high;
+ __u64 ip;
+
+ c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
+ j_high = (sizeof(now) > 4) ? now >> 32 : 0;
+ input[0] = cycles ^ j_high ^ irq;
+ input[1] = now ^ c_high;
+ ip = regs ? instruction_pointer(regs) : _RET_IP_;
+ input[2] = ip;
+ input[3] = ip >> 32;
- fast_mix(fast_pool, input, sizeof(input));
+ fast_mix(fast_pool, input);
- if ((fast_pool->count & 1023) &&
- !time_after(now, fast_pool->last + HZ))
+ if ((fast_pool->count & 63) && !time_after(now, fast_pool->last + HZ))
return;
fast_pool->last = now;
@@ -811,8 +894,18 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
{
__u32 tmp[OUTPUT_POOL_WORDS];
- if (r->pull && r->entropy_count < nbytes * 8 &&
- r->entropy_count < r->poolinfo->POOLBITS) {
+ if (r->limit == 0 && random_min_urandom_seed) {
+ unsigned long now = jiffies;
+
+ if (time_before(now,
+ r->last_pulled + random_min_urandom_seed * HZ)) {
+ return;
+ }
+ r->last_pulled = now;
+ }
+ if (r->pull &&
+ r->entropy_count < (nbytes << (ENTROPY_SHIFT + 3)) &&
+ r->entropy_count < r->poolinfo->poolfracbits) {
/* If we're limited, always leave two wakeup worth's BITS */
int rsvd = r->limit ? 0 : random_read_wakeup_thresh/4;
int bytes = nbytes;
@@ -824,7 +917,8 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
DEBUG_ENT("going to reseed %s with %d bits "
"(%zu of %d requested)\n",
- r->name, bytes * 8, nbytes * 8, r->entropy_count);
+ r->name, bytes * 8, nbytes * 8,
+ r->entropy_count >> ENTROPY_SHIFT);
bytes = extract_entropy(r->pull, tmp, bytes,
random_read_wakeup_thresh / 8, rsvd);
@@ -850,41 +944,44 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
{
unsigned long flags;
int wakeup_write = 0;
+ int have_bytes;
+ int entropy_count, orig;
+ size_t ibytes;
/* Hold lock while accounting */
spin_lock_irqsave(&r->lock, flags);
- BUG_ON(r->entropy_count > r->poolinfo->POOLBITS);
+ BUG_ON(r->entropy_count > r->poolinfo->poolfracbits);
DEBUG_ENT("trying to extract %zu bits from %s\n",
nbytes * 8, r->name);
/* Can we pull enough? */
- if (r->entropy_count / 8 < min + reserved) {
- nbytes = 0;
- } else {
- int entropy_count, orig;
retry:
- entropy_count = orig = ACCESS_ONCE(r->entropy_count);
+ entropy_count = orig = ACCESS_ONCE(r->entropy_count);
+ have_bytes = entropy_count >> (ENTROPY_SHIFT + 3);
+ ibytes = nbytes;
+ if (have_bytes < min + reserved) {
+ ibytes = 0;
+ } else {
/* If limited, never pull more than available */
- if (r->limit && nbytes + reserved >= entropy_count / 8)
- nbytes = entropy_count/8 - reserved;
-
- if (entropy_count / 8 >= nbytes + reserved) {
- entropy_count -= nbytes*8;
- if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
- goto retry;
- } else {
- entropy_count = reserved;
- if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
- goto retry;
- }
+ if (r->limit && ibytes + reserved >= have_bytes)
+ ibytes = have_bytes - reserved;
- if (entropy_count < random_write_wakeup_thresh)
+ 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;
+
+ if ((r->entropy_count >> ENTROPY_SHIFT)
+ < random_write_wakeup_thresh)
wakeup_write = 1;
}
DEBUG_ENT("debiting %zu entropy credits from %s%s\n",
- nbytes * 8, r->name, r->limit ? "" : " (unlimited)");
+ ibytes * 8, r->name, r->limit ? "" : " (unlimited)");
spin_unlock_irqrestore(&r->lock, flags);
@@ -893,7 +990,7 @@ retry:
kill_fasync(&fasync, SIGIO, POLL_OUT);
}
- return nbytes;
+ return ibytes;
}
static void extract_buf(struct entropy_store *r, __u8 *out)
@@ -901,7 +998,7 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
int i;
union {
__u32 w[5];
- unsigned long l[LONGS(EXTRACT_SIZE)];
+ unsigned long l[LONGS(20)];
} hash;
__u32 workspace[SHA_WORKSPACE_WORDS];
__u8 extract[64];
@@ -914,6 +1011,17 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
sha_transform(hash.w, (__u8 *)(r->pool + i), workspace);
/*
+ * If we have a architectural hardware random number
+ * generator, mix that in, too.
+ */
+ for (i = 0; i < LONGS(20); i++) {
+ unsigned long v;
+ if (!arch_get_random_long(&v))
+ break;
+ hash.l[i] ^= v;
+ }
+
+ /*
* We mix the hash back into the pool to prevent backtracking
* attacks (where the attacker knows the state of the pool
* plus the current outputs, and attempts to find previous
@@ -942,17 +1050,6 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
hash.w[1] ^= hash.w[4];
hash.w[2] ^= rol32(hash.w[2], 16);
- /*
- * If we have a architectural hardware random number
- * generator, mix that in, too.
- */
- for (i = 0; i < LONGS(EXTRACT_SIZE); i++) {
- unsigned long v;
- if (!arch_get_random_long(&v))
- break;
- hash.l[i] ^= v;
- }
-
memcpy(out, &hash, EXTRACT_SIZE);
memset(&hash, 0, sizeof(hash));
}
@@ -968,10 +1065,10 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
if (fips_enabled) {
spin_lock_irqsave(&r->lock, flags);
if (!r->last_data_init) {
- r->last_data_init = true;
+ r->last_data_init = 1;
spin_unlock_irqrestore(&r->lock, flags);
trace_extract_entropy(r->name, EXTRACT_SIZE,
- r->entropy_count, _RET_IP_);
+ ENTROPY_BITS(r), _RET_IP_);
xfer_secondary_pool(r, EXTRACT_SIZE);
extract_buf(r, tmp);
spin_lock_irqsave(&r->lock, flags);
@@ -980,7 +1077,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
spin_unlock_irqrestore(&r->lock, flags);
}
- trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_);
+ trace_extract_entropy(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
xfer_secondary_pool(r, nbytes);
nbytes = account(r, nbytes, min, reserved);
@@ -1013,7 +1110,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
ssize_t ret = 0, i;
__u8 tmp[EXTRACT_SIZE];
- trace_extract_entropy_user(r->name, nbytes, r->entropy_count, _RET_IP_);
+ trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
xfer_secondary_pool(r, nbytes);
nbytes = account(r, nbytes, 0, 0);
@@ -1053,6 +1150,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
*/
void get_random_bytes(void *buf, int nbytes)
{
+ trace_get_random_bytes(nbytes, _RET_IP_);
extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
}
EXPORT_SYMBOL(get_random_bytes);
@@ -1071,7 +1169,7 @@ void get_random_bytes_arch(void *buf, int nbytes)
{
char *p = buf;
- trace_get_random_bytes(nbytes, _RET_IP_);
+ trace_get_random_bytes_arch(nbytes, _RET_IP_);
while (nbytes) {
unsigned long v;
int chunk = min(nbytes, (int)sizeof(unsigned long));
@@ -1107,9 +1205,10 @@ static void init_std_data(struct entropy_store *r)
r->entropy_count = 0;
r->entropy_total = 0;
- r->last_data_init = false;
+ r->last_data_init = 0;
+ r->last_pulled = jiffies;
mix_pool_bytes(r, &now, sizeof(now), NULL);
- for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) {
+ for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
if (!arch_get_random_long(&rv))
break;
mix_pool_bytes(r, &rv, sizeof(rv), NULL);
@@ -1185,8 +1284,8 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
DEBUG_ENT("sleeping?\n");
wait_event_interruptible(random_read_wait,
- input_pool.entropy_count >=
- random_read_wakeup_thresh);
+ ENTROPY_BITS(&input_pool) >=
+ random_read_wakeup_thresh);
DEBUG_ENT("awake\n");
@@ -1222,9 +1321,9 @@ random_poll(struct file *file, poll_table * wait)
poll_wait(file, &random_read_wait, wait);
poll_wait(file, &random_write_wait, wait);
mask = 0;
- if (input_pool.entropy_count >= random_read_wakeup_thresh)
+ if (ENTROPY_BITS(&input_pool) >= random_read_wakeup_thresh)
mask |= POLLIN | POLLRDNORM;
- if (input_pool.entropy_count < random_write_wakeup_thresh)
+ if (ENTROPY_BITS(&input_pool) < random_write_wakeup_thresh)
mask |= POLLOUT | POLLWRNORM;
return mask;
}
@@ -1275,7 +1374,8 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
switch (cmd) {
case RNDGETENTCNT:
/* inherently racy, no point locking */
- if (put_user(input_pool.entropy_count, p))
+ ent_count = ENTROPY_BITS(&input_pool);
+ if (put_user(ent_count, p))
return -EFAULT;
return 0;
case RNDADDTOENTCNT:
@@ -1283,7 +1383,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
return -EPERM;
if (get_user(ent_count, p))
return -EFAULT;
- credit_entropy_bits(&input_pool, ent_count);
+ credit_entropy_bits_safe(&input_pool, ent_count);
return 0;
case RNDADDENTROPY:
if (!capable(CAP_SYS_ADMIN))
@@ -1298,7 +1398,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
size);
if (retval < 0)
return retval;
- credit_entropy_bits(&input_pool, ent_count);
+ credit_entropy_bits_safe(&input_pool, ent_count);
return 0;
case RNDZAPENTCNT:
case RNDCLEARPOOL:
@@ -1405,6 +1505,23 @@ static int proc_do_uuid(struct ctl_table *table, int write,
return proc_dostring(&fake_table, write, buffer, lenp, ppos);
}
+/*
+ * Return entropy available scaled to integral bits
+ */
+static int proc_do_entropy(ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ ctl_table fake_table;
+ int entropy_count;
+
+ entropy_count = *(int *)table->data >> ENTROPY_SHIFT;
+
+ fake_table.data = &entropy_count;
+ fake_table.maxlen = sizeof(entropy_count);
+
+ return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
+}
+
static int sysctl_poolsize = INPUT_POOL_WORDS * 32;
extern struct ctl_table random_table[];
struct ctl_table random_table[] = {
@@ -1419,7 +1536,7 @@ struct ctl_table random_table[] = {
.procname = "entropy_avail",
.maxlen = sizeof(int),
.mode = 0444,
- .proc_handler = proc_dointvec,
+ .proc_handler = proc_do_entropy,
.data = &input_pool.entropy_count,
},
{
@@ -1441,6 +1558,13 @@ struct ctl_table random_table[] = {
.extra2 = &max_write_thresh,
},
{
+ .procname = "urandom_min_reseed_secs",
+ .data = &random_min_urandom_seed,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {
.procname = "boot_id",
.data = &sysctl_bootid,
.maxlen = 16,
@@ -1459,12 +1583,11 @@ struct ctl_table random_table[] = {
static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned;
-static int __init random_int_secret_init(void)
+int random_int_secret_init(void)
{
get_random_bytes(random_int_secret, sizeof(random_int_secret));
return 0;
}
-late_initcall(random_int_secret_init);
/*
* Get a random word for internal kernel use only. Similar to urandom but
@@ -1483,7 +1606,7 @@ unsigned int get_random_int(void)
hash = get_cpu_var(get_random_int_hash);
- hash[0] += current->pid + jiffies + get_cycles();
+ hash[0] += current->pid + jiffies + random_get_entropy();
md5_transform(hash, random_int_secret);
ret = hash[0];
put_cpu_var(get_random_int_hash);
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index f3223aac4df1..db5fa4e9b9e5 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -285,9 +285,9 @@ static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd,
static const struct file_operations raw_fops = {
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.write = do_sync_write,
- .aio_write = blkdev_aio_write,
+ .write_iter = blkdev_write_iter,
.fsync = blkdev_fsync,
.open = raw_open,
.release = raw_release,
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 3413380086d5..8eb4799237f0 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -8,6 +8,4 @@ obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o
obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o
-ifdef CONFIG_COMMON_CLK
obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o
-endif
diff --git a/drivers/clocksource/em_sti.c b/drivers/clocksource/em_sti.c
index b9c81b7c3a3b..3a5909c12d42 100644
--- a/drivers/clocksource/em_sti.c
+++ b/drivers/clocksource/em_sti.c
@@ -301,7 +301,7 @@ static void em_sti_register_clockevent(struct em_sti_priv *p)
ced->name = dev_name(&p->pdev->dev);
ced->features = CLOCK_EVT_FEAT_ONESHOT;
ced->rating = 200;
- ced->cpumask = cpumask_of(0);
+ ced->cpumask = cpu_possible_mask;
ced->set_next_event = em_sti_clock_event_next;
ced->set_mode = em_sti_clock_event_mode;
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index a1260b4549db..d2c3253e015e 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -986,6 +986,10 @@ static int __init acpi_cpufreq_init(void)
{
int ret;
+ /* don't keep reloading if cpufreq_driver exists */
+ if (cpufreq_get_current_driver())
+ return 0;
+
if (acpi_disabled)
return 0;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 89b3c52cd5c3..04548f7023af 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1460,6 +1460,9 @@ unsigned int cpufreq_get(unsigned int cpu)
{
unsigned int ret_freq = 0;
+ if (cpufreq_disabled() || !cpufreq_driver)
+ return -ENOENT;
+
if (!down_read_trylock(&cpufreq_rwsem))
return 0;
diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c
index d514c152fd1a..be5380ecdcd4 100644
--- a/drivers/cpufreq/exynos5440-cpufreq.c
+++ b/drivers/cpufreq/exynos5440-cpufreq.c
@@ -457,7 +457,7 @@ err_free_table:
opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
err_put_node:
of_node_put(np);
- dev_err(dvfs_info->dev, "%s: failed initialization\n", __func__);
+ dev_err(&pdev->dev, "%s: failed initialization\n", __func__);
return ret;
}
diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c
index d81c4e5ea0ad..70438de5c0e4 100644
--- a/drivers/cpufreq/pcc-cpufreq.c
+++ b/drivers/cpufreq/pcc-cpufreq.c
@@ -396,15 +396,14 @@ static int __init pcc_cpufreq_probe(void)
struct pcc_memory_resource *mem_resource;
struct pcc_register_resource *reg_resource;
union acpi_object *out_obj, *member;
- acpi_handle handle, osc_handle, pcch_handle;
+ acpi_handle handle, osc_handle;
int ret = 0;
status = acpi_get_handle(NULL, "\\_SB", &handle);
if (ACPI_FAILURE(status))
return -ENODEV;
- status = acpi_get_handle(handle, "PCCH", &pcch_handle);
- if (ACPI_FAILURE(status))
+ if (!acpi_has_method(handle, "PCCH"))
return -ENODEV;
status = acpi_get_handle(handle, "_OSC", &osc_handle);
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index 7c63b72ecd75..86a0d415b9a7 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -2209,6 +2209,13 @@ static int __init caam_algapi_init(void)
priv = dev_get_drvdata(ctrldev);
of_node_put(dev_node);
+ /*
+ * If priv is NULL, it's probably because the caam driver wasn't
+ * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
+ */
+ if (!priv)
+ return -ENODEV;
+
INIT_LIST_HEAD(&priv->alg_list);
atomic_set(&priv->tfm_count, -1);
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index e732bd962e98..ca6218eee460 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -1833,6 +1833,13 @@ static int __init caam_algapi_hash_init(void)
priv = dev_get_drvdata(ctrldev);
of_node_put(dev_node);
+ /*
+ * If priv is NULL, it's probably because the caam driver wasn't
+ * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
+ */
+ if (!priv)
+ return -ENODEV;
+
INIT_LIST_HEAD(&priv->hash_list);
atomic_set(&priv->tfm_count, -1);
diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c
index d1939a9539c0..588ad2288f82 100644
--- a/drivers/crypto/caam/caamrng.c
+++ b/drivers/crypto/caam/caamrng.c
@@ -298,6 +298,13 @@ static int __init caam_rng_init(void)
priv = dev_get_drvdata(ctrldev);
of_node_put(dev_node);
+ /*
+ * If priv is NULL, it's probably because the caam driver wasn't
+ * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
+ */
+ if (!priv)
+ return -ENODEV;
+
caam_init_rng(&rng_ctx, priv->jrdev[0]);
dev_info(priv->jrdev[0], "registering rng-caam\n");
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index b010d42a1803..26438cd12685 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -13,82 +13,75 @@
#include "error.h"
#include "ctrl.h"
-static int caam_remove(struct platform_device *pdev)
-{
- struct device *ctrldev;
- struct caam_drv_private *ctrlpriv;
- struct caam_drv_private_jr *jrpriv;
- struct caam_full __iomem *topregs;
- int ring, ret = 0;
-
- ctrldev = &pdev->dev;
- ctrlpriv = dev_get_drvdata(ctrldev);
- topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
-
- /* shut down JobRs */
- for (ring = 0; ring < ctrlpriv->total_jobrs; ring++) {
- ret |= caam_jr_shutdown(ctrlpriv->jrdev[ring]);
- jrpriv = dev_get_drvdata(ctrlpriv->jrdev[ring]);
- irq_dispose_mapping(jrpriv->irq);
- }
-
- /* Shut down debug views */
-#ifdef CONFIG_DEBUG_FS
- debugfs_remove_recursive(ctrlpriv->dfs_root);
-#endif
-
- /* Unmap controller region */
- iounmap(&topregs->ctrl);
-
- kfree(ctrlpriv->jrdev);
- kfree(ctrlpriv);
-
- return ret;
-}
-
/*
* Descriptor to instantiate RNG State Handle 0 in normal mode and
* load the JDKEK, TDKEK and TDSK registers
*/
-static void build_instantiation_desc(u32 *desc)
+static void build_instantiation_desc(u32 *desc, int handle, int do_sk)
{
- u32 *jump_cmd;
+ u32 *jump_cmd, op_flags;
init_job_desc(desc, 0);
+ op_flags = OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+ (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INIT;
+
/* INIT RNG in non-test mode */
- append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
- OP_ALG_AS_INIT);
+ append_operation(desc, op_flags);
+
+ if (!handle && do_sk) {
+ /*
+ * For SH0, Secure Keys must be generated as well
+ */
+
+ /* wait for done */
+ jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
+ set_jump_tgt_here(desc, jump_cmd);
+
+ /*
+ * load 1 to clear written reg:
+ * resets the done interrrupt and returns the RNG to idle.
+ */
+ append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
+
+ /* Initialize State Handle */
+ append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+ OP_ALG_AAI_RNG4_SK);
+ }
- /* wait for done */
- jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
- set_jump_tgt_here(desc, jump_cmd);
+ append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT);
+}
- /*
- * load 1 to clear written reg:
- * resets the done interrupt and returns the RNG to idle.
- */
- append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
+/* Descriptor for deinstantiation of State Handle 0 of the RNG block. */
+static void build_deinstantiation_desc(u32 *desc, int handle)
+{
+ init_job_desc(desc, 0);
- /* generate secure keys (non-test) */
+ /* Uninstantiate State Handle 0 */
append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
- OP_ALG_RNG4_SK);
+ (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INITFINAL);
+
+ append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT);
}
-static int instantiate_rng(struct device *ctrldev)
+/*
+ * run_descriptor_deco0 - runs a descriptor on DECO0, under direct control of
+ * the software (no JR/QI used).
+ * @ctrldev - pointer to device
+ * @status - descriptor status, after being run
+ *
+ * Return: - 0 if no error occurred
+ * - -ENODEV if the DECO couldn't be acquired
+ * - -EAGAIN if an error occurred while executing the descriptor
+ */
+static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,
+ u32 *status)
{
struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
struct caam_full __iomem *topregs;
unsigned int timeout = 100000;
- u32 *desc;
- int i, ret = 0;
-
- desc = kmalloc(CAAM_CMD_SZ * 6, GFP_KERNEL | GFP_DMA);
- if (!desc) {
- dev_err(ctrldev, "can't allocate RNG init descriptor memory\n");
- return -ENOMEM;
- }
- build_instantiation_desc(desc);
+ u32 deco_dbg_reg, flags;
+ int i;
/* Set the bit to request direct access to DECO0 */
topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
@@ -100,36 +93,221 @@ static int instantiate_rng(struct device *ctrldev)
if (!timeout) {
dev_err(ctrldev, "failed to acquire DECO 0\n");
- ret = -EIO;
- goto out;
+ clrbits32(&topregs->ctrl.deco_rq, DECORR_RQD0ENABLE);
+ return -ENODEV;
}
for (i = 0; i < desc_len(desc); i++)
- topregs->deco.descbuf[i] = *(desc + i);
+ wr_reg32(&topregs->deco.descbuf[i], *(desc + i));
- wr_reg32(&topregs->deco.jr_ctl_hi, DECO_JQCR_WHL | DECO_JQCR_FOUR);
+ flags = DECO_JQCR_WHL;
+ /*
+ * If the descriptor length is longer than 4 words, then the
+ * FOUR bit in JRCTRL register must be set.
+ */
+ if (desc_len(desc) >= 4)
+ flags |= DECO_JQCR_FOUR;
+
+ /* Instruct the DECO to execute it */
+ wr_reg32(&topregs->deco.jr_ctl_hi, flags);
timeout = 10000000;
- while ((rd_reg32(&topregs->deco.desc_dbg) & DECO_DBG_VALID) &&
- --timeout)
+ do {
+ deco_dbg_reg = rd_reg32(&topregs->deco.desc_dbg);
+ /*
+ * If an error occured in the descriptor, then
+ * the DECO status field will be set to 0x0D
+ */
+ if ((deco_dbg_reg & DESC_DBG_DECO_STAT_MASK) ==
+ DESC_DBG_DECO_STAT_HOST_ERR)
+ break;
cpu_relax();
+ } while ((deco_dbg_reg & DESC_DBG_DECO_STAT_VALID) && --timeout);
- if (!timeout) {
- dev_err(ctrldev, "failed to instantiate RNG\n");
- ret = -EIO;
- }
+ *status = rd_reg32(&topregs->deco.op_status_hi) &
+ DECO_OP_STATUS_HI_ERR_MASK;
+ /* Mark the DECO as free */
clrbits32(&topregs->ctrl.deco_rq, DECORR_RQD0ENABLE);
-out:
+
+ if (!timeout)
+ return -EAGAIN;
+
+ return 0;
+}
+
+/*
+ * instantiate_rng - builds and executes a descriptor on DECO0,
+ * which initializes the RNG block.
+ * @ctrldev - pointer to device
+ * @state_handle_mask - bitmask containing the instantiation status
+ * for the RNG4 state handles which exist in
+ * the RNG4 block: 1 if it's been instantiated
+ * by an external entry, 0 otherwise.
+ * @gen_sk - generate data to be loaded into the JDKEK, TDKEK and TDSK;
+ * Caution: this can be done only once; if the keys need to be
+ * regenerated, a POR is required
+ *
+ * Return: - 0 if no error occurred
+ * - -ENOMEM if there isn't enough memory to allocate the descriptor
+ * - -ENODEV if DECO0 couldn't be acquired
+ * - -EAGAIN if an error occurred when executing the descriptor
+ * f.i. there was a RNG hardware error due to not "good enough"
+ * entropy being aquired.
+ */
+static int instantiate_rng(struct device *ctrldev, int state_handle_mask,
+ int gen_sk)
+{
+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
+ struct caam_full __iomem *topregs;
+ struct rng4tst __iomem *r4tst;
+ u32 *desc, status, rdsta_val;
+ int ret = 0, sh_idx;
+
+ topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
+ r4tst = &topregs->ctrl.r4tst[0];
+
+ desc = kmalloc(CAAM_CMD_SZ * 7, GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
+ /*
+ * If the corresponding bit is set, this state handle
+ * was initialized by somebody else, so it's left alone.
+ */
+ if ((1 << sh_idx) & state_handle_mask)
+ continue;
+
+ /* Create the descriptor for instantiating RNG State Handle */
+ build_instantiation_desc(desc, sh_idx, gen_sk);
+
+ /* Try to run it through DECO0 */
+ ret = run_descriptor_deco0(ctrldev, desc, &status);
+
+ /*
+ * If ret is not 0, or descriptor status is not 0, then
+ * something went wrong. No need to try the next state
+ * handle (if available), bail out here.
+ * Also, if for some reason, the State Handle didn't get
+ * instantiated although the descriptor has finished
+ * without any error (HW optimizations for later
+ * CAAM eras), then try again.
+ */
+ rdsta_val =
+ rd_reg32(&topregs->ctrl.r4tst[0].rdsta) & RDSTA_IFMASK;
+ if (status || !(rdsta_val & (1 << sh_idx)))
+ ret = -EAGAIN;
+ if (ret)
+ break;
+
+ dev_info(ctrldev, "Instantiated RNG4 SH%d\n", sh_idx);
+ /* Clear the contents before recreating the descriptor */
+ memset(desc, 0x00, CAAM_CMD_SZ * 7);
+ }
+
kfree(desc);
+
return ret;
}
/*
- * By default, the TRNG runs for 200 clocks per sample;
- * 1600 clocks per sample generates better entropy.
+ * deinstantiate_rng - builds and executes a descriptor on DECO0,
+ * which deinitializes the RNG block.
+ * @ctrldev - pointer to device
+ * @state_handle_mask - bitmask containing the instantiation status
+ * for the RNG4 state handles which exist in
+ * the RNG4 block: 1 if it's been instantiated
+ *
+ * Return: - 0 if no error occurred
+ * - -ENOMEM if there isn't enough memory to allocate the descriptor
+ * - -ENODEV if DECO0 couldn't be acquired
+ * - -EAGAIN if an error occurred when executing the descriptor
*/
-static void kick_trng(struct platform_device *pdev)
+static int deinstantiate_rng(struct device *ctrldev, int state_handle_mask)
+{
+ u32 *desc, status;
+ int sh_idx, ret = 0;
+
+ desc = kmalloc(CAAM_CMD_SZ * 3, GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
+ /*
+ * If the corresponding bit is set, then it means the state
+ * handle was initialized by us, and thus it needs to be
+ * deintialized as well
+ */
+ if ((1 << sh_idx) & state_handle_mask) {
+ /*
+ * Create the descriptor for deinstantating this state
+ * handle
+ */
+ build_deinstantiation_desc(desc, sh_idx);
+
+ /* Try to run it through DECO0 */
+ ret = run_descriptor_deco0(ctrldev, desc, &status);
+
+ if (ret || status) {
+ dev_err(ctrldev,
+ "Failed to deinstantiate RNG4 SH%d\n",
+ sh_idx);
+ break;
+ }
+ dev_info(ctrldev, "Deinstantiated RNG4 SH%d\n", sh_idx);
+ }
+ }
+
+ kfree(desc);
+
+ return ret;
+}
+
+static int caam_remove(struct platform_device *pdev)
+{
+ struct device *ctrldev;
+ struct caam_drv_private *ctrlpriv;
+ struct caam_drv_private_jr *jrpriv;
+ struct caam_full __iomem *topregs;
+ int ring, ret = 0;
+
+ ctrldev = &pdev->dev;
+ ctrlpriv = dev_get_drvdata(ctrldev);
+ topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
+
+ /* shut down JobRs */
+ for (ring = 0; ring < ctrlpriv->total_jobrs; ring++) {
+ ret |= caam_jr_shutdown(ctrlpriv->jrdev[ring]);
+ jrpriv = dev_get_drvdata(ctrlpriv->jrdev[ring]);
+ irq_dispose_mapping(jrpriv->irq);
+ }
+
+ /* De-initialize RNG state handles initialized by this driver. */
+ if (ctrlpriv->rng4_sh_init)
+ deinstantiate_rng(ctrldev, ctrlpriv->rng4_sh_init);
+
+ /* Shut down debug views */
+#ifdef CONFIG_DEBUG_FS
+ debugfs_remove_recursive(ctrlpriv->dfs_root);
+#endif
+
+ /* Unmap controller region */
+ iounmap(&topregs->ctrl);
+
+ kfree(ctrlpriv->jrdev);
+ kfree(ctrlpriv);
+
+ return ret;
+}
+
+/*
+ * kick_trng - sets the various parameters for enabling the initialization
+ * of the RNG4 block in CAAM
+ * @pdev - pointer to the platform device
+ * @ent_delay - Defines the length (in system clocks) of each entropy sample.
+ */
+static void kick_trng(struct platform_device *pdev, int ent_delay)
{
struct device *ctrldev = &pdev->dev;
struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
@@ -142,14 +320,31 @@ static void kick_trng(struct platform_device *pdev)
/* put RNG4 into program mode */
setbits32(&r4tst->rtmctl, RTMCTL_PRGM);
- /* 1600 clocks per sample */
+
+ /*
+ * Performance-wise, it does not make sense to
+ * set the delay to a value that is lower
+ * than the last one that worked (i.e. the state handles
+ * were instantiated properly. Thus, instead of wasting
+ * time trying to set the values controlling the sample
+ * frequency, the function simply returns.
+ */
+ val = (rd_reg32(&r4tst->rtsdctl) & RTSDCTL_ENT_DLY_MASK)
+ >> RTSDCTL_ENT_DLY_SHIFT;
+ if (ent_delay <= val) {
+ /* put RNG4 into run mode */
+ clrbits32(&r4tst->rtmctl, RTMCTL_PRGM);
+ return;
+ }
+
val = rd_reg32(&r4tst->rtsdctl);
- val = (val & ~RTSDCTL_ENT_DLY_MASK) | (1600 << RTSDCTL_ENT_DLY_SHIFT);
+ val = (val & ~RTSDCTL_ENT_DLY_MASK) |
+ (ent_delay << RTSDCTL_ENT_DLY_SHIFT);
wr_reg32(&r4tst->rtsdctl, val);
- /* min. freq. count */
- wr_reg32(&r4tst->rtfrqmin, 400);
- /* max. freq. count */
- wr_reg32(&r4tst->rtfrqmax, 6400);
+ /* min. freq. count, equal to 1/4 of the entropy sample length */
+ wr_reg32(&r4tst->rtfrqmin, ent_delay >> 2);
+ /* max. freq. count, equal to 8 times the entropy sample length */
+ wr_reg32(&r4tst->rtfrqmax, ent_delay << 3);
/* put RNG4 into run mode */
clrbits32(&r4tst->rtmctl, RTMCTL_PRGM);
}
@@ -190,7 +385,7 @@ EXPORT_SYMBOL(caam_get_era);
/* Probe routine for CAAM top (controller) level */
static int caam_probe(struct platform_device *pdev)
{
- int ret, ring, rspec;
+ int ret, ring, rspec, gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN;
u64 caam_id;
struct device *dev;
struct device_node *nprop, *np;
@@ -296,16 +491,55 @@ static int caam_probe(struct platform_device *pdev)
/*
* If SEC has RNG version >= 4 and RNG state handle has not been
- * already instantiated ,do RNG instantiation
+ * already instantiated, do RNG instantiation
*/
- if ((cha_vid & CHA_ID_RNG_MASK) >> CHA_ID_RNG_SHIFT >= 4 &&
- !(rd_reg32(&topregs->ctrl.r4tst[0].rdsta) & RDSTA_IF0)) {
- kick_trng(pdev);
- ret = instantiate_rng(dev);
+ if ((cha_vid & CHA_ID_RNG_MASK) >> CHA_ID_RNG_SHIFT >= 4) {
+ ctrlpriv->rng4_sh_init =
+ rd_reg32(&topregs->ctrl.r4tst[0].rdsta);
+ /*
+ * If the secure keys (TDKEK, JDKEK, TDSK), were already
+ * generated, signal this to the function that is instantiating
+ * the state handles. An error would occur if RNG4 attempts
+ * to regenerate these keys before the next POR.
+ */
+ gen_sk = ctrlpriv->rng4_sh_init & RDSTA_SKVN ? 0 : 1;
+ ctrlpriv->rng4_sh_init &= RDSTA_IFMASK;
+ do {
+ int inst_handles =
+ rd_reg32(&topregs->ctrl.r4tst[0].rdsta) &
+ RDSTA_IFMASK;
+ /*
+ * If either SH were instantiated by somebody else
+ * (e.g. u-boot) then it is assumed that the entropy
+ * parameters are properly set and thus the function
+ * setting these (kick_trng(...)) is skipped.
+ * Also, if a handle was instantiated, do not change
+ * the TRNG parameters.
+ */
+ if (!(ctrlpriv->rng4_sh_init || inst_handles)) {
+ kick_trng(pdev, ent_delay);
+ ent_delay += 400;
+ }
+ /*
+ * if instantiate_rng(...) fails, the loop will rerun
+ * and the kick_trng(...) function will modfiy the
+ * upper and lower limits of the entropy sampling
+ * interval, leading to a sucessful initialization of
+ * the RNG.
+ */
+ ret = instantiate_rng(dev, inst_handles,
+ gen_sk);
+ } while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
if (ret) {
+ dev_err(dev, "failed to instantiate RNG");
caam_remove(pdev);
return ret;
}
+ /*
+ * Set handles init'ed by this module as the complement of the
+ * already initialized ones
+ */
+ ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_IFMASK;
/* Enable RDB bit so that RNG works faster */
setbits32(&topregs->ctrl.scfgr, SCFGR_RDBENABLE);
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index 53b296f78b0d..7e4500f18df6 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -1155,8 +1155,15 @@ struct sec4_sg_entry {
/* randomizer AAI set */
#define OP_ALG_AAI_RNG (0x00 << OP_ALG_AAI_SHIFT)
-#define OP_ALG_AAI_RNG_NOZERO (0x10 << OP_ALG_AAI_SHIFT)
-#define OP_ALG_AAI_RNG_ODD (0x20 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG_NZB (0x10 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG_OBP (0x20 << OP_ALG_AAI_SHIFT)
+
+/* RNG4 AAI set */
+#define OP_ALG_AAI_RNG4_SH_0 (0x00 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG4_SH_1 (0x01 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG4_PS (0x40 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG4_AI (0x80 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG4_SK (0x100 << OP_ALG_AAI_SHIFT)
/* hmac/smac AAI set */
#define OP_ALG_AAI_HASH (0x00 << OP_ALG_AAI_SHIFT)
@@ -1178,12 +1185,6 @@ struct sec4_sg_entry {
#define OP_ALG_AAI_GSM (0x10 << OP_ALG_AAI_SHIFT)
#define OP_ALG_AAI_EDGE (0x20 << OP_ALG_AAI_SHIFT)
-/* RNG4 set */
-#define OP_ALG_RNG4_SHIFT 4
-#define OP_ALG_RNG4_MASK (0x1f3 << OP_ALG_RNG4_SHIFT)
-
-#define OP_ALG_RNG4_SK (0x100 << OP_ALG_RNG4_SHIFT)
-
#define OP_ALG_AS_SHIFT 2
#define OP_ALG_AS_MASK (0x3 << OP_ALG_AS_SHIFT)
#define OP_ALG_AS_UPDATE (0 << OP_ALG_AS_SHIFT)
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index 34c4b9f7fbfa..bbc1ac9ec720 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -87,6 +87,12 @@ struct caam_drv_private {
/* list of registered hash algorithms (mk generic context handle?) */
struct list_head hash_list;
+#define RNG4_MAX_HANDLES 2
+ /* RNG4 block */
+ u32 rng4_sh_init; /* This bitmap shows which of the State
+ Handles of the RNG4 block are initialized
+ by this driver */
+
/*
* debugfs entries for developer view into driver/device
* variables at runtime.
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index 4455396918de..d50174f45b21 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -245,7 +245,7 @@ struct rngtst {
/* RNG4 TRNG test registers */
struct rng4tst {
-#define RTMCTL_PRGM 0x00010000 /* 1 -> program mode, 0 -> run mode */
+#define RTMCTL_PRGM 0x00010000 /* 1 -> program mode, 0 -> run mode */
u32 rtmctl; /* misc. control register */
u32 rtscmisc; /* statistical check misc. register */
u32 rtpkrrng; /* poker range register */
@@ -255,6 +255,8 @@ struct rng4tst {
};
#define RTSDCTL_ENT_DLY_SHIFT 16
#define RTSDCTL_ENT_DLY_MASK (0xffff << RTSDCTL_ENT_DLY_SHIFT)
+#define RTSDCTL_ENT_DLY_MIN 1200
+#define RTSDCTL_ENT_DLY_MAX 12800
u32 rtsdctl; /* seed control register */
union {
u32 rtsblim; /* PRGM=1: sparse bit limit register */
@@ -266,7 +268,11 @@ struct rng4tst {
u32 rtfrqcnt; /* PRGM=0: freq. count register */
};
u32 rsvd1[40];
+#define RDSTA_SKVT 0x80000000
+#define RDSTA_SKVN 0x40000000
#define RDSTA_IF0 0x00000001
+#define RDSTA_IF1 0x00000002
+#define RDSTA_IFMASK (RDSTA_IF1 | RDSTA_IF0)
u32 rdsta;
u32 rsvd2[15];
};
@@ -692,6 +698,7 @@ struct caam_deco {
u32 jr_ctl_hi; /* CxJRR - JobR Control Register @800 */
u32 jr_ctl_lo;
u64 jr_descaddr; /* CxDADR - JobR Descriptor Address */
+#define DECO_OP_STATUS_HI_ERR_MASK 0xF00000FF
u32 op_status_hi; /* DxOPSTA - DECO Operation Status */
u32 op_status_lo;
u32 rsvd24[2];
@@ -706,12 +713,13 @@ struct caam_deco {
u32 rsvd29[48];
u32 descbuf[64]; /* DxDESB - Descriptor buffer */
u32 rscvd30[193];
+#define DESC_DBG_DECO_STAT_HOST_ERR 0x00D00000
+#define DESC_DBG_DECO_STAT_VALID 0x80000000
+#define DESC_DBG_DECO_STAT_MASK 0x00F00000
u32 desc_dbg; /* DxDDR - DECO Debug Register */
u32 rsvd31[126];
};
-/* DECO DBG Register Valid Bit*/
-#define DECO_DBG_VALID 0x80000000
#define DECO_JQCR_WHL 0x20000000
#define DECO_JQCR_FOUR 0x10000000
diff --git a/drivers/crypto/caam/sg_sw_sec4.h b/drivers/crypto/caam/sg_sw_sec4.h
index e0037c8ee243..b12ff85f4241 100644
--- a/drivers/crypto/caam/sg_sw_sec4.h
+++ b/drivers/crypto/caam/sg_sw_sec4.h
@@ -117,6 +117,21 @@ static int dma_unmap_sg_chained(struct device *dev, struct scatterlist *sg,
return nents;
}
+/* Map SG page in kernel virtual address space and copy */
+static inline void sg_map_copy(u8 *dest, struct scatterlist *sg,
+ int len, int offset)
+{
+ u8 *mapped_addr;
+
+ /*
+ * Page here can be user-space pinned using get_user_pages
+ * Same must be kmapped before use and kunmapped subsequently
+ */
+ mapped_addr = kmap_atomic(sg_page(sg));
+ memcpy(dest, mapped_addr + offset, len);
+ kunmap_atomic(mapped_addr);
+}
+
/* Copy from len bytes of sg to dest, starting from beginning */
static inline void sg_copy(u8 *dest, struct scatterlist *sg, unsigned int len)
{
@@ -124,15 +139,15 @@ static inline void sg_copy(u8 *dest, struct scatterlist *sg, unsigned int len)
int cpy_index = 0, next_cpy_index = current_sg->length;
while (next_cpy_index < len) {
- memcpy(dest + cpy_index, (u8 *) sg_virt(current_sg),
- current_sg->length);
+ sg_map_copy(dest + cpy_index, current_sg, current_sg->length,
+ current_sg->offset);
current_sg = scatterwalk_sg_next(current_sg);
cpy_index = next_cpy_index;
next_cpy_index += current_sg->length;
}
if (cpy_index < len)
- memcpy(dest + cpy_index, (u8 *) sg_virt(current_sg),
- len - cpy_index);
+ sg_map_copy(dest + cpy_index, current_sg, len-cpy_index,
+ current_sg->offset);
}
/* Copy sg data, from to_skip to end, to dest */
@@ -140,7 +155,7 @@ static inline void sg_copy_part(u8 *dest, struct scatterlist *sg,
int to_skip, unsigned int end)
{
struct scatterlist *current_sg = sg;
- int sg_index, cpy_index;
+ int sg_index, cpy_index, offset;
sg_index = current_sg->length;
while (sg_index <= to_skip) {
@@ -148,9 +163,10 @@ static inline void sg_copy_part(u8 *dest, struct scatterlist *sg,
sg_index += current_sg->length;
}
cpy_index = sg_index - to_skip;
- memcpy(dest, (u8 *) sg_virt(current_sg) +
- current_sg->length - cpy_index, cpy_index);
- current_sg = scatterwalk_sg_next(current_sg);
- if (end - sg_index)
+ offset = current_sg->offset + current_sg->length - cpy_index;
+ sg_map_copy(dest, current_sg, cpy_index, offset);
+ if (end - sg_index) {
+ current_sg = scatterwalk_sg_next(current_sg);
sg_copy(dest + cpy_index, current_sg, end - sg_index);
+ }
}
diff --git a/drivers/crypto/dcp.c b/drivers/crypto/dcp.c
index a8a7dd4b0d25..7b77c8457854 100644
--- a/drivers/crypto/dcp.c
+++ b/drivers/crypto/dcp.c
@@ -733,12 +733,7 @@ static int dcp_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dev);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!r) {
- dev_err(&pdev->dev, "failed to get IORESOURCE_MEM\n");
- return -ENXIO;
- }
- dev->dcp_regs_base = devm_ioremap(&pdev->dev, r->start,
- resource_size(r));
+ dev->dcp_regs_base = devm_ioremap_resource(&pdev->dev, r);
dcp_set(dev, DCP_CTRL_SFRST, DCP_REG_CTRL);
udelay(10);
@@ -762,7 +757,8 @@ static int dcp_probe(struct platform_device *pdev)
return -EIO;
}
dev->dcp_vmi_irq = r->start;
- ret = request_irq(dev->dcp_vmi_irq, dcp_vmi_irq, 0, "dcp", dev);
+ ret = devm_request_irq(&pdev->dev, dev->dcp_vmi_irq, dcp_vmi_irq, 0,
+ "dcp", dev);
if (ret != 0) {
dev_err(&pdev->dev, "can't request_irq (0)\n");
return -EIO;
@@ -771,15 +767,14 @@ static int dcp_probe(struct platform_device *pdev)
r = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
if (!r) {
dev_err(&pdev->dev, "can't get IRQ resource (1)\n");
- ret = -EIO;
- goto err_free_irq0;
+ return -EIO;
}
dev->dcp_irq = r->start;
- ret = request_irq(dev->dcp_irq, dcp_irq, 0, "dcp", dev);
+ ret = devm_request_irq(&pdev->dev, dev->dcp_irq, dcp_irq, 0, "dcp",
+ dev);
if (ret != 0) {
dev_err(&pdev->dev, "can't request_irq (1)\n");
- ret = -EIO;
- goto err_free_irq0;
+ return -EIO;
}
dev->hw_pkg[0] = dma_alloc_coherent(&pdev->dev,
@@ -788,8 +783,7 @@ static int dcp_probe(struct platform_device *pdev)
GFP_KERNEL);
if (!dev->hw_pkg[0]) {
dev_err(&pdev->dev, "Could not allocate hw descriptors\n");
- ret = -ENOMEM;
- goto err_free_irq1;
+ return -ENOMEM;
}
for (i = 1; i < DCP_MAX_PKG; i++) {
@@ -848,16 +842,14 @@ err_unregister:
for (j = 0; j < i; j++)
crypto_unregister_alg(&algs[j]);
err_free_key_iv:
+ tasklet_kill(&dev->done_task);
+ tasklet_kill(&dev->queue_task);
dma_free_coherent(&pdev->dev, 2 * AES_KEYSIZE_128, dev->payload_base,
dev->payload_base_dma);
err_free_hw_packet:
dma_free_coherent(&pdev->dev, DCP_MAX_PKG *
sizeof(struct dcp_hw_packet), dev->hw_pkg[0],
dev->hw_phys_pkg);
-err_free_irq1:
- free_irq(dev->dcp_irq, dev);
-err_free_irq0:
- free_irq(dev->dcp_vmi_irq, dev);
return ret;
}
@@ -868,23 +860,20 @@ static int dcp_remove(struct platform_device *pdev)
int j;
dev = platform_get_drvdata(pdev);
- dma_free_coherent(&pdev->dev,
- DCP_MAX_PKG * sizeof(struct dcp_hw_packet),
- dev->hw_pkg[0], dev->hw_phys_pkg);
-
- dma_free_coherent(&pdev->dev, 2 * AES_KEYSIZE_128, dev->payload_base,
- dev->payload_base_dma);
+ misc_deregister(&dev->dcp_bootstream_misc);
- free_irq(dev->dcp_irq, dev);
- free_irq(dev->dcp_vmi_irq, dev);
+ for (j = 0; j < ARRAY_SIZE(algs); j++)
+ crypto_unregister_alg(&algs[j]);
tasklet_kill(&dev->done_task);
tasklet_kill(&dev->queue_task);
- for (j = 0; j < ARRAY_SIZE(algs); j++)
- crypto_unregister_alg(&algs[j]);
+ dma_free_coherent(&pdev->dev, 2 * AES_KEYSIZE_128, dev->payload_base,
+ dev->payload_base_dma);
- misc_deregister(&dev->dcp_bootstream_misc);
+ dma_free_coherent(&pdev->dev,
+ DCP_MAX_PKG * sizeof(struct dcp_hw_packet),
+ dev->hw_pkg[0], dev->hw_phys_pkg);
return 0;
}
diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c
index 3374a3ebe4c7..f9b9560f64b4 100644
--- a/drivers/crypto/mv_cesa.c
+++ b/drivers/crypto/mv_cesa.c
@@ -907,7 +907,7 @@ static int mv_cra_hash_hmac_sha1_init(struct crypto_tfm *tfm)
return mv_cra_hash_init(tfm, "sha1", COP_HMAC_SHA1, SHA1_BLOCK_SIZE);
}
-irqreturn_t crypto_int(int irq, void *priv)
+static irqreturn_t crypto_int(int irq, void *priv)
{
u32 val;
@@ -928,7 +928,7 @@ irqreturn_t crypto_int(int irq, void *priv)
return IRQ_HANDLED;
}
-struct crypto_alg mv_aes_alg_ecb = {
+static struct crypto_alg mv_aes_alg_ecb = {
.cra_name = "ecb(aes)",
.cra_driver_name = "mv-ecb-aes",
.cra_priority = 300,
@@ -951,7 +951,7 @@ struct crypto_alg mv_aes_alg_ecb = {
},
};
-struct crypto_alg mv_aes_alg_cbc = {
+static struct crypto_alg mv_aes_alg_cbc = {
.cra_name = "cbc(aes)",
.cra_driver_name = "mv-cbc-aes",
.cra_priority = 300,
@@ -975,7 +975,7 @@ struct crypto_alg mv_aes_alg_cbc = {
},
};
-struct ahash_alg mv_sha1_alg = {
+static struct ahash_alg mv_sha1_alg = {
.init = mv_hash_init,
.update = mv_hash_update,
.final = mv_hash_final,
@@ -999,7 +999,7 @@ struct ahash_alg mv_sha1_alg = {
}
};
-struct ahash_alg mv_hmac_sha1_alg = {
+static struct ahash_alg mv_hmac_sha1_alg = {
.init = mv_hash_init,
.update = mv_hash_update,
.final = mv_hash_final,
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index ce791c2f81f7..e1e58d0ed550 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -554,7 +554,7 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
return err;
}
-int omap_aes_check_aligned(struct scatterlist *sg)
+static int omap_aes_check_aligned(struct scatterlist *sg)
{
while (sg) {
if (!IS_ALIGNED(sg->offset, 4))
@@ -566,7 +566,7 @@ int omap_aes_check_aligned(struct scatterlist *sg)
return 0;
}
-int omap_aes_copy_sgs(struct omap_aes_dev *dd)
+static int omap_aes_copy_sgs(struct omap_aes_dev *dd)
{
void *buf_in, *buf_out;
int pages;
diff --git a/drivers/crypto/tegra-aes.c b/drivers/crypto/tegra-aes.c
index 2d58da972ae2..d8c7a132fea4 100644
--- a/drivers/crypto/tegra-aes.c
+++ b/drivers/crypto/tegra-aes.c
@@ -27,6 +27,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
@@ -199,8 +201,6 @@ static void aes_workqueue_handler(struct work_struct *work);
static DECLARE_WORK(aes_work, aes_workqueue_handler);
static struct workqueue_struct *aes_wq;
-extern unsigned long long tegra_chip_uid(void);
-
static inline u32 aes_readl(struct tegra_aes_dev *dd, u32 offset)
{
return readl(dd->io_base + offset);
@@ -713,13 +713,12 @@ static int tegra_aes_rng_reset(struct crypto_rng *tfm, u8 *seed,
struct tegra_aes_dev *dd = aes_dev;
struct tegra_aes_ctx *ctx = &rng_ctx;
struct tegra_aes_slot *key_slot;
- struct timespec ts;
int ret = 0;
- u64 nsec, tmp[2];
+ u8 tmp[16]; /* 16 bytes = 128 bits of entropy */
u8 *dt;
if (!ctx || !dd) {
- dev_err(dd->dev, "ctx=0x%x, dd=0x%x\n",
+ pr_err("ctx=0x%x, dd=0x%x\n",
(unsigned int)ctx, (unsigned int)dd);
return -EINVAL;
}
@@ -778,14 +777,8 @@ static int tegra_aes_rng_reset(struct crypto_rng *tfm, u8 *seed,
if (dd->ivlen >= (2 * DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128)) {
dt = dd->iv + DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128;
} else {
- getnstimeofday(&ts);
- nsec = timespec_to_ns(&ts);
- do_div(nsec, 1000);
- nsec ^= dd->ctr << 56;
- dd->ctr++;
- tmp[0] = nsec;
- tmp[1] = tegra_chip_uid();
- dt = (u8 *)tmp;
+ get_random_bytes(tmp, sizeof(tmp));
+ dt = tmp;
}
memcpy(dd->dt, dt, DEFAULT_RNG_BLK_SZ);
@@ -804,7 +797,7 @@ static int tegra_aes_cra_init(struct crypto_tfm *tfm)
return 0;
}
-void tegra_aes_cra_exit(struct crypto_tfm *tfm)
+static void tegra_aes_cra_exit(struct crypto_tfm *tfm)
{
struct tegra_aes_ctx *ctx =
crypto_ablkcipher_ctx((struct crypto_ablkcipher *)tfm);
@@ -924,7 +917,7 @@ static int tegra_aes_probe(struct platform_device *pdev)
}
/* Initialize the vde clock */
- dd->aes_clk = clk_get(dev, "vde");
+ dd->aes_clk = devm_clk_get(dev, "vde");
if (IS_ERR(dd->aes_clk)) {
dev_err(dev, "iclock intialization failed.\n");
err = -ENODEV;
@@ -1033,8 +1026,6 @@ out:
if (dd->buf_out)
dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
dd->buf_out, dd->dma_buf_out);
- if (!IS_ERR(dd->aes_clk))
- clk_put(dd->aes_clk);
if (aes_wq)
destroy_workqueue(aes_wq);
spin_lock(&list_lock);
@@ -1068,7 +1059,6 @@ static int tegra_aes_remove(struct platform_device *pdev)
dd->buf_in, dd->dma_buf_in);
dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
dd->buf_out, dd->dma_buf_out);
- clk_put(dd->aes_clk);
aes_dev = NULL;
return 0;
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 526ec77c7ba0..f238cfd33847 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -198,6 +198,7 @@ config TI_EDMA
depends on ARCH_DAVINCI || ARCH_OMAP
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
+ select TI_PRIV_EDMA
default n
help
Enable support for the TI EDMA controller. This DMA
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index ff50ff4c6a57..098a8da450f0 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -749,6 +749,6 @@ static void __exit edma_exit(void)
}
module_exit(edma_exit);
-MODULE_AUTHOR("Matt Porter <mporter@ti.com>");
+MODULE_AUTHOR("Matt Porter <matt.porter@linaro.org>");
MODULE_DESCRIPTION("TI EDMA DMA engine driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index a562d24d20bf..58623dc474d1 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -2923,7 +2923,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
amba_set_drvdata(adev, pdmac);
irq = adev->irq[0];
- ret = request_irq(irq, pl330_irq_handler, 0,
+ ret = devm_request_irq(&adev->dev, irq, pl330_irq_handler, 0,
dev_name(&adev->dev), pi);
if (ret)
return ret;
@@ -2931,7 +2931,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
pi->pcfg.periph_id = adev->periphid;
ret = pl330_add(pi);
if (ret)
- goto probe_err1;
+ return ret;
INIT_LIST_HEAD(&pdmac->desc_pool);
spin_lock_init(&pdmac->pool_lock);
@@ -3044,8 +3044,6 @@ probe_err3:
}
probe_err2:
pl330_del(pi);
-probe_err1:
- free_irq(irq, pi);
return ret;
}
@@ -3055,7 +3053,6 @@ static int pl330_remove(struct amba_device *adev)
struct dma_pl330_dmac *pdmac = amba_get_drvdata(adev);
struct dma_pl330_chan *pch, *_p;
struct pl330_info *pi;
- int irq;
if (!pdmac)
return 0;
@@ -3082,9 +3079,6 @@ static int pl330_remove(struct amba_device *adev)
pl330_del(pi);
- irq = adev->irq[0];
- free_irq(irq, pi);
-
return 0;
}
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
index 5d4986e5f5fa..67a6752bf863 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -1018,7 +1018,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg(
return &dma_desc->txd;
}
-struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
+static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_len,
size_t period_len, enum dma_transfer_direction direction,
unsigned long flags, void *context)
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index e55713083c78..91a702beccc5 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -564,11 +564,10 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
}
ret = arizona_hpdet_read(info);
- if (ret == -EAGAIN) {
+ if (ret == -EAGAIN)
goto out;
- } else if (ret < 0) {
+ else if (ret < 0)
goto done;
- }
reading = ret;
/* Reset back to starting range */
@@ -578,11 +577,10 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
0);
ret = arizona_hpdet_do_id(info, &reading, &mic);
- if (ret == -EAGAIN) {
+ if (ret == -EAGAIN)
goto out;
- } else if (ret < 0) {
+ else if (ret < 0)
goto done;
- }
/* Report high impedence cables as line outputs */
if (reading >= 5000)
@@ -738,8 +736,8 @@ err:
static void arizona_micd_timeout_work(struct work_struct *work)
{
struct arizona_extcon_info *info = container_of(work,
- struct arizona_extcon_info,
- micd_timeout_work.work);
+ struct arizona_extcon_info,
+ micd_timeout_work.work);
mutex_lock(&info->lock);
@@ -756,8 +754,8 @@ static void arizona_micd_timeout_work(struct work_struct *work)
static void arizona_micd_detect(struct work_struct *work)
{
struct arizona_extcon_info *info = container_of(work,
- struct arizona_extcon_info,
- micd_detect_work.work);
+ struct arizona_extcon_info,
+ micd_detect_work.work);
struct arizona *arizona = info->arizona;
unsigned int val = 0, lvl;
int ret, i, key;
@@ -769,7 +767,8 @@ static void arizona_micd_detect(struct work_struct *work)
for (i = 0; i < 10 && !(val & 0x7fc); i++) {
ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
if (ret != 0) {
- dev_err(arizona->dev, "Failed to read MICDET: %d\n", ret);
+ dev_err(arizona->dev,
+ "Failed to read MICDET: %d\n", ret);
mutex_unlock(&info->lock);
return;
}
@@ -777,7 +776,8 @@ static void arizona_micd_detect(struct work_struct *work)
dev_dbg(arizona->dev, "MICDET: %x\n", val);
if (!(val & ARIZONA_MICD_VALID)) {
- dev_warn(arizona->dev, "Microphone detection state invalid\n");
+ dev_warn(arizona->dev,
+ "Microphone detection state invalid\n");
mutex_unlock(&info->lock);
return;
}
@@ -925,8 +925,8 @@ static irqreturn_t arizona_micdet(int irq, void *data)
static void arizona_hpdet_work(struct work_struct *work)
{
struct arizona_extcon_info *info = container_of(work,
- struct arizona_extcon_info,
- hpdet_work.work);
+ struct arizona_extcon_info,
+ hpdet_work.work);
mutex_lock(&info->lock);
arizona_start_hpdet_acc_id(info);
@@ -973,10 +973,13 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
&info->hpdet_work,
msecs_to_jiffies(HPDET_DEBOUNCE));
- if (cancelled_mic)
+ if (cancelled_mic) {
+ int micd_timeout = info->micd_timeout;
+
queue_delayed_work(system_power_efficient_wq,
&info->micd_timeout_work,
- msecs_to_jiffies(info->micd_timeout));
+ msecs_to_jiffies(micd_timeout));
+ }
goto out;
}
diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c
index 148382faded9..b6a3d379fe9a 100644
--- a/drivers/extcon/extcon-class.c
+++ b/drivers/extcon/extcon-class.c
@@ -129,7 +129,6 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
return count;
}
-int extcon_set_state(struct extcon_dev *edev, u32 state);
static ssize_t state_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
@@ -452,7 +451,8 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
if (!obj->edev)
return -ENODEV;
- obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
+ obj->cable_index = extcon_find_cable_index(obj->edev,
+ cable_name);
if (obj->cable_index < 0)
return obj->cable_index;
@@ -460,7 +460,8 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
obj->internal_nb.notifier_call = _call_per_cable;
- return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb);
+ return raw_notifier_chain_register(&obj->edev->nh,
+ &obj->internal_nb);
} else {
struct class_dev_iter iter;
struct extcon_dev *extd;
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index b56bdaa27d4b..5ee0344f734d 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -189,14 +189,17 @@ enum max77693_muic_acc_type {
/* The below accessories have same ADC value so ADCLow and
ADC1K bit is used to separate specific accessory */
- MAX77693_MUIC_GND_USB_OTG = 0x100, /* ADC:0x0, VBVolot:0, ADCLow:0, ADC1K:0 */
- MAX77693_MUIC_GND_USB_OTG_VB = 0x104, /* ADC:0x0, VBVolot:1, ADCLow:0, ADC1K:0 */
- MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* ADC:0x0, VBVolot:0, ADCLow:1, ADC1K:0 */
- MAX77693_MUIC_GND_MHL = 0x103, /* ADC:0x0, VBVolot:0, ADCLow:1, ADC1K:1 */
- MAX77693_MUIC_GND_MHL_VB = 0x107, /* ADC:0x0, VBVolot:1, ADCLow:1, ADC1K:1 */
+ /* ADC|VBVolot|ADCLow|ADC1K| */
+ MAX77693_MUIC_GND_USB_OTG = 0x100, /* 0x0| 0| 0| 0| */
+ MAX77693_MUIC_GND_USB_OTG_VB = 0x104, /* 0x0| 1| 0| 0| */
+ MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* 0x0| 0| 1| 0| */
+ MAX77693_MUIC_GND_MHL = 0x103, /* 0x0| 0| 1| 1| */
+ MAX77693_MUIC_GND_MHL_VB = 0x107, /* 0x0| 1| 1| 1| */
};
-/* MAX77693 MUIC device support below list of accessories(external connector) */
+/*
+ * MAX77693 MUIC device support below list of accessories(external connector)
+ */
enum {
EXTCON_CABLE_USB = 0,
EXTCON_CABLE_USB_HOST,
@@ -395,12 +398,12 @@ static int max77693_muic_get_cable_type(struct max77693_muic_info *info,
vbvolt >>= STATUS2_VBVOLT_SHIFT;
/**
- * [0x1][VBVolt][ADCLow][ADC1K]
- * [0x1 0 0 0 ] : USB_OTG
- * [0x1 1 0 0 ] : USB_OTG_VB
- * [0x1 0 1 0 ] : Audio Video Cable with load
- * [0x1 0 1 1 ] : MHL without charging connector
- * [0x1 1 1 1 ] : MHL with charging connector
+ * [0x1|VBVolt|ADCLow|ADC1K]
+ * [0x1| 0| 0| 0] USB_OTG
+ * [0x1| 1| 0| 0] USB_OTG_VB
+ * [0x1| 0| 1| 0] Audio Video cable with load
+ * [0x1| 0| 1| 1] MHL without charging cable
+ * [0x1| 1| 1| 1] MHL with charging cable
*/
cable_type = ((0x1 << 8)
| (vbvolt << 2)
@@ -723,11 +726,11 @@ static int max77693_muic_adc_handler(struct max77693_muic_info *info)
if (ret < 0)
return ret;
break;
- case MAX77693_MUIC_ADC_REMOTE_S3_BUTTON: /* DOCK_KEY_PREV */
- case MAX77693_MUIC_ADC_REMOTE_S7_BUTTON: /* DOCK_KEY_NEXT */
- case MAX77693_MUIC_ADC_REMOTE_S9_BUTTON: /* DOCK_VOL_DOWN */
- case MAX77693_MUIC_ADC_REMOTE_S10_BUTTON: /* DOCK_VOL_UP */
- case MAX77693_MUIC_ADC_REMOTE_S12_BUTTON: /* DOCK_KEY_PLAY_PAUSE */
+ case MAX77693_MUIC_ADC_REMOTE_S3_BUTTON: /* DOCK_KEY_PREV */
+ case MAX77693_MUIC_ADC_REMOTE_S7_BUTTON: /* DOCK_KEY_NEXT */
+ case MAX77693_MUIC_ADC_REMOTE_S9_BUTTON: /* DOCK_VOL_DOWN */
+ case MAX77693_MUIC_ADC_REMOTE_S10_BUTTON: /* DOCK_VOL_UP */
+ case MAX77693_MUIC_ADC_REMOTE_S12_BUTTON: /* DOCK_KEY_PLAY_PAUSE */
/*
* Button of DOCK device
* - the Prev/Next/Volume Up/Volume Down/Play-Pause button
@@ -815,19 +818,21 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
case MAX77693_MUIC_GND_MHL_VB:
/*
* MHL cable with MHL_TA(USB/TA) cable
- * - MHL cable include two port(HDMI line and separate micro-
- * usb port. When the target connect MHL cable, extcon driver
- * check whether MHL_TA(USB/TA) cable is connected. If MHL_TA
- * cable is connected, extcon driver notify state to notifiee
- * for charging battery.
+ * - MHL cable include two port(HDMI line and separate
+ * micro-usb port. When the target connect MHL cable,
+ * extcon driver check whether MHL_TA(USB/TA) cable is
+ * connected. If MHL_TA cable is connected, extcon
+ * driver notify state to notifiee for charging battery.
*
* Features of 'MHL_TA(USB/TA) with MHL cable'
* - Support MHL
- * - Support charging through micro-usb port without data connection
+ * - Support charging through micro-usb port without
+ * data connection
*/
extcon_set_cable_state(info->edev, "MHL_TA", attached);
if (!cable_attached)
- extcon_set_cable_state(info->edev, "MHL", cable_attached);
+ extcon_set_cable_state(info->edev,
+ "MHL", cable_attached);
break;
}
@@ -839,47 +844,51 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: /* Dock-Audio */
/*
* Dock-Audio device with USB/TA cable
- * - Dock device include two port(Dock-Audio and micro-usb
- * port). When the target connect Dock-Audio device, extcon
- * driver check whether USB/TA cable is connected. If USB/TA
- * cable is connected, extcon driver notify state to notifiee
- * for charging battery.
+ * - Dock device include two port(Dock-Audio and micro-
+ * usb port). When the target connect Dock-Audio device,
+ * extcon driver check whether USB/TA cable is connected
+ * or not. If USB/TA cable is connected, extcon driver
+ * notify state to notifiee for charging battery.
*
* Features of 'USB/TA cable with Dock-Audio device'
* - Support external output feature of audio.
- * - Support charging through micro-usb port without data
- * connection.
+ * - Support charging through micro-usb port without
+ * data connection.
*/
extcon_set_cable_state(info->edev, "USB", attached);
if (!cable_attached)
- extcon_set_cable_state(info->edev, "Dock-Audio", cable_attached);
+ extcon_set_cable_state(info->edev, "Dock-Audio",
+ cable_attached);
break;
case MAX77693_MUIC_ADC_RESERVED_ACC_3: /* Dock-Smart */
/*
* Dock-Smart device with USB/TA cable
* - Dock-Desk device include three type of cable which
* are HDMI, USB for mouse/keyboard and micro-usb port
- * for USB/TA cable. Dock-Smart device need always exteranl
- * power supply(USB/TA cable through micro-usb cable). Dock-
- * Smart device support screen output of target to separate
- * monitor and mouse/keyboard for desktop mode.
+ * for USB/TA cable. Dock-Smart device need always
+ * exteranl power supply(USB/TA cable through micro-usb
+ * cable). Dock-Smart device support screen output of
+ * target to separate monitor and mouse/keyboard for
+ * desktop mode.
*
* Features of 'USB/TA cable with Dock-Smart device'
* - Support MHL
* - Support external output feature of audio
- * - Support charging through micro-usb port without data
- * connection if TA cable is connected to target.
- * - Support charging and data connection through micro-usb port
- * if USB cable is connected between target and host
- * device.
+ * - Support charging through micro-usb port without
+ * data connection if TA cable is connected to target.
+ * - Support charging and data connection through micro-
+ * usb port if USB cable is connected between target
+ * and host device
* - Support OTG device (Mouse/Keyboard)
*/
- ret = max77693_muic_set_path(info, info->path_usb, attached);
+ ret = max77693_muic_set_path(info, info->path_usb,
+ attached);
if (ret < 0)
return ret;
- extcon_set_cable_state(info->edev, "Dock-Smart", attached);
+ extcon_set_cable_state(info->edev, "Dock-Smart",
+ attached);
extcon_set_cable_state(info->edev, "MHL", attached);
break;
@@ -889,25 +898,28 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
switch (chg_type) {
case MAX77693_CHARGER_TYPE_NONE:
/*
- * When MHL(with USB/TA cable) or Dock-Audio with USB/TA cable
- * is attached, muic device happen below two interrupt.
- * - 'MAX77693_MUIC_IRQ_INT1_ADC' for detecting MHL/Dock-Audio.
- * - 'MAX77693_MUIC_IRQ_INT2_CHGTYP' for detecting USB/TA cable
- * connected to MHL or Dock-Audio.
- * Always, happen eariler MAX77693_MUIC_IRQ_INT1_ADC interrupt
- * than MAX77693_MUIC_IRQ_INT2_CHGTYP interrupt.
+ * When MHL(with USB/TA cable) or Dock-Audio with USB/TA
+ * cable is attached, muic device happen below two irq.
+ * - 'MAX77693_MUIC_IRQ_INT1_ADC' for detecting
+ * MHL/Dock-Audio.
+ * - 'MAX77693_MUIC_IRQ_INT2_CHGTYP' for detecting
+ * USB/TA cable connected to MHL or Dock-Audio.
+ * Always, happen eariler MAX77693_MUIC_IRQ_INT1_ADC
+ * irq than MAX77693_MUIC_IRQ_INT2_CHGTYP irq.
*
- * If user attach MHL (with USB/TA cable and immediately detach
- * MHL with USB/TA cable before MAX77693_MUIC_IRQ_INT2_CHGTYP
- * interrupt is happened, USB/TA cable remain connected state to
- * target. But USB/TA cable isn't connected to target. The user
- * be face with unusual action. So, driver should check this
- * situation in spite of, that previous charger type is N/A.
+ * If user attach MHL (with USB/TA cable and immediately
+ * detach MHL with USB/TA cable before MAX77693_MUIC_IRQ
+ * _INT2_CHGTYP irq is happened, USB/TA cable remain
+ * connected state to target. But USB/TA cable isn't
+ * connected to target. The user be face with unusual
+ * action. So, driver should check this situation in
+ * spite of, that previous charger type is N/A.
*/
break;
case MAX77693_CHARGER_TYPE_USB:
/* Only USB cable, PATH:AP_USB */
- ret = max77693_muic_set_path(info, info->path_usb, attached);
+ ret = max77693_muic_set_path(info, info->path_usb,
+ attached);
if (ret < 0)
return ret;
@@ -1214,7 +1226,8 @@ static int max77693_muic_probe(struct platform_device *pdev)
}
if (pdata->muic_data) {
- struct max77693_muic_platform_data *muic_pdata = pdata->muic_data;
+ struct max77693_muic_platform_data *muic_pdata
+ = pdata->muic_data;
/*
* Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index 67d6738d85a0..b9e726daefca 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -426,7 +426,8 @@ static int max8997_muic_adc_handler(struct max8997_muic_info *info)
break;
case MAX8997_MUIC_ADC_FACTORY_MODE_USB_OFF:
case MAX8997_MUIC_ADC_FACTORY_MODE_USB_ON:
- ret = max8997_muic_handle_usb(info, MAX8997_USB_DEVICE, attached);
+ ret = max8997_muic_handle_usb(info,
+ MAX8997_USB_DEVICE, attached);
if (ret < 0)
return ret;
break;
@@ -504,7 +505,8 @@ static int max8997_muic_chg_handler(struct max8997_muic_info *info)
}
break;
case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT:
- extcon_set_cable_state(info->edev, "Charge-downstream", attached);
+ extcon_set_cable_state(info->edev,
+ "Charge-downstream", attached);
break;
case MAX8997_CHARGER_TYPE_DEDICATED_CHG:
extcon_set_cable_state(info->edev, "TA", attached);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index b6ed304863eb..c8b02a585baf 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -129,7 +129,7 @@ config GPIO_IT8761E
config GPIO_EM
tristate "Emma Mobile GPIO"
- depends on ARM
+ depends on ARM && OF_GPIO
help
Say yes here to support GPIO on Renesas Emma Mobile SoCs.
@@ -320,6 +320,15 @@ config GPIO_ICH
If unsure, say N.
+config GPIO_IOP
+ tristate "Intel IOP GPIO"
+ depends on ARM && (ARCH_IOP32X || ARCH_IOP33X)
+ help
+ Say yes here to support the GPIO functionality of a number of Intel
+ IOP32X or IOP33X.
+
+ If unsure, say N.
+
config GPIO_VX855
tristate "VIA VX855/VX875 GPIO"
depends on PCI
@@ -703,7 +712,7 @@ config GPIO_74X164
comment "AC97 GPIO expanders:"
config GPIO_UCB1400
- bool "Philips UCB1400 GPIO"
+ tristate "Philips UCB1400 GPIO"
depends on UCB1400_CORE
help
This enables support for the Philips UCB1400 GPIO pins.
@@ -759,6 +768,12 @@ config GPIO_MSIC
Enable support for GPIO on intel MSIC controllers found in
intel MID devices
+config GPIO_BCM_KONA
+ bool "Broadcom Kona GPIO"
+ depends on OF_GPIO
+ help
+ Turn on GPIO support for Broadcom "Kona" chips.
+
comment "USB GPIO expanders:"
config GPIO_VIPERBOARD
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 98e23ebba2cf..5c353df1de25 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
+obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
@@ -28,6 +29,7 @@ obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o
obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o
obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
+obj-$(CONFIG_GPIO_IOP) += gpio-iop.o
obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index 5d518d5db7a0..1e04bf91328d 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -176,7 +176,6 @@ static int gen_74x164_probe(struct spi_device *spi)
return ret;
exit_destroy:
- spi_set_drvdata(spi, NULL);
mutex_destroy(&chip->lock);
return ret;
}
@@ -190,8 +189,6 @@ static int gen_74x164_remove(struct spi_device *spi)
if (chip == NULL)
return -ENODEV;
- spi_set_drvdata(spi, NULL);
-
ret = gpiochip_remove(&chip->gpio_chip);
if (!ret)
mutex_destroy(&chip->lock);
@@ -212,7 +209,7 @@ static struct spi_driver gen_74x164_driver = {
.driver = {
.name = "74x164",
.owner = THIS_MODULE,
- .of_match_table = of_match_ptr(gen_74x164_dt_ids),
+ .of_match_table = gen_74x164_dt_ids,
},
.probe = gen_74x164_probe,
.remove = gen_74x164_remove,
diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
index fa8b6a762761..a2bec3c6db94 100644
--- a/drivers/gpio/gpio-arizona.c
+++ b/drivers/gpio/gpio-arizona.c
@@ -113,6 +113,7 @@ static int arizona_gpio_probe(struct platform_device *pdev)
switch (arizona->type) {
case WM5102:
case WM5110:
+ case WM8997:
arizona_gpio->gpio_chip.ngpio = 5;
break;
default:
diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c
new file mode 100644
index 000000000000..c0751a8c2dee
--- /dev/null
+++ b/drivers/gpio/gpio-bcm-kona.c
@@ -0,0 +1,640 @@
+/*
+ * Copyright (C) 2012-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/bitops.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/module.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+
+#define BCM_GPIO_PASSWD 0x00a5a501
+#define GPIO_PER_BANK 32
+#define GPIO_MAX_BANK_NUM 8
+
+#define GPIO_BANK(gpio) ((gpio) >> 5)
+#define GPIO_BIT(gpio) ((gpio) & (GPIO_PER_BANK - 1))
+
+#define GPIO_OUT_STATUS(bank) (0x00000000 + ((bank) << 2))
+#define GPIO_IN_STATUS(bank) (0x00000020 + ((bank) << 2))
+#define GPIO_OUT_SET(bank) (0x00000040 + ((bank) << 2))
+#define GPIO_OUT_CLEAR(bank) (0x00000060 + ((bank) << 2))
+#define GPIO_INT_STATUS(bank) (0x00000080 + ((bank) << 2))
+#define GPIO_INT_MASK(bank) (0x000000a0 + ((bank) << 2))
+#define GPIO_INT_MSKCLR(bank) (0x000000c0 + ((bank) << 2))
+#define GPIO_CONTROL(bank) (0x00000100 + ((bank) << 2))
+#define GPIO_PWD_STATUS(bank) (0x00000500 + ((bank) << 2))
+
+#define GPIO_GPPWR_OFFSET 0x00000520
+
+#define GPIO_GPCTR0_DBR_SHIFT 5
+#define GPIO_GPCTR0_DBR_MASK 0x000001e0
+
+#define GPIO_GPCTR0_ITR_SHIFT 3
+#define GPIO_GPCTR0_ITR_MASK 0x00000018
+#define GPIO_GPCTR0_ITR_CMD_RISING_EDGE 0x00000001
+#define GPIO_GPCTR0_ITR_CMD_FALLING_EDGE 0x00000002
+#define GPIO_GPCTR0_ITR_CMD_BOTH_EDGE 0x00000003
+
+#define GPIO_GPCTR0_IOTR_MASK 0x00000001
+#define GPIO_GPCTR0_IOTR_CMD_0UTPUT 0x00000000
+#define GPIO_GPCTR0_IOTR_CMD_INPUT 0x00000001
+
+#define GPIO_GPCTR0_DB_ENABLE_MASK 0x00000100
+
+#define LOCK_CODE 0xffffffff
+#define UNLOCK_CODE 0x00000000
+
+struct bcm_kona_gpio {
+ void __iomem *reg_base;
+ int num_bank;
+ spinlock_t lock;
+ struct gpio_chip gpio_chip;
+ struct irq_domain *irq_domain;
+ struct bcm_kona_gpio_bank *banks;
+ struct platform_device *pdev;
+};
+
+struct bcm_kona_gpio_bank {
+ int id;
+ int irq;
+ /* Used in the interrupt handler */
+ struct bcm_kona_gpio *kona_gpio;
+};
+
+static inline struct bcm_kona_gpio *to_kona_gpio(struct gpio_chip *chip)
+{
+ return container_of(chip, struct bcm_kona_gpio, gpio_chip);
+}
+
+static void bcm_kona_gpio_set_lockcode_bank(void __iomem *reg_base,
+ int bank_id, int lockcode)
+{
+ writel(BCM_GPIO_PASSWD, reg_base + GPIO_GPPWR_OFFSET);
+ writel(lockcode, reg_base + GPIO_PWD_STATUS(bank_id));
+}
+
+static inline void bcm_kona_gpio_lock_bank(void __iomem *reg_base, int bank_id)
+{
+ bcm_kona_gpio_set_lockcode_bank(reg_base, bank_id, LOCK_CODE);
+}
+
+static inline void bcm_kona_gpio_unlock_bank(void __iomem *reg_base,
+ int bank_id)
+{
+ bcm_kona_gpio_set_lockcode_bank(reg_base, bank_id, UNLOCK_CODE);
+}
+
+static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
+{
+ struct bcm_kona_gpio *kona_gpio;
+ void __iomem *reg_base;
+ int bank_id = GPIO_BANK(gpio);
+ int bit = GPIO_BIT(gpio);
+ u32 val, reg_offset;
+ unsigned long flags;
+
+ kona_gpio = to_kona_gpio(chip);
+ reg_base = kona_gpio->reg_base;
+ spin_lock_irqsave(&kona_gpio->lock, flags);
+ bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+ /* determine the GPIO pin direction */
+ val = readl(reg_base + GPIO_CONTROL(gpio));
+ val &= GPIO_GPCTR0_IOTR_MASK;
+
+ /* this function only applies to output pin */
+ if (GPIO_GPCTR0_IOTR_CMD_INPUT == val)
+ goto out;
+
+ reg_offset = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
+
+ val = readl(reg_base + reg_offset);
+ val |= BIT(bit);
+ writel(val, reg_base + reg_offset);
+
+out:
+ bcm_kona_gpio_lock_bank(reg_base, bank_id);
+ spin_unlock_irqrestore(&kona_gpio->lock, flags);
+}
+
+static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
+{
+ struct bcm_kona_gpio *kona_gpio;
+ void __iomem *reg_base;
+ int bank_id = GPIO_BANK(gpio);
+ int bit = GPIO_BIT(gpio);
+ u32 val, reg_offset;
+ unsigned long flags;
+
+ kona_gpio = to_kona_gpio(chip);
+ reg_base = kona_gpio->reg_base;
+ spin_lock_irqsave(&kona_gpio->lock, flags);
+ bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+ /* determine the GPIO pin direction */
+ val = readl(reg_base + GPIO_CONTROL(gpio));
+ val &= GPIO_GPCTR0_IOTR_MASK;
+
+ /* read the GPIO bank status */
+ reg_offset = (GPIO_GPCTR0_IOTR_CMD_INPUT == val) ?
+ GPIO_IN_STATUS(bank_id) : GPIO_OUT_STATUS(bank_id);
+ val = readl(reg_base + reg_offset);
+
+ bcm_kona_gpio_lock_bank(reg_base, bank_id);
+ spin_unlock_irqrestore(&kona_gpio->lock, flags);
+
+ /* return the specified bit status */
+ return !!(val & bit);
+}
+
+static int bcm_kona_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+ struct bcm_kona_gpio *kona_gpio;
+ void __iomem *reg_base;
+ u32 val;
+ unsigned long flags;
+ int bank_id = GPIO_BANK(gpio);
+
+ kona_gpio = to_kona_gpio(chip);
+ reg_base = kona_gpio->reg_base;
+ spin_lock_irqsave(&kona_gpio->lock, flags);
+ bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+ val = readl(reg_base + GPIO_CONTROL(gpio));
+ val &= ~GPIO_GPCTR0_IOTR_MASK;
+ val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
+ writel(val, reg_base + GPIO_CONTROL(gpio));
+
+ bcm_kona_gpio_lock_bank(reg_base, bank_id);
+ spin_unlock_irqrestore(&kona_gpio->lock, flags);
+
+ return 0;
+}
+
+static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
+ unsigned gpio, int value)
+{
+ struct bcm_kona_gpio *kona_gpio;
+ void __iomem *reg_base;
+ int bank_id = GPIO_BANK(gpio);
+ int bit = GPIO_BIT(gpio);
+ u32 val, reg_offset;
+ unsigned long flags;
+
+ kona_gpio = to_kona_gpio(chip);
+ reg_base = kona_gpio->reg_base;
+ spin_lock_irqsave(&kona_gpio->lock, flags);
+ bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+ val = readl(reg_base + GPIO_CONTROL(gpio));
+ val &= ~GPIO_GPCTR0_IOTR_MASK;
+ val |= GPIO_GPCTR0_IOTR_CMD_0UTPUT;
+ writel(val, reg_base + GPIO_CONTROL(gpio));
+ reg_offset = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
+
+ val = readl(reg_base + reg_offset);
+ val |= BIT(bit);
+ writel(val, reg_base + reg_offset);
+
+ bcm_kona_gpio_lock_bank(reg_base, bank_id);
+ spin_unlock_irqrestore(&kona_gpio->lock, flags);
+
+ return 0;
+}
+
+static int bcm_kona_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
+{
+ struct bcm_kona_gpio *kona_gpio;
+
+ kona_gpio = to_kona_gpio(chip);
+ if (gpio >= kona_gpio->gpio_chip.ngpio)
+ return -ENXIO;
+ return irq_create_mapping(kona_gpio->irq_domain, gpio);
+}
+
+static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
+ unsigned debounce)
+{
+ struct bcm_kona_gpio *kona_gpio;
+ void __iomem *reg_base;
+ u32 val, res;
+ unsigned long flags;
+ int bank_id = GPIO_BANK(gpio);
+
+ kona_gpio = to_kona_gpio(chip);
+ reg_base = kona_gpio->reg_base;
+ /* debounce must be 1-128ms (or 0) */
+ if ((debounce > 0 && debounce < 1000) || debounce > 128000) {
+ dev_err(chip->dev, "Debounce value %u not in range\n",
+ debounce);
+ return -EINVAL;
+ }
+
+ /* calculate debounce bit value */
+ if (debounce != 0) {
+ /* Convert to ms */
+ debounce /= 1000;
+ /* find the MSB */
+ res = fls(debounce) - 1;
+ /* Check if MSB-1 is set (round up or down) */
+ if (res > 0 && (debounce & BIT(res - 1)))
+ res++;
+ }
+
+ /* spin lock for read-modify-write of the GPIO register */
+ spin_lock_irqsave(&kona_gpio->lock, flags);
+ bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+ val = readl(reg_base + GPIO_CONTROL(gpio));
+ val &= ~GPIO_GPCTR0_DBR_MASK;
+
+ if (debounce == 0) {
+ /* disable debounce */
+ val &= ~GPIO_GPCTR0_DB_ENABLE_MASK;
+ } else {
+ val |= GPIO_GPCTR0_DB_ENABLE_MASK |
+ (res << GPIO_GPCTR0_DBR_SHIFT);
+ }
+
+ writel(val, reg_base + GPIO_CONTROL(gpio));
+
+ bcm_kona_gpio_lock_bank(reg_base, bank_id);
+ spin_unlock_irqrestore(&kona_gpio->lock, flags);
+
+ return 0;
+}
+
+static struct gpio_chip template_chip = {
+ .label = "bcm-kona-gpio",
+ .direction_input = bcm_kona_gpio_direction_input,
+ .get = bcm_kona_gpio_get,
+ .direction_output = bcm_kona_gpio_direction_output,
+ .set = bcm_kona_gpio_set,
+ .set_debounce = bcm_kona_gpio_set_debounce,
+ .to_irq = bcm_kona_gpio_to_irq,
+ .base = 0,
+};
+
+static void bcm_kona_gpio_irq_ack(struct irq_data *d)
+{
+ struct bcm_kona_gpio *kona_gpio;
+ void __iomem *reg_base;
+ int gpio = d->hwirq;
+ int bank_id = GPIO_BANK(gpio);
+ int bit = GPIO_BIT(gpio);
+ u32 val;
+ unsigned long flags;
+
+ kona_gpio = irq_data_get_irq_chip_data(d);
+ reg_base = kona_gpio->reg_base;
+ spin_lock_irqsave(&kona_gpio->lock, flags);
+ bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+ val = readl(reg_base + GPIO_INT_STATUS(bank_id));
+ val |= BIT(bit);
+ writel(val, reg_base + GPIO_INT_STATUS(bank_id));
+
+ bcm_kona_gpio_lock_bank(reg_base, bank_id);
+ spin_unlock_irqrestore(&kona_gpio->lock, flags);
+}
+
+static void bcm_kona_gpio_irq_mask(struct irq_data *d)
+{
+ struct bcm_kona_gpio *kona_gpio;
+ void __iomem *reg_base;
+ int gpio = d->hwirq;
+ int bank_id = GPIO_BANK(gpio);
+ int bit = GPIO_BIT(gpio);
+ u32 val;
+ unsigned long flags;
+
+ kona_gpio = irq_data_get_irq_chip_data(d);
+ reg_base = kona_gpio->reg_base;
+ spin_lock_irqsave(&kona_gpio->lock, flags);
+ bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+ val = readl(reg_base + GPIO_INT_MASK(bank_id));
+ val |= BIT(bit);
+ writel(val, reg_base + GPIO_INT_MASK(bank_id));
+
+ bcm_kona_gpio_lock_bank(reg_base, bank_id);
+ spin_unlock_irqrestore(&kona_gpio->lock, flags);
+}
+
+static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
+{
+ struct bcm_kona_gpio *kona_gpio;
+ void __iomem *reg_base;
+ int gpio = d->hwirq;
+ int bank_id = GPIO_BANK(gpio);
+ int bit = GPIO_BIT(gpio);
+ u32 val;
+ unsigned long flags;
+
+ kona_gpio = irq_data_get_irq_chip_data(d);
+ reg_base = kona_gpio->reg_base;
+ spin_lock_irqsave(&kona_gpio->lock, flags);
+ bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+ val = readl(reg_base + GPIO_INT_MSKCLR(bank_id));
+ val |= BIT(bit);
+ writel(val, reg_base + GPIO_INT_MSKCLR(bank_id));
+
+ bcm_kona_gpio_lock_bank(reg_base, bank_id);
+ spin_unlock_irqrestore(&kona_gpio->lock, flags);
+}
+
+static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+ struct bcm_kona_gpio *kona_gpio;
+ void __iomem *reg_base;
+ int gpio = d->hwirq;
+ u32 lvl_type;
+ u32 val;
+ unsigned long flags;
+ int bank_id = GPIO_BANK(gpio);
+
+ kona_gpio = irq_data_get_irq_chip_data(d);
+ reg_base = kona_gpio->reg_base;
+ switch (type & IRQ_TYPE_SENSE_MASK) {
+ case IRQ_TYPE_EDGE_RISING:
+ lvl_type = GPIO_GPCTR0_ITR_CMD_RISING_EDGE;
+ break;
+
+ case IRQ_TYPE_EDGE_FALLING:
+ lvl_type = GPIO_GPCTR0_ITR_CMD_FALLING_EDGE;
+ break;
+
+ case IRQ_TYPE_EDGE_BOTH:
+ lvl_type = GPIO_GPCTR0_ITR_CMD_BOTH_EDGE;
+ break;
+
+ case IRQ_TYPE_LEVEL_HIGH:
+ case IRQ_TYPE_LEVEL_LOW:
+ /* BCM GPIO doesn't support level triggering */
+ default:
+ dev_err(kona_gpio->gpio_chip.dev,
+ "Invalid BCM GPIO irq type 0x%x\n", type);
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&kona_gpio->lock, flags);
+ bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+ val = readl(reg_base + GPIO_CONTROL(gpio));
+ val &= ~GPIO_GPCTR0_ITR_MASK;
+ val |= lvl_type << GPIO_GPCTR0_ITR_SHIFT;
+ writel(val, reg_base + GPIO_CONTROL(gpio));
+
+ bcm_kona_gpio_lock_bank(reg_base, bank_id);
+ spin_unlock_irqrestore(&kona_gpio->lock, flags);
+
+ return 0;
+}
+
+static void bcm_kona_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+ void __iomem *reg_base;
+ int bit, bank_id;
+ unsigned long sta;
+ struct bcm_kona_gpio_bank *bank = irq_get_handler_data(irq);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+
+ chained_irq_enter(chip, desc);
+
+ /*
+ * For bank interrupts, we can't use chip_data to store the kona_gpio
+ * pointer, since GIC needs it for its own purposes. Therefore, we get
+ * our pointer from the bank structure.
+ */
+ reg_base = bank->kona_gpio->reg_base;
+ bank_id = bank->id;
+ bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+ while ((sta = readl(reg_base + GPIO_INT_STATUS(bank_id)) &
+ (~(readl(reg_base + GPIO_INT_MASK(bank_id)))))) {
+ for_each_set_bit(bit, &sta, 32) {
+ int gpio = GPIO_PER_BANK * bank_id + bit;
+ int virq = irq_find_mapping(bank->kona_gpio->irq_domain,
+ gpio);
+ /*
+ * Clear interrupt before handler is called so we don't
+ * miss any interrupt occurred during executing them.
+ */
+ writel(readl(reg_base + GPIO_INT_STATUS(bank_id)) |
+ BIT(bit), reg_base + GPIO_INT_STATUS(bank_id));
+ /* Invoke interrupt handler */
+ generic_handle_irq(virq);
+ }
+ }
+
+ bcm_kona_gpio_lock_bank(reg_base, bank_id);
+
+ chained_irq_exit(chip, desc);
+}
+
+static struct irq_chip bcm_gpio_irq_chip = {
+ .name = "bcm-kona-gpio",
+ .irq_ack = bcm_kona_gpio_irq_ack,
+ .irq_mask = bcm_kona_gpio_irq_mask,
+ .irq_unmask = bcm_kona_gpio_irq_unmask,
+ .irq_set_type = bcm_kona_gpio_irq_set_type,
+};
+
+static struct __initconst of_device_id bcm_kona_gpio_of_match[] = {
+ { .compatible = "brcm,kona-gpio" },
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, bcm_kona_gpio_of_match);
+
+/*
+ * 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 gpio_lock_class;
+
+static int bcm_kona_gpio_irq_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ int ret;
+
+ ret = irq_set_chip_data(irq, d->host_data);
+ if (ret < 0)
+ return ret;
+ irq_set_lockdep_class(irq, &gpio_lock_class);
+ irq_set_chip_and_handler(irq, &bcm_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 bcm_kona_gpio_irq_unmap(struct irq_domain *d, unsigned int virq)
+{
+ irq_set_chip_and_handler(virq, NULL, NULL);
+ irq_set_chip_data(virq, NULL);
+}
+
+static struct irq_domain_ops bcm_kona_irq_ops = {
+ .map = bcm_kona_gpio_irq_map,
+ .unmap = bcm_kona_gpio_irq_unmap,
+ .xlate = irq_domain_xlate_twocell,
+};
+
+static void bcm_kona_gpio_reset(struct bcm_kona_gpio *kona_gpio)
+{
+ void __iomem *reg_base;
+ int i;
+
+ reg_base = kona_gpio->reg_base;
+ /* disable interrupts and clear status */
+ for (i = 0; i < kona_gpio->num_bank; i++) {
+ bcm_kona_gpio_unlock_bank(reg_base, i);
+ writel(0xffffffff, reg_base + GPIO_INT_MASK(i));
+ writel(0xffffffff, reg_base + GPIO_INT_STATUS(i));
+ bcm_kona_gpio_lock_bank(reg_base, i);
+ }
+}
+
+static int bcm_kona_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct of_device_id *match;
+ struct resource *res;
+ struct bcm_kona_gpio_bank *bank;
+ struct bcm_kona_gpio *kona_gpio;
+ struct gpio_chip *chip;
+ int ret;
+ int i;
+
+ match = of_match_device(bcm_kona_gpio_of_match, dev);
+ if (!match) {
+ dev_err(dev, "Failed to find gpio controller\n");
+ return -ENODEV;
+ }
+
+ kona_gpio = devm_kzalloc(dev, sizeof(*kona_gpio), GFP_KERNEL);
+ if (!kona_gpio)
+ return -ENOMEM;
+
+ kona_gpio->gpio_chip = template_chip;
+ chip = &kona_gpio->gpio_chip;
+ kona_gpio->num_bank = of_irq_count(dev->of_node);
+ if (kona_gpio->num_bank == 0) {
+ dev_err(dev, "Couldn't determine # GPIO banks\n");
+ return -ENOENT;
+ }
+ if (kona_gpio->num_bank > GPIO_MAX_BANK_NUM) {
+ dev_err(dev, "Too many GPIO banks configured (max=%d)\n",
+ GPIO_MAX_BANK_NUM);
+ return -ENXIO;
+ }
+ kona_gpio->banks = devm_kzalloc(dev,
+ kona_gpio->num_bank *
+ sizeof(*kona_gpio->banks), GFP_KERNEL);
+ if (!kona_gpio->banks)
+ return -ENOMEM;
+
+ kona_gpio->pdev = pdev;
+ platform_set_drvdata(pdev, kona_gpio);
+ chip->of_node = dev->of_node;
+ chip->ngpio = kona_gpio->num_bank * GPIO_PER_BANK;
+
+ kona_gpio->irq_domain = irq_domain_add_linear(dev->of_node,
+ chip->ngpio,
+ &bcm_kona_irq_ops,
+ kona_gpio);
+ if (!kona_gpio->irq_domain) {
+ dev_err(dev, "Couldn't allocate IRQ domain\n");
+ return -ENXIO;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ kona_gpio->reg_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(kona_gpio->reg_base)) {
+ ret = -ENXIO;
+ goto err_irq_domain;
+ }
+
+ for (i = 0; i < kona_gpio->num_bank; i++) {
+ bank = &kona_gpio->banks[i];
+ bank->id = i;
+ bank->irq = platform_get_irq(pdev, i);
+ bank->kona_gpio = kona_gpio;
+ if (bank->irq < 0) {
+ dev_err(dev, "Couldn't get IRQ for bank %d", i);
+ ret = -ENOENT;
+ goto err_irq_domain;
+ }
+ }
+
+ dev_info(&pdev->dev, "Setting up Kona GPIO at 0x%p (phys %#x)\n",
+ kona_gpio->reg_base, res->start);
+
+ bcm_kona_gpio_reset(kona_gpio);
+
+ ret = gpiochip_add(chip);
+ if (ret < 0) {
+ dev_err(dev, "Couldn't add GPIO chip -- %d\n", ret);
+ goto err_irq_domain;
+ }
+ for (i = 0; i < chip->ngpio; i++) {
+ int irq = bcm_kona_gpio_to_irq(chip, i);
+ irq_set_lockdep_class(irq, &gpio_lock_class);
+ irq_set_chip_and_handler(irq, &bcm_gpio_irq_chip,
+ handle_simple_irq);
+#ifdef CONFIG_ARM
+ set_irq_flags(irq, IRQF_VALID);
+#else
+ irq_set_noprobe(irq);
+#endif
+ }
+ for (i = 0; i < kona_gpio->num_bank; i++) {
+ bank = &kona_gpio->banks[i];
+ irq_set_chained_handler(bank->irq, bcm_kona_gpio_irq_handler);
+ irq_set_handler_data(bank->irq, bank);
+ }
+
+ spin_lock_init(&kona_gpio->lock);
+
+ return 0;
+
+err_irq_domain:
+ irq_domain_remove(kona_gpio->irq_domain);
+
+ return ret;
+}
+
+static struct platform_driver bcm_kona_gpio_driver = {
+ .driver = {
+ .name = "bcm-kona-gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = bcm_kona_gpio_of_match,
+ },
+ .probe = bcm_kona_gpio_probe,
+};
+
+module_platform_driver(bcm_kona_gpio_driver);
+
+MODULE_AUTHOR("Broadcom");
+MODULE_DESCRIPTION("Broadcom Kona GPIO Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c
index 8369e71ebe4f..9dfe36fd8baf 100644
--- a/drivers/gpio/gpio-bt8xx.c
+++ b/drivers/gpio/gpio-bt8xx.c
@@ -228,7 +228,6 @@ static int bt8xxgpio_probe(struct pci_dev *dev,
err_release_mem:
release_mem_region(pci_resource_start(dev, 0),
pci_resource_len(dev, 0));
- pci_set_drvdata(dev, NULL);
err_disable:
pci_disable_device(dev);
err_freebg:
@@ -252,7 +251,6 @@ static void bt8xxgpio_remove(struct pci_dev *pdev)
pci_resource_len(pdev, 0));
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
kfree(bg);
}
diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
index c6e1f086efe8..160d759170a5 100644
--- a/drivers/gpio/gpio-em.c
+++ b/drivers/gpio/gpio-em.c
@@ -319,6 +319,7 @@ static int em_gio_probe(struct platform_device *pdev)
}
gpio_chip = &p->gpio_chip;
+ gpio_chip->of_node = pdev->dev.of_node;
gpio_chip->direction_input = em_gio_direction_input;
gpio_chip->get = em_gio_get;
gpio_chip->direction_output = em_gio_direction_output;
diff --git a/arch/arm/plat-iop/gpio.c b/drivers/gpio/gpio-iop.c
index 697de6dc4936..c22a61be3a9c 100644
--- a/arch/arm/plat-iop/gpio.c
+++ b/drivers/gpio/gpio-iop.c
@@ -16,42 +16,61 @@
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/export.h>
-#include <asm/hardware/iop3xx.h>
-#include <mach/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
-void gpio_line_config(int line, int direction)
+#define IOP3XX_N_GPIOS 8
+
+#define GPIO_IN 0
+#define GPIO_OUT 1
+#define GPIO_LOW 0
+#define GPIO_HIGH 1
+
+/* Memory base offset */
+static void __iomem *base;
+
+#define IOP3XX_GPIO_REG(reg) (base + (reg))
+#define IOP3XX_GPOE IOP3XX_GPIO_REG(0x0000)
+#define IOP3XX_GPID IOP3XX_GPIO_REG(0x0004)
+#define IOP3XX_GPOD IOP3XX_GPIO_REG(0x0008)
+
+static void gpio_line_config(int line, int direction)
{
unsigned long flags;
+ u32 val;
local_irq_save(flags);
+ val = readl(IOP3XX_GPOE);
if (direction == GPIO_IN) {
- *IOP3XX_GPOE |= 1 << line;
+ val |= BIT(line);
} else if (direction == GPIO_OUT) {
- *IOP3XX_GPOE &= ~(1 << line);
+ val &= ~BIT(line);
}
+ writel(val, IOP3XX_GPOE);
local_irq_restore(flags);
}
-EXPORT_SYMBOL(gpio_line_config);
-int gpio_line_get(int line)
+static int gpio_line_get(int line)
{
- return !!(*IOP3XX_GPID & (1 << line));
+ return !!(readl(IOP3XX_GPID) & BIT(line));
}
-EXPORT_SYMBOL(gpio_line_get);
-void gpio_line_set(int line, int value)
+static void gpio_line_set(int line, int value)
{
unsigned long flags;
+ u32 val;
local_irq_save(flags);
+ val = readl(IOP3XX_GPOD);
if (value == GPIO_LOW) {
- *IOP3XX_GPOD &= ~(1 << line);
+ val &= ~BIT(line);
} else if (value == GPIO_HIGH) {
- *IOP3XX_GPOD |= 1 << line;
+ val |= BIT(line);
}
+ writel(val, IOP3XX_GPOD);
local_irq_restore(flags);
}
-EXPORT_SYMBOL(gpio_line_set);
static int iop3xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
@@ -86,8 +105,26 @@ static struct gpio_chip iop3xx_chip = {
.ngpio = IOP3XX_N_GPIOS,
};
-static int __init iop3xx_gpio_setup(void)
+static int iop3xx_gpio_probe(struct platform_device *pdev)
{
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+
return gpiochip_add(&iop3xx_chip);
}
-arch_initcall(iop3xx_gpio_setup);
+
+static struct platform_driver iop3xx_gpio_driver = {
+ .driver = {
+ .name = "gpio-iop",
+ .owner = THIS_MODULE,
+ },
+ .probe = iop3xx_gpio_probe,
+};
+
+static int __init iop3xx_gpio_init(void)
+{
+ return platform_driver_register(&iop3xx_gpio_driver);
+}
+arch_initcall(iop3xx_gpio_init);
diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c
index 3fd2caa4a2e0..c0b7835f5136 100644
--- a/drivers/gpio/gpio-mc33880.c
+++ b/drivers/gpio/gpio-mc33880.c
@@ -142,7 +142,6 @@ static int mc33880_probe(struct spi_device *spi)
return ret;
exit_destroy:
- spi_set_drvdata(spi, NULL);
mutex_destroy(&mc->lock);
return ret;
}
@@ -156,8 +155,6 @@ static int mc33880_remove(struct spi_device *spi)
if (mc == NULL)
return -ENODEV;
- spi_set_drvdata(spi, NULL);
-
ret = gpiochip_remove(&mc->chip);
if (!ret)
mutex_destroy(&mc->lock);
diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c
index 8588af0f7661..11801e986dd9 100644
--- a/drivers/gpio/gpio-palmas.c
+++ b/drivers/gpio/gpio-palmas.c
@@ -31,6 +31,10 @@ struct palmas_gpio {
struct palmas *palmas;
};
+struct palmas_device_data {
+ int ngpio;
+};
+
static inline struct palmas_gpio *to_palmas_gpio(struct gpio_chip *chip)
{
return container_of(chip, struct palmas_gpio, gpio_chip);
@@ -42,23 +46,26 @@ static int palmas_gpio_get(struct gpio_chip *gc, unsigned offset)
struct palmas *palmas = pg->palmas;
unsigned int val;
int ret;
+ unsigned int reg;
+ int gpio16 = (offset/8);
+
+ offset %= 8;
+ reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
- ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_DIR, &val);
+ ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);
if (ret < 0) {
- dev_err(gc->dev, "GPIO_DATA_DIR read failed, err = %d\n", ret);
+ dev_err(gc->dev, "Reg 0x%02x read failed, %d\n", reg, ret);
return ret;
}
- if (val & (1 << offset)) {
- ret = palmas_read(palmas, PALMAS_GPIO_BASE,
- PALMAS_GPIO_DATA_OUT, &val);
- } else {
- ret = palmas_read(palmas, PALMAS_GPIO_BASE,
- PALMAS_GPIO_DATA_IN, &val);
- }
+ if (val & BIT(offset))
+ reg = (gpio16) ? PALMAS_GPIO_DATA_OUT2 : PALMAS_GPIO_DATA_OUT;
+ else
+ reg = (gpio16) ? PALMAS_GPIO_DATA_IN2 : PALMAS_GPIO_DATA_IN;
+
+ ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);
if (ret < 0) {
- dev_err(gc->dev, "GPIO_DATA_IN/OUT read failed, err = %d\n",
- ret);
+ dev_err(gc->dev, "Reg 0x%02x read failed, %d\n", reg, ret);
return ret;
}
return !!(val & BIT(offset));
@@ -70,17 +77,20 @@ static void palmas_gpio_set(struct gpio_chip *gc, unsigned offset,
struct palmas_gpio *pg = to_palmas_gpio(gc);
struct palmas *palmas = pg->palmas;
int ret;
+ unsigned int reg;
+ int gpio16 = (offset/8);
- if (value)
- ret = palmas_write(palmas, PALMAS_GPIO_BASE,
- PALMAS_GPIO_SET_DATA_OUT, BIT(offset));
+ offset %= 8;
+ if (gpio16)
+ reg = (value) ?
+ PALMAS_GPIO_SET_DATA_OUT2 : PALMAS_GPIO_CLEAR_DATA_OUT2;
else
- ret = palmas_write(palmas, PALMAS_GPIO_BASE,
- PALMAS_GPIO_CLEAR_DATA_OUT, BIT(offset));
+ reg = (value) ?
+ PALMAS_GPIO_SET_DATA_OUT : PALMAS_GPIO_CLEAR_DATA_OUT;
+
+ ret = palmas_write(palmas, PALMAS_GPIO_BASE, reg, BIT(offset));
if (ret < 0)
- dev_err(gc->dev, "%s write failed, err = %d\n",
- (value) ? "GPIO_SET_DATA_OUT" : "GPIO_CLEAR_DATA_OUT",
- ret);
+ dev_err(gc->dev, "Reg 0x%02x write failed, %d\n", reg, ret);
}
static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset,
@@ -89,14 +99,19 @@ static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset,
struct palmas_gpio *pg = to_palmas_gpio(gc);
struct palmas *palmas = pg->palmas;
int ret;
+ unsigned int reg;
+ int gpio16 = (offset/8);
+
+ offset %= 8;
+ reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
/* Set the initial value */
palmas_gpio_set(gc, offset, value);
- ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE,
- PALMAS_GPIO_DATA_DIR, BIT(offset), BIT(offset));
+ ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg,
+ BIT(offset), BIT(offset));
if (ret < 0)
- dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret);
+ dev_err(gc->dev, "Reg 0x%02x update failed, %d\n", reg, ret);
return ret;
}
@@ -105,11 +120,15 @@ static int palmas_gpio_input(struct gpio_chip *gc, unsigned offset)
struct palmas_gpio *pg = to_palmas_gpio(gc);
struct palmas *palmas = pg->palmas;
int ret;
+ unsigned int reg;
+ int gpio16 = (offset/8);
+
+ offset %= 8;
+ reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
- ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE,
- PALMAS_GPIO_DATA_DIR, BIT(offset), 0);
+ ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, BIT(offset), 0);
if (ret < 0)
- dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret);
+ dev_err(gc->dev, "Reg 0x%02x update failed, %d\n", reg, ret);
return ret;
}
@@ -121,12 +140,36 @@ static int palmas_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
return palmas_irq_get_virq(palmas, PALMAS_GPIO_0_IRQ + offset);
}
+static const struct palmas_device_data palmas_dev_data = {
+ .ngpio = 8,
+};
+
+static const struct palmas_device_data tps80036_dev_data = {
+ .ngpio = 16,
+};
+
+static 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,},
+ { .compatible = "ti,tps80036-gpio", .data = &tps80036_dev_data,},
+ { },
+};
+MODULE_DEVICE_TABLE(of, of_palmas_gpio_match);
+
static int palmas_gpio_probe(struct platform_device *pdev)
{
struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
struct palmas_platform_data *palmas_pdata;
struct palmas_gpio *palmas_gpio;
int ret;
+ const struct of_device_id *match;
+ const struct palmas_device_data *dev_data;
+
+ match = of_match_device(of_palmas_gpio_match, &pdev->dev);
+ dev_data = match->data;
+ if (!dev_data)
+ dev_data = &palmas_dev_data;
palmas_gpio = devm_kzalloc(&pdev->dev,
sizeof(*palmas_gpio), GFP_KERNEL);
@@ -138,7 +181,7 @@ static int palmas_gpio_probe(struct platform_device *pdev)
palmas_gpio->palmas = palmas;
palmas_gpio->gpio_chip.owner = THIS_MODULE;
palmas_gpio->gpio_chip.label = dev_name(&pdev->dev);
- palmas_gpio->gpio_chip.ngpio = 8;
+ palmas_gpio->gpio_chip.ngpio = dev_data->ngpio;
palmas_gpio->gpio_chip.can_sleep = 1;
palmas_gpio->gpio_chip.direction_input = palmas_gpio_input;
palmas_gpio->gpio_chip.direction_output = palmas_gpio_output;
@@ -172,15 +215,6 @@ static int palmas_gpio_remove(struct platform_device *pdev)
return gpiochip_remove(&palmas_gpio->gpio_chip);
}
-static struct of_device_id of_palmas_gpio_match[] = {
- { .compatible = "ti,palmas-gpio"},
- { .compatible = "ti,tps65913-gpio"},
- { .compatible = "ti,tps65914-gpio"},
- { .compatible = "ti,tps80036-gpio"},
- { },
-};
-MODULE_DEVICE_TABLE(of, of_palmas_gpio_match);
-
static struct platform_driver palmas_gpio_driver = {
.driver.name = "palmas-gpio",
.driver.owner = THIS_MODULE,
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index cdd1aa12b895..6e48c07e3d8c 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -683,17 +683,6 @@ static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
int ret;
u8 val[MAX_BANK];
- /* Let every port in proper state, that could save power */
- memset(val, 0, NBANK(chip));
- pca953x_write_regs(chip, PCA957X_PUPD, val);
- memset(val, 0xFF, NBANK(chip));
- pca953x_write_regs(chip, PCA957X_CFG, val);
- memset(val, 0, NBANK(chip));
- pca953x_write_regs(chip, PCA957X_OUT, val);
-
- ret = pca953x_read_regs(chip, PCA957X_IN, val);
- if (ret)
- goto out;
ret = pca953x_read_regs(chip, PCA957X_OUT, chip->reg_output);
if (ret)
goto out;
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index 9e61bb0719d0..1535686e74ea 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -26,9 +26,10 @@
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
-#include <linux/workqueue.h>
static const struct i2c_device_id pcf857x_id[] = {
@@ -50,6 +51,27 @@ static const struct i2c_device_id pcf857x_id[] = {
};
MODULE_DEVICE_TABLE(i2c, pcf857x_id);
+#ifdef CONFIG_OF
+static const struct of_device_id pcf857x_of_table[] = {
+ { .compatible = "nxp,pcf8574" },
+ { .compatible = "nxp,pcf8574a" },
+ { .compatible = "nxp,pca8574" },
+ { .compatible = "nxp,pca9670" },
+ { .compatible = "nxp,pca9672" },
+ { .compatible = "nxp,pca9674" },
+ { .compatible = "nxp,pcf8575" },
+ { .compatible = "nxp,pca8575" },
+ { .compatible = "nxp,pca9671" },
+ { .compatible = "nxp,pca9673" },
+ { .compatible = "nxp,pca9675" },
+ { .compatible = "maxim,max7328" },
+ { .compatible = "maxim,max7329" },
+ { .compatible = "ti,tca9554" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pcf857x_of_table);
+#endif
+
/*
* The pcf857x, pca857x, and pca967x chips only expose one read and one
* write register. Writing a "one" bit (to match the reset state) lets
@@ -66,12 +88,11 @@ struct pcf857x {
struct gpio_chip chip;
struct i2c_client *client;
struct mutex lock; /* protect 'out' */
- struct work_struct work; /* irq demux work */
struct irq_domain *irq_domain; /* for irq demux */
spinlock_t slock; /* protect irq demux */
unsigned out; /* software latch */
unsigned status; /* current status */
- int irq; /* real irq number */
+ unsigned irq_mapped; /* mapped gpio irqs */
int (*write)(struct i2c_client *client, unsigned data);
int (*read)(struct i2c_client *client);
@@ -164,48 +185,54 @@ static void pcf857x_set(struct gpio_chip *chip, unsigned offset, int value)
static int pcf857x_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
+ int ret;
- return irq_create_mapping(gpio->irq_domain, offset);
+ ret = irq_create_mapping(gpio->irq_domain, offset);
+ if (ret > 0)
+ gpio->irq_mapped |= (1 << offset);
+
+ return ret;
}
-static void pcf857x_irq_demux_work(struct work_struct *work)
+static irqreturn_t pcf857x_irq(int irq, void *data)
{
- struct pcf857x *gpio = container_of(work,
- struct pcf857x,
- work);
+ struct pcf857x *gpio = data;
unsigned long change, i, status, flags;
status = gpio->read(gpio->client);
spin_lock_irqsave(&gpio->slock, flags);
- change = gpio->status ^ status;
+ /*
+ * call the interrupt handler iff gpio is used as
+ * interrupt source, just to avoid bad irqs
+ */
+
+ change = ((gpio->status ^ status) & gpio->irq_mapped);
for_each_set_bit(i, &change, gpio->chip.ngpio)
generic_handle_irq(irq_find_mapping(gpio->irq_domain, i));
gpio->status = status;
spin_unlock_irqrestore(&gpio->slock, flags);
-}
-
-static irqreturn_t pcf857x_irq_demux(int irq, void *data)
-{
- struct pcf857x *gpio = data;
-
- /*
- * pcf857x can't read/write data here,
- * since i2c data access might go to sleep.
- */
- schedule_work(&gpio->work);
return IRQ_HANDLED;
}
-static int pcf857x_irq_domain_map(struct irq_domain *domain, unsigned int virq,
+static int pcf857x_irq_domain_map(struct irq_domain *domain, unsigned int irq,
irq_hw_number_t hw)
{
- irq_set_chip_and_handler(virq,
+ struct pcf857x *gpio = domain->host_data;
+
+ irq_set_chip_and_handler(irq,
&dummy_irq_chip,
handle_level_irq);
+#ifdef CONFIG_ARM
+ set_irq_flags(irq, IRQF_VALID);
+#else
+ irq_set_noprobe(irq);
+#endif
+ gpio->irq_mapped |= (1 << hw);
+
return 0;
}
@@ -218,8 +245,6 @@ static void pcf857x_irq_domain_cleanup(struct pcf857x *gpio)
if (gpio->irq_domain)
irq_domain_remove(gpio->irq_domain);
- if (gpio->irq)
- free_irq(gpio->irq, gpio);
}
static int pcf857x_irq_domain_init(struct pcf857x *gpio,
@@ -230,20 +255,21 @@ static int pcf857x_irq_domain_init(struct pcf857x *gpio,
gpio->irq_domain = irq_domain_add_linear(client->dev.of_node,
gpio->chip.ngpio,
&pcf857x_irq_domain_ops,
- NULL);
+ gpio);
if (!gpio->irq_domain)
goto fail;
/* enable real irq */
- status = request_irq(client->irq, pcf857x_irq_demux, 0,
- dev_name(&client->dev), gpio);
+ status = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, pcf857x_irq, IRQF_ONESHOT |
+ IRQF_TRIGGER_FALLING,
+ dev_name(&client->dev), gpio);
+
if (status)
goto fail;
/* enable gpio_to_irq() */
- INIT_WORK(&gpio->work, pcf857x_irq_demux_work);
gpio->chip.to_irq = pcf857x_to_irq;
- gpio->irq = client->irq;
return 0;
@@ -257,14 +283,18 @@ fail:
static int pcf857x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- struct pcf857x_platform_data *pdata;
+ struct pcf857x_platform_data *pdata = dev_get_platdata(&client->dev);
+ struct device_node *np = client->dev.of_node;
struct pcf857x *gpio;
+ unsigned int n_latch = 0;
int status;
- pdata = dev_get_platdata(&client->dev);
- if (!pdata) {
+ if (IS_ENABLED(CONFIG_OF) && np)
+ of_property_read_u32(np, "lines-initial-states", &n_latch);
+ else if (pdata)
+ n_latch = pdata->n_latch;
+ else
dev_dbg(&client->dev, "no platform data\n");
- }
/* Allocate, initialize, and register this gpio_chip. */
gpio = devm_kzalloc(&client->dev, sizeof(*gpio), GFP_KERNEL);
@@ -357,11 +387,11 @@ static int pcf857x_probe(struct i2c_client *client,
* may cause transient glitching since it can't know the last value
* written (some pins may need to be driven low).
*
- * Using pdata->n_latch avoids that trouble. When left initialized
- * to zero, our software copy of the "latch" then matches the chip's
- * all-ones reset state. Otherwise it flags pins to be driven low.
+ * Using n_latch avoids that trouble. When left initialized to zero,
+ * our software copy of the "latch" then matches the chip's all-ones
+ * reset state. Otherwise it flags pins to be driven low.
*/
- gpio->out = pdata ? ~pdata->n_latch : ~0;
+ gpio->out = ~n_latch;
gpio->status = gpio->out;
status = gpiochip_add(&gpio->chip);
@@ -423,6 +453,7 @@ static struct i2c_driver pcf857x_driver = {
.driver = {
.name = "pcf857x",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(pcf857x_of_table),
},
.probe = pcf857x_probe,
.remove = pcf857x_remove,
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
index e3745eb07570..6038966ab045 100644
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -293,10 +293,9 @@ static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p)
if (pdata) {
p->config = *pdata;
} else if (IS_ENABLED(CONFIG_OF) && np) {
- ret = of_parse_phandle_with_args(np, "gpio-ranges",
- "#gpio-range-cells", 0, &args);
- p->config.number_of_pins = ret == 0 && args.args_count == 3
- ? args.args[2]
+ ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0,
+ &args);
+ p->config.number_of_pins = ret == 0 ? args.args[2]
: RCAR_MAX_GPIO_PER_BANK;
p->config.gpio_base = -1;
}
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index 358a21c2d811..29b5d6777dc5 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -2082,34 +2082,14 @@ static __init int samsung_gpiolib_init(void)
int i, nr_chips;
int group = 0;
-#if defined(CONFIG_PINCTRL_EXYNOS) || defined(CONFIG_PINCTRL_EXYNOS5440)
/*
- * This gpio driver includes support for device tree support and there
- * are platforms using it. In order to maintain compatibility with those
- * platforms, and to allow non-dt Exynos4210 platforms to use this
- * gpiolib support, a check is added to find out if there is a active
- * pin-controller driver support available. If it is available, this
- * gpiolib support is ignored and the gpiolib support available in
- * pin-controller driver is used. This is a temporary check and will go
- * away when all of the Exynos4210 platforms have switched to using
- * device tree and the pin-ctrl driver.
- */
- struct device_node *pctrl_np;
- static const struct of_device_id exynos_pinctrl_ids[] = {
- { .compatible = "samsung,s3c2412-pinctrl", },
- { .compatible = "samsung,s3c2416-pinctrl", },
- { .compatible = "samsung,s3c2440-pinctrl", },
- { .compatible = "samsung,s3c2450-pinctrl", },
- { .compatible = "samsung,exynos4210-pinctrl", },
- { .compatible = "samsung,exynos4x12-pinctrl", },
- { .compatible = "samsung,exynos5250-pinctrl", },
- { .compatible = "samsung,exynos5440-pinctrl", },
- { }
- };
- for_each_matching_node(pctrl_np, exynos_pinctrl_ids)
- if (pctrl_np && of_device_is_available(pctrl_np))
- return -ENODEV;
-#endif
+ * Currently there are two drivers that can provide GPIO support for
+ * Samsung SoCs. For device tree enabled platforms, the new
+ * pinctrl-samsung driver is used, providing both GPIO and pin control
+ * interfaces. For legacy (non-DT) platforms this driver is used.
+ */
+ if (of_have_populated_dt())
+ return -ENODEV;
samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 5c1ef2b3ef18..f2beb728ed8f 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -73,15 +73,8 @@ static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
static irqreturn_t acpi_gpio_irq_handler_evt(int irq, void *data)
{
struct acpi_gpio_evt_pin *evt_pin = data;
- struct acpi_object_list args;
- union acpi_object arg;
- arg.type = ACPI_TYPE_INTEGER;
- arg.integer.value = evt_pin->pin;
- args.count = 1;
- args.pointer = &arg;
-
- acpi_evaluate_object(evt_pin->evt_handle, NULL, &args, NULL);
+ acpi_execute_simple_method(evt_pin->evt_handle, NULL, evt_pin->pin);
return IRQ_HANDLED;
}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 86ef3461ec06..54b5c02edc15 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -102,6 +102,39 @@ static int gpiod_export_link(struct device *dev, const char *name,
static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value);
static void gpiod_unexport(struct gpio_desc *desc);
+#ifdef CONFIG_DEBUG_FS
+#define gpiod_emerg(desc, fmt, ...) \
+ pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \
+ ##__VA_ARGS__)
+#define gpiod_crit(desc, fmt, ...) \
+ pr_crit("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \
+ ##__VA_ARGS__)
+#define gpiod_err(desc, fmt, ...) \
+ pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \
+ ##__VA_ARGS__)
+#define gpiod_warn(desc, fmt, ...) \
+ pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \
+ ##__VA_ARGS__)
+#define gpiod_info(desc, fmt, ...) \
+ pr_info("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \
+ ##__VA_ARGS__)
+#define gpiod_dbg(desc, fmt, ...) \
+ pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \
+ ##__VA_ARGS__)
+#else
+#define gpiod_emerg(desc, fmt, ...) \
+ pr_emerg("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+#define gpiod_crit(desc, fmt, ...) \
+ pr_crit("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+#define gpiod_err(desc, fmt, ...) \
+ pr_err("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+#define gpiod_warn(desc, fmt, ...) \
+ pr_warn("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+#define gpiod_info(desc, fmt, ...) \
+ pr_info("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+#define gpiod_dbg(desc, fmt, ...) \
+ pr_debug("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+#endif
static inline void desc_set_label(struct gpio_desc *d, const char *label)
{
@@ -408,7 +441,7 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
if (!value_sd) {
- value_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value");
+ value_sd = sysfs_get_dirent(dev->kobj.sd, "value");
if (!value_sd) {
ret = -ENODEV;
goto err_out;
@@ -1635,8 +1668,9 @@ static int gpiod_direction_input(struct gpio_desc *desc)
chip = desc->chip;
if (!chip->get || !chip->direction_input) {
- pr_warn("%s: missing get() or direction_input() operations\n",
- __func__);
+ gpiod_warn(desc,
+ "%s: missing get() or direction_input() operations\n",
+ __func__);
return -EIO;
}
@@ -1656,8 +1690,7 @@ static int gpiod_direction_input(struct gpio_desc *desc)
if (status) {
status = chip->request(chip, offset);
if (status < 0) {
- pr_debug("GPIO-%d: chip request fail, %d\n",
- desc_to_gpio(desc), status);
+ gpiod_dbg(desc, "chip request fail, %d\n", status);
/* and it's not available to anyone else ...
* gpio_request() is the fully clean solution.
*/
@@ -1675,8 +1708,7 @@ lose:
fail:
spin_unlock_irqrestore(&gpio_lock, flags);
if (status)
- pr_debug("%s: gpio-%d status %d\n", __func__,
- desc_to_gpio(desc), status);
+ gpiod_dbg(desc, "%s status %d\n", __func__, status);
return status;
}
@@ -1708,8 +1740,9 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)
chip = desc->chip;
if (!chip->set || !chip->direction_output) {
- pr_warn("%s: missing set() or direction_output() operations\n",
- __func__);
+ gpiod_warn(desc,
+ "%s: missing set() or direction_output() operations\n",
+ __func__);
return -EIO;
}
@@ -1729,8 +1762,7 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)
if (status) {
status = chip->request(chip, offset);
if (status < 0) {
- pr_debug("GPIO-%d: chip request fail, %d\n",
- desc_to_gpio(desc), status);
+ gpiod_dbg(desc, "chip request fail, %d\n", status);
/* and it's not available to anyone else ...
* gpio_request() is the fully clean solution.
*/
@@ -1748,8 +1780,7 @@ lose:
fail:
spin_unlock_irqrestore(&gpio_lock, flags);
if (status)
- pr_debug("%s: gpio-%d status %d\n", __func__,
- desc_to_gpio(desc), status);
+ gpiod_dbg(desc, "%s: gpio status %d\n", __func__, status);
return status;
}
@@ -1781,8 +1812,9 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
chip = desc->chip;
if (!chip->set || !chip->set_debounce) {
- pr_debug("%s: missing set() or set_debounce() operations\n",
- __func__);
+ gpiod_dbg(desc,
+ "%s: missing set() or set_debounce() operations\n",
+ __func__);
return -ENOTSUPP;
}
@@ -1804,8 +1836,7 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
fail:
spin_unlock_irqrestore(&gpio_lock, flags);
if (status)
- pr_debug("%s: gpio-%d status %d\n", __func__,
- desc_to_gpio(desc), status);
+ gpiod_dbg(desc, "%s: status %d\n", __func__, status);
return status;
}
@@ -1838,6 +1869,19 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce);
* that the GPIO was actually requested.
*/
+static int _gpiod_get_value(const struct gpio_desc *desc)
+{
+ struct gpio_chip *chip;
+ int value;
+ int offset;
+
+ chip = desc->chip;
+ offset = gpio_chip_hwgpio(desc);
+ value = chip->get ? chip->get(chip, offset) : 0;
+ trace_gpio_value(desc_to_gpio(desc), 1, value);
+ return value;
+}
+
/**
* __gpio_get_value() - return a gpio's value
* @gpio: gpio whose value will be returned
@@ -1849,19 +1893,11 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce);
*/
static int gpiod_get_value(const struct gpio_desc *desc)
{
- struct gpio_chip *chip;
- int value;
- int offset;
-
if (!desc)
return 0;
- chip = desc->chip;
- offset = gpio_chip_hwgpio(desc);
/* Should be using gpio_get_value_cansleep() */
- WARN_ON(chip->can_sleep);
- value = chip->get ? chip->get(chip, offset) : 0;
- trace_gpio_value(desc_to_gpio(desc), 1, value);
- return value;
+ WARN_ON(desc->chip->can_sleep);
+ return _gpiod_get_value(desc);
}
int __gpio_get_value(unsigned gpio)
@@ -1893,8 +1929,9 @@ static void _gpio_set_open_drain_value(struct gpio_desc *desc, int value)
}
trace_gpio_direction(desc_to_gpio(desc), value, err);
if (err < 0)
- pr_err("%s: Error in set_value for open drain gpio%d err %d\n",
- __func__, desc_to_gpio(desc), err);
+ gpiod_err(desc,
+ "%s: Error in set_value for open drain err %d\n",
+ __func__, err);
}
/*
@@ -1920,8 +1957,23 @@ static void _gpio_set_open_source_value(struct gpio_desc *desc, int value)
}
trace_gpio_direction(desc_to_gpio(desc), !value, err);
if (err < 0)
- pr_err("%s: Error in set_value for open source gpio%d err %d\n",
- __func__, desc_to_gpio(desc), err);
+ gpiod_err(desc,
+ "%s: Error in set_value for open source err %d\n",
+ __func__, err);
+}
+
+static void _gpiod_set_value(struct gpio_desc *desc, int value)
+{
+ struct gpio_chip *chip;
+
+ chip = desc->chip;
+ trace_gpio_value(desc_to_gpio(desc), 0, value);
+ if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
+ _gpio_set_open_drain_value(desc, value);
+ else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags))
+ _gpio_set_open_source_value(desc, value);
+ else
+ chip->set(chip, gpio_chip_hwgpio(desc), value);
}
/**
@@ -1935,20 +1987,12 @@ static void _gpio_set_open_source_value(struct gpio_desc *desc, int value)
*/
static void gpiod_set_value(struct gpio_desc *desc, int value)
{
- struct gpio_chip *chip;
if (!desc)
return;
- chip = desc->chip;
/* Should be using gpio_set_value_cansleep() */
- WARN_ON(chip->can_sleep);
- trace_gpio_value(desc_to_gpio(desc), 0, value);
- if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
- _gpio_set_open_drain_value(desc, value);
- else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags))
- _gpio_set_open_source_value(desc, value);
- else
- chip->set(chip, gpio_chip_hwgpio(desc), value);
+ WARN_ON(desc->chip->can_sleep);
+ _gpiod_set_value(desc, value);
}
void __gpio_set_value(unsigned gpio, int value)
@@ -2013,18 +2057,10 @@ EXPORT_SYMBOL_GPL(__gpio_to_irq);
static int gpiod_get_value_cansleep(const struct gpio_desc *desc)
{
- struct gpio_chip *chip;
- int value;
- int offset;
-
might_sleep_if(extra_checks);
if (!desc)
return 0;
- chip = desc->chip;
- offset = gpio_chip_hwgpio(desc);
- value = chip->get ? chip->get(chip, offset) : 0;
- trace_gpio_value(desc_to_gpio(desc), 1, value);
- return value;
+ return _gpiod_get_value(desc);
}
int gpio_get_value_cansleep(unsigned gpio)
@@ -2035,19 +2071,10 @@ EXPORT_SYMBOL_GPL(gpio_get_value_cansleep);
static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
{
- struct gpio_chip *chip;
-
might_sleep_if(extra_checks);
if (!desc)
return;
- chip = desc->chip;
- trace_gpio_value(desc_to_gpio(desc), 0, value);
- if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
- _gpio_set_open_drain_value(desc, value);
- else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags))
- _gpio_set_open_source_value(desc, value);
- else
- chip->set(chip, gpio_chip_hwgpio(desc), value);
+ _gpiod_set_value(desc, value);
}
void gpio_set_value_cansleep(unsigned gpio, int value)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index bff2fa941f60..807309f80b0b 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -202,6 +202,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
{ DRM_MODE_CONNECTOR_TV, "TV" },
{ DRM_MODE_CONNECTOR_eDP, "eDP" },
{ DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
+ { DRM_MODE_CONNECTOR_DSI, "DSI" },
};
static const struct drm_prop_enum_list drm_encoder_enum_list[] =
@@ -211,6 +212,7 @@ static const struct drm_prop_enum_list drm_encoder_enum_list[] =
{ DRM_MODE_ENCODER_LVDS, "LVDS" },
{ DRM_MODE_ENCODER_TVDAC, "TV" },
{ DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
+ { DRM_MODE_ENCODER_DSI, "DSI" },
};
void drm_connector_ida_init(void)
@@ -1317,6 +1319,10 @@ static int drm_crtc_convert_umode(struct drm_display_mode *out,
if (in->clock > INT_MAX || in->vrefresh > INT_MAX)
return -ERANGE;
+ /* At most, 1 set bit describing the 3D layout of the mode */
+ if (hweight32(in->flags & DRM_MODE_FLAG_3D_MASK) > 1)
+ return -EINVAL;
+
out->clock = in->clock;
out->hdisplay = in->hdisplay;
out->hsync_start = in->hsync_start;
@@ -1579,6 +1585,19 @@ out:
return ret;
}
+static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
+ const struct drm_file *file_priv)
+{
+ /*
+ * If user-space hasn't configured the driver to expose the stereo 3D
+ * modes, don't expose them.
+ */
+ if (!file_priv->stereo_allowed && drm_mode_is_stereo(mode))
+ return false;
+
+ return true;
+}
+
/**
* drm_mode_getconnector - get connector configuration
* @dev: drm device for the ioctl
@@ -1644,7 +1663,8 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
/* delayed so we get modes regardless of pre-fill_modes state */
list_for_each_entry(mode, &connector->modes, head)
- mode_count++;
+ if (drm_mode_expose_to_userspace(mode, file_priv))
+ mode_count++;
out_resp->connector_id = connector->base.id;
out_resp->connector_type = connector->connector_type;
@@ -1666,6 +1686,9 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
copied = 0;
mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr;
list_for_each_entry(mode, &connector->modes, head) {
+ if (!drm_mode_expose_to_userspace(mode, file_priv))
+ continue;
+
drm_crtc_convert_to_umode(&u_mode, mode);
if (copy_to_user(mode_ptr + copied,
&u_mode, sizeof(u_mode))) {
@@ -2040,6 +2063,45 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
}
EXPORT_SYMBOL(drm_mode_set_config_internal);
+/*
+ * Checks that the framebuffer is big enough for the CRTC viewport
+ * (x, y, hdisplay, vdisplay)
+ */
+static int drm_crtc_check_viewport(const struct drm_crtc *crtc,
+ int x, int y,
+ const struct drm_display_mode *mode,
+ const struct drm_framebuffer *fb)
+
+{
+ int hdisplay, vdisplay;
+
+ hdisplay = mode->hdisplay;
+ vdisplay = mode->vdisplay;
+
+ if (drm_mode_is_stereo(mode)) {
+ struct drm_display_mode adjusted = *mode;
+
+ drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE);
+ hdisplay = adjusted.crtc_hdisplay;
+ vdisplay = adjusted.crtc_vdisplay;
+ }
+
+ if (crtc->invert_dimensions)
+ swap(hdisplay, vdisplay);
+
+ if (hdisplay > fb->width ||
+ vdisplay > fb->height ||
+ x > fb->width - hdisplay ||
+ y > fb->height - vdisplay) {
+ DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
+ fb->width, fb->height, hdisplay, vdisplay, x, y,
+ crtc->invert_dimensions ? " (inverted)" : "");
+ return -ENOSPC;
+ }
+
+ return 0;
+}
+
/**
* drm_mode_setcrtc - set CRTC configuration
* @dev: drm device for the ioctl
@@ -2087,7 +2149,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
if (crtc_req->mode_valid) {
- int hdisplay, vdisplay;
/* If we have a mode we need a framebuffer. */
/* If we pass -1, set the mode with the currently bound fb */
if (crtc_req->fb_id == -1) {
@@ -2123,23 +2184,11 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
- hdisplay = mode->hdisplay;
- vdisplay = mode->vdisplay;
-
- if (crtc->invert_dimensions)
- swap(hdisplay, vdisplay);
-
- if (hdisplay > fb->width ||
- vdisplay > fb->height ||
- crtc_req->x > fb->width - hdisplay ||
- crtc_req->y > fb->height - vdisplay) {
- DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
- fb->width, fb->height,
- hdisplay, vdisplay, crtc_req->x, crtc_req->y,
- crtc->invert_dimensions ? " (inverted)" : "");
- ret = -ENOSPC;
+ ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
+ mode, fb);
+ if (ret)
goto out;
- }
+
}
if (crtc_req->count_connectors == 0 && mode) {
@@ -3556,7 +3605,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
struct drm_framebuffer *fb = NULL, *old_fb = NULL;
struct drm_pending_vblank_event *e = NULL;
unsigned long flags;
- int hdisplay, vdisplay;
int ret = -EINVAL;
if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
@@ -3588,22 +3636,9 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
if (!fb)
goto out;
- hdisplay = crtc->mode.hdisplay;
- vdisplay = crtc->mode.vdisplay;
-
- if (crtc->invert_dimensions)
- swap(hdisplay, vdisplay);
-
- if (hdisplay > fb->width ||
- vdisplay > fb->height ||
- crtc->x > fb->width - hdisplay ||
- crtc->y > fb->height - vdisplay) {
- DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
- fb->width, fb->height, hdisplay, vdisplay, crtc->x, crtc->y,
- crtc->invert_dimensions ? " (inverted)" : "");
- ret = -ENOSPC;
+ ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y, &crtc->mode, fb);
+ if (ret)
goto out;
- }
if (crtc->fb->pixel_format != fb->pixel_format) {
DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index c722c3b5404d..4280e37f34c5 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -76,7 +76,8 @@ static void drm_mode_validate_flag(struct drm_connector *connector,
{
struct drm_display_mode *mode;
- if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE))
+ if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE |
+ DRM_MODE_FLAG_3D_MASK))
return;
list_for_each_entry(mode, &connector->modes, head) {
@@ -86,6 +87,9 @@ static void drm_mode_validate_flag(struct drm_connector *connector,
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;
@@ -175,6 +179,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
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) {
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index e572dd20bdee..e79d8d9ca203 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -69,6 +69,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 1688ff500513..c24af1d6cb47 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2404,7 +2404,7 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) ||
KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) &&
- drm_mode_equal_no_clocks(to_match, cea_mode))
+ drm_mode_equal_no_clocks_no_stereo(to_match, cea_mode))
return mode + 1;
}
return 0;
@@ -2453,7 +2453,7 @@ static u8 drm_match_hdmi_mode(const struct drm_display_mode *to_match)
if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) ||
KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) &&
- drm_mode_equal_no_clocks(to_match, hdmi_mode))
+ drm_mode_equal_no_clocks_no_stereo(to_match, hdmi_mode))
return mode + 1;
}
return 0;
@@ -2507,6 +2507,9 @@ add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid)
if (!newmode)
continue;
+ /* Carry over the stereo flags */
+ newmode->flags |= mode->flags & DRM_MODE_FLAG_3D_MASK;
+
/*
* The current mode could be either variant. Make
* sure to pick the "other" clock for the new mode.
@@ -2553,18 +2556,119 @@ do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
return modes;
}
+struct stereo_mandatory_mode {
+ int width, height, vrefresh;
+ unsigned int flags;
+};
+
+static const struct stereo_mandatory_mode stereo_mandatory_modes[] = {
+ { 1920, 1080, 24,
+ DRM_MODE_FLAG_3D_TOP_AND_BOTTOM | DRM_MODE_FLAG_3D_FRAME_PACKING },
+ { 1920, 1080, 50,
+ DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF },
+ { 1920, 1080, 60,
+ DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF },
+ { 1280, 720, 50,
+ DRM_MODE_FLAG_3D_TOP_AND_BOTTOM | DRM_MODE_FLAG_3D_FRAME_PACKING },
+ { 1280, 720, 60,
+ DRM_MODE_FLAG_3D_TOP_AND_BOTTOM | DRM_MODE_FLAG_3D_FRAME_PACKING }
+};
+
+static bool
+stereo_match_mandatory(const struct drm_display_mode *mode,
+ const struct stereo_mandatory_mode *stereo_mode)
+{
+ unsigned int interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
+
+ return mode->hdisplay == stereo_mode->width &&
+ mode->vdisplay == stereo_mode->height &&
+ interlaced == (stereo_mode->flags & DRM_MODE_FLAG_INTERLACE) &&
+ drm_mode_vrefresh(mode) == stereo_mode->vrefresh;
+}
+
+static const struct stereo_mandatory_mode *
+hdmi_find_stereo_mandatory_mode(const struct drm_display_mode *mode)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(stereo_mandatory_modes); i++)
+ if (stereo_match_mandatory(mode, &stereo_mandatory_modes[i]))
+ return &stereo_mandatory_modes[i];
+
+ return NULL;
+}
+
+static int add_hdmi_mandatory_stereo_modes(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ const struct drm_display_mode *mode;
+ struct list_head stereo_modes;
+ int modes = 0;
+
+ INIT_LIST_HEAD(&stereo_modes);
+
+ list_for_each_entry(mode, &connector->probed_modes, head) {
+ const struct stereo_mandatory_mode *mandatory;
+ u32 stereo_layouts, layout;
+
+ mandatory = hdmi_find_stereo_mandatory_mode(mode);
+ if (!mandatory)
+ continue;
+
+ stereo_layouts = mandatory->flags & DRM_MODE_FLAG_3D_MASK;
+ do {
+ struct drm_display_mode *new_mode;
+
+ layout = 1 << (ffs(stereo_layouts) - 1);
+ stereo_layouts &= ~layout;
+
+ new_mode = drm_mode_duplicate(dev, mode);
+ if (!new_mode)
+ continue;
+
+ new_mode->flags |= layout;
+ list_add_tail(&new_mode->head, &stereo_modes);
+ modes++;
+ } while (stereo_layouts);
+ }
+
+ list_splice_tail(&stereo_modes, &connector->probed_modes);
+
+ return modes;
+}
+
+static int add_hdmi_mode(struct drm_connector *connector, u8 vic)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_display_mode *newmode;
+
+ vic--; /* VICs start at 1 */
+ if (vic >= ARRAY_SIZE(edid_4k_modes)) {
+ DRM_ERROR("Unknown HDMI VIC: %d\n", vic);
+ return 0;
+ }
+
+ newmode = drm_mode_duplicate(dev, &edid_4k_modes[vic]);
+ if (!newmode)
+ return 0;
+
+ drm_mode_probed_add(connector, newmode);
+
+ return 1;
+}
+
/*
* do_hdmi_vsdb_modes - Parse the HDMI Vendor Specific data block
* @connector: connector corresponding to the HDMI sink
* @db: start of the CEA vendor specific block
* @len: length of the CEA block payload, ie. one can access up to db[len]
*
- * Parses the HDMI VSDB looking for modes to add to @connector.
+ * Parses the HDMI VSDB looking for modes to add to @connector. This function
+ * also adds the stereo 3d modes when applicable.
*/
static int
do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len)
{
- struct drm_device *dev = connector->dev;
int modes = 0, offset = 0, i;
u8 vic_len;
@@ -2585,30 +2689,22 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len)
/* the declared length is not long enough for the 2 first bytes
* of additional video format capabilities */
- offset += 2;
- if (len < (8 + offset))
+ if (len < (8 + offset + 2))
goto out;
+ /* 3D_Present */
+ offset++;
+ if (db[8 + offset] & (1 << 7))
+ modes += add_hdmi_mandatory_stereo_modes(connector);
+
+ offset++;
vic_len = db[8 + offset] >> 5;
for (i = 0; i < vic_len && len >= (9 + offset + i); i++) {
- struct drm_display_mode *newmode;
u8 vic;
vic = db[9 + offset + i];
-
- vic--; /* VICs start at 1 */
- if (vic >= ARRAY_SIZE(edid_4k_modes)) {
- DRM_ERROR("Unknown HDMI VIC: %d\n", vic);
- continue;
- }
-
- newmode = drm_mode_duplicate(dev, &edid_4k_modes[vic]);
- if (!newmode)
- continue;
-
- drm_mode_probed_add(connector, newmode);
- modes++;
+ modes += add_hdmi_mode(connector, vic);
}
out:
@@ -2668,8 +2764,8 @@ static int
add_cea_modes(struct drm_connector *connector, struct edid *edid)
{
const u8 *cea = drm_find_cea_extension(edid);
- const u8 *db;
- u8 dbl;
+ const u8 *db, *hdmi = NULL;
+ u8 dbl, hdmi_len;
int modes = 0;
if (cea && cea_revision(cea) >= 3) {
@@ -2684,11 +2780,20 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid)
if (cea_db_tag(db) == VIDEO_BLOCK)
modes += do_cea_modes(connector, db + 1, dbl);
- else if (cea_db_is_hdmi_vsdb(db))
- modes += do_hdmi_vsdb_modes(connector, db, dbl);
+ else if (cea_db_is_hdmi_vsdb(db)) {
+ hdmi = db;
+ hdmi_len = dbl;
+ }
}
}
+ /*
+ * We parse the HDMI VSDB after having added the cea modes as we will
+ * be patching their flags when the sink supports stereo 3D.
+ */
+ if (hdmi)
+ modes += do_hdmi_vsdb_modes(connector, hdmi, hdmi_len);
+
return modes;
}
@@ -3319,6 +3424,33 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
}
EXPORT_SYMBOL(drm_hdmi_avi_infoframe_from_display_mode);
+static enum hdmi_3d_structure
+s3d_structure_from_display_mode(const struct drm_display_mode *mode)
+{
+ u32 layout = mode->flags & DRM_MODE_FLAG_3D_MASK;
+
+ switch (layout) {
+ case DRM_MODE_FLAG_3D_FRAME_PACKING:
+ return HDMI_3D_STRUCTURE_FRAME_PACKING;
+ case DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE:
+ return HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE;
+ case DRM_MODE_FLAG_3D_LINE_ALTERNATIVE:
+ return HDMI_3D_STRUCTURE_LINE_ALTERNATIVE;
+ case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL:
+ return HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL;
+ case DRM_MODE_FLAG_3D_L_DEPTH:
+ return HDMI_3D_STRUCTURE_L_DEPTH;
+ case DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH:
+ return HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH;
+ case DRM_MODE_FLAG_3D_TOP_AND_BOTTOM:
+ return HDMI_3D_STRUCTURE_TOP_AND_BOTTOM;
+ case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF:
+ return HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF;
+ default:
+ return HDMI_3D_STRUCTURE_INVALID;
+ }
+}
+
/**
* drm_hdmi_vendor_infoframe_from_display_mode() - fill an HDMI infoframe with
* data from a DRM display mode
@@ -3336,20 +3468,29 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
const struct drm_display_mode *mode)
{
int err;
+ u32 s3d_flags;
u8 vic;
if (!frame || !mode)
return -EINVAL;
vic = drm_match_hdmi_mode(mode);
- if (!vic)
+ s3d_flags = mode->flags & DRM_MODE_FLAG_3D_MASK;
+
+ if (!vic && !s3d_flags)
+ return -EINVAL;
+
+ if (vic && s3d_flags)
return -EINVAL;
err = hdmi_vendor_infoframe_init(frame);
if (err < 0)
return err;
- frame->vic = vic;
+ if (vic)
+ frame->vic = vic;
+ else
+ frame->s3d_struct = s3d_structure_from_display_mode(mode);
return 0;
}
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 07247e2855a2..dffc836144cc 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -303,6 +303,27 @@ int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
}
/**
+ * Set device/driver capabilities
+ */
+int
+drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+ struct drm_set_client_cap *req = data;
+
+ switch (req->capability) {
+ case DRM_CLIENT_CAP_STEREO_3D:
+ if (req->value > 1)
+ return -EINVAL;
+ file_priv->stereo_allowed = req->value;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
* Setversion ioctl.
*
* \param inode device inode.
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index fc2adb62b757..b0733153dfd2 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -707,18 +707,25 @@ EXPORT_SYMBOL(drm_mode_vrefresh);
/**
* drm_mode_set_crtcinfo - set CRTC modesetting parameters
* @p: mode
- * @adjust_flags: unused? (FIXME)
+ * @adjust_flags: a combination of adjustment flags
*
* LOCKING:
* None.
*
* Setup the CRTC modesetting parameters for @p, adjusting if necessary.
+ *
+ * - The CRTC_INTERLACE_HALVE_V flag can be used to halve vertical timings of
+ * interlaced modes.
+ * - The CRTC_STEREO_DOUBLE flag can be used to compute the timings for
+ * buffers containing two eyes (only adjust the timings when needed, eg. for
+ * "frame packing" or "side by side full").
*/
void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
{
if ((p == NULL) || ((p->type & DRM_MODE_TYPE_CRTC_C) == DRM_MODE_TYPE_BUILTIN))
return;
+ p->crtc_clock = p->clock;
p->crtc_hdisplay = p->hdisplay;
p->crtc_hsync_start = p->hsync_start;
p->crtc_hsync_end = p->hsync_end;
@@ -752,6 +759,20 @@ void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
p->crtc_vtotal *= p->vscan;
}
+ if (adjust_flags & CRTC_STEREO_DOUBLE) {
+ unsigned int layout = p->flags & DRM_MODE_FLAG_3D_MASK;
+
+ switch (layout) {
+ case DRM_MODE_FLAG_3D_FRAME_PACKING:
+ p->crtc_clock *= 2;
+ p->crtc_vdisplay += p->crtc_vtotal;
+ p->crtc_vsync_start += p->crtc_vtotal;
+ p->crtc_vsync_end += p->crtc_vtotal;
+ p->crtc_vtotal += p->crtc_vtotal;
+ break;
+ }
+ }
+
p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay);
p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal);
p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay);
@@ -830,12 +851,16 @@ bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_displ
} else if (mode1->clock != mode2->clock)
return false;
- return drm_mode_equal_no_clocks(mode1, mode2);
+ if ((mode1->flags & DRM_MODE_FLAG_3D_MASK) !=
+ (mode2->flags & DRM_MODE_FLAG_3D_MASK))
+ return false;
+
+ return drm_mode_equal_no_clocks_no_stereo(mode1, mode2);
}
EXPORT_SYMBOL(drm_mode_equal);
/**
- * drm_mode_equal_no_clocks - test modes for equality
+ * drm_mode_equal_no_clocks_no_stereo - test modes for equality
* @mode1: first mode
* @mode2: second mode
*
@@ -843,12 +868,13 @@ EXPORT_SYMBOL(drm_mode_equal);
* None.
*
* Check to see if @mode1 and @mode2 are equivalent, but
- * don't check the pixel clocks.
+ * don't check the pixel clocks nor the stereo layout.
*
* RETURNS:
* True if the modes are equal, false otherwise.
*/
-bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2)
+bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
+ const struct drm_display_mode *mode2)
{
if (mode1->hdisplay == mode2->hdisplay &&
mode1->hsync_start == mode2->hsync_start &&
@@ -860,12 +886,13 @@ bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1, const struct
mode1->vsync_end == mode2->vsync_end &&
mode1->vtotal == mode2->vtotal &&
mode1->vscan == mode2->vscan &&
- mode1->flags == mode2->flags)
+ (mode1->flags & ~DRM_MODE_FLAG_3D_MASK) ==
+ (mode2->flags & ~DRM_MODE_FLAG_3D_MASK))
return true;
return false;
}
-EXPORT_SYMBOL(drm_mode_equal_no_clocks);
+EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo);
/**
* drm_mode_validate_size - make sure modes adhere to size constraints
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index b8449a84a0dc..65e60d26891b 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -21,6 +21,9 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
intel_display.o \
intel_crt.o \
intel_lvds.o \
+ intel_dsi.o \
+ intel_dsi_cmd.o \
+ intel_dsi_pll.o \
intel_bios.o \
intel_ddi.o \
intel_dp.o \
diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h
index 33a62ad80100..312163379db9 100644
--- a/drivers/gpu/drm/i915/dvo.h
+++ b/drivers/gpu/drm/i915/dvo.h
@@ -77,17 +77,6 @@ struct intel_dvo_dev_ops {
struct drm_display_mode *mode);
/*
- * Callback to adjust the mode to be set in the CRTC.
- *
- * This allows an output to adjust the clock or even the entire set of
- * timings, which is used for panels with fixed timings or for
- * buses with clock limitations.
- */
- bool (*mode_fixup)(struct intel_dvo_device *dvo,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
-
- /*
* Callback for preparing mode changes on an output
*/
void (*prepare)(struct intel_dvo_device *dvo);
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index a6f4cb5af185..fcfa98844ccc 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -145,6 +145,13 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
seq_printf(m, " (%s)", obj->ring->name);
}
+static void describe_ctx(struct seq_file *m, struct i915_hw_context *ctx)
+{
+ seq_putc(m, ctx->is_initialized ? 'I' : 'i');
+ seq_putc(m, ctx->remap_slice ? 'R' : 'r');
+ seq_putc(m, ' ');
+}
+
static int i915_gem_object_list_info(struct seq_file *m, void *data)
{
struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -1442,6 +1449,7 @@ static int i915_context_status(struct seq_file *m, void *unused)
struct drm_device *dev = node->minor->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_ring_buffer *ring;
+ struct i915_hw_context *ctx;
int ret, i;
ret = mutex_lock_interruptible(&dev->mode_config.mutex);
@@ -1460,12 +1468,15 @@ static int i915_context_status(struct seq_file *m, void *unused)
seq_putc(m, '\n');
}
- for_each_ring(ring, dev_priv, i) {
- if (ring->default_context) {
- seq_printf(m, "HW default context %s ring ", ring->name);
- describe_obj(m, ring->default_context->obj);
- seq_putc(m, '\n');
- }
+ list_for_each_entry(ctx, &dev_priv->context_list, link) {
+ seq_puts(m, "HW context ");
+ describe_ctx(m, ctx);
+ for_each_ring(ring, dev_priv, i)
+ if (ring->default_context == ctx)
+ seq_printf(m, "(default context %s) ", ring->name);
+
+ describe_obj(m, ctx->obj);
+ seq_putc(m, '\n');
}
mutex_unlock(&dev->mode_config.mutex);
@@ -1610,27 +1621,27 @@ static int i915_dpio_info(struct seq_file *m, void *data)
seq_printf(m, "DPIO_CTL: 0x%08x\n", I915_READ(DPIO_CTL));
seq_printf(m, "DPIO_DIV_A: 0x%08x\n",
- vlv_dpio_read(dev_priv, _DPIO_DIV_A));
+ vlv_dpio_read(dev_priv, PIPE_A, _DPIO_DIV_A));
seq_printf(m, "DPIO_DIV_B: 0x%08x\n",
- vlv_dpio_read(dev_priv, _DPIO_DIV_B));
+ vlv_dpio_read(dev_priv, PIPE_A, _DPIO_DIV_B));
seq_printf(m, "DPIO_REFSFR_A: 0x%08x\n",
- vlv_dpio_read(dev_priv, _DPIO_REFSFR_A));
+ vlv_dpio_read(dev_priv, PIPE_A, _DPIO_REFSFR_A));
seq_printf(m, "DPIO_REFSFR_B: 0x%08x\n",
- vlv_dpio_read(dev_priv, _DPIO_REFSFR_B));
+ vlv_dpio_read(dev_priv, PIPE_A, _DPIO_REFSFR_B));
seq_printf(m, "DPIO_CORE_CLK_A: 0x%08x\n",
- vlv_dpio_read(dev_priv, _DPIO_CORE_CLK_A));
+ vlv_dpio_read(dev_priv, PIPE_A, _DPIO_CORE_CLK_A));
seq_printf(m, "DPIO_CORE_CLK_B: 0x%08x\n",
- vlv_dpio_read(dev_priv, _DPIO_CORE_CLK_B));
+ vlv_dpio_read(dev_priv, PIPE_A, _DPIO_CORE_CLK_B));
seq_printf(m, "DPIO_LPF_COEFF_A: 0x%08x\n",
- vlv_dpio_read(dev_priv, _DPIO_LPF_COEFF_A));
+ vlv_dpio_read(dev_priv, PIPE_A, _DPIO_LPF_COEFF_A));
seq_printf(m, "DPIO_LPF_COEFF_B: 0x%08x\n",
- vlv_dpio_read(dev_priv, _DPIO_LPF_COEFF_B));
+ vlv_dpio_read(dev_priv, PIPE_A, _DPIO_LPF_COEFF_B));
seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n",
- vlv_dpio_read(dev_priv, DPIO_FASTCLK_DISABLE));
+ vlv_dpio_read(dev_priv, PIPE_A, DPIO_FASTCLK_DISABLE));
mutex_unlock(&dev_priv->dpio_lock);
@@ -1657,9 +1668,10 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
struct drm_i915_private *dev_priv = dev->dev_private;
u32 psrstat, psrperf;
- if (!IS_HASWELL(dev)) {
+ if (!HAS_PSR(dev)) {
seq_puts(m, "PSR not supported on this platform\n");
- } else if (IS_HASWELL(dev) && I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE) {
+ } else if (HAS_PSR(dev) &&
+ I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE) {
seq_puts(m, "PSR enabled\n");
} else {
seq_puts(m, "PSR disabled: ");
@@ -1701,7 +1713,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
return 0;
}
- psrstat = I915_READ(EDP_PSR_STATUS_CTL);
+ psrstat = I915_READ(EDP_PSR_STATUS_CTL(dev));
seq_puts(m, "PSR Current State: ");
switch (psrstat & EDP_PSR_STATUS_STATE_MASK) {
@@ -1773,7 +1785,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
seq_printf(m, "Idle Count: %u\n",
psrstat & EDP_PSR_STATUS_IDLE_MASK);
- psrperf = (I915_READ(EDP_PSR_PERF_CNT)) & EDP_PSR_PERF_CNT_MASK;
+ psrperf = (I915_READ(EDP_PSR_PERF_CNT(dev))) & EDP_PSR_PERF_CNT_MASK;
seq_printf(m, "Performance Counter: %u\n", psrperf);
return 0;
@@ -2145,7 +2157,7 @@ drm_add_fake_info_node(struct drm_minor *minor,
{
struct drm_info_node *node;
- node = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
+ node = kmalloc(sizeof(*node), GFP_KERNEL);
if (node == NULL) {
debugfs_remove(ent);
return -ENOMEM;
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index c27a21034a5e..d35de1b9a2dd 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -52,7 +52,7 @@
intel_ring_emit(LP_RING(dev_priv), x)
#define ADVANCE_LP_RING() \
- intel_ring_advance(LP_RING(dev_priv))
+ __intel_ring_advance(LP_RING(dev_priv))
/**
* Lock test for when it's just for synchronization of ring access.
@@ -641,7 +641,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
if (batch->num_cliprects) {
cliprects = kcalloc(batch->num_cliprects,
- sizeof(struct drm_clip_rect),
+ sizeof(*cliprects),
GFP_KERNEL);
if (cliprects == NULL)
return -ENOMEM;
@@ -703,7 +703,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
if (cmdbuf->num_cliprects) {
cliprects = kcalloc(cmdbuf->num_cliprects,
- sizeof(struct drm_clip_rect), GFP_KERNEL);
+ sizeof(*cliprects), GFP_KERNEL);
if (cliprects == NULL) {
ret = -ENOMEM;
goto fail_batch_free;
@@ -1314,13 +1314,18 @@ static int i915_load_modeset_init(struct drm_device *dev)
if (ret)
goto cleanup_gem_stolen;
+ intel_init_power_well(dev);
+
+ /* Keep VGA alive until i915_disable_vga_mem() */
+ intel_display_power_get(dev, POWER_DOMAIN_VGA);
+
/* Important: The output setup functions called by modeset_init need
* working irqs for e.g. gmbus and dp aux transfers. */
intel_modeset_init(dev);
ret = i915_gem_init(dev);
if (ret)
- goto cleanup_irq;
+ goto cleanup_power;
INIT_WORK(&dev_priv->console_resume_work, intel_console_resume);
@@ -1329,8 +1334,10 @@ static int i915_load_modeset_init(struct drm_device *dev)
/* Always safe in the mode setting case. */
/* FIXME: do pre/post-mode set stuff in core KMS code */
dev->vblank_disable_allowed = 1;
- if (INTEL_INFO(dev)->num_pipes == 0)
+ if (INTEL_INFO(dev)->num_pipes == 0) {
+ intel_display_power_put(dev, POWER_DOMAIN_VGA);
return 0;
+ }
ret = intel_fbdev_init(dev);
if (ret)
@@ -1356,6 +1363,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
* vgacon_save_screen() works during the handover.
*/
i915_disable_vga_mem(dev);
+ intel_display_power_put(dev, POWER_DOMAIN_VGA);
/* Only enable hotplug handling once the fbdev is fully set up. */
dev_priv->enable_hotplug_processing = true;
@@ -1371,7 +1379,8 @@ cleanup_gem:
mutex_unlock(&dev->struct_mutex);
i915_gem_cleanup_aliasing_ppgtt(dev);
drm_mm_takedown(&dev_priv->gtt.base.mm);
-cleanup_irq:
+cleanup_power:
+ intel_display_power_put(dev, POWER_DOMAIN_VGA);
drm_irq_uninstall(dev);
cleanup_gem_stolen:
i915_gem_cleanup_stolen(dev);
@@ -1478,7 +1487,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
dev->types[8] = _DRM_STAT_SECONDARY;
dev->types[9] = _DRM_STAT_DMA;
- dev_priv = kzalloc(sizeof(drm_i915_private_t), GFP_KERNEL);
+ dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
if (dev_priv == NULL)
return -ENOMEM;
@@ -1783,8 +1792,6 @@ int i915_driver_unload(struct drm_device *dev)
list_del(&dev_priv->gtt.base.global_link);
WARN_ON(!list_empty(&dev_priv->vm_list));
drm_mm_takedown(&dev_priv->gtt.base.mm);
- if (dev_priv->regs != NULL)
- pci_iounmap(dev->pdev, dev_priv->regs);
intel_teardown_gmbus(dev);
intel_teardown_mchbar(dev);
@@ -1794,6 +1801,10 @@ int i915_driver_unload(struct drm_device *dev)
dev_priv->gtt.base.cleanup(&dev_priv->gtt.base);
+ intel_uncore_fini(dev);
+ if (dev_priv->regs != NULL)
+ pci_iounmap(dev->pdev, dev_priv->regs);
+
if (dev_priv->slab)
kmem_cache_destroy(dev_priv->slab);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 69d8ed5416c3..8ebb0d12e912 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -576,11 +576,24 @@ static void intel_resume_hotplug(struct drm_device *dev)
drm_helper_hpd_irq_event(dev);
}
-static int __i915_drm_thaw(struct drm_device *dev)
+static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
{
struct drm_i915_private *dev_priv = dev->dev_private;
int error = 0;
+ intel_uncore_early_sanitize(dev);
+
+ intel_uncore_sanitize(dev);
+
+ if (drm_core_check_feature(dev, DRIVER_MODESET) &&
+ restore_gtt_mappings) {
+ mutex_lock(&dev->struct_mutex);
+ i915_gem_restore_gtt_mappings(dev);
+ mutex_unlock(&dev->struct_mutex);
+ }
+
+ intel_init_power_well(dev);
+
i915_restore_state(dev);
intel_opregion_setup(dev);
@@ -640,19 +653,7 @@ static int __i915_drm_thaw(struct drm_device *dev)
static int i915_drm_thaw(struct drm_device *dev)
{
- int error = 0;
-
- intel_uncore_sanitize(dev);
-
- if (drm_core_check_feature(dev, DRIVER_MODESET)) {
- mutex_lock(&dev->struct_mutex);
- i915_gem_restore_gtt_mappings(dev);
- mutex_unlock(&dev->struct_mutex);
- }
-
- __i915_drm_thaw(dev);
-
- return error;
+ return __i915_drm_thaw(dev, true);
}
int i915_resume(struct drm_device *dev)
@@ -668,20 +669,12 @@ int i915_resume(struct drm_device *dev)
pci_set_master(dev->pdev);
- intel_uncore_sanitize(dev);
-
/*
* Platforms with opregion should have sane BIOS, older ones (gen3 and
- * earlier) need this since the BIOS might clear all our scratch PTEs.
+ * earlier) need to restore the GTT mappings since the BIOS might clear
+ * all our scratch PTEs.
*/
- if (drm_core_check_feature(dev, DRIVER_MODESET) &&
- !dev_priv->opregion.header) {
- mutex_lock(&dev->struct_mutex);
- i915_gem_restore_gtt_mappings(dev);
- mutex_unlock(&dev->struct_mutex);
- }
-
- ret = __i915_drm_thaw(dev);
+ ret = __i915_drm_thaw(dev, !dev_priv->opregion.header);
if (ret)
return ret;
@@ -719,24 +712,19 @@ int i915_reset(struct drm_device *dev)
simulated = dev_priv->gpu_error.stop_rings != 0;
- if (!simulated && get_seconds() - dev_priv->gpu_error.last_reset < 5) {
- DRM_ERROR("GPU hanging too fast, declaring wedged!\n");
- ret = -ENODEV;
- } else {
- ret = intel_gpu_reset(dev);
-
- /* Also reset the gpu hangman. */
- if (simulated) {
- DRM_INFO("Simulated gpu hang, resetting stop_rings\n");
- dev_priv->gpu_error.stop_rings = 0;
- if (ret == -ENODEV) {
- DRM_ERROR("Reset not implemented, but ignoring "
- "error for simulated gpu hangs\n");
- ret = 0;
- }
- } else
- dev_priv->gpu_error.last_reset = get_seconds();
+ ret = intel_gpu_reset(dev);
+
+ /* Also reset the gpu hangman. */
+ if (simulated) {
+ DRM_INFO("Simulated gpu hang, resetting stop_rings\n");
+ dev_priv->gpu_error.stop_rings = 0;
+ if (ret == -ENODEV) {
+ DRM_ERROR("Reset not implemented, but ignoring "
+ "error for simulated gpu hangs\n");
+ ret = 0;
+ }
}
+
if (ret) {
DRM_ERROR("Failed to reset chip.\n");
mutex_unlock(&dev->struct_mutex);
@@ -799,6 +787,12 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct intel_device_info *intel_info =
(struct intel_device_info *) ent->driver_data;
+ if (IS_PRELIMINARY_HW(intel_info) && !i915_preliminary_hw_support) {
+ DRM_INFO("This hardware requires preliminary hardware support.\n"
+ "See CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT, and/or modparam preliminary_hw_support\n");
+ return -ENODEV;
+ }
+
/* Only bind to function 0 of the device. Early generations
* used function 1 as a placeholder for multi-head. This causes
* us confusion instead, especially on the systems where both
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 35874b3a86dc..e8ffd5731528 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -99,6 +99,7 @@ enum intel_display_power_domain {
POWER_DOMAIN_TRANSCODER_B,
POWER_DOMAIN_TRANSCODER_C,
POWER_DOMAIN_TRANSCODER_EDP = POWER_DOMAIN_TRANSCODER_A + 0xF,
+ POWER_DOMAIN_VGA,
};
#define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A)
@@ -225,6 +226,8 @@ struct intel_opregion {
struct opregion_header __iomem *header;
struct opregion_acpi __iomem *acpi;
struct opregion_swsci __iomem *swsci;
+ u32 swsci_gbda_sub_functions;
+ u32 swsci_sbcb_sub_functions;
struct opregion_asle __iomem *asle;
void __iomem *vbt;
u32 __iomem *lid_state;
@@ -321,11 +324,13 @@ struct drm_i915_error_state {
u32 dirty:1;
u32 purgeable:1;
s32 ring:4;
- u32 cache_level:2;
+ u32 cache_level:3;
} **active_bo, **pinned_bo;
u32 *active_bo_count, *pinned_bo_count;
struct intel_overlay_error_state *overlay;
struct intel_display_error_state *display;
+ int hangcheck_score[I915_NUM_RINGS];
+ enum intel_ring_hangcheck_action hangcheck_action[I915_NUM_RINGS];
};
struct intel_crtc_config;
@@ -357,7 +362,7 @@ struct drm_i915_display_funcs {
int target, int refclk,
struct dpll *match_clock,
struct dpll *best_clock);
- void (*update_wm)(struct drm_device *dev);
+ void (*update_wm)(struct drm_crtc *crtc);
void (*update_sprite_wm)(struct drm_plane *plane,
struct drm_crtc *crtc,
uint32_t sprite_width, int pixel_size,
@@ -367,7 +372,6 @@ struct drm_i915_display_funcs {
* fills out the pipe-config with the hw state. */
bool (*get_pipe_config)(struct intel_crtc *,
struct intel_crtc_config *);
- void (*get_clock)(struct intel_crtc *, struct intel_crtc_config *);
int (*crtc_mode_set)(struct drm_crtc *crtc,
int x, int y,
struct drm_framebuffer *old_fb);
@@ -404,6 +408,8 @@ struct intel_uncore {
unsigned fifo_count;
unsigned forcewake_count;
+
+ struct delayed_work force_wake_work;
};
#define DEV_INFO_FOR_EACH_FLAG(func, sep) \
@@ -420,6 +426,7 @@ struct intel_uncore {
func(is_ivybridge) sep \
func(is_valleyview) sep \
func(is_haswell) sep \
+ func(is_preliminary) sep \
func(has_force_wake) sep \
func(has_fbc) sep \
func(has_pipe_cxsr) sep \
@@ -460,6 +467,36 @@ enum i915_cache_level {
typedef uint32_t gen6_gtt_pte_t;
+/**
+ * A VMA represents a GEM BO that is bound into an address space. Therefore, a
+ * VMA's presence cannot be guaranteed before binding, or after unbinding the
+ * object into/from the address space.
+ *
+ * To make things as simple as possible (ie. no refcounting), a VMA's lifetime
+ * will always be <= an objects lifetime. So object refcounting should cover us.
+ */
+struct i915_vma {
+ struct drm_mm_node node;
+ struct drm_i915_gem_object *obj;
+ struct i915_address_space *vm;
+
+ /** This object's place on the active/inactive lists */
+ struct list_head mm_list;
+
+ struct list_head vma_link; /* Link in the object's VMA list */
+
+ /** This vma's place in the batchbuffer or on the eviction list */
+ struct list_head exec_list;
+
+ /**
+ * Used for performing relocations during execbuffer insertion.
+ */
+ struct hlist_node exec_node;
+ unsigned long exec_handle;
+ struct drm_i915_gem_exec_object2 *exec_entry;
+
+};
+
struct i915_address_space {
struct drm_mm mm;
struct drm_device *dev;
@@ -498,9 +535,18 @@ struct i915_address_space {
/* FIXME: Need a more generic return type */
gen6_gtt_pte_t (*pte_encode)(dma_addr_t addr,
enum i915_cache_level level);
+
+ /** Unmap an object from an address space. This usually consists of
+ * setting the valid PTE entries to a reserved scratch page. */
+ void (*unbind_vma)(struct i915_vma *vma);
void (*clear_range)(struct i915_address_space *vm,
unsigned int first_entry,
unsigned int num_entries);
+ /* Map an object into an address space with the given cache flags. */
+#define GLOBAL_BIND (1<<0)
+ void (*bind_vma)(struct i915_vma *vma,
+ enum i915_cache_level cache_level,
+ u32 flags);
void (*insert_entries)(struct i915_address_space *vm,
struct sg_table *st,
unsigned int first_entry,
@@ -547,35 +593,18 @@ struct i915_hw_ppgtt {
int (*enable)(struct drm_device *dev);
};
-/**
- * A VMA represents a GEM BO that is bound into an address space. Therefore, a
- * VMA's presence cannot be guaranteed before binding, or after unbinding the
- * object into/from the address space.
- *
- * To make things as simple as possible (ie. no refcounting), a VMA's lifetime
- * will always be <= an objects lifetime. So object refcounting should cover us.
- */
-struct i915_vma {
- struct drm_mm_node node;
- struct drm_i915_gem_object *obj;
- struct i915_address_space *vm;
-
- /** This object's place on the active/inactive lists */
- struct list_head mm_list;
-
- struct list_head vma_link; /* Link in the object's VMA list */
-
- /** This vma's place in the batchbuffer or on the eviction list */
- struct list_head exec_list;
-
-};
-
struct i915_ctx_hang_stats {
/* This context had batch pending when hang was declared */
unsigned batch_pending;
/* This context had batch active when hang was declared */
unsigned batch_active;
+
+ /* Time when this context was last blamed for a GPU reset */
+ unsigned long guilty_ts;
+
+ /* This context is banned to submit more work */
+ bool banned;
};
/* This must match up with the value previously used for execbuf2.rsvd1. */
@@ -584,10 +613,13 @@ struct i915_hw_context {
struct kref ref;
int id;
bool is_initialized;
+ uint8_t remap_slice;
struct drm_i915_file_private *file_priv;
struct intel_ring_buffer *ring;
struct drm_i915_gem_object *obj;
struct i915_ctx_hang_stats hang_stats;
+
+ struct list_head link;
};
struct i915_fbc {
@@ -900,9 +932,11 @@ struct i915_ums_state {
int mm_suspended;
};
+#define MAX_L3_SLICES 2
struct intel_l3_parity {
- u32 *remap_info;
+ u32 *remap_info[MAX_L3_SLICES];
struct work_struct error_work;
+ int which_slice;
};
struct i915_gem_mm {
@@ -977,6 +1011,9 @@ struct i915_gpu_error {
/* For hangcheck timer */
#define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
#define DRM_I915_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)
+ /* Hang gpu twice in this window and your context gets banned */
+#define DRM_I915_CTX_BAN_PERIOD DIV_ROUND_UP(8*DRM_I915_HANGCHECK_PERIOD, 1000)
+
struct timer_list hangcheck_timer;
/* For reset and error_state handling. */
@@ -985,8 +1022,6 @@ struct i915_gpu_error {
struct drm_i915_error_state *first_error;
struct work_struct work;
- unsigned long last_reset;
-
/**
* State variable and reset counter controlling the reset flow
*
@@ -1033,6 +1068,14 @@ enum modeset_restore {
MODESET_SUSPENDED,
};
+struct ddi_vbt_port_info {
+ uint8_t hdmi_level_shift;
+
+ uint8_t supports_dvi:1;
+ uint8_t supports_hdmi:1;
+ uint8_t supports_dp:1;
+};
+
struct intel_vbt_data {
struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
@@ -1058,10 +1101,17 @@ struct intel_vbt_data {
int edp_bpp;
struct edp_power_seq edp_pps;
+ /* MIPI DSI */
+ struct {
+ u16 panel_id;
+ } dsi;
+
int crt_ddc_pin;
int child_dev_num;
- struct child_device_config *child_dev;
+ union child_device_config *child_dev;
+
+ struct ddi_vbt_port_info ddi_port_info[I915_MAX_PORTS];
};
enum intel_ddb_partitioning {
@@ -1318,6 +1368,7 @@ typedef struct drm_i915_private {
bool hw_contexts_disabled;
uint32_t hw_context_size;
+ struct list_head context_list;
u32 fdi_rx_config;
@@ -1398,8 +1449,6 @@ struct drm_i915_gem_object {
struct list_head ring_list;
/** Used in execbuf to temporarily hold a ref */
struct list_head obj_exec_link;
- /** This object's place in the batchbuffer or on the eviction list */
- struct list_head exec_list;
/**
* This is set if the object is on the active lists (has pending
@@ -1485,13 +1534,6 @@ struct drm_i915_gem_object {
void *dma_buf_vmapping;
int vmapping_count;
- /**
- * Used for performing relocations during execbuffer insertion.
- */
- struct hlist_node exec_node;
- unsigned long exec_handle;
- struct drm_i915_gem_exec_object2 *exec_entry;
-
struct intel_ring_buffer *ring;
/** Breadcrumb of last rendering to the buffer. */
@@ -1600,6 +1642,9 @@ struct drm_i915_file_private {
((dev)->pci_device & 0xFF00) == 0x0C00)
#define IS_ULT(dev) (IS_HASWELL(dev) && \
((dev)->pci_device & 0xFF00) == 0x0A00)
+#define IS_HSW_GT3(dev) (IS_HASWELL(dev) && \
+ ((dev)->pci_device & 0x00F0) == 0x0020)
+#define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary)
/*
* The genX designation typically refers to the render engine, so render
@@ -1638,7 +1683,6 @@ struct drm_i915_file_private {
#define SUPPORTS_DIGITAL_OUTPUTS(dev) (!IS_GEN2(dev) && !IS_PINEVIEW(dev))
#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_GEN5(dev))
#define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_GEN5(dev))
-#define SUPPORTS_EDP(dev) (IS_IRONLAKE_M(dev))
#define SUPPORTS_TV(dev) (INTEL_INFO(dev)->supports_tv)
#define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug)
@@ -1651,6 +1695,7 @@ struct drm_i915_file_private {
#define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi)
#define HAS_POWER_WELL(dev) (IS_HASWELL(dev))
#define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg)
+#define HAS_PSR(dev) (IS_HASWELL(dev))
#define INTEL_PCH_DEVICE_ID_MASK 0xff00
#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00
@@ -1668,7 +1713,9 @@ struct drm_i915_file_private {
#define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake)
-#define HAS_L3_GPU_CACHE(dev) (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
+/* DPF == dynamic parity feature */
+#define HAS_L3_DPF(dev) (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
+#define NUM_L3_SLICES(dev) (IS_HSW_GT3(dev) ? 2 : HAS_L3_DPF(dev))
#define GT_FREQUENCY_MULTIPLIER 50
@@ -1765,6 +1812,7 @@ extern void intel_uncore_early_sanitize(struct drm_device *dev);
extern void intel_uncore_init(struct drm_device *dev);
extern void intel_uncore_clear_errors(struct drm_device *dev);
extern void intel_uncore_check_errors(struct drm_device *dev);
+extern void intel_uncore_fini(struct drm_device *dev);
void
i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
@@ -1828,8 +1876,6 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
size_t size);
void i915_gem_free_object(struct drm_gem_object *obj);
-struct i915_vma *i915_gem_vma_create(struct drm_i915_gem_object *obj,
- struct i915_address_space *vm);
void i915_gem_vma_destroy(struct i915_vma *vma);
int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj,
@@ -1868,9 +1914,8 @@ static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj)
int __must_check i915_mutex_lock_interruptible(struct drm_device *dev);
int i915_gem_object_sync(struct drm_i915_gem_object *obj,
struct intel_ring_buffer *to);
-void i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
- struct intel_ring_buffer *ring);
-
+void i915_vma_move_to_active(struct i915_vma *vma,
+ struct intel_ring_buffer *ring);
int i915_gem_dumb_create(struct drm_file *file_priv,
struct drm_device *dev,
struct drm_mode_create_dumb *args);
@@ -1931,7 +1976,7 @@ bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force);
int __must_check i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj);
int __must_check i915_gem_init(struct drm_device *dev);
int __must_check i915_gem_init_hw(struct drm_device *dev);
-void i915_gem_l3_remap(struct drm_device *dev);
+int i915_gem_l3_remap(struct intel_ring_buffer *ring, int slice);
void i915_gem_init_swizzling(struct drm_device *dev);
void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
int __must_check i915_gpu_idle(struct drm_device *dev);
@@ -1993,6 +2038,9 @@ struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
struct i915_vma *
i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj,
struct i915_address_space *vm);
+
+struct i915_vma *i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj);
+
/* Some GGTT VM helpers */
#define obj_to_ggtt(obj) \
(&((struct drm_i915_private *)(obj)->base.dev->dev_private)->gtt.base)
@@ -2029,7 +2077,6 @@ i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj,
return i915_gem_object_pin(obj, obj_to_ggtt(obj), alignment,
map_and_fenceable, nonblocking);
}
-#undef obj_to_ggtt
/* i915_gem_context.c */
void i915_gem_context_init(struct drm_device *dev);
@@ -2059,17 +2106,8 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
/* i915_gem_gtt.c */
void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev);
-void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,
- struct drm_i915_gem_object *obj,
- enum i915_cache_level cache_level);
-void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
- struct drm_i915_gem_object *obj);
-
void i915_gem_restore_gtt_mappings(struct drm_device *dev);
int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj);
-void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj,
- enum i915_cache_level cache_level);
-void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj);
void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj);
void i915_gem_init_global_gtt(struct drm_device *dev);
void i915_gem_setup_global_gtt(struct drm_device *dev, unsigned long start,
@@ -2090,6 +2128,7 @@ int __must_check i915_gem_evict_something(struct drm_device *dev,
unsigned cache_level,
bool mappable,
bool nonblock);
+int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle);
int i915_gem_evict_everything(struct drm_device *dev);
/* i915_gem_stolen.c */
@@ -2182,15 +2221,30 @@ static inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
extern void intel_i2c_reset(struct drm_device *dev);
/* intel_opregion.c */
+struct intel_encoder;
extern int intel_opregion_setup(struct drm_device *dev);
#ifdef CONFIG_ACPI
extern void intel_opregion_init(struct drm_device *dev);
extern void intel_opregion_fini(struct drm_device *dev);
extern void intel_opregion_asle_intr(struct drm_device *dev);
+extern int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
+ bool enable);
+extern int intel_opregion_notify_adapter(struct drm_device *dev,
+ pci_power_t state);
#else
static inline void intel_opregion_init(struct drm_device *dev) { return; }
static inline void intel_opregion_fini(struct drm_device *dev) { return; }
static inline void intel_opregion_asle_intr(struct drm_device *dev) { return; }
+static inline int
+intel_opregion_notify_encoder(struct intel_encoder *intel_encoder, bool enable)
+{
+ return 0;
+}
+static inline int
+intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state)
+{
+ return 0;
+}
#endif
/* intel_acpi.c */
@@ -2252,8 +2306,16 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val)
u32 vlv_punit_read(struct drm_i915_private *dev_priv, u8 addr);
void vlv_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val);
u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr);
-u32 vlv_dpio_read(struct drm_i915_private *dev_priv, int reg);
-void vlv_dpio_write(struct drm_i915_private *dev_priv, int reg, u32 val);
+u32 vlv_gpio_nc_read(struct drm_i915_private *dev_priv, u32 reg);
+void vlv_gpio_nc_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
+u32 vlv_cck_read(struct drm_i915_private *dev_priv, u32 reg);
+void vlv_cck_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
+u32 vlv_ccu_read(struct drm_i915_private *dev_priv, u32 reg);
+void vlv_ccu_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
+u32 vlv_gps_core_read(struct drm_i915_private *dev_priv, u32 reg);
+void vlv_gps_core_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
+u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum pipe pipe, int reg);
+void vlv_dpio_write(struct drm_i915_private *dev_priv, enum pipe pipe, int reg, u32 val);
u32 intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg,
enum intel_sbi_destination destination);
void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index cdfb9da0e4ce..0b2bc99b8b81 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -41,6 +41,9 @@ static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *o
static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj,
bool force);
static __must_check int
+i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
+ bool readonly);
+static __must_check int
i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
struct i915_address_space *vm,
unsigned alignment,
@@ -432,11 +435,9 @@ i915_gem_shmem_pread(struct drm_device *dev,
* optimizes for the case when the gpu will dirty the data
* anyway again before the next pread happens. */
needs_clflush = !cpu_cache_is_coherent(dev, obj->cache_level);
- if (i915_gem_obj_bound_any(obj)) {
- ret = i915_gem_object_set_to_gtt_domain(obj, false);
- if (ret)
- return ret;
- }
+ ret = i915_gem_object_wait_rendering(obj, true);
+ if (ret)
+ return ret;
}
ret = i915_gem_object_get_pages(obj);
@@ -748,11 +749,9 @@ i915_gem_shmem_pwrite(struct drm_device *dev,
* optimizes for the case when the gpu will use the data
* right away and we therefore have to clflush anyway. */
needs_clflush_after = cpu_write_needs_clflush(obj);
- if (i915_gem_obj_bound_any(obj)) {
- ret = i915_gem_object_set_to_gtt_domain(obj, true);
- if (ret)
- return ret;
- }
+ ret = i915_gem_object_wait_rendering(obj, false);
+ if (ret)
+ return ret;
}
/* Same trick applies to invalidate partially written cachelines read
* before writing. */
@@ -966,7 +965,7 @@ i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno)
BUG_ON(!mutex_is_locked(&ring->dev->struct_mutex));
ret = 0;
- if (seqno == ring->outstanding_lazy_request)
+ if (seqno == ring->outstanding_lazy_seqno)
ret = i915_add_request(ring, NULL);
return ret;
@@ -1918,7 +1917,7 @@ i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
return 0;
}
-void
+static void
i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
struct intel_ring_buffer *ring)
{
@@ -1957,6 +1956,13 @@ i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
}
}
+void i915_vma_move_to_active(struct i915_vma *vma,
+ struct intel_ring_buffer *ring)
+{
+ list_move_tail(&vma->mm_list, &vma->vm->active_list);
+ return i915_gem_object_move_to_active(vma->obj, ring);
+}
+
static void
i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)
{
@@ -2078,11 +2084,10 @@ int __i915_add_request(struct intel_ring_buffer *ring,
if (ret)
return ret;
- request = kmalloc(sizeof(*request), GFP_KERNEL);
- if (request == NULL)
+ request = ring->preallocated_lazy_request;
+ if (WARN_ON(request == NULL))
return -ENOMEM;
-
/* Record the position of the start of the request so that
* should we detect the updated seqno part-way through the
* GPU processing the request, we never over-estimate the
@@ -2091,17 +2096,13 @@ int __i915_add_request(struct intel_ring_buffer *ring,
request_ring_position = intel_ring_get_tail(ring);
ret = ring->add_request(ring);
- if (ret) {
- kfree(request);
+ if (ret)
return ret;
- }
request->seqno = intel_ring_get_seqno(ring);
request->ring = ring;
request->head = request_start;
request->tail = request_ring_position;
- request->ctx = ring->last_context;
- request->batch_obj = obj;
/* Whilst this request exists, batch_obj will be on the
* active_list, and so will hold the active reference. Only when this
@@ -2109,7 +2110,12 @@ int __i915_add_request(struct intel_ring_buffer *ring,
* inactive_list and lose its active reference. Hence we do not need
* to explicitly hold another reference here.
*/
+ request->batch_obj = obj;
+ /* Hold a reference to the current context so that we can inspect
+ * it later in case a hangcheck error event fires.
+ */
+ request->ctx = ring->last_context;
if (request->ctx)
i915_gem_context_reference(request->ctx);
@@ -2129,7 +2135,8 @@ int __i915_add_request(struct intel_ring_buffer *ring,
}
trace_i915_gem_request_add(ring, request->seqno);
- ring->outstanding_lazy_request = 0;
+ ring->outstanding_lazy_seqno = 0;
+ ring->preallocated_lazy_request = NULL;
if (!dev_priv->ums.mm_suspended) {
i915_queue_hangcheck(ring->dev);
@@ -2224,6 +2231,21 @@ static bool i915_request_guilty(struct drm_i915_gem_request *request,
return false;
}
+static bool i915_context_is_banned(const struct i915_ctx_hang_stats *hs)
+{
+ const unsigned long elapsed = get_seconds() - hs->guilty_ts;
+
+ if (hs->banned)
+ return true;
+
+ if (elapsed <= DRM_I915_CTX_BAN_PERIOD) {
+ DRM_ERROR("context hanging too fast, declaring banned!\n");
+ return true;
+ }
+
+ return false;
+}
+
static void i915_set_reset_status(struct intel_ring_buffer *ring,
struct drm_i915_gem_request *request,
u32 acthd)
@@ -2260,10 +2282,13 @@ static void i915_set_reset_status(struct intel_ring_buffer *ring,
hs = &request->file_priv->hang_stats;
if (hs) {
- if (guilty)
+ if (guilty) {
+ hs->banned = i915_context_is_banned(hs);
hs->batch_active++;
- else
+ hs->guilty_ts = get_seconds();
+ } else {
hs->batch_pending++;
+ }
}
}
@@ -2600,6 +2625,7 @@ i915_gem_object_sync(struct drm_i915_gem_object *obj,
if (ret)
return ret;
+ trace_i915_gem_ring_sync_to(from, to, seqno);
ret = to->sync_to(to, from, seqno);
if (!ret)
/* We use last_read_seqno because sync_to()
@@ -2641,11 +2667,17 @@ int i915_vma_unbind(struct i915_vma *vma)
drm_i915_private_t *dev_priv = obj->base.dev->dev_private;
int ret;
+ /* For now we only ever use 1 vma per object */
+ WARN_ON(!list_is_singular(&obj->vma_list));
+
if (list_empty(&vma->vma_link))
return 0;
- if (!drm_mm_node_allocated(&vma->node))
- goto destroy;
+ if (!drm_mm_node_allocated(&vma->node)) {
+ i915_gem_vma_destroy(vma);
+
+ return 0;
+ }
if (obj->pin_count)
return -EBUSY;
@@ -2669,12 +2701,8 @@ int i915_vma_unbind(struct i915_vma *vma)
trace_i915_vma_unbind(vma);
- if (obj->has_global_gtt_mapping)
- i915_gem_gtt_unbind_object(obj);
- if (obj->has_aliasing_ppgtt_mapping) {
- i915_ppgtt_unbind_object(dev_priv->mm.aliasing_ppgtt, obj);
- obj->has_aliasing_ppgtt_mapping = 0;
- }
+ vma->vm->unbind_vma(vma);
+
i915_gem_gtt_finish_object(obj);
i915_gem_object_unpin_pages(obj);
@@ -2685,13 +2713,10 @@ int i915_vma_unbind(struct i915_vma *vma)
drm_mm_remove_node(&vma->node);
-destroy:
i915_gem_vma_destroy(vma);
/* Since the unbound list is global, only move to that list if
- * no more VMAs exist.
- * NB: Until we have real VMAs there will only ever be one */
- WARN_ON(!list_empty(&obj->vma_list));
+ * no more VMAs exist. */
if (list_empty(&obj->vma_list))
list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list);
@@ -3389,8 +3414,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
/* And bump the LRU for this access */
if (i915_gem_object_is_inactive(obj)) {
- struct i915_vma *vma = i915_gem_obj_to_vma(obj,
- &dev_priv->gtt.base);
+ struct i915_vma *vma = i915_gem_obj_to_ggtt(obj);
if (vma)
list_move_tail(&vma->mm_list,
&dev_priv->gtt.base.inactive_list);
@@ -3404,7 +3428,6 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
enum i915_cache_level cache_level)
{
struct drm_device *dev = obj->base.dev;
- drm_i915_private_t *dev_priv = dev->dev_private;
struct i915_vma *vma;
int ret;
@@ -3443,11 +3466,8 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
return ret;
}
- if (obj->has_global_gtt_mapping)
- i915_gem_gtt_bind_object(obj, cache_level);
- if (obj->has_aliasing_ppgtt_mapping)
- i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,
- obj, cache_level);
+ list_for_each_entry(vma, &obj->vma_list, vma_link)
+ vma->vm->bind_vma(vma, cache_level, 0);
}
list_for_each_entry(vma, &obj->vma_list, vma_link)
@@ -3775,6 +3795,7 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
bool map_and_fenceable,
bool nonblocking)
{
+ const u32 flags = map_and_fenceable ? GLOBAL_BIND : 0;
struct i915_vma *vma;
int ret;
@@ -3803,20 +3824,22 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
}
if (!i915_gem_obj_bound(obj, vm)) {
- struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
-
ret = i915_gem_object_bind_to_vm(obj, vm, alignment,
map_and_fenceable,
nonblocking);
if (ret)
return ret;
- if (!dev_priv->mm.aliasing_ppgtt)
- i915_gem_gtt_bind_object(obj, obj->cache_level);
- }
+ vma = i915_gem_obj_to_vma(obj, vm);
+ vm->bind_vma(vma, obj->cache_level, flags);
+ } else
+ vma = i915_gem_obj_to_vma(obj, vm);
+ /* Objects are created map and fenceable. If we bind an object
+ * the first time, and we had aliasing PPGTT (and didn't request
+ * GLOBAL), we'll need to do this on the second bind.*/
if (!obj->has_global_gtt_mapping && map_and_fenceable)
- i915_gem_gtt_bind_object(obj, obj->cache_level);
+ vm->bind_vma(vma, obj->cache_level, GLOBAL_BIND);
obj->pin_count++;
obj->pin_mappable |= map_and_fenceable;
@@ -4015,7 +4038,6 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
{
INIT_LIST_HEAD(&obj->global_list);
INIT_LIST_HEAD(&obj->ring_list);
- INIT_LIST_HEAD(&obj->exec_list);
INIT_LIST_HEAD(&obj->obj_exec_link);
INIT_LIST_HEAD(&obj->vma_list);
@@ -4147,9 +4169,20 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
i915_gem_object_free(obj);
}
-struct i915_vma *i915_gem_vma_create(struct drm_i915_gem_object *obj,
+struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
struct i915_address_space *vm)
{
+ struct i915_vma *vma;
+ list_for_each_entry(vma, &obj->vma_list, vma_link)
+ if (vma->vm == vm)
+ return vma;
+
+ return NULL;
+}
+
+static struct i915_vma *__i915_gem_vma_create(struct drm_i915_gem_object *obj,
+ struct i915_address_space *vm)
+{
struct i915_vma *vma = kzalloc(sizeof(*vma), GFP_KERNEL);
if (vma == NULL)
return ERR_PTR(-ENOMEM);
@@ -4169,10 +4202,29 @@ struct i915_vma *i915_gem_vma_create(struct drm_i915_gem_object *obj,
return vma;
}
+struct i915_vma *
+i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj,
+ struct i915_address_space *vm)
+{
+ struct i915_vma *vma;
+
+ vma = i915_gem_obj_to_vma(obj, vm);
+ if (!vma)
+ vma = __i915_gem_vma_create(obj, vm);
+
+ return vma;
+}
+
void i915_gem_vma_destroy(struct i915_vma *vma)
{
WARN_ON(vma->node.allocated);
+
+ /* Keep the vma as a placeholder in the execbuffer reservation lists */
+ if (!list_empty(&vma->exec_list))
+ return;
+
list_del(&vma->vma_link);
+
kfree(vma);
}
@@ -4182,16 +4234,13 @@ i915_gem_idle(struct drm_device *dev)
drm_i915_private_t *dev_priv = dev->dev_private;
int ret;
- if (dev_priv->ums.mm_suspended) {
- mutex_unlock(&dev->struct_mutex);
+ if (dev_priv->ums.mm_suspended)
return 0;
- }
ret = i915_gpu_idle(dev);
- if (ret) {
- mutex_unlock(&dev->struct_mutex);
+ if (ret)
return ret;
- }
+
i915_gem_retire_requests(dev);
/* Under UMS, be paranoid and evict. */
@@ -4209,36 +4258,35 @@ i915_gem_idle(struct drm_device *dev)
return 0;
}
-void i915_gem_l3_remap(struct drm_device *dev)
+int i915_gem_l3_remap(struct intel_ring_buffer *ring, int slice)
{
+ struct drm_device *dev = ring->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
- u32 misccpctl;
- int i;
-
- if (!HAS_L3_GPU_CACHE(dev))
- return;
+ u32 reg_base = GEN7_L3LOG_BASE + (slice * 0x200);
+ u32 *remap_info = dev_priv->l3_parity.remap_info[slice];
+ int i, ret;
- if (!dev_priv->l3_parity.remap_info)
- return;
+ if (!HAS_L3_DPF(dev) || !remap_info)
+ return 0;
- misccpctl = I915_READ(GEN7_MISCCPCTL);
- I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE);
- POSTING_READ(GEN7_MISCCPCTL);
+ ret = intel_ring_begin(ring, GEN7_L3LOG_SIZE / 4 * 3);
+ if (ret)
+ return ret;
+ /*
+ * Note: We do not worry about the concurrent register cacheline hang
+ * here because no other code should access these registers other than
+ * at initialization time.
+ */
for (i = 0; i < GEN7_L3LOG_SIZE; i += 4) {
- u32 remap = I915_READ(GEN7_L3LOG_BASE + i);
- if (remap && remap != dev_priv->l3_parity.remap_info[i/4])
- DRM_DEBUG("0x%x was already programmed to %x\n",
- GEN7_L3LOG_BASE + i, remap);
- if (remap && !dev_priv->l3_parity.remap_info[i/4])
- DRM_DEBUG_DRIVER("Clearing remapped register\n");
- I915_WRITE(GEN7_L3LOG_BASE + i, dev_priv->l3_parity.remap_info[i/4]);
+ intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
+ intel_ring_emit(ring, reg_base + i);
+ intel_ring_emit(ring, remap_info[i/4]);
}
- /* Make sure all the writes land before disabling dop clock gating */
- POSTING_READ(GEN7_L3LOG_BASE);
+ intel_ring_advance(ring);
- I915_WRITE(GEN7_MISCCPCTL, misccpctl);
+ return ret;
}
void i915_gem_init_swizzling(struct drm_device *dev)
@@ -4330,7 +4378,7 @@ int
i915_gem_init_hw(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
- int ret;
+ int ret, i;
if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt())
return -EIO;
@@ -4338,20 +4386,26 @@ i915_gem_init_hw(struct drm_device *dev)
if (dev_priv->ellc_size)
I915_WRITE(HSW_IDICR, I915_READ(HSW_IDICR) | IDIHASHMSK(0xf));
+ if (IS_HSW_GT3(dev))
+ I915_WRITE(MI_PREDICATE_RESULT_2, LOWER_SLICE_ENABLED);
+ else
+ I915_WRITE(MI_PREDICATE_RESULT_2, LOWER_SLICE_DISABLED);
+
if (HAS_PCH_NOP(dev)) {
u32 temp = I915_READ(GEN7_MSG_CTL);
temp &= ~(WAIT_FOR_PCH_FLR_ACK | WAIT_FOR_PCH_RESET_ACK);
I915_WRITE(GEN7_MSG_CTL, temp);
}
- i915_gem_l3_remap(dev);
-
i915_gem_init_swizzling(dev);
ret = i915_gem_init_rings(dev);
if (ret)
return ret;
+ for (i = 0; i < NUM_L3_SLICES(dev); i++)
+ i915_gem_l3_remap(&dev_priv->ring[RCS], i);
+
/*
* XXX: There was some w/a described somewhere suggesting loading
* contexts before PPGTT.
@@ -4523,6 +4577,7 @@ i915_gem_load(struct drm_device *dev)
INIT_LIST_HEAD(&dev_priv->vm_list);
i915_init_vm(dev_priv, &dev_priv->gtt.base);
+ INIT_LIST_HEAD(&dev_priv->context_list);
INIT_LIST_HEAD(&dev_priv->mm.unbound_list);
INIT_LIST_HEAD(&dev_priv->mm.bound_list);
INIT_LIST_HEAD(&dev_priv->mm.fence_list);
@@ -4582,7 +4637,7 @@ static int i915_gem_init_phys_object(struct drm_device *dev,
if (dev_priv->mm.phys_objs[id - 1] || !size)
return 0;
- phys_obj = kzalloc(sizeof(struct drm_i915_gem_phys_object), GFP_KERNEL);
+ phys_obj = kzalloc(sizeof(*phys_obj), GFP_KERNEL);
if (!phys_obj)
return -ENOMEM;
@@ -4859,11 +4914,10 @@ bool i915_gem_obj_bound(struct drm_i915_gem_object *o,
bool i915_gem_obj_bound_any(struct drm_i915_gem_object *o)
{
- struct drm_i915_private *dev_priv = o->base.dev->dev_private;
- struct i915_address_space *vm;
+ struct i915_vma *vma;
- list_for_each_entry(vm, &dev_priv->vm_list, global_link)
- if (i915_gem_obj_bound(o, vm))
+ list_for_each_entry(vma, &o->vma_list, vma_link)
+ if (drm_mm_node_allocated(&vma->node))
return true;
return false;
@@ -4921,26 +4975,16 @@ i915_gem_inactive_scan(struct shrinker *shrinker, struct shrink_control *sc)
return freed;
}
-struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
- struct i915_address_space *vm)
+struct i915_vma *i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj)
{
struct i915_vma *vma;
- list_for_each_entry(vma, &obj->vma_list, vma_link)
- if (vma->vm == vm)
- return vma;
-
- return NULL;
-}
-struct i915_vma *
-i915_gem_obj_lookup_or_create_vma(struct drm_i915_gem_object *obj,
- struct i915_address_space *vm)
-{
- struct i915_vma *vma;
+ if (WARN_ON(list_empty(&obj->vma_list)))
+ return NULL;
- vma = i915_gem_obj_to_vma(obj, vm);
- if (!vma)
- vma = i915_gem_vma_create(obj, vm);
+ vma = list_first_entry(&obj->vma_list, typeof(*vma), vma_link);
+ if (WARN_ON(vma->vm != obj_to_ggtt(obj)))
+ return NULL;
return vma;
}
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 403309c2a7d6..d4eb88a0f639 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -73,7 +73,7 @@
*
* There are two confusing terms used above:
* The "current context" means the context which is currently running on the
- * GPU. The GPU has loaded it's state already and has stored away the gtt
+ * GPU. The GPU has loaded its state already and has stored away the gtt
* offset of the BO. The GPU is not actively referencing the data at this
* offset, but it will on the next context switch. The only way to avoid this
* is to do a GPU reset.
@@ -129,6 +129,7 @@ void i915_gem_context_free(struct kref *ctx_ref)
struct i915_hw_context *ctx = container_of(ctx_ref,
typeof(*ctx), ref);
+ list_del(&ctx->link);
drm_gem_object_unreference(&ctx->obj->base);
kfree(ctx);
}
@@ -147,6 +148,7 @@ create_hw_context(struct drm_device *dev,
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");
@@ -166,6 +168,7 @@ create_hw_context(struct drm_device *dev,
* assertion in the context switch code.
*/
ctx->ring = &dev_priv->ring[RCS];
+ list_add_tail(&ctx->link, &dev_priv->context_list);
/* Default context will never have a file_priv */
if (file_priv == NULL)
@@ -178,6 +181,10 @@ create_hw_context(struct drm_device *dev,
ctx->file_priv = file_priv;
ctx->id = ret;
+ /* NB: Mark all slices as needing a remap so that when the context first
+ * loads it will restore whatever remap state already exists. If there
+ * is no remap info, it will be a NOP. */
+ ctx->remap_slice = (1 << NUM_L3_SLICES(dev)) - 1;
return ctx;
@@ -393,11 +400,11 @@ static int do_switch(struct i915_hw_context *to)
struct intel_ring_buffer *ring = to->ring;
struct i915_hw_context *from = ring->last_context;
u32 hw_flags = 0;
- int ret;
+ int ret, i;
BUG_ON(from != NULL && from->obj != NULL && from->obj->pin_count == 0);
- if (from == to)
+ if (from == to && !to->remap_slice)
return 0;
ret = i915_gem_obj_ggtt_pin(to->obj, CONTEXT_ALIGN, false, false);
@@ -415,13 +422,13 @@ static int do_switch(struct i915_hw_context *to)
return ret;
}
- if (!to->obj->has_global_gtt_mapping)
- i915_gem_gtt_bind_object(to->obj, to->obj->cache_level);
+ if (!to->obj->has_global_gtt_mapping) {
+ struct i915_vma *vma = i915_gem_obj_to_ggtt(to->obj);
+ vma->vm->bind_vma(vma, to->obj->cache_level, GLOBAL_BIND);
+ }
if (!to->is_initialized || is_default_context(to))
hw_flags |= MI_RESTORE_INHIBIT;
- else if (WARN_ON_ONCE(from == to)) /* not yet expected */
- hw_flags |= MI_FORCE_RESTORE;
ret = mi_set_context(ring, to, hw_flags);
if (ret) {
@@ -429,6 +436,18 @@ static int do_switch(struct i915_hw_context *to)
return ret;
}
+ for (i = 0; i < MAX_L3_SLICES; i++) {
+ if (!(to->remap_slice & (1<<i)))
+ continue;
+
+ ret = i915_gem_l3_remap(ring, i);
+ /* If it failed, try again next round */
+ if (ret)
+ DRM_DEBUG_DRIVER("L3 remapping failed\n");
+ else
+ to->remap_slice &= ~(1<<i);
+ }
+
/* The backing object for the context is done after switching to the
* *next* context. Therefore we cannot retire the previous context until
* the next context has already started running. In fact, the below code
@@ -436,11 +455,8 @@ static int do_switch(struct i915_hw_context *to)
* MI_SET_CONTEXT instead of when the next seqno has completed.
*/
if (from != NULL) {
- struct drm_i915_private *dev_priv = from->obj->base.dev->dev_private;
- struct i915_address_space *ggtt = &dev_priv->gtt.base;
from->obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
- list_move_tail(&i915_gem_obj_to_vma(from->obj, ggtt)->mm_list, &ggtt->active_list);
- i915_gem_object_move_to_active(from->obj, ring);
+ i915_vma_move_to_active(i915_gem_obj_to_ggtt(from->obj), ring);
/* As long as MI_SET_CONTEXT is serializing, ie. it flushes the
* whole damn pipeline, we don't need to explicitly mark the
* object dirty. The only exception is that the context must be
@@ -451,17 +467,7 @@ static int do_switch(struct i915_hw_context *to)
from->obj->dirty = 1;
BUG_ON(from->obj->ring != ring);
- ret = i915_add_request(ring, NULL);
- if (ret) {
- /* Too late, we've already scheduled a context switch.
- * Try to undo the change so that the hw state is
- * consistent with out tracking. In case of emergency,
- * scream.
- */
- WARN_ON(mi_set_context(ring, from, MI_RESTORE_INHIBIT));
- return ret;
- }
-
+ /* obj is kept alive until the next request by its active ref */
i915_gem_object_unpin(from->obj);
i915_gem_context_unreference(from);
}
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index 91b700155850..b7376533633d 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -37,6 +37,9 @@ mark_free(struct i915_vma *vma, struct list_head *unwind)
if (vma->obj->pin_count)
return false;
+ if (WARN_ON(!list_empty(&vma->exec_list)))
+ return false;
+
list_add(&vma->exec_list, unwind);
return drm_mm_scan_add_block(&vma->node);
}
@@ -113,7 +116,7 @@ none:
}
/* We expect the caller to unpin, evict all and try again, or give up.
- * So calling i915_gem_evict_everything() is unnecessary.
+ * So calling i915_gem_evict_vm() is unnecessary.
*/
return -ENOSPC;
@@ -152,12 +155,48 @@ found:
return ret;
}
+/**
+ * i915_gem_evict_vm - Try to free up VM space
+ *
+ * @vm: Address space to evict from
+ * @do_idle: Boolean directing whether to idle first.
+ *
+ * VM eviction is about freeing up virtual address space. If one wants fine
+ * grained eviction, they should see evict something for more details. In terms
+ * of freeing up actual system memory, this function may not accomplish the
+ * desired result. An object may be shared in multiple address space, and this
+ * function will not assert those objects be freed.
+ *
+ * Using do_idle will result in a more complete eviction because it retires, and
+ * inactivates current BOs.
+ */
+int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle)
+{
+ struct i915_vma *vma, *next;
+ int ret;
+
+ trace_i915_gem_evict_vm(vm);
+
+ if (do_idle) {
+ ret = i915_gpu_idle(vm->dev);
+ if (ret)
+ return ret;
+
+ i915_gem_retire_requests(vm->dev);
+ }
+
+ list_for_each_entry_safe(vma, next, &vm->inactive_list, mm_list)
+ if (vma->obj->pin_count == 0)
+ WARN_ON(i915_vma_unbind(vma));
+
+ return 0;
+}
+
int
i915_gem_evict_everything(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct i915_address_space *vm;
- struct i915_vma *vma, *next;
bool lists_empty = true;
int ret;
@@ -184,11 +223,8 @@ i915_gem_evict_everything(struct drm_device *dev)
i915_gem_retire_requests(dev);
/* Having flushed everything, unbind() should never raise an error */
- list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
- list_for_each_entry_safe(vma, next, &vm->inactive_list, mm_list)
- if (vma->obj->pin_count == 0)
- WARN_ON(i915_vma_unbind(vma));
- }
+ list_for_each_entry(vm, &dev_priv->vm_list, global_link)
+ WARN_ON(i915_gem_evict_vm(vm, false));
return 0;
}
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index bf345777ae9f..88c924f6b2c3 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -33,35 +33,35 @@
#include "intel_drv.h"
#include <linux/dma_remapping.h>
-struct eb_objects {
- struct list_head objects;
+struct eb_vmas {
+ struct list_head vmas;
int and;
union {
- struct drm_i915_gem_object *lut[0];
+ struct i915_vma *lut[0];
struct hlist_head buckets[0];
};
};
-static struct eb_objects *
-eb_create(struct drm_i915_gem_execbuffer2 *args)
+static struct eb_vmas *
+eb_create(struct drm_i915_gem_execbuffer2 *args, struct i915_address_space *vm)
{
- struct eb_objects *eb = NULL;
+ struct eb_vmas *eb = NULL;
if (args->flags & I915_EXEC_HANDLE_LUT) {
- int size = args->buffer_count;
- size *= sizeof(struct drm_i915_gem_object *);
- size += sizeof(struct eb_objects);
+ unsigned size = args->buffer_count;
+ size *= sizeof(struct i915_vma *);
+ size += sizeof(struct eb_vmas);
eb = kmalloc(size, GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
}
if (eb == NULL) {
- int size = args->buffer_count;
- int count = PAGE_SIZE / sizeof(struct hlist_head) / 2;
+ unsigned size = args->buffer_count;
+ unsigned count = PAGE_SIZE / sizeof(struct hlist_head) / 2;
BUILD_BUG_ON_NOT_POWER_OF_2(PAGE_SIZE / sizeof(struct hlist_head));
while (count > 2*size)
count >>= 1;
eb = kzalloc(count*sizeof(struct hlist_head) +
- sizeof(struct eb_objects),
+ sizeof(struct eb_vmas),
GFP_TEMPORARY);
if (eb == NULL)
return eb;
@@ -70,64 +70,102 @@ eb_create(struct drm_i915_gem_execbuffer2 *args)
} else
eb->and = -args->buffer_count;
- INIT_LIST_HEAD(&eb->objects);
+ INIT_LIST_HEAD(&eb->vmas);
return eb;
}
static void
-eb_reset(struct eb_objects *eb)
+eb_reset(struct eb_vmas *eb)
{
if (eb->and >= 0)
memset(eb->buckets, 0, (eb->and+1)*sizeof(struct hlist_head));
}
static int
-eb_lookup_objects(struct eb_objects *eb,
- struct drm_i915_gem_exec_object2 *exec,
- const struct drm_i915_gem_execbuffer2 *args,
- struct drm_file *file)
+eb_lookup_vmas(struct eb_vmas *eb,
+ struct drm_i915_gem_exec_object2 *exec,
+ const struct drm_i915_gem_execbuffer2 *args,
+ struct i915_address_space *vm,
+ struct drm_file *file)
{
- int i;
+ struct drm_i915_gem_object *obj;
+ struct list_head objects;
+ int i, ret = 0;
+ INIT_LIST_HEAD(&objects);
spin_lock(&file->table_lock);
+ /* Grab a reference to the object and release the lock so we can lookup
+ * or create the VMA without using GFP_ATOMIC */
for (i = 0; i < args->buffer_count; i++) {
- struct drm_i915_gem_object *obj;
-
obj = to_intel_bo(idr_find(&file->object_idr, exec[i].handle));
if (obj == NULL) {
spin_unlock(&file->table_lock);
DRM_DEBUG("Invalid object handle %d at index %d\n",
exec[i].handle, i);
- return -ENOENT;
+ ret = -ENOENT;
+ goto out;
}
- if (!list_empty(&obj->exec_list)) {
+ if (!list_empty(&obj->obj_exec_link)) {
spin_unlock(&file->table_lock);
DRM_DEBUG("Object %p [handle %d, index %d] appears more than once in object list\n",
obj, exec[i].handle, i);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
drm_gem_object_reference(&obj->base);
- list_add_tail(&obj->exec_list, &eb->objects);
+ list_add_tail(&obj->obj_exec_link, &objects);
+ }
+ spin_unlock(&file->table_lock);
- obj->exec_entry = &exec[i];
+ i = 0;
+ list_for_each_entry(obj, &objects, obj_exec_link) {
+ struct i915_vma *vma;
+
+ /*
+ * NOTE: We can leak any vmas created here when something fails
+ * later on. But that's no issue since vma_unbind can deal with
+ * vmas which are not actually bound. And since only
+ * lookup_or_create exists as an interface to get at the vma
+ * from the (obj, vm) we don't run the risk of creating
+ * duplicated vmas for the same vm.
+ */
+ vma = i915_gem_obj_lookup_or_create_vma(obj, vm);
+ if (IS_ERR(vma)) {
+ DRM_DEBUG("Failed to lookup VMA\n");
+ ret = PTR_ERR(vma);
+ goto out;
+ }
+
+ list_add_tail(&vma->exec_list, &eb->vmas);
+
+ vma->exec_entry = &exec[i];
if (eb->and < 0) {
- eb->lut[i] = obj;
+ eb->lut[i] = vma;
} else {
uint32_t handle = args->flags & I915_EXEC_HANDLE_LUT ? i : exec[i].handle;
- obj->exec_handle = handle;
- hlist_add_head(&obj->exec_node,
+ vma->exec_handle = handle;
+ hlist_add_head(&vma->exec_node,
&eb->buckets[handle & eb->and]);
}
+ ++i;
}
- spin_unlock(&file->table_lock);
- return 0;
+
+out:
+ while (!list_empty(&objects)) {
+ obj = list_first_entry(&objects,
+ struct drm_i915_gem_object,
+ obj_exec_link);
+ list_del_init(&obj->obj_exec_link);
+ if (ret)
+ drm_gem_object_unreference(&obj->base);
+ }
+ return ret;
}
-static struct drm_i915_gem_object *
-eb_get_object(struct eb_objects *eb, unsigned long handle)
+static struct i915_vma *eb_get_vma(struct eb_vmas *eb, unsigned long handle)
{
if (eb->and < 0) {
if (handle >= -eb->and)
@@ -139,34 +177,33 @@ eb_get_object(struct eb_objects *eb, unsigned long handle)
head = &eb->buckets[handle & eb->and];
hlist_for_each(node, head) {
- struct drm_i915_gem_object *obj;
+ struct i915_vma *vma;
- obj = hlist_entry(node, struct drm_i915_gem_object, exec_node);
- if (obj->exec_handle == handle)
- return obj;
+ vma = hlist_entry(node, struct i915_vma, exec_node);
+ if (vma->exec_handle == handle)
+ return vma;
}
return NULL;
}
}
-static void
-eb_destroy(struct eb_objects *eb)
-{
- while (!list_empty(&eb->objects)) {
- struct drm_i915_gem_object *obj;
+static void eb_destroy(struct eb_vmas *eb) {
+ while (!list_empty(&eb->vmas)) {
+ struct i915_vma *vma;
- obj = list_first_entry(&eb->objects,
- struct drm_i915_gem_object,
+ vma = list_first_entry(&eb->vmas,
+ struct i915_vma,
exec_list);
- list_del_init(&obj->exec_list);
- drm_gem_object_unreference(&obj->base);
+ list_del_init(&vma->exec_list);
+ drm_gem_object_unreference(&vma->obj->base);
}
kfree(eb);
}
static inline int use_cpu_reloc(struct drm_i915_gem_object *obj)
{
- return (obj->base.write_domain == I915_GEM_DOMAIN_CPU ||
+ return (HAS_LLC(obj->base.dev) ||
+ obj->base.write_domain == I915_GEM_DOMAIN_CPU ||
!obj->map_and_fenceable ||
obj->cache_level != I915_CACHE_NONE);
}
@@ -179,7 +216,7 @@ relocate_entry_cpu(struct drm_i915_gem_object *obj,
char *vaddr;
int ret = -EINVAL;
- ret = i915_gem_object_set_to_cpu_domain(obj, 1);
+ ret = i915_gem_object_set_to_cpu_domain(obj, true);
if (ret)
return ret;
@@ -223,22 +260,24 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj,
static int
i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
- struct eb_objects *eb,
+ struct eb_vmas *eb,
struct drm_i915_gem_relocation_entry *reloc,
struct i915_address_space *vm)
{
struct drm_device *dev = obj->base.dev;
struct drm_gem_object *target_obj;
struct drm_i915_gem_object *target_i915_obj;
+ struct i915_vma *target_vma;
uint32_t target_offset;
int ret = -EINVAL;
/* we've already hold a reference to all valid objects */
- target_obj = &eb_get_object(eb, reloc->target_handle)->base;
- if (unlikely(target_obj == NULL))
+ target_vma = eb_get_vma(eb, reloc->target_handle);
+ if (unlikely(target_vma == NULL))
return -ENOENT;
+ target_i915_obj = target_vma->obj;
+ target_obj = &target_vma->obj->base;
- target_i915_obj = to_intel_bo(target_obj);
target_offset = i915_gem_obj_ggtt_offset(target_i915_obj);
/* Sandybridge PPGTT errata: We need a global gtt mapping for MI and
@@ -247,8 +286,14 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
if (unlikely(IS_GEN6(dev) &&
reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION &&
!target_i915_obj->has_global_gtt_mapping)) {
- i915_gem_gtt_bind_object(target_i915_obj,
- target_i915_obj->cache_level);
+ /* SNB shall not support full PPGTT. This path can only be taken
+ * when the VM is the GGTT (aliasing PPGTT is not a real VM, and
+ * therefore doesn't count).
+ */
+ BUG_ON(vm != obj_to_ggtt(target_i915_obj));
+ vm->bind_vma(i915_gem_obj_to_ggtt(target_i915_obj),
+ target_i915_obj->cache_level,
+ GLOBAL_BIND);
}
/* Validate that the target is in a valid r/w GPU domain */
@@ -320,14 +365,13 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
}
static int
-i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,
- struct eb_objects *eb,
- struct i915_address_space *vm)
+i915_gem_execbuffer_relocate_vma(struct i915_vma *vma,
+ struct eb_vmas *eb)
{
#define N_RELOC(x) ((x) / sizeof(struct drm_i915_gem_relocation_entry))
struct drm_i915_gem_relocation_entry stack_reloc[N_RELOC(512)];
struct drm_i915_gem_relocation_entry __user *user_relocs;
- struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
+ struct drm_i915_gem_exec_object2 *entry = vma->exec_entry;
int remain, ret;
user_relocs = to_user_ptr(entry->relocs_ptr);
@@ -346,8 +390,8 @@ i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,
do {
u64 offset = r->presumed_offset;
- ret = i915_gem_execbuffer_relocate_entry(obj, eb, r,
- vm);
+ ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, r,
+ vma->vm);
if (ret)
return ret;
@@ -368,17 +412,16 @@ i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,
}
static int
-i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj,
- struct eb_objects *eb,
- struct drm_i915_gem_relocation_entry *relocs,
- struct i915_address_space *vm)
+i915_gem_execbuffer_relocate_vma_slow(struct i915_vma *vma,
+ struct eb_vmas *eb,
+ struct drm_i915_gem_relocation_entry *relocs)
{
- const struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
+ const struct drm_i915_gem_exec_object2 *entry = vma->exec_entry;
int i, ret;
for (i = 0; i < entry->relocation_count; i++) {
- ret = i915_gem_execbuffer_relocate_entry(obj, eb, &relocs[i],
- vm);
+ ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, &relocs[i],
+ vma->vm);
if (ret)
return ret;
}
@@ -387,10 +430,10 @@ i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj,
}
static int
-i915_gem_execbuffer_relocate(struct eb_objects *eb,
+i915_gem_execbuffer_relocate(struct eb_vmas *eb,
struct i915_address_space *vm)
{
- struct drm_i915_gem_object *obj;
+ struct i915_vma *vma;
int ret = 0;
/* This is the fast path and we cannot handle a pagefault whilst
@@ -401,8 +444,8 @@ i915_gem_execbuffer_relocate(struct eb_objects *eb,
* lockdep complains vehemently.
*/
pagefault_disable();
- list_for_each_entry(obj, &eb->objects, exec_list) {
- ret = i915_gem_execbuffer_relocate_object(obj, eb, vm);
+ list_for_each_entry(vma, &eb->vmas, exec_list) {
+ ret = i915_gem_execbuffer_relocate_vma(vma, eb);
if (ret)
break;
}
@@ -415,31 +458,33 @@ i915_gem_execbuffer_relocate(struct eb_objects *eb,
#define __EXEC_OBJECT_HAS_FENCE (1<<30)
static int
-need_reloc_mappable(struct drm_i915_gem_object *obj)
+need_reloc_mappable(struct i915_vma *vma)
{
- struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
- return entry->relocation_count && !use_cpu_reloc(obj);
+ struct drm_i915_gem_exec_object2 *entry = vma->exec_entry;
+ return entry->relocation_count && !use_cpu_reloc(vma->obj) &&
+ i915_is_ggtt(vma->vm);
}
static int
-i915_gem_execbuffer_reserve_object(struct drm_i915_gem_object *obj,
- struct intel_ring_buffer *ring,
- struct i915_address_space *vm,
- bool *need_reloc)
+i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
+ struct intel_ring_buffer *ring,
+ bool *need_reloc)
{
- struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
- struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
+ struct drm_i915_gem_object *obj = vma->obj;
+ struct drm_i915_gem_exec_object2 *entry = vma->exec_entry;
bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
bool need_fence, need_mappable;
+ u32 flags = (entry->flags & EXEC_OBJECT_NEEDS_GTT) &&
+ !vma->obj->has_global_gtt_mapping ? GLOBAL_BIND : 0;
int ret;
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(obj);
+ need_mappable = need_fence || need_reloc_mappable(vma);
- ret = i915_gem_object_pin(obj, vm, entry->alignment, need_mappable,
+ ret = i915_gem_object_pin(obj, vma->vm, entry->alignment, need_mappable,
false);
if (ret)
return ret;
@@ -459,16 +504,8 @@ i915_gem_execbuffer_reserve_object(struct drm_i915_gem_object *obj,
}
}
- /* Ensure ppgtt mapping exists if needed */
- if (dev_priv->mm.aliasing_ppgtt && !obj->has_aliasing_ppgtt_mapping) {
- i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,
- obj, obj->cache_level);
-
- obj->has_aliasing_ppgtt_mapping = 1;
- }
-
- if (entry->offset != i915_gem_obj_offset(obj, vm)) {
- entry->offset = i915_gem_obj_offset(obj, vm);
+ if (entry->offset != vma->node.start) {
+ entry->offset = vma->node.start;
*need_reloc = true;
}
@@ -477,22 +514,21 @@ i915_gem_execbuffer_reserve_object(struct drm_i915_gem_object *obj,
obj->base.pending_write_domain = I915_GEM_DOMAIN_RENDER;
}
- if (entry->flags & EXEC_OBJECT_NEEDS_GTT &&
- !obj->has_global_gtt_mapping)
- i915_gem_gtt_bind_object(obj, obj->cache_level);
+ vma->vm->bind_vma(vma, obj->cache_level, flags);
return 0;
}
static void
-i915_gem_execbuffer_unreserve_object(struct drm_i915_gem_object *obj)
+i915_gem_execbuffer_unreserve_vma(struct i915_vma *vma)
{
struct drm_i915_gem_exec_object2 *entry;
+ struct drm_i915_gem_object *obj = vma->obj;
- if (!i915_gem_obj_bound_any(obj))
+ if (!drm_mm_node_allocated(&vma->node))
return;
- entry = obj->exec_entry;
+ entry = vma->exec_entry;
if (entry->flags & __EXEC_OBJECT_HAS_FENCE)
i915_gem_object_unpin_fence(obj);
@@ -505,41 +541,46 @@ i915_gem_execbuffer_unreserve_object(struct drm_i915_gem_object *obj)
static int
i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
- struct list_head *objects,
- struct i915_address_space *vm,
+ struct list_head *vmas,
bool *need_relocs)
{
struct drm_i915_gem_object *obj;
- struct list_head ordered_objects;
+ struct i915_vma *vma;
+ struct i915_address_space *vm;
+ struct list_head ordered_vmas;
bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
int retry;
- INIT_LIST_HEAD(&ordered_objects);
- while (!list_empty(objects)) {
+ if (list_empty(vmas))
+ return 0;
+
+ vm = list_first_entry(vmas, struct i915_vma, exec_list)->vm;
+
+ INIT_LIST_HEAD(&ordered_vmas);
+ while (!list_empty(vmas)) {
struct drm_i915_gem_exec_object2 *entry;
bool need_fence, need_mappable;
- obj = list_first_entry(objects,
- struct drm_i915_gem_object,
- exec_list);
- entry = obj->exec_entry;
+ vma = list_first_entry(vmas, struct i915_vma, exec_list);
+ obj = vma->obj;
+ entry = vma->exec_entry;
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(obj);
+ need_mappable = need_fence || need_reloc_mappable(vma);
if (need_mappable)
- list_move(&obj->exec_list, &ordered_objects);
+ list_move(&vma->exec_list, &ordered_vmas);
else
- list_move_tail(&obj->exec_list, &ordered_objects);
+ list_move_tail(&vma->exec_list, &ordered_vmas);
obj->base.pending_read_domains = I915_GEM_GPU_DOMAINS & ~I915_GEM_DOMAIN_COMMAND;
obj->base.pending_write_domain = 0;
obj->pending_fenced_gpu_access = false;
}
- list_splice(&ordered_objects, objects);
+ list_splice(&ordered_vmas, vmas);
/* Attempt to pin all of the buffers into the GTT.
* This is done in 3 phases:
@@ -558,52 +599,52 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
int ret = 0;
/* Unbind any ill-fitting objects or pin. */
- list_for_each_entry(obj, objects, exec_list) {
- struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
+ list_for_each_entry(vma, vmas, exec_list) {
+ struct drm_i915_gem_exec_object2 *entry = vma->exec_entry;
bool need_fence, need_mappable;
- u32 obj_offset;
- if (!i915_gem_obj_bound(obj, vm))
+ obj = vma->obj;
+
+ if (!drm_mm_node_allocated(&vma->node))
continue;
- obj_offset = i915_gem_obj_offset(obj, vm);
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(obj);
+ need_mappable = need_fence || need_reloc_mappable(vma);
WARN_ON((need_mappable || need_fence) &&
- !i915_is_ggtt(vm));
+ !i915_is_ggtt(vma->vm));
if ((entry->alignment &&
- obj_offset & (entry->alignment - 1)) ||
+ vma->node.start & (entry->alignment - 1)) ||
(need_mappable && !obj->map_and_fenceable))
- ret = i915_vma_unbind(i915_gem_obj_to_vma(obj, vm));
+ ret = i915_vma_unbind(vma);
else
- ret = i915_gem_execbuffer_reserve_object(obj, ring, vm, need_relocs);
+ ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs);
if (ret)
goto err;
}
/* Bind fresh objects */
- list_for_each_entry(obj, objects, exec_list) {
- if (i915_gem_obj_bound(obj, vm))
+ list_for_each_entry(vma, vmas, exec_list) {
+ if (drm_mm_node_allocated(&vma->node))
continue;
- ret = i915_gem_execbuffer_reserve_object(obj, ring, vm, need_relocs);
+ ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs);
if (ret)
goto err;
}
err: /* Decrement pin count for bound objects */
- list_for_each_entry(obj, objects, exec_list)
- i915_gem_execbuffer_unreserve_object(obj);
+ list_for_each_entry(vma, vmas, exec_list)
+ i915_gem_execbuffer_unreserve_vma(vma);
if (ret != -ENOSPC || retry++)
return ret;
- ret = i915_gem_evict_everything(ring->dev);
+ ret = i915_gem_evict_vm(vm, true);
if (ret)
return ret;
} while (1);
@@ -614,24 +655,27 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
struct drm_i915_gem_execbuffer2 *args,
struct drm_file *file,
struct intel_ring_buffer *ring,
- struct eb_objects *eb,
- struct drm_i915_gem_exec_object2 *exec,
- struct i915_address_space *vm)
+ struct eb_vmas *eb,
+ struct drm_i915_gem_exec_object2 *exec)
{
struct drm_i915_gem_relocation_entry *reloc;
- struct drm_i915_gem_object *obj;
+ struct i915_address_space *vm;
+ struct i915_vma *vma;
bool need_relocs;
int *reloc_offset;
int i, total, ret;
- int count = args->buffer_count;
+ unsigned count = args->buffer_count;
+
+ if (WARN_ON(list_empty(&eb->vmas)))
+ return 0;
+
+ vm = list_first_entry(&eb->vmas, struct i915_vma, exec_list)->vm;
/* We may process another execbuffer during the unlock... */
- while (!list_empty(&eb->objects)) {
- obj = list_first_entry(&eb->objects,
- struct drm_i915_gem_object,
- exec_list);
- list_del_init(&obj->exec_list);
- drm_gem_object_unreference(&obj->base);
+ while (!list_empty(&eb->vmas)) {
+ vma = list_first_entry(&eb->vmas, struct i915_vma, exec_list);
+ list_del_init(&vma->exec_list);
+ drm_gem_object_unreference(&vma->obj->base);
}
mutex_unlock(&dev->struct_mutex);
@@ -695,20 +739,19 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
/* reacquire the objects */
eb_reset(eb);
- ret = eb_lookup_objects(eb, exec, args, file);
+ ret = eb_lookup_vmas(eb, exec, args, vm, file);
if (ret)
goto err;
need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0;
- ret = i915_gem_execbuffer_reserve(ring, &eb->objects, vm, &need_relocs);
+ ret = i915_gem_execbuffer_reserve(ring, &eb->vmas, &need_relocs);
if (ret)
goto err;
- list_for_each_entry(obj, &eb->objects, exec_list) {
- int offset = obj->exec_entry - exec;
- ret = i915_gem_execbuffer_relocate_object_slow(obj, eb,
- reloc + reloc_offset[offset],
- vm);
+ list_for_each_entry(vma, &eb->vmas, exec_list) {
+ int offset = vma->exec_entry - exec;
+ ret = i915_gem_execbuffer_relocate_vma_slow(vma, eb,
+ reloc + reloc_offset[offset]);
if (ret)
goto err;
}
@@ -727,14 +770,15 @@ err:
static int
i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
- struct list_head *objects)
+ struct list_head *vmas)
{
- struct drm_i915_gem_object *obj;
+ struct i915_vma *vma;
uint32_t flush_domains = 0;
bool flush_chipset = false;
int ret;
- list_for_each_entry(obj, objects, exec_list) {
+ list_for_each_entry(vma, vmas, exec_list) {
+ struct drm_i915_gem_object *obj = vma->obj;
ret = i915_gem_object_sync(obj, ring);
if (ret)
return ret;
@@ -771,8 +815,8 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
int count)
{
int i;
- int relocs_total = 0;
- int relocs_max = INT_MAX / sizeof(struct drm_i915_gem_relocation_entry);
+ unsigned relocs_total = 0;
+ unsigned relocs_max = UINT_MAX / sizeof(struct drm_i915_gem_relocation_entry);
for (i = 0; i < count; i++) {
char __user *ptr = to_user_ptr(exec[i].relocs_ptr);
@@ -809,13 +853,13 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
}
static void
-i915_gem_execbuffer_move_to_active(struct list_head *objects,
- struct i915_address_space *vm,
+i915_gem_execbuffer_move_to_active(struct list_head *vmas,
struct intel_ring_buffer *ring)
{
- struct drm_i915_gem_object *obj;
+ struct i915_vma *vma;
- list_for_each_entry(obj, objects, exec_list) {
+ list_for_each_entry(vma, vmas, exec_list) {
+ struct drm_i915_gem_object *obj = vma->obj;
u32 old_read = obj->base.read_domains;
u32 old_write = obj->base.write_domain;
@@ -825,9 +869,7 @@ i915_gem_execbuffer_move_to_active(struct list_head *objects,
obj->base.read_domains = obj->base.pending_read_domains;
obj->fenced_gpu_access = obj->pending_fenced_gpu_access;
- /* FIXME: This lookup gets fixed later <-- danvet */
- list_move_tail(&i915_gem_obj_to_vma(obj, vm)->mm_list, &vm->active_list);
- i915_gem_object_move_to_active(obj, ring);
+ i915_vma_move_to_active(vma, ring);
if (obj->base.write_domain) {
obj->dirty = 1;
obj->last_write_seqno = intel_ring_get_seqno(ring);
@@ -885,12 +927,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
struct i915_address_space *vm)
{
drm_i915_private_t *dev_priv = dev->dev_private;
- struct eb_objects *eb;
+ struct eb_vmas *eb;
struct drm_i915_gem_object *batch_obj;
struct drm_clip_rect *cliprects = NULL;
struct intel_ring_buffer *ring;
+ struct i915_ctx_hang_stats *hs;
u32 ctx_id = i915_execbuffer2_get_context_id(*args);
- u32 exec_start, exec_len;
+ u32 exec_len, exec_start = args->batch_start_offset;
u32 mask, flags;
int ret, mode, i;
bool need_relocs;
@@ -1000,7 +1043,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
return -EINVAL;
}
- cliprects = kmalloc(args->num_cliprects * sizeof(*cliprects),
+ cliprects = kcalloc(args->num_cliprects,
+ sizeof(*cliprects),
GFP_KERNEL);
if (cliprects == NULL) {
ret = -ENOMEM;
@@ -1025,7 +1069,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
goto pre_mutex_err;
}
- eb = eb_create(args);
+ eb = eb_create(args, vm);
if (eb == NULL) {
mutex_unlock(&dev->struct_mutex);
ret = -ENOMEM;
@@ -1033,18 +1077,16 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
}
/* Look up object handles */
- ret = eb_lookup_objects(eb, exec, args, file);
+ ret = eb_lookup_vmas(eb, exec, args, vm, file);
if (ret)
goto err;
/* take note of the batch buffer before we might reorder the lists */
- batch_obj = list_entry(eb->objects.prev,
- struct drm_i915_gem_object,
- exec_list);
+ batch_obj = list_entry(eb->vmas.prev, struct i915_vma, exec_list)->obj;
/* Move the objects en-masse into the GTT, evicting if necessary. */
need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0;
- ret = i915_gem_execbuffer_reserve(ring, &eb->objects, vm, &need_relocs);
+ ret = i915_gem_execbuffer_reserve(ring, &eb->vmas, &need_relocs);
if (ret)
goto err;
@@ -1054,7 +1096,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
if (ret) {
if (ret == -EFAULT) {
ret = i915_gem_execbuffer_relocate_slow(dev, args, file, ring,
- eb, exec, vm);
+ eb, exec);
BUG_ON(!mutex_is_locked(&dev->struct_mutex));
}
if (ret)
@@ -1073,13 +1115,50 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
* batch" bit. Hence we need to pin secure batches into the global gtt.
* hsw should have this fixed, but let's be paranoid and do it
* unconditionally for now. */
- if (flags & I915_DISPATCH_SECURE && !batch_obj->has_global_gtt_mapping)
- i915_gem_gtt_bind_object(batch_obj, batch_obj->cache_level);
+ if (flags & I915_DISPATCH_SECURE) {
+ struct i915_address_space *ggtt = obj_to_ggtt(batch_obj);
+
+ /* Assuming all privileged batches are in the global GTT means
+ * we need to make sure we have a global gtt offset, as well as
+ * the PTEs mapped. As mentioned above, we can forego this on
+ * HSW, but don't.
+ */
- ret = i915_gem_execbuffer_move_to_gpu(ring, &eb->objects);
+ ret = i915_gem_obj_ggtt_pin(batch_obj, 0, false, false);
+ if (ret)
+ goto err;
+
+ ggtt->bind_vma(i915_gem_obj_to_ggtt(batch_obj),
+ batch_obj->cache_level,
+ GLOBAL_BIND);
+
+ /* Since the active list is per VM, we need to make sure this
+ * VMA ends up on the GGTT's active list to avoid premature
+ * eviction.
+ */
+ i915_vma_move_to_active(i915_gem_obj_to_ggtt(batch_obj), ring);
+
+ i915_gem_object_unpin(batch_obj);
+
+ exec_start += i915_gem_obj_ggtt_offset(batch_obj);
+ } else
+ exec_start += i915_gem_obj_offset(batch_obj, vm);
+
+ ret = i915_gem_execbuffer_move_to_gpu(ring, &eb->vmas);
if (ret)
goto err;
+ hs = i915_gem_context_get_hang_stats(dev, file, ctx_id);
+ if (IS_ERR(hs)) {
+ ret = PTR_ERR(hs);
+ goto err;
+ }
+
+ if (hs->banned) {
+ ret = -EIO;
+ goto err;
+ }
+
ret = i915_switch_context(ring, file, ctx_id);
if (ret)
goto err;
@@ -1105,8 +1184,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
goto err;
}
- exec_start = i915_gem_obj_offset(batch_obj, vm) +
- args->batch_start_offset;
exec_len = args->batch_len;
if (cliprects) {
for (i = 0; i < args->num_cliprects; i++) {
@@ -1131,7 +1208,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
trace_i915_gem_ring_dispatch(ring, intel_ring_get_seqno(ring), flags);
- i915_gem_execbuffer_move_to_active(&eb->objects, vm, ring);
+ i915_gem_execbuffer_move_to_active(&eb->vmas, ring);
i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj);
err:
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 212f6d8c35ec..7ce575646ad6 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -57,6 +57,11 @@
#define HSW_WB_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0xb)
#define HSW_WT_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x6)
+static void gen6_ppgtt_bind_vma(struct i915_vma *vma,
+ enum i915_cache_level cache_level,
+ u32 flags);
+static void gen6_ppgtt_unbind_vma(struct i915_vma *vma);
+
static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr,
enum i915_cache_level level)
{
@@ -332,11 +337,13 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
ppgtt->base.pte_encode = dev_priv->gtt.base.pte_encode;
ppgtt->num_pd_entries = GEN6_PPGTT_PD_ENTRIES;
ppgtt->enable = gen6_ppgtt_enable;
+ ppgtt->base.unbind_vma = NULL;
ppgtt->base.clear_range = gen6_ppgtt_clear_range;
+ ppgtt->base.bind_vma = NULL;
ppgtt->base.insert_entries = gen6_ppgtt_insert_entries;
ppgtt->base.cleanup = gen6_ppgtt_cleanup;
ppgtt->base.scratch = dev_priv->gtt.base.scratch;
- ppgtt->pt_pages = kzalloc(sizeof(struct page *)*ppgtt->num_pd_entries,
+ ppgtt->pt_pages = kcalloc(ppgtt->num_pd_entries, sizeof(struct page *),
GFP_KERNEL);
if (!ppgtt->pt_pages)
return -ENOMEM;
@@ -347,7 +354,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
goto err_pt_alloc;
}
- ppgtt->pt_dma_addr = kzalloc(sizeof(dma_addr_t) *ppgtt->num_pd_entries,
+ ppgtt->pt_dma_addr = kcalloc(ppgtt->num_pd_entries, sizeof(dma_addr_t),
GFP_KERNEL);
if (!ppgtt->pt_dma_addr)
goto err_pt_alloc;
@@ -430,21 +437,24 @@ void i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev)
dev_priv->mm.aliasing_ppgtt = NULL;
}
-void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,
- struct drm_i915_gem_object *obj,
- enum i915_cache_level cache_level)
+static void __always_unused
+gen6_ppgtt_bind_vma(struct i915_vma *vma,
+ enum i915_cache_level cache_level,
+ u32 flags)
{
- ppgtt->base.insert_entries(&ppgtt->base, obj->pages,
- i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT,
- cache_level);
+ const unsigned long entry = vma->node.start >> PAGE_SHIFT;
+
+ WARN_ON(flags);
+
+ gen6_ppgtt_insert_entries(vma->vm, vma->obj->pages, entry, cache_level);
}
-void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
- struct drm_i915_gem_object *obj)
+static void __always_unused gen6_ppgtt_unbind_vma(struct i915_vma *vma)
{
- ppgtt->base.clear_range(&ppgtt->base,
- i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT,
- obj->base.size >> PAGE_SHIFT);
+ const unsigned long entry = vma->node.start >> PAGE_SHIFT;
+
+ gen6_ppgtt_clear_range(vma->vm, entry,
+ vma->obj->base.size >> PAGE_SHIFT);
}
extern int intel_iommu_gfx_mapped;
@@ -496,8 +506,15 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
dev_priv->gtt.base.total / PAGE_SIZE);
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+ struct i915_vma *vma = i915_gem_obj_to_vma(obj,
+ &dev_priv->gtt.base);
+ unsigned flags = obj->has_global_gtt_mapping ? GLOBAL_BIND : 0;
+
i915_gem_clflush_object(obj, obj->pin_display);
- i915_gem_gtt_bind_object(obj, obj->cache_level);
+
+ obj->has_global_gtt_mapping = false;
+
+ vma->vm->bind_vma(vma, obj->cache_level, flags);
}
i915_gem_chipset_flush(dev);
@@ -592,6 +609,19 @@ static void i915_ggtt_insert_entries(struct i915_address_space *vm,
}
+static void i915_ggtt_bind_vma(struct i915_vma *vma,
+ enum i915_cache_level cache_level,
+ u32 unused)
+{
+ const unsigned long entry = vma->node.start >> PAGE_SHIFT;
+ unsigned int flags = (cache_level == I915_CACHE_NONE) ?
+ AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
+
+ BUG_ON(!i915_is_ggtt(vma->vm));
+ intel_gtt_insert_sg_entries(vma->obj->pages, entry, flags);
+ vma->obj->has_global_gtt_mapping = 1;
+}
+
static void i915_ggtt_clear_range(struct i915_address_space *vm,
unsigned int first_entry,
unsigned int num_entries)
@@ -599,32 +629,73 @@ static void i915_ggtt_clear_range(struct i915_address_space *vm,
intel_gtt_clear_range(first_entry, num_entries);
}
+static void i915_ggtt_unbind_vma(struct i915_vma *vma)
+{
+ const unsigned int first = vma->node.start >> PAGE_SHIFT;
+ const unsigned int size = vma->obj->base.size >> PAGE_SHIFT;
-void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj,
- enum i915_cache_level cache_level)
+ BUG_ON(!i915_is_ggtt(vma->vm));
+ vma->obj->has_global_gtt_mapping = 0;
+ intel_gtt_clear_range(first, size);
+}
+
+static void gen6_ggtt_bind_vma(struct i915_vma *vma,
+ enum i915_cache_level cache_level,
+ u32 flags)
{
- struct drm_device *dev = obj->base.dev;
+ struct drm_device *dev = vma->vm->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- const unsigned long entry = i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT;
+ struct drm_i915_gem_object *obj = vma->obj;
+ const unsigned long entry = vma->node.start >> PAGE_SHIFT;
- dev_priv->gtt.base.insert_entries(&dev_priv->gtt.base, obj->pages,
- entry,
- cache_level);
+ /* If there is no aliasing PPGTT, or the caller needs a global mapping,
+ * or we have a global mapping already but the cacheability flags have
+ * changed, set the global PTEs.
+ *
+ * If there is an aliasing PPGTT it is anecdotally faster, so use that
+ * instead if none of the above hold true.
+ *
+ * NB: A global mapping should only be needed for special regions like
+ * "gtt mappable", SNB errata, or if specified via special execbuf
+ * flags. At all other times, the GPU will use the aliasing PPGTT.
+ */
+ if (!dev_priv->mm.aliasing_ppgtt || flags & GLOBAL_BIND) {
+ if (!obj->has_global_gtt_mapping ||
+ (cache_level != obj->cache_level)) {
+ gen6_ggtt_insert_entries(vma->vm, obj->pages, entry,
+ cache_level);
+ obj->has_global_gtt_mapping = 1;
+ }
+ }
- obj->has_global_gtt_mapping = 1;
+ if (dev_priv->mm.aliasing_ppgtt &&
+ (!obj->has_aliasing_ppgtt_mapping ||
+ (cache_level != obj->cache_level))) {
+ gen6_ppgtt_insert_entries(&dev_priv->mm.aliasing_ppgtt->base,
+ vma->obj->pages, entry, cache_level);
+ vma->obj->has_aliasing_ppgtt_mapping = 1;
+ }
}
-void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
+static void gen6_ggtt_unbind_vma(struct i915_vma *vma)
{
- struct drm_device *dev = obj->base.dev;
+ struct drm_device *dev = vma->vm->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- const unsigned long entry = i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT;
+ struct drm_i915_gem_object *obj = vma->obj;
+ const unsigned long entry = vma->node.start >> PAGE_SHIFT;
- dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
+ if (obj->has_global_gtt_mapping) {
+ gen6_ggtt_clear_range(vma->vm, entry,
+ vma->obj->base.size >> PAGE_SHIFT);
+ obj->has_global_gtt_mapping = 0;
+ }
+
+ if (obj->has_aliasing_ppgtt_mapping) {
+ gen6_ppgtt_clear_range(&dev_priv->mm.aliasing_ppgtt->base,
entry,
obj->base.size >> PAGE_SHIFT);
-
- obj->has_global_gtt_mapping = 0;
+ obj->has_aliasing_ppgtt_mapping = 0;
+ }
}
void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj)
@@ -860,7 +931,9 @@ static int gen6_gmch_probe(struct drm_device *dev,
DRM_ERROR("Scratch setup failed\n");
dev_priv->gtt.base.clear_range = gen6_ggtt_clear_range;
+ dev_priv->gtt.base.unbind_vma = gen6_ggtt_unbind_vma;
dev_priv->gtt.base.insert_entries = gen6_ggtt_insert_entries;
+ dev_priv->gtt.base.bind_vma = gen6_ggtt_bind_vma;
return ret;
}
@@ -892,7 +965,9 @@ static int i915_gmch_probe(struct drm_device *dev,
dev_priv->gtt.do_idle_maps = needs_idle_maps(dev_priv->dev);
dev_priv->gtt.base.clear_range = i915_ggtt_clear_range;
+ dev_priv->gtt.base.unbind_vma = i915_ggtt_unbind_vma;
dev_priv->gtt.base.insert_entries = i915_ggtt_insert_entries;
+ dev_priv->gtt.base.bind_vma = i915_ggtt_bind_vma;
return 0;
}
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index e15a1d90037d..d284d892ed94 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -395,7 +395,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
if (gtt_offset == I915_GTT_OFFSET_NONE)
return obj;
- vma = i915_gem_vma_create(obj, ggtt);
+ vma = i915_gem_obj_lookup_or_create_vma(obj, ggtt);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
goto err_out;
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index 032e9ef9c896..ac9ebe98f8b0 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -393,7 +393,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
/* Try to preallocate memory required to save swizzling on put-pages */
if (i915_gem_object_needs_bit17_swizzle(obj)) {
if (obj->bit_17 == NULL) {
- obj->bit_17 = kmalloc(BITS_TO_LONGS(obj->base.size >> PAGE_SHIFT) *
+ obj->bit_17 = kcalloc(BITS_TO_LONGS(obj->base.size >> PAGE_SHIFT),
sizeof(long), GFP_KERNEL);
}
} else {
@@ -504,8 +504,8 @@ i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj)
int i;
if (obj->bit_17 == NULL) {
- obj->bit_17 = kmalloc(BITS_TO_LONGS(page_count) *
- sizeof(long), GFP_KERNEL);
+ obj->bit_17 = kcalloc(BITS_TO_LONGS(page_count),
+ sizeof(long), GFP_KERNEL);
if (obj->bit_17 == NULL) {
DRM_ERROR("Failed to allocate memory for bit 17 "
"record\n");
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index aba9d7498996..0a49b651e510 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -143,8 +143,10 @@ static void i915_error_vprintf(struct drm_i915_error_state_buf *e,
/* Seek the first printf which is hits start position */
if (e->pos < e->start) {
- len = vsnprintf(NULL, 0, f, args);
- if (!__i915_error_seek(e, len))
+ va_list tmp;
+
+ va_copy(tmp, args);
+ if (!__i915_error_seek(e, vsnprintf(NULL, 0, f, tmp)))
return;
}
@@ -213,6 +215,24 @@ static void print_error_buffers(struct drm_i915_error_state_buf *m,
}
}
+static const char *hangcheck_action_to_str(enum intel_ring_hangcheck_action a)
+{
+ switch (a) {
+ case HANGCHECK_IDLE:
+ return "idle";
+ case HANGCHECK_WAIT:
+ return "wait";
+ case HANGCHECK_ACTIVE:
+ return "active";
+ case HANGCHECK_KICK:
+ return "kick";
+ case HANGCHECK_HUNG:
+ return "hung";
+ }
+
+ return "unknown";
+}
+
static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
struct drm_device *dev,
struct drm_i915_error_state *error,
@@ -253,6 +273,9 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
err_printf(m, " waiting: %s\n", yesno(error->waiting[ring]));
err_printf(m, " ring->head: 0x%08x\n", error->cpu_ring_head[ring]);
err_printf(m, " ring->tail: 0x%08x\n", error->cpu_ring_tail[ring]);
+ err_printf(m, " hangcheck: %s [%d]\n",
+ hangcheck_action_to_str(error->hangcheck_action[ring]),
+ error->hangcheck_score[ring]);
}
void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...)
@@ -718,6 +741,9 @@ static void i915_record_ring_state(struct drm_device *dev,
error->cpu_ring_head[ring->id] = ring->head;
error->cpu_ring_tail[ring->id] = ring->tail;
+
+ error->hangcheck_score[ring->id] = ring->hangcheck.score;
+ error->hangcheck_action[ring->id] = ring->hangcheck.action;
}
@@ -767,7 +793,7 @@ static void i915_gem_record_rings(struct drm_device *dev,
error->ring[i].num_requests = count;
error->ring[i].requests =
- kmalloc(count*sizeof(struct drm_i915_error_request),
+ kcalloc(count, sizeof(*error->ring[i].requests),
GFP_ATOMIC);
if (error->ring[i].requests == NULL) {
error->ring[i].num_requests = 0;
@@ -809,7 +835,7 @@ static void i915_gem_capture_vm(struct drm_i915_private *dev_priv,
error->pinned_bo_count[ndx] = i - error->active_bo_count[ndx];
if (i) {
- active_bo = kmalloc(sizeof(*active_bo)*i, GFP_ATOMIC);
+ active_bo = kcalloc(i, sizeof(*active_bo), GFP_ATOMIC);
if (active_bo)
pinned_bo = active_bo + error->active_bo_count[ndx];
}
@@ -986,6 +1012,7 @@ const char *i915_cache_level_str(int type)
case I915_CACHE_NONE: return " uncached";
case I915_CACHE_LLC: return " snooped or LLC";
case I915_CACHE_L3_LLC: return " L3+LLC";
+ case I915_CACHE_WT: return " WT";
default: return "";
}
}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 4b91228fd9bd..84b7efc6ee91 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -665,7 +665,8 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe,
crtc);
}
-static int intel_hpd_irq_event(struct drm_device *dev, struct drm_connector *connector)
+static bool intel_hpd_irq_event(struct drm_device *dev,
+ struct drm_connector *connector)
{
enum drm_connector_status old_status;
@@ -673,11 +674,16 @@ static int intel_hpd_irq_event(struct drm_device *dev, struct drm_connector *con
old_status = connector->status;
connector->status = connector->funcs->detect(connector, false);
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
+ if (old_status == connector->status)
+ return false;
+
+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
connector->base.id,
drm_get_connector_name(connector),
- old_status, connector->status);
- return (old_status != connector->status);
+ drm_get_connector_status_name(old_status),
+ drm_get_connector_status_name(connector->status));
+
+ return true;
}
/*
@@ -801,7 +807,7 @@ static void notify_ring(struct drm_device *dev,
if (ring->obj == NULL)
return;
- trace_i915_gem_request_complete(ring, ring->get_seqno(ring, false));
+ trace_i915_gem_request_complete(ring);
wake_up_all(&ring->irq_queue);
i915_queue_hangcheck(dev);
@@ -882,9 +888,10 @@ static void ivybridge_parity_work(struct work_struct *work)
drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
l3_parity.error_work);
u32 error_status, row, bank, subbank;
- char *parity_event[5];
+ char *parity_event[6];
uint32_t misccpctl;
unsigned long flags;
+ uint8_t slice = 0;
/* We must turn off DOP level clock gating to access the L3 registers.
* In order to prevent a get/put style interface, acquire struct mutex
@@ -892,55 +899,81 @@ static void ivybridge_parity_work(struct work_struct *work)
*/
mutex_lock(&dev_priv->dev->struct_mutex);
+ /* If we've screwed up tracking, just let the interrupt fire again */
+ if (WARN_ON(!dev_priv->l3_parity.which_slice))
+ goto out;
+
misccpctl = I915_READ(GEN7_MISCCPCTL);
I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE);
POSTING_READ(GEN7_MISCCPCTL);
- error_status = I915_READ(GEN7_L3CDERRST1);
- row = GEN7_PARITY_ERROR_ROW(error_status);
- bank = GEN7_PARITY_ERROR_BANK(error_status);
- subbank = GEN7_PARITY_ERROR_SUBBANK(error_status);
+ while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) {
+ u32 reg;
- I915_WRITE(GEN7_L3CDERRST1, GEN7_PARITY_ERROR_VALID |
- GEN7_L3CDERRST1_ENABLE);
- POSTING_READ(GEN7_L3CDERRST1);
+ slice--;
+ if (WARN_ON_ONCE(slice >= NUM_L3_SLICES(dev_priv->dev)))
+ break;
- I915_WRITE(GEN7_MISCCPCTL, misccpctl);
+ dev_priv->l3_parity.which_slice &= ~(1<<slice);
- spin_lock_irqsave(&dev_priv->irq_lock, flags);
- ilk_enable_gt_irq(dev_priv, GT_RENDER_L3_PARITY_ERROR_INTERRUPT);
- spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
+ reg = GEN7_L3CDERRST1 + (slice * 0x200);
- mutex_unlock(&dev_priv->dev->struct_mutex);
+ error_status = I915_READ(reg);
+ row = GEN7_PARITY_ERROR_ROW(error_status);
+ bank = GEN7_PARITY_ERROR_BANK(error_status);
+ subbank = GEN7_PARITY_ERROR_SUBBANK(error_status);
+
+ I915_WRITE(reg, GEN7_PARITY_ERROR_VALID | GEN7_L3CDERRST1_ENABLE);
+ POSTING_READ(reg);
+
+ parity_event[0] = I915_L3_PARITY_UEVENT "=1";
+ parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row);
+ parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank);
+ parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank);
+ parity_event[4] = kasprintf(GFP_KERNEL, "SLICE=%d", slice);
+ parity_event[5] = NULL;
- parity_event[0] = I915_L3_PARITY_UEVENT "=1";
- parity_event[1] = kasprintf(GFP_KERNEL, "ROW=%d", row);
- parity_event[2] = kasprintf(GFP_KERNEL, "BANK=%d", bank);
- parity_event[3] = kasprintf(GFP_KERNEL, "SUBBANK=%d", subbank);
- parity_event[4] = NULL;
+ kobject_uevent_env(&dev_priv->dev->primary->kdev.kobj,
+ KOBJ_CHANGE, parity_event);
- kobject_uevent_env(&dev_priv->dev->primary->kdev.kobj,
- KOBJ_CHANGE, parity_event);
+ DRM_DEBUG("Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n",
+ slice, row, bank, subbank);
+
+ kfree(parity_event[4]);
+ kfree(parity_event[3]);
+ kfree(parity_event[2]);
+ kfree(parity_event[1]);
+ }
+
+ I915_WRITE(GEN7_MISCCPCTL, misccpctl);
- DRM_DEBUG("Parity error: Row = %d, Bank = %d, Sub bank = %d.\n",
- row, bank, subbank);
+out:
+ WARN_ON(dev_priv->l3_parity.which_slice);
+ spin_lock_irqsave(&dev_priv->irq_lock, flags);
+ ilk_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv->dev));
+ spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
- kfree(parity_event[3]);
- kfree(parity_event[2]);
- kfree(parity_event[1]);
+ mutex_unlock(&dev_priv->dev->struct_mutex);
}
-static void ivybridge_parity_error_irq_handler(struct drm_device *dev)
+static void ivybridge_parity_error_irq_handler(struct drm_device *dev, u32 iir)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- if (!HAS_L3_GPU_CACHE(dev))
+ if (!HAS_L3_DPF(dev))
return;
spin_lock(&dev_priv->irq_lock);
- ilk_disable_gt_irq(dev_priv, GT_RENDER_L3_PARITY_ERROR_INTERRUPT);
+ ilk_disable_gt_irq(dev_priv, GT_PARITY_ERROR(dev));
spin_unlock(&dev_priv->irq_lock);
+ iir &= GT_PARITY_ERROR(dev);
+ if (iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1)
+ dev_priv->l3_parity.which_slice |= 1 << 1;
+
+ if (iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT)
+ dev_priv->l3_parity.which_slice |= 1 << 0;
+
queue_work(dev_priv->wq, &dev_priv->l3_parity.error_work);
}
@@ -975,8 +1008,8 @@ static void snb_gt_irq_handler(struct drm_device *dev,
i915_handle_error(dev, false);
}
- if (gt_iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT)
- ivybridge_parity_error_irq_handler(dev);
+ if (gt_iir & GT_PARITY_ERROR(dev))
+ ivybridge_parity_error_irq_handler(dev, gt_iir);
}
#define HPD_STORM_DETECT_PERIOD 1000
@@ -1388,7 +1421,6 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u32 de_iir, gt_iir, de_ier, sde_ier = 0;
irqreturn_t ret = IRQ_NONE;
- bool err_int_reenable = false;
atomic_inc(&dev_priv->irq_received);
@@ -1412,17 +1444,6 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
POSTING_READ(SDEIER);
}
- /* On Haswell, also mask ERR_INT because we don't want to risk
- * generating "unclaimed register" interrupts from inside the interrupt
- * handler. */
- if (IS_HASWELL(dev)) {
- spin_lock(&dev_priv->irq_lock);
- err_int_reenable = ~dev_priv->irq_mask & DE_ERR_INT_IVB;
- if (err_int_reenable)
- ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
- spin_unlock(&dev_priv->irq_lock);
- }
-
gt_iir = I915_READ(GTIIR);
if (gt_iir) {
if (INTEL_INFO(dev)->gen >= 6)
@@ -1452,13 +1473,6 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
}
}
- if (err_int_reenable) {
- spin_lock(&dev_priv->irq_lock);
- if (ivb_can_enable_err_int(dev))
- ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
- spin_unlock(&dev_priv->irq_lock);
- }
-
I915_WRITE(DEIER, de_ier);
POSTING_READ(DEIER);
if (!HAS_PCH_NOP(dev)) {
@@ -2021,6 +2035,8 @@ static void i915_hangcheck_elapsed(unsigned long data)
if (ring->hangcheck.seqno == seqno) {
if (ring_idle(ring, seqno)) {
+ ring->hangcheck.action = HANGCHECK_IDLE;
+
if (waitqueue_active(&ring->irq_queue)) {
/* Issue a wake-up to catch stuck h/w. */
DRM_ERROR("Hangcheck timer elapsed... %s idle\n",
@@ -2049,6 +2065,7 @@ static void i915_hangcheck_elapsed(unsigned long data)
acthd);
switch (ring->hangcheck.action) {
+ case HANGCHECK_IDLE:
case HANGCHECK_WAIT:
break;
case HANGCHECK_ACTIVE:
@@ -2064,6 +2081,8 @@ static void i915_hangcheck_elapsed(unsigned long data)
}
}
} else {
+ ring->hangcheck.action = HANGCHECK_ACTIVE;
+
/* Gradually reduce the count so that we catch DoS
* attempts across multiple batches.
*/
@@ -2254,10 +2273,10 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev)
pm_irqs = gt_irqs = 0;
dev_priv->gt_irq_mask = ~0;
- if (HAS_L3_GPU_CACHE(dev)) {
+ if (HAS_L3_DPF(dev)) {
/* L3 parity interrupt is always unmasked. */
- dev_priv->gt_irq_mask = ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
- gt_irqs |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
+ dev_priv->gt_irq_mask = ~GT_PARITY_ERROR(dev);
+ gt_irqs |= GT_PARITY_ERROR(dev);
}
gt_irqs |= GT_RENDER_USER_INTERRUPT;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index c159e1a6810f..00fda45728d7 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -264,6 +264,11 @@
#define MI_SEMAPHORE_SYNC_VVE (1<<16) /* VECS wait for VCS (VEVSYNC) */
#define MI_SEMAPHORE_SYNC_RVE (2<<16) /* VECS wait for RCS (VERSYNC) */
#define MI_SEMAPHORE_SYNC_INVALID (3<<16)
+
+#define MI_PREDICATE_RESULT_2 (0x2214)
+#define LOWER_SLICE_ENABLED (1<<0)
+#define LOWER_SLICE_DISABLED (0<<0)
+
/*
* 3D instructions used by the kernel
*/
@@ -346,6 +351,10 @@
#define IOSF_PORT_PUNIT 0x4
#define IOSF_PORT_NC 0x11
#define IOSF_PORT_DPIO 0x12
+#define IOSF_PORT_GPIO_NC 0x13
+#define IOSF_PORT_CCK 0x14
+#define IOSF_PORT_CCU 0xA9
+#define IOSF_PORT_GPS_CORE 0x48
#define VLV_IOSF_DATA (VLV_DISPLAY_BASE + 0x2104)
#define VLV_IOSF_ADDR (VLV_DISPLAY_BASE + 0x2108)
@@ -372,6 +381,38 @@
#define FB_FMAX_VMIN_FREQ_LO_SHIFT 27
#define FB_FMAX_VMIN_FREQ_LO_MASK 0xf8000000
+/* vlv2 north clock has */
+#define CCK_REG_DSI_PLL_FUSE 0x44
+#define CCK_REG_DSI_PLL_CONTROL 0x48
+#define DSI_PLL_VCO_EN (1 << 31)
+#define DSI_PLL_LDO_GATE (1 << 30)
+#define DSI_PLL_P1_POST_DIV_SHIFT 17
+#define DSI_PLL_P1_POST_DIV_MASK (0x1ff << 17)
+#define DSI_PLL_P2_MUX_DSI0_DIV2 (1 << 13)
+#define DSI_PLL_P3_MUX_DSI1_DIV2 (1 << 12)
+#define DSI_PLL_MUX_MASK (3 << 9)
+#define DSI_PLL_MUX_DSI0_DSIPLL (0 << 10)
+#define DSI_PLL_MUX_DSI0_CCK (1 << 10)
+#define DSI_PLL_MUX_DSI1_DSIPLL (0 << 9)
+#define DSI_PLL_MUX_DSI1_CCK (1 << 9)
+#define DSI_PLL_CLK_GATE_MASK (0xf << 5)
+#define DSI_PLL_CLK_GATE_DSI0_DSIPLL (1 << 8)
+#define DSI_PLL_CLK_GATE_DSI1_DSIPLL (1 << 7)
+#define DSI_PLL_CLK_GATE_DSI0_CCK (1 << 6)
+#define DSI_PLL_CLK_GATE_DSI1_CCK (1 << 5)
+#define DSI_PLL_LOCK (1 << 0)
+#define CCK_REG_DSI_PLL_DIVIDER 0x4c
+#define DSI_PLL_LFSR (1 << 31)
+#define DSI_PLL_FRACTION_EN (1 << 30)
+#define DSI_PLL_FRAC_COUNTER_SHIFT 27
+#define DSI_PLL_FRAC_COUNTER_MASK (7 << 27)
+#define DSI_PLL_USYNC_CNT_SHIFT 18
+#define DSI_PLL_USYNC_CNT_MASK (0x1ff << 18)
+#define DSI_PLL_N1_DIV_SHIFT 16
+#define DSI_PLL_N1_DIV_MASK (3 << 16)
+#define DSI_PLL_M1_DIV_SHIFT 0
+#define DSI_PLL_M1_DIV_MASK (0x1ff << 0)
+
/*
* DPIO - a special bus for various display related registers to hide behind
*
@@ -886,6 +927,7 @@
#define GT_BLT_USER_INTERRUPT (1 << 22)
#define GT_BSD_CS_ERROR_INTERRUPT (1 << 15)
#define GT_BSD_USER_INTERRUPT (1 << 12)
+#define GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 (1 << 11) /* hsw+; rsvd on snb, ivb, vlv */
#define GT_RENDER_L3_PARITY_ERROR_INTERRUPT (1 << 5) /* !snb */
#define GT_RENDER_PIPECTL_NOTIFY_INTERRUPT (1 << 4)
#define GT_RENDER_CS_MASTER_ERROR_INTERRUPT (1 << 3)
@@ -896,6 +938,10 @@
#define PM_VEBOX_CS_ERROR_INTERRUPT (1 << 12) /* hsw+ */
#define PM_VEBOX_USER_INTERRUPT (1 << 10) /* hsw+ */
+#define GT_PARITY_ERROR(dev) \
+ (GT_RENDER_L3_PARITY_ERROR_INTERRUPT | \
+ (IS_HASWELL(dev) ? GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 : 0))
+
/* These are all the "old" interrupts */
#define ILK_BSD_USER_INTERRUPT (1<<5)
#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18)
@@ -1400,6 +1446,8 @@
* device 0 function 0's pci config register 0x44 or 0x48 and matches it in
* every way. It is not accessible from the CP register read instructions.
*
+ * Starting from Haswell, you can't write registers using the MCHBAR mirror,
+ * just read.
*/
#define MCHBAR_MIRROR_BASE 0x10000
@@ -1800,7 +1848,8 @@
#define VSYNCSHIFT(trans) _TRANSCODER(trans, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
/* HSW eDP PSR registers */
-#define EDP_PSR_CTL 0x64800
+#define EDP_PSR_BASE(dev) 0x64800
+#define EDP_PSR_CTL(dev) (EDP_PSR_BASE(dev) + 0)
#define EDP_PSR_ENABLE (1<<31)
#define EDP_PSR_LINK_DISABLE (0<<27)
#define EDP_PSR_LINK_STANDBY (1<<27)
@@ -1823,16 +1872,16 @@
#define EDP_PSR_TP1_TIME_0us (3<<4)
#define EDP_PSR_IDLE_FRAME_SHIFT 0
-#define EDP_PSR_AUX_CTL 0x64810
-#define EDP_PSR_AUX_DATA1 0x64814
+#define EDP_PSR_AUX_CTL(dev) (EDP_PSR_BASE(dev) + 0x10)
+#define EDP_PSR_AUX_DATA1(dev) (EDP_PSR_BASE(dev) + 0x14)
#define EDP_PSR_DPCD_COMMAND 0x80060000
-#define EDP_PSR_AUX_DATA2 0x64818
+#define EDP_PSR_AUX_DATA2(dev) (EDP_PSR_BASE(dev) + 0x18)
#define EDP_PSR_DPCD_NORMAL_OPERATION (1<<24)
-#define EDP_PSR_AUX_DATA3 0x6481c
-#define EDP_PSR_AUX_DATA4 0x64820
-#define EDP_PSR_AUX_DATA5 0x64824
+#define EDP_PSR_AUX_DATA3(dev) (EDP_PSR_BASE(dev) + 0x1c)
+#define EDP_PSR_AUX_DATA4(dev) (EDP_PSR_BASE(dev) + 0x20)
+#define EDP_PSR_AUX_DATA5(dev) (EDP_PSR_BASE(dev) + 0x24)
-#define EDP_PSR_STATUS_CTL 0x64840
+#define EDP_PSR_STATUS_CTL(dev) (EDP_PSR_BASE(dev) + 0x40)
#define EDP_PSR_STATUS_STATE_MASK (7<<29)
#define EDP_PSR_STATUS_STATE_IDLE (0<<29)
#define EDP_PSR_STATUS_STATE_SRDONACK (1<<29)
@@ -1856,10 +1905,10 @@
#define EDP_PSR_STATUS_SENDING_TP1 (1<<4)
#define EDP_PSR_STATUS_IDLE_MASK 0xf
-#define EDP_PSR_PERF_CNT 0x64844
+#define EDP_PSR_PERF_CNT(dev) (EDP_PSR_BASE(dev) + 0x44)
#define EDP_PSR_PERF_CNT_MASK 0xffffff
-#define EDP_PSR_DEBUG_CTL 0x64860
+#define EDP_PSR_DEBUG_CTL(dev) (EDP_PSR_BASE(dev) + 0x60)
#define EDP_PSR_DEBUG_MASK_LPSP (1<<27)
#define EDP_PSR_DEBUG_MASK_MEMUP (1<<26)
#define EDP_PSR_DEBUG_MASK_HPD (1<<25)
@@ -2030,6 +2079,7 @@
/* Gen 4 SDVO/HDMI bits: */
#define SDVO_COLOR_FORMAT_8bpc (0 << 26)
+#define SDVO_COLOR_FORMAT_MASK (7 << 26)
#define SDVO_ENCODING_SDVO (0 << 10)
#define SDVO_ENCODING_HDMI (2 << 10)
#define HDMI_MODE_SELECT_HDMI (1 << 9) /* HDMI only */
@@ -2982,6 +3032,7 @@
#define PIPECONF_DISABLE 0
#define PIPECONF_DOUBLE_WIDE (1<<30)
#define I965_PIPECONF_ACTIVE (1<<30)
+#define PIPECONF_DSI_PLL_LOCKED (1<<29) /* vlv & pipe A only */
#define PIPECONF_FRAME_START_DELAY_MASK (3<<27)
#define PIPECONF_SINGLE_WIDE 0
#define PIPECONF_PIPE_UNLOCKED 0
@@ -4407,6 +4458,8 @@
#define PIPEA_PP_STATUS (VLV_DISPLAY_BASE + 0x61200)
#define PIPEA_PP_CONTROL (VLV_DISPLAY_BASE + 0x61204)
#define PIPEA_PP_ON_DELAYS (VLV_DISPLAY_BASE + 0x61208)
+#define PANEL_PORT_SELECT_DPB_VLV (1 << 30)
+#define PANEL_PORT_SELECT_DPC_VLV (2 << 30)
#define PIPEA_PP_OFF_DELAYS (VLV_DISPLAY_BASE + 0x6120c)
#define PIPEA_PP_DIVISOR (VLV_DISPLAY_BASE + 0x61210)
@@ -4438,7 +4491,6 @@
#define PANEL_PORT_SELECT_MASK (3 << 30)
#define PANEL_PORT_SELECT_LVDS (0 << 30)
#define PANEL_PORT_SELECT_DPA (1 << 30)
-#define EDP_PANEL (1 << 30)
#define PANEL_PORT_SELECT_DPC (2 << 30)
#define PANEL_PORT_SELECT_DPD (3 << 30)
#define PANEL_POWER_UP_DELAY_MASK (0x1fff0000)
@@ -4447,11 +4499,6 @@
#define PANEL_LIGHT_ON_DELAY_SHIFT 0
#define PCH_PP_OFF_DELAYS 0xc720c
-#define PANEL_POWER_PORT_SELECT_MASK (0x3 << 30)
-#define PANEL_POWER_PORT_LVDS (0 << 30)
-#define PANEL_POWER_PORT_DP_A (1 << 30)
-#define PANEL_POWER_PORT_DP_C (2 << 30)
-#define PANEL_POWER_PORT_DP_D (3 << 30)
#define PANEL_POWER_DOWN_DELAY_MASK (0x1fff0000)
#define PANEL_POWER_DOWN_DELAY_SHIFT 16
#define PANEL_LIGHT_OFF_DELAY_MASK (0x1fff)
@@ -4685,6 +4732,8 @@
#define GEN6_PCODE_READ_MIN_FREQ_TABLE 0x9
#define GEN6_PCODE_WRITE_RC6VIDS 0x4
#define GEN6_PCODE_READ_RC6VIDS 0x5
+#define GEN6_PCODE_READ_D_COMP 0x10
+#define GEN6_PCODE_WRITE_D_COMP 0x11
#define GEN6_ENCODE_RC6_VID(mv) (((mv) - 245) / 5)
#define GEN6_DECODE_RC6_VID(vids) (((vids) * 5) + 245)
#define GEN6_PCODE_DATA 0x138128
@@ -4704,6 +4753,7 @@
/* IVYBRIDGE DPF */
#define GEN7_L3CDERRST1 0xB008 /* L3CD Error Status 1 */
+#define HSW_L3CDERRST11 0xB208 /* L3CD Error Status register 1 slice 1 */
#define GEN7_L3CDERRST1_ROW_MASK (0x7ff<<14)
#define GEN7_PARITY_ERROR_VALID (1<<13)
#define GEN7_L3CDERRST1_BANK_MASK (3<<11)
@@ -4717,6 +4767,7 @@
#define GEN7_L3CDERRST1_ENABLE (1<<7)
#define GEN7_L3LOG_BASE 0xB070
+#define HSW_L3LOG_BASE_SLICE1 0xB270
#define GEN7_L3LOG_SIZE 0x80
#define GEN7_HALF_SLICE_CHICKEN1 0xe100 /* IVB GT1 + VLV */
@@ -5116,4 +5167,414 @@
#define PIPE_CSC_POSTOFF_ME(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_ME, _PIPE_B_CSC_POSTOFF_ME)
#define PIPE_CSC_POSTOFF_LO(pipe) _PIPE(pipe, _PIPE_A_CSC_POSTOFF_LO, _PIPE_B_CSC_POSTOFF_LO)
+/* VLV MIPI registers */
+
+#define _MIPIA_PORT_CTRL (VLV_DISPLAY_BASE + 0x61190)
+#define _MIPIB_PORT_CTRL (VLV_DISPLAY_BASE + 0x61700)
+#define MIPI_PORT_CTRL(pipe) _PIPE(pipe, _MIPIA_PORT_CTRL, _MIPIB_PORT_CTRL)
+#define DPI_ENABLE (1 << 31) /* A + B */
+#define MIPIA_MIPI4DPHY_DELAY_COUNT_SHIFT 27
+#define MIPIA_MIPI4DPHY_DELAY_COUNT_MASK (0xf << 27)
+#define DUAL_LINK_MODE_MASK (1 << 26)
+#define DUAL_LINK_MODE_FRONT_BACK (0 << 26)
+#define DUAL_LINK_MODE_PIXEL_ALTERNATIVE (1 << 26)
+#define DITHERING_ENABLE (1 << 25) /* A + B */
+#define FLOPPED_HSTX (1 << 23)
+#define DE_INVERT (1 << 19) /* XXX */
+#define MIPIA_FLISDSI_DELAY_COUNT_SHIFT 18
+#define MIPIA_FLISDSI_DELAY_COUNT_MASK (0xf << 18)
+#define AFE_LATCHOUT (1 << 17)
+#define LP_OUTPUT_HOLD (1 << 16)
+#define MIPIB_FLISDSI_DELAY_COUNT_HIGH_SHIFT 15
+#define MIPIB_FLISDSI_DELAY_COUNT_HIGH_MASK (1 << 15)
+#define MIPIB_MIPI4DPHY_DELAY_COUNT_SHIFT 11
+#define MIPIB_MIPI4DPHY_DELAY_COUNT_MASK (0xf << 11)
+#define CSB_SHIFT 9
+#define CSB_MASK (3 << 9)
+#define CSB_20MHZ (0 << 9)
+#define CSB_10MHZ (1 << 9)
+#define CSB_40MHZ (2 << 9)
+#define BANDGAP_MASK (1 << 8)
+#define BANDGAP_PNW_CIRCUIT (0 << 8)
+#define BANDGAP_LNC_CIRCUIT (1 << 8)
+#define MIPIB_FLISDSI_DELAY_COUNT_LOW_SHIFT 5
+#define MIPIB_FLISDSI_DELAY_COUNT_LOW_MASK (7 << 5)
+#define TEARING_EFFECT_DELAY (1 << 4) /* A + B */
+#define TEARING_EFFECT_SHIFT 2 /* A + B */
+#define TEARING_EFFECT_MASK (3 << 2)
+#define TEARING_EFFECT_OFF (0 << 2)
+#define TEARING_EFFECT_DSI (1 << 2)
+#define TEARING_EFFECT_GPIO (2 << 2)
+#define LANE_CONFIGURATION_SHIFT 0
+#define LANE_CONFIGURATION_MASK (3 << 0)
+#define LANE_CONFIGURATION_4LANE (0 << 0)
+#define LANE_CONFIGURATION_DUAL_LINK_A (1 << 0)
+#define LANE_CONFIGURATION_DUAL_LINK_B (2 << 0)
+
+#define _MIPIA_TEARING_CTRL (VLV_DISPLAY_BASE + 0x61194)
+#define _MIPIB_TEARING_CTRL (VLV_DISPLAY_BASE + 0x61704)
+#define MIPI_TEARING_CTRL(pipe) _PIPE(pipe, _MIPIA_TEARING_CTRL, _MIPIB_TEARING_CTRL)
+#define TEARING_EFFECT_DELAY_SHIFT 0
+#define TEARING_EFFECT_DELAY_MASK (0xffff << 0)
+
+/* XXX: all bits reserved */
+#define _MIPIA_AUTOPWG (VLV_DISPLAY_BASE + 0x611a0)
+
+/* MIPI DSI Controller and D-PHY registers */
+
+#define _MIPIA_DEVICE_READY (VLV_DISPLAY_BASE + 0xb000)
+#define _MIPIB_DEVICE_READY (VLV_DISPLAY_BASE + 0xb800)
+#define MIPI_DEVICE_READY(pipe) _PIPE(pipe, _MIPIA_DEVICE_READY, _MIPIB_DEVICE_READY)
+#define BUS_POSSESSION (1 << 3) /* set to give bus to receiver */
+#define ULPS_STATE_MASK (3 << 1)
+#define ULPS_STATE_ENTER (2 << 1)
+#define ULPS_STATE_EXIT (1 << 1)
+#define ULPS_STATE_NORMAL_OPERATION (0 << 1)
+#define DEVICE_READY (1 << 0)
+
+#define _MIPIA_INTR_STAT (VLV_DISPLAY_BASE + 0xb004)
+#define _MIPIB_INTR_STAT (VLV_DISPLAY_BASE + 0xb804)
+#define MIPI_INTR_STAT(pipe) _PIPE(pipe, _MIPIA_INTR_STAT, _MIPIB_INTR_STAT)
+#define _MIPIA_INTR_EN (VLV_DISPLAY_BASE + 0xb008)
+#define _MIPIB_INTR_EN (VLV_DISPLAY_BASE + 0xb808)
+#define MIPI_INTR_EN(pipe) _PIPE(pipe, _MIPIA_INTR_EN, _MIPIB_INTR_EN)
+#define TEARING_EFFECT (1 << 31)
+#define SPL_PKT_SENT_INTERRUPT (1 << 30)
+#define GEN_READ_DATA_AVAIL (1 << 29)
+#define LP_GENERIC_WR_FIFO_FULL (1 << 28)
+#define HS_GENERIC_WR_FIFO_FULL (1 << 27)
+#define RX_PROT_VIOLATION (1 << 26)
+#define RX_INVALID_TX_LENGTH (1 << 25)
+#define ACK_WITH_NO_ERROR (1 << 24)
+#define TURN_AROUND_ACK_TIMEOUT (1 << 23)
+#define LP_RX_TIMEOUT (1 << 22)
+#define HS_TX_TIMEOUT (1 << 21)
+#define DPI_FIFO_UNDERRUN (1 << 20)
+#define LOW_CONTENTION (1 << 19)
+#define HIGH_CONTENTION (1 << 18)
+#define TXDSI_VC_ID_INVALID (1 << 17)
+#define TXDSI_DATA_TYPE_NOT_RECOGNISED (1 << 16)
+#define TXCHECKSUM_ERROR (1 << 15)
+#define TXECC_MULTIBIT_ERROR (1 << 14)
+#define TXECC_SINGLE_BIT_ERROR (1 << 13)
+#define TXFALSE_CONTROL_ERROR (1 << 12)
+#define RXDSI_VC_ID_INVALID (1 << 11)
+#define RXDSI_DATA_TYPE_NOT_REGOGNISED (1 << 10)
+#define RXCHECKSUM_ERROR (1 << 9)
+#define RXECC_MULTIBIT_ERROR (1 << 8)
+#define RXECC_SINGLE_BIT_ERROR (1 << 7)
+#define RXFALSE_CONTROL_ERROR (1 << 6)
+#define RXHS_RECEIVE_TIMEOUT_ERROR (1 << 5)
+#define RX_LP_TX_SYNC_ERROR (1 << 4)
+#define RXEXCAPE_MODE_ENTRY_ERROR (1 << 3)
+#define RXEOT_SYNC_ERROR (1 << 2)
+#define RXSOT_SYNC_ERROR (1 << 1)
+#define RXSOT_ERROR (1 << 0)
+
+#define _MIPIA_DSI_FUNC_PRG (VLV_DISPLAY_BASE + 0xb00c)
+#define _MIPIB_DSI_FUNC_PRG (VLV_DISPLAY_BASE + 0xb80c)
+#define MIPI_DSI_FUNC_PRG(pipe) _PIPE(pipe, _MIPIA_DSI_FUNC_PRG, _MIPIB_DSI_FUNC_PRG)
+#define CMD_MODE_DATA_WIDTH_MASK (7 << 13)
+#define CMD_MODE_NOT_SUPPORTED (0 << 13)
+#define CMD_MODE_DATA_WIDTH_16_BIT (1 << 13)
+#define CMD_MODE_DATA_WIDTH_9_BIT (2 << 13)
+#define CMD_MODE_DATA_WIDTH_8_BIT (3 << 13)
+#define CMD_MODE_DATA_WIDTH_OPTION1 (4 << 13)
+#define CMD_MODE_DATA_WIDTH_OPTION2 (5 << 13)
+#define VID_MODE_FORMAT_MASK (0xf << 7)
+#define VID_MODE_NOT_SUPPORTED (0 << 7)
+#define VID_MODE_FORMAT_RGB565 (1 << 7)
+#define VID_MODE_FORMAT_RGB666 (2 << 7)
+#define VID_MODE_FORMAT_RGB666_LOOSE (3 << 7)
+#define VID_MODE_FORMAT_RGB888 (4 << 7)
+#define CMD_MODE_CHANNEL_NUMBER_SHIFT 5
+#define CMD_MODE_CHANNEL_NUMBER_MASK (3 << 5)
+#define VID_MODE_CHANNEL_NUMBER_SHIFT 3
+#define VID_MODE_CHANNEL_NUMBER_MASK (3 << 3)
+#define DATA_LANES_PRG_REG_SHIFT 0
+#define DATA_LANES_PRG_REG_MASK (7 << 0)
+
+#define _MIPIA_HS_TX_TIMEOUT (VLV_DISPLAY_BASE + 0xb010)
+#define _MIPIB_HS_TX_TIMEOUT (VLV_DISPLAY_BASE + 0xb810)
+#define MIPI_HS_TX_TIMEOUT(pipe) _PIPE(pipe, _MIPIA_HS_TX_TIMEOUT, _MIPIB_HS_TX_TIMEOUT)
+#define HIGH_SPEED_TX_TIMEOUT_COUNTER_MASK 0xffffff
+
+#define _MIPIA_LP_RX_TIMEOUT (VLV_DISPLAY_BASE + 0xb014)
+#define _MIPIB_LP_RX_TIMEOUT (VLV_DISPLAY_BASE + 0xb814)
+#define MIPI_LP_RX_TIMEOUT(pipe) _PIPE(pipe, _MIPIA_LP_RX_TIMEOUT, _MIPIB_LP_RX_TIMEOUT)
+#define LOW_POWER_RX_TIMEOUT_COUNTER_MASK 0xffffff
+
+#define _MIPIA_TURN_AROUND_TIMEOUT (VLV_DISPLAY_BASE + 0xb018)
+#define _MIPIB_TURN_AROUND_TIMEOUT (VLV_DISPLAY_BASE + 0xb818)
+#define MIPI_TURN_AROUND_TIMEOUT(pipe) _PIPE(pipe, _MIPIA_TURN_AROUND_TIMEOUT, _MIPIB_TURN_AROUND_TIMEOUT)
+#define TURN_AROUND_TIMEOUT_MASK 0x3f
+
+#define _MIPIA_DEVICE_RESET_TIMER (VLV_DISPLAY_BASE + 0xb01c)
+#define _MIPIB_DEVICE_RESET_TIMER (VLV_DISPLAY_BASE + 0xb81c)
+#define MIPI_DEVICE_RESET_TIMER(pipe) _PIPE(pipe, _MIPIA_DEVICE_RESET_TIMER, _MIPIB_DEVICE_RESET_TIMER)
+#define DEVICE_RESET_TIMER_MASK 0xffff
+
+#define _MIPIA_DPI_RESOLUTION (VLV_DISPLAY_BASE + 0xb020)
+#define _MIPIB_DPI_RESOLUTION (VLV_DISPLAY_BASE + 0xb820)
+#define MIPI_DPI_RESOLUTION(pipe) _PIPE(pipe, _MIPIA_DPI_RESOLUTION, _MIPIB_DPI_RESOLUTION)
+#define VERTICAL_ADDRESS_SHIFT 16
+#define VERTICAL_ADDRESS_MASK (0xffff << 16)
+#define HORIZONTAL_ADDRESS_SHIFT 0
+#define HORIZONTAL_ADDRESS_MASK 0xffff
+
+#define _MIPIA_DBI_FIFO_THROTTLE (VLV_DISPLAY_BASE + 0xb024)
+#define _MIPIB_DBI_FIFO_THROTTLE (VLV_DISPLAY_BASE + 0xb824)
+#define MIPI_DBI_FIFO_THROTTLE(pipe) _PIPE(pipe, _MIPIA_DBI_FIFO_THROTTLE, _MIPIB_DBI_FIFO_THROTTLE)
+#define DBI_FIFO_EMPTY_HALF (0 << 0)
+#define DBI_FIFO_EMPTY_QUARTER (1 << 0)
+#define DBI_FIFO_EMPTY_7_LOCATIONS (2 << 0)
+
+/* regs below are bits 15:0 */
+#define _MIPIA_HSYNC_PADDING_COUNT (VLV_DISPLAY_BASE + 0xb028)
+#define _MIPIB_HSYNC_PADDING_COUNT (VLV_DISPLAY_BASE + 0xb828)
+#define MIPI_HSYNC_PADDING_COUNT(pipe) _PIPE(pipe, _MIPIA_HSYNC_PADDING_COUNT, _MIPIB_HSYNC_PADDING_COUNT)
+
+#define _MIPIA_HBP_COUNT (VLV_DISPLAY_BASE + 0xb02c)
+#define _MIPIB_HBP_COUNT (VLV_DISPLAY_BASE + 0xb82c)
+#define MIPI_HBP_COUNT(pipe) _PIPE(pipe, _MIPIA_HBP_COUNT, _MIPIB_HBP_COUNT)
+
+#define _MIPIA_HFP_COUNT (VLV_DISPLAY_BASE + 0xb030)
+#define _MIPIB_HFP_COUNT (VLV_DISPLAY_BASE + 0xb830)
+#define MIPI_HFP_COUNT(pipe) _PIPE(pipe, _MIPIA_HFP_COUNT, _MIPIB_HFP_COUNT)
+
+#define _MIPIA_HACTIVE_AREA_COUNT (VLV_DISPLAY_BASE + 0xb034)
+#define _MIPIB_HACTIVE_AREA_COUNT (VLV_DISPLAY_BASE + 0xb834)
+#define MIPI_HACTIVE_AREA_COUNT(pipe) _PIPE(pipe, _MIPIA_HACTIVE_AREA_COUNT, _MIPIB_HACTIVE_AREA_COUNT)
+
+#define _MIPIA_VSYNC_PADDING_COUNT (VLV_DISPLAY_BASE + 0xb038)
+#define _MIPIB_VSYNC_PADDING_COUNT (VLV_DISPLAY_BASE + 0xb838)
+#define MIPI_VSYNC_PADDING_COUNT(pipe) _PIPE(pipe, _MIPIA_VSYNC_PADDING_COUNT, _MIPIB_VSYNC_PADDING_COUNT)
+
+#define _MIPIA_VBP_COUNT (VLV_DISPLAY_BASE + 0xb03c)
+#define _MIPIB_VBP_COUNT (VLV_DISPLAY_BASE + 0xb83c)
+#define MIPI_VBP_COUNT(pipe) _PIPE(pipe, _MIPIA_VBP_COUNT, _MIPIB_VBP_COUNT)
+
+#define _MIPIA_VFP_COUNT (VLV_DISPLAY_BASE + 0xb040)
+#define _MIPIB_VFP_COUNT (VLV_DISPLAY_BASE + 0xb840)
+#define MIPI_VFP_COUNT(pipe) _PIPE(pipe, _MIPIA_VFP_COUNT, _MIPIB_VFP_COUNT)
+
+#define _MIPIA_HIGH_LOW_SWITCH_COUNT (VLV_DISPLAY_BASE + 0xb044)
+#define _MIPIB_HIGH_LOW_SWITCH_COUNT (VLV_DISPLAY_BASE + 0xb844)
+#define MIPI_HIGH_LOW_SWITCH_COUNT(pipe) _PIPE(pipe, _MIPIA_HIGH_LOW_SWITCH_COUNT, _MIPIB_HIGH_LOW_SWITCH_COUNT)
+/* regs above are bits 15:0 */
+
+#define _MIPIA_DPI_CONTROL (VLV_DISPLAY_BASE + 0xb048)
+#define _MIPIB_DPI_CONTROL (VLV_DISPLAY_BASE + 0xb848)
+#define MIPI_DPI_CONTROL(pipe) _PIPE(pipe, _MIPIA_DPI_CONTROL, _MIPIB_DPI_CONTROL)
+#define DPI_LP_MODE (1 << 6)
+#define BACKLIGHT_OFF (1 << 5)
+#define BACKLIGHT_ON (1 << 4)
+#define COLOR_MODE_OFF (1 << 3)
+#define COLOR_MODE_ON (1 << 2)
+#define TURN_ON (1 << 1)
+#define SHUTDOWN (1 << 0)
+
+#define _MIPIA_DPI_DATA (VLV_DISPLAY_BASE + 0xb04c)
+#define _MIPIB_DPI_DATA (VLV_DISPLAY_BASE + 0xb84c)
+#define MIPI_DPI_DATA(pipe) _PIPE(pipe, _MIPIA_DPI_DATA, _MIPIB_DPI_DATA)
+#define COMMAND_BYTE_SHIFT 0
+#define COMMAND_BYTE_MASK (0x3f << 0)
+
+#define _MIPIA_INIT_COUNT (VLV_DISPLAY_BASE + 0xb050)
+#define _MIPIB_INIT_COUNT (VLV_DISPLAY_BASE + 0xb850)
+#define MIPI_INIT_COUNT(pipe) _PIPE(pipe, _MIPIA_INIT_COUNT, _MIPIB_INIT_COUNT)
+#define MASTER_INIT_TIMER_SHIFT 0
+#define MASTER_INIT_TIMER_MASK (0xffff << 0)
+
+#define _MIPIA_MAX_RETURN_PKT_SIZE (VLV_DISPLAY_BASE + 0xb054)
+#define _MIPIB_MAX_RETURN_PKT_SIZE (VLV_DISPLAY_BASE + 0xb854)
+#define MIPI_MAX_RETURN_PKT_SIZE(pipe) _PIPE(pipe, _MIPIA_MAX_RETURN_PKT_SIZE, _MIPIB_MAX_RETURN_PKT_SIZE)
+#define MAX_RETURN_PKT_SIZE_SHIFT 0
+#define MAX_RETURN_PKT_SIZE_MASK (0x3ff << 0)
+
+#define _MIPIA_VIDEO_MODE_FORMAT (VLV_DISPLAY_BASE + 0xb058)
+#define _MIPIB_VIDEO_MODE_FORMAT (VLV_DISPLAY_BASE + 0xb858)
+#define MIPI_VIDEO_MODE_FORMAT(pipe) _PIPE(pipe, _MIPIA_VIDEO_MODE_FORMAT, _MIPIB_VIDEO_MODE_FORMAT)
+#define RANDOM_DPI_DISPLAY_RESOLUTION (1 << 4)
+#define DISABLE_VIDEO_BTA (1 << 3)
+#define IP_TG_CONFIG (1 << 2)
+#define VIDEO_MODE_NON_BURST_WITH_SYNC_PULSE (1 << 0)
+#define VIDEO_MODE_NON_BURST_WITH_SYNC_EVENTS (2 << 0)
+#define VIDEO_MODE_BURST (3 << 0)
+
+#define _MIPIA_EOT_DISABLE (VLV_DISPLAY_BASE + 0xb05c)
+#define _MIPIB_EOT_DISABLE (VLV_DISPLAY_BASE + 0xb85c)
+#define MIPI_EOT_DISABLE(pipe) _PIPE(pipe, _MIPIA_EOT_DISABLE, _MIPIB_EOT_DISABLE)
+#define LP_RX_TIMEOUT_ERROR_RECOVERY_DISABLE (1 << 7)
+#define HS_RX_TIMEOUT_ERROR_RECOVERY_DISABLE (1 << 6)
+#define LOW_CONTENTION_RECOVERY_DISABLE (1 << 5)
+#define HIGH_CONTENTION_RECOVERY_DISABLE (1 << 4)
+#define TXDSI_TYPE_NOT_RECOGNISED_ERROR_RECOVERY_DISABLE (1 << 3)
+#define TXECC_MULTIBIT_ERROR_RECOVERY_DISABLE (1 << 2)
+#define CLOCKSTOP (1 << 1)
+#define EOT_DISABLE (1 << 0)
+
+#define _MIPIA_LP_BYTECLK (VLV_DISPLAY_BASE + 0xb060)
+#define _MIPIB_LP_BYTECLK (VLV_DISPLAY_BASE + 0xb860)
+#define MIPI_LP_BYTECLK(pipe) _PIPE(pipe, _MIPIA_LP_BYTECLK, _MIPIB_LP_BYTECLK)
+#define LP_BYTECLK_SHIFT 0
+#define LP_BYTECLK_MASK (0xffff << 0)
+
+/* bits 31:0 */
+#define _MIPIA_LP_GEN_DATA (VLV_DISPLAY_BASE + 0xb064)
+#define _MIPIB_LP_GEN_DATA (VLV_DISPLAY_BASE + 0xb864)
+#define MIPI_LP_GEN_DATA(pipe) _PIPE(pipe, _MIPIA_LP_GEN_DATA, _MIPIB_LP_GEN_DATA)
+
+/* bits 31:0 */
+#define _MIPIA_HS_GEN_DATA (VLV_DISPLAY_BASE + 0xb068)
+#define _MIPIB_HS_GEN_DATA (VLV_DISPLAY_BASE + 0xb868)
+#define MIPI_HS_GEN_DATA(pipe) _PIPE(pipe, _MIPIA_HS_GEN_DATA, _MIPIB_HS_GEN_DATA)
+
+#define _MIPIA_LP_GEN_CTRL (VLV_DISPLAY_BASE + 0xb06c)
+#define _MIPIB_LP_GEN_CTRL (VLV_DISPLAY_BASE + 0xb86c)
+#define MIPI_LP_GEN_CTRL(pipe) _PIPE(pipe, _MIPIA_LP_GEN_CTRL, _MIPIB_LP_GEN_CTRL)
+#define _MIPIA_HS_GEN_CTRL (VLV_DISPLAY_BASE + 0xb070)
+#define _MIPIB_HS_GEN_CTRL (VLV_DISPLAY_BASE + 0xb870)
+#define MIPI_HS_GEN_CTRL(pipe) _PIPE(pipe, _MIPIA_HS_GEN_CTRL, _MIPIB_HS_GEN_CTRL)
+#define LONG_PACKET_WORD_COUNT_SHIFT 8
+#define LONG_PACKET_WORD_COUNT_MASK (0xffff << 8)
+#define SHORT_PACKET_PARAM_SHIFT 8
+#define SHORT_PACKET_PARAM_MASK (0xffff << 8)
+#define VIRTUAL_CHANNEL_SHIFT 6
+#define VIRTUAL_CHANNEL_MASK (3 << 6)
+#define DATA_TYPE_SHIFT 0
+#define DATA_TYPE_MASK (3f << 0)
+/* data type values, see include/video/mipi_display.h */
+
+#define _MIPIA_GEN_FIFO_STAT (VLV_DISPLAY_BASE + 0xb074)
+#define _MIPIB_GEN_FIFO_STAT (VLV_DISPLAY_BASE + 0xb874)
+#define MIPI_GEN_FIFO_STAT(pipe) _PIPE(pipe, _MIPIA_GEN_FIFO_STAT, _MIPIB_GEN_FIFO_STAT)
+#define DPI_FIFO_EMPTY (1 << 28)
+#define DBI_FIFO_EMPTY (1 << 27)
+#define LP_CTRL_FIFO_EMPTY (1 << 26)
+#define LP_CTRL_FIFO_HALF_EMPTY (1 << 25)
+#define LP_CTRL_FIFO_FULL (1 << 24)
+#define HS_CTRL_FIFO_EMPTY (1 << 18)
+#define HS_CTRL_FIFO_HALF_EMPTY (1 << 17)
+#define HS_CTRL_FIFO_FULL (1 << 16)
+#define LP_DATA_FIFO_EMPTY (1 << 10)
+#define LP_DATA_FIFO_HALF_EMPTY (1 << 9)
+#define LP_DATA_FIFO_FULL (1 << 8)
+#define HS_DATA_FIFO_EMPTY (1 << 2)
+#define HS_DATA_FIFO_HALF_EMPTY (1 << 1)
+#define HS_DATA_FIFO_FULL (1 << 0)
+
+#define _MIPIA_HS_LS_DBI_ENABLE (VLV_DISPLAY_BASE + 0xb078)
+#define _MIPIB_HS_LS_DBI_ENABLE (VLV_DISPLAY_BASE + 0xb878)
+#define MIPI_HS_LP_DBI_ENABLE(pipe) _PIPE(pipe, _MIPIA_HS_LS_DBI_ENABLE, _MIPIB_HS_LS_DBI_ENABLE)
+#define DBI_HS_LP_MODE_MASK (1 << 0)
+#define DBI_LP_MODE (1 << 0)
+#define DBI_HS_MODE (0 << 0)
+
+#define _MIPIA_DPHY_PARAM (VLV_DISPLAY_BASE + 0xb080)
+#define _MIPIB_DPHY_PARAM (VLV_DISPLAY_BASE + 0xb880)
+#define MIPI_DPHY_PARAM(pipe) _PIPE(pipe, _MIPIA_DPHY_PARAM, _MIPIB_DPHY_PARAM)
+#define EXIT_ZERO_COUNT_SHIFT 24
+#define EXIT_ZERO_COUNT_MASK (0x3f << 24)
+#define TRAIL_COUNT_SHIFT 16
+#define TRAIL_COUNT_MASK (0x1f << 16)
+#define CLK_ZERO_COUNT_SHIFT 8
+#define CLK_ZERO_COUNT_MASK (0xff << 8)
+#define PREPARE_COUNT_SHIFT 0
+#define PREPARE_COUNT_MASK (0x3f << 0)
+
+/* bits 31:0 */
+#define _MIPIA_DBI_BW_CTRL (VLV_DISPLAY_BASE + 0xb084)
+#define _MIPIB_DBI_BW_CTRL (VLV_DISPLAY_BASE + 0xb884)
+#define MIPI_DBI_BW_CTRL(pipe) _PIPE(pipe, _MIPIA_DBI_BW_CTRL, _MIPIB_DBI_BW_CTRL)
+
+#define _MIPIA_CLK_LANE_SWITCH_TIME_CNT (VLV_DISPLAY_BASE + 0xb088)
+#define _MIPIB_CLK_LANE_SWITCH_TIME_CNT (VLV_DISPLAY_BASE + 0xb888)
+#define MIPI_CLK_LANE_SWITCH_TIME_CNT(pipe) _PIPE(pipe, _MIPIA_CLK_LANE_SWITCH_TIME_CNT, _MIPIB_CLK_LANE_SWITCH_TIME_CNT)
+#define LP_HS_SSW_CNT_SHIFT 16
+#define LP_HS_SSW_CNT_MASK (0xffff << 16)
+#define HS_LP_PWR_SW_CNT_SHIFT 0
+#define HS_LP_PWR_SW_CNT_MASK (0xffff << 0)
+
+#define _MIPIA_STOP_STATE_STALL (VLV_DISPLAY_BASE + 0xb08c)
+#define _MIPIB_STOP_STATE_STALL (VLV_DISPLAY_BASE + 0xb88c)
+#define MIPI_STOP_STATE_STALL(pipe) _PIPE(pipe, _MIPIA_STOP_STATE_STALL, _MIPIB_STOP_STATE_STALL)
+#define STOP_STATE_STALL_COUNTER_SHIFT 0
+#define STOP_STATE_STALL_COUNTER_MASK (0xff << 0)
+
+#define _MIPIA_INTR_STAT_REG_1 (VLV_DISPLAY_BASE + 0xb090)
+#define _MIPIB_INTR_STAT_REG_1 (VLV_DISPLAY_BASE + 0xb890)
+#define MIPI_INTR_STAT_REG_1(pipe) _PIPE(pipe, _MIPIA_INTR_STAT_REG_1, _MIPIB_INTR_STAT_REG_1)
+#define _MIPIA_INTR_EN_REG_1 (VLV_DISPLAY_BASE + 0xb094)
+#define _MIPIB_INTR_EN_REG_1 (VLV_DISPLAY_BASE + 0xb894)
+#define MIPI_INTR_EN_REG_1(pipe) _PIPE(pipe, _MIPIA_INTR_EN_REG_1, _MIPIB_INTR_EN_REG_1)
+#define RX_CONTENTION_DETECTED (1 << 0)
+
+/* XXX: only pipe A ?!? */
+#define MIPIA_DBI_TYPEC_CTRL (VLV_DISPLAY_BASE + 0xb100)
+#define DBI_TYPEC_ENABLE (1 << 31)
+#define DBI_TYPEC_WIP (1 << 30)
+#define DBI_TYPEC_OPTION_SHIFT 28
+#define DBI_TYPEC_OPTION_MASK (3 << 28)
+#define DBI_TYPEC_FREQ_SHIFT 24
+#define DBI_TYPEC_FREQ_MASK (0xf << 24)
+#define DBI_TYPEC_OVERRIDE (1 << 8)
+#define DBI_TYPEC_OVERRIDE_COUNTER_SHIFT 0
+#define DBI_TYPEC_OVERRIDE_COUNTER_MASK (0xff << 0)
+
+
+/* MIPI adapter registers */
+
+#define _MIPIA_CTRL (VLV_DISPLAY_BASE + 0xb104)
+#define _MIPIB_CTRL (VLV_DISPLAY_BASE + 0xb904)
+#define MIPI_CTRL(pipe) _PIPE(pipe, _MIPIA_CTRL, _MIPIB_CTRL)
+#define ESCAPE_CLOCK_DIVIDER_SHIFT 5 /* A only */
+#define ESCAPE_CLOCK_DIVIDER_MASK (3 << 5)
+#define ESCAPE_CLOCK_DIVIDER_1 (0 << 5)
+#define ESCAPE_CLOCK_DIVIDER_2 (1 << 5)
+#define ESCAPE_CLOCK_DIVIDER_4 (2 << 5)
+#define READ_REQUEST_PRIORITY_SHIFT 3
+#define READ_REQUEST_PRIORITY_MASK (3 << 3)
+#define READ_REQUEST_PRIORITY_LOW (0 << 3)
+#define READ_REQUEST_PRIORITY_HIGH (3 << 3)
+#define RGB_FLIP_TO_BGR (1 << 2)
+
+#define _MIPIA_DATA_ADDRESS (VLV_DISPLAY_BASE + 0xb108)
+#define _MIPIB_DATA_ADDRESS (VLV_DISPLAY_BASE + 0xb908)
+#define MIPI_DATA_ADDRESS(pipe) _PIPE(pipe, _MIPIA_DATA_ADDRESS, _MIPIB_DATA_ADDRESS)
+#define DATA_MEM_ADDRESS_SHIFT 5
+#define DATA_MEM_ADDRESS_MASK (0x7ffffff << 5)
+#define DATA_VALID (1 << 0)
+
+#define _MIPIA_DATA_LENGTH (VLV_DISPLAY_BASE + 0xb10c)
+#define _MIPIB_DATA_LENGTH (VLV_DISPLAY_BASE + 0xb90c)
+#define MIPI_DATA_LENGTH(pipe) _PIPE(pipe, _MIPIA_DATA_LENGTH, _MIPIB_DATA_LENGTH)
+#define DATA_LENGTH_SHIFT 0
+#define DATA_LENGTH_MASK (0xfffff << 0)
+
+#define _MIPIA_COMMAND_ADDRESS (VLV_DISPLAY_BASE + 0xb110)
+#define _MIPIB_COMMAND_ADDRESS (VLV_DISPLAY_BASE + 0xb910)
+#define MIPI_COMMAND_ADDRESS(pipe) _PIPE(pipe, _MIPIA_COMMAND_ADDRESS, _MIPIB_COMMAND_ADDRESS)
+#define COMMAND_MEM_ADDRESS_SHIFT 5
+#define COMMAND_MEM_ADDRESS_MASK (0x7ffffff << 5)
+#define AUTO_PWG_ENABLE (1 << 2)
+#define MEMORY_WRITE_DATA_FROM_PIPE_RENDERING (1 << 1)
+#define COMMAND_VALID (1 << 0)
+
+#define _MIPIA_COMMAND_LENGTH (VLV_DISPLAY_BASE + 0xb114)
+#define _MIPIB_COMMAND_LENGTH (VLV_DISPLAY_BASE + 0xb914)
+#define MIPI_COMMAND_LENGTH(pipe) _PIPE(pipe, _MIPIA_COMMAND_LENGTH, _MIPIB_COMMAND_LENGTH)
+#define COMMAND_LENGTH_SHIFT(n) (8 * (n)) /* n: 0...3 */
+#define COMMAND_LENGTH_MASK(n) (0xff << (8 * (n)))
+
+#define _MIPIA_READ_DATA_RETURN0 (VLV_DISPLAY_BASE + 0xb118)
+#define _MIPIB_READ_DATA_RETURN0 (VLV_DISPLAY_BASE + 0xb918)
+#define MIPI_READ_DATA_RETURN(pipe, n) \
+ (_PIPE(pipe, _MIPIA_READ_DATA_RETURN0, _MIPIB_READ_DATA_RETURN0) + 4 * (n)) /* n: 0...7 */
+
+#define _MIPIA_READ_DATA_VALID (VLV_DISPLAY_BASE + 0xb138)
+#define _MIPIB_READ_DATA_VALID (VLV_DISPLAY_BASE + 0xb938)
+#define MIPI_READ_DATA_VALID(pipe) _PIPE(pipe, _MIPIA_READ_DATA_VALID, _MIPIB_READ_DATA_VALID)
+#define READ_DATA_VALID(n) (1 << (n))
+
#endif /* _I915_REG_H_ */
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 70db618989c4..3538370e3a47 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -340,7 +340,9 @@ int i915_save_state(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
int i;
- pci_read_config_byte(dev->pdev, LBB, &dev_priv->regfile.saveLBB);
+ if (INTEL_INFO(dev)->gen <= 4)
+ pci_read_config_byte(dev->pdev, LBB,
+ &dev_priv->regfile.saveLBB);
mutex_lock(&dev->struct_mutex);
@@ -390,7 +392,9 @@ int i915_restore_state(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
int i;
- pci_write_config_byte(dev->pdev, LBB, dev_priv->regfile.saveLBB);
+ if (INTEL_INFO(dev)->gen <= 4)
+ pci_write_config_byte(dev->pdev, LBB,
+ dev_priv->regfile.saveLBB);
mutex_lock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index c8c4112de110..44f4c1a6f7b1 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -65,6 +65,8 @@ show_rc6p_ms(struct device *kdev, struct device_attribute *attr, char *buf)
{
struct drm_minor *dminor = container_of(kdev, struct drm_minor, kdev);
u32 rc6p_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6p);
+ if (IS_VALLEYVIEW(dminor->dev))
+ rc6p_residency = 0;
return snprintf(buf, PAGE_SIZE, "%u\n", rc6p_residency);
}
@@ -73,6 +75,8 @@ show_rc6pp_ms(struct device *kdev, struct device_attribute *attr, char *buf)
{
struct drm_minor *dminor = container_of(kdev, struct drm_minor, kdev);
u32 rc6pp_residency = calc_residency(dminor->dev, GEN6_GT_GFX_RC6pp);
+ if (IS_VALLEYVIEW(dminor->dev))
+ rc6pp_residency = 0;
return snprintf(buf, PAGE_SIZE, "%u\n", rc6pp_residency);
}
@@ -97,7 +101,7 @@ static struct attribute_group rc6_attr_group = {
static int l3_access_valid(struct drm_device *dev, loff_t offset)
{
- if (!HAS_L3_GPU_CACHE(dev))
+ if (!HAS_L3_DPF(dev))
return -EPERM;
if (offset % 4 != 0)
@@ -118,28 +122,31 @@ i915_l3_read(struct file *filp, struct kobject *kobj,
struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
struct drm_device *drm_dev = dminor->dev;
struct drm_i915_private *dev_priv = drm_dev->dev_private;
- uint32_t misccpctl;
- int i, ret;
+ int slice = (int)(uintptr_t)attr->private;
+ int ret;
+
+ count = round_down(count, 4);
ret = l3_access_valid(drm_dev, offset);
if (ret)
return ret;
+ count = min_t(size_t, GEN7_L3LOG_SIZE - offset, count);
+
ret = i915_mutex_lock_interruptible(drm_dev);
if (ret)
return ret;
- misccpctl = I915_READ(GEN7_MISCCPCTL);
- I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE);
-
- for (i = offset; count >= 4 && i < GEN7_L3LOG_SIZE; i += 4, count -= 4)
- *((uint32_t *)(&buf[i])) = I915_READ(GEN7_L3LOG_BASE + i);
-
- I915_WRITE(GEN7_MISCCPCTL, misccpctl);
+ if (dev_priv->l3_parity.remap_info[slice])
+ memcpy(buf,
+ dev_priv->l3_parity.remap_info[slice] + (offset/4),
+ count);
+ else
+ memset(buf, 0, count);
mutex_unlock(&drm_dev->struct_mutex);
- return i - offset;
+ return count;
}
static ssize_t
@@ -151,18 +158,23 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
struct drm_device *drm_dev = dminor->dev;
struct drm_i915_private *dev_priv = drm_dev->dev_private;
+ struct i915_hw_context *ctx;
u32 *temp = NULL; /* Just here to make handling failures easy */
+ int slice = (int)(uintptr_t)attr->private;
int ret;
ret = l3_access_valid(drm_dev, offset);
if (ret)
return ret;
+ if (dev_priv->hw_contexts_disabled)
+ return -ENXIO;
+
ret = i915_mutex_lock_interruptible(drm_dev);
if (ret)
return ret;
- if (!dev_priv->l3_parity.remap_info) {
+ if (!dev_priv->l3_parity.remap_info[slice]) {
temp = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL);
if (!temp) {
mutex_unlock(&drm_dev->struct_mutex);
@@ -182,13 +194,13 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
* at this point it is left as a TODO.
*/
if (temp)
- dev_priv->l3_parity.remap_info = temp;
+ dev_priv->l3_parity.remap_info[slice] = temp;
- memcpy(dev_priv->l3_parity.remap_info + (offset/4),
- buf + (offset/4),
- count);
+ memcpy(dev_priv->l3_parity.remap_info[slice] + (offset/4), buf, count);
- i915_gem_l3_remap(drm_dev);
+ /* NB: We defer the remapping until we switch to the context */
+ list_for_each_entry(ctx, &dev_priv->context_list, link)
+ ctx->remap_slice |= (1<<slice);
mutex_unlock(&drm_dev->struct_mutex);
@@ -200,7 +212,17 @@ static struct bin_attribute dpf_attrs = {
.size = GEN7_L3LOG_SIZE,
.read = i915_l3_read,
.write = i915_l3_write,
- .mmap = NULL
+ .mmap = NULL,
+ .private = (void *)0
+};
+
+static struct bin_attribute dpf_attrs_1 = {
+ .attr = {.name = "l3_parity_slice_1", .mode = (S_IRUSR | S_IWUSR)},
+ .size = GEN7_L3LOG_SIZE,
+ .read = i915_l3_read,
+ .write = i915_l3_write,
+ .mmap = NULL,
+ .private = (void *)1
};
static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
@@ -507,10 +529,17 @@ void i915_setup_sysfs(struct drm_device *dev)
DRM_ERROR("RC6 residency sysfs setup failed\n");
}
#endif
- if (HAS_L3_GPU_CACHE(dev)) {
+ if (HAS_L3_DPF(dev)) {
ret = device_create_bin_file(&dev->primary->kdev, &dpf_attrs);
if (ret)
DRM_ERROR("l3 parity sysfs setup failed\n");
+
+ if (NUM_L3_SLICES(dev) > 1) {
+ ret = device_create_bin_file(&dev->primary->kdev,
+ &dpf_attrs_1);
+ if (ret)
+ DRM_ERROR("l3 parity slice 1 setup failed\n");
+ }
}
ret = 0;
@@ -534,6 +563,7 @@ void i915_teardown_sysfs(struct drm_device *dev)
sysfs_remove_files(&dev->primary->kdev.kobj, vlv_attrs);
else
sysfs_remove_files(&dev->primary->kdev.kobj, gen6_attrs);
+ device_remove_bin_file(&dev->primary->kdev, &dpf_attrs_1);
device_remove_bin_file(&dev->primary->kdev, &dpf_attrs);
#ifdef CONFIG_PM
sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group);
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index e2c5ee6f6194..6e580c98dede 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -233,6 +233,47 @@ TRACE_EVENT(i915_gem_evict_everything,
TP_printk("dev=%d", __entry->dev)
);
+TRACE_EVENT(i915_gem_evict_vm,
+ TP_PROTO(struct i915_address_space *vm),
+ TP_ARGS(vm),
+
+ TP_STRUCT__entry(
+ __field(struct i915_address_space *, vm)
+ ),
+
+ TP_fast_assign(
+ __entry->vm = vm;
+ ),
+
+ TP_printk("dev=%d, vm=%p", __entry->vm->dev->primary->index, __entry->vm)
+);
+
+TRACE_EVENT(i915_gem_ring_sync_to,
+ TP_PROTO(struct intel_ring_buffer *from,
+ struct intel_ring_buffer *to,
+ u32 seqno),
+ TP_ARGS(from, to, seqno),
+
+ TP_STRUCT__entry(
+ __field(u32, dev)
+ __field(u32, sync_from)
+ __field(u32, sync_to)
+ __field(u32, seqno)
+ ),
+
+ TP_fast_assign(
+ __entry->dev = from->dev->primary->index;
+ __entry->sync_from = from->id;
+ __entry->sync_to = to->id;
+ __entry->seqno = seqno;
+ ),
+
+ TP_printk("dev=%u, sync-from=%u, sync-to=%u, seqno=%u",
+ __entry->dev,
+ __entry->sync_from, __entry->sync_to,
+ __entry->seqno)
+);
+
TRACE_EVENT(i915_gem_ring_dispatch,
TP_PROTO(struct intel_ring_buffer *ring, u32 seqno, u32 flags),
TP_ARGS(ring, seqno, flags),
@@ -304,9 +345,24 @@ DEFINE_EVENT(i915_gem_request, i915_gem_request_add,
TP_ARGS(ring, seqno)
);
-DEFINE_EVENT(i915_gem_request, i915_gem_request_complete,
- TP_PROTO(struct intel_ring_buffer *ring, u32 seqno),
- TP_ARGS(ring, seqno)
+TRACE_EVENT(i915_gem_request_complete,
+ TP_PROTO(struct intel_ring_buffer *ring),
+ TP_ARGS(ring),
+
+ TP_STRUCT__entry(
+ __field(u32, dev)
+ __field(u32, ring)
+ __field(u32, seqno)
+ ),
+
+ TP_fast_assign(
+ __entry->dev = ring->dev->primary->index;
+ __entry->ring = ring->id;
+ __entry->seqno = ring->get_seqno(ring, false);
+ ),
+
+ TP_printk("dev=%u, ring=%u, seqno=%u",
+ __entry->dev, __entry->ring, __entry->seqno)
);
DEFINE_EVENT(i915_gem_request, i915_gem_request_retire,
diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c
index 57fe1ae32a0d..43959edd4291 100644
--- a/drivers/gpu/drm/i915/intel_acpi.c
+++ b/drivers/gpu/drm/i915/intel_acpi.c
@@ -193,16 +193,14 @@ out:
static bool intel_dsm_pci_probe(struct pci_dev *pdev)
{
- acpi_handle dhandle, intel_handle;
- acpi_status status;
+ acpi_handle dhandle;
int ret;
dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
if (!dhandle)
return false;
- status = acpi_get_handle(dhandle, "_DSM", &intel_handle);
- if (ACPI_FAILURE(status)) {
+ if (!acpi_has_method(dhandle, "_DSM")) {
DRM_DEBUG_KMS("no _DSM method for intel device\n");
return false;
}
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 53f2bed8bc5f..e29bcae1ef81 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -389,7 +389,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
{
struct sdvo_device_mapping *p_mapping;
struct bdb_general_definitions *p_defs;
- struct child_device_config *p_child;
+ union child_device_config *p_child;
int i, child_device_num, count;
u16 block_size;
@@ -416,36 +416,36 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
count = 0;
for (i = 0; i < child_device_num; i++) {
p_child = &(p_defs->devices[i]);
- if (!p_child->device_type) {
+ if (!p_child->old.device_type) {
/* skip the device block if device type is invalid */
continue;
}
- if (p_child->slave_addr != SLAVE_ADDR1 &&
- p_child->slave_addr != SLAVE_ADDR2) {
+ if (p_child->old.slave_addr != SLAVE_ADDR1 &&
+ p_child->old.slave_addr != SLAVE_ADDR2) {
/*
* If the slave address is neither 0x70 nor 0x72,
* it is not a SDVO device. Skip it.
*/
continue;
}
- if (p_child->dvo_port != DEVICE_PORT_DVOB &&
- p_child->dvo_port != DEVICE_PORT_DVOC) {
+ if (p_child->old.dvo_port != DEVICE_PORT_DVOB &&
+ p_child->old.dvo_port != DEVICE_PORT_DVOC) {
/* skip the incorrect SDVO port */
DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n");
continue;
}
DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on"
" %s port\n",
- p_child->slave_addr,
- (p_child->dvo_port == DEVICE_PORT_DVOB) ?
+ p_child->old.slave_addr,
+ (p_child->old.dvo_port == DEVICE_PORT_DVOB) ?
"SDVOB" : "SDVOC");
- p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]);
+ p_mapping = &(dev_priv->sdvo_mappings[p_child->old.dvo_port - 1]);
if (!p_mapping->initialized) {
- p_mapping->dvo_port = p_child->dvo_port;
- p_mapping->slave_addr = p_child->slave_addr;
- p_mapping->dvo_wiring = p_child->dvo_wiring;
- p_mapping->ddc_pin = p_child->ddc_pin;
- p_mapping->i2c_pin = p_child->i2c_pin;
+ p_mapping->dvo_port = p_child->old.dvo_port;
+ p_mapping->slave_addr = p_child->old.slave_addr;
+ p_mapping->dvo_wiring = p_child->old.dvo_wiring;
+ p_mapping->ddc_pin = p_child->old.ddc_pin;
+ p_mapping->i2c_pin = p_child->old.i2c_pin;
p_mapping->initialized = 1;
DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n",
p_mapping->dvo_port,
@@ -457,7 +457,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
"two SDVO device.\n");
}
- if (p_child->slave2_addr) {
+ if (p_child->old.slave2_addr) {
/* Maybe this is a SDVO device with multiple inputs */
/* And the mapping info is not added */
DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this"
@@ -477,15 +477,13 @@ static void
parse_driver_features(struct drm_i915_private *dev_priv,
struct bdb_header *bdb)
{
- struct drm_device *dev = dev_priv->dev;
struct bdb_driver_features *driver;
driver = find_section(bdb, BDB_DRIVER_FEATURES);
if (!driver)
return;
- if (SUPPORTS_EDP(dev) &&
- driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
+ if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
dev_priv->vbt.edp_support = 1;
if (driver->dual_frequency)
@@ -501,7 +499,7 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
edp = find_section(bdb, BDB_EDP);
if (!edp) {
- if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->vbt.edp_support)
+ if (dev_priv->vbt.edp_support)
DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n");
return;
}
@@ -569,11 +567,149 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
}
static void
+parse_mipi(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
+{
+ struct bdb_mipi *mipi;
+
+ mipi = find_section(bdb, BDB_MIPI);
+ if (!mipi) {
+ DRM_DEBUG_KMS("No MIPI BDB found");
+ return;
+ }
+
+ /* XXX: add more info */
+ dev_priv->vbt.dsi.panel_id = mipi->panel_id;
+}
+
+static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
+ struct bdb_header *bdb)
+{
+ union child_device_config *it, *child = NULL;
+ struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port];
+ uint8_t hdmi_level_shift;
+ int i, j;
+ bool is_dvi, is_hdmi, is_dp, is_edp, is_crt;
+ uint8_t aux_channel;
+ /* Each DDI port can have more than one value on the "DVO Port" field,
+ * so look for all the possible values for each port and abort if more
+ * than one is found. */
+ int dvo_ports[][2] = {
+ {DVO_PORT_HDMIA, DVO_PORT_DPA},
+ {DVO_PORT_HDMIB, DVO_PORT_DPB},
+ {DVO_PORT_HDMIC, DVO_PORT_DPC},
+ {DVO_PORT_HDMID, DVO_PORT_DPD},
+ {DVO_PORT_CRT, -1 /* Port E can only be DVO_PORT_CRT */ },
+ };
+
+ /* Find the child device to use, abort if more than one found. */
+ for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
+ it = dev_priv->vbt.child_dev + i;
+
+ for (j = 0; j < 2; j++) {
+ if (dvo_ports[port][j] == -1)
+ break;
+
+ if (it->common.dvo_port == dvo_ports[port][j]) {
+ if (child) {
+ DRM_DEBUG_KMS("More than one child device for port %c in VBT.\n",
+ port_name(port));
+ return;
+ }
+ child = it;
+ }
+ }
+ }
+ if (!child)
+ return;
+
+ aux_channel = child->raw[25];
+
+ is_dvi = child->common.device_type & (1 << 4);
+ is_dp = child->common.device_type & (1 << 2);
+ is_crt = child->common.device_type & (1 << 0);
+ is_hdmi = is_dvi && (child->common.device_type & (1 << 11)) == 0;
+ is_edp = is_dp && (child->common.device_type & (1 << 12));
+
+ info->supports_dvi = is_dvi;
+ info->supports_hdmi = is_hdmi;
+ info->supports_dp = is_dp;
+
+ DRM_DEBUG_KMS("Port %c VBT info: DP:%d HDMI:%d DVI:%d EDP:%d CRT:%d\n",
+ port_name(port), is_dp, is_hdmi, is_dvi, is_edp, is_crt);
+
+ if (is_edp && is_dvi)
+ DRM_DEBUG_KMS("Internal DP port %c is TMDS compatible\n",
+ port_name(port));
+ if (is_crt && port != PORT_E)
+ DRM_DEBUG_KMS("Port %c is analog\n", port_name(port));
+ if (is_crt && (is_dvi || is_dp))
+ DRM_DEBUG_KMS("Analog port %c is also DP or TMDS compatible\n",
+ port_name(port));
+ if (is_dvi && (port == PORT_A || port == PORT_E))
+ DRM_DEBUG_KMS("Port %c is TMDS compabile\n", port_name(port));
+ if (!is_dvi && !is_dp && !is_crt)
+ DRM_DEBUG_KMS("Port %c is not DP/TMDS/CRT compatible\n",
+ port_name(port));
+ if (is_edp && (port == PORT_B || port == PORT_C || port == PORT_E))
+ DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port));
+
+ if (is_dvi) {
+ if (child->common.ddc_pin == 0x05 && port != PORT_B)
+ DRM_DEBUG_KMS("Unexpected DDC pin for port B\n");
+ if (child->common.ddc_pin == 0x04 && port != PORT_C)
+ DRM_DEBUG_KMS("Unexpected DDC pin for port C\n");
+ if (child->common.ddc_pin == 0x06 && port != PORT_D)
+ DRM_DEBUG_KMS("Unexpected DDC pin for port D\n");
+ }
+
+ if (is_dp) {
+ if (aux_channel == 0x40 && port != PORT_A)
+ DRM_DEBUG_KMS("Unexpected AUX channel for port A\n");
+ if (aux_channel == 0x10 && port != PORT_B)
+ DRM_DEBUG_KMS("Unexpected AUX channel for port B\n");
+ if (aux_channel == 0x20 && port != PORT_C)
+ DRM_DEBUG_KMS("Unexpected AUX channel for port C\n");
+ if (aux_channel == 0x30 && port != PORT_D)
+ DRM_DEBUG_KMS("Unexpected AUX channel for port D\n");
+ }
+
+ if (bdb->version >= 158) {
+ /* The VBT HDMI level shift values match the table we have. */
+ hdmi_level_shift = child->raw[7] & 0xF;
+ if (hdmi_level_shift < 0xC) {
+ DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n",
+ port_name(port),
+ hdmi_level_shift);
+ info->hdmi_level_shift = hdmi_level_shift;
+ }
+ }
+}
+
+static void parse_ddi_ports(struct drm_i915_private *dev_priv,
+ struct bdb_header *bdb)
+{
+ struct drm_device *dev = dev_priv->dev;
+ enum port port;
+
+ if (!HAS_DDI(dev))
+ return;
+
+ if (!dev_priv->vbt.child_dev_num)
+ return;
+
+ if (bdb->version < 155)
+ return;
+
+ for (port = PORT_A; port < I915_MAX_PORTS; port++)
+ parse_ddi_port(dev_priv, port, bdb);
+}
+
+static void
parse_device_mapping(struct drm_i915_private *dev_priv,
struct bdb_header *bdb)
{
struct bdb_general_definitions *p_defs;
- struct child_device_config *p_child, *child_dev_ptr;
+ union child_device_config *p_child, *child_dev_ptr;
int i, child_device_num, count;
u16 block_size;
@@ -601,7 +737,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
/* get the number of child device that is present */
for (i = 0; i < child_device_num; i++) {
p_child = &(p_defs->devices[i]);
- if (!p_child->device_type) {
+ if (!p_child->common.device_type) {
/* skip the device block if device type is invalid */
continue;
}
@@ -621,7 +757,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
count = 0;
for (i = 0; i < child_device_num; i++) {
p_child = &(p_defs->devices[i]);
- if (!p_child->device_type) {
+ if (!p_child->common.device_type) {
/* skip the device block if device type is invalid */
continue;
}
@@ -637,6 +773,7 @@ static void
init_vbt_defaults(struct drm_i915_private *dev_priv)
{
struct drm_device *dev = dev_priv->dev;
+ enum port port;
dev_priv->vbt.crt_ddc_pin = GMBUS_PORT_VGADDC;
@@ -655,6 +792,18 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
dev_priv->vbt.lvds_use_ssc = 1;
dev_priv->vbt.lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->vbt.lvds_ssc_freq);
+
+ for (port = PORT_A; port < I915_MAX_PORTS; port++) {
+ struct ddi_vbt_port_info *info =
+ &dev_priv->vbt.ddi_port_info[port];
+
+ /* Recommended BSpec default: 800mV 0dB. */
+ info->hdmi_level_shift = 6;
+
+ info->supports_dvi = (port != PORT_A && port != PORT_E);
+ info->supports_hdmi = info->supports_dvi;
+ info->supports_dp = (port != PORT_E);
+ }
}
static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
@@ -745,6 +894,8 @@ intel_parse_bios(struct drm_device *dev)
parse_device_mapping(dev_priv, bdb);
parse_driver_features(dev_priv, bdb);
parse_edp(dev_priv, bdb);
+ parse_mipi(dev_priv, bdb);
+ parse_ddi_ports(dev_priv, bdb);
if (bios)
pci_unmap_rom(pdev, bios);
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h
index e088d6f0956a..287cc5a21c2e 100644
--- a/drivers/gpu/drm/i915/intel_bios.h
+++ b/drivers/gpu/drm/i915/intel_bios.h
@@ -104,6 +104,7 @@ struct vbios_data {
#define BDB_LVDS_LFP_DATA 42
#define BDB_LVDS_BACKLIGHT 43
#define BDB_LVDS_POWER 44
+#define BDB_MIPI 50
#define BDB_SKIP 254 /* VBIOS private block, ignore */
struct bdb_general_features {
@@ -201,7 +202,10 @@ struct bdb_general_features {
#define DEVICE_PORT_DVOB 0x01
#define DEVICE_PORT_DVOC 0x02
-struct child_device_config {
+/* We used to keep this struct but without any version control. We should avoid
+ * using it in the future, but it should be safe to keep using it in the old
+ * code. */
+struct old_child_dev_config {
u16 handle;
u16 device_type;
u8 device_id[10]; /* ascii string */
@@ -223,6 +227,32 @@ struct child_device_config {
u8 dvo_function;
} __attribute__((packed));
+/* This one contains field offsets that are known to be common for all BDB
+ * versions. Notice that the meaning of the contents contents may still change,
+ * but at least the offsets are consistent. */
+struct common_child_dev_config {
+ u16 handle;
+ u16 device_type;
+ u8 not_common1[12];
+ u8 dvo_port;
+ u8 not_common2[2];
+ u8 ddc_pin;
+ u16 edid_ptr;
+} __attribute__((packed));
+
+/* This field changes depending on the BDB version, so the most reliable way to
+ * read it is by checking the BDB version and reading the raw pointer. */
+union child_device_config {
+ /* This one is safe to be used anywhere, but the code should still check
+ * the BDB version. */
+ u8 raw[33];
+ /* This one should only be kept for legacy code. */
+ struct old_child_dev_config old;
+ /* This one should also be safe to use anywhere, even without version
+ * checks. */
+ struct common_child_dev_config common;
+};
+
struct bdb_general_definitions {
/* DDC GPIO */
u8 crt_ddc_gmbus_pin;
@@ -248,7 +278,7 @@ struct bdb_general_definitions {
* number = (block_size - sizeof(bdb_general_definitions))/
* sizeof(child_device_config);
*/
- struct child_device_config devices[0];
+ union child_device_config devices[0];
} __attribute__((packed));
struct bdb_lvds_options {
@@ -618,4 +648,57 @@ int intel_parse_bios(struct drm_device *dev);
#define PORT_IDPC 8
#define PORT_IDPD 9
+/* Possible values for the "DVO Port" field for versions >= 155: */
+#define DVO_PORT_HDMIA 0
+#define DVO_PORT_HDMIB 1
+#define DVO_PORT_HDMIC 2
+#define DVO_PORT_HDMID 3
+#define DVO_PORT_LVDS 4
+#define DVO_PORT_TV 5
+#define DVO_PORT_CRT 6
+#define DVO_PORT_DPB 7
+#define DVO_PORT_DPC 8
+#define DVO_PORT_DPD 9
+#define DVO_PORT_DPA 10
+
+/* MIPI DSI panel info */
+struct bdb_mipi {
+ u16 panel_id;
+ u16 bridge_revision;
+
+ /* General params */
+ u32 dithering:1;
+ u32 bpp_pixel_format:1;
+ u32 rsvd1:1;
+ u32 dphy_valid:1;
+ u32 resvd2:28;
+
+ u16 port_info;
+ u16 rsvd3:2;
+ u16 num_lanes:2;
+ u16 rsvd4:12;
+
+ /* DSI config */
+ u16 virt_ch_num:2;
+ u16 vtm:2;
+ u16 rsvd5:12;
+
+ u32 dsi_clock;
+ u32 bridge_ref_clk;
+ u16 rsvd_pwr;
+
+ /* Dphy Params */
+ u32 prepare_cnt:5;
+ u32 rsvd6:3;
+ u32 clk_zero_cnt:8;
+ u32 trail_cnt:5;
+ u32 rsvd7:3;
+ u32 exit_zero_cnt:6;
+ u32 rsvd8:2;
+
+ u32 hl_switch_cnt;
+ u32 lp_byte_clk;
+ u32 clk_lane_switch_cnt;
+} __attribute__((packed));
+
#endif /* _I830_BIOS_H_ */
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index ea9022ef15d5..0263629332d0 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -83,8 +83,7 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
return true;
}
-static void intel_crt_get_config(struct intel_encoder *encoder,
- struct intel_crtc_config *pipe_config)
+static unsigned int intel_crt_get_flags(struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_crt *crt = intel_encoder_to_crt(encoder);
@@ -102,7 +101,35 @@ static void intel_crt_get_config(struct intel_encoder *encoder,
else
flags |= DRM_MODE_FLAG_NVSYNC;
- pipe_config->adjusted_mode.flags |= flags;
+ return flags;
+}
+
+static void intel_crt_get_config(struct intel_encoder *encoder,
+ struct intel_crtc_config *pipe_config)
+{
+ struct drm_device *dev = encoder->base.dev;
+ int dotclock;
+
+ pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder);
+
+ dotclock = pipe_config->port_clock;
+
+ if (HAS_PCH_SPLIT(dev))
+ ironlake_check_encoder_dotclock(pipe_config, dotclock);
+
+ pipe_config->adjusted_mode.crtc_clock = dotclock;
+}
+
+static void hsw_crt_get_config(struct intel_encoder *encoder,
+ struct intel_crtc_config *pipe_config)
+{
+ intel_ddi_get_config(encoder, pipe_config);
+
+ pipe_config->adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC |
+ DRM_MODE_FLAG_NHSYNC |
+ DRM_MODE_FLAG_PVSYNC |
+ DRM_MODE_FLAG_NVSYNC);
+ pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder);
}
/* Note: The caller is required to filter out dpms modes not supported by the
@@ -349,9 +376,6 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector)
DRM_DEBUG_KMS("valleyview hotplug adpa=0x%x, result %d\n", adpa, ret);
- /* FIXME: debug force function and remove */
- ret = true;
-
return ret;
}
@@ -759,7 +783,7 @@ void intel_crt_init(struct drm_device *dev)
if (!crt)
return;
- intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
+ intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
if (!intel_connector) {
kfree(crt);
return;
@@ -799,7 +823,10 @@ void intel_crt_init(struct drm_device *dev)
crt->base.mode_set = intel_crt_mode_set;
crt->base.disable = intel_disable_crt;
crt->base.enable = intel_enable_crt;
- crt->base.get_config = intel_crt_get_config;
+ if (IS_HASWELL(dev))
+ crt->base.get_config = hsw_crt_get_config;
+ else
+ crt->base.get_config = intel_crt_get_config;
if (I915_HAS_HOTPLUG(dev))
crt->base.hpd_pin = HPD_CRT;
if (HAS_DDI(dev))
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 63de2701b974..a43ac3a17bdc 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -42,7 +42,6 @@ static const u32 hsw_ddi_translations_dp[] = {
0x80C30FFF, 0x000B0000,
0x00FFFFFF, 0x00040006,
0x80D75FFF, 0x000B0000,
- 0x00FFFFFF, 0x00040006 /* HDMI parameters */
};
static const u32 hsw_ddi_translations_fdi[] = {
@@ -55,10 +54,25 @@ static const u32 hsw_ddi_translations_fdi[] = {
0x00C30FFF, 0x001E0000,
0x00FFFFFF, 0x00060006,
0x00D75FFF, 0x001E0000,
- 0x00FFFFFF, 0x00040006 /* HDMI parameters */
};
-static enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
+static const u32 hsw_ddi_translations_hdmi[] = {
+ /* Idx NT mV diff T mV diff db */
+ 0x00FFFFFF, 0x0006000E, /* 0: 400 400 0 */
+ 0x00E79FFF, 0x000E000C, /* 1: 400 500 2 */
+ 0x00D75FFF, 0x0005000A, /* 2: 400 600 3.5 */
+ 0x00FFFFFF, 0x0005000A, /* 3: 600 600 0 */
+ 0x00E79FFF, 0x001D0007, /* 4: 600 750 2 */
+ 0x00D75FFF, 0x000C0004, /* 5: 600 900 3.5 */
+ 0x00FFFFFF, 0x00040006, /* 6: 800 800 0 */
+ 0x80E79FFF, 0x00030002, /* 7: 800 1000 2 */
+ 0x00FFFFFF, 0x00140005, /* 8: 850 850 0 */
+ 0x00FFFFFF, 0x000C0004, /* 9: 900 900 0 */
+ 0x00FFFFFF, 0x001C0003, /* 10: 950 950 0 */
+ 0x80FFFFFF, 0x00030002, /* 11: 1000 1000 0 */
+};
+
+enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
{
struct drm_encoder *encoder = &intel_encoder->base;
int type = intel_encoder->type;
@@ -92,12 +106,18 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
const u32 *ddi_translations = (port == PORT_E) ?
hsw_ddi_translations_fdi :
hsw_ddi_translations_dp;
+ int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift;
for (i = 0, reg = DDI_BUF_TRANS(port);
i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) {
I915_WRITE(reg, ddi_translations[i]);
reg += 4;
}
+ /* Entry 9 is for HDMI: */
+ for (i = 0; i < 2; i++) {
+ I915_WRITE(reg, hsw_ddi_translations_hdmi[hdmi_level * 2 + i]);
+ reg += 4;
+ }
}
/* Program DDI buffers translations for DP. By default, program ports A-D in DP
@@ -767,9 +787,9 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
BUG();
}
- if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC)
+ if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_PVSYNC)
temp |= TRANS_DDI_PVSYNC;
- if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
+ if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_PHSYNC)
temp |= TRANS_DDI_PHSYNC;
if (cpu_transcoder == TRANSCODER_EDP) {
@@ -1249,8 +1269,8 @@ static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder)
intel_dp_check_link_status(intel_dp);
}
-static void intel_ddi_get_config(struct intel_encoder *encoder,
- struct intel_crtc_config *pipe_config)
+void intel_ddi_get_config(struct intel_encoder *encoder,
+ struct intel_crtc_config *pipe_config)
{
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
@@ -1268,6 +1288,37 @@ static void intel_ddi_get_config(struct intel_encoder *encoder,
flags |= DRM_MODE_FLAG_NVSYNC;
pipe_config->adjusted_mode.flags |= flags;
+
+ switch (temp & TRANS_DDI_BPC_MASK) {
+ case TRANS_DDI_BPC_6:
+ pipe_config->pipe_bpp = 18;
+ break;
+ case TRANS_DDI_BPC_8:
+ pipe_config->pipe_bpp = 24;
+ break;
+ case TRANS_DDI_BPC_10:
+ pipe_config->pipe_bpp = 30;
+ break;
+ case TRANS_DDI_BPC_12:
+ pipe_config->pipe_bpp = 36;
+ break;
+ default:
+ break;
+ }
+
+ switch (temp & TRANS_DDI_MODE_SELECT_MASK) {
+ case TRANS_DDI_MODE_SELECT_HDMI:
+ case TRANS_DDI_MODE_SELECT_DVI:
+ case TRANS_DDI_MODE_SELECT_FDI:
+ break;
+ case TRANS_DDI_MODE_SELECT_DP_SST:
+ case TRANS_DDI_MODE_SELECT_DP_MST:
+ pipe_config->has_dp_encoder = true;
+ intel_dp_get_m_n(intel_crtc, pipe_config);
+ break;
+ default:
+ break;
+ }
}
static void intel_ddi_destroy(struct drm_encoder *encoder)
@@ -1305,12 +1356,23 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
struct drm_encoder *encoder;
struct intel_connector *hdmi_connector = NULL;
struct intel_connector *dp_connector = NULL;
+ bool init_hdmi, init_dp;
+
+ init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi ||
+ dev_priv->vbt.ddi_port_info[port].supports_hdmi);
+ init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp;
+ if (!init_dp && !init_hdmi) {
+ DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible\n",
+ port_name(port));
+ init_hdmi = true;
+ init_dp = true;
+ }
- intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL);
+ intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
if (!intel_dig_port)
return;
- dp_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
+ dp_connector = kzalloc(sizeof(*dp_connector), GFP_KERNEL);
if (!dp_connector) {
kfree(intel_dig_port);
return;
@@ -1342,19 +1404,20 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
intel_encoder->cloneable = false;
intel_encoder->hot_plug = intel_ddi_hot_plug;
- if (!intel_dp_init_connector(intel_dig_port, dp_connector)) {
+ if (init_dp && !intel_dp_init_connector(intel_dig_port, dp_connector)) {
drm_encoder_cleanup(encoder);
kfree(intel_dig_port);
kfree(dp_connector);
return;
}
- if (intel_encoder->type != INTEL_OUTPUT_EDP) {
- hdmi_connector = kzalloc(sizeof(struct intel_connector),
+ /* In theory we don't need the encoder->type check, but leave it just in
+ * case we have some really bad VBTs... */
+ if (intel_encoder->type != INTEL_OUTPUT_EDP && init_hdmi) {
+ hdmi_connector = kzalloc(sizeof(*hdmi_connector),
GFP_KERNEL);
- if (!hdmi_connector) {
+ if (!hdmi_connector)
return;
- }
intel_dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port);
intel_hdmi_init_connector(intel_dig_port, hdmi_connector);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d8a1d98693e7..665fa8f40af5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -41,14 +41,13 @@
#include <drm/drm_crtc_helper.h>
#include <linux/dma_remapping.h>
-bool intel_pipe_has_type(struct drm_crtc *crtc, int type);
static void intel_increase_pllclock(struct drm_crtc *crtc);
static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on);
static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
struct intel_crtc_config *pipe_config);
-static void ironlake_crtc_clock_get(struct intel_crtc *crtc,
- struct intel_crtc_config *pipe_config);
+static void ironlake_pch_clock_get(struct intel_crtc *crtc,
+ struct intel_crtc_config *pipe_config);
static int intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
int x, int y, struct drm_framebuffer *old_fb);
@@ -69,9 +68,6 @@ struct intel_limit {
intel_p2_t p2;
};
-/* FDI */
-#define IRONLAKE_FDI_FREQ 2700000 /* in kHz for mode->clock */
-
int
intel_pch_rawclk(struct drm_device *dev)
{
@@ -339,18 +335,20 @@ static const intel_limit_t intel_limits_vlv_hdmi = {
.p2_slow = 2, .p2_fast = 20 },
};
-static const intel_limit_t intel_limits_vlv_dp = {
- .dot = { .min = 25000, .max = 270000 },
- .vco = { .min = 4000000, .max = 6000000 },
- .n = { .min = 1, .max = 7 },
- .m = { .min = 22, .max = 450 },
- .m1 = { .min = 2, .max = 3 },
- .m2 = { .min = 11, .max = 156 },
- .p = { .min = 10, .max = 30 },
- .p1 = { .min = 1, .max = 3 },
- .p2 = { .dot_limit = 270000,
- .p2_slow = 2, .p2_fast = 20 },
-};
+/**
+ * Returns whether any output on the specified pipe is of the specified type
+ */
+static bool intel_pipe_has_type(struct drm_crtc *crtc, int type)
+{
+ struct drm_device *dev = crtc->dev;
+ struct intel_encoder *encoder;
+
+ for_each_encoder_on_crtc(dev, crtc, encoder)
+ if (encoder->type == type)
+ return true;
+
+ return false;
+}
static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
int refclk)
@@ -414,10 +412,8 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc, int refclk)
} else if (IS_VALLEYVIEW(dev)) {
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG))
limit = &intel_limits_vlv_dac;
- else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI))
- limit = &intel_limits_vlv_hdmi;
else
- limit = &intel_limits_vlv_dp;
+ limit = &intel_limits_vlv_hdmi;
} else if (!IS_GEN2(dev)) {
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
limit = &intel_limits_i9xx_lvds;
@@ -456,21 +452,6 @@ static void i9xx_clock(int refclk, intel_clock_t *clock)
clock->dot = clock->vco / clock->p;
}
-/**
- * Returns whether any output on the specified pipe is of the specified type
- */
-bool intel_pipe_has_type(struct drm_crtc *crtc, int type)
-{
- struct drm_device *dev = crtc->dev;
- struct intel_encoder *encoder;
-
- for_each_encoder_on_crtc(dev, crtc, encoder)
- if (encoder->type == type)
- return true;
-
- return false;
-}
-
#define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0)
/**
* Returns whether the given set of divisors are valid for a given refclk with
@@ -751,6 +732,23 @@ vlv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc,
return true;
}
+bool intel_crtc_active(struct drm_crtc *crtc)
+{
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+ /* Be paranoid as we can arrive here with only partial
+ * state retrieved from the hardware during setup.
+ *
+ * We can ditch the adjusted_mode.crtc_clock check as soon
+ * as Haswell has gained clock readout/fastboot support.
+ *
+ * We can ditch the crtc->fb check as soon as we can
+ * properly reconstruct framebuffers.
+ */
+ return intel_crtc->active && crtc->fb &&
+ intel_crtc->config.adjusted_mode.crtc_clock;
+}
+
enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
enum pipe pipe)
{
@@ -929,6 +927,24 @@ void assert_pll(struct drm_i915_private *dev_priv,
state_string(state), state_string(cur_state));
}
+/* XXX: the dsi pll is shared between MIPI DSI ports */
+static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state)
+{
+ u32 val;
+ bool cur_state;
+
+ mutex_lock(&dev_priv->dpio_lock);
+ val = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL);
+ mutex_unlock(&dev_priv->dpio_lock);
+
+ cur_state = val & DSI_PLL_VCO_EN;
+ WARN(cur_state != state,
+ "DSI PLL state assertion failure (expected %s, current %s)\n",
+ state_string(state), state_string(cur_state));
+}
+#define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true)
+#define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false)
+
struct intel_shared_dpll *
intel_crtc_to_shared_dpll(struct intel_crtc *crtc)
{
@@ -1069,6 +1085,26 @@ static void assert_panel_unlocked(struct drm_i915_private *dev_priv,
pipe_name(pipe));
}
+static void assert_cursor(struct drm_i915_private *dev_priv,
+ enum pipe pipe, bool state)
+{
+ struct drm_device *dev = dev_priv->dev;
+ bool cur_state;
+
+ if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
+ cur_state = I915_READ(CURCNTR_IVB(pipe)) & CURSOR_MODE;
+ else if (IS_845G(dev) || IS_I865G(dev))
+ cur_state = I915_READ(_CURACNTR) & CURSOR_ENABLE;
+ else
+ cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE;
+
+ WARN(cur_state != state,
+ "cursor on pipe %c assertion failure (expected %s, current %s)\n",
+ pipe_name(pipe), state_string(state), state_string(cur_state));
+}
+#define assert_cursor_enabled(d, p) assert_cursor(d, p, true)
+#define assert_cursor_disabled(d, p) assert_cursor(d, p, false)
+
void assert_pipe(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state)
{
@@ -1661,7 +1697,7 @@ static void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv)
* returning.
*/
static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
- bool pch_port)
+ bool pch_port, bool dsi)
{
enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
pipe);
@@ -1670,6 +1706,7 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
u32 val;
assert_planes_disabled(dev_priv, pipe);
+ assert_cursor_disabled(dev_priv, pipe);
assert_sprites_disabled(dev_priv, pipe);
if (HAS_PCH_LPT(dev_priv->dev))
@@ -1683,7 +1720,10 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
* need the check.
*/
if (!HAS_PCH_SPLIT(dev_priv->dev))
- assert_pll_enabled(dev_priv, pipe);
+ if (dsi)
+ assert_dsi_pll_enabled(dev_priv);
+ else
+ assert_pll_enabled(dev_priv, pipe);
else {
if (pch_port) {
/* if driving the PCH, we need FDI enabled */
@@ -1728,6 +1768,7 @@ static void intel_disable_pipe(struct drm_i915_private *dev_priv,
* or we might hang the display.
*/
assert_planes_disabled(dev_priv, pipe);
+ assert_cursor_disabled(dev_priv, pipe);
assert_sprites_disabled(dev_priv, pipe);
/* Don't disable pipe A or pipe A PLLs if needed */
@@ -2872,6 +2913,7 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
+ int clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
u32 divsel, phaseinc, auxdiv, phasedir = 0;
u32 temp;
@@ -2889,14 +2931,14 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
SBI_ICLK);
/* 20MHz is a corner case which is out of range for the 7-bit divisor */
- if (crtc->mode.clock == 20000) {
+ if (clock == 20000) {
auxdiv = 1;
divsel = 0x41;
phaseinc = 0x20;
} else {
/* The iCLK virtual clock root frequency is in MHz,
- * but the crtc->mode.clock in in KHz. To get the divisors,
- * it is necessary to divide one by another, so we
+ * but the adjusted_mode->crtc_clock in in KHz. To get the
+ * divisors, it is necessary to divide one by another, so we
* convert the virtual clock precision to KHz here for higher
* precision.
*/
@@ -2904,7 +2946,7 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
u32 iclk_pi_range = 64;
u32 desired_divisor, msb_divisor_value, pi_value;
- desired_divisor = (iclk_virtual_root_freq / crtc->mode.clock);
+ desired_divisor = (iclk_virtual_root_freq / clock);
msb_divisor_value = desired_divisor / iclk_pi_range;
pi_value = desired_divisor % iclk_pi_range;
@@ -2920,7 +2962,7 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
~SBI_SSCDIVINTPHASE_INCVAL_MASK);
DRM_DEBUG_KMS("iCLKIP clock: found settings for %dKHz refresh rate: auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n",
- crtc->mode.clock,
+ clock,
auxdiv,
divsel,
phasedir,
@@ -3240,6 +3282,84 @@ static void intel_disable_planes(struct drm_crtc *crtc)
intel_plane_disable(&intel_plane->base);
}
+static void hsw_enable_ips(struct intel_crtc *crtc)
+{
+ struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+
+ if (!crtc->config.ips_enabled)
+ return;
+
+ /* We can only enable IPS after we enable a plane and wait for a vblank.
+ * We guarantee that the plane is enabled by calling intel_enable_ips
+ * only after intel_enable_plane. And intel_enable_plane already waits
+ * for a vblank, so all we need to do here is to enable the IPS bit. */
+ assert_plane_enabled(dev_priv, crtc->plane);
+ I915_WRITE(IPS_CTL, IPS_ENABLE);
+}
+
+static void hsw_disable_ips(struct intel_crtc *crtc)
+{
+ struct drm_device *dev = crtc->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (!crtc->config.ips_enabled)
+ return;
+
+ assert_plane_enabled(dev_priv, crtc->plane);
+ I915_WRITE(IPS_CTL, 0);
+ POSTING_READ(IPS_CTL);
+
+ /* We need to wait for a vblank before we can disable the plane. */
+ intel_wait_for_vblank(dev, crtc->pipe);
+}
+
+/** Loads the palette/gamma unit for the CRTC with the prepared values */
+static void intel_crtc_load_lut(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ enum pipe pipe = intel_crtc->pipe;
+ int palreg = PALETTE(pipe);
+ int i;
+ bool reenable_ips = false;
+
+ /* The clocks have to be on to load the palette. */
+ if (!crtc->enabled || !intel_crtc->active)
+ return;
+
+ if (!HAS_PCH_SPLIT(dev_priv->dev)) {
+ if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI))
+ assert_dsi_pll_enabled(dev_priv);
+ else
+ assert_pll_enabled(dev_priv, pipe);
+ }
+
+ /* use legacy palette for Ironlake */
+ if (HAS_PCH_SPLIT(dev))
+ palreg = LGC_PALETTE(pipe);
+
+ /* Workaround : Do not read or write the pipe palette/gamma data while
+ * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
+ */
+ if (intel_crtc->config.ips_enabled &&
+ ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
+ GAMMA_MODE_MODE_SPLIT)) {
+ hsw_disable_ips(intel_crtc);
+ reenable_ips = true;
+ }
+
+ for (i = 0; i < 256; i++) {
+ I915_WRITE(palreg + 4 * i,
+ (intel_crtc->lut_r[i] << 16) |
+ (intel_crtc->lut_g[i] << 8) |
+ intel_crtc->lut_b[i]);
+ }
+
+ if (reenable_ips)
+ hsw_enable_ips(intel_crtc);
+}
+
static void ironlake_crtc_enable(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
@@ -3259,8 +3379,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
intel_set_pch_fifo_underrun_reporting(dev, pipe, true);
- intel_update_watermarks(dev);
-
for_each_encoder_on_crtc(dev, crtc, encoder)
if (encoder->pre_enable)
encoder->pre_enable(encoder);
@@ -3283,8 +3401,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
*/
intel_crtc_load_lut(crtc);
+ intel_update_watermarks(crtc);
intel_enable_pipe(dev_priv, pipe,
- intel_crtc->config.has_pch_encoder);
+ intel_crtc->config.has_pch_encoder, false);
intel_enable_plane(dev_priv, plane, pipe);
intel_enable_planes(crtc);
intel_crtc_update_cursor(crtc, true);
@@ -3319,36 +3438,6 @@ static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
return HAS_IPS(crtc->base.dev) && crtc->pipe == PIPE_A;
}
-static void hsw_enable_ips(struct intel_crtc *crtc)
-{
- struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
-
- if (!crtc->config.ips_enabled)
- return;
-
- /* We can only enable IPS after we enable a plane and wait for a vblank.
- * We guarantee that the plane is enabled by calling intel_enable_ips
- * only after intel_enable_plane. And intel_enable_plane already waits
- * for a vblank, so all we need to do here is to enable the IPS bit. */
- assert_plane_enabled(dev_priv, crtc->plane);
- I915_WRITE(IPS_CTL, IPS_ENABLE);
-}
-
-static void hsw_disable_ips(struct intel_crtc *crtc)
-{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
-
- if (!crtc->config.ips_enabled)
- return;
-
- assert_plane_enabled(dev_priv, crtc->plane);
- I915_WRITE(IPS_CTL, 0);
-
- /* We need to wait for a vblank before we can disable the plane. */
- intel_wait_for_vblank(dev, crtc->pipe);
-}
-
static void haswell_crtc_enable(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
@@ -3369,8 +3458,6 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
if (intel_crtc->config.has_pch_encoder)
intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
- intel_update_watermarks(dev);
-
if (intel_crtc->config.has_pch_encoder)
dev_priv->display.fdi_link_train(crtc);
@@ -3391,8 +3478,9 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
intel_ddi_set_pipe_settings(crtc);
intel_ddi_enable_transcoder_func(crtc);
+ intel_update_watermarks(crtc);
intel_enable_pipe(dev_priv, pipe,
- intel_crtc->config.has_pch_encoder);
+ intel_crtc->config.has_pch_encoder, false);
intel_enable_plane(dev_priv, plane, pipe);
intel_enable_planes(crtc);
intel_crtc_update_cursor(crtc, true);
@@ -3406,8 +3494,10 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
intel_update_fbc(dev);
mutex_unlock(&dev->struct_mutex);
- for_each_encoder_on_crtc(dev, crtc, encoder)
+ for_each_encoder_on_crtc(dev, crtc, encoder) {
encoder->enable(encoder);
+ intel_opregion_notify_encoder(encoder, true);
+ }
/*
* There seems to be a race in PCH platform hw (at least on some
@@ -3501,7 +3591,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
}
intel_crtc->active = false;
- intel_update_watermarks(dev);
+ intel_update_watermarks(crtc);
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
@@ -3521,8 +3611,10 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
if (!intel_crtc->active)
return;
- for_each_encoder_on_crtc(dev, crtc, encoder)
+ for_each_encoder_on_crtc(dev, crtc, encoder) {
+ intel_opregion_notify_encoder(encoder, false);
encoder->disable(encoder);
+ }
intel_crtc_wait_for_pending_flips(crtc);
drm_vblank_off(dev, pipe);
@@ -3558,7 +3650,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
}
intel_crtc->active = false;
- intel_update_watermarks(dev);
+ intel_update_watermarks(crtc);
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
@@ -3650,6 +3742,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
struct intel_encoder *encoder;
int pipe = intel_crtc->pipe;
int plane = intel_crtc->plane;
+ bool is_dsi;
WARN_ON(!crtc->enabled);
@@ -3657,13 +3750,15 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
return;
intel_crtc->active = true;
- intel_update_watermarks(dev);
for_each_encoder_on_crtc(dev, crtc, encoder)
if (encoder->pre_pll_enable)
encoder->pre_pll_enable(encoder);
- vlv_enable_pll(intel_crtc);
+ is_dsi = intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI);
+
+ if (!is_dsi)
+ vlv_enable_pll(intel_crtc);
for_each_encoder_on_crtc(dev, crtc, encoder)
if (encoder->pre_enable)
@@ -3673,7 +3768,8 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
intel_crtc_load_lut(crtc);
- intel_enable_pipe(dev_priv, pipe, false);
+ intel_update_watermarks(crtc);
+ intel_enable_pipe(dev_priv, pipe, false, is_dsi);
intel_enable_plane(dev_priv, plane, pipe);
intel_enable_planes(crtc);
intel_crtc_update_cursor(crtc, true);
@@ -3699,7 +3795,6 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
return;
intel_crtc->active = true;
- intel_update_watermarks(dev);
for_each_encoder_on_crtc(dev, crtc, encoder)
if (encoder->pre_enable)
@@ -3711,7 +3806,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
intel_crtc_load_lut(crtc);
- intel_enable_pipe(dev_priv, pipe, false);
+ intel_update_watermarks(crtc);
+ intel_enable_pipe(dev_priv, pipe, false, false);
intel_enable_plane(dev_priv, plane, pipe);
intel_enable_planes(crtc);
/* The fixup needs to happen before cursor is enabled */
@@ -3778,11 +3874,13 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
if (encoder->post_disable)
encoder->post_disable(encoder);
- i9xx_disable_pll(dev_priv, pipe);
+ if (!intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI))
+ i9xx_disable_pll(dev_priv, pipe);
intel_crtc->active = false;
+ intel_update_watermarks(crtc);
+
intel_update_fbc(dev);
- intel_update_watermarks(dev);
}
static void i9xx_crtc_off(struct drm_crtc *crtc)
@@ -3856,6 +3954,7 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
dev_priv->display.off(crtc);
assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
+ assert_cursor_disabled(dev_priv, to_intel_crtc(crtc)->pipe);
assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
if (crtc->fb) {
@@ -4049,8 +4148,7 @@ retry:
*/
link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10;
- fdi_dotclock = adjusted_mode->clock;
- fdi_dotclock /= pipe_config->pixel_multiplier;
+ fdi_dotclock = adjusted_mode->crtc_clock;
lane = ironlake_get_lanes_required(fdi_dotclock, link_bw,
pipe_config->pipe_bpp);
@@ -4092,13 +4190,39 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
struct drm_device *dev = crtc->base.dev;
struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
- if (HAS_PCH_SPLIT(dev)) {
- /* FDI link clock is fixed at 2.7G */
- if (pipe_config->requested_mode.clock * 3
- > IRONLAKE_FDI_FREQ * 4)
+ /* FIXME should check pixel clock limits on all platforms */
+ if (INTEL_INFO(dev)->gen < 4) {
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int clock_limit =
+ dev_priv->display.get_display_clock_speed(dev);
+
+ /*
+ * Enable pixel doubling when the dot clock
+ * is > 90% of the (display) core speed.
+ *
+ * GDG double wide on either pipe,
+ * otherwise pipe A only.
+ */
+ if ((crtc->pipe == PIPE_A || IS_I915G(dev)) &&
+ adjusted_mode->crtc_clock > clock_limit * 9 / 10) {
+ clock_limit *= 2;
+ pipe_config->double_wide = true;
+ }
+
+ if (adjusted_mode->crtc_clock > clock_limit * 9 / 10)
return -EINVAL;
}
+ /*
+ * Pipe horizontal size must be even in:
+ * - DVO ganged mode
+ * - LVDS dual channel mode
+ * - Double wide pipe
+ */
+ if ((intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) &&
+ intel_is_dual_link_lvds(dev)) || pipe_config->double_wide)
+ pipe_config->pipe_src_w &= ~1;
+
/* Cantiga+ cannot handle modes with a hsync front porch of 0.
* WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
*/
@@ -4262,28 +4386,6 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
}
-static int vlv_get_refclk(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- int refclk = 27000; /* for DP & HDMI */
-
- return 100000; /* only one validated so far */
-
- if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) {
- refclk = 96000;
- } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
- if (intel_panel_use_ssc(dev_priv))
- refclk = 100000;
- else
- refclk = 96000;
- } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
- refclk = 100000;
- }
-
- return refclk;
-}
-
static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors)
{
struct drm_device *dev = crtc->dev;
@@ -4291,7 +4393,7 @@ static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors)
int refclk;
if (IS_VALLEYVIEW(dev)) {
- refclk = vlv_get_refclk(crtc);
+ refclk = 100000;
} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
refclk = dev_priv->vbt.lvds_ssc_freq * 1000;
@@ -4349,7 +4451,8 @@ static void i9xx_update_pll_dividers(struct intel_crtc *crtc,
}
}
-static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv)
+static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, enum pipe
+ pipe)
{
u32 reg_val;
@@ -4357,24 +4460,24 @@ static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv)
* PLLB opamp always calibrates to max value of 0x3f, force enable it
* and set it to a reasonable value instead.
*/
- reg_val = vlv_dpio_read(dev_priv, DPIO_IREF(1));
+ reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF(1));
reg_val &= 0xffffff00;
reg_val |= 0x00000030;
- vlv_dpio_write(dev_priv, DPIO_IREF(1), reg_val);
+ vlv_dpio_write(dev_priv, pipe, DPIO_IREF(1), reg_val);
- reg_val = vlv_dpio_read(dev_priv, DPIO_CALIBRATION);
+ reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_CALIBRATION);
reg_val &= 0x8cffffff;
reg_val = 0x8c000000;
- vlv_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val);
+ vlv_dpio_write(dev_priv, pipe, DPIO_CALIBRATION, reg_val);
- reg_val = vlv_dpio_read(dev_priv, DPIO_IREF(1));
+ reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF(1));
reg_val &= 0xffffff00;
- vlv_dpio_write(dev_priv, DPIO_IREF(1), reg_val);
+ vlv_dpio_write(dev_priv, pipe, DPIO_IREF(1), reg_val);
- reg_val = vlv_dpio_read(dev_priv, DPIO_CALIBRATION);
+ reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_CALIBRATION);
reg_val &= 0x00ffffff;
reg_val |= 0xb0000000;
- vlv_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val);
+ vlv_dpio_write(dev_priv, pipe, DPIO_CALIBRATION, reg_val);
}
static void intel_pch_transcoder_set_m_n(struct intel_crtc *crtc,
@@ -4440,18 +4543,18 @@ static void vlv_update_pll(struct intel_crtc *crtc)
/* PLL B needs special handling */
if (pipe)
- vlv_pllb_recal_opamp(dev_priv);
+ vlv_pllb_recal_opamp(dev_priv, pipe);
/* Set up Tx target for periodic Rcomp update */
- vlv_dpio_write(dev_priv, DPIO_IREF_BCAST, 0x0100000f);
+ vlv_dpio_write(dev_priv, pipe, DPIO_IREF_BCAST, 0x0100000f);
/* Disable target IRef on PLL */
- reg_val = vlv_dpio_read(dev_priv, DPIO_IREF_CTL(pipe));
+ reg_val = vlv_dpio_read(dev_priv, pipe, DPIO_IREF_CTL(pipe));
reg_val &= 0x00ffffff;
- vlv_dpio_write(dev_priv, DPIO_IREF_CTL(pipe), reg_val);
+ vlv_dpio_write(dev_priv, pipe, DPIO_IREF_CTL(pipe), reg_val);
/* Disable fast lock */
- vlv_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x610);
+ vlv_dpio_write(dev_priv, pipe, DPIO_FASTCLK_DISABLE, 0x610);
/* Set idtafcrecal before PLL is enabled */
mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK));
@@ -4465,48 +4568,48 @@ static void vlv_update_pll(struct intel_crtc *crtc)
* Note: don't use the DAC post divider as it seems unstable.
*/
mdiv |= (DPIO_POST_DIV_HDMIDP << DPIO_POST_DIV_SHIFT);
- vlv_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv);
+ vlv_dpio_write(dev_priv, pipe, DPIO_DIV(pipe), mdiv);
mdiv |= DPIO_ENABLE_CALIBRATION;
- vlv_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv);
+ vlv_dpio_write(dev_priv, pipe, DPIO_DIV(pipe), mdiv);
/* Set HBR and RBR LPF coefficients */
if (crtc->config.port_clock == 162000 ||
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_ANALOG) ||
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI))
- vlv_dpio_write(dev_priv, DPIO_LPF_COEFF(pipe),
+ vlv_dpio_write(dev_priv, pipe, DPIO_LPF_COEFF(pipe),
0x009f0003);
else
- vlv_dpio_write(dev_priv, DPIO_LPF_COEFF(pipe),
+ vlv_dpio_write(dev_priv, pipe, DPIO_LPF_COEFF(pipe),
0x00d0000f);
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) ||
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) {
/* Use SSC source */
if (!pipe)
- vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe),
+ vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe),
0x0df40000);
else
- vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe),
+ vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe),
0x0df70000);
} else { /* HDMI or VGA */
/* Use bend source */
if (!pipe)
- vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe),
+ vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe),
0x0df70000);
else
- vlv_dpio_write(dev_priv, DPIO_REFSFR(pipe),
+ vlv_dpio_write(dev_priv, pipe, DPIO_REFSFR(pipe),
0x0df40000);
}
- coreclk = vlv_dpio_read(dev_priv, DPIO_CORE_CLK(pipe));
+ coreclk = vlv_dpio_read(dev_priv, pipe, DPIO_CORE_CLK(pipe));
coreclk = (coreclk & 0x0000ff00) | 0x01c00000;
if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT) ||
intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP))
coreclk |= 0x01000000;
- vlv_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), coreclk);
+ vlv_dpio_write(dev_priv, pipe, DPIO_CORE_CLK(pipe), coreclk);
- vlv_dpio_write(dev_priv, DPIO_PLL_CML(pipe), 0x87871000);
+ vlv_dpio_write(dev_priv, pipe, DPIO_PLL_CML(pipe), 0x87871000);
/* Enable DPIO clock input */
dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV |
@@ -4651,7 +4754,6 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
struct drm_display_mode *adjusted_mode =
&intel_crtc->config.adjusted_mode;
- struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
uint32_t vsyncshift, crtc_vtotal, crtc_vblank_end;
/* We need to be careful not to changed the adjusted mode, for otherwise
@@ -4704,7 +4806,8 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
* always be the user's requested size.
*/
I915_WRITE(PIPESRC(pipe),
- ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
+ ((intel_crtc->config.pipe_src_w - 1) << 16) |
+ (intel_crtc->config.pipe_src_h - 1));
}
static void intel_get_pipe_timings(struct intel_crtc *crtc,
@@ -4742,8 +4845,11 @@ static void intel_get_pipe_timings(struct intel_crtc *crtc,
}
tmp = I915_READ(PIPESRC(crtc->pipe));
- pipe_config->requested_mode.vdisplay = (tmp & 0xffff) + 1;
- pipe_config->requested_mode.hdisplay = ((tmp >> 16) & 0xffff) + 1;
+ pipe_config->pipe_src_h = (tmp & 0xffff) + 1;
+ pipe_config->pipe_src_w = ((tmp >> 16) & 0xffff) + 1;
+
+ pipe_config->requested_mode.vdisplay = pipe_config->pipe_src_h;
+ pipe_config->requested_mode.hdisplay = pipe_config->pipe_src_w;
}
static void intel_crtc_mode_from_pipe_config(struct intel_crtc *intel_crtc,
@@ -4763,7 +4869,7 @@ static void intel_crtc_mode_from_pipe_config(struct intel_crtc *intel_crtc,
crtc->mode.flags = pipe_config->adjusted_mode.flags;
- crtc->mode.clock = pipe_config->adjusted_mode.clock;
+ crtc->mode.clock = pipe_config->adjusted_mode.crtc_clock;
crtc->mode.flags |= pipe_config->adjusted_mode.flags;
}
@@ -4775,17 +4881,12 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
pipeconf = 0;
- if (intel_crtc->pipe == 0 && INTEL_INFO(dev)->gen < 4) {
- /* Enable pixel doubling when the dot clock is > 90% of the (display)
- * core speed.
- *
- * XXX: No double-wide on 915GM pipe B. Is that the only reason for the
- * pipe == 0 check?
- */
- if (intel_crtc->config.requested_mode.clock >
- dev_priv->display.get_display_clock_speed(dev) * 9 / 10)
- pipeconf |= PIPECONF_DOUBLE_WIDE;
- }
+ if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
+ I915_READ(PIPECONF(intel_crtc->pipe)) & PIPECONF_ENABLE)
+ pipeconf |= PIPECONF_ENABLE;
+
+ if (intel_crtc->config.double_wide)
+ pipeconf |= PIPECONF_DOUBLE_WIDE;
/* only g4x and later have fancy bpc/dither controls */
if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
@@ -4839,14 +4940,13 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
int pipe = intel_crtc->pipe;
int plane = intel_crtc->plane;
int refclk, num_connectors = 0;
intel_clock_t clock, reduced_clock;
u32 dspcntr;
bool ok, has_reduced_clock = false;
- bool is_lvds = false;
+ bool is_lvds = false, is_dsi = false;
struct intel_encoder *encoder;
const intel_limit_t *limit;
int ret;
@@ -4856,42 +4956,49 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
case INTEL_OUTPUT_LVDS:
is_lvds = true;
break;
+ case INTEL_OUTPUT_DSI:
+ is_dsi = true;
+ break;
}
num_connectors++;
}
- refclk = i9xx_get_refclk(crtc, num_connectors);
+ if (is_dsi)
+ goto skip_dpll;
- /*
- * Returns a set of divisors for the desired target clock with the given
- * refclk, or FALSE. The returned values represent the clock equation:
- * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
- */
- limit = intel_limit(crtc, refclk);
- ok = dev_priv->display.find_dpll(limit, crtc,
- intel_crtc->config.port_clock,
- refclk, NULL, &clock);
- if (!ok && !intel_crtc->config.clock_set) {
- DRM_ERROR("Couldn't find PLL settings for mode!\n");
- return -EINVAL;
- }
+ if (!intel_crtc->config.clock_set) {
+ refclk = i9xx_get_refclk(crtc, num_connectors);
- if (is_lvds && dev_priv->lvds_downclock_avail) {
/*
- * Ensure we match the reduced clock's P to the target clock.
- * If the clocks don't match, we can't switch the display clock
- * by using the FP0/FP1. In such case we will disable the LVDS
- * downclock feature.
- */
- has_reduced_clock =
- dev_priv->display.find_dpll(limit, crtc,
- dev_priv->lvds_downclock,
- refclk, &clock,
- &reduced_clock);
- }
- /* Compat-code for transition, will disappear. */
- if (!intel_crtc->config.clock_set) {
+ * Returns a set of divisors for the desired target clock with
+ * the given refclk, or FALSE. The returned values represent
+ * the clock equation: reflck * (5 * (m1 + 2) + (m2 + 2)) / (n +
+ * 2) / p1 / p2.
+ */
+ limit = intel_limit(crtc, refclk);
+ ok = dev_priv->display.find_dpll(limit, crtc,
+ intel_crtc->config.port_clock,
+ refclk, NULL, &clock);
+ if (!ok) {
+ DRM_ERROR("Couldn't find PLL settings for mode!\n");
+ return -EINVAL;
+ }
+
+ if (is_lvds && dev_priv->lvds_downclock_avail) {
+ /*
+ * Ensure we match the reduced clock's P to the target
+ * clock. If the clocks don't match, we can't switch
+ * the display clock by using the FP0/FP1. In such case
+ * we will disable the LVDS downclock feature.
+ */
+ has_reduced_clock =
+ dev_priv->display.find_dpll(limit, crtc,
+ dev_priv->lvds_downclock,
+ refclk, &clock,
+ &reduced_clock);
+ }
+ /* Compat-code for transition, will disappear. */
intel_crtc->config.dpll.n = clock.n;
intel_crtc->config.dpll.m1 = clock.m1;
intel_crtc->config.dpll.m2 = clock.m2;
@@ -4899,17 +5006,19 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
intel_crtc->config.dpll.p2 = clock.p2;
}
- if (IS_GEN2(dev))
+ if (IS_GEN2(dev)) {
i8xx_update_pll(intel_crtc,
has_reduced_clock ? &reduced_clock : NULL,
num_connectors);
- else if (IS_VALLEYVIEW(dev))
+ } else if (IS_VALLEYVIEW(dev)) {
vlv_update_pll(intel_crtc);
- else
+ } else {
i9xx_update_pll(intel_crtc,
has_reduced_clock ? &reduced_clock : NULL,
num_connectors);
+ }
+skip_dpll:
/* Set up the display plane register */
dspcntr = DISPPLANE_GAMMA_ENABLE;
@@ -4926,8 +5035,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
* which should always be the user's requested size.
*/
I915_WRITE(DSPSIZE(plane),
- ((mode->vdisplay - 1) << 16) |
- (mode->hdisplay - 1));
+ ((intel_crtc->config.pipe_src_h - 1) << 16) |
+ (intel_crtc->config.pipe_src_w - 1));
I915_WRITE(DSPPOS(plane), 0);
i9xx_set_pipeconf(intel_crtc);
@@ -4937,8 +5046,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
ret = intel_pipe_set_base(crtc, x, y, fb);
- intel_update_watermarks(dev);
-
return ret;
}
@@ -4969,6 +5076,32 @@ static void i9xx_get_pfit_config(struct intel_crtc *crtc,
I915_READ(LVDS) & LVDS_BORDER_ENABLE;
}
+static void vlv_crtc_clock_get(struct intel_crtc *crtc,
+ struct intel_crtc_config *pipe_config)
+{
+ struct drm_device *dev = crtc->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int pipe = pipe_config->cpu_transcoder;
+ intel_clock_t clock;
+ u32 mdiv;
+ int refclk = 100000;
+
+ mutex_lock(&dev_priv->dpio_lock);
+ mdiv = vlv_dpio_read(dev_priv, pipe, DPIO_DIV(pipe));
+ mutex_unlock(&dev_priv->dpio_lock);
+
+ clock.m1 = (mdiv >> DPIO_M1DIV_SHIFT) & 7;
+ clock.m2 = mdiv & DPIO_M2DIV_MASK;
+ clock.n = (mdiv >> DPIO_N_SHIFT) & 0xf;
+ clock.p1 = (mdiv >> DPIO_P1_SHIFT) & 7;
+ clock.p2 = (mdiv >> DPIO_P2_SHIFT) & 0x1f;
+
+ clock.vco = refclk * clock.m1 * clock.m2 / clock.n;
+ clock.dot = 2 * clock.vco / (clock.p1 * clock.p2);
+
+ pipe_config->port_clock = clock.dot / 10;
+}
+
static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
struct intel_crtc_config *pipe_config)
{
@@ -4983,6 +5116,25 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
if (!(tmp & PIPECONF_ENABLE))
return false;
+ if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
+ switch (tmp & PIPECONF_BPC_MASK) {
+ case PIPECONF_6BPC:
+ pipe_config->pipe_bpp = 18;
+ break;
+ case PIPECONF_8BPC:
+ pipe_config->pipe_bpp = 24;
+ break;
+ case PIPECONF_10BPC:
+ pipe_config->pipe_bpp = 30;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (INTEL_INFO(dev)->gen < 4)
+ pipe_config->double_wide = tmp & PIPECONF_DOUBLE_WIDE;
+
intel_get_pipe_timings(crtc, pipe_config);
i9xx_get_pfit_config(crtc, pipe_config);
@@ -5015,6 +5167,11 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
DPLL_PORTB_READY_MASK);
}
+ if (IS_VALLEYVIEW(dev))
+ vlv_crtc_clock_get(crtc, pipe_config);
+ else
+ i9xx_crtc_clock_get(crtc, pipe_config);
+
return true;
}
@@ -5822,25 +5979,67 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
ret = intel_pipe_set_base(crtc, x, y, fb);
- intel_update_watermarks(dev);
-
return ret;
}
-static void ironlake_get_fdi_m_n_config(struct intel_crtc *crtc,
- struct intel_crtc_config *pipe_config)
+static void intel_pch_transcoder_get_m_n(struct intel_crtc *crtc,
+ struct intel_link_m_n *m_n)
{
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
- enum transcoder transcoder = pipe_config->cpu_transcoder;
+ enum pipe pipe = crtc->pipe;
- pipe_config->fdi_m_n.link_m = I915_READ(PIPE_LINK_M1(transcoder));
- pipe_config->fdi_m_n.link_n = I915_READ(PIPE_LINK_N1(transcoder));
- pipe_config->fdi_m_n.gmch_m = I915_READ(PIPE_DATA_M1(transcoder))
- & ~TU_SIZE_MASK;
- pipe_config->fdi_m_n.gmch_n = I915_READ(PIPE_DATA_N1(transcoder));
- pipe_config->fdi_m_n.tu = ((I915_READ(PIPE_DATA_M1(transcoder))
- & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1;
+ m_n->link_m = I915_READ(PCH_TRANS_LINK_M1(pipe));
+ m_n->link_n = I915_READ(PCH_TRANS_LINK_N1(pipe));
+ m_n->gmch_m = I915_READ(PCH_TRANS_DATA_M1(pipe))
+ & ~TU_SIZE_MASK;
+ m_n->gmch_n = I915_READ(PCH_TRANS_DATA_N1(pipe));
+ m_n->tu = ((I915_READ(PCH_TRANS_DATA_M1(pipe))
+ & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1;
+}
+
+static void intel_cpu_transcoder_get_m_n(struct intel_crtc *crtc,
+ enum transcoder transcoder,
+ struct intel_link_m_n *m_n)
+{
+ struct drm_device *dev = crtc->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ enum pipe pipe = crtc->pipe;
+
+ if (INTEL_INFO(dev)->gen >= 5) {
+ m_n->link_m = I915_READ(PIPE_LINK_M1(transcoder));
+ m_n->link_n = I915_READ(PIPE_LINK_N1(transcoder));
+ m_n->gmch_m = I915_READ(PIPE_DATA_M1(transcoder))
+ & ~TU_SIZE_MASK;
+ m_n->gmch_n = I915_READ(PIPE_DATA_N1(transcoder));
+ m_n->tu = ((I915_READ(PIPE_DATA_M1(transcoder))
+ & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1;
+ } else {
+ m_n->link_m = I915_READ(PIPE_LINK_M_G4X(pipe));
+ m_n->link_n = I915_READ(PIPE_LINK_N_G4X(pipe));
+ m_n->gmch_m = I915_READ(PIPE_DATA_M_G4X(pipe))
+ & ~TU_SIZE_MASK;
+ m_n->gmch_n = I915_READ(PIPE_DATA_N_G4X(pipe));
+ m_n->tu = ((I915_READ(PIPE_DATA_M_G4X(pipe))
+ & TU_SIZE_MASK) >> TU_SIZE_SHIFT) + 1;
+ }
+}
+
+void intel_dp_get_m_n(struct intel_crtc *crtc,
+ struct intel_crtc_config *pipe_config)
+{
+ if (crtc->config.has_pch_encoder)
+ intel_pch_transcoder_get_m_n(crtc, &pipe_config->dp_m_n);
+ else
+ intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder,
+ &pipe_config->dp_m_n);
+}
+
+static void ironlake_get_fdi_m_n_config(struct intel_crtc *crtc,
+ struct intel_crtc_config *pipe_config)
+{
+ intel_cpu_transcoder_get_m_n(crtc, pipe_config->cpu_transcoder,
+ &pipe_config->fdi_m_n);
}
static void ironlake_get_pfit_config(struct intel_crtc *crtc,
@@ -5881,6 +6080,23 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
if (!(tmp & PIPECONF_ENABLE))
return false;
+ switch (tmp & PIPECONF_BPC_MASK) {
+ case PIPECONF_6BPC:
+ pipe_config->pipe_bpp = 18;
+ break;
+ case PIPECONF_8BPC:
+ pipe_config->pipe_bpp = 24;
+ break;
+ case PIPECONF_10BPC:
+ pipe_config->pipe_bpp = 30;
+ break;
+ case PIPECONF_12BPC:
+ pipe_config->pipe_bpp = 36;
+ break;
+ default:
+ break;
+ }
+
if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) {
struct intel_shared_dpll *pll;
@@ -5912,6 +6128,8 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
pipe_config->pixel_multiplier =
((tmp & PLL_REF_SDVO_HDMI_MULTIPLIER_MASK)
>> PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT) + 1;
+
+ ironlake_pch_clock_get(crtc, pipe_config);
} else {
pipe_config->pixel_multiplier = 1;
}
@@ -5968,8 +6186,8 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
* register. Callers should take care of disabling all the display engine
* functions, doing the mode unset, fixing interrupts, etc.
*/
-void hsw_disable_lcpll(struct drm_i915_private *dev_priv,
- bool switch_to_fclk, bool allow_power_down)
+static void hsw_disable_lcpll(struct drm_i915_private *dev_priv,
+ bool switch_to_fclk, bool allow_power_down)
{
uint32_t val;
@@ -5997,7 +6215,10 @@ void hsw_disable_lcpll(struct drm_i915_private *dev_priv,
val = I915_READ(D_COMP);
val |= D_COMP_COMP_DISABLE;
- I915_WRITE(D_COMP, val);
+ mutex_lock(&dev_priv->rps.hw_lock);
+ if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP, val))
+ DRM_ERROR("Failed to disable D_COMP\n");
+ mutex_unlock(&dev_priv->rps.hw_lock);
POSTING_READ(D_COMP);
ndelay(100);
@@ -6016,7 +6237,7 @@ void hsw_disable_lcpll(struct drm_i915_private *dev_priv,
* Fully restores LCPLL, disallowing power down and switching back to LCPLL
* source.
*/
-void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
+static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
{
uint32_t val;
@@ -6039,7 +6260,10 @@ void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
val = I915_READ(D_COMP);
val |= D_COMP_COMP_FORCE;
val &= ~D_COMP_COMP_DISABLE;
- I915_WRITE(D_COMP, val);
+ mutex_lock(&dev_priv->rps.hw_lock);
+ if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP, val))
+ DRM_ERROR("Failed to enable D_COMP\n");
+ mutex_unlock(&dev_priv->rps.hw_lock);
POSTING_READ(D_COMP);
val = I915_READ(LCPLL_CTL);
@@ -6276,8 +6500,6 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
ret = intel_pipe_set_base(crtc, x, y, fb);
- intel_update_watermarks(dev);
-
return ret;
}
@@ -6640,49 +6862,6 @@ void intel_write_eld(struct drm_encoder *encoder,
dev_priv->display.write_eld(connector, crtc);
}
-/** Loads the palette/gamma unit for the CRTC with the prepared values */
-void intel_crtc_load_lut(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- enum pipe pipe = intel_crtc->pipe;
- int palreg = PALETTE(pipe);
- int i;
- bool reenable_ips = false;
-
- /* The clocks have to be on to load the palette. */
- if (!crtc->enabled || !intel_crtc->active)
- return;
-
- if (!HAS_PCH_SPLIT(dev_priv->dev))
- assert_pll_enabled(dev_priv, pipe);
-
- /* use legacy palette for Ironlake */
- if (HAS_PCH_SPLIT(dev))
- palreg = LGC_PALETTE(pipe);
-
- /* Workaround : Do not read or write the pipe palette/gamma data while
- * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
- */
- if (intel_crtc->config.ips_enabled &&
- ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
- GAMMA_MODE_MODE_SPLIT)) {
- hsw_disable_ips(intel_crtc);
- reenable_ips = true;
- }
-
- for (i = 0; i < 256; i++) {
- I915_WRITE(palreg + 4 * i,
- (intel_crtc->lut_r[i] << 16) |
- (intel_crtc->lut_g[i] << 8) |
- intel_crtc->lut_b[i]);
- }
-
- if (reenable_ips)
- hsw_enable_ips(intel_crtc);
-}
-
static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
{
struct drm_device *dev = crtc->dev;
@@ -6778,23 +6957,20 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
int pipe = intel_crtc->pipe;
int x = intel_crtc->cursor_x;
int y = intel_crtc->cursor_y;
- u32 base, pos;
+ u32 base = 0, pos = 0;
bool visible;
- pos = 0;
-
- if (on && crtc->enabled && crtc->fb) {
+ if (on)
base = intel_crtc->cursor_addr;
- if (x > (int) crtc->fb->width)
- base = 0;
- if (y > (int) crtc->fb->height)
- base = 0;
- } else
+ if (x >= intel_crtc->config.pipe_src_w)
+ base = 0;
+
+ if (y >= intel_crtc->config.pipe_src_h)
base = 0;
if (x < 0) {
- if (x + intel_crtc->cursor_width < 0)
+ if (x + intel_crtc->cursor_width <= 0)
base = 0;
pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
@@ -6803,7 +6979,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
pos |= x << CURSOR_X_SHIFT;
if (y < 0) {
- if (y + intel_crtc->cursor_height < 0)
+ if (y + intel_crtc->cursor_height <= 0)
base = 0;
pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
@@ -6955,27 +7131,6 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
return 0;
}
-/** Sets the color ramps on behalf of RandR */
-void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
- u16 blue, int regno)
-{
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
- intel_crtc->lut_r[regno] = red >> 8;
- intel_crtc->lut_g[regno] = green >> 8;
- intel_crtc->lut_b[regno] = blue >> 8;
-}
-
-void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
- u16 *blue, int regno)
-{
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
- *red = intel_crtc->lut_r[regno] << 8;
- *green = intel_crtc->lut_g[regno] << 8;
- *blue = intel_crtc->lut_b[regno] << 8;
-}
-
static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
u16 *blue, uint32_t start, uint32_t size)
{
@@ -7224,6 +7379,22 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
mutex_unlock(&crtc->mutex);
}
+static int i9xx_pll_refclk(struct drm_device *dev,
+ const struct intel_crtc_config *pipe_config)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ u32 dpll = pipe_config->dpll_hw_state.dpll;
+
+ if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
+ return dev_priv->vbt.lvds_ssc_freq * 1000;
+ else if (HAS_PCH_SPLIT(dev))
+ return 120000;
+ else if (!IS_GEN2(dev))
+ return 96000;
+ else
+ return 48000;
+}
+
/* Returns the clock of the currently programmed mode of the given pipe. */
static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
struct intel_crtc_config *pipe_config)
@@ -7231,14 +7402,15 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int pipe = pipe_config->cpu_transcoder;
- u32 dpll = I915_READ(DPLL(pipe));
+ u32 dpll = pipe_config->dpll_hw_state.dpll;
u32 fp;
intel_clock_t clock;
+ int refclk = i9xx_pll_refclk(dev, pipe_config);
if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
- fp = I915_READ(FP0(pipe));
+ fp = pipe_config->dpll_hw_state.fp0;
else
- fp = I915_READ(FP1(pipe));
+ fp = pipe_config->dpll_hw_state.fp1;
clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
if (IS_PINEVIEW(dev)) {
@@ -7269,14 +7441,13 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
default:
DRM_DEBUG_KMS("Unknown DPLL mode %08x in programmed "
"mode\n", (int)(dpll & DPLL_MODE_MASK));
- pipe_config->adjusted_mode.clock = 0;
return;
}
if (IS_PINEVIEW(dev))
- pineview_clock(96000, &clock);
+ pineview_clock(refclk, &clock);
else
- i9xx_clock(96000, &clock);
+ i9xx_clock(refclk, &clock);
} else {
bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
@@ -7284,13 +7455,6 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
DPLL_FPA01_P1_POST_DIV_SHIFT);
clock.p2 = 14;
-
- if ((dpll & PLL_REF_INPUT_MASK) ==
- PLLB_REF_INPUT_SPREADSPECTRUMIN) {
- /* XXX: might not be 66MHz */
- i9xx_clock(66000, &clock);
- } else
- i9xx_clock(48000, &clock);
} else {
if (dpll & PLL_P1_DIVIDE_BY_TWO)
clock.p1 = 2;
@@ -7302,59 +7466,55 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
clock.p2 = 4;
else
clock.p2 = 2;
-
- i9xx_clock(48000, &clock);
}
+
+ i9xx_clock(refclk, &clock);
}
- pipe_config->adjusted_mode.clock = clock.dot;
+ /*
+ * This value includes pixel_multiplier. We will use
+ * port_clock to compute adjusted_mode.crtc_clock in the
+ * encoder's get_config() function.
+ */
+ pipe_config->port_clock = clock.dot;
}
-static void ironlake_crtc_clock_get(struct intel_crtc *crtc,
- struct intel_crtc_config *pipe_config)
+int intel_dotclock_calculate(int link_freq,
+ const struct intel_link_m_n *m_n)
{
- struct drm_device *dev = crtc->base.dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
- int link_freq, repeat;
- u64 clock;
- u32 link_m, link_n;
-
- repeat = pipe_config->pixel_multiplier;
-
/*
* The calculation for the data clock is:
- * pixel_clock = ((m/n)*(link_clock * nr_lanes * repeat))/bpp
+ * pixel_clock = ((m/n)*(link_clock * nr_lanes))/bpp
* But we want to avoid losing precison if possible, so:
- * pixel_clock = ((m * link_clock * nr_lanes * repeat)/(n*bpp))
+ * pixel_clock = ((m * link_clock * nr_lanes)/(n*bpp))
*
* and the link clock is simpler:
- * link_clock = (m * link_clock * repeat) / n
+ * link_clock = (m * link_clock) / n
*/
- /*
- * We need to get the FDI or DP link clock here to derive
- * the M/N dividers.
- *
- * For FDI, we read it from the BIOS or use a fixed 2.7GHz.
- * For DP, it's either 1.62GHz or 2.7GHz.
- * We do our calculations in 10*MHz since we don't need much precison.
- */
- if (pipe_config->has_pch_encoder)
- link_freq = intel_fdi_link_freq(dev) * 10000;
- else
- link_freq = pipe_config->port_clock;
+ if (!m_n->link_n)
+ return 0;
- link_m = I915_READ(PIPE_LINK_M1(cpu_transcoder));
- link_n = I915_READ(PIPE_LINK_N1(cpu_transcoder));
+ return div_u64((u64)m_n->link_m * link_freq, m_n->link_n);
+}
- if (!link_m || !link_n)
- return;
+static void ironlake_pch_clock_get(struct intel_crtc *crtc,
+ struct intel_crtc_config *pipe_config)
+{
+ struct drm_device *dev = crtc->base.dev;
- clock = ((u64)link_m * (u64)link_freq * (u64)repeat);
- do_div(clock, link_n);
+ /* read out port_clock from the DPLL */
+ i9xx_crtc_clock_get(crtc, pipe_config);
- pipe_config->adjusted_mode.clock = clock;
+ /*
+ * This value does not include pixel_multiplier.
+ * We will check that port_clock and adjusted_mode.crtc_clock
+ * agree once we know their relationship in the encoder's
+ * get_config() function.
+ */
+ pipe_config->adjusted_mode.crtc_clock =
+ intel_dotclock_calculate(intel_fdi_link_freq(dev) * 10000,
+ &pipe_config->fdi_m_n);
}
/** Returns the currently programmed mode of the given pipe. */
@@ -7370,6 +7530,7 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
int hsync = I915_READ(HSYNC(cpu_transcoder));
int vtot = I915_READ(VTOTAL(cpu_transcoder));
int vsync = I915_READ(VSYNC(cpu_transcoder));
+ enum pipe pipe = intel_crtc->pipe;
mode = kzalloc(sizeof(*mode), GFP_KERNEL);
if (!mode)
@@ -7382,11 +7543,14 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
* Note, if LVDS ever uses a non-1 pixel multiplier, we'll need
* to use a real value here instead.
*/
- pipe_config.cpu_transcoder = (enum transcoder) intel_crtc->pipe;
+ pipe_config.cpu_transcoder = (enum transcoder) pipe;
pipe_config.pixel_multiplier = 1;
+ pipe_config.dpll_hw_state.dpll = I915_READ(DPLL(pipe));
+ pipe_config.dpll_hw_state.fp0 = I915_READ(FP0(pipe));
+ pipe_config.dpll_hw_state.fp1 = I915_READ(FP1(pipe));
i9xx_crtc_clock_get(intel_crtc, &pipe_config);
- mode->clock = pipe_config.adjusted_mode.clock;
+ mode->clock = pipe_config.port_clock / pipe_config.pixel_multiplier;
mode->hdisplay = (htot & 0xffff) + 1;
mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
mode->hsync_start = (hsync & 0xffff) + 1;
@@ -7680,7 +7844,7 @@ static int intel_gen2_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, 0); /* aux display base address, unused */
intel_mark_page_flip_active(intel_crtc);
- intel_ring_advance(ring);
+ __intel_ring_advance(ring);
return 0;
err_unpin:
@@ -7722,7 +7886,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, MI_NOOP);
intel_mark_page_flip_active(intel_crtc);
- intel_ring_advance(ring);
+ __intel_ring_advance(ring);
return 0;
err_unpin:
@@ -7771,7 +7935,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, pf | pipesrc);
intel_mark_page_flip_active(intel_crtc);
- intel_ring_advance(ring);
+ __intel_ring_advance(ring);
return 0;
err_unpin:
@@ -7816,7 +7980,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, pf | pipesrc);
intel_mark_page_flip_active(intel_crtc);
- intel_ring_advance(ring);
+ __intel_ring_advance(ring);
return 0;
err_unpin:
@@ -7895,7 +8059,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
intel_ring_emit(ring, (MI_NOOP));
intel_mark_page_flip_active(intel_crtc);
- intel_ring_advance(ring);
+ __intel_ring_advance(ring);
return 0;
err_unpin:
@@ -7940,7 +8104,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
fb->pitches[0] != crtc->fb->pitches[0]))
return -EINVAL;
- work = kzalloc(sizeof *work, GFP_KERNEL);
+ work = kzalloc(sizeof(*work), GFP_KERNEL);
if (work == NULL)
return -ENOMEM;
@@ -8175,6 +8339,17 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc,
return bpp;
}
+static void intel_dump_crtc_timings(const struct drm_display_mode *mode)
+{
+ DRM_DEBUG_KMS("crtc timings: %d %d %d %d %d %d %d %d %d, "
+ "type: 0x%x flags: 0x%x\n",
+ mode->crtc_clock,
+ mode->crtc_hdisplay, mode->crtc_hsync_start,
+ mode->crtc_hsync_end, mode->crtc_htotal,
+ mode->crtc_vdisplay, mode->crtc_vsync_start,
+ mode->crtc_vsync_end, mode->crtc_vtotal, mode->type, mode->flags);
+}
+
static void intel_dump_pipe_config(struct intel_crtc *crtc,
struct intel_crtc_config *pipe_config,
const char *context)
@@ -8191,10 +8366,19 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
pipe_config->fdi_m_n.gmch_m, pipe_config->fdi_m_n.gmch_n,
pipe_config->fdi_m_n.link_m, pipe_config->fdi_m_n.link_n,
pipe_config->fdi_m_n.tu);
+ DRM_DEBUG_KMS("dp: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n",
+ pipe_config->has_dp_encoder,
+ pipe_config->dp_m_n.gmch_m, pipe_config->dp_m_n.gmch_n,
+ pipe_config->dp_m_n.link_m, pipe_config->dp_m_n.link_n,
+ pipe_config->dp_m_n.tu);
DRM_DEBUG_KMS("requested mode:\n");
drm_mode_debug_printmodeline(&pipe_config->requested_mode);
DRM_DEBUG_KMS("adjusted mode:\n");
drm_mode_debug_printmodeline(&pipe_config->adjusted_mode);
+ intel_dump_crtc_timings(&pipe_config->adjusted_mode);
+ DRM_DEBUG_KMS("port clock: %d\n", pipe_config->port_clock);
+ DRM_DEBUG_KMS("pipe src size: %dx%d\n",
+ pipe_config->pipe_src_w, pipe_config->pipe_src_h);
DRM_DEBUG_KMS("gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n",
pipe_config->gmch_pfit.control,
pipe_config->gmch_pfit.pgm_ratios,
@@ -8204,6 +8388,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
pipe_config->pch_pfit.size,
pipe_config->pch_pfit.enabled ? "enabled" : "disabled");
DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled);
+ DRM_DEBUG_KMS("double wide: %i\n", pipe_config->double_wide);
}
static bool check_encoder_cloning(struct drm_crtc *crtc)
@@ -8247,6 +8432,7 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
drm_mode_copy(&pipe_config->adjusted_mode, mode);
drm_mode_copy(&pipe_config->requested_mode, mode);
+
pipe_config->cpu_transcoder =
(enum transcoder) to_intel_crtc(crtc)->pipe;
pipe_config->shared_dpll = DPLL_ID_PRIVATE;
@@ -8279,7 +8465,11 @@ encoder_retry:
pipe_config->pixel_multiplier = 1;
/* Fill in default crtc timings, allow encoders to overwrite them. */
- drm_mode_set_crtcinfo(&pipe_config->adjusted_mode, 0);
+ drm_mode_set_crtcinfo(&pipe_config->adjusted_mode, CRTC_STEREO_DOUBLE);
+
+ /* set_crtcinfo() may have adjusted hdisplay/vdisplay */
+ pipe_config->pipe_src_w = pipe_config->adjusted_mode.crtc_hdisplay;
+ pipe_config->pipe_src_h = pipe_config->adjusted_mode.crtc_vdisplay;
/* Pass our mode to the connectors and the CRTC to give them a chance to
* adjust it according to limitations or connector properties, and also
@@ -8300,7 +8490,8 @@ encoder_retry:
/* Set default port clock if not overwritten by the encoder. Needs to be
* done afterwards in case the encoder adjusts the mode. */
if (!pipe_config->port_clock)
- pipe_config->port_clock = pipe_config->adjusted_mode.clock;
+ pipe_config->port_clock = pipe_config->adjusted_mode.crtc_clock
+ * pipe_config->pixel_multiplier;
ret = intel_crtc_compute_config(to_intel_crtc(crtc), pipe_config);
if (ret < 0) {
@@ -8487,13 +8678,9 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
}
-static bool intel_fuzzy_clock_check(struct intel_crtc_config *cur,
- struct intel_crtc_config *new)
+static bool intel_fuzzy_clock_check(int clock1, int clock2)
{
- int clock1, clock2, diff;
-
- clock1 = cur->adjusted_mode.clock;
- clock2 = new->adjusted_mode.clock;
+ int diff;
if (clock1 == clock2)
return true;
@@ -8547,6 +8734,15 @@ intel_pipe_config_compare(struct drm_device *dev,
return false; \
}
+#define PIPE_CONF_CHECK_CLOCK_FUZZY(name) \
+ if (!intel_fuzzy_clock_check(current_config->name, pipe_config->name)) { \
+ DRM_ERROR("mismatch in " #name " " \
+ "(expected %i, found %i)\n", \
+ current_config->name, \
+ pipe_config->name); \
+ return false; \
+ }
+
#define PIPE_CONF_QUIRK(quirk) \
((current_config->quirks | pipe_config->quirks) & (quirk))
@@ -8560,6 +8756,13 @@ intel_pipe_config_compare(struct drm_device *dev,
PIPE_CONF_CHECK_I(fdi_m_n.link_n);
PIPE_CONF_CHECK_I(fdi_m_n.tu);
+ PIPE_CONF_CHECK_I(has_dp_encoder);
+ PIPE_CONF_CHECK_I(dp_m_n.gmch_m);
+ PIPE_CONF_CHECK_I(dp_m_n.gmch_n);
+ PIPE_CONF_CHECK_I(dp_m_n.link_m);
+ PIPE_CONF_CHECK_I(dp_m_n.link_n);
+ PIPE_CONF_CHECK_I(dp_m_n.tu);
+
PIPE_CONF_CHECK_I(adjusted_mode.crtc_hdisplay);
PIPE_CONF_CHECK_I(adjusted_mode.crtc_htotal);
PIPE_CONF_CHECK_I(adjusted_mode.crtc_hblank_start);
@@ -8590,8 +8793,8 @@ intel_pipe_config_compare(struct drm_device *dev,
DRM_MODE_FLAG_NVSYNC);
}
- PIPE_CONF_CHECK_I(requested_mode.hdisplay);
- PIPE_CONF_CHECK_I(requested_mode.vdisplay);
+ 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+ */
@@ -8606,26 +8809,28 @@ intel_pipe_config_compare(struct drm_device *dev,
PIPE_CONF_CHECK_I(ips_enabled);
+ PIPE_CONF_CHECK_I(double_wide);
+
PIPE_CONF_CHECK_I(shared_dpll);
PIPE_CONF_CHECK_X(dpll_hw_state.dpll);
PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md);
PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
PIPE_CONF_CHECK_X(dpll_hw_state.fp1);
+ if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5)
+ PIPE_CONF_CHECK_I(pipe_bpp);
+
+ if (!IS_HASWELL(dev)) {
+ PIPE_CONF_CHECK_CLOCK_FUZZY(adjusted_mode.crtc_clock);
+ PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock);
+ }
+
#undef PIPE_CONF_CHECK_X
#undef PIPE_CONF_CHECK_I
#undef PIPE_CONF_CHECK_FLAGS
+#undef PIPE_CONF_CHECK_CLOCK_FUZZY
#undef PIPE_CONF_QUIRK
- if (!IS_HASWELL(dev)) {
- if (!intel_fuzzy_clock_check(current_config, pipe_config)) {
- DRM_ERROR("mismatch in clock (expected %d, found %d)\n",
- current_config->adjusted_mode.clock,
- pipe_config->adjusted_mode.clock);
- return false;
- }
- }
-
return true;
}
@@ -8757,9 +8962,6 @@ check_crtc_state(struct drm_device *dev)
encoder->get_config(encoder, &pipe_config);
}
- if (dev_priv->display.get_clock)
- dev_priv->display.get_clock(crtc, &pipe_config);
-
WARN(crtc->active != active,
"crtc active state doesn't match with hw state "
"(expected %i, found %i)\n", crtc->active, active);
@@ -8834,6 +9036,18 @@ intel_modeset_check_state(struct drm_device *dev)
check_shared_dpll_state(dev);
}
+void ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config,
+ int dotclock)
+{
+ /*
+ * FDI already provided one idea for the dotclock.
+ * Yell if the encoder disagrees.
+ */
+ WARN(!intel_fuzzy_clock_check(pipe_config->adjusted_mode.crtc_clock, dotclock),
+ "FDI dotclock and encoder dotclock mismatch, fdi: %i, encoder: %i\n",
+ pipe_config->adjusted_mode.crtc_clock, dotclock);
+}
+
static int __intel_set_mode(struct drm_crtc *crtc,
struct drm_display_mode *mode,
int x, int y, struct drm_framebuffer *fb)
@@ -8846,7 +9060,7 @@ static int __intel_set_mode(struct drm_crtc *crtc,
unsigned disable_pipes, prepare_pipes, modeset_pipes;
int ret = 0;
- saved_mode = kmalloc(2 * sizeof(*saved_mode), GFP_KERNEL);
+ saved_mode = kcalloc(2, sizeof(*saved_mode), GFP_KERNEL);
if (!saved_mode)
return -ENOMEM;
saved_hwmode = saved_mode + 1;
@@ -9385,7 +9599,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
struct intel_crtc *intel_crtc;
int i;
- intel_crtc = kzalloc(sizeof(struct intel_crtc) + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
+ intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL);
if (intel_crtc == NULL)
return;
@@ -9551,6 +9765,8 @@ static void intel_setup_outputs(struct drm_device *dev)
if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED)
intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B);
}
+
+ intel_dsi_init(dev);
} else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) {
bool found = false;
@@ -9783,7 +9999,6 @@ static void intel_init_display(struct drm_device *dev)
dev_priv->display.update_plane = ironlake_update_plane;
} else if (HAS_PCH_SPLIT(dev)) {
dev_priv->display.get_pipe_config = ironlake_get_pipe_config;
- dev_priv->display.get_clock = ironlake_crtc_clock_get;
dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set;
dev_priv->display.crtc_enable = ironlake_crtc_enable;
dev_priv->display.crtc_disable = ironlake_crtc_disable;
@@ -9791,7 +10006,6 @@ static void intel_init_display(struct drm_device *dev)
dev_priv->display.update_plane = ironlake_update_plane;
} else if (IS_VALLEYVIEW(dev)) {
dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
- dev_priv->display.get_clock = i9xx_crtc_clock_get;
dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
dev_priv->display.crtc_enable = valleyview_crtc_enable;
dev_priv->display.crtc_disable = i9xx_crtc_disable;
@@ -9799,7 +10013,6 @@ static void intel_init_display(struct drm_device *dev)
dev_priv->display.update_plane = i9xx_update_plane;
} else {
dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
- dev_priv->display.get_clock = i9xx_crtc_clock_get;
dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
dev_priv->display.crtc_enable = i9xx_crtc_enable;
dev_priv->display.crtc_disable = i9xx_crtc_disable;
@@ -9985,20 +10198,11 @@ static struct intel_quirk intel_quirks[] = {
/* Sony Vaio Y cannot use SSC on LVDS */
{ 0x0046, 0x104d, 0x9076, quirk_ssc_force_disable },
- /* Acer Aspire 5734Z must invert backlight brightness */
- { 0x2a42, 0x1025, 0x0459, quirk_invert_brightness },
-
- /* Acer/eMachines G725 */
- { 0x2a42, 0x1025, 0x0210, quirk_invert_brightness },
-
- /* Acer/eMachines e725 */
- { 0x2a42, 0x1025, 0x0212, quirk_invert_brightness },
-
- /* Acer/Packard Bell NCL20 */
- { 0x2a42, 0x1025, 0x034b, quirk_invert_brightness },
-
- /* Acer Aspire 4736Z */
- { 0x2a42, 0x1025, 0x0260, quirk_invert_brightness },
+ /*
+ * All GM45 Acer (and its brands eMachines and Packard Bell) laptops
+ * seem to use inverted backlight PWM.
+ */
+ { 0x2a42, 0x1025, PCI_ANY_ID, quirk_invert_brightness },
/* Dell XPS13 HD Sandy Bridge */
{ 0x0116, 0x1028, 0x052e, quirk_no_pcm_pwm_enable },
@@ -10074,8 +10278,6 @@ void i915_disable_vga_mem(struct drm_device *dev)
void intel_modeset_init_hw(struct drm_device *dev)
{
- intel_init_power_well(dev);
-
intel_prepare_ddi(dev);
intel_init_clock_gating(dev);
@@ -10418,15 +10620,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
pipe);
}
- list_for_each_entry(crtc, &dev->mode_config.crtc_list,
- base.head) {
- if (!crtc->active)
- continue;
- if (dev_priv->display.get_clock)
- dev_priv->display.get_clock(crtc,
- &crtc->config);
- }
-
list_for_each_entry(connector, &dev->mode_config.connector_list,
base.head) {
if (connector->get_hw_state(connector)) {
@@ -10451,7 +10644,6 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
{
struct drm_i915_private *dev_priv = dev->dev_private;
enum pipe pipe;
- struct drm_plane *plane;
struct intel_crtc *crtc;
struct intel_encoder *encoder;
int i;
@@ -10499,6 +10691,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
}
if (force_restore) {
+ i915_redisable_vga(dev);
+
/*
* We need to use raw interfaces for restoring state to avoid
* checking (bogus) intermediate states.
@@ -10510,10 +10704,6 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
__intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y,
crtc->fb);
}
- list_for_each_entry(plane, &dev->mode_config.plane_list, head)
- intel_plane_restore(plane);
-
- i915_redisable_vga(dev);
} else {
intel_modeset_update_staged_output_state(dev);
}
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 2151d13772b8..95a31598feda 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -38,6 +38,32 @@
#define DP_LINK_CHECK_TIMEOUT (10 * 1000)
+struct dp_link_dpll {
+ int link_bw;
+ struct dpll dpll;
+};
+
+static const struct dp_link_dpll gen4_dpll[] = {
+ { DP_LINK_BW_1_62,
+ { .p1 = 2, .p2 = 10, .n = 2, .m1 = 23, .m2 = 8 } },
+ { DP_LINK_BW_2_7,
+ { .p1 = 1, .p2 = 10, .n = 1, .m1 = 14, .m2 = 2 } }
+};
+
+static const struct dp_link_dpll pch_dpll[] = {
+ { DP_LINK_BW_1_62,
+ { .p1 = 2, .p2 = 10, .n = 1, .m1 = 12, .m2 = 9 } },
+ { DP_LINK_BW_2_7,
+ { .p1 = 1, .p2 = 10, .n = 2, .m1 = 14, .m2 = 8 } }
+};
+
+static const struct dp_link_dpll vlv_dpll[] = {
+ { DP_LINK_BW_1_62,
+ { .p1 = 3, .p2 = 2, .n = 5, .m1 = 3, .m2 = 81 } },
+ { DP_LINK_BW_2_7,
+ { .p1 = 2, .p2 = 2, .n = 1, .m1 = 2, .m2 = 27 } }
+};
+
/**
* is_edp - is the given port attached to an eDP panel (either CPU or PCH)
* @intel_dp: DP struct
@@ -211,24 +237,77 @@ intel_hrawclk(struct drm_device *dev)
}
}
+static void
+intel_dp_init_panel_power_sequencer(struct drm_device *dev,
+ struct intel_dp *intel_dp,
+ struct edp_power_seq *out);
+static void
+intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
+ struct intel_dp *intel_dp,
+ struct edp_power_seq *out);
+
+static enum pipe
+vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
+{
+ struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+ struct drm_crtc *crtc = intel_dig_port->base.base.crtc;
+ struct drm_device *dev = intel_dig_port->base.base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ enum port port = intel_dig_port->port;
+ enum pipe pipe;
+
+ /* modeset should have pipe */
+ if (crtc)
+ return to_intel_crtc(crtc)->pipe;
+
+ /* init time, try to find a pipe with this port selected */
+ for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
+ u32 port_sel = I915_READ(VLV_PIPE_PP_ON_DELAYS(pipe)) &
+ PANEL_PORT_SELECT_MASK;
+ if (port_sel == PANEL_PORT_SELECT_DPB_VLV && port == PORT_B)
+ return pipe;
+ if (port_sel == PANEL_PORT_SELECT_DPC_VLV && port == PORT_C)
+ return pipe;
+ }
+
+ /* shrug */
+ return PIPE_A;
+}
+
+static u32 _pp_ctrl_reg(struct intel_dp *intel_dp)
+{
+ struct drm_device *dev = intel_dp_to_dev(intel_dp);
+
+ if (HAS_PCH_SPLIT(dev))
+ return PCH_PP_CONTROL;
+ else
+ return VLV_PIPE_PP_CONTROL(vlv_power_sequencer_pipe(intel_dp));
+}
+
+static u32 _pp_stat_reg(struct intel_dp *intel_dp)
+{
+ struct drm_device *dev = intel_dp_to_dev(intel_dp);
+
+ if (HAS_PCH_SPLIT(dev))
+ return PCH_PP_STATUS;
+ else
+ return VLV_PIPE_PP_STATUS(vlv_power_sequencer_pipe(intel_dp));
+}
+
static bool ironlake_edp_have_panel_power(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 pp_stat_reg;
- pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
- return (I915_READ(pp_stat_reg) & PP_ON) != 0;
+ return (I915_READ(_pp_stat_reg(intel_dp)) & PP_ON) != 0;
}
static bool ironlake_edp_have_panel_vdd(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 pp_ctrl_reg;
- pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
- return (I915_READ(pp_ctrl_reg) & EDP_FORCE_VDD) != 0;
+ return (I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD) != 0;
}
static void
@@ -236,19 +315,15 @@ intel_dp_check_edp(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev->dev_private;
- u32 pp_stat_reg, pp_ctrl_reg;
if (!is_edp(intel_dp))
return;
- pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
- pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
-
if (!ironlake_edp_have_panel_power(intel_dp) && !ironlake_edp_have_panel_vdd(intel_dp)) {
WARN(1, "eDP powered off while attempting aux channel communication.\n");
DRM_DEBUG_KMS("Status 0x%08x Control 0x%08x\n",
- I915_READ(pp_stat_reg),
- I915_READ(pp_ctrl_reg));
+ I915_READ(_pp_stat_reg(intel_dp)),
+ I915_READ(_pp_ctrl_reg(intel_dp)));
}
}
@@ -361,6 +436,12 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
goto out;
}
+ /* Only 5 data registers! */
+ if (WARN_ON(send_bytes > 20 || recv_size > 20)) {
+ ret = -E2BIG;
+ goto out;
+ }
+
while ((aux_clock_divider = get_aux_clock_divider(intel_dp, clock++))) {
/* Must try at least 3 times according to DP spec */
for (try = 0; try < 5; try++) {
@@ -451,9 +532,10 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp,
int msg_bytes;
uint8_t ack;
+ if (WARN_ON(send_bytes > 16))
+ return -E2BIG;
+
intel_dp_check_edp(intel_dp);
- if (send_bytes > 16)
- return -1;
msg[0] = AUX_NATIVE_WRITE << 4;
msg[1] = address >> 8;
msg[2] = address & 0xff;
@@ -494,6 +576,9 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp,
uint8_t ack;
int ret;
+ if (WARN_ON(recv_bytes > 19))
+ return -E2BIG;
+
intel_dp_check_edp(intel_dp);
msg[0] = AUX_NATIVE_READ << 4;
msg[1] = address >> 8;
@@ -588,7 +673,18 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
DRM_DEBUG_KMS("aux_ch native nack\n");
return -EREMOTEIO;
case AUX_NATIVE_REPLY_DEFER:
- udelay(100);
+ /*
+ * For now, just give more slack to branch devices. We
+ * could check the DPCD for I2C bit rate capabilities,
+ * and if available, adjust the interval. We could also
+ * be more careful with DP-to-Legacy adapters where a
+ * long legacy cable may force very low I2C bit rates.
+ */
+ if (intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
+ DP_DWN_STRM_PORT_PRESENT)
+ usleep_range(500, 600);
+ else
+ usleep_range(300, 400);
continue;
default:
DRM_ERROR("aux_ch invalid native reply 0x%02x\n",
@@ -649,41 +745,30 @@ intel_dp_set_clock(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config, int link_bw)
{
struct drm_device *dev = encoder->base.dev;
+ const struct dp_link_dpll *divisor = NULL;
+ int i, count = 0;
if (IS_G4X(dev)) {
- if (link_bw == DP_LINK_BW_1_62) {
- pipe_config->dpll.p1 = 2;
- pipe_config->dpll.p2 = 10;
- pipe_config->dpll.n = 2;
- pipe_config->dpll.m1 = 23;
- pipe_config->dpll.m2 = 8;
- } else {
- pipe_config->dpll.p1 = 1;
- pipe_config->dpll.p2 = 10;
- pipe_config->dpll.n = 1;
- pipe_config->dpll.m1 = 14;
- pipe_config->dpll.m2 = 2;
- }
- pipe_config->clock_set = true;
+ divisor = gen4_dpll;
+ count = ARRAY_SIZE(gen4_dpll);
} else if (IS_HASWELL(dev)) {
/* Haswell has special-purpose DP DDI clocks. */
} else if (HAS_PCH_SPLIT(dev)) {
- if (link_bw == DP_LINK_BW_1_62) {
- pipe_config->dpll.n = 1;
- pipe_config->dpll.p1 = 2;
- pipe_config->dpll.p2 = 10;
- pipe_config->dpll.m1 = 12;
- pipe_config->dpll.m2 = 9;
- } else {
- pipe_config->dpll.n = 2;
- pipe_config->dpll.p1 = 1;
- pipe_config->dpll.p2 = 10;
- pipe_config->dpll.m1 = 14;
- pipe_config->dpll.m2 = 8;
- }
- pipe_config->clock_set = true;
+ divisor = pch_dpll;
+ count = ARRAY_SIZE(pch_dpll);
} else if (IS_VALLEYVIEW(dev)) {
- /* FIXME: Need to figure out optimized DP clocks for vlv. */
+ divisor = vlv_dpll;
+ count = ARRAY_SIZE(vlv_dpll);
+ }
+
+ if (divisor && count) {
+ for (i = 0; i < count; i++) {
+ if (link_bw == divisor[i].link_bw) {
+ pipe_config->dpll = divisor[i].dpll;
+ pipe_config->clock_set = true;
+ break;
+ }
+ }
}
}
@@ -726,7 +811,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
DRM_DEBUG_KMS("DP link computation with max lane count %i "
"max bw %02x pixel clock %iKHz\n",
- max_lane_count, bws[max_clock], adjusted_mode->clock);
+ max_lane_count, bws[max_clock],
+ adjusted_mode->crtc_clock);
/* Walk through all bpp values. Luckily they're all nicely spaced with 2
* bpc in between. */
@@ -738,7 +824,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
}
for (; bpp >= 6*3; bpp -= 2*3) {
- mode_rate = intel_dp_link_required(adjusted_mode->clock, bpp);
+ mode_rate = intel_dp_link_required(adjusted_mode->crtc_clock,
+ bpp);
for (clock = 0; clock <= max_clock; clock++) {
for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
@@ -783,7 +870,8 @@ found:
mode_rate, link_avail);
intel_link_compute_m_n(bpp, lane_count,
- adjusted_mode->clock, pipe_config->port_clock,
+ adjusted_mode->crtc_clock,
+ pipe_config->port_clock,
&pipe_config->dp_m_n);
intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw);
@@ -933,8 +1021,8 @@ static void ironlake_wait_panel_status(struct intel_dp *intel_dp,
struct drm_i915_private *dev_priv = dev->dev_private;
u32 pp_stat_reg, pp_ctrl_reg;
- pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
- pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+ pp_stat_reg = _pp_stat_reg(intel_dp);
+ pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
DRM_DEBUG_KMS("mask %08x value %08x status %08x control %08x\n",
mask, value,
@@ -976,11 +1064,8 @@ static u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev->dev_private;
u32 control;
- u32 pp_ctrl_reg;
-
- pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
- control = I915_READ(pp_ctrl_reg);
+ control = I915_READ(_pp_ctrl_reg(intel_dp));
control &= ~PANEL_UNLOCK_MASK;
control |= PANEL_UNLOCK_REGS;
return control;
@@ -1013,8 +1098,8 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
pp = ironlake_get_pp_control(intel_dp);
pp |= EDP_FORCE_VDD;
- pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
- pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+ pp_stat_reg = _pp_stat_reg(intel_dp);
+ pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
I915_WRITE(pp_ctrl_reg, pp);
POSTING_READ(pp_ctrl_reg);
@@ -1042,8 +1127,8 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
pp = ironlake_get_pp_control(intel_dp);
pp &= ~EDP_FORCE_VDD;
- pp_stat_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_STATUS : PCH_PP_STATUS;
- pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+ pp_stat_reg = _pp_ctrl_reg(intel_dp);
+ pp_ctrl_reg = _pp_stat_reg(intel_dp);
I915_WRITE(pp_ctrl_reg, pp);
POSTING_READ(pp_ctrl_reg);
@@ -1108,20 +1193,19 @@ void ironlake_edp_panel_on(struct intel_dp *intel_dp)
ironlake_wait_panel_power_cycle(intel_dp);
+ pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
pp = ironlake_get_pp_control(intel_dp);
if (IS_GEN5(dev)) {
/* ILK workaround: disable reset around power sequence */
pp &= ~PANEL_POWER_RESET;
- I915_WRITE(PCH_PP_CONTROL, pp);
- POSTING_READ(PCH_PP_CONTROL);
+ I915_WRITE(pp_ctrl_reg, pp);
+ POSTING_READ(pp_ctrl_reg);
}
pp |= POWER_TARGET_ON;
if (!IS_GEN5(dev))
pp |= PANEL_POWER_RESET;
- pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
-
I915_WRITE(pp_ctrl_reg, pp);
POSTING_READ(pp_ctrl_reg);
@@ -1129,8 +1213,8 @@ void ironlake_edp_panel_on(struct intel_dp *intel_dp)
if (IS_GEN5(dev)) {
pp |= PANEL_POWER_RESET; /* restore panel reset bit */
- I915_WRITE(PCH_PP_CONTROL, pp);
- POSTING_READ(PCH_PP_CONTROL);
+ I915_WRITE(pp_ctrl_reg, pp);
+ POSTING_READ(pp_ctrl_reg);
}
}
@@ -1153,7 +1237,7 @@ void ironlake_edp_panel_off(struct intel_dp *intel_dp)
* panels get very unhappy and cease to work. */
pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
- pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+ pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
I915_WRITE(pp_ctrl_reg, pp);
POSTING_READ(pp_ctrl_reg);
@@ -1186,7 +1270,7 @@ void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
pp = ironlake_get_pp_control(intel_dp);
pp |= EDP_BLC_ENABLE;
- pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+ pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
I915_WRITE(pp_ctrl_reg, pp);
POSTING_READ(pp_ctrl_reg);
@@ -1210,7 +1294,7 @@ void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
pp = ironlake_get_pp_control(intel_dp);
pp &= ~EDP_BLC_ENABLE;
- pp_ctrl_reg = IS_VALLEYVIEW(dev) ? PIPEA_PP_CONTROL : PCH_PP_CONTROL;
+ pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
I915_WRITE(pp_ctrl_reg, pp);
POSTING_READ(pp_ctrl_reg);
@@ -1357,6 +1441,7 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
struct drm_i915_private *dev_priv = dev->dev_private;
enum port port = dp_to_dig_port(intel_dp)->port;
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+ int dotclock;
if ((port == PORT_A) || !HAS_PCH_CPT(dev)) {
tmp = I915_READ(intel_dp->output_reg);
@@ -1384,12 +1469,24 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
pipe_config->adjusted_mode.flags |= flags;
- if (dp_to_dig_port(intel_dp)->port == PORT_A) {
+ pipe_config->has_dp_encoder = true;
+
+ intel_dp_get_m_n(crtc, pipe_config);
+
+ if (port == PORT_A) {
if ((I915_READ(DP_A) & DP_PLL_FREQ_MASK) == DP_PLL_FREQ_160MHZ)
pipe_config->port_clock = 162000;
else
pipe_config->port_clock = 270000;
}
+
+ dotclock = intel_dotclock_calculate(pipe_config->port_clock,
+ &pipe_config->dp_m_n);
+
+ if (HAS_PCH_SPLIT(dev_priv->dev) && port != PORT_A)
+ ironlake_check_encoder_dotclock(pipe_config, dotclock);
+
+ pipe_config->adjusted_mode.crtc_clock = dotclock;
}
static bool is_edp_psr(struct intel_dp *intel_dp)
@@ -1402,10 +1499,10 @@ static bool intel_edp_is_psr_enabled(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- if (!IS_HASWELL(dev))
+ if (!HAS_PSR(dev))
return false;
- return I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE;
+ return I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE;
}
static void intel_edp_psr_write_vsc(struct intel_dp *intel_dp,
@@ -1455,7 +1552,7 @@ static void intel_edp_psr_setup(struct intel_dp *intel_dp)
intel_edp_psr_write_vsc(intel_dp, &psr_vsc);
/* Avoid continuous PSR exit by masking memup and hpd */
- I915_WRITE(EDP_PSR_DEBUG_CTL, EDP_PSR_DEBUG_MASK_MEMUP |
+ I915_WRITE(EDP_PSR_DEBUG_CTL(dev), EDP_PSR_DEBUG_MASK_MEMUP |
EDP_PSR_DEBUG_MASK_HPD);
intel_dp->psr_setup_done = true;
@@ -1480,9 +1577,9 @@ static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
DP_PSR_MAIN_LINK_ACTIVE);
/* Setup AUX registers */
- I915_WRITE(EDP_PSR_AUX_DATA1, EDP_PSR_DPCD_COMMAND);
- I915_WRITE(EDP_PSR_AUX_DATA2, EDP_PSR_DPCD_NORMAL_OPERATION);
- I915_WRITE(EDP_PSR_AUX_CTL,
+ I915_WRITE(EDP_PSR_AUX_DATA1(dev), EDP_PSR_DPCD_COMMAND);
+ I915_WRITE(EDP_PSR_AUX_DATA2(dev), EDP_PSR_DPCD_NORMAL_OPERATION);
+ I915_WRITE(EDP_PSR_AUX_CTL(dev),
DP_AUX_CH_CTL_TIME_OUT_400us |
(msg_size << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
(precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
@@ -1505,7 +1602,7 @@ static void intel_edp_psr_enable_source(struct intel_dp *intel_dp)
} else
val |= EDP_PSR_LINK_DISABLE;
- I915_WRITE(EDP_PSR_CTL, val |
+ I915_WRITE(EDP_PSR_CTL(dev), val |
EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES |
max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT |
idle_frames << EDP_PSR_IDLE_FRAME_SHIFT |
@@ -1522,7 +1619,7 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
- if (!IS_HASWELL(dev)) {
+ if (!HAS_PSR(dev)) {
DRM_DEBUG_KMS("PSR not supported on this platform\n");
dev_priv->no_psr_reason = PSR_NO_SOURCE;
return false;
@@ -1555,7 +1652,7 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
}
intel_crtc = to_intel_crtc(crtc);
- if (!intel_crtc->active || !crtc->fb || !crtc->mode.clock) {
+ if (!intel_crtc_active(crtc)) {
DRM_DEBUG_KMS("crtc not active for PSR\n");
dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE;
return false;
@@ -1582,7 +1679,7 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
return false;
}
- if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) {
+ if (intel_crtc->config.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) {
DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
dev_priv->no_psr_reason = PSR_INTERLACED_ENABLED;
return false;
@@ -1626,10 +1723,11 @@ void intel_edp_psr_disable(struct intel_dp *intel_dp)
if (!intel_edp_is_psr_enabled(dev))
return;
- I915_WRITE(EDP_PSR_CTL, I915_READ(EDP_PSR_CTL) & ~EDP_PSR_ENABLE);
+ I915_WRITE(EDP_PSR_CTL(dev),
+ I915_READ(EDP_PSR_CTL(dev)) & ~EDP_PSR_ENABLE);
/* Wait till PSR is idle */
- if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL) &
+ if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL(dev)) &
EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
DRM_ERROR("Timed out waiting for PSR Idle State\n");
}
@@ -1702,14 +1800,24 @@ static void intel_enable_dp(struct intel_encoder *encoder)
ironlake_edp_panel_vdd_off(intel_dp, true);
intel_dp_complete_link_train(intel_dp);
intel_dp_stop_link_train(intel_dp);
+}
+
+static void g4x_enable_dp(struct intel_encoder *encoder)
+{
+ struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+
+ intel_enable_dp(encoder);
ironlake_edp_backlight_on(intel_dp);
}
static void vlv_enable_dp(struct intel_encoder *encoder)
{
+ struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+
+ ironlake_edp_backlight_on(intel_dp);
}
-static void intel_pre_enable_dp(struct intel_encoder *encoder)
+static void g4x_pre_enable_dp(struct intel_encoder *encoder)
{
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
@@ -1727,53 +1835,59 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
int port = vlv_dport_to_channel(dport);
int pipe = intel_crtc->pipe;
+ struct edp_power_seq power_seq;
u32 val;
mutex_lock(&dev_priv->dpio_lock);
- val = vlv_dpio_read(dev_priv, DPIO_DATA_LANE_A(port));
+ val = vlv_dpio_read(dev_priv, pipe, DPIO_DATA_LANE_A(port));
val = 0;
if (pipe)
val |= (1<<21);
else
val &= ~(1<<21);
val |= 0x001000c4;
- vlv_dpio_write(dev_priv, DPIO_DATA_CHANNEL(port), val);
- vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(port), 0x00760018);
- vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(port), 0x00400888);
+ vlv_dpio_write(dev_priv, pipe, DPIO_DATA_CHANNEL(port), val);
+ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF0(port), 0x00760018);
+ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF8(port), 0x00400888);
mutex_unlock(&dev_priv->dpio_lock);
+ /* init power sequencer on this pipe and port */
+ intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+ intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
+ &power_seq);
+
intel_enable_dp(encoder);
vlv_wait_port_ready(dev_priv, port);
}
-static void intel_dp_pre_pll_enable(struct intel_encoder *encoder)
+static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder)
{
struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc =
+ to_intel_crtc(encoder->base.crtc);
int port = vlv_dport_to_channel(dport);
-
- if (!IS_VALLEYVIEW(dev))
- return;
+ int pipe = intel_crtc->pipe;
/* Program Tx lane resets to default */
mutex_lock(&dev_priv->dpio_lock);
- vlv_dpio_write(dev_priv, DPIO_PCS_TX(port),
+ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port),
DPIO_PCS_TX_LANE2_RESET |
DPIO_PCS_TX_LANE1_RESET);
- vlv_dpio_write(dev_priv, DPIO_PCS_CLK(port),
+ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port),
DPIO_PCS_CLK_CRI_RXEB_EIOS_EN |
DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN |
(1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) |
DPIO_PCS_CLK_SOFT_RESET);
/* Fix up inter-pair skew failure */
- vlv_dpio_write(dev_priv, DPIO_PCS_STAGGER1(port), 0x00750f00);
- vlv_dpio_write(dev_priv, DPIO_TX_CTL(port), 0x00001500);
- vlv_dpio_write(dev_priv, DPIO_TX_LANE(port), 0x40400000);
+ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER1(port), 0x00750f00);
+ vlv_dpio_write(dev_priv, pipe, DPIO_TX_CTL(port), 0x00001500);
+ vlv_dpio_write(dev_priv, pipe, DPIO_TX_LANE(port), 0x40400000);
mutex_unlock(&dev_priv->dpio_lock);
}
@@ -1908,10 +2022,13 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp)
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
+ struct intel_crtc *intel_crtc =
+ to_intel_crtc(dport->base.base.crtc);
unsigned long demph_reg_value, preemph_reg_value,
uniqtranscale_reg_value;
uint8_t train_set = intel_dp->train_set[0];
int port = vlv_dport_to_channel(dport);
+ int pipe = intel_crtc->pipe;
switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
case DP_TRAIN_PRE_EMPHASIS_0:
@@ -1987,14 +2104,14 @@ static uint32_t intel_vlv_signal_levels(struct intel_dp *intel_dp)
}
mutex_lock(&dev_priv->dpio_lock);
- vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0x00000000);
- vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL4(port), demph_reg_value);
- vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL2(port),
+ vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0x00000000);
+ vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL4(port), demph_reg_value);
+ vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL2(port),
uniqtranscale_reg_value);
- vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL3(port), 0x0C782040);
- vlv_dpio_write(dev_priv, DPIO_PCS_STAGGER0(port), 0x00030000);
- vlv_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port), preemph_reg_value);
- vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0x80000000);
+ vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL3(port), 0x0C782040);
+ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER0(port), 0x00030000);
+ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port), preemph_reg_value);
+ vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0x80000000);
mutex_unlock(&dev_priv->dpio_lock);
return 0;
@@ -2573,11 +2690,14 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
/* Check if the panel supports PSR */
memset(intel_dp->psr_dpcd, 0, sizeof(intel_dp->psr_dpcd));
- intel_dp_aux_native_read_retry(intel_dp, DP_PSR_SUPPORT,
- intel_dp->psr_dpcd,
- sizeof(intel_dp->psr_dpcd));
- if (is_edp_psr(intel_dp))
- DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
+ if (is_edp(intel_dp)) {
+ intel_dp_aux_native_read_retry(intel_dp, DP_PSR_SUPPORT,
+ intel_dp->psr_dpcd,
+ sizeof(intel_dp->psr_dpcd));
+ if (is_edp_psr(intel_dp))
+ DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
+ }
+
if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
DP_DWN_STRM_PORT_PRESENT))
return true; /* native DP sink */
@@ -3090,7 +3210,7 @@ intel_trans_dp_port_sel(struct drm_crtc *crtc)
bool intel_dpd_is_edp(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct child_device_config *p_child;
+ union child_device_config *p_child;
int i;
if (!dev_priv->vbt.child_dev_num)
@@ -3099,8 +3219,8 @@ bool intel_dpd_is_edp(struct drm_device *dev)
for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
p_child = dev_priv->vbt.child_dev + i;
- if (p_child->dvo_port == PORT_IDPD &&
- p_child->device_type == DEVICE_TYPE_eDP)
+ if (p_child->common.dvo_port == PORT_IDPD &&
+ p_child->common.device_type == DEVICE_TYPE_eDP)
return true;
}
return false;
@@ -3133,24 +3253,26 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
struct drm_i915_private *dev_priv = dev->dev_private;
struct edp_power_seq cur, vbt, spec, final;
u32 pp_on, pp_off, pp_div, pp;
- int pp_control_reg, pp_on_reg, pp_off_reg, pp_div_reg;
+ int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg;
if (HAS_PCH_SPLIT(dev)) {
- pp_control_reg = PCH_PP_CONTROL;
+ pp_ctrl_reg = PCH_PP_CONTROL;
pp_on_reg = PCH_PP_ON_DELAYS;
pp_off_reg = PCH_PP_OFF_DELAYS;
pp_div_reg = PCH_PP_DIVISOR;
} else {
- pp_control_reg = PIPEA_PP_CONTROL;
- pp_on_reg = PIPEA_PP_ON_DELAYS;
- pp_off_reg = PIPEA_PP_OFF_DELAYS;
- pp_div_reg = PIPEA_PP_DIVISOR;
+ enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
+
+ pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
+ pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe);
+ pp_off_reg = VLV_PIPE_PP_OFF_DELAYS(pipe);
+ pp_div_reg = VLV_PIPE_PP_DIVISOR(pipe);
}
/* Workaround: Need to write PP_CONTROL with the unlock key as
* the very first thing. */
pp = ironlake_get_pp_control(intel_dp);
- I915_WRITE(pp_control_reg, pp);
+ I915_WRITE(pp_ctrl_reg, pp);
pp_on = I915_READ(pp_on_reg);
pp_off = I915_READ(pp_off_reg);
@@ -3238,9 +3360,11 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
pp_off_reg = PCH_PP_OFF_DELAYS;
pp_div_reg = PCH_PP_DIVISOR;
} else {
- pp_on_reg = PIPEA_PP_ON_DELAYS;
- pp_off_reg = PIPEA_PP_OFF_DELAYS;
- pp_div_reg = PIPEA_PP_DIVISOR;
+ enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
+
+ pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe);
+ pp_off_reg = VLV_PIPE_PP_OFF_DELAYS(pipe);
+ pp_div_reg = VLV_PIPE_PP_DIVISOR(pipe);
}
/* And finally store the new values in the power sequencer. */
@@ -3257,12 +3381,15 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
/* Haswell doesn't have any port selection bits for the panel
* power sequencer any more. */
if (IS_VALLEYVIEW(dev)) {
- port_sel = I915_READ(pp_on_reg) & 0xc0000000;
+ if (dp_to_dig_port(intel_dp)->port == PORT_B)
+ port_sel = PANEL_PORT_SELECT_DPB_VLV;
+ else
+ port_sel = PANEL_PORT_SELECT_DPC_VLV;
} else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
if (dp_to_dig_port(intel_dp)->port == PORT_A)
- port_sel = PANEL_POWER_PORT_DP_A;
+ port_sel = PANEL_PORT_SELECT_DPA;
else
- port_sel = PANEL_POWER_PORT_DP_D;
+ port_sel = PANEL_PORT_SELECT_DPD;
}
pp_on |= port_sel;
@@ -3505,11 +3632,11 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
struct drm_encoder *encoder;
struct intel_connector *intel_connector;
- intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL);
+ intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
if (!intel_dig_port)
return;
- intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
+ intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
if (!intel_connector) {
kfree(intel_dig_port);
return;
@@ -3528,12 +3655,12 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
intel_encoder->get_hw_state = intel_dp_get_hw_state;
intel_encoder->get_config = intel_dp_get_config;
if (IS_VALLEYVIEW(dev)) {
- intel_encoder->pre_pll_enable = intel_dp_pre_pll_enable;
+ intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable;
intel_encoder->pre_enable = vlv_pre_enable_dp;
intel_encoder->enable = vlv_enable_dp;
} else {
- intel_encoder->pre_enable = intel_pre_enable_dp;
- intel_encoder->enable = intel_enable_dp;
+ intel_encoder->pre_enable = g4x_pre_enable_dp;
+ intel_encoder->enable = g4x_enable_dp;
}
intel_dig_port->port = port;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 28cae80495e2..a17a86ac4e40 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -77,7 +77,6 @@
/* the i915, i945 have a single sDVO i2c bus - which is different */
#define MAX_OUTPUTS 6
/* maximum connectors per crtcs in the mode set */
-#define INTELFB_CONN_LIMIT 4
#define INTEL_I2C_BUS_DVO 1
#define INTEL_I2C_BUS_SDVO 2
@@ -93,13 +92,17 @@
#define INTEL_OUTPUT_HDMI 6
#define INTEL_OUTPUT_DISPLAYPORT 7
#define INTEL_OUTPUT_EDP 8
-#define INTEL_OUTPUT_UNKNOWN 9
+#define INTEL_OUTPUT_DSI 9
+#define INTEL_OUTPUT_UNKNOWN 10
#define INTEL_DVO_CHIP_NONE 0
#define INTEL_DVO_CHIP_LVDS 1
#define INTEL_DVO_CHIP_TMDS 2
#define INTEL_DVO_CHIP_TVOUT 4
+#define INTEL_DSI_COMMAND_MODE 0
+#define INTEL_DSI_VIDEO_MODE 1
+
struct intel_framebuffer {
struct drm_framebuffer base;
struct drm_i915_gem_object *obj;
@@ -207,8 +210,21 @@ struct intel_crtc_config {
#define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */
unsigned long quirks;
+ /* User requested mode, only valid as a starting point to
+ * compute adjusted_mode, except in the case of (S)DVO where
+ * it's also for the output timings of the (S)DVO chip.
+ * adjusted_mode will then correspond to the S(DVO) chip's
+ * preferred input timings. */
struct drm_display_mode requested_mode;
+ /* Actual pipe timings ie. what we program into the pipe timing
+ * registers. adjusted_mode.crtc_clock is the pipe pixel clock. */
struct drm_display_mode adjusted_mode;
+
+ /* Pipe source size (ie. panel fitter input size)
+ * All planes will be positioned inside this space,
+ * and get clipped at the edges. */
+ int pipe_src_w, pipe_src_h;
+
/* Whether to set up the PCH/FDI. Note that we never allow sharing
* between pch encoders and cpu encoders. */
bool has_pch_encoder;
@@ -262,7 +278,8 @@ struct intel_crtc_config {
/*
* Frequence the dpll for the port should run at. Differs from the
- * adjusted dotclock e.g. for DP or 12bpc hdmi mode.
+ * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also
+ * already multiplied by pixel_multiplier.
*/
int port_clock;
@@ -288,6 +305,8 @@ struct intel_crtc_config {
struct intel_link_m_n fdi_m_n;
bool ips_enabled;
+
+ bool double_wide;
};
struct intel_crtc {
@@ -495,80 +514,6 @@ struct intel_unpin_work {
bool enable_stall_check;
};
-int intel_pch_rawclk(struct drm_device *dev);
-
-int intel_connector_update_modes(struct drm_connector *connector,
- struct edid *edid);
-int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
-
-extern void intel_attach_force_audio_property(struct drm_connector *connector);
-extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
-
-extern bool intel_pipe_has_type(struct drm_crtc *crtc, int type);
-extern void intel_crt_init(struct drm_device *dev);
-extern void intel_hdmi_init(struct drm_device *dev,
- int hdmi_reg, enum port port);
-extern void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
- struct intel_connector *intel_connector);
-extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
-extern bool intel_hdmi_compute_config(struct intel_encoder *encoder,
- struct intel_crtc_config *pipe_config);
-extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
- bool is_sdvob);
-extern void intel_dvo_init(struct drm_device *dev);
-extern void intel_tv_init(struct drm_device *dev);
-extern void intel_mark_busy(struct drm_device *dev);
-extern void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
- struct intel_ring_buffer *ring);
-extern void intel_mark_idle(struct drm_device *dev);
-extern void intel_lvds_init(struct drm_device *dev);
-extern bool intel_is_dual_link_lvds(struct drm_device *dev);
-extern void intel_dp_init(struct drm_device *dev, int output_reg,
- enum port port);
-extern bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
- struct intel_connector *intel_connector);
-extern void intel_dp_init_link_config(struct intel_dp *intel_dp);
-extern void intel_dp_start_link_train(struct intel_dp *intel_dp);
-extern void intel_dp_complete_link_train(struct intel_dp *intel_dp);
-extern void intel_dp_stop_link_train(struct intel_dp *intel_dp);
-extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
-extern void intel_dp_encoder_destroy(struct drm_encoder *encoder);
-extern void intel_dp_check_link_status(struct intel_dp *intel_dp);
-extern bool intel_dp_compute_config(struct intel_encoder *encoder,
- struct intel_crtc_config *pipe_config);
-extern bool intel_dpd_is_edp(struct drm_device *dev);
-extern void ironlake_edp_backlight_on(struct intel_dp *intel_dp);
-extern void ironlake_edp_backlight_off(struct intel_dp *intel_dp);
-extern void ironlake_edp_panel_on(struct intel_dp *intel_dp);
-extern void ironlake_edp_panel_off(struct intel_dp *intel_dp);
-extern void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp);
-extern void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
-extern int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane);
-extern void intel_flush_display_plane(struct drm_i915_private *dev_priv,
- enum plane plane);
-
-/* intel_panel.c */
-extern int intel_panel_init(struct intel_panel *panel,
- struct drm_display_mode *fixed_mode);
-extern void intel_panel_fini(struct intel_panel *panel);
-
-extern void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
- struct drm_display_mode *adjusted_mode);
-extern void intel_pch_panel_fitting(struct intel_crtc *crtc,
- struct intel_crtc_config *pipe_config,
- int fitting_mode);
-extern void intel_gmch_panel_fitting(struct intel_crtc *crtc,
- struct intel_crtc_config *pipe_config,
- int fitting_mode);
-extern void intel_panel_set_backlight(struct drm_device *dev,
- u32 level, u32 max);
-extern int intel_panel_setup_backlight(struct drm_connector *connector);
-extern void intel_panel_enable_backlight(struct drm_device *dev,
- enum pipe pipe);
-extern void intel_panel_disable_backlight(struct drm_device *dev);
-extern void intel_panel_destroy_backlight(struct drm_device *dev);
-extern enum drm_connector_status intel_panel_detect(struct drm_device *dev);
-
struct intel_set_config {
struct drm_encoder **save_connector_encoders;
struct drm_crtc **save_encoder_crtcs;
@@ -577,18 +522,14 @@ struct intel_set_config {
bool mode_changed;
};
-extern void intel_crtc_restore_mode(struct drm_crtc *crtc);
-extern void intel_crtc_load_lut(struct drm_crtc *crtc);
-extern void intel_crtc_update_dpms(struct drm_crtc *crtc);
-extern void intel_encoder_destroy(struct drm_encoder *encoder);
-extern void intel_connector_dpms(struct drm_connector *, int mode);
-extern bool intel_connector_get_hw_state(struct intel_connector *connector);
-extern void intel_modeset_check_state(struct drm_device *dev);
-extern void intel_plane_restore(struct drm_plane *plane);
-extern void intel_plane_disable(struct drm_plane *plane);
-
+struct intel_load_detect_pipe {
+ struct drm_framebuffer *release_fb;
+ bool load_detect_temp;
+ int dpms_mode;
+};
-static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector)
+static inline struct intel_encoder *
+intel_attached_encoder(struct drm_connector *connector)
{
return to_intel_connector(connector)->encoder;
}
@@ -616,73 +557,94 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi)
return container_of(intel_hdmi, struct intel_digital_port, hdmi);
}
+
+/* i915_irq.c */
+bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
+ enum pipe pipe, bool enable);
+bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
+ enum transcoder pch_transcoder,
+ bool enable);
+void ilk_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void ilk_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void snb_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void hsw_pc8_disable_interrupts(struct drm_device *dev);
+void hsw_pc8_restore_interrupts(struct drm_device *dev);
+
+
+/* intel_crt.c */
+void intel_crt_init(struct drm_device *dev);
+
+
+/* intel_ddi.c */
+void intel_prepare_ddi(struct drm_device *dev);
+void hsw_fdi_link_train(struct drm_crtc *crtc);
+void intel_ddi_init(struct drm_device *dev, enum port port);
+enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder);
+bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe);
+int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv);
+void intel_ddi_pll_init(struct drm_device *dev);
+void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc);
+void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
+ enum transcoder cpu_transcoder);
+void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
+void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
+void intel_ddi_setup_hw_pll_state(struct drm_device *dev);
+bool intel_ddi_pll_mode_set(struct drm_crtc *crtc);
+void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
+void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
+void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
+bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
+void intel_ddi_fdi_disable(struct drm_crtc *crtc);
+void intel_ddi_get_config(struct intel_encoder *encoder,
+ struct intel_crtc_config *pipe_config);
+
+
+/* intel_display.c */
+int intel_pch_rawclk(struct drm_device *dev);
+void intel_mark_busy(struct drm_device *dev);
+void intel_mark_fb_busy(struct drm_i915_gem_object *obj,
+ struct intel_ring_buffer *ring);
+void intel_mark_idle(struct drm_device *dev);
+void intel_crtc_restore_mode(struct drm_crtc *crtc);
+void intel_crtc_update_dpms(struct drm_crtc *crtc);
+void intel_encoder_destroy(struct drm_encoder *encoder);
+void intel_connector_dpms(struct drm_connector *, int mode);
+bool intel_connector_get_hw_state(struct intel_connector *connector);
+void intel_modeset_check_state(struct drm_device *dev);
bool ibx_digital_port_connected(struct drm_i915_private *dev_priv,
struct intel_digital_port *port);
-
-extern void intel_connector_attach_encoder(struct intel_connector *connector,
- struct intel_encoder *encoder);
-extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector);
-
-extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
- struct drm_crtc *crtc);
+void intel_connector_attach_encoder(struct intel_connector *connector,
+ struct intel_encoder *encoder);
+struct drm_encoder *intel_best_encoder(struct drm_connector *connector);
+struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
+ struct drm_crtc *crtc);
int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
struct drm_file *file_priv);
-extern enum transcoder
-intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
- enum pipe pipe);
-extern void intel_wait_for_vblank(struct drm_device *dev, int pipe);
-extern void intel_wait_for_pipe_off(struct drm_device *dev, int pipe);
-extern int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp);
-extern void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port);
-
-struct intel_load_detect_pipe {
- struct drm_framebuffer *release_fb;
- bool load_detect_temp;
- int dpms_mode;
-};
-extern bool intel_get_load_detect_pipe(struct drm_connector *connector,
- struct drm_display_mode *mode,
- struct intel_load_detect_pipe *old);
-extern void intel_release_load_detect_pipe(struct drm_connector *connector,
- struct intel_load_detect_pipe *old);
-
-extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
- u16 blue, int regno);
-extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
- u16 *blue, int regno);
-
-extern int intel_pin_and_fence_fb_obj(struct drm_device *dev,
- struct drm_i915_gem_object *obj,
- struct intel_ring_buffer *pipelined);
-extern void intel_unpin_fb_obj(struct drm_i915_gem_object *obj);
-
-extern int intel_framebuffer_init(struct drm_device *dev,
- struct intel_framebuffer *ifb,
- struct drm_mode_fb_cmd2 *mode_cmd,
- struct drm_i915_gem_object *obj);
-extern void intel_framebuffer_fini(struct intel_framebuffer *fb);
-extern int intel_fbdev_init(struct drm_device *dev);
-extern void intel_fbdev_initial_config(struct drm_device *dev);
-extern void intel_fbdev_fini(struct drm_device *dev);
-extern void intel_fbdev_set_suspend(struct drm_device *dev, int state);
-extern void intel_prepare_page_flip(struct drm_device *dev, int plane);
-extern void intel_finish_page_flip(struct drm_device *dev, int pipe);
-extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
-
-extern void intel_setup_overlay(struct drm_device *dev);
-extern void intel_cleanup_overlay(struct drm_device *dev);
-extern int intel_overlay_switch_off(struct intel_overlay *overlay);
-extern int intel_overlay_put_image(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-extern int intel_overlay_attrs(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-
-extern void intel_fb_output_poll_changed(struct drm_device *dev);
-extern void intel_fb_restore_mode(struct drm_device *dev);
-
-struct intel_shared_dpll *
-intel_crtc_to_shared_dpll(struct intel_crtc *crtc);
-
+enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
+ enum pipe pipe);
+void intel_wait_for_vblank(struct drm_device *dev, int pipe);
+void intel_wait_for_pipe_off(struct drm_device *dev, int pipe);
+int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp);
+void vlv_wait_port_ready(struct drm_i915_private *dev_priv, int port);
+bool intel_get_load_detect_pipe(struct drm_connector *connector,
+ struct drm_display_mode *mode,
+ struct intel_load_detect_pipe *old);
+void intel_release_load_detect_pipe(struct drm_connector *connector,
+ struct intel_load_detect_pipe *old);
+int intel_pin_and_fence_fb_obj(struct drm_device *dev,
+ struct drm_i915_gem_object *obj,
+ struct intel_ring_buffer *pipelined);
+void intel_unpin_fb_obj(struct drm_i915_gem_object *obj);
+int intel_framebuffer_init(struct drm_device *dev,
+ struct intel_framebuffer *ifb,
+ struct drm_mode_fb_cmd2 *mode_cmd,
+ struct drm_i915_gem_object *obj);
+void intel_framebuffer_fini(struct intel_framebuffer *fb);
+void intel_prepare_page_flip(struct drm_device *dev, int plane);
+void intel_finish_page_flip(struct drm_device *dev, int pipe);
+void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
+struct intel_shared_dpll *intel_crtc_to_shared_dpll(struct intel_crtc *crtc);
void assert_shared_dpll(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll,
bool state);
@@ -696,103 +658,172 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
enum pipe pipe, bool state);
#define assert_fdi_rx_pll_enabled(d, p) assert_fdi_rx_pll(d, p, true)
#define assert_fdi_rx_pll_disabled(d, p) assert_fdi_rx_pll(d, p, false)
-extern void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
- bool state);
+void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state);
#define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
#define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
+void intel_write_eld(struct drm_encoder *encoder,
+ struct drm_display_mode *mode);
+unsigned long intel_gen4_compute_page_offset(int *x, int *y,
+ unsigned int tiling_mode,
+ unsigned int bpp,
+ unsigned int pitch);
+void intel_display_handle_reset(struct drm_device *dev);
+void hsw_enable_pc8_work(struct work_struct *__work);
+void hsw_enable_package_c8(struct drm_i915_private *dev_priv);
+void hsw_disable_package_c8(struct drm_i915_private *dev_priv);
+void intel_dp_get_m_n(struct intel_crtc *crtc,
+ struct intel_crtc_config *pipe_config);
+int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n);
+void
+ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config,
+ int dotclock);
+bool intel_crtc_active(struct drm_crtc *crtc);
+void i915_disable_vga_mem(struct drm_device *dev);
+
+
+/* intel_dp.c */
+void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
+bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
+ struct intel_connector *intel_connector);
+void intel_dp_init_link_config(struct intel_dp *intel_dp);
+void intel_dp_start_link_train(struct intel_dp *intel_dp);
+void intel_dp_complete_link_train(struct intel_dp *intel_dp);
+void intel_dp_stop_link_train(struct intel_dp *intel_dp);
+void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
+void intel_dp_encoder_destroy(struct drm_encoder *encoder);
+void intel_dp_check_link_status(struct intel_dp *intel_dp);
+bool intel_dp_compute_config(struct intel_encoder *encoder,
+ struct intel_crtc_config *pipe_config);
+bool intel_dpd_is_edp(struct drm_device *dev);
+void ironlake_edp_backlight_on(struct intel_dp *intel_dp);
+void ironlake_edp_backlight_off(struct intel_dp *intel_dp);
+void ironlake_edp_panel_on(struct intel_dp *intel_dp);
+void ironlake_edp_panel_off(struct intel_dp *intel_dp);
+void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp);
+void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
+void intel_edp_psr_enable(struct intel_dp *intel_dp);
+void intel_edp_psr_disable(struct intel_dp *intel_dp);
+void intel_edp_psr_update(struct drm_device *dev);
+
+
+/* intel_dsi.c */
+bool intel_dsi_init(struct drm_device *dev);
+
+
+/* intel_dvo.c */
+void intel_dvo_init(struct drm_device *dev);
+
+
+/* intel_fb.c */
+int intel_fbdev_init(struct drm_device *dev);
+void intel_fbdev_initial_config(struct drm_device *dev);
+void intel_fbdev_fini(struct drm_device *dev);
+void intel_fbdev_set_suspend(struct drm_device *dev, int state);
+void intel_fb_output_poll_changed(struct drm_device *dev);
+void intel_fb_restore_mode(struct drm_device *dev);
+
+
+/* intel_hdmi.c */
+void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port);
+void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
+ struct intel_connector *intel_connector);
+struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
+bool intel_hdmi_compute_config(struct intel_encoder *encoder,
+ struct intel_crtc_config *pipe_config);
+
+
+/* intel_lvds.c */
+void intel_lvds_init(struct drm_device *dev);
+bool intel_is_dual_link_lvds(struct drm_device *dev);
+
+
+/* intel_modes.c */
+int intel_connector_update_modes(struct drm_connector *connector,
+ struct edid *edid);
+int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
+void intel_attach_force_audio_property(struct drm_connector *connector);
+void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
+
+
+/* intel_overlay.c */
+void intel_setup_overlay(struct drm_device *dev);
+void intel_cleanup_overlay(struct drm_device *dev);
+int intel_overlay_switch_off(struct intel_overlay *overlay);
+int intel_overlay_put_image(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int intel_overlay_attrs(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
-extern void intel_init_clock_gating(struct drm_device *dev);
-extern void intel_suspend_hw(struct drm_device *dev);
-extern void intel_write_eld(struct drm_encoder *encoder,
- struct drm_display_mode *mode);
-extern void intel_prepare_ddi(struct drm_device *dev);
-extern void hsw_fdi_link_train(struct drm_crtc *crtc);
-extern void intel_ddi_init(struct drm_device *dev, enum port port);
-
-/* For use by IVB LP watermark workaround in intel_sprite.c */
-extern void intel_update_watermarks(struct drm_device *dev);
-extern void intel_update_sprite_watermarks(struct drm_plane *plane,
- struct drm_crtc *crtc,
- uint32_t sprite_width, int pixel_size,
- bool enabled, bool scaled);
-
-extern unsigned long intel_gen4_compute_page_offset(int *x, int *y,
- unsigned int tiling_mode,
- unsigned int bpp,
- unsigned int pitch);
-
-extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-extern int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-
-/* Power-related functions, located in intel_pm.c */
-extern void intel_init_pm(struct drm_device *dev);
-/* FBC */
-extern bool intel_fbc_enabled(struct drm_device *dev);
-extern void intel_update_fbc(struct drm_device *dev);
-/* IPS */
-extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
-extern void intel_gpu_ips_teardown(void);
-
-/* Power well */
-extern int i915_init_power_well(struct drm_device *dev);
-extern void i915_remove_power_well(struct drm_device *dev);
-
-extern bool intel_display_power_enabled(struct drm_device *dev,
- enum intel_display_power_domain domain);
-extern void intel_init_power_well(struct drm_device *dev);
-extern void intel_set_power_well(struct drm_device *dev, bool enable);
-extern void intel_enable_gt_powersave(struct drm_device *dev);
-extern void intel_disable_gt_powersave(struct drm_device *dev);
-extern void ironlake_teardown_rc6(struct drm_device *dev);
+
+/* intel_panel.c */
+int intel_panel_init(struct intel_panel *panel,
+ struct drm_display_mode *fixed_mode);
+void intel_panel_fini(struct intel_panel *panel);
+void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
+ struct drm_display_mode *adjusted_mode);
+void intel_pch_panel_fitting(struct intel_crtc *crtc,
+ struct intel_crtc_config *pipe_config,
+ int fitting_mode);
+void intel_gmch_panel_fitting(struct intel_crtc *crtc,
+ struct intel_crtc_config *pipe_config,
+ int fitting_mode);
+void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max);
+int intel_panel_setup_backlight(struct drm_connector *connector);
+void intel_panel_enable_backlight(struct drm_device *dev, enum pipe pipe);
+void intel_panel_disable_backlight(struct drm_device *dev);
+void intel_panel_destroy_backlight(struct drm_device *dev);
+enum drm_connector_status intel_panel_detect(struct drm_device *dev);
+
+
+/* intel_pm.c */
+void intel_init_clock_gating(struct drm_device *dev);
+void intel_suspend_hw(struct drm_device *dev);
+void intel_update_watermarks(struct drm_crtc *crtc);
+void intel_update_sprite_watermarks(struct drm_plane *plane,
+ struct drm_crtc *crtc,
+ uint32_t sprite_width, int pixel_size,
+ bool enabled, bool scaled);
+void intel_init_pm(struct drm_device *dev);
+bool intel_fbc_enabled(struct drm_device *dev);
+void intel_update_fbc(struct drm_device *dev);
+void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
+void intel_gpu_ips_teardown(void);
+int i915_init_power_well(struct drm_device *dev);
+void i915_remove_power_well(struct drm_device *dev);
+bool intel_display_power_enabled(struct drm_device *dev,
+ enum intel_display_power_domain domain);
+void intel_display_power_get(struct drm_device *dev,
+ enum intel_display_power_domain domain);
+void intel_display_power_put(struct drm_device *dev,
+ enum intel_display_power_domain domain);
+void intel_init_power_well(struct drm_device *dev);
+void intel_set_power_well(struct drm_device *dev, bool enable);
+void intel_resume_power_well(struct drm_device *dev);
+void intel_enable_gt_powersave(struct drm_device *dev);
+void intel_disable_gt_powersave(struct drm_device *dev);
+void ironlake_teardown_rc6(struct drm_device *dev);
void gen6_update_ring_freq(struct drm_device *dev);
+void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
+void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
+
+
+/* intel_sdvo.c */
+bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob);
+
+
+/* intel_sprite.c */
+int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane);
+void intel_flush_display_plane(struct drm_i915_private *dev_priv,
+ enum plane plane);
+void intel_plane_restore(struct drm_plane *plane);
+void intel_plane_disable(struct drm_plane *plane);
+int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+
-extern bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
- enum pipe *pipe);
-extern int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv);
-extern void intel_ddi_pll_init(struct drm_device *dev);
-extern void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc);
-extern void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
- enum transcoder cpu_transcoder);
-extern void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc);
-extern void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc);
-extern void intel_ddi_setup_hw_pll_state(struct drm_device *dev);
-extern bool intel_ddi_pll_mode_set(struct drm_crtc *crtc);
-extern void intel_ddi_put_crtc_pll(struct drm_crtc *crtc);
-extern void intel_ddi_set_pipe_settings(struct drm_crtc *crtc);
-extern void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
-extern bool
-intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
-extern void intel_ddi_fdi_disable(struct drm_crtc *crtc);
-
-extern void intel_display_handle_reset(struct drm_device *dev);
-extern bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
- enum pipe pipe,
- bool enable);
-extern bool intel_set_pch_fifo_underrun_reporting(struct drm_device *dev,
- enum transcoder pch_transcoder,
- bool enable);
-
-extern void intel_edp_psr_enable(struct intel_dp *intel_dp);
-extern void intel_edp_psr_disable(struct intel_dp *intel_dp);
-extern void intel_edp_psr_update(struct drm_device *dev);
-extern void hsw_disable_lcpll(struct drm_i915_private *dev_priv,
- bool switch_to_fclk, bool allow_power_down);
-extern void hsw_restore_lcpll(struct drm_i915_private *dev_priv);
-extern void ilk_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
-extern void ilk_disable_gt_irq(struct drm_i915_private *dev_priv,
- uint32_t mask);
-extern void snb_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
-extern void snb_disable_pm_irq(struct drm_i915_private *dev_priv,
- uint32_t mask);
-extern void hsw_enable_pc8_work(struct work_struct *__work);
-extern void hsw_enable_package_c8(struct drm_i915_private *dev_priv);
-extern void hsw_disable_package_c8(struct drm_i915_private *dev_priv);
-extern void hsw_pc8_disable_interrupts(struct drm_device *dev);
-extern void hsw_pc8_restore_interrupts(struct drm_device *dev);
-extern void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
-extern void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
-extern void i915_disable_vga_mem(struct drm_device *dev);
+/* intel_tv.c */
+void intel_tv_init(struct drm_device *dev);
#endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
new file mode 100644
index 000000000000..674fd4989b45
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -0,0 +1,621 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Jani Nikula <jani.nikula@intel.com>
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+#include <drm/i915_drm.h>
+#include <linux/slab.h>
+#include "i915_drv.h"
+#include "intel_drv.h"
+#include "intel_dsi.h"
+#include "intel_dsi_cmd.h"
+
+/* the sub-encoders aka panel drivers */
+static const struct intel_dsi_device intel_dsi_devices[] = {
+};
+
+
+static void vlv_cck_modify(struct drm_i915_private *dev_priv, u32 reg, u32 val,
+ u32 mask)
+{
+ u32 tmp = vlv_cck_read(dev_priv, reg);
+ tmp &= ~mask;
+ tmp |= val;
+ vlv_cck_write(dev_priv, reg, tmp);
+}
+
+static void band_gap_wa(struct drm_i915_private *dev_priv)
+{
+ mutex_lock(&dev_priv->dpio_lock);
+
+ /* Enable bandgap fix in GOP driver */
+ vlv_cck_modify(dev_priv, 0x6D, 0x00010000, 0x00030000);
+ msleep(20);
+ vlv_cck_modify(dev_priv, 0x6E, 0x00010000, 0x00030000);
+ msleep(20);
+ vlv_cck_modify(dev_priv, 0x6F, 0x00010000, 0x00030000);
+ msleep(20);
+ vlv_cck_modify(dev_priv, 0x00, 0x00008000, 0x00008000);
+ msleep(20);
+ vlv_cck_modify(dev_priv, 0x00, 0x00000000, 0x00008000);
+ msleep(20);
+
+ /* Turn Display Trunk on */
+ vlv_cck_modify(dev_priv, 0x6B, 0x00020000, 0x00030000);
+ msleep(20);
+
+ vlv_cck_modify(dev_priv, 0x6C, 0x00020000, 0x00030000);
+ msleep(20);
+
+ vlv_cck_modify(dev_priv, 0x6D, 0x00020000, 0x00030000);
+ msleep(20);
+ vlv_cck_modify(dev_priv, 0x6E, 0x00020000, 0x00030000);
+ msleep(20);
+ vlv_cck_modify(dev_priv, 0x6F, 0x00020000, 0x00030000);
+
+ mutex_unlock(&dev_priv->dpio_lock);
+
+ /* Need huge delay, otherwise clock is not stable */
+ msleep(100);
+}
+
+static struct intel_dsi *intel_attached_dsi(struct drm_connector *connector)
+{
+ return container_of(intel_attached_encoder(connector),
+ struct intel_dsi, base);
+}
+
+static inline bool is_vid_mode(struct intel_dsi *intel_dsi)
+{
+ return intel_dsi->dev.type == INTEL_DSI_VIDEO_MODE;
+}
+
+static inline bool is_cmd_mode(struct intel_dsi *intel_dsi)
+{
+ return intel_dsi->dev.type == INTEL_DSI_COMMAND_MODE;
+}
+
+static void intel_dsi_hot_plug(struct intel_encoder *encoder)
+{
+ DRM_DEBUG_KMS("\n");
+}
+
+static bool intel_dsi_compute_config(struct intel_encoder *encoder,
+ struct intel_crtc_config *config)
+{
+ struct intel_dsi *intel_dsi = container_of(encoder, struct intel_dsi,
+ base);
+ struct intel_connector *intel_connector = intel_dsi->attached_connector;
+ struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
+ struct drm_display_mode *adjusted_mode = &config->adjusted_mode;
+ struct drm_display_mode *mode = &config->requested_mode;
+
+ DRM_DEBUG_KMS("\n");
+
+ if (fixed_mode)
+ intel_fixed_panel_mode(fixed_mode, adjusted_mode);
+
+ if (intel_dsi->dev.dev_ops->mode_fixup)
+ return intel_dsi->dev.dev_ops->mode_fixup(&intel_dsi->dev,
+ mode, adjusted_mode);
+
+ return true;
+}
+
+static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder)
+{
+ DRM_DEBUG_KMS("\n");
+
+ vlv_enable_dsi_pll(encoder);
+}
+
+static void intel_dsi_pre_enable(struct intel_encoder *encoder)
+{
+ DRM_DEBUG_KMS("\n");
+}
+
+static void intel_dsi_enable(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+ struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+ int pipe = intel_crtc->pipe;
+ u32 temp;
+
+ DRM_DEBUG_KMS("\n");
+
+ temp = I915_READ(MIPI_DEVICE_READY(pipe));
+ if ((temp & DEVICE_READY) == 0) {
+ temp &= ~ULPS_STATE_MASK;
+ I915_WRITE(MIPI_DEVICE_READY(pipe), temp | DEVICE_READY);
+ } else if (temp & ULPS_STATE_MASK) {
+ temp &= ~ULPS_STATE_MASK;
+ I915_WRITE(MIPI_DEVICE_READY(pipe), temp | ULPS_STATE_EXIT);
+ /*
+ * We need to ensure that there is a minimum of 1 ms time
+ * available before clearing the UPLS exit state.
+ */
+ msleep(2);
+ I915_WRITE(MIPI_DEVICE_READY(pipe), temp);
+ }
+
+ if (is_cmd_mode(intel_dsi))
+ I915_WRITE(MIPI_MAX_RETURN_PKT_SIZE(pipe), 8 * 4);
+
+ if (is_vid_mode(intel_dsi)) {
+ msleep(20); /* XXX */
+ dpi_send_cmd(intel_dsi, TURN_ON);
+ msleep(100);
+
+ /* assert ip_tg_enable signal */
+ temp = I915_READ(MIPI_PORT_CTRL(pipe));
+ I915_WRITE(MIPI_PORT_CTRL(pipe), temp | DPI_ENABLE);
+ POSTING_READ(MIPI_PORT_CTRL(pipe));
+ }
+
+ intel_dsi->dev.dev_ops->enable(&intel_dsi->dev);
+}
+
+static void intel_dsi_disable(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+ struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+ int pipe = intel_crtc->pipe;
+ u32 temp;
+
+ DRM_DEBUG_KMS("\n");
+
+ intel_dsi->dev.dev_ops->disable(&intel_dsi->dev);
+
+ if (is_vid_mode(intel_dsi)) {
+ dpi_send_cmd(intel_dsi, SHUTDOWN);
+ msleep(10);
+
+ /* de-assert ip_tg_enable signal */
+ temp = I915_READ(MIPI_PORT_CTRL(pipe));
+ I915_WRITE(MIPI_PORT_CTRL(pipe), temp & ~DPI_ENABLE);
+ POSTING_READ(MIPI_PORT_CTRL(pipe));
+
+ msleep(2);
+ }
+
+ temp = I915_READ(MIPI_DEVICE_READY(pipe));
+ if (temp & DEVICE_READY) {
+ temp &= ~DEVICE_READY;
+ temp &= ~ULPS_STATE_MASK;
+ I915_WRITE(MIPI_DEVICE_READY(pipe), temp);
+ }
+}
+
+static void intel_dsi_post_disable(struct intel_encoder *encoder)
+{
+ DRM_DEBUG_KMS("\n");
+
+ vlv_disable_dsi_pll(encoder);
+}
+
+static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
+ enum pipe *pipe)
+{
+ struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+ u32 port, func;
+ enum pipe p;
+
+ DRM_DEBUG_KMS("\n");
+
+ /* XXX: this only works for one DSI output */
+ for (p = PIPE_A; p <= PIPE_B; p++) {
+ port = I915_READ(MIPI_PORT_CTRL(p));
+ func = I915_READ(MIPI_DSI_FUNC_PRG(p));
+
+ if ((port & DPI_ENABLE) || (func & CMD_MODE_DATA_WIDTH_MASK)) {
+ if (I915_READ(MIPI_DEVICE_READY(p)) & DEVICE_READY) {
+ *pipe = p;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static void intel_dsi_get_config(struct intel_encoder *encoder,
+ struct intel_crtc_config *pipe_config)
+{
+ DRM_DEBUG_KMS("\n");
+
+ /* XXX: read flags, set to adjusted_mode */
+}
+
+static int intel_dsi_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ struct intel_connector *intel_connector = to_intel_connector(connector);
+ struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
+ struct intel_dsi *intel_dsi = intel_attached_dsi(connector);
+
+ DRM_DEBUG_KMS("\n");
+
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
+ DRM_DEBUG_KMS("MODE_NO_DBLESCAN\n");
+ return MODE_NO_DBLESCAN;
+ }
+
+ if (fixed_mode) {
+ if (mode->hdisplay > fixed_mode->hdisplay)
+ return MODE_PANEL;
+ if (mode->vdisplay > fixed_mode->vdisplay)
+ return MODE_PANEL;
+ }
+
+ return intel_dsi->dev.dev_ops->mode_valid(&intel_dsi->dev, mode);
+}
+
+/* return txclkesc cycles in terms of divider and duration in us */
+static u16 txclkesc(u32 divider, unsigned int us)
+{
+ switch (divider) {
+ case ESCAPE_CLOCK_DIVIDER_1:
+ default:
+ return 20 * us;
+ case ESCAPE_CLOCK_DIVIDER_2:
+ return 10 * us;
+ case ESCAPE_CLOCK_DIVIDER_4:
+ return 5 * us;
+ }
+}
+
+/* return pixels in terms of txbyteclkhs */
+static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count)
+{
+ return DIV_ROUND_UP(DIV_ROUND_UP(pixels * bpp, 8), lane_count);
+}
+
+static void set_dsi_timings(struct drm_encoder *encoder,
+ const struct drm_display_mode *mode)
+{
+ struct drm_device *dev = encoder->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+ struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
+ int pipe = intel_crtc->pipe;
+ unsigned int bpp = intel_crtc->config.pipe_bpp;
+ unsigned int lane_count = intel_dsi->lane_count;
+
+ u16 hactive, hfp, hsync, hbp, vfp, vsync, vbp;
+
+ hactive = mode->hdisplay;
+ hfp = mode->hsync_start - mode->hdisplay;
+ hsync = mode->hsync_end - mode->hsync_start;
+ hbp = mode->htotal - mode->hsync_end;
+
+ vfp = mode->vsync_start - mode->vdisplay;
+ vsync = mode->vsync_end - mode->vsync_start;
+ vbp = mode->vtotal - mode->vsync_end;
+
+ /* horizontal values are in terms of high speed byte clock */
+ hactive = txbyteclkhs(hactive, bpp, lane_count);
+ hfp = txbyteclkhs(hfp, bpp, lane_count);
+ hsync = txbyteclkhs(hsync, bpp, lane_count);
+ hbp = txbyteclkhs(hbp, bpp, lane_count);
+
+ I915_WRITE(MIPI_HACTIVE_AREA_COUNT(pipe), hactive);
+ I915_WRITE(MIPI_HFP_COUNT(pipe), hfp);
+
+ /* meaningful for video mode non-burst sync pulse mode only, can be zero
+ * for non-burst sync events and burst modes */
+ I915_WRITE(MIPI_HSYNC_PADDING_COUNT(pipe), hsync);
+ I915_WRITE(MIPI_HBP_COUNT(pipe), hbp);
+
+ /* vertical values are in terms of lines */
+ I915_WRITE(MIPI_VFP_COUNT(pipe), vfp);
+ I915_WRITE(MIPI_VSYNC_PADDING_COUNT(pipe), vsync);
+ I915_WRITE(MIPI_VBP_COUNT(pipe), vbp);
+}
+
+static void intel_dsi_mode_set(struct intel_encoder *intel_encoder)
+{
+ struct drm_encoder *encoder = &intel_encoder->base;
+ struct drm_device *dev = encoder->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+ struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
+ struct drm_display_mode *adjusted_mode =
+ &intel_crtc->config.adjusted_mode;
+ int pipe = intel_crtc->pipe;
+ unsigned int bpp = intel_crtc->config.pipe_bpp;
+ u32 val, tmp;
+
+ DRM_DEBUG_KMS("pipe %d\n", pipe);
+
+ /* Update the DSI PLL */
+ vlv_enable_dsi_pll(intel_encoder);
+
+ /* XXX: Location of the call */
+ band_gap_wa(dev_priv);
+
+ /* escape clock divider, 20MHz, shared for A and C. device ready must be
+ * off when doing this! txclkesc? */
+ tmp = I915_READ(MIPI_CTRL(0));
+ tmp &= ~ESCAPE_CLOCK_DIVIDER_MASK;
+ I915_WRITE(MIPI_CTRL(0), tmp | ESCAPE_CLOCK_DIVIDER_1);
+
+ /* read request priority is per pipe */
+ tmp = I915_READ(MIPI_CTRL(pipe));
+ tmp &= ~READ_REQUEST_PRIORITY_MASK;
+ I915_WRITE(MIPI_CTRL(pipe), tmp | READ_REQUEST_PRIORITY_HIGH);
+
+ /* XXX: why here, why like this? handling in irq handler?! */
+ I915_WRITE(MIPI_INTR_STAT(pipe), 0xffffffff);
+ I915_WRITE(MIPI_INTR_EN(pipe), 0xffffffff);
+
+ I915_WRITE(MIPI_DPHY_PARAM(pipe),
+ 0x3c << EXIT_ZERO_COUNT_SHIFT |
+ 0x1f << TRAIL_COUNT_SHIFT |
+ 0xc5 << CLK_ZERO_COUNT_SHIFT |
+ 0x1f << PREPARE_COUNT_SHIFT);
+
+ I915_WRITE(MIPI_DPI_RESOLUTION(pipe),
+ adjusted_mode->vdisplay << VERTICAL_ADDRESS_SHIFT |
+ adjusted_mode->hdisplay << HORIZONTAL_ADDRESS_SHIFT);
+
+ set_dsi_timings(encoder, adjusted_mode);
+
+ val = intel_dsi->lane_count << DATA_LANES_PRG_REG_SHIFT;
+ if (is_cmd_mode(intel_dsi)) {
+ val |= intel_dsi->channel << CMD_MODE_CHANNEL_NUMBER_SHIFT;
+ val |= CMD_MODE_DATA_WIDTH_8_BIT; /* XXX */
+ } else {
+ val |= intel_dsi->channel << VID_MODE_CHANNEL_NUMBER_SHIFT;
+
+ /* XXX: cross-check bpp vs. pixel format? */
+ val |= intel_dsi->pixel_format;
+ }
+ I915_WRITE(MIPI_DSI_FUNC_PRG(pipe), val);
+
+ /* timeouts for recovery. one frame IIUC. if counter expires, EOT and
+ * stop state. */
+
+ /*
+ * In burst mode, value greater than one DPI line Time in byte clock
+ * (txbyteclkhs) To timeout this timer 1+ of the above said value is
+ * recommended.
+ *
+ * In non-burst mode, Value greater than one DPI frame time in byte
+ * clock(txbyteclkhs) To timeout this timer 1+ of the above said value
+ * is recommended.
+ *
+ * In DBI only mode, value greater than one DBI frame time in byte
+ * clock(txbyteclkhs) To timeout this timer 1+ of the above said value
+ * is recommended.
+ */
+
+ if (is_vid_mode(intel_dsi) &&
+ intel_dsi->video_mode_format == VIDEO_MODE_BURST) {
+ I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe),
+ txbyteclkhs(adjusted_mode->htotal, bpp,
+ intel_dsi->lane_count) + 1);
+ } else {
+ I915_WRITE(MIPI_HS_TX_TIMEOUT(pipe),
+ txbyteclkhs(adjusted_mode->vtotal *
+ adjusted_mode->htotal,
+ bpp, intel_dsi->lane_count) + 1);
+ }
+ I915_WRITE(MIPI_LP_RX_TIMEOUT(pipe), 8309); /* max */
+ I915_WRITE(MIPI_TURN_AROUND_TIMEOUT(pipe), 0x14); /* max */
+ I915_WRITE(MIPI_DEVICE_RESET_TIMER(pipe), 0xffff); /* max */
+
+ /* dphy stuff */
+
+ /* in terms of low power clock */
+ I915_WRITE(MIPI_INIT_COUNT(pipe), txclkesc(ESCAPE_CLOCK_DIVIDER_1, 100));
+
+ /* recovery disables */
+ I915_WRITE(MIPI_EOT_DISABLE(pipe), intel_dsi->eot_disable);
+
+ /* in terms of txbyteclkhs. actual high to low switch +
+ * MIPI_STOP_STATE_STALL * MIPI_LP_BYTECLK.
+ *
+ * XXX: write MIPI_STOP_STATE_STALL?
+ */
+ I915_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT(pipe), 0x46);
+
+ /* XXX: low power clock equivalence in terms of byte clock. the number
+ * of byte clocks occupied in one low power clock. based on txbyteclkhs
+ * and txclkesc. txclkesc time / txbyteclk time * (105 +
+ * MIPI_STOP_STATE_STALL) / 105.???
+ */
+ I915_WRITE(MIPI_LP_BYTECLK(pipe), 4);
+
+ /* the bw essential for transmitting 16 long packets containing 252
+ * bytes meant for dcs write memory command is programmed in this
+ * register in terms of byte clocks. based on dsi transfer rate and the
+ * number of lanes configured the time taken to transmit 16 long packets
+ * in a dsi stream varies. */
+ I915_WRITE(MIPI_DBI_BW_CTRL(pipe), 0x820);
+
+ I915_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT(pipe),
+ 0xa << LP_HS_SSW_CNT_SHIFT |
+ 0x14 << HS_LP_PWR_SW_CNT_SHIFT);
+
+ if (is_vid_mode(intel_dsi))
+ I915_WRITE(MIPI_VIDEO_MODE_FORMAT(pipe),
+ intel_dsi->video_mode_format);
+}
+
+static enum drm_connector_status
+intel_dsi_detect(struct drm_connector *connector, bool force)
+{
+ struct intel_dsi *intel_dsi = intel_attached_dsi(connector);
+ DRM_DEBUG_KMS("\n");
+ return intel_dsi->dev.dev_ops->detect(&intel_dsi->dev);
+}
+
+static int intel_dsi_get_modes(struct drm_connector *connector)
+{
+ struct intel_connector *intel_connector = to_intel_connector(connector);
+ struct drm_display_mode *mode;
+
+ DRM_DEBUG_KMS("\n");
+
+ if (!intel_connector->panel.fixed_mode) {
+ DRM_DEBUG_KMS("no fixed mode\n");
+ return 0;
+ }
+
+ mode = drm_mode_duplicate(connector->dev,
+ intel_connector->panel.fixed_mode);
+ if (!mode) {
+ DRM_DEBUG_KMS("drm_mode_duplicate failed\n");
+ return 0;
+ }
+
+ drm_mode_probed_add(connector, mode);
+ return 1;
+}
+
+static void intel_dsi_destroy(struct drm_connector *connector)
+{
+ struct intel_connector *intel_connector = to_intel_connector(connector);
+
+ DRM_DEBUG_KMS("\n");
+ intel_panel_fini(&intel_connector->panel);
+ drm_sysfs_connector_remove(connector);
+ drm_connector_cleanup(connector);
+ kfree(connector);
+}
+
+static const struct drm_encoder_funcs intel_dsi_funcs = {
+ .destroy = intel_encoder_destroy,
+};
+
+static const struct drm_connector_helper_funcs intel_dsi_connector_helper_funcs = {
+ .get_modes = intel_dsi_get_modes,
+ .mode_valid = intel_dsi_mode_valid,
+ .best_encoder = intel_best_encoder,
+};
+
+static const struct drm_connector_funcs intel_dsi_connector_funcs = {
+ .dpms = intel_connector_dpms,
+ .detect = intel_dsi_detect,
+ .destroy = intel_dsi_destroy,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+};
+
+bool intel_dsi_init(struct drm_device *dev)
+{
+ struct intel_dsi *intel_dsi;
+ struct intel_encoder *intel_encoder;
+ struct drm_encoder *encoder;
+ struct intel_connector *intel_connector;
+ struct drm_connector *connector;
+ struct drm_display_mode *fixed_mode = NULL;
+ const struct intel_dsi_device *dsi;
+ unsigned int i;
+
+ DRM_DEBUG_KMS("\n");
+
+ intel_dsi = kzalloc(sizeof(*intel_dsi), GFP_KERNEL);
+ if (!intel_dsi)
+ return false;
+
+ intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
+ if (!intel_connector) {
+ kfree(intel_dsi);
+ return false;
+ }
+
+ intel_encoder = &intel_dsi->base;
+ encoder = &intel_encoder->base;
+ intel_dsi->attached_connector = intel_connector;
+
+ connector = &intel_connector->base;
+
+ drm_encoder_init(dev, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI);
+
+ /* XXX: very likely not all of these are needed */
+ intel_encoder->hot_plug = intel_dsi_hot_plug;
+ intel_encoder->compute_config = intel_dsi_compute_config;
+ intel_encoder->pre_pll_enable = intel_dsi_pre_pll_enable;
+ intel_encoder->pre_enable = intel_dsi_pre_enable;
+ intel_encoder->enable = intel_dsi_enable;
+ intel_encoder->mode_set = intel_dsi_mode_set;
+ intel_encoder->disable = intel_dsi_disable;
+ intel_encoder->post_disable = intel_dsi_post_disable;
+ intel_encoder->get_hw_state = intel_dsi_get_hw_state;
+ intel_encoder->get_config = intel_dsi_get_config;
+
+ intel_connector->get_hw_state = intel_connector_get_hw_state;
+
+ for (i = 0; i < ARRAY_SIZE(intel_dsi_devices); i++) {
+ dsi = &intel_dsi_devices[i];
+ intel_dsi->dev = *dsi;
+
+ if (dsi->dev_ops->init(&intel_dsi->dev))
+ break;
+ }
+
+ if (i == ARRAY_SIZE(intel_dsi_devices)) {
+ DRM_DEBUG_KMS("no device found\n");
+ goto err;
+ }
+
+ intel_encoder->type = INTEL_OUTPUT_DSI;
+ intel_encoder->crtc_mask = (1 << 0); /* XXX */
+
+ intel_encoder->cloneable = false;
+ drm_connector_init(dev, connector, &intel_dsi_connector_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+
+ drm_connector_helper_add(connector, &intel_dsi_connector_helper_funcs);
+
+ connector->display_info.subpixel_order = SubPixelHorizontalRGB; /*XXX*/
+ connector->interlace_allowed = false;
+ connector->doublescan_allowed = false;
+
+ intel_connector_attach_encoder(intel_connector, intel_encoder);
+
+ drm_sysfs_connector_add(connector);
+
+ fixed_mode = dsi->dev_ops->get_modes(&intel_dsi->dev);
+ if (!fixed_mode) {
+ DRM_DEBUG_KMS("no fixed mode\n");
+ goto err;
+ }
+
+ fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
+ intel_panel_init(&intel_connector->panel, fixed_mode);
+
+ return true;
+
+err:
+ drm_encoder_cleanup(&intel_encoder->base);
+ kfree(intel_dsi);
+ kfree(intel_connector);
+
+ return false;
+}
diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
new file mode 100644
index 000000000000..c7765f33d524
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_dsi.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _INTEL_DSI_H
+#define _INTEL_DSI_H
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include "intel_drv.h"
+
+struct intel_dsi_device {
+ unsigned int panel_id;
+ const char *name;
+ int type;
+ const struct intel_dsi_dev_ops *dev_ops;
+ void *dev_priv;
+};
+
+struct intel_dsi_dev_ops {
+ bool (*init)(struct intel_dsi_device *dsi);
+
+ /* This callback must be able to assume DSI commands can be sent */
+ void (*enable)(struct intel_dsi_device *dsi);
+
+ /* This callback must be able to assume DSI commands can be sent */
+ void (*disable)(struct intel_dsi_device *dsi);
+
+ int (*mode_valid)(struct intel_dsi_device *dsi,
+ struct drm_display_mode *mode);
+
+ bool (*mode_fixup)(struct intel_dsi_device *dsi,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+
+ void (*mode_set)(struct intel_dsi_device *dsi,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
+
+ enum drm_connector_status (*detect)(struct intel_dsi_device *dsi);
+
+ bool (*get_hw_state)(struct intel_dsi_device *dev);
+
+ struct drm_display_mode *(*get_modes)(struct intel_dsi_device *dsi);
+
+ void (*destroy) (struct intel_dsi_device *dsi);
+};
+
+struct intel_dsi {
+ struct intel_encoder base;
+
+ struct intel_dsi_device dev;
+
+ struct intel_connector *attached_connector;
+
+ /* if true, use HS mode, otherwise LP */
+ bool hs;
+
+ /* virtual channel */
+ int channel;
+
+ /* number of DSI lanes */
+ unsigned int lane_count;
+
+ /* video mode pixel format for MIPI_DSI_FUNC_PRG register */
+ u32 pixel_format;
+
+ /* video mode format for MIPI_VIDEO_MODE_FORMAT register */
+ u32 video_mode_format;
+
+ /* eot for MIPI_EOT_DISABLE register */
+ u32 eot_disable;
+};
+
+static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
+{
+ return container_of(encoder, struct intel_dsi, base.base);
+}
+
+extern void vlv_enable_dsi_pll(struct intel_encoder *encoder);
+extern void vlv_disable_dsi_pll(struct intel_encoder *encoder);
+
+#endif /* _INTEL_DSI_H */
diff --git a/drivers/gpu/drm/i915/intel_dsi_cmd.c b/drivers/gpu/drm/i915/intel_dsi_cmd.c
new file mode 100644
index 000000000000..7c40f981d2c7
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_dsi_cmd.c
@@ -0,0 +1,427 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Jani Nikula <jani.nikula@intel.com>
+ */
+
+#include <linux/export.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <video/mipi_display.h>
+#include "i915_drv.h"
+#include "intel_drv.h"
+#include "intel_dsi.h"
+#include "intel_dsi_cmd.h"
+
+/*
+ * XXX: MIPI_DATA_ADDRESS, MIPI_DATA_LENGTH, MIPI_COMMAND_LENGTH, and
+ * MIPI_COMMAND_ADDRESS registers.
+ *
+ * Apparently these registers provide a MIPI adapter level way to send (lots of)
+ * commands and data to the receiver, without having to write the commands and
+ * data to MIPI_{HS,LP}_GEN_{CTRL,DATA} registers word by word.
+ *
+ * Presumably for anything other than MIPI_DCS_WRITE_MEMORY_START and
+ * MIPI_DCS_WRITE_MEMORY_CONTINUE (which are used to update the external
+ * framebuffer in command mode displays) these are just an optimization that can
+ * come later.
+ *
+ * For memory writes, these should probably be used for performance.
+ */
+
+static void print_stat(struct intel_dsi *intel_dsi)
+{
+ struct drm_encoder *encoder = &intel_dsi->base.base;
+ struct drm_device *dev = encoder->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+ enum pipe pipe = intel_crtc->pipe;
+ u32 val;
+
+ val = I915_READ(MIPI_INTR_STAT(pipe));
+
+#define STAT_BIT(val, bit) (val) & (bit) ? " " #bit : ""
+ DRM_DEBUG_KMS("MIPI_INTR_STAT(%d) = %08x"
+ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
+ "\n", pipe, val,
+ STAT_BIT(val, TEARING_EFFECT),
+ STAT_BIT(val, SPL_PKT_SENT_INTERRUPT),
+ STAT_BIT(val, GEN_READ_DATA_AVAIL),
+ STAT_BIT(val, LP_GENERIC_WR_FIFO_FULL),
+ STAT_BIT(val, HS_GENERIC_WR_FIFO_FULL),
+ STAT_BIT(val, RX_PROT_VIOLATION),
+ STAT_BIT(val, RX_INVALID_TX_LENGTH),
+ STAT_BIT(val, ACK_WITH_NO_ERROR),
+ STAT_BIT(val, TURN_AROUND_ACK_TIMEOUT),
+ STAT_BIT(val, LP_RX_TIMEOUT),
+ STAT_BIT(val, HS_TX_TIMEOUT),
+ STAT_BIT(val, DPI_FIFO_UNDERRUN),
+ STAT_BIT(val, LOW_CONTENTION),
+ STAT_BIT(val, HIGH_CONTENTION),
+ STAT_BIT(val, TXDSI_VC_ID_INVALID),
+ STAT_BIT(val, TXDSI_DATA_TYPE_NOT_RECOGNISED),
+ STAT_BIT(val, TXCHECKSUM_ERROR),
+ STAT_BIT(val, TXECC_MULTIBIT_ERROR),
+ STAT_BIT(val, TXECC_SINGLE_BIT_ERROR),
+ STAT_BIT(val, TXFALSE_CONTROL_ERROR),
+ STAT_BIT(val, RXDSI_VC_ID_INVALID),
+ STAT_BIT(val, RXDSI_DATA_TYPE_NOT_REGOGNISED),
+ STAT_BIT(val, RXCHECKSUM_ERROR),
+ STAT_BIT(val, RXECC_MULTIBIT_ERROR),
+ STAT_BIT(val, RXECC_SINGLE_BIT_ERROR),
+ STAT_BIT(val, RXFALSE_CONTROL_ERROR),
+ STAT_BIT(val, RXHS_RECEIVE_TIMEOUT_ERROR),
+ STAT_BIT(val, RX_LP_TX_SYNC_ERROR),
+ STAT_BIT(val, RXEXCAPE_MODE_ENTRY_ERROR),
+ STAT_BIT(val, RXEOT_SYNC_ERROR),
+ STAT_BIT(val, RXSOT_SYNC_ERROR),
+ STAT_BIT(val, RXSOT_ERROR));
+#undef STAT_BIT
+}
+
+enum dsi_type {
+ DSI_DCS,
+ DSI_GENERIC,
+};
+
+/* enable or disable command mode hs transmissions */
+void dsi_hs_mode_enable(struct intel_dsi *intel_dsi, bool enable)
+{
+ struct drm_encoder *encoder = &intel_dsi->base.base;
+ struct drm_device *dev = encoder->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+ enum pipe pipe = intel_crtc->pipe;
+ u32 temp;
+ u32 mask = DBI_FIFO_EMPTY;
+
+ if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(pipe)) & mask) == mask, 50))
+ DRM_ERROR("Timeout waiting for DBI FIFO empty\n");
+
+ temp = I915_READ(MIPI_HS_LP_DBI_ENABLE(pipe));
+ temp &= DBI_HS_LP_MODE_MASK;
+ I915_WRITE(MIPI_HS_LP_DBI_ENABLE(pipe), enable ? DBI_HS_MODE : DBI_LP_MODE);
+
+ intel_dsi->hs = enable;
+}
+
+static int dsi_vc_send_short(struct intel_dsi *intel_dsi, int channel,
+ u8 data_type, u16 data)
+{
+ struct drm_encoder *encoder = &intel_dsi->base.base;
+ struct drm_device *dev = encoder->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+ enum pipe pipe = intel_crtc->pipe;
+ u32 ctrl_reg;
+ u32 ctrl;
+ u32 mask;
+
+ DRM_DEBUG_KMS("channel %d, data_type %d, data %04x\n",
+ channel, data_type, data);
+
+ if (intel_dsi->hs) {
+ ctrl_reg = MIPI_HS_GEN_CTRL(pipe);
+ mask = HS_CTRL_FIFO_FULL;
+ } else {
+ ctrl_reg = MIPI_LP_GEN_CTRL(pipe);
+ mask = LP_CTRL_FIFO_FULL;
+ }
+
+ if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(pipe)) & mask) == 0, 50)) {
+ DRM_ERROR("Timeout waiting for HS/LP CTRL FIFO !full\n");
+ print_stat(intel_dsi);
+ }
+
+ /*
+ * Note: This function is also used for long packets, with length passed
+ * as data, since SHORT_PACKET_PARAM_SHIFT ==
+ * LONG_PACKET_WORD_COUNT_SHIFT.
+ */
+ ctrl = data << SHORT_PACKET_PARAM_SHIFT |
+ channel << VIRTUAL_CHANNEL_SHIFT |
+ data_type << DATA_TYPE_SHIFT;
+
+ I915_WRITE(ctrl_reg, ctrl);
+
+ return 0;
+}
+
+static int dsi_vc_send_long(struct intel_dsi *intel_dsi, int channel,
+ u8 data_type, const u8 *data, int len)
+{
+ struct drm_encoder *encoder = &intel_dsi->base.base;
+ struct drm_device *dev = encoder->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+ enum pipe pipe = intel_crtc->pipe;
+ u32 data_reg;
+ int i, j, n;
+ u32 mask;
+
+ DRM_DEBUG_KMS("channel %d, data_type %d, len %04x\n",
+ channel, data_type, len);
+
+ if (intel_dsi->hs) {
+ data_reg = MIPI_HS_GEN_DATA(pipe);
+ mask = HS_DATA_FIFO_FULL;
+ } else {
+ data_reg = MIPI_LP_GEN_DATA(pipe);
+ mask = LP_DATA_FIFO_FULL;
+ }
+
+ if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(pipe)) & mask) == 0, 50))
+ DRM_ERROR("Timeout waiting for HS/LP DATA FIFO !full\n");
+
+ for (i = 0; i < len; i += n) {
+ u32 val = 0;
+ n = min_t(int, len - i, 4);
+
+ for (j = 0; j < n; j++)
+ val |= *data++ << 8 * j;
+
+ I915_WRITE(data_reg, val);
+ /* XXX: check for data fifo full, once that is set, write 4
+ * dwords, then wait for not set, then continue. */
+ }
+
+ return dsi_vc_send_short(intel_dsi, channel, data_type, len);
+}
+
+static int dsi_vc_write_common(struct intel_dsi *intel_dsi,
+ int channel, const u8 *data, int len,
+ enum dsi_type type)
+{
+ int ret;
+
+ if (len == 0) {
+ BUG_ON(type == DSI_GENERIC);
+ ret = dsi_vc_send_short(intel_dsi, channel,
+ MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM,
+ 0);
+ } else if (len == 1) {
+ ret = dsi_vc_send_short(intel_dsi, channel,
+ type == DSI_GENERIC ?
+ MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM :
+ MIPI_DSI_DCS_SHORT_WRITE, data[0]);
+ } else if (len == 2) {
+ ret = dsi_vc_send_short(intel_dsi, channel,
+ type == DSI_GENERIC ?
+ MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM :
+ MIPI_DSI_DCS_SHORT_WRITE_PARAM,
+ (data[1] << 8) | data[0]);
+ } else {
+ ret = dsi_vc_send_long(intel_dsi, channel,
+ type == DSI_GENERIC ?
+ MIPI_DSI_GENERIC_LONG_WRITE :
+ MIPI_DSI_DCS_LONG_WRITE, data, len);
+ }
+
+ return ret;
+}
+
+int dsi_vc_dcs_write(struct intel_dsi *intel_dsi, int channel,
+ const u8 *data, int len)
+{
+ return dsi_vc_write_common(intel_dsi, channel, data, len, DSI_DCS);
+}
+
+int dsi_vc_generic_write(struct intel_dsi *intel_dsi, int channel,
+ const u8 *data, int len)
+{
+ return dsi_vc_write_common(intel_dsi, channel, data, len, DSI_GENERIC);
+}
+
+static int dsi_vc_dcs_send_read_request(struct intel_dsi *intel_dsi,
+ int channel, u8 dcs_cmd)
+{
+ return dsi_vc_send_short(intel_dsi, channel, MIPI_DSI_DCS_READ,
+ dcs_cmd);
+}
+
+static int dsi_vc_generic_send_read_request(struct intel_dsi *intel_dsi,
+ int channel, u8 *reqdata,
+ int reqlen)
+{
+ u16 data;
+ u8 data_type;
+
+ switch (reqlen) {
+ case 0:
+ data_type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
+ data = 0;
+ break;
+ case 1:
+ data_type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
+ data = reqdata[0];
+ break;
+ case 2:
+ data_type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
+ data = (reqdata[1] << 8) | reqdata[0];
+ break;
+ default:
+ BUG();
+ }
+
+ return dsi_vc_send_short(intel_dsi, channel, data_type, data);
+}
+
+static int dsi_read_data_return(struct intel_dsi *intel_dsi,
+ u8 *buf, int buflen)
+{
+ struct drm_encoder *encoder = &intel_dsi->base.base;
+ struct drm_device *dev = encoder->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+ enum pipe pipe = intel_crtc->pipe;
+ int i, len = 0;
+ u32 data_reg, val;
+
+ if (intel_dsi->hs) {
+ data_reg = MIPI_HS_GEN_DATA(pipe);
+ } else {
+ data_reg = MIPI_LP_GEN_DATA(pipe);
+ }
+
+ while (len < buflen) {
+ val = I915_READ(data_reg);
+ for (i = 0; i < 4 && len < buflen; i++, len++)
+ buf[len] = val >> 8 * i;
+ }
+
+ return len;
+}
+
+int dsi_vc_dcs_read(struct intel_dsi *intel_dsi, int channel, u8 dcs_cmd,
+ u8 *buf, int buflen)
+{
+ struct drm_encoder *encoder = &intel_dsi->base.base;
+ struct drm_device *dev = encoder->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+ enum pipe pipe = intel_crtc->pipe;
+ u32 mask;
+ int ret;
+
+ /*
+ * XXX: should issue multiple read requests and reads if request is
+ * longer than MIPI_MAX_RETURN_PKT_SIZE
+ */
+
+ I915_WRITE(MIPI_INTR_STAT(pipe), GEN_READ_DATA_AVAIL);
+
+ ret = dsi_vc_dcs_send_read_request(intel_dsi, channel, dcs_cmd);
+ if (ret)
+ return ret;
+
+ mask = GEN_READ_DATA_AVAIL;
+ if (wait_for((I915_READ(MIPI_INTR_STAT(pipe)) & mask) == mask, 50))
+ DRM_ERROR("Timeout waiting for read data.\n");
+
+ ret = dsi_read_data_return(intel_dsi, buf, buflen);
+ if (ret < 0)
+ return ret;
+
+ if (ret != buflen)
+ return -EIO;
+
+ return 0;
+}
+
+int dsi_vc_generic_read(struct intel_dsi *intel_dsi, int channel,
+ u8 *reqdata, int reqlen, u8 *buf, int buflen)
+{
+ struct drm_encoder *encoder = &intel_dsi->base.base;
+ struct drm_device *dev = encoder->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+ enum pipe pipe = intel_crtc->pipe;
+ u32 mask;
+ int ret;
+
+ /*
+ * XXX: should issue multiple read requests and reads if request is
+ * longer than MIPI_MAX_RETURN_PKT_SIZE
+ */
+
+ I915_WRITE(MIPI_INTR_STAT(pipe), GEN_READ_DATA_AVAIL);
+
+ ret = dsi_vc_generic_send_read_request(intel_dsi, channel, reqdata,
+ reqlen);
+ if (ret)
+ return ret;
+
+ mask = GEN_READ_DATA_AVAIL;
+ if (wait_for((I915_READ(MIPI_INTR_STAT(pipe)) & mask) == mask, 50))
+ DRM_ERROR("Timeout waiting for read data.\n");
+
+ ret = dsi_read_data_return(intel_dsi, buf, buflen);
+ if (ret < 0)
+ return ret;
+
+ if (ret != buflen)
+ return -EIO;
+
+ return 0;
+}
+
+/*
+ * send a video mode command
+ *
+ * XXX: commands with data in MIPI_DPI_DATA?
+ */
+int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd)
+{
+ struct drm_encoder *encoder = &intel_dsi->base.base;
+ struct drm_device *dev = encoder->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+ enum pipe pipe = intel_crtc->pipe;
+ u32 mask;
+
+ /* XXX: pipe, hs */
+ if (intel_dsi->hs)
+ cmd &= ~DPI_LP_MODE;
+ else
+ cmd |= DPI_LP_MODE;
+
+ /* DPI virtual channel?! */
+
+ mask = DPI_FIFO_EMPTY;
+ if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(pipe)) & mask) == mask, 50))
+ DRM_ERROR("Timeout waiting for DPI FIFO empty.\n");
+
+ /* clear bit */
+ I915_WRITE(MIPI_INTR_STAT(pipe), SPL_PKT_SENT_INTERRUPT);
+
+ /* XXX: old code skips write if control unchanged */
+ if (cmd == I915_READ(MIPI_DPI_CONTROL(pipe)))
+ DRM_ERROR("Same special packet %02x twice in a row.\n", cmd);
+
+ I915_WRITE(MIPI_DPI_CONTROL(pipe), cmd);
+
+ mask = SPL_PKT_SENT_INTERRUPT;
+ if (wait_for((I915_READ(MIPI_INTR_STAT(pipe)) & mask) == mask, 100))
+ DRM_ERROR("Video mode command 0x%08x send failed.\n", cmd);
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/intel_dsi_cmd.h b/drivers/gpu/drm/i915/intel_dsi_cmd.h
new file mode 100644
index 000000000000..54c8a234a2e0
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_dsi_cmd.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Jani Nikula <jani.nikula@intel.com>
+ */
+
+#ifndef _INTEL_DSI_DSI_H
+#define _INTEL_DSI_DSI_H
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <video/mipi_display.h>
+#include "i915_drv.h"
+#include "intel_drv.h"
+#include "intel_dsi.h"
+
+void dsi_hs_mode_enable(struct intel_dsi *intel_dsi, bool enable);
+
+int dsi_vc_dcs_write(struct intel_dsi *intel_dsi, int channel,
+ const u8 *data, int len);
+
+int dsi_vc_generic_write(struct intel_dsi *intel_dsi, int channel,
+ const u8 *data, int len);
+
+int dsi_vc_dcs_read(struct intel_dsi *intel_dsi, int channel, u8 dcs_cmd,
+ u8 *buf, int buflen);
+
+int dsi_vc_generic_read(struct intel_dsi *intel_dsi, int channel,
+ u8 *reqdata, int reqlen, u8 *buf, int buflen);
+
+int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd);
+
+/* XXX: questionable write helpers */
+static inline int dsi_vc_dcs_write_0(struct intel_dsi *intel_dsi,
+ int channel, u8 dcs_cmd)
+{
+ return dsi_vc_dcs_write(intel_dsi, channel, &dcs_cmd, 1);
+}
+
+static inline int dsi_vc_dcs_write_1(struct intel_dsi *intel_dsi,
+ int channel, u8 dcs_cmd, u8 param)
+{
+ u8 buf[2] = { dcs_cmd, param };
+ return dsi_vc_dcs_write(intel_dsi, channel, buf, 2);
+}
+
+static inline int dsi_vc_generic_write_0(struct intel_dsi *intel_dsi,
+ int channel)
+{
+ return dsi_vc_generic_write(intel_dsi, channel, NULL, 0);
+}
+
+static inline int dsi_vc_generic_write_1(struct intel_dsi *intel_dsi,
+ int channel, u8 param)
+{
+ return dsi_vc_generic_write(intel_dsi, channel, &param, 1);
+}
+
+static inline int dsi_vc_generic_write_2(struct intel_dsi *intel_dsi,
+ int channel, u8 param1, u8 param2)
+{
+ u8 buf[2] = { param1, param2 };
+ return dsi_vc_generic_write(intel_dsi, channel, buf, 2);
+}
+
+/* XXX: questionable read helpers */
+static inline int dsi_vc_generic_read_0(struct intel_dsi *intel_dsi,
+ int channel, u8 *buf, int buflen)
+{
+ return dsi_vc_generic_read(intel_dsi, channel, NULL, 0, buf, buflen);
+}
+
+static inline int dsi_vc_generic_read_1(struct intel_dsi *intel_dsi,
+ int channel, u8 param, u8 *buf,
+ int buflen)
+{
+ return dsi_vc_generic_read(intel_dsi, channel, &param, 1, buf, buflen);
+}
+
+static inline int dsi_vc_generic_read_2(struct intel_dsi *intel_dsi,
+ int channel, u8 param1, u8 param2,
+ u8 *buf, int buflen)
+{
+ u8 req[2] = { param1, param2 };
+
+ return dsi_vc_generic_read(intel_dsi, channel, req, 2, buf, buflen);
+}
+
+
+#endif /* _INTEL_DSI_DSI_H */
diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c
new file mode 100644
index 000000000000..44279b2ade88
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_dsi_pll.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Shobhit Kumar <shobhit.kumar@intel.com>
+ * Yogesh Mohan Marimuthu <yogesh.mohan.marimuthu@intel.com>
+ */
+
+#include <linux/kernel.h>
+#include "intel_drv.h"
+#include "i915_drv.h"
+#include "intel_dsi.h"
+
+#define DSI_HSS_PACKET_SIZE 4
+#define DSI_HSE_PACKET_SIZE 4
+#define DSI_HSA_PACKET_EXTRA_SIZE 6
+#define DSI_HBP_PACKET_EXTRA_SIZE 6
+#define DSI_HACTIVE_PACKET_EXTRA_SIZE 6
+#define DSI_HFP_PACKET_EXTRA_SIZE 6
+#define DSI_EOTP_PACKET_SIZE 4
+
+struct dsi_mnp {
+ u32 dsi_pll_ctrl;
+ u32 dsi_pll_div;
+};
+
+static const u32 lfsr_converts[] = {
+ 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 62 - 70 */
+ 461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */
+ 106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */
+ 71, 35 /* 91 - 92 */
+};
+
+static u32 dsi_rr_formula(const struct drm_display_mode *mode,
+ int pixel_format, int video_mode_format,
+ int lane_count, bool eotp)
+{
+ u32 bpp;
+ u32 hactive, vactive, hfp, hsync, hbp, vfp, vsync, vbp;
+ u32 hsync_bytes, hbp_bytes, hactive_bytes, hfp_bytes;
+ u32 bytes_per_line, bytes_per_frame;
+ u32 num_frames;
+ u32 bytes_per_x_frames, bytes_per_x_frames_x_lanes;
+ u32 dsi_bit_clock_hz;
+ u32 dsi_clk;
+
+ switch (pixel_format) {
+ default:
+ case VID_MODE_FORMAT_RGB888:
+ case VID_MODE_FORMAT_RGB666_LOOSE:
+ bpp = 24;
+ break;
+ case VID_MODE_FORMAT_RGB666:
+ bpp = 18;
+ break;
+ case VID_MODE_FORMAT_RGB565:
+ bpp = 16;
+ break;
+ }
+
+ hactive = mode->hdisplay;
+ vactive = mode->vdisplay;
+ hfp = mode->hsync_start - mode->hdisplay;
+ hsync = mode->hsync_end - mode->hsync_start;
+ hbp = mode->htotal - mode->hsync_end;
+
+ vfp = mode->vsync_start - mode->vdisplay;
+ vsync = mode->vsync_end - mode->vsync_start;
+ vbp = mode->vtotal - mode->vsync_end;
+
+ hsync_bytes = DIV_ROUND_UP(hsync * bpp, 8);
+ hbp_bytes = DIV_ROUND_UP(hbp * bpp, 8);
+ hactive_bytes = DIV_ROUND_UP(hactive * bpp, 8);
+ hfp_bytes = DIV_ROUND_UP(hfp * bpp, 8);
+
+ bytes_per_line = DSI_HSS_PACKET_SIZE + hsync_bytes +
+ DSI_HSA_PACKET_EXTRA_SIZE + DSI_HSE_PACKET_SIZE +
+ hbp_bytes + DSI_HBP_PACKET_EXTRA_SIZE +
+ hactive_bytes + DSI_HACTIVE_PACKET_EXTRA_SIZE +
+ hfp_bytes + DSI_HFP_PACKET_EXTRA_SIZE;
+
+ /*
+ * XXX: Need to accurately calculate LP to HS transition timeout and add
+ * it to bytes_per_line/bytes_per_frame.
+ */
+
+ if (eotp && video_mode_format == VIDEO_MODE_BURST)
+ bytes_per_line += DSI_EOTP_PACKET_SIZE;
+
+ bytes_per_frame = vsync * bytes_per_line + vbp * bytes_per_line +
+ vactive * bytes_per_line + vfp * bytes_per_line;
+
+ if (eotp &&
+ (video_mode_format == VIDEO_MODE_NON_BURST_WITH_SYNC_PULSE ||
+ video_mode_format == VIDEO_MODE_NON_BURST_WITH_SYNC_EVENTS))
+ bytes_per_frame += DSI_EOTP_PACKET_SIZE;
+
+ num_frames = drm_mode_vrefresh(mode);
+ bytes_per_x_frames = num_frames * bytes_per_frame;
+
+ bytes_per_x_frames_x_lanes = bytes_per_x_frames / lane_count;
+
+ /* the dsi clock is divided by 2 in the hardware to get dsi ddr clock */
+ dsi_bit_clock_hz = bytes_per_x_frames_x_lanes * 8;
+ dsi_clk = dsi_bit_clock_hz / (1000 * 1000);
+
+ if (eotp && video_mode_format == VIDEO_MODE_BURST)
+ dsi_clk *= 2;
+
+ return dsi_clk;
+}
+
+#ifdef MNP_FROM_TABLE
+
+struct dsi_clock_table {
+ u32 freq;
+ u8 m;
+ u8 p;
+};
+
+static const struct dsi_clock_table dsi_clk_tbl[] = {
+ {300, 72, 6}, {313, 75, 6}, {323, 78, 6}, {333, 80, 6},
+ {343, 82, 6}, {353, 85, 6}, {363, 87, 6}, {373, 90, 6},
+ {383, 92, 6}, {390, 78, 5}, {393, 79, 5}, {400, 80, 5},
+ {401, 80, 5}, {402, 80, 5}, {403, 81, 5}, {404, 81, 5},
+ {405, 81, 5}, {406, 81, 5}, {407, 81, 5}, {408, 82, 5},
+ {409, 82, 5}, {410, 82, 5}, {411, 82, 5}, {412, 82, 5},
+ {413, 83, 5}, {414, 83, 5}, {415, 83, 5}, {416, 83, 5},
+ {417, 83, 5}, {418, 84, 5}, {419, 84, 5}, {420, 84, 5},
+ {430, 86, 5}, {440, 88, 5}, {450, 90, 5}, {460, 92, 5},
+ {470, 75, 4}, {480, 77, 4}, {490, 78, 4}, {500, 80, 4},
+ {510, 82, 4}, {520, 83, 4}, {530, 85, 4}, {540, 86, 4},
+ {550, 88, 4}, {560, 90, 4}, {570, 91, 4}, {580, 70, 3},
+ {590, 71, 3}, {600, 72, 3}, {610, 73, 3}, {620, 74, 3},
+ {630, 76, 3}, {640, 77, 3}, {650, 78, 3}, {660, 79, 3},
+ {670, 80, 3}, {680, 82, 3}, {690, 83, 3}, {700, 84, 3},
+ {710, 85, 3}, {720, 86, 3}, {730, 88, 3}, {740, 89, 3},
+ {750, 90, 3}, {760, 91, 3}, {770, 92, 3}, {780, 62, 2},
+ {790, 63, 2}, {800, 64, 2}, {880, 70, 2}, {900, 72, 2},
+ {1000, 80, 2}, /* dsi clock frequency in Mhz*/
+};
+
+static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
+{
+ unsigned int i;
+ u8 m;
+ u8 n;
+ u8 p;
+ u32 m_seed;
+
+ if (dsi_clk < 300 || dsi_clk > 1000)
+ return -ECHRNG;
+
+ for (i = 0; i <= ARRAY_SIZE(dsi_clk_tbl); i++) {
+ if (dsi_clk_tbl[i].freq > dsi_clk)
+ break;
+ }
+
+ m = dsi_clk_tbl[i].m;
+ p = dsi_clk_tbl[i].p;
+ m_seed = lfsr_converts[m - 62];
+ n = 1;
+ dsi_mnp->dsi_pll_ctrl = 1 << (DSI_PLL_P1_POST_DIV_SHIFT + p - 2);
+ dsi_mnp->dsi_pll_div = (n - 1) << DSI_PLL_N1_DIV_SHIFT |
+ m_seed << DSI_PLL_M1_DIV_SHIFT;
+
+ return 0;
+}
+
+#else
+
+static int dsi_calc_mnp(u32 dsi_clk, struct dsi_mnp *dsi_mnp)
+{
+ u32 m, n, p;
+ u32 ref_clk;
+ u32 error;
+ u32 tmp_error;
+ u32 target_dsi_clk;
+ u32 calc_dsi_clk;
+ u32 calc_m;
+ u32 calc_p;
+ u32 m_seed;
+
+ if (dsi_clk < 300 || dsi_clk > 1150) {
+ DRM_ERROR("DSI CLK Out of Range\n");
+ return -ECHRNG;
+ }
+
+ ref_clk = 25000;
+ target_dsi_clk = dsi_clk * 1000;
+ error = 0xFFFFFFFF;
+ calc_m = 0;
+ calc_p = 0;
+
+ for (m = 62; m <= 92; m++) {
+ for (p = 2; p <= 6; p++) {
+
+ calc_dsi_clk = (m * ref_clk) / p;
+ if (calc_dsi_clk >= target_dsi_clk) {
+ tmp_error = calc_dsi_clk - target_dsi_clk;
+ if (tmp_error < error) {
+ error = tmp_error;
+ calc_m = m;
+ calc_p = p;
+ }
+ }
+ }
+ }
+
+ m_seed = lfsr_converts[calc_m - 62];
+ n = 1;
+ dsi_mnp->dsi_pll_ctrl = 1 << (DSI_PLL_P1_POST_DIV_SHIFT + calc_p - 2);
+ dsi_mnp->dsi_pll_div = (n - 1) << DSI_PLL_N1_DIV_SHIFT |
+ m_seed << DSI_PLL_M1_DIV_SHIFT;
+
+ return 0;
+}
+
+#endif
+
+/*
+ * XXX: The muxing and gating is hard coded for now. Need to add support for
+ * sharing PLLs with two DSI outputs.
+ */
+static void vlv_configure_dsi_pll(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+ const struct drm_display_mode *mode = &intel_crtc->config.adjusted_mode;
+ struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+ int ret;
+ struct dsi_mnp dsi_mnp;
+ u32 dsi_clk;
+
+ dsi_clk = dsi_rr_formula(mode, intel_dsi->pixel_format,
+ intel_dsi->video_mode_format,
+ intel_dsi->lane_count, !intel_dsi->eot_disable);
+
+ ret = dsi_calc_mnp(dsi_clk, &dsi_mnp);
+ if (ret) {
+ DRM_DEBUG_KMS("dsi_calc_mnp failed\n");
+ return;
+ }
+
+ dsi_mnp.dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI0_DSIPLL;
+
+ DRM_DEBUG_KMS("dsi pll div %08x, ctrl %08x\n",
+ dsi_mnp.dsi_pll_div, dsi_mnp.dsi_pll_ctrl);
+
+ vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, 0);
+ vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_DIVIDER, dsi_mnp.dsi_pll_div);
+ vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_mnp.dsi_pll_ctrl);
+}
+
+void vlv_enable_dsi_pll(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+ u32 tmp;
+
+ DRM_DEBUG_KMS("\n");
+
+ mutex_lock(&dev_priv->dpio_lock);
+
+ vlv_configure_dsi_pll(encoder);
+
+ /* wait at least 0.5 us after ungating before enabling VCO */
+ usleep_range(1, 10);
+
+ tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL);
+ tmp |= DSI_PLL_VCO_EN;
+ vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp);
+
+ mutex_unlock(&dev_priv->dpio_lock);
+
+ if (wait_for(I915_READ(PIPECONF(PIPE_A)) & PIPECONF_DSI_PLL_LOCKED, 20)) {
+ DRM_ERROR("DSI PLL lock failed\n");
+ return;
+ }
+
+ DRM_DEBUG_KMS("DSI PLL locked\n");
+}
+
+void vlv_disable_dsi_pll(struct intel_encoder *encoder)
+{
+ struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+ u32 tmp;
+
+ DRM_DEBUG_KMS("\n");
+
+ mutex_lock(&dev_priv->dpio_lock);
+
+ tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL);
+ tmp &= ~DSI_PLL_VCO_EN;
+ tmp |= DSI_PLL_LDO_GATE;
+ vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp);
+
+ mutex_unlock(&dev_priv->dpio_lock);
+}
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 7fa7df546c1e..91287d1d3059 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -153,6 +153,8 @@ static void intel_dvo_get_config(struct intel_encoder *encoder,
flags |= DRM_MODE_FLAG_NVSYNC;
pipe_config->adjusted_mode.flags |= flags;
+
+ pipe_config->adjusted_mode.crtc_clock = pipe_config->port_clock;
}
static void intel_disable_dvo(struct intel_encoder *encoder)
@@ -267,11 +269,6 @@ static bool intel_dvo_compute_config(struct intel_encoder *encoder,
drm_mode_set_crtcinfo(adjusted_mode, 0);
}
- if (intel_dvo->dev.dev_ops->mode_fixup)
- return intel_dvo->dev.dev_ops->mode_fixup(&intel_dvo->dev,
- &pipe_config->requested_mode,
- adjusted_mode);
-
return true;
}
@@ -451,11 +448,11 @@ void intel_dvo_init(struct drm_device *dev)
int i;
int encoder_type = DRM_MODE_ENCODER_NONE;
- intel_dvo = kzalloc(sizeof(struct intel_dvo), GFP_KERNEL);
+ intel_dvo = kzalloc(sizeof(*intel_dvo), GFP_KERNEL);
if (!intel_dvo)
return;
- intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
+ intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
if (!intel_connector) {
kfree(intel_dvo);
return;
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index bc2100007b21..d883b77b1b78 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -184,6 +184,27 @@ out:
return ret;
}
+/** Sets the color ramps on behalf of RandR */
+static void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
+ u16 blue, int regno)
+{
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+ intel_crtc->lut_r[regno] = red >> 8;
+ intel_crtc->lut_g[regno] = green >> 8;
+ intel_crtc->lut_b[regno] = blue >> 8;
+}
+
+static void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+ u16 *blue, int regno)
+{
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+ *red = intel_crtc->lut_r[regno] << 8;
+ *green = intel_crtc->lut_g[regno] << 8;
+ *blue = intel_crtc->lut_b[regno] << 8;
+}
+
static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
.gamma_set = intel_crtc_fb_gamma_set,
.gamma_get = intel_crtc_fb_gamma_get,
@@ -216,7 +237,7 @@ int intel_fbdev_init(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
- ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
+ ifbdev = kzalloc(sizeof(*ifbdev), GFP_KERNEL);
if (!ifbdev)
return -ENOMEM;
@@ -225,7 +246,7 @@ int intel_fbdev_init(struct drm_device *dev)
ret = drm_fb_helper_init(dev, &ifbdev->helper,
INTEL_INFO(dev)->num_pipes,
- INTELFB_CONN_LIMIT);
+ 4);
if (ret) {
kfree(ifbdev);
return ret;
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 4148cc85bf7f..6004f9c549aa 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -713,6 +713,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
u32 tmp, flags = 0;
+ int dotclock;
tmp = I915_READ(intel_hdmi->hdmi_reg);
@@ -727,6 +728,16 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
flags |= DRM_MODE_FLAG_NVSYNC;
pipe_config->adjusted_mode.flags |= flags;
+
+ if ((tmp & SDVO_COLOR_FORMAT_MASK) == HDMI_COLOR_FORMAT_12bpc)
+ dotclock = pipe_config->port_clock * 2 / 3;
+ else
+ dotclock = pipe_config->port_clock;
+
+ if (HAS_PCH_SPLIT(dev_priv->dev))
+ ironlake_check_encoder_dotclock(pipe_config, dotclock);
+
+ pipe_config->adjusted_mode.crtc_clock = dotclock;
}
static void intel_enable_hdmi(struct intel_encoder *encoder)
@@ -862,7 +873,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
struct drm_device *dev = encoder->base.dev;
struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
- int clock_12bpc = pipe_config->requested_mode.clock * 3 / 2;
+ int clock_12bpc = pipe_config->adjusted_mode.crtc_clock * 3 / 2;
int portclock_limit = hdmi_portclock_limit(intel_hdmi);
int desired_bpp;
@@ -904,7 +915,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
pipe_config->pipe_bpp = desired_bpp;
}
- if (adjusted_mode->clock > portclock_limit) {
+ if (adjusted_mode->crtc_clock > portclock_limit) {
DRM_DEBUG_KMS("too high HDMI clock, rejecting mode\n");
return false;
}
@@ -1079,35 +1090,35 @@ static void intel_hdmi_pre_enable(struct intel_encoder *encoder)
/* Enable clock channels for this port */
mutex_lock(&dev_priv->dpio_lock);
- val = vlv_dpio_read(dev_priv, DPIO_DATA_LANE_A(port));
+ val = vlv_dpio_read(dev_priv, pipe, DPIO_DATA_LANE_A(port));
val = 0;
if (pipe)
val |= (1<<21);
else
val &= ~(1<<21);
val |= 0x001000c4;
- vlv_dpio_write(dev_priv, DPIO_DATA_CHANNEL(port), val);
+ vlv_dpio_write(dev_priv, pipe, DPIO_DATA_CHANNEL(port), val);
/* HDMI 1.0V-2dB */
- vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port), 0);
- vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL4(port),
+ vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port), 0);
+ vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL4(port),
0x2b245f5f);
- vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL2(port),
+ vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL2(port),
0x5578b83a);
- vlv_dpio_write(dev_priv, DPIO_TX_SWING_CTL3(port),
+ vlv_dpio_write(dev_priv, pipe, DPIO_TX_SWING_CTL3(port),
0x0c782040);
- vlv_dpio_write(dev_priv, DPIO_TX3_SWING_CTL4(port),
+ vlv_dpio_write(dev_priv, pipe, DPIO_TX3_SWING_CTL4(port),
0x2b247878);
- vlv_dpio_write(dev_priv, DPIO_PCS_STAGGER0(port), 0x00030000);
- vlv_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port),
+ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER0(port), 0x00030000);
+ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port),
0x00002000);
- vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port),
+ vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port),
DPIO_TX_OCALINIT_EN);
/* Program lane clock */
- vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(port),
+ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF0(port),
0x00760018);
- vlv_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(port),
+ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLOCKBUF8(port),
0x00400888);
mutex_unlock(&dev_priv->dpio_lock);
@@ -1121,30 +1132,33 @@ static void intel_hdmi_pre_pll_enable(struct intel_encoder *encoder)
struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc =
+ to_intel_crtc(encoder->base.crtc);
int port = vlv_dport_to_channel(dport);
+ int pipe = intel_crtc->pipe;
if (!IS_VALLEYVIEW(dev))
return;
/* Program Tx lane resets to default */
mutex_lock(&dev_priv->dpio_lock);
- vlv_dpio_write(dev_priv, DPIO_PCS_TX(port),
+ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port),
DPIO_PCS_TX_LANE2_RESET |
DPIO_PCS_TX_LANE1_RESET);
- vlv_dpio_write(dev_priv, DPIO_PCS_CLK(port),
+ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port),
DPIO_PCS_CLK_CRI_RXEB_EIOS_EN |
DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN |
(1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) |
DPIO_PCS_CLK_SOFT_RESET);
/* Fix up inter-pair skew failure */
- vlv_dpio_write(dev_priv, DPIO_PCS_STAGGER1(port), 0x00750f00);
- vlv_dpio_write(dev_priv, DPIO_TX_CTL(port), 0x00001500);
- vlv_dpio_write(dev_priv, DPIO_TX_LANE(port), 0x40400000);
+ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_STAGGER1(port), 0x00750f00);
+ vlv_dpio_write(dev_priv, pipe, DPIO_TX_CTL(port), 0x00001500);
+ vlv_dpio_write(dev_priv, pipe, DPIO_TX_LANE(port), 0x40400000);
- vlv_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(port),
+ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CTL_OVER1(port),
0x00002000);
- vlv_dpio_write(dev_priv, DPIO_TX_OCALINIT(port),
+ vlv_dpio_write(dev_priv, pipe, DPIO_TX_OCALINIT(port),
DPIO_TX_OCALINIT_EN);
mutex_unlock(&dev_priv->dpio_lock);
}
@@ -1153,12 +1167,15 @@ static void intel_hdmi_post_disable(struct intel_encoder *encoder)
{
struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+ struct intel_crtc *intel_crtc =
+ to_intel_crtc(encoder->base.crtc);
int port = vlv_dport_to_channel(dport);
+ int pipe = intel_crtc->pipe;
/* Reset lanes to avoid HDMI flicker (VLV w/a) */
mutex_lock(&dev_priv->dpio_lock);
- vlv_dpio_write(dev_priv, DPIO_PCS_TX(port), 0x00000000);
- vlv_dpio_write(dev_priv, DPIO_PCS_CLK(port), 0x00e00060);
+ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_TX(port), 0x00000000);
+ vlv_dpio_write(dev_priv, pipe, DPIO_PCS_CLK(port), 0x00e00060);
mutex_unlock(&dev_priv->dpio_lock);
}
@@ -1211,6 +1228,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
connector->interlace_allowed = 1;
connector->doublescan_allowed = 0;
+ connector->stereo_allowed = 1;
switch (port) {
case PORT_B:
@@ -1275,11 +1293,11 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector;
- intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL);
+ intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
if (!intel_dig_port)
return;
- intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
+ intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
if (!intel_connector) {
kfree(intel_dig_port);
return;
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 831a5c021c4b..fb3f8efcc6e2 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -92,6 +92,7 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 lvds_reg, tmp, flags = 0;
+ int dotclock;
if (HAS_PCH_SPLIT(dev))
lvds_reg = PCH_LVDS;
@@ -116,6 +117,13 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
pipe_config->gmch_pfit.control |= tmp & PANEL_8TO6_DITHER_ENABLE;
}
+
+ dotclock = pipe_config->port_clock;
+
+ if (HAS_PCH_SPLIT(dev_priv->dev))
+ ironlake_check_encoder_dotclock(pipe_config, dotclock);
+
+ pipe_config->adjusted_mode.crtc_clock = dotclock;
}
/* The LVDS pin pair needs to be on before the DPLLs are enabled.
@@ -786,7 +794,8 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev,
return true;
for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
- struct child_device_config *child = dev_priv->vbt.child_dev + i;
+ union child_device_config *uchild = dev_priv->vbt.child_dev + i;
+ struct old_child_dev_config *child = &uchild->old;
/* If the device type is not LFP, continue.
* We have to check both the new identifiers as well as the
@@ -940,11 +949,11 @@ void intel_lvds_init(struct drm_device *dev)
}
}
- lvds_encoder = kzalloc(sizeof(struct intel_lvds_encoder), GFP_KERNEL);
+ lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);
if (!lvds_encoder)
return;
- lvds_connector = kzalloc(sizeof(struct intel_lvds_connector), GFP_KERNEL);
+ lvds_connector = kzalloc(sizeof(*lvds_connector), GFP_KERNEL);
if (!lvds_connector) {
kfree(lvds_encoder);
return;
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index 119771ff46ab..2acf5cae20e4 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -36,8 +36,11 @@
#include "i915_drv.h"
#include "intel_drv.h"
-#define PCI_ASLE 0xe4
-#define PCI_ASLS 0xfc
+#define PCI_ASLE 0xe4
+#define PCI_ASLS 0xfc
+#define PCI_SWSCI 0xe8
+#define PCI_SWSCI_SCISEL (1 << 15)
+#define PCI_SWSCI_GSSCIE (1 << 0)
#define OPREGION_HEADER_OFFSET 0
#define OPREGION_ACPI_OFFSET 0x100
@@ -107,25 +110,38 @@ struct opregion_asle {
u32 epfm; /* enabled panel fitting modes */
u8 plut[74]; /* panel LUT and identifier */
u32 pfmb; /* PWM freq and min brightness */
- u8 rsvd[102];
+ u32 cddv; /* color correction default values */
+ u32 pcft; /* power conservation features */
+ u32 srot; /* supported rotation angles */
+ u32 iuer; /* IUER events */
+ u8 rsvd[86];
} __attribute__((packed));
/* Driver readiness indicator */
#define ASLE_ARDY_READY (1 << 0)
#define ASLE_ARDY_NOT_READY (0 << 0)
-/* ASLE irq request bits */
-#define ASLE_SET_ALS_ILLUM (1 << 0)
-#define ASLE_SET_BACKLIGHT (1 << 1)
-#define ASLE_SET_PFIT (1 << 2)
-#define ASLE_SET_PWM_FREQ (1 << 3)
-#define ASLE_REQ_MSK 0xf
-
-/* response bits of ASLE irq request */
-#define ASLE_ALS_ILLUM_FAILED (1<<10)
-#define ASLE_BACKLIGHT_FAILED (1<<12)
-#define ASLE_PFIT_FAILED (1<<14)
-#define ASLE_PWM_FREQ_FAILED (1<<16)
+/* ASLE Interrupt Command (ASLC) bits */
+#define ASLC_SET_ALS_ILLUM (1 << 0)
+#define ASLC_SET_BACKLIGHT (1 << 1)
+#define ASLC_SET_PFIT (1 << 2)
+#define ASLC_SET_PWM_FREQ (1 << 3)
+#define ASLC_SUPPORTED_ROTATION_ANGLES (1 << 4)
+#define ASLC_BUTTON_ARRAY (1 << 5)
+#define ASLC_CONVERTIBLE_INDICATOR (1 << 6)
+#define ASLC_DOCKING_INDICATOR (1 << 7)
+#define ASLC_ISCT_STATE_CHANGE (1 << 8)
+#define ASLC_REQ_MSK 0x1ff
+/* response bits */
+#define ASLC_ALS_ILLUM_FAILED (1 << 10)
+#define ASLC_BACKLIGHT_FAILED (1 << 12)
+#define ASLC_PFIT_FAILED (1 << 14)
+#define ASLC_PWM_FREQ_FAILED (1 << 16)
+#define ASLC_ROTATION_ANGLES_FAILED (1 << 18)
+#define ASLC_BUTTON_ARRAY_FAILED (1 << 20)
+#define ASLC_CONVERTIBLE_FAILED (1 << 22)
+#define ASLC_DOCKING_FAILED (1 << 24)
+#define ASLC_ISCT_STATE_FAILED (1 << 26)
/* Technology enabled indicator */
#define ASLE_TCHE_ALS_EN (1 << 0)
@@ -151,6 +167,60 @@ struct opregion_asle {
#define ASLE_CBLV_VALID (1<<31)
+/* IUER */
+#define ASLE_IUER_DOCKING (1 << 7)
+#define ASLE_IUER_CONVERTIBLE (1 << 6)
+#define ASLE_IUER_ROTATION_LOCK_BTN (1 << 4)
+#define ASLE_IUER_VOLUME_DOWN_BTN (1 << 3)
+#define ASLE_IUER_VOLUME_UP_BTN (1 << 2)
+#define ASLE_IUER_WINDOWS_BTN (1 << 1)
+#define ASLE_IUER_POWER_BTN (1 << 0)
+
+/* Software System Control Interrupt (SWSCI) */
+#define SWSCI_SCIC_INDICATOR (1 << 0)
+#define SWSCI_SCIC_MAIN_FUNCTION_SHIFT 1
+#define SWSCI_SCIC_MAIN_FUNCTION_MASK (0xf << 1)
+#define SWSCI_SCIC_SUB_FUNCTION_SHIFT 8
+#define SWSCI_SCIC_SUB_FUNCTION_MASK (0xff << 8)
+#define SWSCI_SCIC_EXIT_PARAMETER_SHIFT 8
+#define SWSCI_SCIC_EXIT_PARAMETER_MASK (0xff << 8)
+#define SWSCI_SCIC_EXIT_STATUS_SHIFT 5
+#define SWSCI_SCIC_EXIT_STATUS_MASK (7 << 5)
+#define SWSCI_SCIC_EXIT_STATUS_SUCCESS 1
+
+#define SWSCI_FUNCTION_CODE(main, sub) \
+ ((main) << SWSCI_SCIC_MAIN_FUNCTION_SHIFT | \
+ (sub) << SWSCI_SCIC_SUB_FUNCTION_SHIFT)
+
+/* SWSCI: Get BIOS Data (GBDA) */
+#define SWSCI_GBDA 4
+#define SWSCI_GBDA_SUPPORTED_CALLS SWSCI_FUNCTION_CODE(SWSCI_GBDA, 0)
+#define SWSCI_GBDA_REQUESTED_CALLBACKS SWSCI_FUNCTION_CODE(SWSCI_GBDA, 1)
+#define SWSCI_GBDA_BOOT_DISPLAY_PREF SWSCI_FUNCTION_CODE(SWSCI_GBDA, 4)
+#define SWSCI_GBDA_PANEL_DETAILS SWSCI_FUNCTION_CODE(SWSCI_GBDA, 5)
+#define SWSCI_GBDA_TV_STANDARD SWSCI_FUNCTION_CODE(SWSCI_GBDA, 6)
+#define SWSCI_GBDA_INTERNAL_GRAPHICS SWSCI_FUNCTION_CODE(SWSCI_GBDA, 7)
+#define SWSCI_GBDA_SPREAD_SPECTRUM SWSCI_FUNCTION_CODE(SWSCI_GBDA, 10)
+
+/* SWSCI: System BIOS Callbacks (SBCB) */
+#define SWSCI_SBCB 6
+#define SWSCI_SBCB_SUPPORTED_CALLBACKS SWSCI_FUNCTION_CODE(SWSCI_SBCB, 0)
+#define SWSCI_SBCB_INIT_COMPLETION SWSCI_FUNCTION_CODE(SWSCI_SBCB, 1)
+#define SWSCI_SBCB_PRE_HIRES_SET_MODE SWSCI_FUNCTION_CODE(SWSCI_SBCB, 3)
+#define SWSCI_SBCB_POST_HIRES_SET_MODE SWSCI_FUNCTION_CODE(SWSCI_SBCB, 4)
+#define SWSCI_SBCB_DISPLAY_SWITCH SWSCI_FUNCTION_CODE(SWSCI_SBCB, 5)
+#define SWSCI_SBCB_SET_TV_FORMAT SWSCI_FUNCTION_CODE(SWSCI_SBCB, 6)
+#define SWSCI_SBCB_ADAPTER_POWER_STATE SWSCI_FUNCTION_CODE(SWSCI_SBCB, 7)
+#define SWSCI_SBCB_DISPLAY_POWER_STATE SWSCI_FUNCTION_CODE(SWSCI_SBCB, 8)
+#define SWSCI_SBCB_SET_BOOT_DISPLAY SWSCI_FUNCTION_CODE(SWSCI_SBCB, 9)
+#define SWSCI_SBCB_SET_PANEL_DETAILS SWSCI_FUNCTION_CODE(SWSCI_SBCB, 10)
+#define SWSCI_SBCB_SET_INTERNAL_GFX SWSCI_FUNCTION_CODE(SWSCI_SBCB, 11)
+#define SWSCI_SBCB_POST_HIRES_TO_DOS_FS SWSCI_FUNCTION_CODE(SWSCI_SBCB, 16)
+#define SWSCI_SBCB_SUSPEND_RESUME SWSCI_FUNCTION_CODE(SWSCI_SBCB, 17)
+#define SWSCI_SBCB_SET_SPREAD_SPECTRUM SWSCI_FUNCTION_CODE(SWSCI_SBCB, 18)
+#define SWSCI_SBCB_POST_VBE_PM SWSCI_FUNCTION_CODE(SWSCI_SBCB, 19)
+#define SWSCI_SBCB_ENABLE_DISABLE_AUDIO SWSCI_FUNCTION_CODE(SWSCI_SBCB, 21)
+
#define ACPI_OTHER_OUTPUT (0<<8)
#define ACPI_VGA_OUTPUT (1<<8)
#define ACPI_TV_OUTPUT (2<<8)
@@ -158,6 +228,169 @@ struct opregion_asle {
#define ACPI_LVDS_OUTPUT (4<<8)
#ifdef CONFIG_ACPI
+static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct opregion_swsci __iomem *swsci = dev_priv->opregion.swsci;
+ u32 main_function, sub_function, scic;
+ u16 pci_swsci;
+ u32 dslp;
+
+ if (!swsci)
+ return -ENODEV;
+
+ main_function = (function & SWSCI_SCIC_MAIN_FUNCTION_MASK) >>
+ SWSCI_SCIC_MAIN_FUNCTION_SHIFT;
+ sub_function = (function & SWSCI_SCIC_SUB_FUNCTION_MASK) >>
+ SWSCI_SCIC_SUB_FUNCTION_SHIFT;
+
+ /* Check if we can call the function. See swsci_setup for details. */
+ if (main_function == SWSCI_SBCB) {
+ if ((dev_priv->opregion.swsci_sbcb_sub_functions &
+ (1 << sub_function)) == 0)
+ return -EINVAL;
+ } else if (main_function == SWSCI_GBDA) {
+ if ((dev_priv->opregion.swsci_gbda_sub_functions &
+ (1 << sub_function)) == 0)
+ return -EINVAL;
+ }
+
+ /* Driver sleep timeout in ms. */
+ dslp = ioread32(&swsci->dslp);
+ if (!dslp) {
+ dslp = 2;
+ } else if (dslp > 500) {
+ /* Hey bios, trust must be earned. */
+ WARN_ONCE(1, "excessive driver sleep timeout (DSPL) %u\n", dslp);
+ dslp = 500;
+ }
+
+ /* The spec tells us to do this, but we are the only user... */
+ scic = ioread32(&swsci->scic);
+ if (scic & SWSCI_SCIC_INDICATOR) {
+ DRM_DEBUG_DRIVER("SWSCI request already in progress\n");
+ return -EBUSY;
+ }
+
+ scic = function | SWSCI_SCIC_INDICATOR;
+
+ iowrite32(parm, &swsci->parm);
+ iowrite32(scic, &swsci->scic);
+
+ /* Ensure SCI event is selected and event trigger is cleared. */
+ pci_read_config_word(dev->pdev, PCI_SWSCI, &pci_swsci);
+ if (!(pci_swsci & PCI_SWSCI_SCISEL) || (pci_swsci & PCI_SWSCI_GSSCIE)) {
+ pci_swsci |= PCI_SWSCI_SCISEL;
+ pci_swsci &= ~PCI_SWSCI_GSSCIE;
+ pci_write_config_word(dev->pdev, PCI_SWSCI, pci_swsci);
+ }
+
+ /* Use event trigger to tell bios to check the mail. */
+ pci_swsci |= PCI_SWSCI_GSSCIE;
+ pci_write_config_word(dev->pdev, PCI_SWSCI, pci_swsci);
+
+ /* Poll for the result. */
+#define C (((scic = ioread32(&swsci->scic)) & SWSCI_SCIC_INDICATOR) == 0)
+ if (wait_for(C, dslp)) {
+ DRM_DEBUG_DRIVER("SWSCI request timed out\n");
+ return -ETIMEDOUT;
+ }
+
+ scic = (scic & SWSCI_SCIC_EXIT_STATUS_MASK) >>
+ SWSCI_SCIC_EXIT_STATUS_SHIFT;
+
+ /* Note: scic == 0 is an error! */
+ if (scic != SWSCI_SCIC_EXIT_STATUS_SUCCESS) {
+ DRM_DEBUG_DRIVER("SWSCI request error %u\n", scic);
+ return -EIO;
+ }
+
+ if (parm_out)
+ *parm_out = ioread32(&swsci->parm);
+
+ return 0;
+
+#undef C
+}
+
+#define DISPLAY_TYPE_CRT 0
+#define DISPLAY_TYPE_TV 1
+#define DISPLAY_TYPE_EXTERNAL_FLAT_PANEL 2
+#define DISPLAY_TYPE_INTERNAL_FLAT_PANEL 3
+
+int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
+ bool enable)
+{
+ struct drm_device *dev = intel_encoder->base.dev;
+ u32 parm = 0;
+ u32 type = 0;
+ u32 port;
+
+ /* don't care about old stuff for now */
+ if (!HAS_DDI(dev))
+ return 0;
+
+ port = intel_ddi_get_encoder_port(intel_encoder);
+ if (port == PORT_E) {
+ port = 0;
+ } else {
+ parm |= 1 << port;
+ port++;
+ }
+
+ if (!enable)
+ parm |= 4 << 8;
+
+ switch (intel_encoder->type) {
+ case INTEL_OUTPUT_ANALOG:
+ type = DISPLAY_TYPE_CRT;
+ break;
+ case INTEL_OUTPUT_UNKNOWN:
+ case INTEL_OUTPUT_DISPLAYPORT:
+ case INTEL_OUTPUT_HDMI:
+ type = DISPLAY_TYPE_EXTERNAL_FLAT_PANEL;
+ break;
+ case INTEL_OUTPUT_EDP:
+ type = DISPLAY_TYPE_INTERNAL_FLAT_PANEL;
+ break;
+ default:
+ WARN_ONCE(1, "unsupported intel_encoder type %d\n",
+ intel_encoder->type);
+ return -EINVAL;
+ }
+
+ parm |= type << (16 + port * 3);
+
+ return swsci(dev, SWSCI_SBCB_DISPLAY_POWER_STATE, parm, NULL);
+}
+
+static const struct {
+ pci_power_t pci_power_state;
+ u32 parm;
+} power_state_map[] = {
+ { PCI_D0, 0x00 },
+ { PCI_D1, 0x01 },
+ { PCI_D2, 0x02 },
+ { PCI_D3hot, 0x04 },
+ { PCI_D3cold, 0x04 },
+};
+
+int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state)
+{
+ int i;
+
+ if (!HAS_DDI(dev))
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(power_state_map); i++) {
+ if (state == power_state_map[i].pci_power_state)
+ return swsci(dev, SWSCI_SBCB_ADAPTER_POWER_STATE,
+ power_state_map[i].parm, NULL);
+ }
+
+ return -EINVAL;
+}
+
static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -166,11 +399,11 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
if (!(bclp & ASLE_BCLP_VALID))
- return ASLE_BACKLIGHT_FAILED;
+ return ASLC_BACKLIGHT_FAILED;
bclp &= ASLE_BCLP_MSK;
if (bclp > 255)
- return ASLE_BACKLIGHT_FAILED;
+ return ASLC_BACKLIGHT_FAILED;
intel_panel_set_backlight(dev, bclp, 255);
iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv);
@@ -183,13 +416,13 @@ static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi)
/* alsi is the current ALS reading in lux. 0 indicates below sensor
range, 0xffff indicates above sensor range. 1-0xfffe are valid */
DRM_DEBUG_DRIVER("Illum is not supported\n");
- return ASLE_ALS_ILLUM_FAILED;
+ return ASLC_ALS_ILLUM_FAILED;
}
static u32 asle_set_pwm_freq(struct drm_device *dev, u32 pfmb)
{
DRM_DEBUG_DRIVER("PWM freq is not supported\n");
- return ASLE_PWM_FREQ_FAILED;
+ return ASLC_PWM_FREQ_FAILED;
}
static u32 asle_set_pfit(struct drm_device *dev, u32 pfit)
@@ -197,39 +430,106 @@ static u32 asle_set_pfit(struct drm_device *dev, u32 pfit)
/* Panel fitting is currently controlled by the X code, so this is a
noop until modesetting support works fully */
DRM_DEBUG_DRIVER("Pfit is not supported\n");
- return ASLE_PFIT_FAILED;
+ return ASLC_PFIT_FAILED;
+}
+
+static u32 asle_set_supported_rotation_angles(struct drm_device *dev, u32 srot)
+{
+ DRM_DEBUG_DRIVER("SROT is not supported\n");
+ return ASLC_ROTATION_ANGLES_FAILED;
+}
+
+static u32 asle_set_button_array(struct drm_device *dev, u32 iuer)
+{
+ if (!iuer)
+ DRM_DEBUG_DRIVER("Button array event is not supported (nothing)\n");
+ if (iuer & ASLE_IUER_ROTATION_LOCK_BTN)
+ DRM_DEBUG_DRIVER("Button array event is not supported (rotation lock)\n");
+ if (iuer & ASLE_IUER_VOLUME_DOWN_BTN)
+ DRM_DEBUG_DRIVER("Button array event is not supported (volume down)\n");
+ if (iuer & ASLE_IUER_VOLUME_UP_BTN)
+ DRM_DEBUG_DRIVER("Button array event is not supported (volume up)\n");
+ if (iuer & ASLE_IUER_WINDOWS_BTN)
+ DRM_DEBUG_DRIVER("Button array event is not supported (windows)\n");
+ if (iuer & ASLE_IUER_POWER_BTN)
+ DRM_DEBUG_DRIVER("Button array event is not supported (power)\n");
+
+ return ASLC_BUTTON_ARRAY_FAILED;
+}
+
+static u32 asle_set_convertible(struct drm_device *dev, u32 iuer)
+{
+ if (iuer & ASLE_IUER_CONVERTIBLE)
+ DRM_DEBUG_DRIVER("Convertible is not supported (clamshell)\n");
+ else
+ DRM_DEBUG_DRIVER("Convertible is not supported (slate)\n");
+
+ return ASLC_CONVERTIBLE_FAILED;
+}
+
+static u32 asle_set_docking(struct drm_device *dev, u32 iuer)
+{
+ if (iuer & ASLE_IUER_DOCKING)
+ DRM_DEBUG_DRIVER("Docking is not supported (docked)\n");
+ else
+ DRM_DEBUG_DRIVER("Docking is not supported (undocked)\n");
+
+ return ASLC_DOCKING_FAILED;
+}
+
+static u32 asle_isct_state(struct drm_device *dev)
+{
+ DRM_DEBUG_DRIVER("ISCT is not supported\n");
+ return ASLC_ISCT_STATE_FAILED;
}
void intel_opregion_asle_intr(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct opregion_asle __iomem *asle = dev_priv->opregion.asle;
- u32 asle_stat = 0;
- u32 asle_req;
+ u32 aslc_stat = 0;
+ u32 aslc_req;
if (!asle)
return;
- asle_req = ioread32(&asle->aslc) & ASLE_REQ_MSK;
+ aslc_req = ioread32(&asle->aslc);
- if (!asle_req) {
- DRM_DEBUG_DRIVER("non asle set request??\n");
+ if (!(aslc_req & ASLC_REQ_MSK)) {
+ DRM_DEBUG_DRIVER("No request on ASLC interrupt 0x%08x\n",
+ aslc_req);
return;
}
- if (asle_req & ASLE_SET_ALS_ILLUM)
- asle_stat |= asle_set_als_illum(dev, ioread32(&asle->alsi));
+ if (aslc_req & ASLC_SET_ALS_ILLUM)
+ aslc_stat |= asle_set_als_illum(dev, ioread32(&asle->alsi));
+
+ if (aslc_req & ASLC_SET_BACKLIGHT)
+ aslc_stat |= asle_set_backlight(dev, ioread32(&asle->bclp));
+
+ if (aslc_req & ASLC_SET_PFIT)
+ aslc_stat |= asle_set_pfit(dev, ioread32(&asle->pfit));
+
+ if (aslc_req & ASLC_SET_PWM_FREQ)
+ aslc_stat |= asle_set_pwm_freq(dev, ioread32(&asle->pfmb));
- if (asle_req & ASLE_SET_BACKLIGHT)
- asle_stat |= asle_set_backlight(dev, ioread32(&asle->bclp));
+ if (aslc_req & ASLC_SUPPORTED_ROTATION_ANGLES)
+ aslc_stat |= asle_set_supported_rotation_angles(dev,
+ ioread32(&asle->srot));
- if (asle_req & ASLE_SET_PFIT)
- asle_stat |= asle_set_pfit(dev, ioread32(&asle->pfit));
+ if (aslc_req & ASLC_BUTTON_ARRAY)
+ aslc_stat |= asle_set_button_array(dev, ioread32(&asle->iuer));
- if (asle_req & ASLE_SET_PWM_FREQ)
- asle_stat |= asle_set_pwm_freq(dev, ioread32(&asle->pfmb));
+ if (aslc_req & ASLC_CONVERTIBLE_INDICATOR)
+ aslc_stat |= asle_set_convertible(dev, ioread32(&asle->iuer));
- iowrite32(asle_stat, &asle->aslc);
+ if (aslc_req & ASLC_DOCKING_INDICATOR)
+ aslc_stat |= asle_set_docking(dev, ioread32(&asle->iuer));
+
+ if (aslc_req & ASLC_ISCT_STATE_CHANGE)
+ aslc_stat |= asle_isct_state(dev);
+
+ iowrite32(aslc_stat, &asle->aslc);
}
#define ACPI_EV_DISPLAY_SWITCH (1<<0)
@@ -446,8 +746,68 @@ void intel_opregion_fini(struct drm_device *dev)
opregion->swsci = NULL;
opregion->asle = NULL;
opregion->vbt = NULL;
+ opregion->lid_state = NULL;
+}
+
+static void swsci_setup(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_opregion *opregion = &dev_priv->opregion;
+ bool requested_callbacks = false;
+ u32 tmp;
+
+ /* Sub-function code 0 is okay, let's allow them. */
+ opregion->swsci_gbda_sub_functions = 1;
+ opregion->swsci_sbcb_sub_functions = 1;
+
+ /* We use GBDA to ask for supported GBDA calls. */
+ if (swsci(dev, SWSCI_GBDA_SUPPORTED_CALLS, 0, &tmp) == 0) {
+ /* make the bits match the sub-function codes */
+ tmp <<= 1;
+ opregion->swsci_gbda_sub_functions |= tmp;
+ }
+
+ /*
+ * We also use GBDA to ask for _requested_ SBCB callbacks. The driver
+ * must not call interfaces that are not specifically requested by the
+ * bios.
+ */
+ if (swsci(dev, SWSCI_GBDA_REQUESTED_CALLBACKS, 0, &tmp) == 0) {
+ /* here, the bits already match sub-function codes */
+ opregion->swsci_sbcb_sub_functions |= tmp;
+ requested_callbacks = true;
+ }
+
+ /*
+ * But we use SBCB to ask for _supported_ SBCB calls. This does not mean
+ * the callback is _requested_. But we still can't call interfaces that
+ * are not requested.
+ */
+ if (swsci(dev, SWSCI_SBCB_SUPPORTED_CALLBACKS, 0, &tmp) == 0) {
+ /* make the bits match the sub-function codes */
+ u32 low = tmp & 0x7ff;
+ u32 high = tmp & ~0xfff; /* bit 11 is reserved */
+ tmp = (high << 4) | (low << 1) | 1;
+
+ /* best guess what to do with supported wrt requested */
+ if (requested_callbacks) {
+ u32 req = opregion->swsci_sbcb_sub_functions;
+ if ((req & tmp) != req)
+ DRM_DEBUG_DRIVER("SWSCI BIOS requested (%08x) SBCB callbacks that are not supported (%08x)\n", req, tmp);
+ /* XXX: for now, trust the requested callbacks */
+ /* opregion->swsci_sbcb_sub_functions &= tmp; */
+ } else {
+ opregion->swsci_sbcb_sub_functions |= tmp;
+ }
+ }
+
+ DRM_DEBUG_DRIVER("SWSCI GBDA callbacks %08x, SBCB callbacks %08x\n",
+ opregion->swsci_gbda_sub_functions,
+ opregion->swsci_sbcb_sub_functions);
}
-#endif
+#else /* CONFIG_ACPI */
+static inline void swsci_setup(struct drm_device *dev) {}
+#endif /* CONFIG_ACPI */
int intel_opregion_setup(struct drm_device *dev)
{
@@ -490,6 +850,7 @@ int intel_opregion_setup(struct drm_device *dev)
if (mboxes & MBOX_SWSCI) {
DRM_DEBUG_DRIVER("SWSCI supported\n");
opregion->swsci = base + OPREGION_SWSCI_OFFSET;
+ swsci_setup(dev);
}
if (mboxes & MBOX_ASLE) {
DRM_DEBUG_DRIVER("ASLE supported\n");
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index ddfd0aefe0c0..a98a990fbab3 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -821,14 +821,11 @@ int intel_overlay_switch_off(struct intel_overlay *overlay)
static int check_overlay_possible_on_crtc(struct intel_overlay *overlay,
struct intel_crtc *crtc)
{
- drm_i915_private_t *dev_priv = overlay->dev->dev_private;
-
if (!crtc->active)
return -EINVAL;
/* can't use the overlay with double wide pipe */
- if (INTEL_INFO(overlay->dev)->gen < 4 &&
- (I915_READ(PIPECONF(crtc->pipe)) & (PIPECONF_DOUBLE_WIDE | PIPECONF_ENABLE)) != PIPECONF_ENABLE)
+ if (crtc->config.double_wide)
return -EINVAL;
return 0;
@@ -1056,7 +1053,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
return ret;
}
- params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL);
+ params = kmalloc(sizeof(*params), GFP_KERNEL);
if (!params)
return -ENOMEM;
@@ -1323,7 +1320,7 @@ void intel_setup_overlay(struct drm_device *dev)
if (!HAS_OVERLAY(dev))
return;
- overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
+ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
if (!overlay)
return;
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 293564a2896a..54684168de1e 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -50,23 +50,22 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
struct intel_crtc_config *pipe_config,
int fitting_mode)
{
- struct drm_display_mode *mode, *adjusted_mode;
+ struct drm_display_mode *adjusted_mode;
int x, y, width, height;
- mode = &pipe_config->requested_mode;
adjusted_mode = &pipe_config->adjusted_mode;
x = y = width = height = 0;
/* Native modes don't need fitting */
- if (adjusted_mode->hdisplay == mode->hdisplay &&
- adjusted_mode->vdisplay == mode->vdisplay)
+ if (adjusted_mode->hdisplay == pipe_config->pipe_src_w &&
+ adjusted_mode->vdisplay == pipe_config->pipe_src_h)
goto done;
switch (fitting_mode) {
case DRM_MODE_SCALE_CENTER:
- width = mode->hdisplay;
- height = mode->vdisplay;
+ width = pipe_config->pipe_src_w;
+ height = pipe_config->pipe_src_h;
x = (adjusted_mode->hdisplay - width + 1)/2;
y = (adjusted_mode->vdisplay - height + 1)/2;
break;
@@ -74,17 +73,19 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
case DRM_MODE_SCALE_ASPECT:
/* Scale but preserve the aspect ratio */
{
- u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay;
- u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
+ u32 scaled_width = adjusted_mode->hdisplay
+ * pipe_config->pipe_src_h;
+ u32 scaled_height = pipe_config->pipe_src_w
+ * adjusted_mode->vdisplay;
if (scaled_width > scaled_height) { /* pillar */
- width = scaled_height / mode->vdisplay;
+ width = scaled_height / pipe_config->pipe_src_h;
if (width & 1)
width++;
x = (adjusted_mode->hdisplay - width + 1) / 2;
y = 0;
height = adjusted_mode->vdisplay;
} else if (scaled_width < scaled_height) { /* letter */
- height = scaled_width / mode->hdisplay;
+ height = scaled_width / pipe_config->pipe_src_w;
if (height & 1)
height++;
y = (adjusted_mode->vdisplay - height + 1) / 2;
@@ -171,20 +172,96 @@ static inline u32 panel_fitter_scaling(u32 source, u32 target)
return (FACTOR * ratio + FACTOR/2) / FACTOR;
}
+static void i965_scale_aspect(struct intel_crtc_config *pipe_config,
+ u32 *pfit_control)
+{
+ struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
+ u32 scaled_width = adjusted_mode->hdisplay *
+ pipe_config->pipe_src_h;
+ u32 scaled_height = pipe_config->pipe_src_w *
+ adjusted_mode->vdisplay;
+
+ /* 965+ is easy, it does everything in hw */
+ if (scaled_width > scaled_height)
+ *pfit_control |= PFIT_ENABLE |
+ PFIT_SCALING_PILLAR;
+ else if (scaled_width < scaled_height)
+ *pfit_control |= PFIT_ENABLE |
+ PFIT_SCALING_LETTER;
+ else if (adjusted_mode->hdisplay != pipe_config->pipe_src_w)
+ *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
+}
+
+static void i9xx_scale_aspect(struct intel_crtc_config *pipe_config,
+ u32 *pfit_control, u32 *pfit_pgm_ratios,
+ u32 *border)
+{
+ struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
+ u32 scaled_width = adjusted_mode->hdisplay *
+ pipe_config->pipe_src_h;
+ u32 scaled_height = pipe_config->pipe_src_w *
+ adjusted_mode->vdisplay;
+ u32 bits;
+
+ /*
+ * For earlier chips we have to calculate the scaling
+ * ratio by hand and program it into the
+ * PFIT_PGM_RATIO register
+ */
+ if (scaled_width > scaled_height) { /* pillar */
+ centre_horizontally(adjusted_mode,
+ scaled_height /
+ pipe_config->pipe_src_h);
+
+ *border = LVDS_BORDER_ENABLE;
+ if (pipe_config->pipe_src_h != adjusted_mode->vdisplay) {
+ bits = panel_fitter_scaling(pipe_config->pipe_src_h,
+ adjusted_mode->vdisplay);
+
+ *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
+ bits << PFIT_VERT_SCALE_SHIFT);
+ *pfit_control |= (PFIT_ENABLE |
+ VERT_INTERP_BILINEAR |
+ HORIZ_INTERP_BILINEAR);
+ }
+ } else if (scaled_width < scaled_height) { /* letter */
+ centre_vertically(adjusted_mode,
+ scaled_width /
+ pipe_config->pipe_src_w);
+
+ *border = LVDS_BORDER_ENABLE;
+ if (pipe_config->pipe_src_w != adjusted_mode->hdisplay) {
+ bits = panel_fitter_scaling(pipe_config->pipe_src_w,
+ adjusted_mode->hdisplay);
+
+ *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
+ bits << PFIT_VERT_SCALE_SHIFT);
+ *pfit_control |= (PFIT_ENABLE |
+ VERT_INTERP_BILINEAR |
+ HORIZ_INTERP_BILINEAR);
+ }
+ } else {
+ /* Aspects match, Let hw scale both directions */
+ *pfit_control |= (PFIT_ENABLE |
+ VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
+ VERT_INTERP_BILINEAR |
+ HORIZ_INTERP_BILINEAR);
+ }
+}
+
void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
struct intel_crtc_config *pipe_config,
int fitting_mode)
{
struct drm_device *dev = intel_crtc->base.dev;
u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
- struct drm_display_mode *mode, *adjusted_mode;
+ struct drm_display_mode *adjusted_mode;
- mode = &pipe_config->requested_mode;
adjusted_mode = &pipe_config->adjusted_mode;
/* Native modes don't need fitting */
- if (adjusted_mode->hdisplay == mode->hdisplay &&
- adjusted_mode->vdisplay == mode->vdisplay)
+ if (adjusted_mode->hdisplay == pipe_config->pipe_src_w &&
+ adjusted_mode->vdisplay == pipe_config->pipe_src_h)
goto out;
switch (fitting_mode) {
@@ -193,81 +270,25 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
* For centered modes, we have to calculate border widths &
* heights and modify the values programmed into the CRTC.
*/
- centre_horizontally(adjusted_mode, mode->hdisplay);
- centre_vertically(adjusted_mode, mode->vdisplay);
+ centre_horizontally(adjusted_mode, pipe_config->pipe_src_w);
+ centre_vertically(adjusted_mode, pipe_config->pipe_src_h);
border = LVDS_BORDER_ENABLE;
break;
case DRM_MODE_SCALE_ASPECT:
/* Scale but preserve the aspect ratio */
- if (INTEL_INFO(dev)->gen >= 4) {
- u32 scaled_width = adjusted_mode->hdisplay *
- mode->vdisplay;
- u32 scaled_height = mode->hdisplay *
- adjusted_mode->vdisplay;
-
- /* 965+ is easy, it does everything in hw */
- if (scaled_width > scaled_height)
- pfit_control |= PFIT_ENABLE |
- PFIT_SCALING_PILLAR;
- else if (scaled_width < scaled_height)
- pfit_control |= PFIT_ENABLE |
- PFIT_SCALING_LETTER;
- else if (adjusted_mode->hdisplay != mode->hdisplay)
- pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
- } else {
- u32 scaled_width = adjusted_mode->hdisplay *
- mode->vdisplay;
- u32 scaled_height = mode->hdisplay *
- adjusted_mode->vdisplay;
- /*
- * For earlier chips we have to calculate the scaling
- * ratio by hand and program it into the
- * PFIT_PGM_RATIO register
- */
- if (scaled_width > scaled_height) { /* pillar */
- centre_horizontally(adjusted_mode,
- scaled_height /
- mode->vdisplay);
-
- border = LVDS_BORDER_ENABLE;
- if (mode->vdisplay != adjusted_mode->vdisplay) {
- u32 bits = panel_fitter_scaling(mode->vdisplay, adjusted_mode->vdisplay);
- pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
- bits << PFIT_VERT_SCALE_SHIFT);
- pfit_control |= (PFIT_ENABLE |
- VERT_INTERP_BILINEAR |
- HORIZ_INTERP_BILINEAR);
- }
- } else if (scaled_width < scaled_height) { /* letter */
- centre_vertically(adjusted_mode,
- scaled_width /
- mode->hdisplay);
-
- border = LVDS_BORDER_ENABLE;
- if (mode->hdisplay != adjusted_mode->hdisplay) {
- u32 bits = panel_fitter_scaling(mode->hdisplay, adjusted_mode->hdisplay);
- pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
- bits << PFIT_VERT_SCALE_SHIFT);
- pfit_control |= (PFIT_ENABLE |
- VERT_INTERP_BILINEAR |
- HORIZ_INTERP_BILINEAR);
- }
- } else {
- /* Aspects match, Let hw scale both directions */
- pfit_control |= (PFIT_ENABLE |
- VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
- VERT_INTERP_BILINEAR |
- HORIZ_INTERP_BILINEAR);
- }
- }
+ if (INTEL_INFO(dev)->gen >= 4)
+ i965_scale_aspect(pipe_config, &pfit_control);
+ else
+ i9xx_scale_aspect(pipe_config, &pfit_control,
+ &pfit_pgm_ratios, &border);
break;
case DRM_MODE_SCALE_FULLSCREEN:
/*
* Full scaling, even if it changes the aspect ratio.
* Fortunately this is all done for us in hw.
*/
- if (mode->vdisplay != adjusted_mode->vdisplay ||
- mode->hdisplay != adjusted_mode->hdisplay) {
+ if (pipe_config->pipe_src_h != adjusted_mode->vdisplay ||
+ pipe_config->pipe_src_w != adjusted_mode->hdisplay) {
pfit_control |= PFIT_ENABLE;
if (INTEL_INFO(dev)->gen >= 4)
pfit_control |= PFIT_SCALING_AUTO;
@@ -308,7 +329,7 @@ static int is_backlight_combination_mode(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- if (INTEL_INFO(dev)->gen >= 4)
+ if (IS_GEN4(dev))
return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE;
if (IS_GEN2(dev))
@@ -351,6 +372,9 @@ static u32 i915_read_blc_pwm_ctl(struct drm_device *dev)
I915_WRITE(BLC_PWM_CTL2,
dev_priv->regfile.saveBLC_PWM_CTL2);
}
+
+ if (IS_VALLEYVIEW(dev) && !val)
+ val = 0x0f42ffff;
}
return val;
@@ -441,7 +465,8 @@ static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level)
I915_WRITE(BLC_PWM_CPU_CTL, val | level);
}
-static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level)
+static void intel_panel_actually_set_backlight(struct drm_device *dev,
+ u32 level)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 tmp;
@@ -607,10 +632,24 @@ set_level:
spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
}
+/* FIXME: use VBT vals to init PWM_CTL and PWM_CTL2 correctly */
+static void intel_panel_init_backlight_regs(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ if (IS_VALLEYVIEW(dev)) {
+ u32 cur_val = I915_READ(BLC_PWM_CTL) &
+ BACKLIGHT_DUTY_CYCLE_MASK;
+ I915_WRITE(BLC_PWM_CTL, (0xf42 << 16) | cur_val);
+ }
+}
+
static void intel_panel_init_backlight(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ intel_panel_init_backlight_regs(dev);
+
dev_priv->backlight.level = intel_panel_get_backlight(dev);
dev_priv->backlight.enabled = dev_priv->backlight.level != 0;
}
@@ -637,7 +676,7 @@ intel_panel_detect(struct drm_device *dev)
}
}
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
static int intel_panel_update_status(struct backlight_device *bd)
{
struct drm_device *dev = bl_get_data(bd);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index dd176b7296c1..2ac1c2fd58bb 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -43,14 +43,6 @@
* i915.i915_enable_fbc parameter
*/
-static bool intel_crtc_active(struct drm_crtc *crtc)
-{
- /* Be paranoid as we can arrive here with only partial
- * state retrieved from the hardware during setup.
- */
- return to_intel_crtc(crtc)->active && crtc->fb && crtc->mode.clock;
-}
-
static void i8xx_disable_fbc(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -378,7 +370,7 @@ static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
intel_cancel_fbc_work(dev_priv);
- work = kzalloc(sizeof *work, GFP_KERNEL);
+ work = kzalloc(sizeof(*work), GFP_KERNEL);
if (work == NULL) {
DRM_ERROR("Failed to allocate FBC work structure\n");
dev_priv->display.enable_fbc(crtc, interval);
@@ -458,7 +450,8 @@ void intel_update_fbc(struct drm_device *dev)
struct drm_framebuffer *fb;
struct intel_framebuffer *intel_fb;
struct drm_i915_gem_object *obj;
- unsigned int max_hdisplay, max_vdisplay;
+ const struct drm_display_mode *adjusted_mode;
+ unsigned int max_width, max_height;
if (!I915_HAS_FBC(dev)) {
set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED);
@@ -502,6 +495,7 @@ void intel_update_fbc(struct drm_device *dev)
fb = crtc->fb;
intel_fb = to_intel_framebuffer(fb);
obj = intel_fb->obj;
+ adjusted_mode = &intel_crtc->config.adjusted_mode;
if (i915_enable_fbc < 0 &&
INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev)) {
@@ -514,8 +508,8 @@ void intel_update_fbc(struct drm_device *dev)
DRM_DEBUG_KMS("fbc disabled per module param\n");
goto out_disable;
}
- if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) ||
- (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) {
+ if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ||
+ (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) {
if (set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED_MODE))
DRM_DEBUG_KMS("mode incompatible with compression, "
"disabling\n");
@@ -523,14 +517,14 @@ void intel_update_fbc(struct drm_device *dev)
}
if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) {
- max_hdisplay = 4096;
- max_vdisplay = 2048;
+ max_width = 4096;
+ max_height = 2048;
} else {
- max_hdisplay = 2048;
- max_vdisplay = 1536;
+ max_width = 2048;
+ max_height = 1536;
}
- if ((crtc->mode.hdisplay > max_hdisplay) ||
- (crtc->mode.vdisplay > max_vdisplay)) {
+ if (intel_crtc->config.pipe_src_w > max_width ||
+ intel_crtc->config.pipe_src_h > max_height) {
if (set_no_fbc_reason(dev_priv, FBC_MODE_TOO_LARGE))
DRM_DEBUG_KMS("mode too large for compression, disabling\n");
goto out_disable;
@@ -1087,8 +1081,9 @@ static struct drm_crtc *single_enabled_crtc(struct drm_device *dev)
return enabled;
}
-static void pineview_update_wm(struct drm_device *dev)
+static void pineview_update_wm(struct drm_crtc *unused_crtc)
{
+ struct drm_device *dev = unused_crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc;
const struct cxsr_latency *latency;
@@ -1105,8 +1100,12 @@ static void pineview_update_wm(struct drm_device *dev)
crtc = single_enabled_crtc(dev);
if (crtc) {
- int clock = crtc->mode.clock;
+ const struct drm_display_mode *adjusted_mode;
int pixel_size = crtc->fb->bits_per_pixel / 8;
+ int clock;
+
+ adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
+ clock = adjusted_mode->crtc_clock;
/* Display SR */
wm = intel_calculate_wm(clock, &pineview_display_wm,
@@ -1166,6 +1165,7 @@ static bool g4x_compute_wm0(struct drm_device *dev,
int *cursor_wm)
{
struct drm_crtc *crtc;
+ const struct drm_display_mode *adjusted_mode;
int htotal, hdisplay, clock, pixel_size;
int line_time_us, line_count;
int entries, tlb_miss;
@@ -1177,9 +1177,10 @@ static bool g4x_compute_wm0(struct drm_device *dev,
return false;
}
- htotal = crtc->mode.htotal;
- hdisplay = crtc->mode.hdisplay;
- clock = crtc->mode.clock;
+ adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
+ clock = adjusted_mode->crtc_clock;
+ htotal = adjusted_mode->htotal;
+ hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
pixel_size = crtc->fb->bits_per_pixel / 8;
/* Use the small buffer method to calculate plane watermark */
@@ -1250,6 +1251,7 @@ static bool g4x_compute_srwm(struct drm_device *dev,
int *display_wm, int *cursor_wm)
{
struct drm_crtc *crtc;
+ const struct drm_display_mode *adjusted_mode;
int hdisplay, htotal, pixel_size, clock;
unsigned long line_time_us;
int line_count, line_size;
@@ -1262,9 +1264,10 @@ static bool g4x_compute_srwm(struct drm_device *dev,
}
crtc = intel_get_crtc_for_plane(dev, plane);
- hdisplay = crtc->mode.hdisplay;
- htotal = crtc->mode.htotal;
- clock = crtc->mode.clock;
+ adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
+ clock = adjusted_mode->crtc_clock;
+ htotal = adjusted_mode->htotal;
+ hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
pixel_size = crtc->fb->bits_per_pixel / 8;
line_time_us = (htotal * 1000) / clock;
@@ -1303,7 +1306,7 @@ static bool vlv_compute_drain_latency(struct drm_device *dev,
if (!intel_crtc_active(crtc))
return false;
- clock = crtc->mode.clock; /* VESA DOT Clock */
+ clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
pixel_size = crtc->fb->bits_per_pixel / 8; /* BPP */
entries = (clock / 1000) * pixel_size;
@@ -1365,8 +1368,9 @@ static void vlv_update_drain_latency(struct drm_device *dev)
#define single_plane_enabled(mask) is_power_of_2(mask)
-static void valleyview_update_wm(struct drm_device *dev)
+static void valleyview_update_wm(struct drm_crtc *crtc)
{
+ struct drm_device *dev = crtc->dev;
static const int sr_latency_ns = 12000;
struct drm_i915_private *dev_priv = dev->dev_private;
int planea_wm, planeb_wm, cursora_wm, cursorb_wm;
@@ -1424,8 +1428,9 @@ static void valleyview_update_wm(struct drm_device *dev)
(cursor_sr << DSPFW_CURSOR_SR_SHIFT));
}
-static void g4x_update_wm(struct drm_device *dev)
+static void g4x_update_wm(struct drm_crtc *crtc)
{
+ struct drm_device *dev = crtc->dev;
static const int sr_latency_ns = 12000;
struct drm_i915_private *dev_priv = dev->dev_private;
int planea_wm, planeb_wm, cursora_wm, cursorb_wm;
@@ -1476,8 +1481,9 @@ static void g4x_update_wm(struct drm_device *dev)
(cursor_sr << DSPFW_CURSOR_SR_SHIFT));
}
-static void i965_update_wm(struct drm_device *dev)
+static void i965_update_wm(struct drm_crtc *unused_crtc)
{
+ struct drm_device *dev = unused_crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc;
int srwm = 1;
@@ -1488,9 +1494,11 @@ static void i965_update_wm(struct drm_device *dev)
if (crtc) {
/* self-refresh has much higher latency */
static const int sr_latency_ns = 12000;
- int clock = crtc->mode.clock;
- int htotal = crtc->mode.htotal;
- int hdisplay = crtc->mode.hdisplay;
+ const struct drm_display_mode *adjusted_mode =
+ &to_intel_crtc(crtc)->config.adjusted_mode;
+ int clock = adjusted_mode->crtc_clock;
+ int htotal = adjusted_mode->htotal;
+ int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
int pixel_size = crtc->fb->bits_per_pixel / 8;
unsigned long line_time_us;
int entries;
@@ -1541,8 +1549,9 @@ static void i965_update_wm(struct drm_device *dev)
I915_WRITE(DSPFW3, (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
}
-static void i9xx_update_wm(struct drm_device *dev)
+static void i9xx_update_wm(struct drm_crtc *unused_crtc)
{
+ struct drm_device *dev = unused_crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
const struct intel_watermark_params *wm_info;
uint32_t fwater_lo;
@@ -1562,11 +1571,13 @@ static void i9xx_update_wm(struct drm_device *dev)
fifo_size = dev_priv->display.get_fifo_size(dev, 0);
crtc = intel_get_crtc_for_plane(dev, 0);
if (intel_crtc_active(crtc)) {
+ const struct drm_display_mode *adjusted_mode;
int cpp = crtc->fb->bits_per_pixel / 8;
if (IS_GEN2(dev))
cpp = 4;
- planea_wm = intel_calculate_wm(crtc->mode.clock,
+ adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
+ planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock,
wm_info, fifo_size, cpp,
latency_ns);
enabled = crtc;
@@ -1576,11 +1587,13 @@ static void i9xx_update_wm(struct drm_device *dev)
fifo_size = dev_priv->display.get_fifo_size(dev, 1);
crtc = intel_get_crtc_for_plane(dev, 1);
if (intel_crtc_active(crtc)) {
+ const struct drm_display_mode *adjusted_mode;
int cpp = crtc->fb->bits_per_pixel / 8;
if (IS_GEN2(dev))
cpp = 4;
- planeb_wm = intel_calculate_wm(crtc->mode.clock,
+ adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
+ planeb_wm = intel_calculate_wm(adjusted_mode->crtc_clock,
wm_info, fifo_size, cpp,
latency_ns);
if (enabled == NULL)
@@ -1607,9 +1620,11 @@ static void i9xx_update_wm(struct drm_device *dev)
if (HAS_FW_BLC(dev) && enabled) {
/* self-refresh has much higher latency */
static const int sr_latency_ns = 6000;
- int clock = enabled->mode.clock;
- int htotal = enabled->mode.htotal;
- int hdisplay = enabled->mode.hdisplay;
+ const struct drm_display_mode *adjusted_mode =
+ &to_intel_crtc(enabled)->config.adjusted_mode;
+ int clock = adjusted_mode->crtc_clock;
+ int htotal = adjusted_mode->htotal;
+ int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
int pixel_size = enabled->fb->bits_per_pixel / 8;
unsigned long line_time_us;
int entries;
@@ -1658,10 +1673,12 @@ static void i9xx_update_wm(struct drm_device *dev)
}
}
-static void i830_update_wm(struct drm_device *dev)
+static void i830_update_wm(struct drm_crtc *unused_crtc)
{
+ struct drm_device *dev = unused_crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc;
+ const struct drm_display_mode *adjusted_mode;
uint32_t fwater_lo;
int planea_wm;
@@ -1669,7 +1686,9 @@ static void i830_update_wm(struct drm_device *dev)
if (crtc == NULL)
return;
- planea_wm = intel_calculate_wm(crtc->mode.clock, &i830_wm_info,
+ adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
+ planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock,
+ &i830_wm_info,
dev_priv->display.get_fifo_size(dev, 0),
4, latency_ns);
fwater_lo = I915_READ(FW_BLC) & ~0xfff;
@@ -1741,6 +1760,7 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane,
int *fbc_wm, int *display_wm, int *cursor_wm)
{
struct drm_crtc *crtc;
+ const struct drm_display_mode *adjusted_mode;
unsigned long line_time_us;
int hdisplay, htotal, pixel_size, clock;
int line_count, line_size;
@@ -1753,9 +1773,10 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane,
}
crtc = intel_get_crtc_for_plane(dev, plane);
- hdisplay = crtc->mode.hdisplay;
- htotal = crtc->mode.htotal;
- clock = crtc->mode.clock;
+ adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode;
+ clock = adjusted_mode->crtc_clock;
+ htotal = adjusted_mode->htotal;
+ hdisplay = to_intel_crtc(crtc)->config.pipe_src_w;
pixel_size = crtc->fb->bits_per_pixel / 8;
line_time_us = (htotal * 1000) / clock;
@@ -1785,8 +1806,9 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane,
display, cursor);
}
-static void ironlake_update_wm(struct drm_device *dev)
+static void ironlake_update_wm(struct drm_crtc *crtc)
{
+ struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int fbc_wm, plane_wm, cursor_wm;
unsigned int enabled;
@@ -1868,8 +1890,9 @@ static void ironlake_update_wm(struct drm_device *dev)
*/
}
-static void sandybridge_update_wm(struct drm_device *dev)
+static void sandybridge_update_wm(struct drm_crtc *crtc)
{
+ struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int latency = dev_priv->wm.pri_latency[0] * 100; /* In unit 0.1us */
u32 val;
@@ -1970,8 +1993,9 @@ static void sandybridge_update_wm(struct drm_device *dev)
cursor_wm);
}
-static void ivybridge_update_wm(struct drm_device *dev)
+static void ivybridge_update_wm(struct drm_crtc *crtc)
{
+ struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
int latency = dev_priv->wm.pri_latency[0] * 100; /* In unit 0.1us */
u32 val;
@@ -2098,7 +2122,7 @@ static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev,
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
uint32_t pixel_rate;
- pixel_rate = intel_crtc->config.adjusted_mode.clock;
+ pixel_rate = intel_crtc->config.adjusted_mode.crtc_clock;
/* We only use IF-ID interlacing. If we ever use PF-ID we'll need to
* adjust the pixel_rate here. */
@@ -2107,8 +2131,8 @@ static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev,
uint64_t pipe_w, pipe_h, pfit_w, pfit_h;
uint32_t pfit_size = intel_crtc->config.pch_pfit.size;
- pipe_w = intel_crtc->config.requested_mode.hdisplay;
- pipe_h = intel_crtc->config.requested_mode.vdisplay;
+ pipe_w = intel_crtc->config.pipe_src_w;
+ pipe_h = intel_crtc->config.pipe_src_h;
pfit_w = (pfit_size >> 16) & 0xFFFF;
pfit_h = pfit_size & 0xFFFF;
if (pipe_w < pfit_w)
@@ -2196,7 +2220,7 @@ struct intel_wm_config {
* For both WM_PIPE and WM_LP.
* mem_value must be in 0.1us units.
*/
-static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
+static uint32_t ilk_compute_pri_wm(const struct hsw_pipe_wm_parameters *params,
uint32_t mem_value,
bool is_lp)
{
@@ -2225,7 +2249,7 @@ static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params,
* For both WM_PIPE and WM_LP.
* mem_value must be in 0.1us units.
*/
-static uint32_t ilk_compute_spr_wm(struct hsw_pipe_wm_parameters *params,
+static uint32_t ilk_compute_spr_wm(const struct hsw_pipe_wm_parameters *params,
uint32_t mem_value)
{
uint32_t method1, method2;
@@ -2248,7 +2272,7 @@ static uint32_t ilk_compute_spr_wm(struct hsw_pipe_wm_parameters *params,
* For both WM_PIPE and WM_LP.
* mem_value must be in 0.1us units.
*/
-static uint32_t ilk_compute_cur_wm(struct hsw_pipe_wm_parameters *params,
+static uint32_t ilk_compute_cur_wm(const struct hsw_pipe_wm_parameters *params,
uint32_t mem_value)
{
if (!params->active || !params->cur.enabled)
@@ -2262,7 +2286,7 @@ static uint32_t ilk_compute_cur_wm(struct hsw_pipe_wm_parameters *params,
}
/* Only for WM_LP. */
-static uint32_t ilk_compute_fbc_wm(struct hsw_pipe_wm_parameters *params,
+static uint32_t ilk_compute_fbc_wm(const struct hsw_pipe_wm_parameters *params,
uint32_t pri_val)
{
if (!params->active || !params->pri.enabled)
@@ -2413,7 +2437,7 @@ static bool ilk_check_wm(int level,
static void ilk_compute_wm_level(struct drm_i915_private *dev_priv,
int level,
- struct hsw_pipe_wm_parameters *p,
+ const struct hsw_pipe_wm_parameters *p,
struct intel_wm_level *result)
{
uint16_t pri_latency = dev_priv->wm.pri_latency[level];
@@ -2435,8 +2459,8 @@ static void ilk_compute_wm_level(struct drm_i915_private *dev_priv,
}
static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv,
- int level, struct hsw_wm_maximums *max,
- struct hsw_pipe_wm_parameters *params,
+ int level, const struct hsw_wm_maximums *max,
+ const struct hsw_pipe_wm_parameters *params,
struct intel_wm_level *result)
{
enum pipe pipe;
@@ -2454,33 +2478,31 @@ static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv,
return ilk_check_wm(level, max, result);
}
-static uint32_t hsw_compute_wm_pipe(struct drm_i915_private *dev_priv,
- enum pipe pipe,
- struct hsw_pipe_wm_parameters *params)
+
+static uint32_t hsw_compute_wm_pipe(struct drm_device *dev,
+ const struct hsw_pipe_wm_parameters *params)
{
- uint32_t pri_val, cur_val, spr_val;
- /* WM0 latency values stored in 0.1us units */
- uint16_t pri_latency = dev_priv->wm.pri_latency[0];
- uint16_t spr_latency = dev_priv->wm.spr_latency[0];
- uint16_t cur_latency = dev_priv->wm.cur_latency[0];
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_wm_config config = {
+ .num_pipes_active = 1,
+ .sprites_enabled = params->spr.enabled,
+ .sprites_scaled = params->spr.scaled,
+ };
+ struct hsw_wm_maximums max;
+ struct intel_wm_level res;
- pri_val = ilk_compute_pri_wm(params, pri_latency, false);
- spr_val = ilk_compute_spr_wm(params, spr_latency);
- cur_val = ilk_compute_cur_wm(params, cur_latency);
+ if (!params->active)
+ return 0;
- WARN(pri_val > 127,
- "Primary WM error, mode not supported for pipe %c\n",
- pipe_name(pipe));
- WARN(spr_val > 127,
- "Sprite WM error, mode not supported for pipe %c\n",
- pipe_name(pipe));
- WARN(cur_val > 63,
- "Cursor WM error, mode not supported for pipe %c\n",
- pipe_name(pipe));
+ ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
- return (pri_val << WM0_PIPE_PLANE_SHIFT) |
- (spr_val << WM0_PIPE_SPRITE_SHIFT) |
- cur_val;
+ ilk_compute_wm_level(dev_priv, 0, params, &res);
+
+ ilk_check_wm(0, &max, &res);
+
+ return (res.pri_val << WM0_PIPE_PLANE_SHIFT) |
+ (res.spr_val << WM0_PIPE_SPRITE_SHIFT) |
+ res.cur_val;
}
static uint32_t
@@ -2554,19 +2576,22 @@ static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5])
wm[3] *= 2;
}
-static void intel_print_wm_latency(struct drm_device *dev,
- const char *name,
- const uint16_t wm[5])
+static int ilk_wm_max_level(const struct drm_device *dev)
{
- int level, max_level;
-
/* how many WM levels are we expecting */
if (IS_HASWELL(dev))
- max_level = 4;
+ return 4;
else if (INTEL_INFO(dev)->gen >= 6)
- max_level = 3;
+ return 3;
else
- max_level = 2;
+ return 2;
+}
+
+static void intel_print_wm_latency(struct drm_device *dev,
+ const char *name,
+ const uint16_t wm[5])
+{
+ int level, max_level = ilk_wm_max_level(dev);
for (level = 0; level <= max_level; level++) {
unsigned int latency = wm[level];
@@ -2633,8 +2658,7 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc);
p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8;
p->cur.bytes_per_pixel = 4;
- p->pri.horiz_pixels =
- intel_crtc->config.requested_mode.hdisplay;
+ p->pri.horiz_pixels = intel_crtc->config.pipe_src_w;
p->cur.horiz_pixels = 64;
/* TODO: for now, assume primary and cursor planes are always enabled. */
p->pri.enabled = true;
@@ -2664,8 +2688,8 @@ static void hsw_compute_wm_parameters(struct drm_device *dev,
}
static void hsw_compute_wm_results(struct drm_device *dev,
- struct hsw_pipe_wm_parameters *params,
- struct hsw_wm_maximums *lp_maximums,
+ const struct hsw_pipe_wm_parameters *params,
+ const struct hsw_wm_maximums *lp_maximums,
struct hsw_wm_values *results)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2709,7 +2733,7 @@ static void hsw_compute_wm_results(struct drm_device *dev,
}
for_each_pipe(pipe)
- results->wm_pipe[pipe] = hsw_compute_wm_pipe(dev_priv, pipe,
+ results->wm_pipe[pipe] = hsw_compute_wm_pipe(dev,
&params[pipe]);
for_each_pipe(pipe) {
@@ -2841,8 +2865,9 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
}
-static void haswell_update_wm(struct drm_device *dev)
+static void haswell_update_wm(struct drm_crtc *crtc)
{
+ struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct hsw_wm_maximums lp_max_1_2, lp_max_5_6;
struct hsw_pipe_wm_parameters params[3];
@@ -2879,7 +2904,7 @@ static void haswell_update_sprite_wm(struct drm_plane *plane,
intel_plane->wm.horiz_pixels = sprite_width;
intel_plane->wm.bytes_per_pixel = pixel_size;
- haswell_update_wm(plane->dev);
+ haswell_update_wm(crtc);
}
static bool
@@ -2898,7 +2923,7 @@ sandybridge_compute_sprite_wm(struct drm_device *dev, int plane,
return false;
}
- clock = crtc->mode.clock;
+ clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
/* Use the small buffer method to calculate the sprite watermark */
entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
@@ -2933,7 +2958,7 @@ sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane,
}
crtc = intel_get_crtc_for_plane(dev, plane);
- clock = crtc->mode.clock;
+ clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock;
if (!clock) {
*sprite_wm = 0;
return false;
@@ -3076,12 +3101,12 @@ static void sandybridge_update_sprite_wm(struct drm_plane *plane,
* We don't use the sprite, so we can ignore that. And on Crestline we have
* to set the non-SR watermarks to 8.
*/
-void intel_update_watermarks(struct drm_device *dev)
+void intel_update_watermarks(struct drm_crtc *crtc)
{
- struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_private *dev_priv = crtc->dev->dev_private;
if (dev_priv->display.update_wm)
- dev_priv->display.update_wm(dev);
+ dev_priv->display.update_wm(crtc);
}
void intel_update_sprite_watermarks(struct drm_plane *plane,
@@ -3773,7 +3798,7 @@ static void valleyview_enable_rps(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_ring_buffer *ring;
- u32 gtfifodbg, val;
+ u32 gtfifodbg, val, rc6_mode = 0;
int i;
WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
@@ -3813,8 +3838,9 @@ static void valleyview_enable_rps(struct drm_device *dev)
/* allows RC6 residency counter to work */
I915_WRITE(0x138104, _MASKED_BIT_ENABLE(0x3));
- I915_WRITE(GEN6_RC_CONTROL,
- GEN7_RC_CTL_TO_MODE);
+ if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
+ rc6_mode = GEN7_RC_CTL_TO_MODE;
+ I915_WRITE(GEN6_RC_CONTROL, rc6_mode);
val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
switch ((val >> 6) & 3) {
@@ -5267,6 +5293,7 @@ bool intel_display_power_enabled(struct drm_device *dev,
case POWER_DOMAIN_PIPE_A:
case POWER_DOMAIN_TRANSCODER_EDP:
return true;
+ case POWER_DOMAIN_VGA:
case POWER_DOMAIN_PIPE_B:
case POWER_DOMAIN_PIPE_C:
case POWER_DOMAIN_PIPE_A_PANEL_FITTER:
@@ -5329,6 +5356,81 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable)
}
}
+static void __intel_power_well_get(struct i915_power_well *power_well)
+{
+ if (!power_well->count++)
+ __intel_set_power_well(power_well->device, true);
+}
+
+static void __intel_power_well_put(struct i915_power_well *power_well)
+{
+ WARN_ON(!power_well->count);
+ if (!--power_well->count)
+ __intel_set_power_well(power_well->device, false);
+}
+
+void intel_display_power_get(struct drm_device *dev,
+ enum intel_display_power_domain domain)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct i915_power_well *power_well = &dev_priv->power_well;
+
+ if (!HAS_POWER_WELL(dev))
+ return;
+
+ switch (domain) {
+ case POWER_DOMAIN_PIPE_A:
+ case POWER_DOMAIN_TRANSCODER_EDP:
+ return;
+ case POWER_DOMAIN_VGA:
+ case POWER_DOMAIN_PIPE_B:
+ case POWER_DOMAIN_PIPE_C:
+ case POWER_DOMAIN_PIPE_A_PANEL_FITTER:
+ case POWER_DOMAIN_PIPE_B_PANEL_FITTER:
+ case POWER_DOMAIN_PIPE_C_PANEL_FITTER:
+ case POWER_DOMAIN_TRANSCODER_A:
+ case POWER_DOMAIN_TRANSCODER_B:
+ case POWER_DOMAIN_TRANSCODER_C:
+ spin_lock_irq(&power_well->lock);
+ __intel_power_well_get(power_well);
+ spin_unlock_irq(&power_well->lock);
+ return;
+ default:
+ BUG();
+ }
+}
+
+void intel_display_power_put(struct drm_device *dev,
+ enum intel_display_power_domain domain)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct i915_power_well *power_well = &dev_priv->power_well;
+
+ if (!HAS_POWER_WELL(dev))
+ return;
+
+ switch (domain) {
+ case POWER_DOMAIN_PIPE_A:
+ case POWER_DOMAIN_TRANSCODER_EDP:
+ return;
+ case POWER_DOMAIN_VGA:
+ case POWER_DOMAIN_PIPE_B:
+ case POWER_DOMAIN_PIPE_C:
+ case POWER_DOMAIN_PIPE_A_PANEL_FITTER:
+ case POWER_DOMAIN_PIPE_B_PANEL_FITTER:
+ case POWER_DOMAIN_PIPE_C_PANEL_FITTER:
+ case POWER_DOMAIN_TRANSCODER_A:
+ case POWER_DOMAIN_TRANSCODER_B:
+ case POWER_DOMAIN_TRANSCODER_C:
+ spin_lock_irq(&power_well->lock);
+ __intel_power_well_put(power_well);
+ spin_unlock_irq(&power_well->lock);
+ return;
+ default:
+ BUG();
+ }
+}
+
static struct i915_power_well *hsw_pwr;
/* Display audio driver power well request */
@@ -5338,9 +5440,7 @@ void i915_request_power_well(void)
return;
spin_lock_irq(&hsw_pwr->lock);
- if (!hsw_pwr->count++ &&
- !hsw_pwr->i915_request)
- __intel_set_power_well(hsw_pwr->device, true);
+ __intel_power_well_get(hsw_pwr);
spin_unlock_irq(&hsw_pwr->lock);
}
EXPORT_SYMBOL_GPL(i915_request_power_well);
@@ -5352,10 +5452,7 @@ void i915_release_power_well(void)
return;
spin_lock_irq(&hsw_pwr->lock);
- WARN_ON(!hsw_pwr->count);
- if (!--hsw_pwr->count &&
- !hsw_pwr->i915_request)
- __intel_set_power_well(hsw_pwr->device, false);
+ __intel_power_well_put(hsw_pwr);
spin_unlock_irq(&hsw_pwr->lock);
}
EXPORT_SYMBOL_GPL(i915_release_power_well);
@@ -5390,15 +5487,37 @@ void intel_set_power_well(struct drm_device *dev, bool enable)
return;
spin_lock_irq(&power_well->lock);
+
+ /*
+ * This function will only ever contribute one
+ * to the power well reference count. i915_request
+ * is what tracks whether we have or have not
+ * added the one to the reference count.
+ */
+ if (power_well->i915_request == enable)
+ goto out;
+
power_well->i915_request = enable;
- /* only reject "disable" power well request */
- if (power_well->count && !enable) {
- spin_unlock_irq(&power_well->lock);
+ if (enable)
+ __intel_power_well_get(power_well);
+ else
+ __intel_power_well_put(power_well);
+
+ out:
+ spin_unlock_irq(&power_well->lock);
+}
+
+void intel_resume_power_well(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct i915_power_well *power_well = &dev_priv->power_well;
+
+ if (!HAS_POWER_WELL(dev))
return;
- }
- __intel_set_power_well(dev, enable);
+ spin_lock_irq(&power_well->lock);
+ __intel_set_power_well(dev, power_well->count > 0);
spin_unlock_irq(&power_well->lock);
}
@@ -5417,6 +5536,7 @@ void intel_init_power_well(struct drm_device *dev)
/* For now, we need the power well to be always enabled. */
intel_set_power_well(dev, true);
+ intel_resume_power_well(dev);
/* We're taking over the BIOS, so clear any requests made by it since
* the driver is in charge now. */
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 460ee1026fca..b67104aaade5 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -41,6 +41,16 @@ static inline int ring_space(struct intel_ring_buffer *ring)
return space;
}
+void __intel_ring_advance(struct intel_ring_buffer *ring)
+{
+ struct drm_i915_private *dev_priv = ring->dev->dev_private;
+
+ ring->tail &= ring->size - 1;
+ if (dev_priv->gpu_error.stop_rings & intel_ring_flag(ring))
+ return;
+ ring->write_tail(ring, ring->tail);
+}
+
static int
gen2_render_ring_flush(struct intel_ring_buffer *ring,
u32 invalidate_domains,
@@ -559,8 +569,8 @@ static int init_render_ring(struct intel_ring_buffer *ring)
if (INTEL_INFO(dev)->gen >= 6)
I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
- if (HAS_L3_GPU_CACHE(dev))
- I915_WRITE_IMR(ring, ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT);
+ if (HAS_L3_DPF(dev))
+ I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev));
return ret;
}
@@ -593,7 +603,7 @@ update_mboxes(struct intel_ring_buffer *ring,
#define MBOX_UPDATE_DWORDS 4
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
intel_ring_emit(ring, mmio_offset);
- intel_ring_emit(ring, ring->outstanding_lazy_request);
+ intel_ring_emit(ring, ring->outstanding_lazy_seqno);
intel_ring_emit(ring, MI_NOOP);
}
@@ -629,9 +639,9 @@ gen6_add_request(struct intel_ring_buffer *ring)
intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
- intel_ring_emit(ring, ring->outstanding_lazy_request);
+ intel_ring_emit(ring, ring->outstanding_lazy_seqno);
intel_ring_emit(ring, MI_USER_INTERRUPT);
- intel_ring_advance(ring);
+ __intel_ring_advance(ring);
return 0;
}
@@ -723,7 +733,7 @@ pc_render_add_request(struct intel_ring_buffer *ring)
PIPE_CONTROL_WRITE_FLUSH |
PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE);
intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
- intel_ring_emit(ring, ring->outstanding_lazy_request);
+ intel_ring_emit(ring, ring->outstanding_lazy_seqno);
intel_ring_emit(ring, 0);
PIPE_CONTROL_FLUSH(ring, scratch_addr);
scratch_addr += 128; /* write to separate cachelines */
@@ -742,9 +752,9 @@ pc_render_add_request(struct intel_ring_buffer *ring)
PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
PIPE_CONTROL_NOTIFY);
intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
- intel_ring_emit(ring, ring->outstanding_lazy_request);
+ intel_ring_emit(ring, ring->outstanding_lazy_seqno);
intel_ring_emit(ring, 0);
- intel_ring_advance(ring);
+ __intel_ring_advance(ring);
return 0;
}
@@ -963,9 +973,9 @@ i9xx_add_request(struct intel_ring_buffer *ring)
intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
- intel_ring_emit(ring, ring->outstanding_lazy_request);
+ intel_ring_emit(ring, ring->outstanding_lazy_seqno);
intel_ring_emit(ring, MI_USER_INTERRUPT);
- intel_ring_advance(ring);
+ __intel_ring_advance(ring);
return 0;
}
@@ -987,10 +997,10 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring)
spin_lock_irqsave(&dev_priv->irq_lock, flags);
if (ring->irq_refcount++ == 0) {
- if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS)
+ if (HAS_L3_DPF(dev) && ring->id == RCS)
I915_WRITE_IMR(ring,
~(ring->irq_enable_mask |
- GT_RENDER_L3_PARITY_ERROR_INTERRUPT));
+ GT_PARITY_ERROR(dev)));
else
I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
ilk_enable_gt_irq(dev_priv, ring->irq_enable_mask);
@@ -1009,9 +1019,8 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring)
spin_lock_irqsave(&dev_priv->irq_lock, flags);
if (--ring->irq_refcount == 0) {
- if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS)
- I915_WRITE_IMR(ring,
- ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT);
+ if (HAS_L3_DPF(dev) && ring->id == RCS)
+ I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev));
else
I915_WRITE_IMR(ring, ~0);
ilk_disable_gt_irq(dev_priv, ring->irq_enable_mask);
@@ -1414,6 +1423,9 @@ static int ring_wait_for_space(struct intel_ring_buffer *ring, int n)
if (ret != -ENOSPC)
return ret;
+ /* force the tail write in case we have been skipping them */
+ __intel_ring_advance(ring);
+
trace_i915_ring_wait_begin(ring);
/* With GEM the hangcheck timer should kick us out of the loop,
* leaving it early runs the risk of corrupting GEM state (due
@@ -1475,7 +1487,7 @@ int intel_ring_idle(struct intel_ring_buffer *ring)
int ret;
/* We need to add any requests required to flush the objects and ring */
- if (ring->outstanding_lazy_request) {
+ if (ring->outstanding_lazy_seqno) {
ret = i915_add_request(ring, NULL);
if (ret)
return ret;
@@ -1495,10 +1507,20 @@ int intel_ring_idle(struct intel_ring_buffer *ring)
static int
intel_ring_alloc_seqno(struct intel_ring_buffer *ring)
{
- if (ring->outstanding_lazy_request)
+ if (ring->outstanding_lazy_seqno)
return 0;
- return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_request);
+ if (ring->preallocated_lazy_request == NULL) {
+ struct drm_i915_gem_request *request;
+
+ request = kmalloc(sizeof(*request), GFP_KERNEL);
+ if (request == NULL)
+ return -ENOMEM;
+
+ ring->preallocated_lazy_request = request;
+ }
+
+ return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_seqno);
}
static int __intel_ring_begin(struct intel_ring_buffer *ring,
@@ -1545,7 +1567,7 @@ void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno)
{
struct drm_i915_private *dev_priv = ring->dev->dev_private;
- BUG_ON(ring->outstanding_lazy_request);
+ BUG_ON(ring->outstanding_lazy_seqno);
if (INTEL_INFO(ring->dev)->gen >= 6) {
I915_WRITE(RING_SYNC_0(ring->mmio_base), 0);
@@ -1558,17 +1580,6 @@ void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno)
ring->hangcheck.seqno = seqno;
}
-void intel_ring_advance(struct intel_ring_buffer *ring)
-{
- struct drm_i915_private *dev_priv = ring->dev->dev_private;
-
- ring->tail &= ring->size - 1;
- if (dev_priv->gpu_error.stop_rings & intel_ring_flag(ring))
- return;
- ring->write_tail(ring, ring->tail);
-}
-
-
static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring,
u32 value)
{
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 68b1ca974d59..71a73f4fe252 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)
enum intel_ring_hangcheck_action {
+ HANGCHECK_IDLE = 0,
HANGCHECK_WAIT,
HANGCHECK_ACTIVE,
HANGCHECK_KICK,
@@ -140,7 +141,8 @@ struct intel_ring_buffer {
/**
* Do we have some not yet emitted requests outstanding?
*/
- u32 outstanding_lazy_request;
+ struct drm_i915_gem_request *preallocated_lazy_request;
+ u32 outstanding_lazy_seqno;
bool gpu_caches_dirty;
bool fbc_dirty;
@@ -237,7 +239,12 @@ static inline void intel_ring_emit(struct intel_ring_buffer *ring,
iowrite32(data, ring->virtual_start + ring->tail);
ring->tail += 4;
}
-void intel_ring_advance(struct intel_ring_buffer *ring);
+static inline void intel_ring_advance(struct intel_ring_buffer *ring)
+{
+ ring->tail &= ring->size - 1;
+}
+void __intel_ring_advance(struct intel_ring_buffer *ring);
+
int __must_check intel_ring_idle(struct intel_ring_buffer *ring);
void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno);
int intel_ring_flush_all_caches(struct intel_ring_buffer *ring);
@@ -258,8 +265,8 @@ static inline u32 intel_ring_get_tail(struct intel_ring_buffer *ring)
static inline u32 intel_ring_get_seqno(struct intel_ring_buffer *ring)
{
- BUG_ON(ring->outstanding_lazy_request == 0);
- return ring->outstanding_lazy_request;
+ BUG_ON(ring->outstanding_lazy_seqno == 0);
+ return ring->outstanding_lazy_seqno;
}
static inline void i915_trace_irq_get(struct intel_ring_buffer *ring, u32 seqno)
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 49482fd5b76c..5e59d64cfd95 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -539,7 +539,7 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo,
goto log_fail;
while ((status == SDVO_CMD_STATUS_PENDING ||
- status == SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED) && --retry) {
+ status == SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED) && --retry) {
if (retry < 10)
msleep(15);
else
@@ -1068,7 +1068,7 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo,
static void i9xx_adjust_sdvo_tv_clock(struct intel_crtc_config *pipe_config)
{
- unsigned dotclock = pipe_config->adjusted_mode.clock;
+ unsigned dotclock = pipe_config->port_clock;
struct dpll *clock = &pipe_config->dpll;
/* SDVO TV has fixed PLL values depend on its clock range,
@@ -1133,7 +1133,6 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder,
*/
pipe_config->pixel_multiplier =
intel_sdvo_get_pixel_multiplier(adjusted_mode);
- adjusted_mode->clock *= pipe_config->pixel_multiplier;
if (intel_sdvo->color_range_auto) {
/* See CEA-861-E - 5.1 Default Encoding Parameters */
@@ -1217,11 +1216,7 @@ static void intel_sdvo_mode_set(struct intel_encoder *intel_encoder)
!intel_sdvo_set_tv_format(intel_sdvo))
return;
- /* We have tried to get input timing in mode_fixup, and filled into
- * adjusted_mode.
- */
intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
- input_dtd.part1.clock /= crtc->config.pixel_multiplier;
if (intel_sdvo->is_tv || intel_sdvo->is_lvds)
input_dtd.part2.sdvo_flags = intel_sdvo->dtd_sdvo_flags;
@@ -1330,6 +1325,7 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder,
struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
struct intel_sdvo_dtd dtd;
int encoder_pixel_multiplier = 0;
+ int dotclock;
u32 flags = 0, sdvox;
u8 val;
bool ret;
@@ -1368,6 +1364,13 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder,
>> SDVO_PORT_MULTIPLY_SHIFT) + 1;
}
+ dotclock = pipe_config->port_clock / pipe_config->pixel_multiplier;
+
+ if (HAS_PCH_SPLIT(dev))
+ ironlake_check_encoder_dotclock(pipe_config, dotclock);
+
+ pipe_config->adjusted_mode.crtc_clock = dotclock;
+
/* Cross check the port pixel multiplier with the sdvo encoder state. */
if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_CLOCK_RATE_MULT,
&val, 1)) {
@@ -1770,6 +1773,9 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
{
struct edid *edid;
+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+ connector->base.id, drm_get_connector_name(connector));
+
/* set the bus switch and get the modes */
edid = intel_sdvo_get_edid(connector);
@@ -1865,6 +1871,9 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
uint32_t reply = 0, format_map = 0;
int i;
+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+ connector->base.id, drm_get_connector_name(connector));
+
/* Read the list of supported input resolutions for the selected TV
* format.
*/
@@ -1899,6 +1908,9 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
struct drm_i915_private *dev_priv = connector->dev->dev_private;
struct drm_display_mode *newmode;
+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+ connector->base.id, drm_get_connector_name(connector));
+
/*
* Fetch modes from VBT. For SDVO prefer the VBT mode since some
* SDVO->LVDS transcoders can't cope with the EDID mode.
@@ -1930,7 +1942,6 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
break;
}
}
-
}
static int intel_sdvo_get_modes(struct drm_connector *connector)
@@ -2394,7 +2405,9 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
struct intel_connector *intel_connector;
struct intel_sdvo_connector *intel_sdvo_connector;
- intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL);
+ DRM_DEBUG_KMS("initialising DVI device %d\n", device);
+
+ intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL);
if (!intel_sdvo_connector)
return false;
@@ -2442,7 +2455,9 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
struct intel_connector *intel_connector;
struct intel_sdvo_connector *intel_sdvo_connector;
- intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL);
+ DRM_DEBUG_KMS("initialising TV type %d\n", type);
+
+ intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL);
if (!intel_sdvo_connector)
return false;
@@ -2479,7 +2494,9 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
struct intel_connector *intel_connector;
struct intel_sdvo_connector *intel_sdvo_connector;
- intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL);
+ DRM_DEBUG_KMS("initialising analog device %d\n", device);
+
+ intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL);
if (!intel_sdvo_connector)
return false;
@@ -2510,7 +2527,9 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
struct intel_connector *intel_connector;
struct intel_sdvo_connector *intel_sdvo_connector;
- intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL);
+ DRM_DEBUG_KMS("initialising LVDS device %d\n", device);
+
+ intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL);
if (!intel_sdvo_connector)
return false;
@@ -2876,7 +2895,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
struct intel_encoder *intel_encoder;
struct intel_sdvo *intel_sdvo;
int i;
- intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL);
+ intel_sdvo = kzalloc(sizeof(*intel_sdvo), GFP_KERNEL);
if (!intel_sdvo)
return false;
diff --git a/drivers/gpu/drm/i915/intel_sideband.c b/drivers/gpu/drm/i915/intel_sideband.c
index 9a0e6c5ea540..acd1cfe8b7dd 100644
--- a/drivers/gpu/drm/i915/intel_sideband.c
+++ b/drivers/gpu/drm/i915/intel_sideband.c
@@ -101,19 +101,83 @@ u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr)
return val;
}
-u32 vlv_dpio_read(struct drm_i915_private *dev_priv, int reg)
+u32 vlv_gpio_nc_read(struct drm_i915_private *dev_priv, u32 reg)
{
u32 val = 0;
+ vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_GPIO_NC,
+ PUNIT_OPCODE_REG_READ, reg, &val);
+ return val;
+}
- vlv_sideband_rw(dev_priv, DPIO_DEVFN, IOSF_PORT_DPIO,
- DPIO_OPCODE_REG_READ, reg, &val);
+void vlv_gpio_nc_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
+{
+ vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_GPIO_NC,
+ PUNIT_OPCODE_REG_WRITE, reg, &val);
+}
+
+u32 vlv_cck_read(struct drm_i915_private *dev_priv, u32 reg)
+{
+ u32 val = 0;
+ vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_CCK,
+ PUNIT_OPCODE_REG_READ, reg, &val);
+ return val;
+}
+
+void vlv_cck_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
+{
+ vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_CCK,
+ PUNIT_OPCODE_REG_WRITE, reg, &val);
+}
+
+u32 vlv_ccu_read(struct drm_i915_private *dev_priv, u32 reg)
+{
+ u32 val = 0;
+ vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_CCU,
+ PUNIT_OPCODE_REG_READ, reg, &val);
+ return val;
+}
+
+void vlv_ccu_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
+{
+ vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_CCU,
+ PUNIT_OPCODE_REG_WRITE, reg, &val);
+}
+
+u32 vlv_gps_core_read(struct drm_i915_private *dev_priv, u32 reg)
+{
+ u32 val = 0;
+ vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_GPS_CORE,
+ PUNIT_OPCODE_REG_READ, reg, &val);
+ return val;
+}
+
+void vlv_gps_core_write(struct drm_i915_private *dev_priv, u32 reg, u32 val)
+{
+ vlv_sideband_rw(dev_priv, PCI_DEVFN(2, 0), IOSF_PORT_GPS_CORE,
+ PUNIT_OPCODE_REG_WRITE, reg, &val);
+}
+static u32 vlv_get_phy_port(enum pipe pipe)
+{
+ u32 port = IOSF_PORT_DPIO;
+
+ WARN_ON ((pipe != PIPE_A) && (pipe != PIPE_B));
+
+ return port;
+}
+
+u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum pipe pipe, int reg)
+{
+ u32 val = 0;
+
+ vlv_sideband_rw(dev_priv, DPIO_DEVFN, vlv_get_phy_port(pipe),
+ DPIO_OPCODE_REG_READ, reg, &val);
return val;
}
-void vlv_dpio_write(struct drm_i915_private *dev_priv, int reg, u32 val)
+void vlv_dpio_write(struct drm_i915_private *dev_priv, enum pipe pipe, int reg, u32 val)
{
- vlv_sideband_rw(dev_priv, DPIO_DEVFN, IOSF_PORT_DPIO,
+ vlv_sideband_rw(dev_priv, DPIO_DEVFN, vlv_get_phy_port(pipe),
DPIO_OPCODE_REG_WRITE, reg, &val);
}
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index ad6ec4b39005..cae10bc746d0 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -288,7 +288,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
dev_priv->sprite_scaling_enabled |= 1 << pipe;
if (!scaling_was_enabled) {
- intel_update_watermarks(dev);
+ intel_update_watermarks(crtc);
intel_wait_for_vblank(dev, pipe);
}
sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
@@ -323,7 +323,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
/* potentially re-enable LP watermarks */
if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
- intel_update_watermarks(dev);
+ intel_update_watermarks(crtc);
}
static void
@@ -349,7 +349,7 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
/* potentially re-enable LP watermarks */
if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
- intel_update_watermarks(dev);
+ intel_update_watermarks(crtc);
}
static int
@@ -652,8 +652,8 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
.y2 = crtc_y + crtc_h,
};
const struct drm_rect clip = {
- .x2 = crtc->mode.hdisplay,
- .y2 = crtc->mode.vdisplay,
+ .x2 = intel_crtc->config.pipe_src_w,
+ .y2 = intel_crtc->config.pipe_src_h,
};
intel_fb = to_intel_framebuffer(fb);
@@ -1034,7 +1034,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
if (INTEL_INFO(dev)->gen < 5)
return -ENODEV;
- intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL);
+ intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
if (!intel_plane)
return -ENOMEM;
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index f2c6d7909ae2..75925a1ab351 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -912,10 +912,18 @@ intel_tv_compute_config(struct intel_encoder *encoder,
if (!tv_mode)
return false;
- pipe_config->adjusted_mode.clock = tv_mode->clock;
+ pipe_config->adjusted_mode.crtc_clock = tv_mode->clock;
DRM_DEBUG_KMS("forcing bpc to 8 for TV\n");
pipe_config->pipe_bpp = 8*3;
+ /* TV has it's own notion of sync and other mode flags, so clear them. */
+ pipe_config->adjusted_mode.flags = 0;
+
+ /*
+ * FIXME: We don't check whether the input mode is actually what we want
+ * or whether userspace is doing something stupid.
+ */
+
return true;
}
@@ -1510,7 +1518,7 @@ static const struct drm_encoder_funcs intel_tv_enc_funcs = {
static int tv_is_present_in_vbt(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- struct child_device_config *p_child;
+ union child_device_config *p_child;
int i, ret;
if (!dev_priv->vbt.child_dev_num)
@@ -1522,13 +1530,13 @@ static int tv_is_present_in_vbt(struct drm_device *dev)
/*
* If the device type is not TV, continue.
*/
- if (p_child->device_type != DEVICE_TYPE_INT_TV &&
- p_child->device_type != DEVICE_TYPE_TV)
+ if (p_child->old.device_type != DEVICE_TYPE_INT_TV &&
+ p_child->old.device_type != DEVICE_TYPE_TV)
continue;
/* Only when the addin_offset is non-zero, it is regarded
* as present.
*/
- if (p_child->addin_offset) {
+ if (p_child->old.addin_offset) {
ret = 1;
break;
}
@@ -1582,12 +1590,12 @@ intel_tv_init(struct drm_device *dev)
(tv_dac_off & TVDAC_STATE_CHG_EN) != 0)
return;
- intel_tv = kzalloc(sizeof(struct intel_tv), GFP_KERNEL);
+ intel_tv = kzalloc(sizeof(*intel_tv), GFP_KERNEL);
if (!intel_tv) {
return;
}
- intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
+ intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL);
if (!intel_connector) {
kfree(intel_tv);
return;
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 8649f1c36b00..f2753d9fb098 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -204,6 +204,18 @@ static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
gen6_gt_check_fifodbg(dev_priv);
}
+static void gen6_force_wake_work(struct work_struct *work)
+{
+ struct drm_i915_private *dev_priv =
+ container_of(work, typeof(*dev_priv), uncore.force_wake_work.work);
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+ if (--dev_priv->uncore.forcewake_count == 0)
+ dev_priv->uncore.funcs.force_wake_put(dev_priv);
+ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+}
+
void intel_uncore_early_sanitize(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -216,6 +228,9 @@ void intel_uncore_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ INIT_DELAYED_WORK(&dev_priv->uncore.force_wake_work,
+ gen6_force_wake_work);
+
if (IS_VALLEYVIEW(dev)) {
dev_priv->uncore.funcs.force_wake_get = vlv_force_wake_get;
dev_priv->uncore.funcs.force_wake_put = vlv_force_wake_put;
@@ -261,6 +276,16 @@ void intel_uncore_init(struct drm_device *dev)
}
}
+void intel_uncore_fini(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ flush_delayed_work(&dev_priv->uncore.force_wake_work);
+
+ /* Paranoia: make sure we have disabled everything before we exit. */
+ intel_uncore_sanitize(dev);
+}
+
static void intel_uncore_forcewake_reset(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -306,8 +331,12 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
unsigned long irqflags;
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
- if (--dev_priv->uncore.forcewake_count == 0)
- dev_priv->uncore.funcs.force_wake_put(dev_priv);
+ if (--dev_priv->uncore.forcewake_count == 0) {
+ dev_priv->uncore.forcewake_count++;
+ mod_delayed_work(dev_priv->wq,
+ &dev_priv->uncore.force_wake_work,
+ 1);
+ }
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
index d4fbf11360fe..0e3270c3ffd2 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
@@ -326,8 +326,6 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode)
regp->MiscOutReg = 0x23; /* +hsync +vsync */
}
- regp->MiscOutReg |= (mode->clock_index & 0x03) << 2;
-
/*
* Time Sequencer
*/
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index 145bdac13a37..ceb96c61eebe 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -254,18 +254,15 @@ static struct vga_switcheroo_handler nouveau_dsm_handler = {
static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
{
- acpi_handle dhandle, nvidia_handle;
- acpi_status status;
+ acpi_handle dhandle;
int retval = 0;
dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
if (!dhandle)
return false;
- status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle);
- if (ACPI_FAILURE(status)) {
+ if (!acpi_has_method(dhandle, "_DSM"))
return false;
- }
if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER))
retval |= NOUVEAU_DSM_HAS_MUX;
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 71b70e3a7a71..53747245d904 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -322,7 +322,7 @@ config HID_LCPOWER
config HID_LENOVO_TPKBD
tristate "Lenovo ThinkPad USB Keyboard with TrackPoint"
- depends on USB_HID
+ depends on HID
select NEW_LEDS
select LEDS_CLASS
---help---
diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c
index f042a6cf8b18..4e49462870ab 100644
--- a/drivers/hid/hid-elo.c
+++ b/drivers/hid/hid-elo.c
@@ -181,7 +181,40 @@ fail:
*/
static bool elo_broken_firmware(struct usb_device *dev)
{
- return use_fw_quirk && le16_to_cpu(dev->descriptor.bcdDevice) == 0x10d;
+ struct usb_device *hub = dev->parent;
+ struct usb_device *child = NULL;
+ u16 fw_lvl = le16_to_cpu(dev->descriptor.bcdDevice);
+ u16 child_vid, child_pid;
+ int i;
+
+ if (!use_fw_quirk)
+ return false;
+ if (fw_lvl != 0x10d)
+ return false;
+
+ /* iterate sibling devices of the touch controller */
+ usb_hub_for_each_child(hub, i, child) {
+ child_vid = le16_to_cpu(child->descriptor.idVendor);
+ child_pid = le16_to_cpu(child->descriptor.idProduct);
+
+ /*
+ * If one of the devices below is present attached as a sibling of
+ * the touch controller then this is a newer IBM 4820 monitor that
+ * does not need the IBM-requested workaround if fw level is
+ * 0x010d - aka 'M'.
+ * No other HW can have this combination.
+ */
+ if (child_vid==0x04b3) {
+ switch (child_pid) {
+ case 0x4676: /* 4820 21x Video */
+ case 0x4677: /* 4820 51x Video */
+ case 0x4678: /* 4820 2Lx Video */
+ case 0x4679: /* 4820 5Lx Video */
+ return false;
+ }
+ }
+ }
+ return true;
}
static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id)
diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c
index 31cf29a6ba17..2d25b6cbbc05 100644
--- a/drivers/hid/hid-lenovo-tpkbd.c
+++ b/drivers/hid/hid-lenovo-tpkbd.c
@@ -14,11 +14,9 @@
#include <linux/module.h>
#include <linux/sysfs.h>
#include <linux/device.h>
-#include <linux/usb.h>
#include <linux/hid.h>
#include <linux/input.h>
#include <linux/leds.h>
-#include "usbhid/usbhid.h"
#include "hid-ids.h"
@@ -41,10 +39,9 @@ static int tpkbd_input_mapping(struct hid_device *hdev,
struct hid_input *hi, struct hid_field *field,
struct hid_usage *usage, unsigned long **bit, int *max)
{
- struct usbhid_device *uhdev;
-
- uhdev = (struct usbhid_device *) hdev->driver_data;
- if (uhdev->ifnum == 1 && usage->hid == (HID_UP_BUTTON | 0x0010)) {
+ if (usage->hid == (HID_UP_BUTTON | 0x0010)) {
+ /* mark the device as pointer */
+ hid_set_drvdata(hdev, (void *)1);
map_key_clear(KEY_MICMUTE);
return 1;
}
@@ -339,7 +336,7 @@ static int tpkbd_probe_tp(struct hid_device *hdev)
struct tpkbd_data_pointer *data_pointer;
size_t name_sz = strlen(dev_name(dev)) + 16;
char *name_mute, *name_micmute;
- int i, ret;
+ int i;
/* Validate required reports. */
for (i = 0; i < 4; i++) {
@@ -354,7 +351,9 @@ static int tpkbd_probe_tp(struct hid_device *hdev)
hid_warn(hdev, "Could not create sysfs group\n");
}
- data_pointer = kzalloc(sizeof(struct tpkbd_data_pointer), GFP_KERNEL);
+ data_pointer = devm_kzalloc(&hdev->dev,
+ sizeof(struct tpkbd_data_pointer),
+ GFP_KERNEL);
if (data_pointer == NULL) {
hid_err(hdev, "Could not allocate memory for driver data\n");
return -ENOMEM;
@@ -364,20 +363,13 @@ static int tpkbd_probe_tp(struct hid_device *hdev)
data_pointer->sensitivity = 0xa0;
data_pointer->press_speed = 0x38;
- name_mute = kzalloc(name_sz, GFP_KERNEL);
- if (name_mute == NULL) {
+ name_mute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
+ name_micmute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL);
+ if (name_mute == NULL || name_micmute == NULL) {
hid_err(hdev, "Could not allocate memory for led data\n");
- ret = -ENOMEM;
- goto err;
+ return -ENOMEM;
}
snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev));
-
- name_micmute = kzalloc(name_sz, GFP_KERNEL);
- if (name_micmute == NULL) {
- hid_err(hdev, "Could not allocate memory for led data\n");
- ret = -ENOMEM;
- goto err2;
- }
snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev));
hid_set_drvdata(hdev, data_pointer);
@@ -397,19 +389,12 @@ static int tpkbd_probe_tp(struct hid_device *hdev)
tpkbd_features_set(hdev);
return 0;
-
-err2:
- kfree(name_mute);
-err:
- kfree(data_pointer);
- return ret;
}
static int tpkbd_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
int ret;
- struct usbhid_device *uhdev;
ret = hid_parse(hdev);
if (ret) {
@@ -423,9 +408,8 @@ static int tpkbd_probe(struct hid_device *hdev,
goto err;
}
- uhdev = (struct usbhid_device *) hdev->driver_data;
-
- if (uhdev->ifnum == 1) {
+ if (hid_get_drvdata(hdev)) {
+ hid_set_drvdata(hdev, NULL);
ret = tpkbd_probe_tp(hdev);
if (ret)
goto err_hid;
@@ -449,17 +433,11 @@ static void tpkbd_remove_tp(struct hid_device *hdev)
led_classdev_unregister(&data_pointer->led_mute);
hid_set_drvdata(hdev, NULL);
- kfree(data_pointer->led_micmute.name);
- kfree(data_pointer->led_mute.name);
- kfree(data_pointer);
}
static void tpkbd_remove(struct hid_device *hdev)
{
- struct usbhid_device *uhdev;
-
- uhdev = (struct usbhid_device *) hdev->driver_data;
- if (uhdev->ifnum == 1)
+ if (hid_get_drvdata(hdev))
tpkbd_remove_tp(hdev);
hid_hw_stop(hdev);
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index b18320db5f7d..bc37a1800166 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -419,21 +419,14 @@ static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
*/
static int sixaxis_set_operational_usb(struct hid_device *hdev)
{
- struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- struct usb_device *dev = interface_to_usbdev(intf);
- __u16 ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
int ret;
char *buf = kmalloc(18, GFP_KERNEL);
if (!buf)
return -ENOMEM;
- ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- HID_REQ_GET_REPORT,
- USB_DIR_IN | USB_TYPE_CLASS |
- USB_RECIP_INTERFACE,
- (3 << 8) | 0xf2, ifnum, buf, 17,
- USB_CTRL_GET_TIMEOUT);
+ ret = hdev->hid_get_raw_report(hdev, 0xf2, buf, 17, HID_FEATURE_REPORT);
+
if (ret < 0)
hid_err(hdev, "can't set operational mode\n");
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index c1336193b04b..fd7ce374f812 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -854,10 +854,10 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client,
0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45,
0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE,
};
- struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
- union acpi_object params[4], *obj;
+ union acpi_object params[4];
struct acpi_object_list input;
struct acpi_device *adev;
+ unsigned long long value;
acpi_handle handle;
handle = ACPI_HANDLE(&client->dev);
@@ -878,22 +878,14 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client,
params[3].package.count = 0;
params[3].package.elements = NULL;
- if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DSM", &input, &buf))) {
+ if (ACPI_FAILURE(acpi_evaluate_integer(handle, "_DSM", &input,
+ &value))) {
dev_err(&client->dev, "device _DSM execution failed\n");
return -ENODEV;
}
- obj = (union acpi_object *)buf.pointer;
- if (obj->type != ACPI_TYPE_INTEGER) {
- dev_err(&client->dev, "device _DSM returned invalid type: %d\n",
- obj->type);
- kfree(buf.pointer);
- return -EINVAL;
- }
-
- pdata->hid_descriptor_address = obj->integer.value;
+ pdata->hid_descriptor_address = value;
- kfree(buf.pointer);
return 0;
}
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index 6de6c98ce6eb..cea623c36ae2 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -47,8 +47,8 @@ static void vmbus_setevent(struct vmbus_channel *channel)
(unsigned long *) vmbus_connection.send_int_page +
(channel->offermsg.child_relid >> 5));
- monitorpage = vmbus_connection.monitor_pages;
- monitorpage++; /* Get the child to parent monitor page */
+ /* Get the child to parent monitor page */
+ monitorpage = vmbus_connection.monitor_pages[1];
sync_set_bit(channel->monitor_bit,
(unsigned long *)&monitorpage->trigger_group
@@ -60,50 +60,6 @@ static void vmbus_setevent(struct vmbus_channel *channel)
}
/*
- * vmbus_get_debug_info -Retrieve various channel debug info
- */
-void vmbus_get_debug_info(struct vmbus_channel *channel,
- struct vmbus_channel_debug_info *debuginfo)
-{
- struct hv_monitor_page *monitorpage;
- u8 monitor_group = (u8)channel->offermsg.monitorid / 32;
- u8 monitor_offset = (u8)channel->offermsg.monitorid % 32;
-
- debuginfo->relid = channel->offermsg.child_relid;
- debuginfo->state = channel->state;
- memcpy(&debuginfo->interfacetype,
- &channel->offermsg.offer.if_type, sizeof(uuid_le));
- memcpy(&debuginfo->interface_instance,
- &channel->offermsg.offer.if_instance,
- sizeof(uuid_le));
-
- monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages;
-
- debuginfo->monitorid = channel->offermsg.monitorid;
-
- debuginfo->servermonitor_pending =
- monitorpage->trigger_group[monitor_group].pending;
- debuginfo->servermonitor_latency =
- monitorpage->latency[monitor_group][monitor_offset];
- debuginfo->servermonitor_connectionid =
- monitorpage->parameter[monitor_group]
- [monitor_offset].connectionid.u.id;
-
- monitorpage++;
-
- debuginfo->clientmonitor_pending =
- monitorpage->trigger_group[monitor_group].pending;
- debuginfo->clientmonitor_latency =
- monitorpage->latency[monitor_group][monitor_offset];
- debuginfo->clientmonitor_connectionid =
- monitorpage->parameter[monitor_group]
- [monitor_offset].connectionid.u.id;
-
- hv_ringbuffer_get_debuginfo(&channel->inbound, &debuginfo->inbound);
- hv_ringbuffer_get_debuginfo(&channel->outbound, &debuginfo->outbound);
-}
-
-/*
* vmbus_open - Open the specified channel.
*/
int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
@@ -855,6 +811,6 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
if (signal)
vmbus_setevent(channel);
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index 8f4743ab5fb2..af6edf9b1936 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -76,10 +76,8 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo,
msg->header.msgtype = CHANNELMSG_INITIATE_CONTACT;
msg->vmbus_version_requested = version;
msg->interrupt_page = virt_to_phys(vmbus_connection.int_page);
- msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages);
- msg->monitor_page2 = virt_to_phys(
- (void *)((unsigned long)vmbus_connection.monitor_pages +
- PAGE_SIZE));
+ msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]);
+ msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]);
/*
* Add to list before we send the request since we may
@@ -169,9 +167,10 @@ int vmbus_connect(void)
* Setup the monitor notification facility. The 1st page for
* parent->child and the 2nd page for child->parent
*/
- vmbus_connection.monitor_pages =
- (void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 1);
- if (vmbus_connection.monitor_pages == NULL) {
+ vmbus_connection.monitor_pages[0] = (void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 0);
+ vmbus_connection.monitor_pages[1] = (void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 0);
+ if ((vmbus_connection.monitor_pages[0] == NULL) ||
+ (vmbus_connection.monitor_pages[1] == NULL)) {
ret = -ENOMEM;
goto cleanup;
}
@@ -195,7 +194,7 @@ int vmbus_connect(void)
do {
ret = vmbus_negotiate_version(msginfo, version);
- if (ret)
+ if (ret == -ETIMEDOUT)
goto cleanup;
if (vmbus_connection.conn_state == CONNECTED)
@@ -229,10 +228,10 @@ cleanup:
vmbus_connection.int_page = NULL;
}
- if (vmbus_connection.monitor_pages) {
- free_pages((unsigned long)vmbus_connection.monitor_pages, 1);
- vmbus_connection.monitor_pages = NULL;
- }
+ free_pages((unsigned long)vmbus_connection.monitor_pages[0], 1);
+ free_pages((unsigned long)vmbus_connection.monitor_pages[1], 1);
+ vmbus_connection.monitor_pages[0] = NULL;
+ vmbus_connection.monitor_pages[1] = NULL;
kfree(msginfo);
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 28b03325b872..09988b289622 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -32,13 +32,17 @@
/*
* Pre win8 version numbers used in ws2008 and ws 2008 r2 (win7)
*/
+#define WS2008_SRV_MAJOR 1
+#define WS2008_SRV_MINOR 0
+#define WS2008_SRV_VERSION (WS2008_SRV_MAJOR << 16 | WS2008_SRV_MINOR)
+
#define WIN7_SRV_MAJOR 3
#define WIN7_SRV_MINOR 0
-#define WIN7_SRV_MAJOR_MINOR (WIN7_SRV_MAJOR << 16 | WIN7_SRV_MINOR)
+#define WIN7_SRV_VERSION (WIN7_SRV_MAJOR << 16 | WIN7_SRV_MINOR)
#define WIN8_SRV_MAJOR 4
#define WIN8_SRV_MINOR 0
-#define WIN8_SRV_MAJOR_MINOR (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
+#define WIN8_SRV_VERSION (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
/*
* Global state maintained for transaction that is being processed.
@@ -587,6 +591,8 @@ void hv_kvp_onchannelcallback(void *context)
struct icmsg_hdr *icmsghdrp;
struct icmsg_negotiate *negop = NULL;
+ int util_fw_version;
+ int kvp_srv_version;
if (kvp_transaction.active) {
/*
@@ -606,17 +612,26 @@ void hv_kvp_onchannelcallback(void *context)
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
/*
- * We start with win8 version and if the host cannot
- * support that we use the previous version.
+ * Based on the host, select appropriate
+ * framework and service versions we will
+ * negotiate.
*/
- if (vmbus_prep_negotiate_resp(icmsghdrp, negop,
- recv_buffer, UTIL_FW_MAJOR_MINOR,
- WIN8_SRV_MAJOR_MINOR))
- goto done;
-
+ switch (vmbus_proto_version) {
+ case (VERSION_WS2008):
+ util_fw_version = UTIL_WS2K8_FW_VERSION;
+ kvp_srv_version = WS2008_SRV_VERSION;
+ break;
+ case (VERSION_WIN7):
+ util_fw_version = UTIL_FW_VERSION;
+ kvp_srv_version = WIN7_SRV_VERSION;
+ break;
+ default:
+ util_fw_version = UTIL_FW_VERSION;
+ kvp_srv_version = WIN8_SRV_VERSION;
+ }
vmbus_prep_negotiate_resp(icmsghdrp, negop,
- recv_buffer, UTIL_FW_MAJOR_MINOR,
- WIN7_SRV_MAJOR_MINOR);
+ recv_buffer, util_fw_version,
+ kvp_srv_version);
} else {
kvp_msg = (struct hv_kvp_msg *)&recv_buffer[
@@ -649,7 +664,6 @@ void hv_kvp_onchannelcallback(void *context)
return;
}
-done:
icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
| ICMSGHDRFLAG_RESPONSE;
diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c
index e4572f3f2834..0c3546224376 100644
--- a/drivers/hv/hv_snapshot.c
+++ b/drivers/hv/hv_snapshot.c
@@ -26,7 +26,7 @@
#define VSS_MAJOR 5
#define VSS_MINOR 0
-#define VSS_MAJOR_MINOR (VSS_MAJOR << 16 | VSS_MINOR)
+#define VSS_VERSION (VSS_MAJOR << 16 | VSS_MINOR)
@@ -190,8 +190,8 @@ void hv_vss_onchannelcallback(void *context)
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
vmbus_prep_negotiate_resp(icmsghdrp, negop,
- recv_buffer, UTIL_FW_MAJOR_MINOR,
- VSS_MAJOR_MINOR);
+ recv_buffer, UTIL_FW_VERSION,
+ VSS_VERSION);
} else {
vss_msg = (struct hv_vss_msg *)&recv_buffer[
sizeof(struct vmbuspipe_hdr) +
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index cb82233541b1..62dfd246b948 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -28,17 +28,32 @@
#include <linux/reboot.h>
#include <linux/hyperv.h>
-#define SHUTDOWN_MAJOR 3
-#define SHUTDOWN_MINOR 0
-#define SHUTDOWN_MAJOR_MINOR (SHUTDOWN_MAJOR << 16 | SHUTDOWN_MINOR)
-#define TIMESYNCH_MAJOR 3
-#define TIMESYNCH_MINOR 0
-#define TIMESYNCH_MAJOR_MINOR (TIMESYNCH_MAJOR << 16 | TIMESYNCH_MINOR)
+#define SD_MAJOR 3
+#define SD_MINOR 0
+#define SD_VERSION (SD_MAJOR << 16 | SD_MINOR)
-#define HEARTBEAT_MAJOR 3
-#define HEARTBEAT_MINOR 0
-#define HEARTBEAT_MAJOR_MINOR (HEARTBEAT_MAJOR << 16 | HEARTBEAT_MINOR)
+#define SD_WS2008_MAJOR 1
+#define SD_WS2008_VERSION (SD_WS2008_MAJOR << 16 | SD_MINOR)
+
+#define TS_MAJOR 3
+#define TS_MINOR 0
+#define TS_VERSION (TS_MAJOR << 16 | TS_MINOR)
+
+#define TS_WS2008_MAJOR 1
+#define TS_WS2008_VERSION (TS_WS2008_MAJOR << 16 | TS_MINOR)
+
+#define HB_MAJOR 3
+#define HB_MINOR 0
+#define HB_VERSION (HB_MAJOR << 16 | HB_MINOR)
+
+#define HB_WS2008_MAJOR 1
+#define HB_WS2008_VERSION (HB_WS2008_MAJOR << 16 | HB_MINOR)
+
+static int sd_srv_version;
+static int ts_srv_version;
+static int hb_srv_version;
+static int util_fw_version;
static void shutdown_onchannelcallback(void *context);
static struct hv_util_service util_shutdown = {
@@ -82,7 +97,7 @@ static void shutdown_onchannelcallback(void *context)
struct vmbus_channel *channel = context;
u32 recvlen;
u64 requestid;
- u8 execute_shutdown = false;
+ bool execute_shutdown = false;
u8 *shut_txf_buf = util_shutdown.recv_buffer;
struct shutdown_msg_data *shutdown_msg;
@@ -99,8 +114,8 @@ static void shutdown_onchannelcallback(void *context)
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
vmbus_prep_negotiate_resp(icmsghdrp, negop,
- shut_txf_buf, UTIL_FW_MAJOR_MINOR,
- SHUTDOWN_MAJOR_MINOR);
+ shut_txf_buf, util_fw_version,
+ sd_srv_version);
} else {
shutdown_msg =
(struct shutdown_msg_data *)&shut_txf_buf[
@@ -216,6 +231,7 @@ static void timesync_onchannelcallback(void *context)
struct icmsg_hdr *icmsghdrp;
struct ictimesync_data *timedatap;
u8 *time_txf_buf = util_timesynch.recv_buffer;
+ struct icmsg_negotiate *negop = NULL;
vmbus_recvpacket(channel, time_txf_buf,
PAGE_SIZE, &recvlen, &requestid);
@@ -225,9 +241,10 @@ static void timesync_onchannelcallback(void *context)
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
- vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf,
- UTIL_FW_MAJOR_MINOR,
- TIMESYNCH_MAJOR_MINOR);
+ vmbus_prep_negotiate_resp(icmsghdrp, negop,
+ time_txf_buf,
+ util_fw_version,
+ ts_srv_version);
} else {
timedatap = (struct ictimesync_data *)&time_txf_buf[
sizeof(struct vmbuspipe_hdr) +
@@ -257,6 +274,7 @@ static void heartbeat_onchannelcallback(void *context)
struct icmsg_hdr *icmsghdrp;
struct heartbeat_msg_data *heartbeat_msg;
u8 *hbeat_txf_buf = util_heartbeat.recv_buffer;
+ struct icmsg_negotiate *negop = NULL;
vmbus_recvpacket(channel, hbeat_txf_buf,
PAGE_SIZE, &recvlen, &requestid);
@@ -266,9 +284,9 @@ static void heartbeat_onchannelcallback(void *context)
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
- vmbus_prep_negotiate_resp(icmsghdrp, NULL,
- hbeat_txf_buf, UTIL_FW_MAJOR_MINOR,
- HEARTBEAT_MAJOR_MINOR);
+ vmbus_prep_negotiate_resp(icmsghdrp, negop,
+ hbeat_txf_buf, util_fw_version,
+ hb_srv_version);
} else {
heartbeat_msg =
(struct heartbeat_msg_data *)&hbeat_txf_buf[
@@ -321,6 +339,25 @@ static int util_probe(struct hv_device *dev,
goto error;
hv_set_drvdata(dev, srv);
+ /*
+ * Based on the host; initialize the framework and
+ * service version numbers we will negotiate.
+ */
+ switch (vmbus_proto_version) {
+ case (VERSION_WS2008):
+ util_fw_version = UTIL_WS2K8_FW_VERSION;
+ sd_srv_version = SD_WS2008_VERSION;
+ ts_srv_version = TS_WS2008_VERSION;
+ hb_srv_version = HB_WS2008_VERSION;
+ break;
+
+ default:
+ util_fw_version = UTIL_FW_VERSION;
+ sd_srv_version = SD_VERSION;
+ ts_srv_version = TS_VERSION;
+ hb_srv_version = HB_VERSION;
+ }
+
return 0;
error:
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index d84918fe19ab..e05517616a06 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -514,6 +514,13 @@ struct hv_context {
extern struct hv_context hv_context;
+struct hv_ring_buffer_debug_info {
+ u32 current_interrupt_mask;
+ u32 current_read_index;
+ u32 current_write_index;
+ u32 bytes_avail_toread;
+ u32 bytes_avail_towrite;
+};
/* Hv Interface */
@@ -612,7 +619,7 @@ struct vmbus_connection {
* 2 pages - 1st page for parent->child notification and 2nd
* is child->parent notification
*/
- void *monitor_pages;
+ struct hv_monitor_page *monitor_pages[2];
struct list_head chn_msg_list;
spinlock_t channelmsg_lock;
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index f9fe46f52cfa..48aad4faea06 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -46,24 +46,6 @@ static struct tasklet_struct msg_dpc;
static struct completion probe_event;
static int irq;
-struct hv_device_info {
- u32 chn_id;
- u32 chn_state;
- uuid_le chn_type;
- uuid_le chn_instance;
-
- u32 monitor_id;
- u32 server_monitor_pending;
- u32 server_monitor_latency;
- u32 server_monitor_conn_id;
- u32 client_monitor_pending;
- u32 client_monitor_latency;
- u32 client_monitor_conn_id;
-
- struct hv_dev_port_info inbound;
- struct hv_dev_port_info outbound;
-};
-
static int vmbus_exists(void)
{
if (hv_acpi_dev == NULL)
@@ -72,169 +54,361 @@ static int vmbus_exists(void)
return 0;
}
+#define VMBUS_ALIAS_LEN ((sizeof((struct hv_vmbus_device_id *)0)->guid) * 2)
+static void print_alias_name(struct hv_device *hv_dev, char *alias_name)
+{
+ int i;
+ for (i = 0; i < VMBUS_ALIAS_LEN; i += 2)
+ sprintf(&alias_name[i], "%02x", hv_dev->dev_type.b[i/2]);
+}
-static void get_channel_info(struct hv_device *device,
- struct hv_device_info *info)
+static u8 channel_monitor_group(struct vmbus_channel *channel)
{
- struct vmbus_channel_debug_info debug_info;
+ return (u8)channel->offermsg.monitorid / 32;
+}
- if (!device->channel)
- return;
+static u8 channel_monitor_offset(struct vmbus_channel *channel)
+{
+ return (u8)channel->offermsg.monitorid % 32;
+}
- vmbus_get_debug_info(device->channel, &debug_info);
+static u32 channel_pending(struct vmbus_channel *channel,
+ struct hv_monitor_page *monitor_page)
+{
+ u8 monitor_group = channel_monitor_group(channel);
+ return monitor_page->trigger_group[monitor_group].pending;
+}
- info->chn_id = debug_info.relid;
- info->chn_state = debug_info.state;
- memcpy(&info->chn_type, &debug_info.interfacetype,
- sizeof(uuid_le));
- memcpy(&info->chn_instance, &debug_info.interface_instance,
- sizeof(uuid_le));
+static u32 channel_latency(struct vmbus_channel *channel,
+ struct hv_monitor_page *monitor_page)
+{
+ u8 monitor_group = channel_monitor_group(channel);
+ u8 monitor_offset = channel_monitor_offset(channel);
+ return monitor_page->latency[monitor_group][monitor_offset];
+}
- info->monitor_id = debug_info.monitorid;
+static u32 channel_conn_id(struct vmbus_channel *channel,
+ struct hv_monitor_page *monitor_page)
+{
+ u8 monitor_group = channel_monitor_group(channel);
+ u8 monitor_offset = channel_monitor_offset(channel);
+ return monitor_page->parameter[monitor_group][monitor_offset].connectionid.u.id;
+}
- info->server_monitor_pending = debug_info.servermonitor_pending;
- info->server_monitor_latency = debug_info.servermonitor_latency;
- info->server_monitor_conn_id = debug_info.servermonitor_connectionid;
+static ssize_t id_show(struct device *dev, struct device_attribute *dev_attr,
+ char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
- info->client_monitor_pending = debug_info.clientmonitor_pending;
- info->client_monitor_latency = debug_info.clientmonitor_latency;
- info->client_monitor_conn_id = debug_info.clientmonitor_connectionid;
+ if (!hv_dev->channel)
+ return -ENODEV;
+ return sprintf(buf, "%d\n", hv_dev->channel->offermsg.child_relid);
+}
+static DEVICE_ATTR_RO(id);
- info->inbound.int_mask = debug_info.inbound.current_interrupt_mask;
- info->inbound.read_idx = debug_info.inbound.current_read_index;
- info->inbound.write_idx = debug_info.inbound.current_write_index;
- info->inbound.bytes_avail_toread =
- debug_info.inbound.bytes_avail_toread;
- info->inbound.bytes_avail_towrite =
- debug_info.inbound.bytes_avail_towrite;
+static ssize_t state_show(struct device *dev, struct device_attribute *dev_attr,
+ char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
- info->outbound.int_mask =
- debug_info.outbound.current_interrupt_mask;
- info->outbound.read_idx = debug_info.outbound.current_read_index;
- info->outbound.write_idx = debug_info.outbound.current_write_index;
- info->outbound.bytes_avail_toread =
- debug_info.outbound.bytes_avail_toread;
- info->outbound.bytes_avail_towrite =
- debug_info.outbound.bytes_avail_towrite;
+ if (!hv_dev->channel)
+ return -ENODEV;
+ return sprintf(buf, "%d\n", hv_dev->channel->state);
}
+static DEVICE_ATTR_RO(state);
-#define VMBUS_ALIAS_LEN ((sizeof((struct hv_vmbus_device_id *)0)->guid) * 2)
-static void print_alias_name(struct hv_device *hv_dev, char *alias_name)
+static ssize_t monitor_id_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
{
- int i;
- for (i = 0; i < VMBUS_ALIAS_LEN; i += 2)
- sprintf(&alias_name[i], "%02x", hv_dev->dev_type.b[i/2]);
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ return sprintf(buf, "%d\n", hv_dev->channel->offermsg.monitorid);
}
+static DEVICE_ATTR_RO(monitor_id);
-/*
- * vmbus_show_device_attr - Show the device attribute in sysfs.
- *
- * This is invoked when user does a
- * "cat /sys/bus/vmbus/devices/<busdevice>/<attr name>"
- */
-static ssize_t vmbus_show_device_attr(struct device *dev,
- struct device_attribute *dev_attr,
- char *buf)
+static ssize_t class_id_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ return sprintf(buf, "{%pUl}\n",
+ hv_dev->channel->offermsg.offer.if_type.b);
+}
+static DEVICE_ATTR_RO(class_id);
+
+static ssize_t device_id_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ return sprintf(buf, "{%pUl}\n",
+ hv_dev->channel->offermsg.offer.if_instance.b);
+}
+static DEVICE_ATTR_RO(device_id);
+
+static ssize_t modalias_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
{
struct hv_device *hv_dev = device_to_hv_device(dev);
- struct hv_device_info *device_info;
char alias_name[VMBUS_ALIAS_LEN + 1];
- int ret = 0;
- device_info = kzalloc(sizeof(struct hv_device_info), GFP_KERNEL);
- if (!device_info)
- return ret;
+ print_alias_name(hv_dev, alias_name);
+ return sprintf(buf, "vmbus:%s\n", alias_name);
+}
+static DEVICE_ATTR_RO(modalias);
- get_channel_info(hv_dev, device_info);
-
- if (!strcmp(dev_attr->attr.name, "class_id")) {
- ret = sprintf(buf, "{%pUl}\n", device_info->chn_type.b);
- } else if (!strcmp(dev_attr->attr.name, "device_id")) {
- ret = sprintf(buf, "{%pUl}\n", device_info->chn_instance.b);
- } else if (!strcmp(dev_attr->attr.name, "modalias")) {
- print_alias_name(hv_dev, alias_name);
- ret = sprintf(buf, "vmbus:%s\n", alias_name);
- } else if (!strcmp(dev_attr->attr.name, "state")) {
- ret = sprintf(buf, "%d\n", device_info->chn_state);
- } else if (!strcmp(dev_attr->attr.name, "id")) {
- ret = sprintf(buf, "%d\n", device_info->chn_id);
- } else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) {
- ret = sprintf(buf, "%d\n", device_info->outbound.int_mask);
- } else if (!strcmp(dev_attr->attr.name, "out_read_index")) {
- ret = sprintf(buf, "%d\n", device_info->outbound.read_idx);
- } else if (!strcmp(dev_attr->attr.name, "out_write_index")) {
- ret = sprintf(buf, "%d\n", device_info->outbound.write_idx);
- } else if (!strcmp(dev_attr->attr.name, "out_read_bytes_avail")) {
- ret = sprintf(buf, "%d\n",
- device_info->outbound.bytes_avail_toread);
- } else if (!strcmp(dev_attr->attr.name, "out_write_bytes_avail")) {
- ret = sprintf(buf, "%d\n",
- device_info->outbound.bytes_avail_towrite);
- } else if (!strcmp(dev_attr->attr.name, "in_intr_mask")) {
- ret = sprintf(buf, "%d\n", device_info->inbound.int_mask);
- } else if (!strcmp(dev_attr->attr.name, "in_read_index")) {
- ret = sprintf(buf, "%d\n", device_info->inbound.read_idx);
- } else if (!strcmp(dev_attr->attr.name, "in_write_index")) {
- ret = sprintf(buf, "%d\n", device_info->inbound.write_idx);
- } else if (!strcmp(dev_attr->attr.name, "in_read_bytes_avail")) {
- ret = sprintf(buf, "%d\n",
- device_info->inbound.bytes_avail_toread);
- } else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) {
- ret = sprintf(buf, "%d\n",
- device_info->inbound.bytes_avail_towrite);
- } else if (!strcmp(dev_attr->attr.name, "monitor_id")) {
- ret = sprintf(buf, "%d\n", device_info->monitor_id);
- } else if (!strcmp(dev_attr->attr.name, "server_monitor_pending")) {
- ret = sprintf(buf, "%d\n", device_info->server_monitor_pending);
- } else if (!strcmp(dev_attr->attr.name, "server_monitor_latency")) {
- ret = sprintf(buf, "%d\n", device_info->server_monitor_latency);
- } else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id")) {
- ret = sprintf(buf, "%d\n",
- device_info->server_monitor_conn_id);
- } else if (!strcmp(dev_attr->attr.name, "client_monitor_pending")) {
- ret = sprintf(buf, "%d\n", device_info->client_monitor_pending);
- } else if (!strcmp(dev_attr->attr.name, "client_monitor_latency")) {
- ret = sprintf(buf, "%d\n", device_info->client_monitor_latency);
- } else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id")) {
- ret = sprintf(buf, "%d\n",
- device_info->client_monitor_conn_id);
- }
+static ssize_t server_monitor_pending_show(struct device *dev,
+ struct device_attribute *dev_attr,
+ char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
- kfree(device_info);
- return ret;
+ if (!hv_dev->channel)
+ return -ENODEV;
+ return sprintf(buf, "%d\n",
+ channel_pending(hv_dev->channel,
+ vmbus_connection.monitor_pages[1]));
+}
+static DEVICE_ATTR_RO(server_monitor_pending);
+
+static ssize_t client_monitor_pending_show(struct device *dev,
+ struct device_attribute *dev_attr,
+ char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ return sprintf(buf, "%d\n",
+ channel_pending(hv_dev->channel,
+ vmbus_connection.monitor_pages[1]));
+}
+static DEVICE_ATTR_RO(client_monitor_pending);
+
+static ssize_t server_monitor_latency_show(struct device *dev,
+ struct device_attribute *dev_attr,
+ char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ return sprintf(buf, "%d\n",
+ channel_latency(hv_dev->channel,
+ vmbus_connection.monitor_pages[0]));
+}
+static DEVICE_ATTR_RO(server_monitor_latency);
+
+static ssize_t client_monitor_latency_show(struct device *dev,
+ struct device_attribute *dev_attr,
+ char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ return sprintf(buf, "%d\n",
+ channel_latency(hv_dev->channel,
+ vmbus_connection.monitor_pages[1]));
+}
+static DEVICE_ATTR_RO(client_monitor_latency);
+
+static ssize_t server_monitor_conn_id_show(struct device *dev,
+ struct device_attribute *dev_attr,
+ char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ return sprintf(buf, "%d\n",
+ channel_conn_id(hv_dev->channel,
+ vmbus_connection.monitor_pages[0]));
+}
+static DEVICE_ATTR_RO(server_monitor_conn_id);
+
+static ssize_t client_monitor_conn_id_show(struct device *dev,
+ struct device_attribute *dev_attr,
+ char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ return sprintf(buf, "%d\n",
+ channel_conn_id(hv_dev->channel,
+ vmbus_connection.monitor_pages[1]));
+}
+static DEVICE_ATTR_RO(client_monitor_conn_id);
+
+static ssize_t out_intr_mask_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+ struct hv_ring_buffer_debug_info outbound;
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+ return sprintf(buf, "%d\n", outbound.current_interrupt_mask);
+}
+static DEVICE_ATTR_RO(out_intr_mask);
+
+static ssize_t out_read_index_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+ struct hv_ring_buffer_debug_info outbound;
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+ return sprintf(buf, "%d\n", outbound.current_read_index);
+}
+static DEVICE_ATTR_RO(out_read_index);
+
+static ssize_t out_write_index_show(struct device *dev,
+ struct device_attribute *dev_attr,
+ char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+ struct hv_ring_buffer_debug_info outbound;
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+ return sprintf(buf, "%d\n", outbound.current_write_index);
+}
+static DEVICE_ATTR_RO(out_write_index);
+
+static ssize_t out_read_bytes_avail_show(struct device *dev,
+ struct device_attribute *dev_attr,
+ char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+ struct hv_ring_buffer_debug_info outbound;
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+ return sprintf(buf, "%d\n", outbound.bytes_avail_toread);
}
+static DEVICE_ATTR_RO(out_read_bytes_avail);
+
+static ssize_t out_write_bytes_avail_show(struct device *dev,
+ struct device_attribute *dev_attr,
+ char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+ struct hv_ring_buffer_debug_info outbound;
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+ return sprintf(buf, "%d\n", outbound.bytes_avail_towrite);
+}
+static DEVICE_ATTR_RO(out_write_bytes_avail);
+
+static ssize_t in_intr_mask_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+ struct hv_ring_buffer_debug_info inbound;
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+ return sprintf(buf, "%d\n", inbound.current_interrupt_mask);
+}
+static DEVICE_ATTR_RO(in_intr_mask);
+
+static ssize_t in_read_index_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+ struct hv_ring_buffer_debug_info inbound;
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+ return sprintf(buf, "%d\n", inbound.current_read_index);
+}
+static DEVICE_ATTR_RO(in_read_index);
+
+static ssize_t in_write_index_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+ struct hv_ring_buffer_debug_info inbound;
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+ return sprintf(buf, "%d\n", inbound.current_write_index);
+}
+static DEVICE_ATTR_RO(in_write_index);
+
+static ssize_t in_read_bytes_avail_show(struct device *dev,
+ struct device_attribute *dev_attr,
+ char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+ struct hv_ring_buffer_debug_info inbound;
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+ return sprintf(buf, "%d\n", inbound.bytes_avail_toread);
+}
+static DEVICE_ATTR_RO(in_read_bytes_avail);
+
+static ssize_t in_write_bytes_avail_show(struct device *dev,
+ struct device_attribute *dev_attr,
+ char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+ struct hv_ring_buffer_debug_info inbound;
+
+ if (!hv_dev->channel)
+ return -ENODEV;
+ hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+ return sprintf(buf, "%d\n", inbound.bytes_avail_towrite);
+}
+static DEVICE_ATTR_RO(in_write_bytes_avail);
/* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */
-static struct device_attribute vmbus_device_attrs[] = {
- __ATTR(id, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR(state, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR(class_id, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR(device_id, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR(monitor_id, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR(modalias, S_IRUGO, vmbus_show_device_attr, NULL),
-
- __ATTR(server_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR(server_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR(server_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL),
-
- __ATTR(client_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR(client_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR(client_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL),
-
- __ATTR(out_intr_mask, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR(out_read_index, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR(out_write_index, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR(out_read_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR(out_write_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
-
- __ATTR(in_intr_mask, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR(in_read_index, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR(in_write_index, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR(in_read_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR(in_write_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
- __ATTR_NULL
+static struct attribute *vmbus_attrs[] = {
+ &dev_attr_id.attr,
+ &dev_attr_state.attr,
+ &dev_attr_monitor_id.attr,
+ &dev_attr_class_id.attr,
+ &dev_attr_device_id.attr,
+ &dev_attr_modalias.attr,
+ &dev_attr_server_monitor_pending.attr,
+ &dev_attr_client_monitor_pending.attr,
+ &dev_attr_server_monitor_latency.attr,
+ &dev_attr_client_monitor_latency.attr,
+ &dev_attr_server_monitor_conn_id.attr,
+ &dev_attr_client_monitor_conn_id.attr,
+ &dev_attr_out_intr_mask.attr,
+ &dev_attr_out_read_index.attr,
+ &dev_attr_out_write_index.attr,
+ &dev_attr_out_read_bytes_avail.attr,
+ &dev_attr_out_write_bytes_avail.attr,
+ &dev_attr_in_intr_mask.attr,
+ &dev_attr_in_read_index.attr,
+ &dev_attr_in_write_index.attr,
+ &dev_attr_in_read_bytes_avail.attr,
+ &dev_attr_in_write_bytes_avail.attr,
+ NULL,
};
-
+ATTRIBUTE_GROUPS(vmbus);
/*
* vmbus_uevent - add uevent for our device
@@ -383,7 +557,7 @@ static struct bus_type hv_bus = {
.remove = vmbus_remove,
.probe = vmbus_probe,
.uevent = vmbus_uevent,
- .dev_attrs = vmbus_device_attrs,
+ .dev_groups = vmbus_groups,
};
static const char *driver_name = "hyperv";
diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c
index a9e3d0152c0b..8d40da314a8e 100644
--- a/drivers/hwmon/acpi_power_meter.c
+++ b/drivers/hwmon/acpi_power_meter.c
@@ -381,8 +381,10 @@ static ssize_t show_str(struct device *dev,
val = resource->oem_info;
break;
default:
- BUG();
+ WARN(1, "Implementation error: unexpected attribute index %d\n",
+ attr->index);
val = "";
+ break;
}
return sprintf(buf, "%s\n", val);
@@ -436,7 +438,9 @@ static ssize_t show_val(struct device *dev,
val = resource->trip[attr->index - 7] * 1000;
break;
default:
- BUG();
+ WARN(1, "Implementation error: unexpected attribute index %d\n",
+ attr->index);
+ break;
}
return sprintf(buf, "%llu\n", val);
@@ -855,7 +859,8 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
dev_info(&device->dev, "Capping in progress.\n");
break;
default:
- BUG();
+ WARN(1, "Unexpected event %d\n", event);
+ break;
}
mutex_unlock(&resource->lock);
@@ -991,7 +996,7 @@ static int __init acpi_power_meter_init(void)
result = acpi_bus_register_driver(&acpi_power_meter_driver);
if (result < 0)
- return -ENODEV;
+ return result;
return 0;
}
diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c
index 751b1f0264a4..04c08c2f79b8 100644
--- a/drivers/hwmon/adcxx.c
+++ b/drivers/hwmon/adcxx.c
@@ -203,7 +203,6 @@ out_err:
for (i--; i >= 0; i--)
device_remove_file(&spi->dev, &ad_input[i].dev_attr);
- spi_set_drvdata(spi, NULL);
mutex_unlock(&adc->lock);
return status;
}
@@ -218,7 +217,6 @@ static int adcxx_remove(struct spi_device *spi)
for (i = 0; i < 3 + adc->channels; i++)
device_remove_file(&spi->dev, &ad_input[i].dev_attr);
- spi_set_drvdata(spi, NULL);
mutex_unlock(&adc->lock);
return 0;
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index 3a6d9ef1c16c..b3498acb9ab4 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -616,7 +616,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
data->gpio = gpio;
data->last_reading = jiffies;
- }; /* last_reading */
+ } /* last_reading */
if (!data->valid ||
time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) {
@@ -700,7 +700,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
}
data->last_config = jiffies;
- }; /* last_config */
+ } /* last_config */
data->valid = 1;
mutex_unlock(&data->update_lock);
@@ -1791,7 +1791,7 @@ static int adm1026_detect(struct i2c_client *client,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
/* We need to be able to do byte I/O */
return -ENODEV;
- };
+ }
/* Now, we do the remaining detection. */
diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c
index addb5a4d5064..562cc3881d33 100644
--- a/drivers/hwmon/adt7462.c
+++ b/drivers/hwmon/adt7462.c
@@ -700,7 +700,7 @@ static int find_trange_value(int trange)
if (trange_values[i] == trange)
return i;
- return -ENODEV;
+ return -EINVAL;
}
static struct adt7462_data *adt7462_update_device(struct device *dev)
@@ -1294,9 +1294,8 @@ static ssize_t set_pwm_tmax(struct device *dev,
/* trange = tmax - tmin */
tmin = (data->pwm_tmin[attr->index] - 64) * 1000;
trange_value = find_trange_value(trange - tmin);
-
if (trange_value < 0)
- return -EINVAL;
+ return trange_value;
temp = trange_value << ADT7462_PWM_RANGE_SHIFT;
temp |= data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK;
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 62c2e32e25ef..98814d12a604 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -525,16 +525,25 @@ static int applesmc_init_smcreg_try(void)
{
struct applesmc_registers *s = &smcreg;
bool left_light_sensor, right_light_sensor;
+ unsigned int count;
u8 tmp[1];
int ret;
if (s->init_complete)
return 0;
- ret = read_register_count(&s->key_count);
+ ret = read_register_count(&count);
if (ret)
return ret;
+ if (s->cache && s->key_count != count) {
+ pr_warn("key count changed from %d to %d\n",
+ s->key_count, count);
+ kfree(s->cache);
+ s->cache = NULL;
+ }
+ s->key_count = count;
+
if (!s->cache)
s->cache = kcalloc(s->key_count, sizeof(*s->cache), GFP_KERNEL);
if (!s->cache)
diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c
index 3ad9d849add2..8d9f2a0e8efe 100644
--- a/drivers/hwmon/asc7621.c
+++ b/drivers/hwmon/asc7621.c
@@ -138,7 +138,7 @@ static inline u8 read_byte(struct i2c_client *client, u8 reg)
dev_err(&client->dev,
"Unable to read from register 0x%02x.\n", reg);
return 0;
- };
+ }
return res & 0xff;
}
@@ -149,7 +149,7 @@ static inline int write_byte(struct i2c_client *client, u8 reg, u8 data)
dev_err(&client->dev,
"Unable to write value 0x%02x to register 0x%02x.\n",
data, reg);
- };
+ }
return res;
}
@@ -1030,7 +1030,7 @@ static struct asc7621_data *asc7621_update_device(struct device *dev)
}
}
data->last_high_reading = jiffies;
- }; /* last_reading */
+ } /* last_reading */
/* Read all the low priority registers. */
@@ -1044,7 +1044,7 @@ static struct asc7621_data *asc7621_update_device(struct device *dev)
}
}
data->last_low_reading = jiffies;
- }; /* last_reading */
+ } /* last_reading */
data->valid = 1;
@@ -1084,11 +1084,11 @@ static void asc7621_init_client(struct i2c_client *client)
dev_err(&client->dev,
"Client (%d,0x%02x) config is locked.\n",
i2c_adapter_id(client->adapter), client->addr);
- };
+ }
if (!(value & 0x04)) {
dev_err(&client->dev, "Client (%d,0x%02x) is not ready.\n",
i2c_adapter_id(client->adapter), client->addr);
- };
+ }
/*
* Start monitoring
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index aecb9ea7beb5..ddff02e3e66f 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -147,10 +147,9 @@ static ssize_t atxp1_storevcore(struct device *dev,
/* Calculate VID */
vid = vid_to_reg(vcore, data->vrm);
-
if (vid < 0) {
dev_err(dev, "VID calculation failed.\n");
- return -1;
+ return vid;
}
/*
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index a26ba7a17c2b..872d76744e30 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -120,7 +120,7 @@ static const u8 DS1621_REG_TEMP[3] = {
/* Each client has this additional data */
struct ds1621_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
@@ -151,10 +151,10 @@ static inline u16 DS1621_TEMP_TO_REG(long temp, u8 zbits)
return temp;
}
-static void ds1621_init_client(struct i2c_client *client)
+static void ds1621_init_client(struct ds1621_data *data,
+ struct i2c_client *client)
{
u8 conf, new_conf, sreg, resol;
- struct ds1621_data *data = i2c_get_clientdata(client);
new_conf = conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF);
/* switch to continuous conversion mode */
@@ -197,8 +197,8 @@ static void ds1621_init_client(struct i2c_client *client)
static struct ds1621_data *ds1621_update_client(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ds1621_data *data = i2c_get_clientdata(client);
+ struct ds1621_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 new_conf;
mutex_lock(&data->update_lock);
@@ -247,8 +247,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct i2c_client *client = to_i2c_client(dev);
- struct ds1621_data *data = i2c_get_clientdata(client);
+ struct ds1621_data *data = dev_get_drvdata(dev);
long val;
int err;
@@ -258,7 +257,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
mutex_lock(&data->update_lock);
data->temp[attr->index] = DS1621_TEMP_TO_REG(val, data->zbits);
- i2c_smbus_write_word_swapped(client, DS1621_REG_TEMP[attr->index],
+ i2c_smbus_write_word_swapped(data->client, DS1621_REG_TEMP[attr->index],
data->temp[attr->index]);
mutex_unlock(&data->update_lock);
return count;
@@ -282,16 +281,15 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *da,
static ssize_t show_convrate(struct device *dev, struct device_attribute *da,
char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ds1621_data *data = i2c_get_clientdata(client);
+ struct ds1621_data *data = dev_get_drvdata(dev);
return scnprintf(buf, PAGE_SIZE, "%hu\n", data->update_interval);
}
static ssize_t set_convrate(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ds1621_data *data = i2c_get_clientdata(client);
+ struct ds1621_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long convrate;
s32 err;
int resol = 0;
@@ -343,8 +341,7 @@ static umode_t ds1621_attribute_visible(struct kobject *kobj,
struct attribute *attr, int index)
{
struct device *dev = container_of(kobj, struct device, kobj);
- struct i2c_client *client = to_i2c_client(dev);
- struct ds1621_data *data = i2c_get_clientdata(client);
+ struct ds1621_data *data = dev_get_drvdata(dev);
if (attr == &dev_attr_update_interval.attr)
if (data->kind == ds1621 || data->kind == ds1625)
@@ -357,52 +354,31 @@ static const struct attribute_group ds1621_group = {
.attrs = ds1621_attributes,
.is_visible = ds1621_attribute_visible
};
+__ATTRIBUTE_GROUPS(ds1621);
static int ds1621_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct ds1621_data *data;
- int err;
+ struct device *hwmon_dev;
data = devm_kzalloc(&client->dev, sizeof(struct ds1621_data),
GFP_KERNEL);
if (!data)
return -ENOMEM;
- i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
data->kind = id->driver_data;
+ data->client = client;
/* Initialize the DS1621 chip */
- ds1621_init_client(client);
-
- /* Register sysfs hooks */
- err = sysfs_create_group(&client->dev.kobj, &ds1621_group);
- if (err)
- return err;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove_files;
- }
-
- return 0;
-
- exit_remove_files:
- sysfs_remove_group(&client->dev.kobj, &ds1621_group);
- return err;
-}
-
-static int ds1621_remove(struct i2c_client *client)
-{
- struct ds1621_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &ds1621_group);
+ ds1621_init_client(data, client);
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
+ client->name, data,
+ ds1621_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct i2c_device_id ds1621_id[] = {
@@ -422,7 +398,6 @@ static struct i2c_driver ds1621_driver = {
.name = "ds1621",
},
.probe = ds1621_probe,
- .remove = ds1621_remove,
.id_table = ds1621_id,
};
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index 31b221eeee6c..03d8592810bf 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -2420,7 +2420,6 @@ static int f71882fg_probe(struct platform_device *pdev)
exit_unregister_sysfs:
f71882fg_remove(pdev); /* Will unregister the sysfs files for us */
return err; /* f71882fg_remove() also frees our data */
- return err;
}
static int f71882fg_remove(struct platform_device *pdev)
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index a837b94977f4..80c42bea90ed 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -275,7 +275,7 @@ static bool duty_mode_enabled(u8 pwm_enable)
case 3: /* Manual, speed mode */
return false;
default:
- BUG();
+ WARN(1, "Unexpected pwm_enable value %d\n", pwm_enable);
return true;
}
}
@@ -291,7 +291,7 @@ static bool auto_mode_enabled(u8 pwm_enable)
case 4: /* Auto, duty mode */
return true;
default:
- BUG();
+ WARN(1, "Unexpected pwm_enable value %d\n", pwm_enable);
return false;
}
}
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
index b7d6a5704eb2..d5148c85ec5f 100644
--- a/drivers/hwmon/gpio-fan.c
+++ b/drivers/hwmon/gpio-fan.c
@@ -169,7 +169,7 @@ static int get_fan_speed_index(struct gpio_fan_data *fan_data)
dev_warn(&fan_data->pdev->dev,
"missing speed array entry for GPIO value 0x%x\n", ctrl_val);
- return -EINVAL;
+ return -ENODEV;
}
static int rpm_to_speed_index(struct gpio_fan_data *fan_data, int rpm)
@@ -309,12 +309,6 @@ exit_unlock:
return ret;
}
-static ssize_t show_name(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "gpio-fan\n");
-}
-
static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm);
static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
show_pwm_enable, set_pwm_enable);
@@ -324,26 +318,23 @@ static DEVICE_ATTR(fan1_max, S_IRUGO, show_rpm_max, NULL);
static DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, NULL);
static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, show_rpm, set_rpm);
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-
static umode_t gpio_fan_is_visible(struct kobject *kobj,
struct attribute *attr, int index)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct gpio_fan_data *data = dev_get_drvdata(dev);
- if (index == 1 && !data->alarm)
+ if (index == 0 && !data->alarm)
return 0;
- if (index > 1 && !data->ctrl)
+ if (index > 0 && !data->ctrl)
return 0;
return attr->mode;
}
static struct attribute *gpio_fan_attributes[] = {
- &dev_attr_name.attr,
- &dev_attr_fan1_alarm.attr, /* 1 */
- &dev_attr_pwm1.attr, /* 2 */
+ &dev_attr_fan1_alarm.attr, /* 0 */
+ &dev_attr_pwm1.attr, /* 1 */
&dev_attr_pwm1_enable.attr,
&dev_attr_pwm1_mode.attr,
&dev_attr_fan1_input.attr,
@@ -358,6 +349,11 @@ static const struct attribute_group gpio_fan_group = {
.is_visible = gpio_fan_is_visible,
};
+static const struct attribute_group *gpio_fan_groups[] = {
+ &gpio_fan_group,
+ NULL
+};
+
static int fan_ctrl_init(struct gpio_fan_data *fan_data,
struct gpio_fan_platform_data *pdata)
{
@@ -384,7 +380,7 @@ static int fan_ctrl_init(struct gpio_fan_data *fan_data,
fan_data->pwm_enable = true; /* Enable manual fan speed control. */
fan_data->speed_index = get_fan_speed_index(fan_data);
if (fan_data->speed_index < 0)
- return -ENODEV;
+ return fan_data->speed_index;
return 0;
}
@@ -539,24 +535,16 @@ static int gpio_fan_probe(struct platform_device *pdev)
return err;
}
- err = sysfs_create_group(&pdev->dev.kobj, &gpio_fan_group);
- if (err)
- return err;
-
/* Make this driver part of hwmon class. */
- fan_data->hwmon_dev = hwmon_device_register(&pdev->dev);
- if (IS_ERR(fan_data->hwmon_dev)) {
- err = PTR_ERR(fan_data->hwmon_dev);
- goto err_remove;
- }
+ fan_data->hwmon_dev = hwmon_device_register_with_groups(&pdev->dev,
+ "gpio-fan", fan_data,
+ gpio_fan_groups);
+ if (IS_ERR(fan_data->hwmon_dev))
+ return PTR_ERR(fan_data->hwmon_dev);
dev_info(&pdev->dev, "GPIO fan initialized\n");
return 0;
-
-err_remove:
- sysfs_remove_group(&pdev->dev.kobj, &gpio_fan_group);
- return err;
}
static int gpio_fan_remove(struct platform_device *pdev)
@@ -564,7 +552,6 @@ static int gpio_fan_remove(struct platform_device *pdev)
struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
hwmon_device_unregister(fan_data->hwmon_dev);
- sysfs_remove_group(&pdev->dev.kobj, &gpio_fan_group);
return 0;
}
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 646314f7c839..e176a43af63d 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/device.h>
#include <linux/err.h>
+#include <linux/slab.h>
#include <linux/kdev_t.h>
#include <linux/idr.h>
#include <linux/hwmon.h>
@@ -25,35 +26,122 @@
#define HWMON_ID_PREFIX "hwmon"
#define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
-static struct class *hwmon_class;
+struct hwmon_device {
+ const char *name;
+ struct device dev;
+};
+#define to_hwmon_device(d) container_of(d, struct hwmon_device, dev)
+
+static ssize_t
+show_name(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", to_hwmon_device(dev)->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static struct attribute *hwmon_dev_attrs[] = {
+ &dev_attr_name.attr,
+ NULL
+};
+
+static umode_t hwmon_dev_name_is_visible(struct kobject *kobj,
+ struct attribute *attr, int n)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+
+ if (to_hwmon_device(dev)->name == NULL)
+ return 0;
+
+ return attr->mode;
+}
+
+static struct attribute_group hwmon_dev_attr_group = {
+ .attrs = hwmon_dev_attrs,
+ .is_visible = hwmon_dev_name_is_visible,
+};
+
+static const struct attribute_group *hwmon_dev_attr_groups[] = {
+ &hwmon_dev_attr_group,
+ NULL
+};
+
+static void hwmon_dev_release(struct device *dev)
+{
+ kfree(to_hwmon_device(dev));
+}
+
+static struct class hwmon_class = {
+ .name = "hwmon",
+ .owner = THIS_MODULE,
+ .dev_groups = hwmon_dev_attr_groups,
+ .dev_release = hwmon_dev_release,
+};
static DEFINE_IDA(hwmon_ida);
/**
- * hwmon_device_register - register w/ hwmon
- * @dev: the device to register
+ * hwmon_device_register_with_groups - register w/ hwmon
+ * @dev: the parent device
+ * @name: hwmon name attribute
+ * @drvdata: driver data to attach to created device
+ * @groups: List of attribute groups to create
*
* hwmon_device_unregister() must be called when the device is no
* longer needed.
*
* Returns the pointer to the new device.
*/
-struct device *hwmon_device_register(struct device *dev)
+struct device *
+hwmon_device_register_with_groups(struct device *dev, const char *name,
+ void *drvdata,
+ const struct attribute_group **groups)
{
- struct device *hwdev;
- int id;
+ struct hwmon_device *hwdev;
+ int err, id;
id = ida_simple_get(&hwmon_ida, 0, 0, GFP_KERNEL);
if (id < 0)
return ERR_PTR(id);
- hwdev = device_create(hwmon_class, dev, MKDEV(0, 0), NULL,
- HWMON_ID_FORMAT, id);
+ hwdev = kzalloc(sizeof(*hwdev), GFP_KERNEL);
+ if (hwdev == NULL) {
+ err = -ENOMEM;
+ goto ida_remove;
+ }
- if (IS_ERR(hwdev))
- ida_simple_remove(&hwmon_ida, id);
+ hwdev->name = name;
+ hwdev->dev.class = &hwmon_class;
+ hwdev->dev.parent = dev;
+ hwdev->dev.groups = groups;
+ hwdev->dev.of_node = dev ? dev->of_node : NULL;
+ dev_set_drvdata(&hwdev->dev, drvdata);
+ dev_set_name(&hwdev->dev, HWMON_ID_FORMAT, id);
+ err = device_register(&hwdev->dev);
+ if (err)
+ goto free;
- return hwdev;
+ return &hwdev->dev;
+
+free:
+ kfree(hwdev);
+ida_remove:
+ ida_simple_remove(&hwmon_ida, id);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(hwmon_device_register_with_groups);
+
+/**
+ * hwmon_device_register - register w/ hwmon
+ * @dev: the device to register
+ *
+ * hwmon_device_unregister() must be called when the device is no
+ * longer needed.
+ *
+ * Returns the pointer to the new device.
+ */
+struct device *hwmon_device_register(struct device *dev)
+{
+ return hwmon_device_register_with_groups(dev, NULL, NULL, NULL);
}
EXPORT_SYMBOL_GPL(hwmon_device_register);
@@ -75,6 +163,69 @@ void hwmon_device_unregister(struct device *dev)
}
EXPORT_SYMBOL_GPL(hwmon_device_unregister);
+static void devm_hwmon_release(struct device *dev, void *res)
+{
+ struct device *hwdev = *(struct device **)res;
+
+ hwmon_device_unregister(hwdev);
+}
+
+/**
+ * devm_hwmon_device_register_with_groups - register w/ hwmon
+ * @dev: the parent device
+ * @name: hwmon name attribute
+ * @drvdata: driver data to attach to created device
+ * @groups: List of attribute groups to create
+ *
+ * Returns the pointer to the new device. The new device is automatically
+ * unregistered with the parent device.
+ */
+struct device *
+devm_hwmon_device_register_with_groups(struct device *dev, const char *name,
+ void *drvdata,
+ const struct attribute_group **groups)
+{
+ struct device **ptr, *hwdev;
+
+ if (!dev)
+ return ERR_PTR(-EINVAL);
+
+ ptr = devres_alloc(devm_hwmon_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ hwdev = hwmon_device_register_with_groups(dev, name, drvdata, groups);
+ if (IS_ERR(hwdev))
+ goto error;
+
+ *ptr = hwdev;
+ devres_add(dev, ptr);
+ return hwdev;
+
+error:
+ devres_free(ptr);
+ return hwdev;
+}
+EXPORT_SYMBOL_GPL(devm_hwmon_device_register_with_groups);
+
+static int devm_hwmon_match(struct device *dev, void *res, void *data)
+{
+ struct device **hwdev = res;
+
+ return *hwdev == data;
+}
+
+/**
+ * devm_hwmon_device_unregister - removes a previously registered hwmon device
+ *
+ * @dev: the parent device of the device to unregister
+ */
+void devm_hwmon_device_unregister(struct device *dev)
+{
+ WARN_ON(devres_release(dev, devm_hwmon_release, devm_hwmon_match, dev));
+}
+EXPORT_SYMBOL_GPL(devm_hwmon_device_unregister);
+
static void __init hwmon_pci_quirks(void)
{
#if defined CONFIG_X86 && defined CONFIG_PCI
@@ -105,19 +256,21 @@ static void __init hwmon_pci_quirks(void)
static int __init hwmon_init(void)
{
+ int err;
+
hwmon_pci_quirks();
- hwmon_class = class_create(THIS_MODULE, "hwmon");
- if (IS_ERR(hwmon_class)) {
- pr_err("couldn't create sysfs class\n");
- return PTR_ERR(hwmon_class);
+ err = class_register(&hwmon_class);
+ if (err) {
+ pr_err("couldn't register hwmon sysfs class\n");
+ return err;
}
return 0;
}
static void __exit hwmon_exit(void)
{
- class_destroy(hwmon_class);
+ class_unregister(&hwmon_class);
}
subsys_initcall(hwmon_init);
diff --git a/drivers/hwmon/ina209.c b/drivers/hwmon/ina209.c
index c6fdd5bd395e..5378fdefc1f7 100644
--- a/drivers/hwmon/ina209.c
+++ b/drivers/hwmon/ina209.c
@@ -63,7 +63,7 @@
#define INA209_SHUNT_DEFAULT 10000 /* uOhm */
struct ina209_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex update_lock;
bool valid;
@@ -78,8 +78,8 @@ struct ina209_data {
static struct ina209_data *ina209_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ina209_data *data = i2c_get_clientdata(client);
+ struct ina209_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
struct ina209_data *ret = data;
s32 val;
int i;
@@ -234,7 +234,6 @@ static ssize_t ina209_set_interval(struct device *dev,
struct device_attribute *da,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
struct ina209_data *data = ina209_update_device(dev);
long val;
u16 regval;
@@ -250,7 +249,8 @@ static ssize_t ina209_set_interval(struct device *dev,
mutex_lock(&data->update_lock);
regval = ina209_reg_from_interval(data->regs[INA209_CONFIGURATION],
val);
- i2c_smbus_write_word_swapped(client, INA209_CONFIGURATION, regval);
+ i2c_smbus_write_word_swapped(data->client, INA209_CONFIGURATION,
+ regval);
data->regs[INA209_CONFIGURATION] = regval;
data->update_interval = ina209_interval_from_reg(regval);
mutex_unlock(&data->update_lock);
@@ -260,8 +260,7 @@ static ssize_t ina209_set_interval(struct device *dev,
static ssize_t ina209_show_interval(struct device *dev,
struct device_attribute *da, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ina209_data *data = i2c_get_clientdata(client);
+ struct ina209_data *data = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%d\n", data->update_interval);
}
@@ -285,9 +284,9 @@ static ssize_t ina209_reset_history(struct device *dev,
const char *buf,
size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ina209_data *data = i2c_get_clientdata(client);
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct ina209_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u32 mask = attr->index;
long val;
int i, ret;
@@ -312,7 +311,6 @@ static ssize_t ina209_set_value(struct device *dev,
const char *buf,
size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
struct ina209_data *data = ina209_update_device(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
int reg = attr->index;
@@ -332,7 +330,7 @@ static ssize_t ina209_set_value(struct device *dev,
count = ret;
goto abort;
}
- i2c_smbus_write_word_swapped(client, reg, ret);
+ i2c_smbus_write_word_swapped(data->client, reg, ret);
data->regs[reg] = ret;
abort:
mutex_unlock(&data->update_lock);
@@ -457,7 +455,7 @@ static SENSOR_DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR,
* Finally, construct an array of pointers to members of the above objects,
* as required for sysfs_create_group()
*/
-static struct attribute *ina209_attributes[] = {
+static struct attribute *ina209_attrs[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in0_input_highest.dev_attr.attr,
&sensor_dev_attr_in0_input_lowest.dev_attr.attr,
@@ -498,10 +496,7 @@ static struct attribute *ina209_attributes[] = {
NULL,
};
-
-static const struct attribute_group ina209_group = {
- .attrs = ina209_attributes,
-};
+ATTRIBUTE_GROUPS(ina209);
static void ina209_restore_conf(struct i2c_client *client,
struct ina209_data *data)
@@ -565,6 +560,7 @@ static int ina209_probe(struct i2c_client *client,
{
struct i2c_adapter *adapter = client->adapter;
struct ina209_data *data;
+ struct device *hwmon_dev;
int ret;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
@@ -575,27 +571,23 @@ static int ina209_probe(struct i2c_client *client,
return -ENOMEM;
i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->update_lock);
ret = ina209_init_client(client, data);
if (ret)
return ret;
- /* Register sysfs hooks */
- ret = sysfs_create_group(&client->dev.kobj, &ina209_group);
- if (ret)
+ hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
+ client->name,
+ data, ina209_groups);
+ if (IS_ERR(hwmon_dev)) {
+ ret = PTR_ERR(hwmon_dev);
goto out_restore_conf;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- ret = PTR_ERR(data->hwmon_dev);
- goto out_hwmon_device_register;
}
return 0;
-out_hwmon_device_register:
- sysfs_remove_group(&client->dev.kobj, &ina209_group);
out_restore_conf:
ina209_restore_conf(client, data);
return ret;
@@ -605,8 +597,6 @@ static int ina209_remove(struct i2c_client *client)
{
struct ina209_data *data = i2c_get_clientdata(client);
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &ina209_group);
ina209_restore_conf(client, data);
return 0;
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
index 70a39a8ac016..93d26e8af3e2 100644
--- a/drivers/hwmon/ina2xx.c
+++ b/drivers/hwmon/ina2xx.c
@@ -78,7 +78,7 @@ struct ina2xx_config {
};
struct ina2xx_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
const struct ina2xx_config *config;
struct mutex update_lock;
@@ -112,8 +112,8 @@ static const struct ina2xx_config ina2xx_config[] = {
static struct ina2xx_data *ina2xx_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ina2xx_data *data = i2c_get_clientdata(client);
+ struct ina2xx_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
struct ina2xx_data *ret = data;
mutex_lock(&data->update_lock);
@@ -203,41 +203,39 @@ static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ina2xx_show_value, NULL,
INA2XX_POWER);
/* pointers to created device attributes */
-static struct attribute *ina2xx_attributes[] = {
+static struct attribute *ina2xx_attrs[] = {
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
&sensor_dev_attr_curr1_input.dev_attr.attr,
&sensor_dev_attr_power1_input.dev_attr.attr,
NULL,
};
-
-static const struct attribute_group ina2xx_group = {
- .attrs = ina2xx_attributes,
-};
+ATTRIBUTE_GROUPS(ina2xx);
static int ina2xx_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = client->adapter;
- struct ina2xx_data *data;
struct ina2xx_platform_data *pdata;
- int ret;
- u32 val;
+ struct device *dev = &client->dev;
+ struct ina2xx_data *data;
+ struct device *hwmon_dev;
long shunt = 10000; /* default shunt value 10mOhms */
+ u32 val;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
return -ENODEV;
- data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- if (dev_get_platdata(&client->dev)) {
- pdata = dev_get_platdata(&client->dev);
+ if (dev_get_platdata(dev)) {
+ pdata = dev_get_platdata(dev);
shunt = pdata->shunt_uohms;
- } else if (!of_property_read_u32(client->dev.of_node,
- "shunt-resistor", &val)) {
- shunt = val;
+ } else if (!of_property_read_u32(dev->of_node,
+ "shunt-resistor", &val)) {
+ shunt = val;
}
if (shunt <= 0)
@@ -255,37 +253,18 @@ static int ina2xx_probe(struct i2c_client *client,
i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION,
data->config->calibration_factor / shunt);
- i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->update_lock);
- ret = sysfs_create_group(&client->dev.kobj, &ina2xx_group);
- if (ret)
- return ret;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- ret = PTR_ERR(data->hwmon_dev);
- goto out_err_hwmon;
- }
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data, ina2xx_groups);
+ if (IS_ERR(hwmon_dev))
+ return PTR_ERR(hwmon_dev);
- dev_info(&client->dev, "power monitor %s (Rshunt = %li uOhm)\n",
+ dev_info(dev, "power monitor %s (Rshunt = %li uOhm)\n",
id->name, shunt);
return 0;
-
-out_err_hwmon:
- sysfs_remove_group(&client->dev.kobj, &ina2xx_group);
- return ret;
-}
-
-static int ina2xx_remove(struct i2c_client *client)
-{
- struct ina2xx_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &ina2xx_group);
-
- return 0;
}
static const struct i2c_device_id ina2xx_id[] = {
@@ -302,7 +281,6 @@ static struct i2c_driver ina2xx_driver = {
.name = "ina2xx",
},
.probe = ina2xx_probe,
- .remove = ina2xx_remove,
.id_table = ina2xx_id,
};
diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c
index 4a58f130fd4e..6013611e4f21 100644
--- a/drivers/hwmon/jc42.c
+++ b/drivers/hwmon/jc42.c
@@ -163,7 +163,7 @@ static struct jc42_chips jc42_chips[] = {
/* Each client has this additional data */
struct jc42_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex update_lock; /* protect register access */
bool extended; /* true if extended range supported */
bool valid;
@@ -193,21 +193,21 @@ MODULE_DEVICE_TABLE(i2c, jc42_id);
static int jc42_suspend(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct jc42_data *data = i2c_get_clientdata(client);
+ struct jc42_data *data = dev_get_drvdata(dev);
data->config |= JC42_CFG_SHUTDOWN;
- i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, data->config);
+ i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG,
+ data->config);
return 0;
}
static int jc42_resume(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct jc42_data *data = i2c_get_clientdata(client);
+ struct jc42_data *data = dev_get_drvdata(dev);
data->config &= ~JC42_CFG_SHUTDOWN;
- i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, data->config);
+ i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG,
+ data->config);
return 0;
}
@@ -317,15 +317,14 @@ static ssize_t set_##value(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct jc42_data *data = i2c_get_clientdata(client); \
+ struct jc42_data *data = dev_get_drvdata(dev); \
int err, ret = count; \
long val; \
- if (kstrtol(buf, 10, &val) < 0) \
+ if (kstrtol(buf, 10, &val) < 0) \
return -EINVAL; \
mutex_lock(&data->update_lock); \
data->value = jc42_temp_to_reg(val, data->extended); \
- err = i2c_smbus_write_word_swapped(client, reg, data->value); \
+ err = i2c_smbus_write_word_swapped(data->client, reg, data->value); \
if (err < 0) \
ret = err; \
mutex_unlock(&data->update_lock); \
@@ -344,8 +343,7 @@ static ssize_t set_temp_crit_hyst(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct jc42_data *data = i2c_get_clientdata(client);
+ struct jc42_data *data = dev_get_drvdata(dev);
unsigned long val;
int diff, hyst;
int err;
@@ -368,7 +366,7 @@ static ssize_t set_temp_crit_hyst(struct device *dev,
mutex_lock(&data->update_lock);
data->config = (data->config & ~JC42_CFG_HYST_MASK)
| (hyst << JC42_CFG_HYST_SHIFT);
- err = i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG,
+ err = i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG,
data->config);
if (err < 0)
ret = err;
@@ -430,8 +428,7 @@ static umode_t jc42_attribute_mode(struct kobject *kobj,
struct attribute *attr, int index)
{
struct device *dev = container_of(kobj, struct device, kobj);
- struct i2c_client *client = to_i2c_client(dev);
- struct jc42_data *data = i2c_get_clientdata(client);
+ struct jc42_data *data = dev_get_drvdata(dev);
unsigned int config = data->config;
bool readonly;
@@ -452,6 +449,7 @@ static const struct attribute_group jc42_group = {
.attrs = jc42_attributes,
.is_visible = jc42_attribute_mode,
};
+__ATTRIBUTE_GROUPS(jc42);
/* Return 0 if detection is successful, -ENODEV otherwise */
static int jc42_detect(struct i2c_client *client, struct i2c_board_info *info)
@@ -487,14 +485,16 @@ static int jc42_detect(struct i2c_client *client, struct i2c_board_info *info)
static int jc42_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
- struct jc42_data *data;
- int config, cap, err;
struct device *dev = &client->dev;
+ struct device *hwmon_dev;
+ struct jc42_data *data;
+ int config, cap;
data = devm_kzalloc(dev, sizeof(struct jc42_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
+ data->client = client;
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
@@ -515,29 +515,15 @@ static int jc42_probe(struct i2c_client *client, const struct i2c_device_id *id)
}
data->config = config;
- /* Register sysfs hooks */
- err = sysfs_create_group(&dev->kobj, &jc42_group);
- if (err)
- return err;
-
- data->hwmon_dev = hwmon_device_register(dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- return 0;
-
-exit_remove:
- sysfs_remove_group(&dev->kobj, &jc42_group);
- return err;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data,
+ jc42_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static int jc42_remove(struct i2c_client *client)
{
struct jc42_data *data = i2c_get_clientdata(client);
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &jc42_group);
/* Restore original configuration except hysteresis */
if ((data->config & ~JC42_CFG_HYST_MASK) !=
@@ -553,8 +539,8 @@ static int jc42_remove(struct i2c_client *client)
static struct jc42_data *jc42_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct jc42_data *data = i2c_get_clientdata(client);
+ struct jc42_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
struct jc42_data *ret = data;
int val;
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
index 016efa26ba7c..505a59e100b0 100644
--- a/drivers/hwmon/lm70.c
+++ b/drivers/hwmon/lm70.c
@@ -174,7 +174,6 @@ out_dev_reg_failed:
out_dev_create_file_failed:
device_remove_file(&spi->dev, &dev_attr_temp1_input);
out_dev_create_temp_file_failed:
- spi_set_drvdata(spi, NULL);
return status;
}
@@ -185,7 +184,6 @@ static int lm70_remove(struct spi_device *spi)
hwmon_device_unregister(p_lm70->hwmon_dev);
device_remove_file(&spi->dev, &dev_attr_temp1_input);
device_remove_file(&spi->dev, &dev_attr_name);
- spi_set_drvdata(spi, NULL);
return 0;
}
diff --git a/drivers/hwmon/lm73.c b/drivers/hwmon/lm73.c
index 9bde9644b102..9653bb870a47 100644
--- a/drivers/hwmon/lm73.c
+++ b/drivers/hwmon/lm73.c
@@ -55,7 +55,7 @@ static const unsigned short lm73_convrates[] = {
};
struct lm73_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex lock;
u8 ctrl; /* control register value */
};
@@ -66,7 +66,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct i2c_client *client = to_i2c_client(dev);
+ struct lm73_data *data = dev_get_drvdata(dev);
long temp;
short value;
s32 err;
@@ -77,7 +77,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
/* Write value */
value = clamp_val(temp / 250, LM73_TEMP_MIN, LM73_TEMP_MAX) << 5;
- err = i2c_smbus_write_word_swapped(client, attr->index, value);
+ err = i2c_smbus_write_word_swapped(data->client, attr->index, value);
return (err < 0) ? err : count;
}
@@ -85,10 +85,10 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct i2c_client *client = to_i2c_client(dev);
+ struct lm73_data *data = dev_get_drvdata(dev);
int temp;
- s32 err = i2c_smbus_read_word_swapped(client, attr->index);
+ s32 err = i2c_smbus_read_word_swapped(data->client, attr->index);
if (err < 0)
return err;
@@ -101,8 +101,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da,
static ssize_t set_convrate(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm73_data *data = i2c_get_clientdata(client);
+ struct lm73_data *data = dev_get_drvdata(dev);
unsigned long convrate;
s32 err;
int res = 0;
@@ -124,7 +123,8 @@ static ssize_t set_convrate(struct device *dev, struct device_attribute *da,
mutex_lock(&data->lock);
data->ctrl &= LM73_CTRL_TO_MASK;
data->ctrl |= res << LM73_CTRL_RES_SHIFT;
- err = i2c_smbus_write_byte_data(client, LM73_REG_CTRL, data->ctrl);
+ err = i2c_smbus_write_byte_data(data->client, LM73_REG_CTRL,
+ data->ctrl);
mutex_unlock(&data->lock);
if (err < 0)
@@ -136,8 +136,7 @@ static ssize_t set_convrate(struct device *dev, struct device_attribute *da,
static ssize_t show_convrate(struct device *dev, struct device_attribute *da,
char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm73_data *data = i2c_get_clientdata(client);
+ struct lm73_data *data = dev_get_drvdata(dev);
int res;
res = (data->ctrl & LM73_CTRL_RES_MASK) >> LM73_CTRL_RES_SHIFT;
@@ -147,13 +146,12 @@ static ssize_t show_convrate(struct device *dev, struct device_attribute *da,
static ssize_t show_maxmin_alarm(struct device *dev,
struct device_attribute *da, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct lm73_data *data = i2c_get_clientdata(client);
+ struct lm73_data *data = dev_get_drvdata(dev);
s32 ctrl;
mutex_lock(&data->lock);
- ctrl = i2c_smbus_read_byte_data(client, LM73_REG_CTRL);
+ ctrl = i2c_smbus_read_byte_data(data->client, LM73_REG_CTRL);
if (ctrl < 0)
goto abort;
data->ctrl = ctrl;
@@ -183,7 +181,7 @@ static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO,
static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO,
show_maxmin_alarm, NULL, LM73_CTRL_LO_SHIFT);
-static struct attribute *lm73_attributes[] = {
+static struct attribute *lm73_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp1_min.dev_attr.attr,
@@ -192,10 +190,7 @@ static struct attribute *lm73_attributes[] = {
&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
NULL
};
-
-static const struct attribute_group lm73_group = {
- .attrs = lm73_attributes,
-};
+ATTRIBUTE_GROUPS(lm73);
/*-----------------------------------------------------------------------*/
@@ -204,16 +199,16 @@ static const struct attribute_group lm73_group = {
static int
lm73_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
- int status;
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
struct lm73_data *data;
int ctrl;
- data = devm_kzalloc(&client->dev, sizeof(struct lm73_data),
- GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct lm73_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->lock);
ctrl = i2c_smbus_read_byte_data(client, LM73_REG_CTRL);
@@ -221,33 +216,13 @@ lm73_probe(struct i2c_client *client, const struct i2c_device_id *id)
return ctrl;
data->ctrl = ctrl;
- /* Register sysfs hooks */
- status = sysfs_create_group(&client->dev.kobj, &lm73_group);
- if (status)
- return status;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- status = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data, lm73_groups);
+ if (IS_ERR(hwmon_dev))
+ return PTR_ERR(hwmon_dev);
- dev_info(&client->dev, "%s: sensor '%s'\n",
- dev_name(data->hwmon_dev), client->name);
-
- return 0;
-
-exit_remove:
- sysfs_remove_group(&client->dev.kobj, &lm73_group);
- return status;
-}
-
-static int lm73_remove(struct i2c_client *client)
-{
- struct lm73_data *data = i2c_get_clientdata(client);
+ dev_info(dev, "sensor '%s'\n", client->name);
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &lm73_group);
return 0;
}
@@ -300,7 +275,6 @@ static struct i2c_driver lm73_driver = {
.name = "lm73",
},
.probe = lm73_probe,
- .remove = lm73_remove,
.id_table = lm73_ids,
.detect = lm73_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/lm95234.c b/drivers/hwmon/lm95234.c
index 307c9eaeeb9f..411202bdaf6b 100644
--- a/drivers/hwmon/lm95234.c
+++ b/drivers/hwmon/lm95234.c
@@ -57,7 +57,7 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4d, 0x4e, I2C_CLIENT_END };
/* Client data (each client gets its own) */
struct lm95234_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex update_lock;
unsigned long last_updated, interval; /* in jiffies */
bool valid; /* false until following fields are valid */
@@ -114,9 +114,9 @@ static u16 update_intervals[] = { 143, 364, 1000, 2500 };
/* Fill value cache. Must be called with update lock held. */
-static int lm95234_fill_cache(struct i2c_client *client)
+static int lm95234_fill_cache(struct lm95234_data *data,
+ struct i2c_client *client)
{
- struct lm95234_data *data = i2c_get_clientdata(client);
int i, ret;
ret = i2c_smbus_read_byte_data(client, LM95234_REG_CONVRATE);
@@ -157,9 +157,9 @@ static int lm95234_fill_cache(struct i2c_client *client)
return 0;
}
-static int lm95234_update_device(struct i2c_client *client,
- struct lm95234_data *data)
+static int lm95234_update_device(struct lm95234_data *data)
{
+ struct i2c_client *client = data->client;
int ret;
mutex_lock(&data->update_lock);
@@ -169,7 +169,7 @@ static int lm95234_update_device(struct i2c_client *client,
int i;
if (!data->valid) {
- ret = lm95234_fill_cache(client);
+ ret = lm95234_fill_cache(data, client);
if (ret < 0)
goto abort;
}
@@ -209,10 +209,9 @@ abort:
static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm95234_data *data = i2c_get_clientdata(client);
+ struct lm95234_data *data = dev_get_drvdata(dev);
int index = to_sensor_dev_attr(attr)->index;
- int ret = lm95234_update_device(client, data);
+ int ret = lm95234_update_device(data);
if (ret)
return ret;
@@ -224,10 +223,9 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
static ssize_t show_alarm(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm95234_data *data = i2c_get_clientdata(client);
+ struct lm95234_data *data = dev_get_drvdata(dev);
u32 mask = to_sensor_dev_attr(attr)->index;
- int ret = lm95234_update_device(client, data);
+ int ret = lm95234_update_device(data);
if (ret)
return ret;
@@ -238,10 +236,9 @@ static ssize_t show_alarm(struct device *dev,
static ssize_t show_type(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm95234_data *data = i2c_get_clientdata(client);
+ struct lm95234_data *data = dev_get_drvdata(dev);
u8 mask = to_sensor_dev_attr(attr)->index;
- int ret = lm95234_update_device(client, data);
+ int ret = lm95234_update_device(data);
if (ret)
return ret;
@@ -252,11 +249,10 @@ static ssize_t show_type(struct device *dev, struct device_attribute *attr,
static ssize_t set_type(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm95234_data *data = i2c_get_clientdata(client);
+ struct lm95234_data *data = dev_get_drvdata(dev);
unsigned long val;
u8 mask = to_sensor_dev_attr(attr)->index;
- int ret = lm95234_update_device(client, data);
+ int ret = lm95234_update_device(data);
if (ret)
return ret;
@@ -274,7 +270,7 @@ static ssize_t set_type(struct device *dev, struct device_attribute *attr,
else
data->sensor_type &= ~mask;
data->valid = false;
- i2c_smbus_write_byte_data(client, LM95234_REG_REM_MODEL,
+ i2c_smbus_write_byte_data(data->client, LM95234_REG_REM_MODEL,
data->sensor_type);
mutex_unlock(&data->update_lock);
@@ -284,10 +280,9 @@ static ssize_t set_type(struct device *dev, struct device_attribute *attr,
static ssize_t show_tcrit2(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm95234_data *data = i2c_get_clientdata(client);
+ struct lm95234_data *data = dev_get_drvdata(dev);
int index = to_sensor_dev_attr(attr)->index;
- int ret = lm95234_update_device(client, data);
+ int ret = lm95234_update_device(data);
if (ret)
return ret;
@@ -298,11 +293,10 @@ static ssize_t show_tcrit2(struct device *dev, struct device_attribute *attr,
static ssize_t set_tcrit2(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm95234_data *data = i2c_get_clientdata(client);
+ struct lm95234_data *data = dev_get_drvdata(dev);
int index = to_sensor_dev_attr(attr)->index;
long val;
- int ret = lm95234_update_device(client, data);
+ int ret = lm95234_update_device(data);
if (ret)
return ret;
@@ -315,7 +309,7 @@ static ssize_t set_tcrit2(struct device *dev, struct device_attribute *attr,
mutex_lock(&data->update_lock);
data->tcrit2[index] = val;
- i2c_smbus_write_byte_data(client, LM95234_REG_TCRIT2(index), val);
+ i2c_smbus_write_byte_data(data->client, LM95234_REG_TCRIT2(index), val);
mutex_unlock(&data->update_lock);
return count;
@@ -324,10 +318,9 @@ static ssize_t set_tcrit2(struct device *dev, struct device_attribute *attr,
static ssize_t show_tcrit2_hyst(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm95234_data *data = i2c_get_clientdata(client);
+ struct lm95234_data *data = dev_get_drvdata(dev);
int index = to_sensor_dev_attr(attr)->index;
- int ret = lm95234_update_device(client, data);
+ int ret = lm95234_update_device(data);
if (ret)
return ret;
@@ -340,8 +333,7 @@ static ssize_t show_tcrit2_hyst(struct device *dev,
static ssize_t show_tcrit1(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm95234_data *data = i2c_get_clientdata(client);
+ struct lm95234_data *data = dev_get_drvdata(dev);
int index = to_sensor_dev_attr(attr)->index;
return sprintf(buf, "%u", data->tcrit1[index] * 1000);
@@ -350,11 +342,10 @@ static ssize_t show_tcrit1(struct device *dev, struct device_attribute *attr,
static ssize_t set_tcrit1(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm95234_data *data = i2c_get_clientdata(client);
+ struct lm95234_data *data = dev_get_drvdata(dev);
int index = to_sensor_dev_attr(attr)->index;
+ int ret = lm95234_update_device(data);
long val;
- int ret = lm95234_update_device(client, data);
if (ret)
return ret;
@@ -367,7 +358,7 @@ static ssize_t set_tcrit1(struct device *dev, struct device_attribute *attr,
mutex_lock(&data->update_lock);
data->tcrit1[index] = val;
- i2c_smbus_write_byte_data(client, LM95234_REG_TCRIT1(index), val);
+ i2c_smbus_write_byte_data(data->client, LM95234_REG_TCRIT1(index), val);
mutex_unlock(&data->update_lock);
return count;
@@ -376,10 +367,9 @@ static ssize_t set_tcrit1(struct device *dev, struct device_attribute *attr,
static ssize_t show_tcrit1_hyst(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm95234_data *data = i2c_get_clientdata(client);
+ struct lm95234_data *data = dev_get_drvdata(dev);
int index = to_sensor_dev_attr(attr)->index;
- int ret = lm95234_update_device(client, data);
+ int ret = lm95234_update_device(data);
if (ret)
return ret;
@@ -393,11 +383,10 @@ static ssize_t set_tcrit1_hyst(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm95234_data *data = i2c_get_clientdata(client);
+ struct lm95234_data *data = dev_get_drvdata(dev);
int index = to_sensor_dev_attr(attr)->index;
+ int ret = lm95234_update_device(data);
long val;
- int ret = lm95234_update_device(client, data);
if (ret)
return ret;
@@ -411,7 +400,7 @@ static ssize_t set_tcrit1_hyst(struct device *dev,
mutex_lock(&data->update_lock);
data->thyst = val;
- i2c_smbus_write_byte_data(client, LM95234_REG_TCRIT_HYST, val);
+ i2c_smbus_write_byte_data(data->client, LM95234_REG_TCRIT_HYST, val);
mutex_unlock(&data->update_lock);
return count;
@@ -420,10 +409,9 @@ static ssize_t set_tcrit1_hyst(struct device *dev,
static ssize_t show_offset(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm95234_data *data = i2c_get_clientdata(client);
+ struct lm95234_data *data = dev_get_drvdata(dev);
int index = to_sensor_dev_attr(attr)->index;
- int ret = lm95234_update_device(client, data);
+ int ret = lm95234_update_device(data);
if (ret)
return ret;
@@ -434,11 +422,10 @@ static ssize_t show_offset(struct device *dev, struct device_attribute *attr,
static ssize_t set_offset(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm95234_data *data = i2c_get_clientdata(client);
+ struct lm95234_data *data = dev_get_drvdata(dev);
int index = to_sensor_dev_attr(attr)->index;
+ int ret = lm95234_update_device(data);
long val;
- int ret = lm95234_update_device(client, data);
if (ret)
return ret;
@@ -452,7 +439,7 @@ static ssize_t set_offset(struct device *dev, struct device_attribute *attr,
mutex_lock(&data->update_lock);
data->toffset[index] = val;
- i2c_smbus_write_byte_data(client, LM95234_REG_OFFSET(index), val);
+ i2c_smbus_write_byte_data(data->client, LM95234_REG_OFFSET(index), val);
mutex_unlock(&data->update_lock);
return count;
@@ -461,9 +448,8 @@ static ssize_t set_offset(struct device *dev, struct device_attribute *attr,
static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm95234_data *data = i2c_get_clientdata(client);
- int ret = lm95234_update_device(client, data);
+ struct lm95234_data *data = dev_get_drvdata(dev);
+ int ret = lm95234_update_device(data);
if (ret)
return ret;
@@ -475,11 +461,10 @@ static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm95234_data *data = i2c_get_clientdata(client);
+ struct lm95234_data *data = dev_get_drvdata(dev);
+ int ret = lm95234_update_device(data);
unsigned long val;
u8 regval;
- int ret = lm95234_update_device(client, data);
if (ret)
return ret;
@@ -495,7 +480,7 @@ static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
mutex_lock(&data->update_lock);
data->interval = msecs_to_jiffies(update_intervals[regval]);
- i2c_smbus_write_byte_data(client, LM95234_REG_CONVRATE, regval);
+ i2c_smbus_write_byte_data(data->client, LM95234_REG_CONVRATE, regval);
mutex_unlock(&data->update_lock);
return count;
@@ -579,7 +564,7 @@ static SENSOR_DEVICE_ATTR(temp5_offset, S_IWUSR | S_IRUGO, show_offset,
static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval,
set_interval);
-static struct attribute *lm95234_attributes[] = {
+static struct attribute *lm95234_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp2_input.dev_attr.attr,
&sensor_dev_attr_temp3_input.dev_attr.attr,
@@ -621,10 +606,7 @@ static struct attribute *lm95234_attributes[] = {
&dev_attr_update_interval.attr,
NULL
};
-
-static const struct attribute_group lm95234_group = {
- .attrs = lm95234_attributes,
-};
+ATTRIBUTE_GROUPS(lm95234);
static int lm95234_detect(struct i2c_client *client,
struct i2c_board_info *info)
@@ -701,13 +683,14 @@ static int lm95234_probe(struct i2c_client *client,
{
struct device *dev = &client->dev;
struct lm95234_data *data;
+ struct device *hwmon_dev;
int err;
data = devm_kzalloc(dev, sizeof(struct lm95234_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->update_lock);
/* Initialize the LM95234 chip */
@@ -715,32 +698,10 @@ static int lm95234_probe(struct i2c_client *client,
if (err < 0)
return err;
- /* Register sysfs hooks */
- err = sysfs_create_group(&dev->kobj, &lm95234_group);
- if (err)
- return err;
-
- data->hwmon_dev = hwmon_device_register(dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove_files;
- }
-
- return 0;
-
-exit_remove_files:
- sysfs_remove_group(&dev->kobj, &lm95234_group);
- return err;
-}
-
-static int lm95234_remove(struct i2c_client *client)
-{
- struct lm95234_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &lm95234_group);
-
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data,
+ lm95234_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
/* Driver data (common to all clients) */
@@ -756,7 +717,6 @@ static struct i2c_driver lm95234_driver = {
.name = DRVNAME,
},
.probe = lm95234_probe,
- .remove = lm95234_remove,
.id_table = lm95234_id,
.detect = lm95234_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c
index cdc1ecc6734d..d4172933ce4f 100644
--- a/drivers/hwmon/ltc4245.c
+++ b/drivers/hwmon/ltc4245.c
@@ -51,7 +51,9 @@ enum ltc4245_cmd {
};
struct ltc4245_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
+
+ const struct attribute_group *groups[3];
struct mutex update_lock;
bool valid;
@@ -77,8 +79,8 @@ struct ltc4245_data {
*/
static void ltc4245_update_gpios(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ltc4245_data *data = i2c_get_clientdata(client);
+ struct ltc4245_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u8 gpio_curr, gpio_next, gpio_reg;
int i;
@@ -130,8 +132,8 @@ static void ltc4245_update_gpios(struct device *dev)
static struct ltc4245_data *ltc4245_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ltc4245_data *data = i2c_get_clientdata(client);
+ struct ltc4245_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
s32 val;
int i;
@@ -455,41 +457,14 @@ static const struct attribute_group ltc4245_gpio_group = {
.attrs = ltc4245_gpio_attributes,
};
-static int ltc4245_sysfs_create_groups(struct i2c_client *client)
+static void ltc4245_sysfs_add_groups(struct ltc4245_data *data)
{
- struct ltc4245_data *data = i2c_get_clientdata(client);
- struct device *dev = &client->dev;
- int ret;
-
- /* register the standard sysfs attributes */
- ret = sysfs_create_group(&dev->kobj, &ltc4245_std_group);
- if (ret) {
- dev_err(dev, "unable to register standard attributes\n");
- return ret;
- }
+ /* standard sysfs attributes */
+ data->groups[0] = &ltc4245_std_group;
/* if we're using the extra gpio support, register it's attributes */
- if (data->use_extra_gpios) {
- ret = sysfs_create_group(&dev->kobj, &ltc4245_gpio_group);
- if (ret) {
- dev_err(dev, "unable to register gpio attributes\n");
- sysfs_remove_group(&dev->kobj, &ltc4245_std_group);
- return ret;
- }
- }
-
- return 0;
-}
-
-static void ltc4245_sysfs_remove_groups(struct i2c_client *client)
-{
- struct ltc4245_data *data = i2c_get_clientdata(client);
- struct device *dev = &client->dev;
-
if (data->use_extra_gpios)
- sysfs_remove_group(&dev->kobj, &ltc4245_gpio_group);
-
- sysfs_remove_group(&dev->kobj, &ltc4245_std_group);
+ data->groups[1] = &ltc4245_gpio_group;
}
static bool ltc4245_use_extra_gpios(struct i2c_client *client)
@@ -517,7 +492,7 @@ static int ltc4245_probe(struct i2c_client *client,
{
struct i2c_adapter *adapter = client->adapter;
struct ltc4245_data *data;
- int ret;
+ struct device *hwmon_dev;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
@@ -526,7 +501,7 @@ static int ltc4245_probe(struct i2c_client *client,
if (!data)
return -ENOMEM;
- i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->update_lock);
data->use_extra_gpios = ltc4245_use_extra_gpios(client);
@@ -534,30 +509,25 @@ static int ltc4245_probe(struct i2c_client *client,
i2c_smbus_write_byte_data(client, LTC4245_FAULT1, 0x00);
i2c_smbus_write_byte_data(client, LTC4245_FAULT2, 0x00);
- /* Register sysfs hooks */
- ret = ltc4245_sysfs_create_groups(client);
- if (ret)
- return ret;
+ /* Add sysfs hooks */
+ ltc4245_sysfs_add_groups(data);
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- ret = PTR_ERR(data->hwmon_dev);
- goto out_hwmon_device_register;
- }
+ hwmon_dev = hwmon_device_register_with_groups(&client->dev,
+ client->name, data,
+ data->groups);
+ if (IS_ERR(hwmon_dev))
+ return PTR_ERR(hwmon_dev);
- return 0;
+ i2c_set_clientdata(client, hwmon_dev);
-out_hwmon_device_register:
- ltc4245_sysfs_remove_groups(client);
- return ret;
+ return 0;
}
static int ltc4245_remove(struct i2c_client *client)
{
- struct ltc4245_data *data = i2c_get_clientdata(client);
+ struct device *hwmon_dev = i2c_get_clientdata(client);
- hwmon_device_unregister(data->hwmon_dev);
- ltc4245_sysfs_remove_groups(client);
+ hwmon_device_unregister(hwmon_dev);
return 0;
}
diff --git a/drivers/hwmon/ltc4261.c b/drivers/hwmon/ltc4261.c
index 487da58ec86c..0becd69842bb 100644
--- a/drivers/hwmon/ltc4261.c
+++ b/drivers/hwmon/ltc4261.c
@@ -55,7 +55,7 @@
#define FAULT_OC (1<<2)
struct ltc4261_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex update_lock;
bool valid;
@@ -67,8 +67,8 @@ struct ltc4261_data {
static struct ltc4261_data *ltc4261_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct ltc4261_data *data = i2c_get_clientdata(client);
+ struct ltc4261_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
struct ltc4261_data *ret = data;
mutex_lock(&data->update_lock);
@@ -150,7 +150,6 @@ static ssize_t ltc4261_show_bool(struct device *dev,
struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct i2c_client *client = to_i2c_client(dev);
struct ltc4261_data *data = ltc4261_update_device(dev);
u8 fault;
@@ -159,7 +158,7 @@ static ssize_t ltc4261_show_bool(struct device *dev,
fault = data->regs[LTC4261_FAULT] & attr->index;
if (fault) /* Clear reported faults in chip register */
- i2c_smbus_write_byte_data(client, LTC4261_FAULT, ~fault);
+ i2c_smbus_write_byte_data(data->client, LTC4261_FAULT, ~fault);
return snprintf(buf, PAGE_SIZE, "%d\n", fault ? 1 : 0);
}
@@ -197,7 +196,7 @@ static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4261_show_value, NULL,
static SENSOR_DEVICE_ATTR(curr1_max_alarm, S_IRUGO, ltc4261_show_bool, NULL,
FAULT_OC);
-static struct attribute *ltc4261_attributes[] = {
+static struct attribute *ltc4261_attrs[] = {
&sensor_dev_attr_in1_input.dev_attr.attr,
&sensor_dev_attr_in1_min_alarm.dev_attr.attr,
&sensor_dev_attr_in1_max_alarm.dev_attr.attr,
@@ -210,62 +209,38 @@ static struct attribute *ltc4261_attributes[] = {
NULL,
};
-
-static const struct attribute_group ltc4261_group = {
- .attrs = ltc4261_attributes,
-};
+ATTRIBUTE_GROUPS(ltc4261);
static int ltc4261_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = client->adapter;
+ struct device *dev = &client->dev;
struct ltc4261_data *data;
- int ret;
+ struct device *hwmon_dev;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
if (i2c_smbus_read_byte_data(client, LTC4261_STATUS) < 0) {
- dev_err(&client->dev, "Failed to read status register\n");
+ dev_err(dev, "Failed to read status register\n");
return -ENODEV;
}
- data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->update_lock);
/* Clear faults */
i2c_smbus_write_byte_data(client, LTC4261_FAULT, 0x00);
- /* Register sysfs hooks */
- ret = sysfs_create_group(&client->dev.kobj, &ltc4261_group);
- if (ret)
- return ret;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- ret = PTR_ERR(data->hwmon_dev);
- goto out_hwmon_device_register;
- }
-
- return 0;
-
-out_hwmon_device_register:
- sysfs_remove_group(&client->dev.kobj, &ltc4261_group);
- return ret;
-}
-
-static int ltc4261_remove(struct i2c_client *client)
-{
- struct ltc4261_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &ltc4261_group);
-
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data,
+ ltc4261_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct i2c_device_id ltc4261_id[] = {
@@ -281,7 +256,6 @@ static struct i2c_driver ltc4261_driver = {
.name = "ltc4261",
},
.probe = ltc4261_probe,
- .remove = ltc4261_remove,
.id_table = ltc4261_id,
};
diff --git a/drivers/hwmon/max16065.c b/drivers/hwmon/max16065.c
index 2fa2c02f5569..d4efc79d7b93 100644
--- a/drivers/hwmon/max16065.c
+++ b/drivers/hwmon/max16065.c
@@ -83,7 +83,8 @@ static const bool max16065_have_current[] = {
struct max16065_data {
enum chips type;
- struct device *hwmon_dev;
+ struct i2c_client *client;
+ const struct attribute_group *groups[4];
struct mutex update_lock;
bool valid;
unsigned long last_updated; /* in jiffies */
@@ -144,8 +145,8 @@ static int max16065_read_adc(struct i2c_client *client, int reg)
static struct max16065_data *max16065_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct max16065_data *data = i2c_get_clientdata(client);
+ struct max16065_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
@@ -186,7 +187,7 @@ static ssize_t max16065_show_alarm(struct device *dev,
val &= (1 << attr2->index);
if (val)
- i2c_smbus_write_byte_data(to_i2c_client(dev),
+ i2c_smbus_write_byte_data(data->client,
MAX16065_FAULT(attr2->nr), val);
return snprintf(buf, PAGE_SIZE, "%d\n", !!val);
@@ -223,8 +224,7 @@ static ssize_t max16065_set_limit(struct device *dev,
const char *buf, size_t count)
{
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da);
- struct i2c_client *client = to_i2c_client(dev);
- struct max16065_data *data = i2c_get_clientdata(client);
+ struct max16065_data *data = dev_get_drvdata(dev);
unsigned long val;
int err;
int limit;
@@ -238,7 +238,7 @@ static ssize_t max16065_set_limit(struct device *dev,
mutex_lock(&data->update_lock);
data->limit[attr2->nr][attr2->index]
= LIMIT_TO_MV(limit, data->range[attr2->index]);
- i2c_smbus_write_byte_data(client,
+ i2c_smbus_write_byte_data(data->client,
MAX16065_LIMIT(attr2->nr, attr2->index),
limit);
mutex_unlock(&data->update_lock);
@@ -250,8 +250,7 @@ static ssize_t max16065_show_limit(struct device *dev,
struct device_attribute *da, char *buf)
{
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da);
- struct i2c_client *client = to_i2c_client(dev);
- struct max16065_data *data = i2c_get_clientdata(client);
+ struct max16065_data *data = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%d\n",
data->limit[attr2->nr][attr2->index]);
@@ -516,8 +515,32 @@ static struct attribute *max16065_max_attributes[] = {
NULL
};
+static umode_t max16065_basic_is_visible(struct kobject *kobj,
+ struct attribute *a, int n)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct max16065_data *data = dev_get_drvdata(dev);
+ int index = n / 4;
+
+ if (index >= data->num_adc || !data->range[index])
+ return 0;
+ return a->mode;
+}
+
+static umode_t max16065_secondary_is_visible(struct kobject *kobj,
+ struct attribute *a, int index)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct max16065_data *data = dev_get_drvdata(dev);
+
+ if (index >= data->num_adc)
+ return 0;
+ return a->mode;
+}
+
static const struct attribute_group max16065_basic_group = {
.attrs = max16065_basic_attributes,
+ .is_visible = max16065_basic_is_visible,
};
static const struct attribute_group max16065_current_group = {
@@ -526,38 +549,35 @@ static const struct attribute_group max16065_current_group = {
static const struct attribute_group max16065_min_group = {
.attrs = max16065_min_attributes,
+ .is_visible = max16065_secondary_is_visible,
};
static const struct attribute_group max16065_max_group = {
.attrs = max16065_max_attributes,
+ .is_visible = max16065_secondary_is_visible,
};
-static void max16065_cleanup(struct i2c_client *client)
-{
- sysfs_remove_group(&client->dev.kobj, &max16065_max_group);
- sysfs_remove_group(&client->dev.kobj, &max16065_min_group);
- sysfs_remove_group(&client->dev.kobj, &max16065_current_group);
- sysfs_remove_group(&client->dev.kobj, &max16065_basic_group);
-}
-
static int max16065_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = client->adapter;
struct max16065_data *data;
- int i, j, val, ret;
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
+ int i, j, val;
bool have_secondary; /* true if chip has secondary limits */
bool secondary_is_max = false; /* secondary limits reflect max */
+ int groups = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_READ_WORD_DATA))
return -ENODEV;
- data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (unlikely(!data))
return -ENOMEM;
- i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->update_lock);
data->num_adc = max16065_num_adc[id->driver_data];
@@ -596,38 +616,16 @@ static int max16065_probe(struct i2c_client *client,
}
}
- /* Register sysfs hooks */
- for (i = 0; i < data->num_adc * 4; i++) {
- /* Do not create sysfs entry if channel is disabled */
- if (!data->range[i / 4])
- continue;
-
- ret = sysfs_create_file(&client->dev.kobj,
- max16065_basic_attributes[i]);
- if (unlikely(ret))
- goto out;
- }
-
- if (have_secondary) {
- struct attribute **attr = secondary_is_max ?
- max16065_max_attributes : max16065_min_attributes;
-
- for (i = 0; i < data->num_adc; i++) {
- if (!data->range[i])
- continue;
-
- ret = sysfs_create_file(&client->dev.kobj, attr[i]);
- if (unlikely(ret))
- goto out;
- }
- }
+ /* sysfs hooks */
+ data->groups[groups++] = &max16065_basic_group;
+ if (have_secondary)
+ data->groups[groups++] = secondary_is_max ?
+ &max16065_max_group : &max16065_min_group;
if (data->have_current) {
val = i2c_smbus_read_byte_data(client, MAX16065_CURR_CONTROL);
- if (unlikely(val < 0)) {
- ret = val;
- goto out;
- }
+ if (unlikely(val < 0))
+ return val;
if (val & MAX16065_CURR_ENABLE) {
/*
* Current gain is 6, 12, 24, 48 based on values in
@@ -636,33 +634,16 @@ static int max16065_probe(struct i2c_client *client,
data->curr_gain = 6 << ((val >> 2) & 0x03);
data->range[MAX16065_NUM_ADC]
= max16065_csp_adc_range[(val >> 1) & 0x01];
- ret = sysfs_create_group(&client->dev.kobj,
- &max16065_current_group);
- if (unlikely(ret))
- goto out;
+ data->groups[groups++] = &max16065_current_group;
} else {
data->have_current = false;
}
}
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (unlikely(IS_ERR(data->hwmon_dev))) {
- ret = PTR_ERR(data->hwmon_dev);
- goto out;
- }
- return 0;
-
-out:
- max16065_cleanup(client);
- return ret;
-}
-
-static int max16065_remove(struct i2c_client *client)
-{
- struct max16065_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- max16065_cleanup(client);
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data, data->groups);
+ if (unlikely(IS_ERR(hwmon_dev)))
+ return PTR_ERR(hwmon_dev);
return 0;
}
@@ -685,7 +666,6 @@ static struct i2c_driver max16065_driver = {
.name = "max16065",
},
.probe = max16065_probe,
- .remove = max16065_remove,
.id_table = max16065_id,
};
diff --git a/drivers/hwmon/max6642.c b/drivers/hwmon/max6642.c
index 57d58cd32206..8326fbd60150 100644
--- a/drivers/hwmon/max6642.c
+++ b/drivers/hwmon/max6642.c
@@ -87,7 +87,7 @@ static int temp_to_reg(int val)
*/
struct max6642_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
struct mutex update_lock;
bool valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -102,10 +102,10 @@ struct max6642_data {
* Real code
*/
-static void max6642_init_client(struct i2c_client *client)
+static void max6642_init_client(struct max6642_data *data,
+ struct i2c_client *client)
{
u8 config;
- struct max6642_data *data = i2c_get_clientdata(client);
/*
* Start the conversions.
@@ -168,14 +168,14 @@ static int max6642_detect(struct i2c_client *client,
static struct max6642_data *max6642_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct max6642_data *data = i2c_get_clientdata(client);
+ struct max6642_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
u16 val, tmp;
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
- dev_dbg(&client->dev, "Updating max6642 data.\n");
+ dev_dbg(dev, "Updating max6642 data.\n");
val = i2c_smbus_read_byte_data(client,
MAX6642_REG_R_LOCAL_TEMPL);
tmp = (val >> 6) & 3;
@@ -209,8 +209,8 @@ static struct max6642_data *max6642_update_device(struct device *dev)
static ssize_t show_temp_max10(struct device *dev,
struct device_attribute *dev_attr, char *buf)
{
- struct max6642_data *data = max6642_update_device(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+ struct max6642_data *data = max6642_update_device(dev);
return sprintf(buf, "%d\n",
temp_from_reg10(data->temp_input[attr->index]));
@@ -219,8 +219,8 @@ static ssize_t show_temp_max10(struct device *dev,
static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct max6642_data *data = max6642_update_device(dev);
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
+ struct max6642_data *data = max6642_update_device(dev);
return sprintf(buf, "%d\n", temp_from_reg(data->temp_high[attr2->nr]));
}
@@ -228,11 +228,10 @@ static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
+ struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
+ struct max6642_data *data = dev_get_drvdata(dev);
unsigned long val;
int err;
- struct i2c_client *client = to_i2c_client(dev);
- struct max6642_data *data = i2c_get_clientdata(client);
- struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
err = kstrtoul(buf, 10, &val);
if (err < 0)
@@ -240,7 +239,7 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
mutex_lock(&data->update_lock);
data->temp_high[attr2->nr] = clamp_val(temp_to_reg(val), 0, 255);
- i2c_smbus_write_byte_data(client, attr2->index,
+ i2c_smbus_write_byte_data(data->client, attr2->index,
data->temp_high[attr2->nr]);
mutex_unlock(&data->update_lock);
return count;
@@ -264,7 +263,7 @@ static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2);
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4);
-static struct attribute *max6642_attributes[] = {
+static struct attribute *max6642_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp2_input.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
@@ -275,54 +274,29 @@ static struct attribute *max6642_attributes[] = {
&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
NULL
};
+ATTRIBUTE_GROUPS(max6642);
-static const struct attribute_group max6642_group = {
- .attrs = max6642_attributes,
-};
-
-static int max6642_probe(struct i2c_client *new_client,
+static int max6642_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device *dev = &client->dev;
struct max6642_data *data;
- int err;
+ struct device *hwmon_dev;
- data = devm_kzalloc(&new_client->dev, sizeof(struct max6642_data),
- GFP_KERNEL);
+ data = devm_kzalloc(dev, sizeof(struct max6642_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- i2c_set_clientdata(new_client, data);
+ data->client = client;
mutex_init(&data->update_lock);
/* Initialize the MAX6642 chip */
- max6642_init_client(new_client);
+ max6642_init_client(data, client);
- /* Register sysfs hooks */
- err = sysfs_create_group(&new_client->dev.kobj, &max6642_group);
- if (err)
- return err;
-
- data->hwmon_dev = hwmon_device_register(&new_client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove_files;
- }
-
- return 0;
-
-exit_remove_files:
- sysfs_remove_group(&new_client->dev.kobj, &max6642_group);
- return err;
-}
-
-static int max6642_remove(struct i2c_client *client)
-{
- struct max6642_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &max6642_group);
-
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
+ client->name, data,
+ max6642_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
/*
@@ -341,7 +315,6 @@ static struct i2c_driver max6642_driver = {
.name = "max6642",
},
.probe = max6642_probe,
- .remove = max6642_remove,
.id_table = max6642_id,
.detect = max6642_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c
index a41b5f3fc506..7fd3eaf817f4 100644
--- a/drivers/hwmon/max6697.c
+++ b/drivers/hwmon/max6697.c
@@ -77,7 +77,7 @@ struct max6697_chip_data {
};
struct max6697_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
enum chips type;
const struct max6697_chip_data *chip;
@@ -181,8 +181,8 @@ static const struct max6697_chip_data max6697_chip_data[] = {
static struct max6697_data *max6697_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct max6697_data *data = i2c_get_clientdata(client);
+ struct max6697_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
struct max6697_data *ret = data;
int val;
int i;
@@ -303,8 +303,7 @@ static ssize_t set_temp(struct device *dev,
{
int nr = to_sensor_dev_attr_2(devattr)->nr;
int index = to_sensor_dev_attr_2(devattr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct max6697_data *data = i2c_get_clientdata(client);
+ struct max6697_data *data = dev_get_drvdata(dev);
long temp;
int ret;
@@ -316,7 +315,7 @@ static ssize_t set_temp(struct device *dev,
temp = DIV_ROUND_CLOSEST(temp, 1000) + data->temp_offset;
temp = clamp_val(temp, 0, data->type == max6581 ? 255 : 127);
data->temp[nr][index] = temp;
- ret = i2c_smbus_write_byte_data(client,
+ ret = i2c_smbus_write_byte_data(data->client,
index == 2 ? MAX6697_REG_MAX[nr]
: MAX6697_REG_CRIT[nr],
temp);
@@ -405,8 +404,7 @@ static umode_t max6697_is_visible(struct kobject *kobj, struct attribute *attr,
int index)
{
struct device *dev = container_of(kobj, struct device, kobj);
- struct i2c_client *client = to_i2c_client(dev);
- struct max6697_data *data = i2c_get_clientdata(client);
+ struct max6697_data *data = dev_get_drvdata(dev);
const struct max6697_chip_data *chip = data->chip;
int channel = index / 6; /* channel number */
int nr = index % 6; /* attribute index within channel */
@@ -489,6 +487,7 @@ static struct attribute *max6697_attributes[] = {
static const struct attribute_group max6697_group = {
.attrs = max6697_attributes, .is_visible = max6697_is_visible,
};
+__ATTRIBUTE_GROUPS(max6697);
static void max6697_get_config_of(struct device_node *node,
struct max6697_platform_data *pdata)
@@ -525,9 +524,9 @@ static void max6697_get_config_of(struct device_node *node,
}
}
-static int max6697_init_chip(struct i2c_client *client)
+static int max6697_init_chip(struct max6697_data *data,
+ struct i2c_client *client)
{
- struct max6697_data *data = i2c_get_clientdata(client);
struct max6697_platform_data *pdata = dev_get_platdata(&client->dev);
struct max6697_platform_data p;
const struct max6697_chip_data *chip = data->chip;
@@ -625,6 +624,7 @@ static int max6697_probe(struct i2c_client *client,
struct i2c_adapter *adapter = client->adapter;
struct device *dev = &client->dev;
struct max6697_data *data;
+ struct device *hwmon_dev;
int err;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -636,39 +636,17 @@ static int max6697_probe(struct i2c_client *client,
data->type = id->driver_data;
data->chip = &max6697_chip_data[data->type];
-
- i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->update_lock);
- err = max6697_init_chip(client);
- if (err)
- return err;
-
- err = sysfs_create_group(&client->dev.kobj, &max6697_group);
+ err = max6697_init_chip(data, client);
if (err)
return err;
- data->hwmon_dev = hwmon_device_register(dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto error;
- }
-
- return 0;
-
-error:
- sysfs_remove_group(&client->dev.kobj, &max6697_group);
- return err;
-}
-
-static int max6697_remove(struct i2c_client *client)
-{
- struct max6697_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &max6697_group);
-
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data,
+ max6697_groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
static const struct i2c_device_id max6697_id[] = {
@@ -692,7 +670,6 @@ static struct i2c_driver max6697_driver = {
.name = "max6697",
},
.probe = max6697_probe,
- .remove = max6697_remove,
.id_table = max6697_id,
};
diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c
index 982d8622c09b..ae00e60d856c 100644
--- a/drivers/hwmon/mc13783-adc.c
+++ b/drivers/hwmon/mc13783-adc.c
@@ -37,7 +37,7 @@
struct mc13783_adc_priv {
struct mc13xxx *mc13xxx;
struct device *hwmon_dev;
- char name[10];
+ char name[PLATFORM_NAME_SIZE];
};
static ssize_t mc13783_adc_show_name(struct device *dev, struct device_attribute
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c
index 6eb03ce2cff4..7a1b6a75ed54 100644
--- a/drivers/hwmon/nct6775.c
+++ b/drivers/hwmon/nct6775.c
@@ -724,11 +724,8 @@ struct nct6775_data {
enum kinds kind;
const char *name;
- struct device *hwmon_dev;
- struct attribute_group *group_in;
- struct attribute_group *group_fan;
- struct attribute_group *group_temp;
- struct attribute_group *group_pwm;
+ int num_attr_groups;
+ const struct attribute_group *groups[6];
u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
* 3=temp_crit, 4=temp_lcrit
@@ -942,7 +939,7 @@ nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg,
struct sensor_device_attribute_2 *a2;
struct attribute **attrs;
struct sensor_device_template **t;
- int err, i, j, count;
+ int i, j, count;
if (repeat <= 0)
return ERR_PTR(-EINVAL);
@@ -1002,10 +999,6 @@ nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg,
}
}
- err = sysfs_create_group(&dev->kobj, group);
- if (err)
- return ERR_PTR(-ENOMEM);
-
return group;
}
@@ -1457,7 +1450,8 @@ static struct nct6775_data *nct6775_update_device(struct device *dev)
= nct6775_read_temp(data,
data->reg_temp[j][i]);
}
- if (!(data->have_temp_fixed & (1 << i)))
+ if (i >= NUM_TEMP_FIXED ||
+ !(data->have_temp_fixed & (1 << i)))
continue;
data->temp_offset[i]
= nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
@@ -1545,7 +1539,7 @@ static int find_temp_source(struct nct6775_data *data, int index, int count)
if (src == source)
return nr;
}
- return -1;
+ return -ENODEV;
}
static ssize_t
@@ -1644,7 +1638,7 @@ store_temp_beep(struct device *dev, struct device_attribute *attr,
nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
if (nr < 0)
- return -ENODEV;
+ return nr;
bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
regindex = bit >> 3;
@@ -2726,16 +2720,6 @@ store_fan_time(struct device *dev, struct device_attribute *attr,
}
static ssize_t
-show_name(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct nct6775_data *data = dev_get_drvdata(dev);
-
- return sprintf(buf, "%s\n", data->name);
-}
-
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-
-static ssize_t
show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
{
struct nct6775_data *data = nct6775_update_device(dev);
@@ -3061,16 +3045,16 @@ static umode_t nct6775_other_is_visible(struct kobject *kobj,
struct device *dev = container_of(kobj, struct device, kobj);
struct nct6775_data *data = dev_get_drvdata(dev);
- if (index == 1 && !data->have_vid)
+ if (index == 0 && !data->have_vid)
return 0;
- if (index == 2 || index == 3) {
- if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 2] < 0)
+ if (index == 1 || index == 2) {
+ if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 1] < 0)
return 0;
}
- if (index == 4 || index == 5) {
- if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 4] < 0)
+ if (index == 3 || index == 4) {
+ if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 3] < 0)
return 0;
}
@@ -3083,13 +3067,12 @@ static umode_t nct6775_other_is_visible(struct kobject *kobj,
* Any change in order or content must be matched.
*/
static struct attribute *nct6775_attributes_other[] = {
- &dev_attr_name.attr,
- &dev_attr_cpu0_vid.attr, /* 1 */
- &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, /* 2 */
- &sensor_dev_attr_intrusion1_alarm.dev_attr.attr, /* 3 */
- &sensor_dev_attr_intrusion0_beep.dev_attr.attr, /* 4 */
- &sensor_dev_attr_intrusion1_beep.dev_attr.attr, /* 5 */
- &sensor_dev_attr_beep_enable.dev_attr.attr, /* 6 */
+ &dev_attr_cpu0_vid.attr, /* 0 */
+ &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, /* 1 */
+ &sensor_dev_attr_intrusion1_alarm.dev_attr.attr, /* 2 */
+ &sensor_dev_attr_intrusion0_beep.dev_attr.attr, /* 3 */
+ &sensor_dev_attr_intrusion1_beep.dev_attr.attr, /* 4 */
+ &sensor_dev_attr_beep_enable.dev_attr.attr, /* 5 */
NULL
};
@@ -3099,27 +3082,6 @@ static const struct attribute_group nct6775_group_other = {
.is_visible = nct6775_other_is_visible,
};
-/*
- * Driver and device management
- */
-
-static void nct6775_device_remove_files(struct device *dev)
-{
- struct nct6775_data *data = dev_get_drvdata(dev);
-
- if (data->group_pwm)
- sysfs_remove_group(&dev->kobj, data->group_pwm);
- if (data->group_in)
- sysfs_remove_group(&dev->kobj, data->group_in);
- if (data->group_fan)
- sysfs_remove_group(&dev->kobj, data->group_fan);
- if (data->group_temp)
- sysfs_remove_group(&dev->kobj, data->group_temp);
-
- sysfs_remove_group(&dev->kobj, &nct6775_group_other);
-}
-
-/* Get the monitoring functions started */
static inline void nct6775_init_device(struct nct6775_data *data)
{
int i;
@@ -3296,6 +3258,7 @@ static int nct6775_probe(struct platform_device *pdev)
int num_reg_temp;
u8 cr2a;
struct attribute_group *group;
+ struct device *hwmon_dev;
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
@@ -3870,61 +3833,36 @@ static int nct6775_probe(struct platform_device *pdev)
/* Register sysfs hooks */
group = nct6775_create_attr_group(dev, &nct6775_pwm_template_group,
data->pwm_num);
- if (IS_ERR(group)) {
- err = PTR_ERR(group);
- goto exit_remove;
- }
- data->group_pwm = group;
+ if (IS_ERR(group))
+ return PTR_ERR(group);
+
+ data->groups[data->num_attr_groups++] = group;
group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
fls(data->have_in));
- if (IS_ERR(group)) {
- err = PTR_ERR(group);
- goto exit_remove;
- }
- data->group_in = group;
+ if (IS_ERR(group))
+ return PTR_ERR(group);
+
+ data->groups[data->num_attr_groups++] = group;
group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
fls(data->has_fan));
- if (IS_ERR(group)) {
- err = PTR_ERR(group);
- goto exit_remove;
- }
- data->group_fan = group;
+ if (IS_ERR(group))
+ return PTR_ERR(group);
+
+ data->groups[data->num_attr_groups++] = group;
group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
fls(data->have_temp));
- if (IS_ERR(group)) {
- err = PTR_ERR(group);
- goto exit_remove;
- }
- data->group_temp = group;
-
- err = sysfs_create_group(&dev->kobj, &nct6775_group_other);
- if (err)
- goto exit_remove;
+ if (IS_ERR(group))
+ return PTR_ERR(group);
- data->hwmon_dev = hwmon_device_register(dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- return 0;
-
-exit_remove:
- nct6775_device_remove_files(dev);
- return err;
-}
-
-static int nct6775_remove(struct platform_device *pdev)
-{
- struct nct6775_data *data = platform_get_drvdata(pdev);
+ data->groups[data->num_attr_groups++] = group;
+ data->groups[data->num_attr_groups++] = &nct6775_group_other;
- hwmon_device_unregister(data->hwmon_dev);
- nct6775_device_remove_files(&pdev->dev);
-
- return 0;
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, data->name,
+ data, data->groups);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
}
#ifdef CONFIG_PM
@@ -4013,7 +3951,6 @@ static struct platform_driver nct6775_driver = {
.pm = NCT6775_DEV_PM_OPS,
},
.probe = nct6775_probe,
- .remove = nct6775_remove,
};
static const char * const nct6775_sio_names[] __initconst = {
@@ -4101,7 +4038,7 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
/*
* when Super-I/O functions move to a separate file, the Super-I/O
* bus will manage the lifetime of the device and this module will only keep
- * track of the nct6775 driver. But since we platform_device_alloc(), we
+ * track of the nct6775 driver. But since we use platform_device_alloc(), we
* must keep track of the device
*/
static struct platform_device *pdev[2];
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 9319fcf142d9..7f9ce3251063 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -97,6 +97,7 @@ struct pmbus_data {
int max_attributes;
int num_attributes;
struct attribute_group group;
+ const struct attribute_group *groups[2];
struct pmbus_sensor *sensors;
@@ -348,7 +349,7 @@ static struct _pmbus_status {
static struct pmbus_data *pmbus_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_client *client = to_i2c_client(dev->parent);
struct pmbus_data *data = i2c_get_clientdata(client);
const struct pmbus_driver_info *info = data->info;
struct pmbus_sensor *sensor;
@@ -686,7 +687,7 @@ static int pmbus_get_boolean(struct pmbus_data *data, struct pmbus_boolean *b,
if (!s1 && !s2) {
ret = !!regval;
} else if (!s1 || !s2) {
- BUG();
+ WARN(1, "Bad boolean descriptor %p: s1=%p, s2=%p\n", b, s1, s2);
return 0;
} else {
long v1, v2;
@@ -733,7 +734,7 @@ static ssize_t pmbus_set_sensor(struct device *dev,
struct device_attribute *devattr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_client *client = to_i2c_client(dev->parent);
struct pmbus_data *data = i2c_get_clientdata(client);
struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
ssize_t rv = count;
@@ -1768,22 +1769,16 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
goto out_kfree;
}
- /* Register sysfs hooks */
- ret = sysfs_create_group(&dev->kobj, &data->group);
- if (ret) {
- dev_err(dev, "Failed to create sysfs entries\n");
- goto out_kfree;
- }
- data->hwmon_dev = hwmon_device_register(dev);
+ data->groups[0] = &data->group;
+ data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name,
+ data, data->groups);
if (IS_ERR(data->hwmon_dev)) {
ret = PTR_ERR(data->hwmon_dev);
dev_err(dev, "Failed to register hwmon device\n");
- goto out_hwmon_device_register;
+ goto out_kfree;
}
return 0;
-out_hwmon_device_register:
- sysfs_remove_group(&dev->kobj, &data->group);
out_kfree:
kfree(data->group.attrs);
return ret;
@@ -1794,7 +1789,6 @@ int pmbus_do_remove(struct i2c_client *client)
{
struct pmbus_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &data->group);
kfree(data->group.attrs);
return 0;
}
diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c
index dfe6d9527efb..49bd122d3640 100644
--- a/drivers/hwmon/tmp401.c
+++ b/drivers/hwmon/tmp401.c
@@ -155,7 +155,8 @@ MODULE_DEVICE_TABLE(i2c, tmp401_id);
*/
struct tmp401_data {
- struct device *hwmon_dev;
+ struct i2c_client *client;
+ const struct attribute_group *groups[3];
struct mutex update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
@@ -231,8 +232,8 @@ static int tmp401_update_device_reg16(struct i2c_client *client,
static struct tmp401_data *tmp401_update_device(struct device *dev)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct tmp401_data *data = i2c_get_clientdata(client);
+ struct tmp401_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
struct tmp401_data *ret = data;
int i, val;
unsigned long next_update;
@@ -350,8 +351,8 @@ static ssize_t store_temp(struct device *dev, struct device_attribute *devattr,
{
int nr = to_sensor_dev_attr_2(devattr)->nr;
int index = to_sensor_dev_attr_2(devattr)->index;
- struct i2c_client *client = to_i2c_client(dev);
- struct tmp401_data *data = tmp401_update_device(dev);
+ struct tmp401_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
u16 reg;
u8 regaddr;
@@ -405,7 +406,7 @@ static ssize_t store_temp_crit_hyst(struct device *dev, struct device_attribute
val = clamp_val(val, temp - 255000, temp);
reg = ((temp - val) + 500) / 1000;
- i2c_smbus_write_byte_data(to_i2c_client(dev), TMP401_TEMP_CRIT_HYST,
+ i2c_smbus_write_byte_data(data->client, TMP401_TEMP_CRIT_HYST,
reg);
data->temp_crit_hyst = reg;
@@ -423,8 +424,8 @@ static ssize_t store_temp_crit_hyst(struct device *dev, struct device_attribute
static ssize_t reset_temp_history(struct device *dev,
struct device_attribute *devattr, const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct tmp401_data *data = i2c_get_clientdata(client);
+ struct tmp401_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
long val;
if (kstrtol(buf, 10, &val))
@@ -447,8 +448,7 @@ static ssize_t reset_temp_history(struct device *dev,
static ssize_t show_update_interval(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct tmp401_data *data = i2c_get_clientdata(client);
+ struct tmp401_data *data = dev_get_drvdata(dev);
return sprintf(buf, "%u\n", data->update_interval);
}
@@ -457,8 +457,8 @@ static ssize_t set_update_interval(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct tmp401_data *data = i2c_get_clientdata(client);
+ struct tmp401_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
unsigned long val;
int err, rate;
@@ -616,10 +616,10 @@ static const struct attribute_group tmp432_group = {
* Begin non sysfs callback code (aka Real code)
*/
-static void tmp401_init_client(struct i2c_client *client)
+static void tmp401_init_client(struct tmp401_data *data,
+ struct i2c_client *client)
{
int config, config_orig;
- struct tmp401_data *data = i2c_get_clientdata(client);
/* Set the conversion rate to 2 Hz */
i2c_smbus_write_byte_data(client, TMP401_CONVERSION_RATE_WRITE, 5);
@@ -705,77 +705,45 @@ static int tmp401_detect(struct i2c_client *client,
return 0;
}
-static int tmp401_remove(struct i2c_client *client)
-{
- struct device *dev = &client->dev;
- struct tmp401_data *data = i2c_get_clientdata(client);
-
- if (data->hwmon_dev)
- hwmon_device_unregister(data->hwmon_dev);
-
- sysfs_remove_group(&dev->kobj, &tmp401_group);
-
- if (data->kind == tmp411)
- sysfs_remove_group(&dev->kobj, &tmp411_group);
-
- if (data->kind == tmp432)
- sysfs_remove_group(&dev->kobj, &tmp432_group);
-
- return 0;
-}
-
static int tmp401_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ const char *names[] = { "TMP401", "TMP411", "TMP431", "TMP432" };
struct device *dev = &client->dev;
- int err;
+ struct device *hwmon_dev;
struct tmp401_data *data;
- const char *names[] = { "TMP401", "TMP411", "TMP431", "TMP432" };
+ int groups = 0;
data = devm_kzalloc(dev, sizeof(struct tmp401_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- i2c_set_clientdata(client, data);
+ data->client = client;
mutex_init(&data->update_lock);
data->kind = id->driver_data;
/* Initialize the TMP401 chip */
- tmp401_init_client(client);
+ tmp401_init_client(data, client);
/* Register sysfs hooks */
- err = sysfs_create_group(&dev->kobj, &tmp401_group);
- if (err)
- return err;
+ data->groups[groups++] = &tmp401_group;
/* Register additional tmp411 sysfs hooks */
- if (data->kind == tmp411) {
- err = sysfs_create_group(&dev->kobj, &tmp411_group);
- if (err)
- goto exit_remove;
- }
+ if (data->kind == tmp411)
+ data->groups[groups++] = &tmp411_group;
/* Register additional tmp432 sysfs hooks */
- if (data->kind == tmp432) {
- err = sysfs_create_group(&dev->kobj, &tmp432_group);
- if (err)
- goto exit_remove;
- }
+ if (data->kind == tmp432)
+ data->groups[groups++] = &tmp432_group;
- data->hwmon_dev = hwmon_device_register(dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- data->hwmon_dev = NULL;
- goto exit_remove;
- }
+ hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+ data, data->groups);
+ if (IS_ERR(hwmon_dev))
+ return PTR_ERR(hwmon_dev);
dev_info(dev, "Detected TI %s chip\n", names[data->kind]);
return 0;
-
-exit_remove:
- tmp401_remove(client);
- return err;
}
static struct i2c_driver tmp401_driver = {
@@ -784,7 +752,6 @@ static struct i2c_driver tmp401_driver = {
.name = "tmp401",
},
.probe = tmp401_probe,
- .remove = tmp401_remove,
.id_table = tmp401_id,
.detect = tmp401_detect,
.address_list = normal_i2c,
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 02906ca99b41..8fb46aab2d87 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -197,8 +197,8 @@ comment "IDE chipset support/bugfixes"
config IDE_GENERIC
tristate "generic/default IDE chipset support"
- depends on ALPHA || X86 || IA64 || M32R || MIPS || ARCH_RPC || ARCH_SHARK
- default ARM && (ARCH_RPC || ARCH_SHARK)
+ depends on ALPHA || X86 || IA64 || M32R || MIPS || ARCH_RPC
+ default ARM && ARCH_RPC
help
This is the generic IDE driver. This driver attaches to the
fixed legacy ports (e.g. on PCs 0x1f0/0x170, 0x1e8/0x168 and
@@ -722,13 +722,6 @@ config BLK_DEV_IDE_RAPIDE
Say Y here if you want to support the Yellowstone RapIDE controller
manufactured for use with Acorn computers.
-config IDE_H8300
- tristate "H8300 IDE support"
- depends on H8300
- default y
- help
- Enables the H8300 IDE driver.
-
config BLK_DEV_GAYLE
tristate "Amiga Gayle IDE interface support"
depends on AMIGA
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index af8d016c37ea..a04ee82f1c8f 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -78,8 +78,6 @@ obj-$(CONFIG_BLK_DEV_CMD640) += cmd640.o
obj-$(CONFIG_BLK_DEV_IDE_PMAC) += pmac.o
-obj-$(CONFIG_IDE_H8300) += ide-h8300.o
-
obj-$(CONFIG_IDE_GENERIC) += ide-generic.o
obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o
diff --git a/drivers/ide/ide-h8300.c b/drivers/ide/ide-h8300.c
deleted file mode 100644
index 520f42c5445a..000000000000
--- a/drivers/ide/ide-h8300.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * H8/300 generic IDE interface
- */
-
-#include <linux/init.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#define DRV_NAME "ide-h8300"
-
-#define bswap(d) \
-({ \
- u16 r; \
- __asm__("mov.b %w1,r1h\n\t" \
- "mov.b %x1,r1l\n\t" \
- "mov.w r1,%0" \
- :"=r"(r) \
- :"r"(d) \
- :"er1"); \
- (r); \
-})
-
-static void mm_outsw(unsigned long addr, void *buf, u32 len)
-{
- unsigned short *bp = (unsigned short *)buf;
- for (; len > 0; len--, bp++)
- *(volatile u16 *)addr = bswap(*bp);
-}
-
-static void mm_insw(unsigned long addr, void *buf, u32 len)
-{
- unsigned short *bp = (unsigned short *)buf;
- for (; len > 0; len--, bp++)
- *bp = bswap(*(volatile u16 *)addr);
-}
-
-static void h8300_input_data(ide_drive_t *drive, struct ide_cmd *cmd,
- void *buf, unsigned int len)
-{
- mm_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
-}
-
-static void h8300_output_data(ide_drive_t *drive, struct ide_cmd *cmd,
- void *buf, unsigned int len)
-{
- mm_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
-}
-
-static const struct ide_tp_ops h8300_tp_ops = {
- .exec_command = ide_exec_command,
- .read_status = ide_read_status,
- .read_altstatus = ide_read_altstatus,
- .write_devctl = ide_write_devctl,
-
- .dev_select = ide_dev_select,
- .tf_load = ide_tf_load,
- .tf_read = ide_tf_read,
-
- .input_data = h8300_input_data,
- .output_data = h8300_output_data,
-};
-
-#define H8300_IDE_GAP (2)
-
-static inline void hw_setup(struct ide_hw *hw)
-{
- int i;
-
- memset(hw, 0, sizeof(*hw));
- for (i = 0; i <= 7; i++)
- hw->io_ports_array[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i;
- hw->io_ports.ctl_addr = CONFIG_H8300_IDE_ALT;
- hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ;
-}
-
-static const struct ide_port_info h8300_port_info = {
- .tp_ops = &h8300_tp_ops,
- .host_flags = IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA,
- .chipset = ide_generic,
-};
-
-static int __init h8300_ide_init(void)
-{
- struct ide_hw hw, *hws[] = { &hw };
-
- printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n");
-
- if (!request_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8, "ide-h8300"))
- goto out_busy;
- if (!request_region(CONFIG_H8300_IDE_ALT, H8300_IDE_GAP, "ide-h8300")) {
- release_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8);
- goto out_busy;
- }
-
- hw_setup(&hw);
-
- return ide_host_add(&h8300_port_info, hws, 1, NULL);
-
-out_busy:
- printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n");
-
- return -EBUSY;
-}
-
-module_init(h8300_ide_init);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index fa6964d8681a..45935d9949d2 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1,7 +1,7 @@
/*
* intel_idle.c - native hardware idle loop for modern Intel processors
*
- * Copyright (c) 2010, Intel Corporation.
+ * Copyright (c) 2013, Intel Corporation.
* Len Brown <len.brown@intel.com>
*
* This program is free software; you can redistribute it and/or modify it
@@ -123,7 +123,7 @@ static struct cpuidle_state *cpuidle_state_table;
* which is also the index into the MWAIT hint array.
* Thus C0 is a dummy.
*/
-static struct cpuidle_state nehalem_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state nehalem_cstates[] __initdata = {
{
.name = "C1-NHM",
.desc = "MWAIT 0x00",
@@ -156,7 +156,7 @@ static struct cpuidle_state nehalem_cstates[CPUIDLE_STATE_MAX] = {
.enter = NULL }
};
-static struct cpuidle_state snb_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state snb_cstates[] __initdata = {
{
.name = "C1-SNB",
.desc = "MWAIT 0x00",
@@ -196,7 +196,7 @@ static struct cpuidle_state snb_cstates[CPUIDLE_STATE_MAX] = {
.enter = NULL }
};
-static struct cpuidle_state ivb_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state ivb_cstates[] __initdata = {
{
.name = "C1-IVB",
.desc = "MWAIT 0x00",
@@ -236,7 +236,7 @@ static struct cpuidle_state ivb_cstates[CPUIDLE_STATE_MAX] = {
.enter = NULL }
};
-static struct cpuidle_state hsw_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state hsw_cstates[] __initdata = {
{
.name = "C1-HSW",
.desc = "MWAIT 0x00",
@@ -297,7 +297,7 @@ static struct cpuidle_state hsw_cstates[CPUIDLE_STATE_MAX] = {
.enter = NULL }
};
-static struct cpuidle_state atom_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state atom_cstates[] __initdata = {
{
.name = "C1E-ATM",
.desc = "MWAIT 0x00",
@@ -329,6 +329,36 @@ static struct cpuidle_state atom_cstates[CPUIDLE_STATE_MAX] = {
{
.enter = NULL }
};
+static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = {
+ {
+ .name = "C1-AVN",
+ .desc = "MWAIT 0x00",
+ .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID,
+ .exit_latency = 1,
+ .target_residency = 1,
+ .enter = &intel_idle },
+ {
+ .name = "C1E-AVN",
+ .desc = "MWAIT 0x01",
+ .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID,
+ .exit_latency = 5,
+ .target_residency = 10,
+ .enter = &intel_idle },
+ {
+ .name = "C6NS-AVN", /* No Cache Shrink */
+ .desc = "MWAIT 0x51",
+ .flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 15,
+ .target_residency = 45,
+ .enter = &intel_idle },
+ {
+ .name = "C6FS-AVN", /* Full Cache shrink */
+ .desc = "MWAIT 0x52",
+ .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+ .exit_latency = 150, /* fake penalty added due to cold cache */
+ .target_residency = 100000, /* fake penalty added due to cold cache */
+ .enter = &intel_idle },
+};
/**
* intel_idle
@@ -359,7 +389,7 @@ static int intel_idle(struct cpuidle_device *dev,
if (!(lapic_timer_reliable_states & (1 << (cstate))))
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
- if (!need_resched()) {
+ if (!current_set_polling_and_test()) {
__monitor((void *)&current_thread_info()->flags, 0, 0);
smp_mb();
@@ -462,6 +492,11 @@ static const struct idle_cpu idle_cpu_hsw = {
.disable_promotion_to_c1e = true,
};
+static const struct idle_cpu idle_cpu_avn = {
+ .state_table = avn_cstates,
+ .disable_promotion_to_c1e = true,
+};
+
#define ICPU(model, cpu) \
{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu }
@@ -483,6 +518,7 @@ static const struct x86_cpu_id intel_idle_ids[] = {
ICPU(0x3f, idle_cpu_hsw),
ICPU(0x45, idle_cpu_hsw),
ICPU(0x46, idle_cpu_hsw),
+ ICPU(0x4D, idle_cpu_avn),
{}
};
MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids);
@@ -490,7 +526,7 @@ MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids);
/*
* intel_idle_probe()
*/
-static int intel_idle_probe(void)
+static int __init intel_idle_probe(void)
{
unsigned int eax, ebx, ecx;
const struct x86_cpu_id *id;
@@ -558,7 +594,7 @@ static void intel_idle_cpuidle_devices_uninit(void)
* intel_idle_cpuidle_driver_init()
* allocate, initialize cpuidle_states
*/
-static int intel_idle_cpuidle_driver_init(void)
+static int __init intel_idle_cpuidle_driver_init(void)
{
int cstate;
struct cpuidle_driver *drv = &intel_idle_driver;
@@ -628,7 +664,7 @@ static int intel_idle_cpu_init(int cpu)
int num_substates, mwait_hint, mwait_cstate, mwait_substate;
if (cpuidle_state_table[cstate].enter == NULL)
- continue;
+ break;
if (cstate + 1 > max_cstate) {
printk(PREFIX "max_cstate %d reached\n", max_cstate);
diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c
index 81e3dc260993..28b39283bccf 100644
--- a/drivers/iio/accel/bma180.c
+++ b/drivers/iio/accel/bma180.c
@@ -471,13 +471,10 @@ static irqreturn_t bma180_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bma180_data *data = iio_priv(indio_dev);
+ int64_t time_ns = iio_get_time_ns();
int bit, ret, i = 0;
mutex_lock(&data->mutex);
- if (indio_dev->scan_timestamp) {
- ret = indio_dev->scan_bytes / sizeof(s64) - 1;
- ((s64 *)data->buff)[ret] = iio_get_time_ns();
- }
for_each_set_bit(bit, indio_dev->buffer->scan_mask,
indio_dev->masklength) {
@@ -490,7 +487,7 @@ static irqreturn_t bma180_trigger_handler(int irq, void *p)
}
mutex_unlock(&data->mutex);
- iio_push_to_buffers(indio_dev, (u8 *)data->buff);
+ iio_push_to_buffers_with_timestamp(indio_dev, data->buff, time_ns);
err:
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index 46d22f3fb1a9..dcda17395c4e 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -182,10 +182,11 @@ static const struct iio_info accel_3d_info = {
};
/* Function to push data to buffer */
-static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
+static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data,
+ int len)
{
dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
- iio_push_to_buffers(indio_dev, (u8 *)data);
+ iio_push_to_buffers(indio_dev, data);
}
/* Callback handler to send event after all samples are received and captured */
@@ -200,7 +201,7 @@ static int accel_3d_proc_event(struct hid_sensor_hub_device *hsdev,
accel_state->common_attributes.data_ready);
if (accel_state->common_attributes.data_ready)
hid_sensor_push_data(indio_dev,
- (u8 *)accel_state->accel_val,
+ accel_state->accel_val,
sizeof(accel_state->accel_val));
return 0;
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index 1458343f6f3f..38caedc76b98 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -452,8 +452,9 @@ static const struct iio_trigger_ops st_accel_trigger_ops = {
int st_accel_common_probe(struct iio_dev *indio_dev,
struct st_sensors_platform_data *plat_data)
{
- int err;
struct st_sensor_data *adata = iio_priv(indio_dev);
+ int irq = adata->get_irq_data_ready(indio_dev);
+ int err;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &accel_info;
@@ -461,7 +462,7 @@ int st_accel_common_probe(struct iio_dev *indio_dev,
err = st_sensors_check_device_support(indio_dev,
ARRAY_SIZE(st_accel_sensors), st_accel_sensors);
if (err < 0)
- goto st_accel_common_probe_error;
+ return err;
adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS;
adata->multiread_bit = adata->sensor->multi_read_bit;
@@ -478,13 +479,13 @@ int st_accel_common_probe(struct iio_dev *indio_dev,
err = st_sensors_init_sensor(indio_dev, plat_data);
if (err < 0)
- goto st_accel_common_probe_error;
+ return err;
- if (adata->get_irq_data_ready(indio_dev) > 0) {
- err = st_accel_allocate_ring(indio_dev);
- if (err < 0)
- goto st_accel_common_probe_error;
+ err = st_accel_allocate_ring(indio_dev);
+ if (err < 0)
+ return err;
+ if (irq > 0) {
err = st_sensors_allocate_trigger(indio_dev,
ST_ACCEL_TRIGGER_OPS);
if (err < 0)
@@ -495,15 +496,14 @@ int st_accel_common_probe(struct iio_dev *indio_dev,
if (err)
goto st_accel_device_register_error;
- return err;
+ return 0;
st_accel_device_register_error:
- if (adata->get_irq_data_ready(indio_dev) > 0)
+ if (irq > 0)
st_sensors_deallocate_trigger(indio_dev);
st_accel_probe_trigger_error:
- if (adata->get_irq_data_ready(indio_dev) > 0)
- st_accel_deallocate_ring(indio_dev);
-st_accel_common_probe_error:
+ st_accel_deallocate_ring(indio_dev);
+
return err;
}
EXPORT_SYMBOL(st_accel_common_probe);
@@ -513,10 +513,10 @@ void st_accel_common_remove(struct iio_dev *indio_dev)
struct st_sensor_data *adata = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
- if (adata->get_irq_data_ready(indio_dev) > 0) {
+ if (adata->get_irq_data_ready(indio_dev) > 0)
st_sensors_deallocate_trigger(indio_dev);
- st_accel_deallocate_ring(indio_dev);
- }
+
+ st_accel_deallocate_ring(indio_dev);
}
EXPORT_SYMBOL(st_accel_common_remove);
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 09371cbc9dc1..8b885188b839 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -145,6 +145,16 @@ config MCP320X
This driver can also be built as a module. If so, the module will be
called mcp320x.
+config MCP3422
+ tristate "Microchip Technology MCP3422/3/4 driver"
+ depends on I2C
+ help
+ Say yes here to build support for Microchip Technology's MCP3422,
+ MCP3423 or MCP3424 analog to digital converters.
+
+ This driver can also be built as a module. If so, the module will be
+ called mcp3422.
+
config NAU7802
tristate "Nuvoton NAU7802 ADC driver"
depends on I2C
@@ -167,6 +177,7 @@ config TI_ADC081C
config TI_AM335X_ADC
tristate "TI's AM335X ADC driver"
depends on MFD_TI_AM335X_TSCADC
+ select IIO_KFIFO_BUF
help
Say yes here to build support for Texas Instruments ADC
driver which is also a MFD client.
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 33656ef7d1f6..ba9a10a24cd0 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_MAX1363) += max1363.o
obj-$(CONFIG_MCP320X) += mcp320x.o
+obj-$(CONFIG_MCP3422) += mcp3422.o
obj-$(CONFIG_NAU7802) += nau7802.o
obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index 371731df1634..656aa3e102f2 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -96,9 +96,8 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p)
ret = spi_read(st->spi, st->data, 4);
if (ret == 0) {
- if (indio_dev->scan_timestamp)
- ((s64 *)st->data)[1] = pf->timestamp;
- iio_push_to_buffers(indio_dev, (u8 *)st->data);
+ iio_push_to_buffers_with_timestamp(indio_dev, st->data,
+ pf->timestamp);
}
iio_trigger_notify_done(indio_dev->trig);
@@ -293,7 +292,7 @@ static const struct iio_info ad7266_info = {
.driver_module = THIS_MODULE,
};
-static unsigned long ad7266_available_scan_masks[] = {
+static const unsigned long ad7266_available_scan_masks[] = {
0x003,
0x00c,
0x030,
@@ -303,14 +302,14 @@ static unsigned long ad7266_available_scan_masks[] = {
0x000,
};
-static unsigned long ad7266_available_scan_masks_diff[] = {
+static const unsigned long ad7266_available_scan_masks_diff[] = {
0x003,
0x00c,
0x030,
0x000,
};
-static unsigned long ad7266_available_scan_masks_fixed[] = {
+static const unsigned long ad7266_available_scan_masks_fixed[] = {
0x003,
0x000,
};
@@ -318,7 +317,7 @@ static unsigned long ad7266_available_scan_masks_fixed[] = {
struct ad7266_chan_info {
const struct iio_chan_spec *channels;
unsigned int num_channels;
- unsigned long *scan_masks;
+ const unsigned long *scan_masks;
};
#define AD7266_CHAN_INFO_INDEX(_differential, _signed, _fixed) \
diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c
index 85d1481c312f..2a3b65c74af9 100644
--- a/drivers/iio/adc/ad7298.c
+++ b/drivers/iio/adc/ad7298.c
@@ -159,20 +159,14 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct ad7298_state *st = iio_priv(indio_dev);
- s64 time_ns = 0;
int b_sent;
b_sent = spi_sync(st->spi, &st->ring_msg);
if (b_sent)
goto done;
- if (indio_dev->scan_timestamp) {
- time_ns = iio_get_time_ns();
- memcpy((u8 *)st->rx_buf + indio_dev->scan_bytes - sizeof(s64),
- &time_ns, sizeof(time_ns));
- }
-
- iio_push_to_buffers(indio_dev, (u8 *)st->rx_buf);
+ iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
+ iio_get_time_ns());
done:
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c
index 6d2b1d8d1a1f..8d808b9de909 100644
--- a/drivers/iio/adc/ad7476.c
+++ b/drivers/iio/adc/ad7476.c
@@ -64,19 +64,14 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct ad7476_state *st = iio_priv(indio_dev);
- s64 time_ns;
int b_sent;
b_sent = spi_sync(st->spi, &st->msg);
if (b_sent < 0)
goto done;
- time_ns = iio_get_time_ns();
-
- if (indio_dev->scan_timestamp)
- ((s64 *)st->data)[1] = time_ns;
-
- iio_push_to_buffers(indio_dev, st->data);
+ iio_push_to_buffers_with_timestamp(indio_dev, st->data,
+ iio_get_time_ns());
done:
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c
index 9dd077b78759..faedd0e165f6 100644
--- a/drivers/iio/adc/ad7887.c
+++ b/drivers/iio/adc/ad7887.c
@@ -121,20 +121,14 @@ static irqreturn_t ad7887_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct ad7887_state *st = iio_priv(indio_dev);
- s64 time_ns;
int b_sent;
b_sent = spi_sync(st->spi, st->ring_msg);
if (b_sent)
goto done;
- time_ns = iio_get_time_ns();
-
- if (indio_dev->scan_timestamp)
- memcpy(st->data + indio_dev->scan_bytes - sizeof(s64),
- &time_ns, sizeof(time_ns));
-
- iio_push_to_buffers(indio_dev, st->data);
+ iio_push_to_buffers_with_timestamp(indio_dev, st->data,
+ iio_get_time_ns());
done:
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c
index 4108dbb28c3d..28732c28e819 100644
--- a/drivers/iio/adc/ad7923.c
+++ b/drivers/iio/adc/ad7923.c
@@ -174,20 +174,14 @@ static irqreturn_t ad7923_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct ad7923_state *st = iio_priv(indio_dev);
- s64 time_ns = 0;
int b_sent;
b_sent = spi_sync(st->spi, &st->ring_msg);
if (b_sent)
goto done;
- if (indio_dev->scan_timestamp) {
- time_ns = iio_get_time_ns();
- memcpy((u8 *)st->rx_buf + indio_dev->scan_bytes - sizeof(s64),
- &time_ns, sizeof(time_ns));
- }
-
- iio_push_to_buffers(indio_dev, (u8 *)st->rx_buf);
+ iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
+ iio_get_time_ns());
done:
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index f0d6335ae087..2b5911274763 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -368,10 +368,6 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
memset(data, 0x00, 16);
- /* Guaranteed to be aligned with 8 byte boundary */
- if (indio_dev->scan_timestamp)
- ((s64 *)data)[1] = pf->timestamp;
-
reg_size = indio_dev->channels[0].scan_type.realbits +
indio_dev->channels[0].scan_type.shift;
reg_size = DIV_ROUND_UP(reg_size, 8);
@@ -391,7 +387,7 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
break;
}
- iio_push_to_buffers(indio_dev, (uint8_t *)data);
+ iio_push_to_buffers_with_timestamp(indio_dev, data, pf->timestamp);
iio_trigger_notify_done(indio_dev->trig);
sigma_delta->irq_dis = false;
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 0f16b553e063..78121949d6ef 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -83,13 +83,7 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
j++;
}
- if (idev->scan_timestamp) {
- s64 *timestamp = (s64 *)((u8 *)st->buffer +
- ALIGN(j, sizeof(s64)));
- *timestamp = pf->timestamp;
- }
-
- iio_push_to_buffers(idev, (u8 *)st->buffer);
+ iio_push_to_buffers_with_timestamp(idev, st->buffer, pf->timestamp);
iio_trigger_notify_done(idev->trig);
@@ -279,7 +273,7 @@ static int at91_adc_trigger_init(struct iio_dev *idev)
int i, ret;
st->trig = devm_kzalloc(&idev->dev,
- st->trigger_number * sizeof(st->trig),
+ st->trigger_number * sizeof(*st->trig),
GFP_KERNEL);
if (st->trig == NULL) {
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
index 4fb35d1d7494..b4bc166d57b0 100644
--- a/drivers/iio/adc/max1363.c
+++ b/drivers/iio/adc/max1363.c
@@ -1436,7 +1436,6 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct max1363_state *st = iio_priv(indio_dev);
- s64 time_ns;
__u8 *rxbuf;
int b_sent;
size_t d_size;
@@ -1470,11 +1469,7 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p)
if (b_sent < 0)
goto done_free;
- time_ns = iio_get_time_ns();
-
- if (indio_dev->scan_timestamp)
- memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
- iio_push_to_buffers(indio_dev, rxbuf);
+ iio_push_to_buffers_with_timestamp(indio_dev, rxbuf, iio_get_time_ns());
done_free:
kfree(rxbuf);
@@ -1484,12 +1479,6 @@ done:
return IRQ_HANDLED;
}
-static const struct iio_buffer_setup_ops max1363_buffered_setup_ops = {
- .postenable = &iio_triggered_buffer_postenable,
- .preenable = &iio_sw_buffer_preenable,
- .predisable = &iio_triggered_buffer_predisable,
-};
-
static int max1363_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -1559,7 +1548,7 @@ static int max1363_probe(struct i2c_client *client,
goto error_disable_reg;
ret = iio_triggered_buffer_setup(indio_dev, NULL,
- &max1363_trigger_handler, &max1363_buffered_setup_ops);
+ &max1363_trigger_handler, NULL);
if (ret)
goto error_disable_reg;
diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c
new file mode 100644
index 000000000000..bc93f538cb13
--- /dev/null
+++ b/drivers/iio/adc/mcp3422.c
@@ -0,0 +1,409 @@
+/*
+ * mcp3422.c - driver for the Microchip mcp3422/3/4 chip family
+ *
+ * Copyright (C) 2013, Angelo Compagnucci
+ * Author: Angelo Compagnucci <angelo.compagnucci@gmail.com>
+ *
+ * Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/22088b.pdf
+ *
+ * This driver exports the value of analog input voltage to sysfs, the
+ * voltage unit is nV.
+ *
+ * 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 <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/sysfs.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+/* Masks */
+#define MCP3422_CHANNEL_MASK 0x60
+#define MCP3422_PGA_MASK 0x03
+#define MCP3422_SRATE_MASK 0x0C
+#define MCP3422_SRATE_240 0x0
+#define MCP3422_SRATE_60 0x1
+#define MCP3422_SRATE_15 0x2
+#define MCP3422_SRATE_3 0x3
+#define MCP3422_PGA_1 0
+#define MCP3422_PGA_2 1
+#define MCP3422_PGA_4 2
+#define MCP3422_PGA_8 3
+#define MCP3422_CONT_SAMPLING 0x10
+
+#define MCP3422_CHANNEL(config) (((config) & MCP3422_CHANNEL_MASK) >> 5)
+#define MCP3422_PGA(config) ((config) & MCP3422_PGA_MASK)
+#define MCP3422_SAMPLE_RATE(config) (((config) & MCP3422_SRATE_MASK) >> 2)
+
+#define MCP3422_CHANNEL_VALUE(value) (((value) << 5) & MCP3422_CHANNEL_MASK)
+#define MCP3422_PGA_VALUE(value) ((value) & MCP3422_PGA_MASK)
+#define MCP3422_SAMPLE_RATE_VALUE(value) ((value << 2) & MCP3422_SRATE_MASK)
+
+#define MCP3422_CHAN(_index) \
+ { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = _index, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \
+ | BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ }
+
+/* LSB is in nV to eliminate floating point */
+static const u32 rates_to_lsb[] = {1000000, 250000, 62500, 15625};
+
+/*
+ * scales calculated as:
+ * rates_to_lsb[sample_rate] / (1 << pga);
+ * pga is 1 for 0, 2
+ */
+
+static const int mcp3422_scales[4][4] = {
+ { 1000000, 250000, 62500, 15625 },
+ { 500000 , 125000, 31250, 7812 },
+ { 250000 , 62500 , 15625, 3906 },
+ { 125000 , 31250 , 7812 , 1953 } };
+
+/* Constant msleep times for data acquisitions */
+static const int mcp3422_read_times[4] = {
+ [MCP3422_SRATE_240] = 1000 / 240,
+ [MCP3422_SRATE_60] = 1000 / 60,
+ [MCP3422_SRATE_15] = 1000 / 15,
+ [MCP3422_SRATE_3] = 1000 / 3 };
+
+/* sample rates to integer conversion table */
+static const int mcp3422_sample_rates[4] = {
+ [MCP3422_SRATE_240] = 240,
+ [MCP3422_SRATE_60] = 60,
+ [MCP3422_SRATE_15] = 15,
+ [MCP3422_SRATE_3] = 3 };
+
+/* sample rates to sign extension table */
+static const int mcp3422_sign_extend[4] = {
+ [MCP3422_SRATE_240] = 12,
+ [MCP3422_SRATE_60] = 14,
+ [MCP3422_SRATE_15] = 16,
+ [MCP3422_SRATE_3] = 18 };
+
+/* Client data (each client gets its own) */
+struct mcp3422 {
+ struct i2c_client *i2c;
+ u8 config;
+ u8 pga[4];
+ struct mutex lock;
+};
+
+static int mcp3422_update_config(struct mcp3422 *adc, u8 newconfig)
+{
+ int ret;
+
+ mutex_lock(&adc->lock);
+
+ ret = i2c_master_send(adc->i2c, &newconfig, 1);
+ if (ret > 0) {
+ adc->config = newconfig;
+ ret = 0;
+ }
+
+ mutex_unlock(&adc->lock);
+
+ return ret;
+}
+
+static int mcp3422_read(struct mcp3422 *adc, int *value, u8 *config)
+{
+ int ret = 0;
+ u8 sample_rate = MCP3422_SAMPLE_RATE(adc->config);
+ u8 buf[4] = {0, 0, 0, 0};
+ u32 temp;
+
+ if (sample_rate == MCP3422_SRATE_3) {
+ ret = i2c_master_recv(adc->i2c, buf, 4);
+ temp = buf[0] << 16 | buf[1] << 8 | buf[2];
+ *config = buf[3];
+ } else {
+ ret = i2c_master_recv(adc->i2c, buf, 3);
+ temp = buf[0] << 8 | buf[1];
+ *config = buf[2];
+ }
+
+ *value = sign_extend32(temp, mcp3422_sign_extend[sample_rate]);
+
+ return ret;
+}
+
+static int mcp3422_read_channel(struct mcp3422 *adc,
+ struct iio_chan_spec const *channel, int *value)
+{
+ int ret;
+ u8 config;
+ u8 req_channel = channel->channel;
+
+ if (req_channel != MCP3422_CHANNEL(adc->config)) {
+ config = adc->config;
+ config &= ~MCP3422_CHANNEL_MASK;
+ config |= MCP3422_CHANNEL_VALUE(req_channel);
+ config &= ~MCP3422_PGA_MASK;
+ config |= MCP3422_PGA_VALUE(adc->pga[req_channel]);
+ ret = mcp3422_update_config(adc, config);
+ if (ret < 0)
+ return ret;
+ msleep(mcp3422_read_times[MCP3422_SAMPLE_RATE(adc->config)]);
+ }
+
+ return mcp3422_read(adc, value, &config);
+}
+
+static int mcp3422_read_raw(struct iio_dev *iio,
+ struct iio_chan_spec const *channel, int *val1,
+ int *val2, long mask)
+{
+ struct mcp3422 *adc = iio_priv(iio);
+ int err;
+
+ u8 sample_rate = MCP3422_SAMPLE_RATE(adc->config);
+ u8 pga = MCP3422_PGA(adc->config);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ err = mcp3422_read_channel(adc, channel, val1);
+ if (err < 0)
+ return -EINVAL;
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+
+ *val1 = 0;
+ *val2 = mcp3422_scales[sample_rate][pga];
+ return IIO_VAL_INT_PLUS_NANO;
+
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val1 = mcp3422_sample_rates[MCP3422_SAMPLE_RATE(adc->config)];
+ return IIO_VAL_INT;
+
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static int mcp3422_write_raw(struct iio_dev *iio,
+ struct iio_chan_spec const *channel, int val1,
+ int val2, long mask)
+{
+ struct mcp3422 *adc = iio_priv(iio);
+ u8 temp;
+ u8 config = adc->config;
+ u8 req_channel = channel->channel;
+ u8 sample_rate = MCP3422_SAMPLE_RATE(config);
+ u8 i;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ if (val1 != 0)
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(mcp3422_scales[0]); i++) {
+ if (val2 == mcp3422_scales[sample_rate][i]) {
+ adc->pga[req_channel] = i;
+
+ config &= ~MCP3422_CHANNEL_MASK;
+ config |= MCP3422_CHANNEL_VALUE(req_channel);
+ config &= ~MCP3422_PGA_MASK;
+ config |= MCP3422_PGA_VALUE(adc->pga[req_channel]);
+
+ return mcp3422_update_config(adc, config);
+ }
+ }
+ return -EINVAL;
+
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ switch (val1) {
+ case 240:
+ temp = MCP3422_SRATE_240;
+ break;
+ case 60:
+ temp = MCP3422_SRATE_60;
+ break;
+ case 15:
+ temp = MCP3422_SRATE_15;
+ break;
+ case 3:
+ temp = MCP3422_SRATE_3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ config &= ~MCP3422_CHANNEL_MASK;
+ config |= MCP3422_CHANNEL_VALUE(req_channel);
+ config &= ~MCP3422_SRATE_MASK;
+ config |= MCP3422_SAMPLE_RATE_VALUE(temp);
+
+ return mcp3422_update_config(adc, config);
+
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static int mcp3422_write_raw_get_fmt(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ return IIO_VAL_INT_PLUS_NANO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static ssize_t mcp3422_show_scales(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mcp3422 *adc = iio_priv(dev_to_iio_dev(dev));
+ u8 sample_rate = MCP3422_SAMPLE_RATE(adc->config);
+
+ return sprintf(buf, "0.%09u 0.%09u 0.%09u 0.%09u\n",
+ mcp3422_scales[sample_rate][0],
+ mcp3422_scales[sample_rate][1],
+ mcp3422_scales[sample_rate][2],
+ mcp3422_scales[sample_rate][3]);
+}
+
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("240 60 15 3");
+static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO,
+ mcp3422_show_scales, NULL, 0);
+
+static struct attribute *mcp3422_attributes[] = {
+ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+ &iio_dev_attr_in_voltage_scale_available.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group mcp3422_attribute_group = {
+ .attrs = mcp3422_attributes,
+};
+
+static const struct iio_chan_spec mcp3422_channels[] = {
+ MCP3422_CHAN(0),
+ MCP3422_CHAN(1),
+};
+
+static const struct iio_chan_spec mcp3424_channels[] = {
+ MCP3422_CHAN(0),
+ MCP3422_CHAN(1),
+ MCP3422_CHAN(2),
+ MCP3422_CHAN(3),
+};
+
+static const struct iio_info mcp3422_info = {
+ .read_raw = mcp3422_read_raw,
+ .write_raw = mcp3422_write_raw,
+ .write_raw_get_fmt = mcp3422_write_raw_get_fmt,
+ .attrs = &mcp3422_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
+static int mcp3422_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct iio_dev *indio_dev;
+ struct mcp3422 *adc;
+ int err;
+ u8 config;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return -ENODEV;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*adc));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ adc = iio_priv(indio_dev);
+ adc->i2c = client;
+
+ mutex_init(&adc->lock);
+
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->name = dev_name(&client->dev);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &mcp3422_info;
+
+ switch ((unsigned int)(id->driver_data)) {
+ case 2:
+ case 3:
+ indio_dev->channels = mcp3422_channels;
+ indio_dev->num_channels = ARRAY_SIZE(mcp3422_channels);
+ break;
+ case 4:
+ indio_dev->channels = mcp3424_channels;
+ indio_dev->num_channels = ARRAY_SIZE(mcp3424_channels);
+ break;
+ }
+
+ /* meaningful default configuration */
+ config = (MCP3422_CONT_SAMPLING
+ | MCP3422_CHANNEL_VALUE(1)
+ | MCP3422_PGA_VALUE(MCP3422_PGA_1)
+ | MCP3422_SAMPLE_RATE_VALUE(MCP3422_SRATE_240));
+ mcp3422_update_config(adc, config);
+
+ err = iio_device_register(indio_dev);
+ if (err < 0)
+ return err;
+
+ i2c_set_clientdata(client, indio_dev);
+
+ return 0;
+}
+
+static int mcp3422_remove(struct i2c_client *client)
+{
+ iio_device_unregister(i2c_get_clientdata(client));
+ return 0;
+}
+
+static const struct i2c_device_id mcp3422_id[] = {
+ { "mcp3422", 2 },
+ { "mcp3423", 3 },
+ { "mcp3424", 4 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mcp3422_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id mcp3422_of_match[] = {
+ { .compatible = "mcp3422" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, mcp3422_of_match);
+#endif
+
+static struct i2c_driver mcp3422_driver = {
+ .driver = {
+ .name = "mcp3422",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(mcp3422_of_match),
+ },
+ .probe = mcp3422_probe,
+ .remove = mcp3422_remove,
+ .id_table = mcp3422_id,
+};
+module_i2c_driver(mcp3422_driver);
+
+MODULE_AUTHOR("Angelo Compagnucci <angelo.compagnucci@gmail.com>");
+MODULE_DESCRIPTION("Microchip mcp3422/3/4 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index a952538a1a8b..8fb5429e39ae 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -28,12 +28,16 @@
#include <linux/iio/driver.h>
#include <linux/mfd/ti_am335x_tscadc.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
struct tiadc_device {
struct ti_tscadc_dev *mfd_tscadc;
int channels;
u8 channel_line[8];
u8 channel_step[8];
+ int buffer_en_ch_steps;
+ u16 data[8];
};
static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
@@ -56,8 +60,14 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
return step_en;
}
-static void tiadc_step_config(struct tiadc_device *adc_dev)
+static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
{
+ return 1 << adc_dev->channel_step[chan];
+}
+
+static void tiadc_step_config(struct iio_dev *indio_dev)
+{
+ struct tiadc_device *adc_dev = iio_priv(indio_dev);
unsigned int stepconfig;
int i, steps;
@@ -72,7 +82,11 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
*/
steps = TOTAL_STEPS - adc_dev->channels;
- stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
+ if (iio_buffer_enabled(indio_dev))
+ stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1
+ | STEPCONFIG_MODE_SWCNT;
+ else
+ stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
for (i = 0; i < adc_dev->channels; i++) {
int chan;
@@ -85,9 +99,175 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
adc_dev->channel_step[i] = steps;
steps++;
}
+}
+
+static irqreturn_t tiadc_irq_h(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct tiadc_device *adc_dev = iio_priv(indio_dev);
+ unsigned int status, config;
+ status = tiadc_readl(adc_dev, REG_IRQSTATUS);
+
+ /*
+ * ADC and touchscreen share the IRQ line.
+ * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only
+ */
+ if (status & IRQENB_FIFO1OVRRUN) {
+ /* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */
+ config = tiadc_readl(adc_dev, REG_CTRL);
+ config &= ~(CNTRLREG_TSCSSENB);
+ tiadc_writel(adc_dev, REG_CTRL, config);
+ tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
+ | IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
+ tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
+ return IRQ_HANDLED;
+ } else if (status & IRQENB_FIFO1THRES) {
+ /* Disable irq and wake worker thread */
+ tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES);
+ return IRQ_WAKE_THREAD;
+ }
+
+ return IRQ_NONE;
+}
+
+static irqreturn_t tiadc_worker_h(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct tiadc_device *adc_dev = iio_priv(indio_dev);
+ int i, k, fifo1count, read;
+ u16 *data = adc_dev->data;
+
+ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+ for (k = 0; k < fifo1count; k = k + i) {
+ for (i = 0; i < (indio_dev->scan_bytes)/2; i++) {
+ read = tiadc_readl(adc_dev, REG_FIFO1);
+ data[i] = read & FIFOREAD_DATA_MASK;
+ }
+ iio_push_to_buffers(indio_dev, (u8 *) data);
+ }
+
+ tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES);
+ tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
+
+ return IRQ_HANDLED;
+}
+
+static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct tiadc_device *adc_dev = iio_priv(indio_dev);
+ int i, fifo1count, read;
+
+ tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
+ IRQENB_FIFO1OVRRUN |
+ IRQENB_FIFO1UNDRFLW));
+
+ /* Flush FIFO. Needed in corner cases in simultaneous tsc/adc use */
+ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+ for (i = 0; i < fifo1count; i++)
+ read = tiadc_readl(adc_dev, REG_FIFO1);
+
+ return iio_sw_buffer_preenable(indio_dev);
+}
+
+static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct tiadc_device *adc_dev = iio_priv(indio_dev);
+ struct iio_buffer *buffer = indio_dev->buffer;
+ unsigned int enb = 0;
+ u8 bit;
+
+ tiadc_step_config(indio_dev);
+ for_each_set_bit(bit, buffer->scan_mask, adc_dev->channels)
+ enb |= (get_adc_step_bit(adc_dev, bit) << 1);
+ adc_dev->buffer_en_ch_steps = enb;
+
+ am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);
+
+ tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES
+ | IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
+ tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES
+ | IRQENB_FIFO1OVRRUN);
+
+ return 0;
+}
+
+static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct tiadc_device *adc_dev = iio_priv(indio_dev);
+ int fifo1count, i, read;
+
+ tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
+ IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
+ am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
+
+ /* Flush FIFO of leftover data in the time it takes to disable adc */
+ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+ for (i = 0; i < fifo1count; i++)
+ read = tiadc_readl(adc_dev, REG_FIFO1);
+
+ return 0;
+}
+
+static int tiadc_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ tiadc_step_config(indio_dev);
+ return 0;
}
+static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = {
+ .preenable = &tiadc_buffer_preenable,
+ .postenable = &tiadc_buffer_postenable,
+ .predisable = &tiadc_buffer_predisable,
+ .postdisable = &tiadc_buffer_postdisable,
+};
+
+static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev,
+ irqreturn_t (*pollfunc_bh)(int irq, void *p),
+ irqreturn_t (*pollfunc_th)(int irq, void *p),
+ int irq,
+ unsigned long flags,
+ const struct iio_buffer_setup_ops *setup_ops)
+{
+ int ret;
+
+ indio_dev->buffer = iio_kfifo_allocate(indio_dev);
+ if (!indio_dev->buffer)
+ return -ENOMEM;
+
+ ret = request_threaded_irq(irq, pollfunc_th, pollfunc_bh,
+ flags, indio_dev->name, indio_dev);
+ if (ret)
+ goto error_kfifo_free;
+
+ indio_dev->setup_ops = setup_ops;
+ indio_dev->modes |= INDIO_BUFFER_HARDWARE;
+
+ ret = iio_buffer_register(indio_dev,
+ indio_dev->channels,
+ indio_dev->num_channels);
+ if (ret)
+ goto error_free_irq;
+
+ return 0;
+
+error_free_irq:
+ free_irq(irq, indio_dev);
+error_kfifo_free:
+ iio_kfifo_free(indio_dev->buffer);
+ return ret;
+}
+
+static void tiadc_iio_buffered_hardware_remove(struct iio_dev *indio_dev)
+{
+ struct tiadc_device *adc_dev = iio_priv(indio_dev);
+
+ free_irq(adc_dev->mfd_tscadc->irq, indio_dev);
+ iio_kfifo_free(indio_dev->buffer);
+ iio_buffer_unregister(indio_dev);
+}
+
+
static const char * const chan_name_ain[] = {
"AIN0",
"AIN1",
@@ -120,9 +300,10 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
chan->channel = adc_dev->channel_line[i];
chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
chan->datasheet_name = chan_name_ain[chan->channel];
+ chan->scan_index = i;
chan->scan_type.sign = 'u';
chan->scan_type.realbits = 12;
- chan->scan_type.storagebits = 32;
+ chan->scan_type.storagebits = 16;
}
indio_dev->channels = chan_array;
@@ -142,11 +323,14 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
struct tiadc_device *adc_dev = iio_priv(indio_dev);
int i, map_val;
unsigned int fifo1count, read, stepid;
- u32 step = UINT_MAX;
bool found = false;
u32 step_en;
unsigned long timeout = jiffies + usecs_to_jiffies
(IDLE_TIMEOUT * adc_dev->channels);
+
+ if (iio_buffer_enabled(indio_dev))
+ return -EBUSY;
+
step_en = get_adc_step_mask(adc_dev);
am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
@@ -168,15 +352,6 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
* Hence we need to flush out this data.
*/
- for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) {
- if (chan->channel == adc_dev->channel_line[i]) {
- step = adc_dev->channel_step[i];
- break;
- }
- }
- if (WARN_ON_ONCE(step == UINT_MAX))
- return -EINVAL;
-
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
for (i = 0; i < fifo1count; i++) {
read = tiadc_readl(adc_dev, REG_FIFO1);
@@ -186,7 +361,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
if (stepid == map_val) {
read = read & FIFOREAD_DATA_MASK;
found = true;
- *val = read;
+ *val = (u16) read;
}
}
@@ -237,20 +412,33 @@ static int tiadc_probe(struct platform_device *pdev)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &tiadc_info;
- tiadc_step_config(adc_dev);
+ tiadc_step_config(indio_dev);
+ tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
err = tiadc_channel_init(indio_dev, adc_dev->channels);
if (err < 0)
return err;
- err = iio_device_register(indio_dev);
+ err = tiadc_iio_buffered_hardware_setup(indio_dev,
+ &tiadc_worker_h,
+ &tiadc_irq_h,
+ adc_dev->mfd_tscadc->irq,
+ IRQF_SHARED,
+ &tiadc_buffer_setup_ops);
+
if (err)
goto err_free_channels;
+ err = iio_device_register(indio_dev);
+ if (err)
+ goto err_buffer_unregister;
+
platform_set_drvdata(pdev, indio_dev);
return 0;
+err_buffer_unregister:
+ tiadc_iio_buffered_hardware_remove(indio_dev);
err_free_channels:
tiadc_channels_remove(indio_dev);
return err;
@@ -263,6 +451,7 @@ static int tiadc_remove(struct platform_device *pdev)
u32 step_en;
iio_device_unregister(indio_dev);
+ tiadc_iio_buffered_hardware_remove(indio_dev);
tiadc_channels_remove(indio_dev);
step_en = get_adc_step_mask(adc_dev);
@@ -301,7 +490,7 @@ static int tiadc_resume(struct device *dev)
restore &= ~(CNTRLREG_POWERDOWN);
tiadc_writel(adc_dev, REG_CTRL, restore);
- tiadc_step_config(adc_dev);
+ tiadc_step_config(indio_dev);
return 0;
}
diff --git a/drivers/iio/buffer_cb.c b/drivers/iio/buffer_cb.c
index 415f3c6efd72..841fec1e78b2 100644
--- a/drivers/iio/buffer_cb.c
+++ b/drivers/iio/buffer_cb.c
@@ -7,12 +7,12 @@
struct iio_cb_buffer {
struct iio_buffer buffer;
- int (*cb)(u8 *data, void *private);
+ int (*cb)(const void *data, void *private);
void *private;
struct iio_channel *channels;
};
-static int iio_buffer_cb_store_to(struct iio_buffer *buffer, u8 *data)
+static int iio_buffer_cb_store_to(struct iio_buffer *buffer, const void *data)
{
struct iio_cb_buffer *cb_buff = container_of(buffer,
struct iio_cb_buffer,
@@ -21,12 +21,12 @@ static int iio_buffer_cb_store_to(struct iio_buffer *buffer, u8 *data)
return cb_buff->cb(data, cb_buff->private);
}
-static struct iio_buffer_access_funcs iio_cb_access = {
+static const struct iio_buffer_access_funcs iio_cb_access = {
.store_to = &iio_buffer_cb_store_to,
};
struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
- int (*cb)(u8 *data,
+ int (*cb)(const void *data,
void *private),
void *private)
{
diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c
index 71a2c5f63b9c..1665c8e4b62b 100644
--- a/drivers/iio/common/st_sensors/st_sensors_buffer.c
+++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c
@@ -113,11 +113,8 @@ irqreturn_t st_sensors_trigger_handler(int irq, void *p)
if (len < 0)
goto st_sensors_get_buffer_element_error;
- if (indio_dev->scan_timestamp)
- *(s64 *)((u8 *)sdata->buffer_data +
- ALIGN(len, sizeof(s64))) = pf->timestamp;
-
- iio_push_to_buffers(indio_dev, sdata->buffer_data);
+ iio_push_to_buffers_with_timestamp(indio_dev, sdata->buffer_data,
+ pf->timestamp);
st_sensors_get_buffer_element_error:
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c
index 965ee22d3ac8..7ba1ef270213 100644
--- a/drivers/iio/common/st_sensors/st_sensors_core.c
+++ b/drivers/iio/common/st_sensors/st_sensors_core.c
@@ -198,21 +198,17 @@ int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable)
}
EXPORT_SYMBOL(st_sensors_set_axis_enable);
-int st_sensors_init_sensor(struct iio_dev *indio_dev,
- struct st_sensors_platform_data *pdata)
+static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev,
+ struct st_sensors_platform_data *pdata)
{
- int err;
struct st_sensor_data *sdata = iio_priv(indio_dev);
- mutex_init(&sdata->tb.buf_lock);
-
switch (pdata->drdy_int_pin) {
case 1:
if (sdata->sensor->drdy_irq.mask_int1 == 0) {
dev_err(&indio_dev->dev,
"DRDY on INT1 not available.\n");
- err = -EINVAL;
- goto init_error;
+ return -EINVAL;
}
sdata->drdy_int_pin = 1;
break;
@@ -220,39 +216,53 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev,
if (sdata->sensor->drdy_irq.mask_int2 == 0) {
dev_err(&indio_dev->dev,
"DRDY on INT2 not available.\n");
- err = -EINVAL;
- goto init_error;
+ return -EINVAL;
}
sdata->drdy_int_pin = 2;
break;
default:
dev_err(&indio_dev->dev, "DRDY on pdata not valid.\n");
- err = -EINVAL;
- goto init_error;
+ return -EINVAL;
}
+ return 0;
+}
+
+int st_sensors_init_sensor(struct iio_dev *indio_dev,
+ struct st_sensors_platform_data *pdata)
+{
+ struct st_sensor_data *sdata = iio_priv(indio_dev);
+ int err = 0;
+
+ mutex_init(&sdata->tb.buf_lock);
+
+ if (pdata)
+ err = st_sensors_set_drdy_int_pin(indio_dev, pdata);
+
err = st_sensors_set_enable(indio_dev, false);
if (err < 0)
- goto init_error;
+ return err;
- err = st_sensors_set_fullscale(indio_dev,
- sdata->current_fullscale->num);
- if (err < 0)
- goto init_error;
+ if (sdata->current_fullscale) {
+ err = st_sensors_set_fullscale(indio_dev,
+ sdata->current_fullscale->num);
+ if (err < 0)
+ return err;
+ } else
+ dev_info(&indio_dev->dev, "Full-scale not possible\n");
err = st_sensors_set_odr(indio_dev, sdata->odr);
if (err < 0)
- goto init_error;
+ return err;
/* set BDU */
err = st_sensors_write_data_with_mask(indio_dev,
sdata->sensor->bdu.addr, sdata->sensor->bdu.mask, true);
if (err < 0)
- goto init_error;
+ return err;
err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
-init_error:
return err;
}
EXPORT_SYMBOL(st_sensors_init_sensor);
@@ -263,6 +273,9 @@ int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable)
u8 drdy_mask;
struct st_sensor_data *sdata = iio_priv(indio_dev);
+ if (!sdata->sensor->drdy_irq.addr)
+ return 0;
+
/* Enable/Disable the interrupt generator 1. */
if (sdata->sensor->drdy_irq.ig1.en_addr > 0) {
err = st_sensors_write_data_with_mask(indio_dev,
@@ -318,10 +331,8 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
unsigned int byte_for_channel = ch->scan_type.storagebits >> 3;
outdata = kmalloc(byte_for_channel, GFP_KERNEL);
- if (!outdata) {
- err = -EINVAL;
- goto st_sensors_read_axis_data_error;
- }
+ if (!outdata)
+ return -ENOMEM;
err = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
ch->address, byte_for_channel,
@@ -336,7 +347,7 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
st_sensors_free_memory:
kfree(outdata);
-st_sensors_read_axis_data_error:
+
return err;
}
@@ -349,28 +360,25 @@ int st_sensors_read_info_raw(struct iio_dev *indio_dev,
mutex_lock(&indio_dev->mlock);
if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
err = -EBUSY;
- goto read_error;
+ goto out;
} else {
err = st_sensors_set_enable(indio_dev, true);
if (err < 0)
- goto read_error;
+ goto out;
msleep((sdata->sensor->bootime * 1000) / sdata->odr);
err = st_sensors_read_axis_data(indio_dev, ch, val);
if (err < 0)
- goto read_error;
+ goto out;
*val = *val >> ch->scan_type.shift;
err = st_sensors_set_enable(indio_dev, false);
}
+out:
mutex_unlock(&indio_dev->mlock);
return err;
-
-read_error:
- mutex_unlock(&indio_dev->mlock);
- return err;
}
EXPORT_SYMBOL(st_sensors_read_info_raw);
diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c
index a3a52be4852c..b18e8c4347c2 100644
--- a/drivers/iio/dac/ad5064.c
+++ b/drivers/iio/dac/ad5064.c
@@ -285,8 +285,9 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = {
.name = "powerdown",
.read = ad5064_read_dac_powerdown,
.write = ad5064_write_dac_powerdown,
+ .shared = IIO_SEPARATE,
},
- IIO_ENUM("powerdown_mode", false, &ad5064_powerdown_mode_enum),
+ IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5064_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5064_powerdown_mode_enum),
{ },
};
diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c
index 1c44ae3920e2..4c791e66e0d7 100644
--- a/drivers/iio/dac/ad5380.c
+++ b/drivers/iio/dac/ad5380.c
@@ -247,8 +247,10 @@ static struct iio_chan_spec_ext_info ad5380_ext_info[] = {
.name = "powerdown",
.read = ad5380_read_dac_powerdown,
.write = ad5380_write_dac_powerdown,
+ .shared = IIO_SEPARATE,
},
- IIO_ENUM("powerdown_mode", true, &ad5380_powerdown_mode_enum),
+ IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
+ &ad5380_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5380_powerdown_mode_enum),
{ },
};
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c
index 96e9ed4c2d01..6dcb6d93f0e4 100644
--- a/drivers/iio/dac/ad5446.c
+++ b/drivers/iio/dac/ad5446.c
@@ -132,8 +132,9 @@ static const struct iio_chan_spec_ext_info ad5446_ext_info_powerdown[] = {
.name = "powerdown",
.read = ad5446_read_dac_powerdown,
.write = ad5446_write_dac_powerdown,
+ .shared = IIO_SEPARATE,
},
- IIO_ENUM("powerdown_mode", false, &ad5446_powerdown_mode_enum),
+ IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5446_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5446_powerdown_mode_enum),
{ },
};
diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c
index caffb16bc05c..31f4ff29f914 100644
--- a/drivers/iio/dac/ad5504.c
+++ b/drivers/iio/dac/ad5504.c
@@ -248,8 +248,10 @@ static const struct iio_chan_spec_ext_info ad5504_ext_info[] = {
.name = "powerdown",
.read = ad5504_read_dac_powerdown,
.write = ad5504_write_dac_powerdown,
+ .shared = IIO_SEPARATE,
},
- IIO_ENUM("powerdown_mode", true, &ad5504_powerdown_mode_enum),
+ IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
+ &ad5504_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5504_powerdown_mode_enum),
{ },
};
diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c
index 714af757cd56..dbb1289cc7a6 100644
--- a/drivers/iio/dac/ad5624r_spi.c
+++ b/drivers/iio/dac/ad5624r_spi.c
@@ -163,8 +163,10 @@ static const struct iio_chan_spec_ext_info ad5624r_ext_info[] = {
.name = "powerdown",
.read = ad5624r_read_dac_powerdown,
.write = ad5624r_write_dac_powerdown,
+ .shared = IIO_SEPARATE,
},
- IIO_ENUM("powerdown_mode", true, &ad5624r_powerdown_mode_enum),
+ IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
+ &ad5624r_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5624r_powerdown_mode_enum),
{ },
};
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 57825ead7db2..f472b48445f6 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -213,7 +213,6 @@ static int ad5686_read_raw(struct iio_dev *indio_dev,
return ret;
*val = ret;
return IIO_VAL_INT;
- break;
case IIO_CHAN_INFO_SCALE:
scale_uv = (st->vref_mv * 100000)
>> (chan->scan_type.realbits);
@@ -265,8 +264,9 @@ static const struct iio_chan_spec_ext_info ad5686_ext_info[] = {
.name = "powerdown",
.read = ad5686_read_dac_powerdown,
.write = ad5686_write_dac_powerdown,
+ .shared = IIO_SEPARATE,
},
- IIO_ENUM("powerdown_mode", false, &ad5686_powerdown_mode_enum),
+ IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5686_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5686_powerdown_mode_enum),
{ },
};
diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c
index 36a4361aece1..f305a0c83418 100644
--- a/drivers/iio/dac/ad5755.c
+++ b/drivers/iio/dac/ad5755.c
@@ -386,6 +386,7 @@ static const struct iio_chan_spec_ext_info ad5755_ext_info[] = {
.name = "powerdown",
.read = ad5755_read_powerdown,
.write = ad5755_write_powerdown,
+ .shared = IIO_SEPARATE,
},
{ },
};
diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c
index ce7458963309..3cee89be68c3 100644
--- a/drivers/iio/dac/ad5791.c
+++ b/drivers/iio/dac/ad5791.c
@@ -287,11 +287,12 @@ static int ad5791_read_raw(struct iio_dev *indio_dev,
static const struct iio_chan_spec_ext_info ad5791_ext_info[] = {
{
.name = "powerdown",
- .shared = true,
+ .shared = IIO_SHARED_BY_TYPE,
.read = ad5791_read_dac_powerdown,
.write = ad5791_write_dac_powerdown,
},
- IIO_ENUM("powerdown_mode", true, &ad5791_powerdown_mode_enum),
+ IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
+ &ad5791_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &ad5791_powerdown_mode_enum),
{ },
};
diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c
index ed2d276477bd..d0505fd22ef4 100644
--- a/drivers/iio/dac/ad7303.c
+++ b/drivers/iio/dac/ad7303.c
@@ -169,6 +169,7 @@ static const struct iio_chan_spec_ext_info ad7303_ext_info[] = {
.name = "powerdown",
.read = ad7303_read_dac_powerdown,
.write = ad7303_write_dac_powerdown,
+ .shared = IIO_SEPARATE,
},
{ },
};
diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
index 1397b6e0e414..7a42d85269bb 100644
--- a/drivers/iio/dac/mcp4725.c
+++ b/drivers/iio/dac/mcp4725.c
@@ -195,8 +195,9 @@ static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = {
.name = "powerdown",
.read = mcp4725_read_powerdown,
.write = mcp4725_write_powerdown,
+ .shared = IIO_SEPARATE,
},
- IIO_ENUM("powerdown_mode", false, &mcp4725_powerdown_mode_enum),
+ IIO_ENUM("powerdown_mode", IIO_SEPARATE, &mcp4725_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", &mcp4725_powerdown_mode_enum),
{ },
};
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c
index a7b30be86ae0..85152547aa8b 100644
--- a/drivers/iio/frequency/adf4350.c
+++ b/drivers/iio/frequency/adf4350.c
@@ -351,6 +351,7 @@ static ssize_t adf4350_read(struct iio_dev *indio_dev,
.read = adf4350_read, \
.write = adf4350_write, \
.private = _ident, \
+ .shared = IIO_SEPARATE, \
}
static const struct iio_chan_spec_ext_info adf4350_ext_info[] = {
diff --git a/drivers/iio/gyro/adis16130.c b/drivers/iio/gyro/adis16130.c
index ac66fc184042..9155cf6cf287 100644
--- a/drivers/iio/gyro/adis16130.c
+++ b/drivers/iio/gyro/adis16130.c
@@ -103,7 +103,6 @@ static int adis16130_read_raw(struct iio_dev *indio_dev,
default:
return -EINVAL;
}
- break;
case IIO_CHAN_INFO_OFFSET:
switch (chan->type) {
case IIO_ANGL_VEL:
@@ -115,7 +114,6 @@ static int adis16130_read_raw(struct iio_dev *indio_dev,
default:
return -EINVAL;
}
- break;
}
return -EINVAL;
diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c
index 06541162fc02..22b6fb80fa1a 100644
--- a/drivers/iio/gyro/adis16260.c
+++ b/drivers/iio/gyro/adis16260.c
@@ -239,7 +239,6 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
default:
return -EINVAL;
}
- break;
case IIO_CHAN_INFO_OFFSET:
*val = 250000 / 1453; /* 25 C = 0x00 */
return IIO_VAL_INT;
diff --git a/drivers/iio/gyro/adxrs450.c b/drivers/iio/gyro/adxrs450.c
index 6dab2995f0f2..c1f40efbf639 100644
--- a/drivers/iio/gyro/adxrs450.c
+++ b/drivers/iio/gyro/adxrs450.c
@@ -354,7 +354,6 @@ static int adxrs450_read_raw(struct iio_dev *indio_dev,
default:
return -EINVAL;
}
- break;
case IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW:
ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t);
if (ret)
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index c688d974d3e3..ea01c6bcfb56 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -182,10 +182,11 @@ static const struct iio_info gyro_3d_info = {
};
/* Function to push data to buffer */
-static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
+static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data,
+ int len)
{
dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
- iio_push_to_buffers(indio_dev, (u8 *)data);
+ iio_push_to_buffers(indio_dev, data);
}
/* Callback handler to send event after all samples are received and captured */
@@ -200,7 +201,7 @@ static int gyro_3d_proc_event(struct hid_sensor_hub_device *hsdev,
gyro_state->common_attributes.data_ready);
if (gyro_state->common_attributes.data_ready)
hid_sensor_push_data(indio_dev,
- (u8 *)gyro_state->gyro_val,
+ gyro_state->gyro_val,
sizeof(gyro_state->gyro_val));
return 0;
diff --git a/drivers/iio/gyro/itg3200_buffer.c b/drivers/iio/gyro/itg3200_buffer.c
index 6c43af9bb0a4..e3b3c5084070 100644
--- a/drivers/iio/gyro/itg3200_buffer.c
+++ b/drivers/iio/gyro/itg3200_buffer.c
@@ -55,11 +55,8 @@ static irqreturn_t itg3200_trigger_handler(int irq, void *p)
if (ret < 0)
goto error_ret;
- if (indio_dev->scan_timestamp)
- memcpy(buf + indio_dev->scan_bytes - sizeof(s64),
- &pf->timestamp, sizeof(pf->timestamp));
+ iio_push_to_buffers_with_timestamp(indio_dev, buf, pf->timestamp);
- iio_push_to_buffers(indio_dev, (u8 *)buf);
iio_trigger_notify_done(indio_dev->trig);
error_ret:
diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c
index e13c2b0bf3d1..d53d91adfb55 100644
--- a/drivers/iio/gyro/st_gyro_core.c
+++ b/drivers/iio/gyro/st_gyro_core.c
@@ -305,8 +305,9 @@ static const struct iio_trigger_ops st_gyro_trigger_ops = {
int st_gyro_common_probe(struct iio_dev *indio_dev,
struct st_sensors_platform_data *pdata)
{
- int err;
struct st_sensor_data *gdata = iio_priv(indio_dev);
+ int irq = gdata->get_irq_data_ready(indio_dev);
+ int err;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &gyro_info;
@@ -314,7 +315,7 @@ int st_gyro_common_probe(struct iio_dev *indio_dev,
err = st_sensors_check_device_support(indio_dev,
ARRAY_SIZE(st_gyro_sensors), st_gyro_sensors);
if (err < 0)
- goto st_gyro_common_probe_error;
+ return err;
gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS;
gdata->multiread_bit = gdata->sensor->multi_read_bit;
@@ -327,13 +328,13 @@ int st_gyro_common_probe(struct iio_dev *indio_dev,
err = st_sensors_init_sensor(indio_dev, pdata);
if (err < 0)
- goto st_gyro_common_probe_error;
+ return err;
- if (gdata->get_irq_data_ready(indio_dev) > 0) {
- err = st_gyro_allocate_ring(indio_dev);
- if (err < 0)
- goto st_gyro_common_probe_error;
+ err = st_gyro_allocate_ring(indio_dev);
+ if (err < 0)
+ return err;
+ if (irq > 0) {
err = st_sensors_allocate_trigger(indio_dev,
ST_GYRO_TRIGGER_OPS);
if (err < 0)
@@ -344,15 +345,14 @@ int st_gyro_common_probe(struct iio_dev *indio_dev,
if (err)
goto st_gyro_device_register_error;
- return err;
+ return 0;
st_gyro_device_register_error:
- if (gdata->get_irq_data_ready(indio_dev) > 0)
+ if (irq > 0)
st_sensors_deallocate_trigger(indio_dev);
st_gyro_probe_trigger_error:
- if (gdata->get_irq_data_ready(indio_dev) > 0)
- st_gyro_deallocate_ring(indio_dev);
-st_gyro_common_probe_error:
+ st_gyro_deallocate_ring(indio_dev);
+
return err;
}
EXPORT_SYMBOL(st_gyro_common_probe);
@@ -362,10 +362,10 @@ void st_gyro_common_remove(struct iio_dev *indio_dev)
struct st_sensor_data *gdata = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
- if (gdata->get_irq_data_ready(indio_dev) > 0) {
+ if (gdata->get_irq_data_ready(indio_dev) > 0)
st_sensors_deallocate_trigger(indio_dev);
- st_gyro_deallocate_ring(indio_dev);
- }
+
+ st_gyro_deallocate_ring(indio_dev);
}
EXPORT_SYMBOL(st_gyro_common_remove);
diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
index 9b32253b824b..9209f47b273a 100644
--- a/drivers/iio/iio_core.h
+++ b/drivers/iio/iio_core.h
@@ -30,7 +30,7 @@ int __iio_add_chan_devattr(const char *postfix,
const char *buf,
size_t len),
u64 mask,
- bool generic,
+ enum iio_shared_by shared_by,
struct device *dev,
struct list_head *attr_list);
diff --git a/drivers/iio/imu/adis16400_buffer.c b/drivers/iio/imu/adis16400_buffer.c
index 054c01d6e73c..f2cf829e5df1 100644
--- a/drivers/iio/imu/adis16400_buffer.c
+++ b/drivers/iio/imu/adis16400_buffer.c
@@ -82,13 +82,8 @@ irqreturn_t adis16400_trigger_handler(int irq, void *p)
spi_setup(st->adis.spi);
}
- /* Guaranteed to be aligned with 8 byte boundary */
- if (indio_dev->scan_timestamp) {
- void *b = adis->buffer + indio_dev->scan_bytes - sizeof(s64);
- *(s64 *)b = pf->timestamp;
- }
-
- iio_push_to_buffers(indio_dev, adis->buffer);
+ iio_push_to_buffers_with_timestamp(indio_dev, adis->buffer,
+ pf->timestamp);
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c
index 99d8e0b0dd34..cb32b593f1c5 100644
--- a/drivers/iio/imu/adis_buffer.c
+++ b/drivers/iio/imu/adis_buffer.c
@@ -102,13 +102,8 @@ static irqreturn_t adis_trigger_handler(int irq, void *p)
mutex_unlock(&adis->txrx_lock);
}
- /* Guaranteed to be aligned with 8 byte boundary */
- if (indio_dev->scan_timestamp) {
- void *b = adis->buffer + indio_dev->scan_bytes - sizeof(s64);
- *(s64 *)b = pf->timestamp;
- }
-
- iio_push_to_buffers(indio_dev, adis->buffer);
+ iio_push_to_buffers_with_timestamp(indio_dev, adis->buffer,
+ pf->timestamp);
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
index 7da0832f187b..429517117eff 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
@@ -124,7 +124,6 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
u8 data[INV_MPU6050_OUTPUT_DATA_SIZE];
u16 fifo_count;
s64 timestamp;
- u64 *tmp;
mutex_lock(&indio_dev->mlock);
if (!(st->chip_config.accl_fifo_enable |
@@ -170,9 +169,8 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
if (0 == result)
timestamp = 0;
- tmp = (u64 *)data;
- tmp[DIV_ROUND_UP(bytes_per_datum, 8)] = timestamp;
- result = iio_push_to_buffers(indio_dev, data);
+ result = iio_push_to_buffers_with_timestamp(indio_dev, data,
+ timestamp);
if (result)
goto flush_fifo;
fifo_count -= bytes_per_datum;
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 2710f7245c3b..e9f389b9da69 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -31,16 +31,9 @@ static const char * const iio_endian_prefix[] = {
[IIO_LE] = "le",
};
-static bool iio_buffer_is_active(struct iio_dev *indio_dev,
- struct iio_buffer *buf)
+static bool iio_buffer_is_active(struct iio_buffer *buf)
{
- struct list_head *p;
-
- list_for_each(p, &indio_dev->buffer_list)
- if (p == &buf->buffer_list)
- return true;
-
- return false;
+ return !list_empty(&buf->buffer_list);
}
/**
@@ -79,6 +72,7 @@ unsigned int iio_buffer_poll(struct file *filp,
void iio_buffer_init(struct iio_buffer *buffer)
{
INIT_LIST_HEAD(&buffer->demux_list);
+ INIT_LIST_HEAD(&buffer->buffer_list);
init_waitqueue_head(&buffer->pollq);
}
EXPORT_SYMBOL(iio_buffer_init);
@@ -146,7 +140,7 @@ static ssize_t iio_scan_el_store(struct device *dev,
if (ret < 0)
return ret;
mutex_lock(&indio_dev->mlock);
- if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
+ if (iio_buffer_is_active(indio_dev->buffer)) {
ret = -EBUSY;
goto error_ret;
}
@@ -192,7 +186,7 @@ static ssize_t iio_scan_el_ts_store(struct device *dev,
return ret;
mutex_lock(&indio_dev->mlock);
- if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
+ if (iio_buffer_is_active(indio_dev->buffer)) {
ret = -EBUSY;
goto error_ret;
}
@@ -214,7 +208,7 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
&iio_show_scan_index,
NULL,
0,
- 0,
+ IIO_SEPARATE,
&indio_dev->dev,
&buffer->scan_el_dev_attr_list);
if (ret)
@@ -249,6 +243,8 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev,
0,
&indio_dev->dev,
&buffer->scan_el_dev_attr_list);
+ if (ret)
+ goto error_ret;
attrcount++;
ret = attrcount;
error_ret:
@@ -396,7 +392,7 @@ ssize_t iio_buffer_write_length(struct device *dev,
return len;
mutex_lock(&indio_dev->mlock);
- if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
+ if (iio_buffer_is_active(indio_dev->buffer)) {
ret = -EBUSY;
} else {
if (buffer->access->set_length)
@@ -414,13 +410,11 @@ ssize_t iio_buffer_show_enable(struct device *dev,
char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- return sprintf(buf, "%d\n",
- iio_buffer_is_active(indio_dev,
- indio_dev->buffer));
+ return sprintf(buf, "%d\n", iio_buffer_is_active(indio_dev->buffer));
}
EXPORT_SYMBOL(iio_buffer_show_enable);
-/* note NULL used as error indicator as it doesn't make sense. */
+/* Note NULL used as error indicator as it doesn't make sense. */
static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks,
unsigned int masklength,
const unsigned long *mask)
@@ -435,8 +429,8 @@ static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks,
return NULL;
}
-static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const long *mask,
- bool timestamp)
+static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
+ const unsigned long *mask, bool timestamp)
{
const struct iio_chan_spec *ch;
unsigned bytes = 0;
@@ -509,7 +503,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
indio_dev->active_scan_mask = NULL;
if (remove_buffer)
- list_del(&remove_buffer->buffer_list);
+ list_del_init(&remove_buffer->buffer_list);
if (insert_buffer)
list_add(&insert_buffer->buffer_list, &indio_dev->buffer_list);
@@ -521,7 +515,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
return 0;
}
- /* What scan mask do we actually have ?*/
+ /* What scan mask do we actually have? */
compound_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength),
sizeof(long), GFP_KERNEL);
if (compound_mask == NULL) {
@@ -546,7 +540,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
* Roll back.
* Note can only occur when adding a buffer.
*/
- list_del(&insert_buffer->buffer_list);
+ list_del_init(&insert_buffer->buffer_list);
if (old_mask) {
indio_dev->active_scan_mask = old_mask;
success = -EINVAL;
@@ -594,7 +588,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
goto error_run_postdisable;
}
}
- /* Definitely possible for devices to support both of these.*/
+ /* Definitely possible for devices to support both of these. */
if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) {
if (!indio_dev->trig) {
printk(KERN_INFO "Buffer not started: no trigger\n");
@@ -605,7 +599,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
indio_dev->currentmode = INDIO_BUFFER_TRIGGERED;
} else if (indio_dev->modes & INDIO_BUFFER_HARDWARE) {
indio_dev->currentmode = INDIO_BUFFER_HARDWARE;
- } else { /* should never be reached */
+ } else { /* Should never be reached */
ret = -EINVAL;
goto error_run_postdisable;
}
@@ -637,7 +631,7 @@ error_run_postdisable:
error_remove_inserted:
if (insert_buffer)
- list_del(&insert_buffer->buffer_list);
+ list_del_init(&insert_buffer->buffer_list);
indio_dev->active_scan_mask = old_mask;
kfree(compound_mask);
error_ret:
@@ -654,7 +648,6 @@ ssize_t iio_buffer_store_enable(struct device *dev,
int ret;
bool requested_state;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct iio_buffer *pbuf = indio_dev->buffer;
bool inlist;
ret = strtobool(buf, &requested_state);
@@ -664,7 +657,7 @@ ssize_t iio_buffer_store_enable(struct device *dev,
mutex_lock(&indio_dev->mlock);
/* Find out if it is in the list */
- inlist = iio_buffer_is_active(indio_dev, pbuf);
+ inlist = iio_buffer_is_active(indio_dev->buffer);
/* Already in desired state */
if (inlist == requested_state)
goto done;
@@ -729,6 +722,7 @@ static bool iio_validate_scan_mask(struct iio_dev *indio_dev,
/**
* iio_scan_mask_set() - set particular bit in the scan mask
+ * @indio_dev: the iio device
* @buffer: the buffer whose scan mask we are interested in
* @bit: the bit to be set.
*
@@ -749,7 +743,7 @@ int iio_scan_mask_set(struct iio_dev *indio_dev,
if (trialmask == NULL)
return -ENOMEM;
if (!indio_dev->masklength) {
- WARN_ON("trying to set scanmask prior to registering buffer\n");
+ WARN_ON("Trying to set scanmask prior to registering buffer\n");
goto err_invalid_mask;
}
bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength);
@@ -804,8 +798,8 @@ struct iio_demux_table {
struct list_head l;
};
-static unsigned char *iio_demux(struct iio_buffer *buffer,
- unsigned char *datain)
+static const void *iio_demux(struct iio_buffer *buffer,
+ const void *datain)
{
struct iio_demux_table *t;
@@ -818,9 +812,9 @@ static unsigned char *iio_demux(struct iio_buffer *buffer,
return buffer->demux_bounce;
}
-static int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data)
+static int iio_push_to_buffer(struct iio_buffer *buffer, const void *data)
{
- unsigned char *dataout = iio_demux(buffer, data);
+ const void *dataout = iio_demux(buffer, data);
return buffer->access->store_to(buffer, dataout);
}
@@ -835,7 +829,7 @@ static void iio_buffer_demux_free(struct iio_buffer *buffer)
}
-int iio_push_to_buffers(struct iio_dev *indio_dev, unsigned char *data)
+int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data)
{
int ret;
struct iio_buffer *buf;
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 8e84cd522e49..863aa010ce5a 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -101,6 +101,7 @@ static const char * const iio_chan_info_postfix[] = {
[IIO_CHAN_INFO_PHASE] = "phase",
[IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain",
[IIO_CHAN_INFO_HYSTERESIS] = "hysteresis",
+ [IIO_CHAN_INFO_INT_TIME] = "integration_time",
};
const struct iio_chan_spec
@@ -516,14 +517,15 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
struct device_attribute *attr,
const char *buf,
size_t len),
- bool generic)
+ enum iio_shared_by shared_by)
{
- int ret;
- char *name_format, *full_postfix;
+ int ret = 0;
+ char *name_format = NULL;
+ char *full_postfix;
sysfs_attr_init(&dev_attr->attr);
/* Build up postfix of <extend_name>_<modifier>_postfix */
- if (chan->modified && !generic) {
+ if (chan->modified && (shared_by == IIO_SEPARATE)) {
if (chan->extend_name)
full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",
iio_modifier_names[chan
@@ -544,53 +546,78 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
chan->extend_name,
postfix);
}
- if (full_postfix == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ if (full_postfix == NULL)
+ return -ENOMEM;
if (chan->differential) { /* Differential can not have modifier */
- if (generic)
+ switch (shared_by) {
+ case IIO_SHARED_BY_ALL:
+ name_format = kasprintf(GFP_KERNEL, "%s", full_postfix);
+ break;
+ case IIO_SHARED_BY_DIR:
+ name_format = kasprintf(GFP_KERNEL, "%s_%s",
+ iio_direction[chan->output],
+ full_postfix);
+ break;
+ case IIO_SHARED_BY_TYPE:
name_format
= kasprintf(GFP_KERNEL, "%s_%s-%s_%s",
iio_direction[chan->output],
iio_chan_type_name_spec[chan->type],
iio_chan_type_name_spec[chan->type],
full_postfix);
- else if (chan->indexed)
+ break;
+ case IIO_SEPARATE:
+ if (!chan->indexed) {
+ WARN_ON("Differential channels must be indexed\n");
+ ret = -EINVAL;
+ goto error_free_full_postfix;
+ }
name_format
- = kasprintf(GFP_KERNEL, "%s_%s%d-%s%d_%s",
+ = kasprintf(GFP_KERNEL,
+ "%s_%s%d-%s%d_%s",
iio_direction[chan->output],
iio_chan_type_name_spec[chan->type],
chan->channel,
iio_chan_type_name_spec[chan->type],
chan->channel2,
full_postfix);
- else {
- WARN_ON("Differential channels must be indexed\n");
- ret = -EINVAL;
- goto error_free_full_postfix;
+ break;
}
} else { /* Single ended */
- if (generic)
- name_format
- = kasprintf(GFP_KERNEL, "%s_%s_%s",
- iio_direction[chan->output],
- iio_chan_type_name_spec[chan->type],
- full_postfix);
- else if (chan->indexed)
- name_format
- = kasprintf(GFP_KERNEL, "%s_%s%d_%s",
- iio_direction[chan->output],
- iio_chan_type_name_spec[chan->type],
- chan->channel,
- full_postfix);
- else
+ switch (shared_by) {
+ case IIO_SHARED_BY_ALL:
+ name_format = kasprintf(GFP_KERNEL, "%s", full_postfix);
+ break;
+ case IIO_SHARED_BY_DIR:
+ name_format = kasprintf(GFP_KERNEL, "%s_%s",
+ iio_direction[chan->output],
+ full_postfix);
+ break;
+ case IIO_SHARED_BY_TYPE:
name_format
= kasprintf(GFP_KERNEL, "%s_%s_%s",
iio_direction[chan->output],
iio_chan_type_name_spec[chan->type],
full_postfix);
+ break;
+
+ case IIO_SEPARATE:
+ if (chan->indexed)
+ name_format
+ = kasprintf(GFP_KERNEL, "%s_%s%d_%s",
+ iio_direction[chan->output],
+ iio_chan_type_name_spec[chan->type],
+ chan->channel,
+ full_postfix);
+ else
+ name_format
+ = kasprintf(GFP_KERNEL, "%s_%s_%s",
+ iio_direction[chan->output],
+ iio_chan_type_name_spec[chan->type],
+ full_postfix);
+ break;
+ }
}
if (name_format == NULL) {
ret = -ENOMEM;
@@ -614,16 +641,11 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
dev_attr->attr.mode |= S_IWUSR;
dev_attr->store = writefunc;
}
- kfree(name_format);
- kfree(full_postfix);
-
- return 0;
-
error_free_name_format:
kfree(name_format);
error_free_full_postfix:
kfree(full_postfix);
-error_ret:
+
return ret;
}
@@ -642,7 +664,7 @@ int __iio_add_chan_devattr(const char *postfix,
const char *buf,
size_t len),
u64 mask,
- bool generic,
+ enum iio_shared_by shared_by,
struct device *dev,
struct list_head *attr_list)
{
@@ -656,7 +678,7 @@ int __iio_add_chan_devattr(const char *postfix,
}
ret = __iio_device_attr_init(&iio_attr->dev_attr,
postfix, chan,
- readfunc, writefunc, generic);
+ readfunc, writefunc, shared_by);
if (ret)
goto error_iio_dev_attr_free;
iio_attr->c = chan;
@@ -664,7 +686,7 @@ int __iio_add_chan_devattr(const char *postfix,
list_for_each_entry(t, attr_list, l)
if (strcmp(t->dev_attr.attr.name,
iio_attr->dev_attr.attr.name) == 0) {
- if (!generic)
+ if (shared_by == IIO_SEPARATE)
dev_err(dev, "tried to double register : %s\n",
t->dev_attr.attr.name);
ret = -EBUSY;
@@ -682,46 +704,68 @@ error_ret:
return ret;
}
-static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan)
+static int iio_device_add_info_mask_type(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ enum iio_shared_by shared_by,
+ const long *infomask)
{
- int ret, attrcount = 0;
- int i;
- const struct iio_chan_spec_ext_info *ext_info;
+ int i, ret, attrcount = 0;
- if (chan->channel < 0)
- return 0;
- for_each_set_bit(i, &chan->info_mask_separate, sizeof(long)*8) {
+ for_each_set_bit(i, infomask, sizeof(infomask)*8) {
ret = __iio_add_chan_devattr(iio_chan_info_postfix[i],
chan,
&iio_read_channel_info,
&iio_write_channel_info,
i,
- 0,
+ shared_by,
&indio_dev->dev,
&indio_dev->channel_attr_list);
- if (ret < 0)
- goto error_ret;
- attrcount++;
- }
- for_each_set_bit(i, &chan->info_mask_shared_by_type, sizeof(long)*8) {
- ret = __iio_add_chan_devattr(iio_chan_info_postfix[i],
- chan,
- &iio_read_channel_info,
- &iio_write_channel_info,
- i,
- 1,
- &indio_dev->dev,
- &indio_dev->channel_attr_list);
- if (ret == -EBUSY) {
- ret = 0;
+ if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE))
continue;
- } else if (ret < 0) {
- goto error_ret;
- }
+ else if (ret < 0)
+ return ret;
attrcount++;
}
+ return attrcount;
+}
+
+static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan)
+{
+ int ret, attrcount = 0;
+ const struct iio_chan_spec_ext_info *ext_info;
+
+ if (chan->channel < 0)
+ return 0;
+ ret = iio_device_add_info_mask_type(indio_dev, chan,
+ IIO_SEPARATE,
+ &chan->info_mask_separate);
+ if (ret < 0)
+ return ret;
+ attrcount += ret;
+
+ ret = iio_device_add_info_mask_type(indio_dev, chan,
+ IIO_SHARED_BY_TYPE,
+ &chan->info_mask_shared_by_type);
+ if (ret < 0)
+ return ret;
+ attrcount += ret;
+
+ ret = iio_device_add_info_mask_type(indio_dev, chan,
+ IIO_SHARED_BY_DIR,
+ &chan->info_mask_shared_by_dir);
+ if (ret < 0)
+ return ret;
+ attrcount += ret;
+
+ ret = iio_device_add_info_mask_type(indio_dev, chan,
+ IIO_SHARED_BY_ALL,
+ &chan->info_mask_shared_by_all);
+ if (ret < 0)
+ return ret;
+ attrcount += ret;
+
if (chan->ext_info) {
unsigned int i = 0;
for (ext_info = chan->ext_info; ext_info->name; ext_info++) {
@@ -740,15 +784,13 @@ static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
continue;
if (ret)
- goto error_ret;
+ return ret;
attrcount++;
}
}
- ret = attrcount;
-error_ret:
- return ret;
+ return attrcount;
}
static void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev,
diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c
index 6be65ef5faa9..36f0c8e0eb3d 100644
--- a/drivers/iio/industrialio-event.c
+++ b/drivers/iio/industrialio-event.c
@@ -166,7 +166,7 @@ int iio_event_getfd(struct iio_dev *indio_dev)
iio_device_get(indio_dev);
fd = anon_inode_getfd("iio:event", &iio_event_chrdev_fileops,
- indio_dev, O_RDONLY);
+ indio_dev, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
spin_lock_irq(&ev_int->wait.lock);
__clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c
index a923c78d5cb4..538d4616e48f 100644
--- a/drivers/iio/kfifo_buf.c
+++ b/drivers/iio/kfifo_buf.c
@@ -7,6 +7,7 @@
#include <linux/mutex.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/sched.h>
+#include <linux/poll.h>
struct iio_kfifo {
struct iio_buffer buffer;
@@ -94,7 +95,7 @@ static int iio_set_length_kfifo(struct iio_buffer *r, int length)
}
static int iio_store_to_kfifo(struct iio_buffer *r,
- u8 *data)
+ const void *data)
{
int ret;
struct iio_kfifo *kf = iio_to_kfifo(r);
@@ -102,7 +103,7 @@ static int iio_store_to_kfifo(struct iio_buffer *r,
if (ret != 1)
return -EBUSY;
r->stufftoread = true;
- wake_up_interruptible(&r->pollq);
+ wake_up_interruptible_poll(&r->pollq, POLLIN | POLLRDNORM);
return 0;
}
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index bf9fa0d7aff9..0a25ae6b132e 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -27,6 +27,18 @@ config APDS9300
To compile this driver as a module, choose M here: the
module will be called apds9300.
+config GP2AP020A00F
+ tristate "Sharp GP2AP020A00F Proximity/ALS sensor"
+ depends on I2C
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say Y here if you have a Sharp GP2AP020A00F proximity/ALS combo-chip
+ hooked to an I2C bus.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gp2ap020a00f.
+
config HID_SENSOR_ALS
depends on HID_SENSOR_HUB
select IIO_BUFFER
@@ -55,6 +67,16 @@ config SENSORS_LM3533
changes. The ALS-control output values can be set per zone for the
three current output channels.
+config TCS3472
+ tristate "TAOS TCS3472 color light-to-digital converter"
+ depends on I2C
+ help
+ If you say yes here you get support for the TAOS TCS3472
+ family of color light-to-digital converters with IR filter.
+
+ This driver can also be built as a module. If so, the module
+ will be called tcs3472.
+
config SENSORS_TSL2563
tristate "TAOS TSL2560, TSL2561, TSL2562 and TSL2563 ambient light sensors"
depends on I2C
@@ -65,6 +87,16 @@ config SENSORS_TSL2563
This driver can also be built as a module. If so, the module
will be called tsl2563.
+config TSL4531
+ tristate "TAOS TSL4531 ambient light sensors"
+ depends on I2C
+ help
+ Say Y here if you want to build a driver for the TAOS TSL4531 family
+ of ambient light sensors with direct lux output.
+
+ To compile this driver as a module, choose M here: the
+ module will be called tsl4531.
+
config VCNL4000
tristate "VCNL4000 combined ALS and proximity sensor"
depends on I2C
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index 354ee9ab2379..cef590f2ff00 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -5,7 +5,10 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ADJD_S311) += adjd_s311.o
obj-$(CONFIG_APDS9300) += apds9300.o
+obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o
obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o
obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
+obj-$(CONFIG_TCS3472) += tcs3472.o
+obj-$(CONFIG_TSL4531) += tsl4531.o
obj-$(CONFIG_VCNL4000) += vcnl4000.o
diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c
index 23cff798598a..83d15c5baf64 100644
--- a/drivers/iio/light/adjd_s311.c
+++ b/drivers/iio/light/adjd_s311.c
@@ -114,43 +114,6 @@ static int adjd_s311_read_data(struct iio_dev *indio_dev, u8 reg, int *val)
return 0;
}
-static ssize_t adjd_s311_read_int_time(struct iio_dev *indio_dev,
- uintptr_t private, const struct iio_chan_spec *chan, char *buf)
-{
- struct adjd_s311_data *data = iio_priv(indio_dev);
- s32 ret;
-
- ret = i2c_smbus_read_word_data(data->client,
- ADJD_S311_INT_REG(chan->address));
- if (ret < 0)
- return ret;
-
- return sprintf(buf, "%d\n", ret & ADJD_S311_INT_MASK);
-}
-
-static ssize_t adjd_s311_write_int_time(struct iio_dev *indio_dev,
- uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
- size_t len)
-{
- struct adjd_s311_data *data = iio_priv(indio_dev);
- unsigned long int_time;
- int ret;
-
- ret = kstrtoul(buf, 10, &int_time);
- if (ret)
- return ret;
-
- if (int_time > ADJD_S311_INT_MASK)
- return -EINVAL;
-
- ret = i2c_smbus_write_word_data(data->client,
- ADJD_S311_INT_REG(chan->address), int_time);
- if (ret < 0)
- return ret;
-
- return len;
-}
-
static irqreturn_t adjd_s311_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
@@ -175,10 +138,7 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p)
len += 2;
}
- if (indio_dev->scan_timestamp)
- *(s64 *)((u8 *)data->buffer + ALIGN(len, sizeof(s64)))
- = time_ns;
- iio_push_to_buffers(indio_dev, (u8 *)data->buffer);
+ iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, time_ns);
done:
iio_trigger_notify_done(indio_dev->trig);
@@ -186,25 +146,16 @@ done:
return IRQ_HANDLED;
}
-static const struct iio_chan_spec_ext_info adjd_s311_ext_info[] = {
- {
- .name = "integration_time",
- .read = adjd_s311_read_int_time,
- .write = adjd_s311_write_int_time,
- },
- { }
-};
-
#define ADJD_S311_CHANNEL(_color, _scan_idx) { \
.type = IIO_INTENSITY, \
.modified = 1, \
.address = (IDX_##_color), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
- BIT(IIO_CHAN_INFO_HARDWAREGAIN), \
+ BIT(IIO_CHAN_INFO_HARDWAREGAIN) | \
+ BIT(IIO_CHAN_INFO_INT_TIME), \
.channel2 = (IIO_MOD_LIGHT_##_color), \
.scan_index = (_scan_idx), \
.scan_type = IIO_ST('u', 10, 16, 0), \
- .ext_info = adjd_s311_ext_info, \
}
static const struct iio_chan_spec adjd_s311_channels[] = {
@@ -236,6 +187,18 @@ static int adjd_s311_read_raw(struct iio_dev *indio_dev,
return ret;
*val = ret & ADJD_S311_CAP_MASK;
return IIO_VAL_INT;
+ case IIO_CHAN_INFO_INT_TIME:
+ ret = i2c_smbus_read_word_data(data->client,
+ ADJD_S311_INT_REG(chan->address));
+ if (ret < 0)
+ return ret;
+ *val = 0;
+ /*
+ * not documented, based on measurement:
+ * 4095 LSBs correspond to roughly 4 ms
+ */
+ *val2 = ret & ADJD_S311_INT_MASK;
+ return IIO_VAL_INT_PLUS_MICRO;
}
return -EINVAL;
}
@@ -245,16 +208,20 @@ static int adjd_s311_write_raw(struct iio_dev *indio_dev,
int val, int val2, long mask)
{
struct adjd_s311_data *data = iio_priv(indio_dev);
- int ret;
switch (mask) {
case IIO_CHAN_INFO_HARDWAREGAIN:
if (val < 0 || val > ADJD_S311_CAP_MASK)
return -EINVAL;
- ret = i2c_smbus_write_byte_data(data->client,
+ return i2c_smbus_write_byte_data(data->client,
ADJD_S311_CAP_REG(chan->address), val);
- return ret;
+ case IIO_CHAN_INFO_INT_TIME:
+ if (val != 0 || val2 < 0 || val2 > ADJD_S311_INT_MASK)
+ return -EINVAL;
+
+ return i2c_smbus_write_word_data(data->client,
+ ADJD_S311_INT_REG(chan->address), val2);
}
return -EINVAL;
}
diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c
new file mode 100644
index 000000000000..b1e4615b87e8
--- /dev/null
+++ b/drivers/iio/light/gp2ap020a00f.c
@@ -0,0 +1,1617 @@
+/*
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
+ *
+ * IIO features supported by the driver:
+ *
+ * Read-only raw channels:
+ * - illiminance_clear [lux]
+ * - illiminance_ir
+ * - proximity
+ *
+ * Triggered buffer:
+ * - illiminance_clear
+ * - illiminance_ir
+ * - proximity
+ *
+ * Events:
+ * - illuminance_clear (rising and falling)
+ * - proximity (rising and falling)
+ * - both falling and rising thresholds for the proximity events
+ * must be set to the values greater than 0.
+ *
+ * The driver supports triggered buffers for all the three
+ * channels as well as high and low threshold events for the
+ * illuminance_clear and proxmimity channels. Triggers
+ * can be enabled simultaneously with both illuminance_clear
+ * events. Proximity events cannot be enabled simultaneously
+ * with any triggers or illuminance events. Enabling/disabling
+ * one of the proximity events automatically enables/disables
+ * the other one.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irq_work.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/events.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define GP2A_I2C_NAME "gp2ap020a00f"
+
+/* Registers */
+#define GP2AP020A00F_OP_REG 0x00 /* Basic operations */
+#define GP2AP020A00F_ALS_REG 0x01 /* ALS related settings */
+#define GP2AP020A00F_PS_REG 0x02 /* PS related settings */
+#define GP2AP020A00F_LED_REG 0x03 /* LED reg */
+#define GP2AP020A00F_TL_L_REG 0x04 /* ALS: Threshold low LSB */
+#define GP2AP020A00F_TL_H_REG 0x05 /* ALS: Threshold low MSB */
+#define GP2AP020A00F_TH_L_REG 0x06 /* ALS: Threshold high LSB */
+#define GP2AP020A00F_TH_H_REG 0x07 /* ALS: Threshold high MSB */
+#define GP2AP020A00F_PL_L_REG 0x08 /* PS: Threshold low LSB */
+#define GP2AP020A00F_PL_H_REG 0x09 /* PS: Threshold low MSB */
+#define GP2AP020A00F_PH_L_REG 0x0a /* PS: Threshold high LSB */
+#define GP2AP020A00F_PH_H_REG 0x0b /* PS: Threshold high MSB */
+#define GP2AP020A00F_D0_L_REG 0x0c /* ALS result: Clear/Illuminance LSB */
+#define GP2AP020A00F_D0_H_REG 0x0d /* ALS result: Clear/Illuminance MSB */
+#define GP2AP020A00F_D1_L_REG 0x0e /* ALS result: IR LSB */
+#define GP2AP020A00F_D1_H_REG 0x0f /* ALS result: IR LSB */
+#define GP2AP020A00F_D2_L_REG 0x10 /* PS result LSB */
+#define GP2AP020A00F_D2_H_REG 0x11 /* PS result MSB */
+#define GP2AP020A00F_NUM_REGS 0x12 /* Number of registers */
+
+/* OP_REG bits */
+#define GP2AP020A00F_OP3_MASK 0x80 /* Software shutdown */
+#define GP2AP020A00F_OP3_SHUTDOWN 0x00
+#define GP2AP020A00F_OP3_OPERATION 0x80
+#define GP2AP020A00F_OP2_MASK 0x40 /* Auto shutdown/Continuous mode */
+#define GP2AP020A00F_OP2_AUTO_SHUTDOWN 0x00
+#define GP2AP020A00F_OP2_CONT_OPERATION 0x40
+#define GP2AP020A00F_OP_MASK 0x30 /* Operating mode selection */
+#define GP2AP020A00F_OP_ALS_AND_PS 0x00
+#define GP2AP020A00F_OP_ALS 0x10
+#define GP2AP020A00F_OP_PS 0x20
+#define GP2AP020A00F_OP_DEBUG 0x30
+#define GP2AP020A00F_PROX_MASK 0x08 /* PS: detection/non-detection */
+#define GP2AP020A00F_PROX_NON_DETECT 0x00
+#define GP2AP020A00F_PROX_DETECT 0x08
+#define GP2AP020A00F_FLAG_P 0x04 /* PS: interrupt result */
+#define GP2AP020A00F_FLAG_A 0x02 /* ALS: interrupt result */
+#define GP2AP020A00F_TYPE_MASK 0x01 /* Output data type selection */
+#define GP2AP020A00F_TYPE_MANUAL_CALC 0x00
+#define GP2AP020A00F_TYPE_AUTO_CALC 0x01
+
+/* ALS_REG bits */
+#define GP2AP020A00F_PRST_MASK 0xc0 /* Number of measurement cycles */
+#define GP2AP020A00F_PRST_ONCE 0x00
+#define GP2AP020A00F_PRST_4_CYCLES 0x40
+#define GP2AP020A00F_PRST_8_CYCLES 0x80
+#define GP2AP020A00F_PRST_16_CYCLES 0xc0
+#define GP2AP020A00F_RES_A_MASK 0x38 /* ALS: Resolution */
+#define GP2AP020A00F_RES_A_800ms 0x00
+#define GP2AP020A00F_RES_A_400ms 0x08
+#define GP2AP020A00F_RES_A_200ms 0x10
+#define GP2AP020A00F_RES_A_100ms 0x18
+#define GP2AP020A00F_RES_A_25ms 0x20
+#define GP2AP020A00F_RES_A_6_25ms 0x28
+#define GP2AP020A00F_RES_A_1_56ms 0x30
+#define GP2AP020A00F_RES_A_0_39ms 0x38
+#define GP2AP020A00F_RANGE_A_MASK 0x07 /* ALS: Max measurable range */
+#define GP2AP020A00F_RANGE_A_x1 0x00
+#define GP2AP020A00F_RANGE_A_x2 0x01
+#define GP2AP020A00F_RANGE_A_x4 0x02
+#define GP2AP020A00F_RANGE_A_x8 0x03
+#define GP2AP020A00F_RANGE_A_x16 0x04
+#define GP2AP020A00F_RANGE_A_x32 0x05
+#define GP2AP020A00F_RANGE_A_x64 0x06
+#define GP2AP020A00F_RANGE_A_x128 0x07
+
+/* PS_REG bits */
+#define GP2AP020A00F_ALC_MASK 0x80 /* Auto light cancel */
+#define GP2AP020A00F_ALC_ON 0x80
+#define GP2AP020A00F_ALC_OFF 0x00
+#define GP2AP020A00F_INTTYPE_MASK 0x40 /* Interrupt type setting */
+#define GP2AP020A00F_INTTYPE_LEVEL 0x00
+#define GP2AP020A00F_INTTYPE_PULSE 0x40
+#define GP2AP020A00F_RES_P_MASK 0x38 /* PS: Resolution */
+#define GP2AP020A00F_RES_P_800ms_x2 0x00
+#define GP2AP020A00F_RES_P_400ms_x2 0x08
+#define GP2AP020A00F_RES_P_200ms_x2 0x10
+#define GP2AP020A00F_RES_P_100ms_x2 0x18
+#define GP2AP020A00F_RES_P_25ms_x2 0x20
+#define GP2AP020A00F_RES_P_6_25ms_x2 0x28
+#define GP2AP020A00F_RES_P_1_56ms_x2 0x30
+#define GP2AP020A00F_RES_P_0_39ms_x2 0x38
+#define GP2AP020A00F_RANGE_P_MASK 0x07 /* PS: Max measurable range */
+#define GP2AP020A00F_RANGE_P_x1 0x00
+#define GP2AP020A00F_RANGE_P_x2 0x01
+#define GP2AP020A00F_RANGE_P_x4 0x02
+#define GP2AP020A00F_RANGE_P_x8 0x03
+#define GP2AP020A00F_RANGE_P_x16 0x04
+#define GP2AP020A00F_RANGE_P_x32 0x05
+#define GP2AP020A00F_RANGE_P_x64 0x06
+#define GP2AP020A00F_RANGE_P_x128 0x07
+
+/* LED reg bits */
+#define GP2AP020A00F_INTVAL_MASK 0xc0 /* Intermittent operating */
+#define GP2AP020A00F_INTVAL_0 0x00
+#define GP2AP020A00F_INTVAL_4 0x40
+#define GP2AP020A00F_INTVAL_8 0x80
+#define GP2AP020A00F_INTVAL_16 0xc0
+#define GP2AP020A00F_IS_MASK 0x30 /* ILED drive peak current */
+#define GP2AP020A00F_IS_13_8mA 0x00
+#define GP2AP020A00F_IS_27_5mA 0x10
+#define GP2AP020A00F_IS_55mA 0x20
+#define GP2AP020A00F_IS_110mA 0x30
+#define GP2AP020A00F_PIN_MASK 0x0c /* INT terminal setting */
+#define GP2AP020A00F_PIN_ALS_OR_PS 0x00
+#define GP2AP020A00F_PIN_ALS 0x04
+#define GP2AP020A00F_PIN_PS 0x08
+#define GP2AP020A00F_PIN_PS_DETECT 0x0c
+#define GP2AP020A00F_FREQ_MASK 0x02 /* LED modulation frequency */
+#define GP2AP020A00F_FREQ_327_5kHz 0x00
+#define GP2AP020A00F_FREQ_81_8kHz 0x02
+#define GP2AP020A00F_RST 0x01 /* Software reset */
+
+#define GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR 0
+#define GP2AP020A00F_SCAN_MODE_LIGHT_IR 1
+#define GP2AP020A00F_SCAN_MODE_PROXIMITY 2
+#define GP2AP020A00F_CHAN_TIMESTAMP 3
+
+#define GP2AP020A00F_DATA_READY_TIMEOUT msecs_to_jiffies(1000)
+#define GP2AP020A00F_DATA_REG(chan) (GP2AP020A00F_D0_L_REG + \
+ (chan) * 2)
+#define GP2AP020A00F_THRESH_REG(th_val_id) (GP2AP020A00F_TL_L_REG + \
+ (th_val_id) * 2)
+#define GP2AP020A00F_THRESH_VAL_ID(reg_addr) ((reg_addr - 4) / 2)
+
+#define GP2AP020A00F_SUBTRACT_MODE 0
+#define GP2AP020A00F_ADD_MODE 1
+
+#define GP2AP020A00F_MAX_CHANNELS 3
+
+enum gp2ap020a00f_opmode {
+ GP2AP020A00F_OPMODE_READ_RAW_CLEAR,
+ GP2AP020A00F_OPMODE_READ_RAW_IR,
+ GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY,
+ GP2AP020A00F_OPMODE_ALS,
+ GP2AP020A00F_OPMODE_PS,
+ GP2AP020A00F_OPMODE_ALS_AND_PS,
+ GP2AP020A00F_OPMODE_PROX_DETECT,
+ GP2AP020A00F_OPMODE_SHUTDOWN,
+ GP2AP020A00F_NUM_OPMODES,
+};
+
+enum gp2ap020a00f_cmd {
+ GP2AP020A00F_CMD_READ_RAW_CLEAR,
+ GP2AP020A00F_CMD_READ_RAW_IR,
+ GP2AP020A00F_CMD_READ_RAW_PROXIMITY,
+ GP2AP020A00F_CMD_TRIGGER_CLEAR_EN,
+ GP2AP020A00F_CMD_TRIGGER_CLEAR_DIS,
+ GP2AP020A00F_CMD_TRIGGER_IR_EN,
+ GP2AP020A00F_CMD_TRIGGER_IR_DIS,
+ GP2AP020A00F_CMD_TRIGGER_PROX_EN,
+ GP2AP020A00F_CMD_TRIGGER_PROX_DIS,
+ GP2AP020A00F_CMD_ALS_HIGH_EV_EN,
+ GP2AP020A00F_CMD_ALS_HIGH_EV_DIS,
+ GP2AP020A00F_CMD_ALS_LOW_EV_EN,
+ GP2AP020A00F_CMD_ALS_LOW_EV_DIS,
+ GP2AP020A00F_CMD_PROX_HIGH_EV_EN,
+ GP2AP020A00F_CMD_PROX_HIGH_EV_DIS,
+ GP2AP020A00F_CMD_PROX_LOW_EV_EN,
+ GP2AP020A00F_CMD_PROX_LOW_EV_DIS,
+};
+
+enum gp2ap020a00f_flags {
+ GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER,
+ GP2AP020A00F_FLAG_ALS_IR_TRIGGER,
+ GP2AP020A00F_FLAG_PROX_TRIGGER,
+ GP2AP020A00F_FLAG_PROX_RISING_EV,
+ GP2AP020A00F_FLAG_PROX_FALLING_EV,
+ GP2AP020A00F_FLAG_ALS_RISING_EV,
+ GP2AP020A00F_FLAG_ALS_FALLING_EV,
+ GP2AP020A00F_FLAG_LUX_MODE_HI,
+ GP2AP020A00F_FLAG_DATA_READY,
+};
+
+enum gp2ap020a00f_thresh_val_id {
+ GP2AP020A00F_THRESH_TL,
+ GP2AP020A00F_THRESH_TH,
+ GP2AP020A00F_THRESH_PL,
+ GP2AP020A00F_THRESH_PH,
+};
+
+struct gp2ap020a00f_data {
+ const struct gp2ap020a00f_platform_data *pdata;
+ struct i2c_client *client;
+ struct mutex lock;
+ char *buffer;
+ struct regulator *vled_reg;
+ unsigned long flags;
+ enum gp2ap020a00f_opmode cur_opmode;
+ struct iio_trigger *trig;
+ struct regmap *regmap;
+ unsigned int thresh_val[4];
+ u8 debug_reg_addr;
+ struct irq_work work;
+ wait_queue_head_t data_ready_queue;
+};
+
+static const u8 gp2ap020a00f_reg_init_tab[] = {
+ [GP2AP020A00F_OP_REG] = GP2AP020A00F_OP3_SHUTDOWN,
+ [GP2AP020A00F_ALS_REG] = GP2AP020A00F_RES_A_25ms |
+ GP2AP020A00F_RANGE_A_x8,
+ [GP2AP020A00F_PS_REG] = GP2AP020A00F_ALC_ON |
+ GP2AP020A00F_RES_P_1_56ms_x2 |
+ GP2AP020A00F_RANGE_P_x4,
+ [GP2AP020A00F_LED_REG] = GP2AP020A00F_INTVAL_0 |
+ GP2AP020A00F_IS_110mA |
+ GP2AP020A00F_FREQ_327_5kHz,
+ [GP2AP020A00F_TL_L_REG] = 0,
+ [GP2AP020A00F_TL_H_REG] = 0,
+ [GP2AP020A00F_TH_L_REG] = 0,
+ [GP2AP020A00F_TH_H_REG] = 0,
+ [GP2AP020A00F_PL_L_REG] = 0,
+ [GP2AP020A00F_PL_H_REG] = 0,
+ [GP2AP020A00F_PH_L_REG] = 0,
+ [GP2AP020A00F_PH_H_REG] = 0,
+};
+
+static bool gp2ap020a00f_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case GP2AP020A00F_OP_REG:
+ case GP2AP020A00F_D0_L_REG:
+ case GP2AP020A00F_D0_H_REG:
+ case GP2AP020A00F_D1_L_REG:
+ case GP2AP020A00F_D1_H_REG:
+ case GP2AP020A00F_D2_L_REG:
+ case GP2AP020A00F_D2_H_REG:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_config gp2ap020a00f_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = GP2AP020A00F_D2_H_REG,
+ .cache_type = REGCACHE_RBTREE,
+
+ .volatile_reg = gp2ap020a00f_is_volatile_reg,
+};
+
+static const struct gp2ap020a00f_mutable_config_regs {
+ u8 op_reg;
+ u8 als_reg;
+ u8 ps_reg;
+ u8 led_reg;
+} opmode_regs_settings[GP2AP020A00F_NUM_OPMODES] = {
+ [GP2AP020A00F_OPMODE_READ_RAW_CLEAR] = {
+ GP2AP020A00F_OP_ALS | GP2AP020A00F_OP2_CONT_OPERATION
+ | GP2AP020A00F_OP3_OPERATION
+ | GP2AP020A00F_TYPE_AUTO_CALC,
+ GP2AP020A00F_PRST_ONCE,
+ GP2AP020A00F_INTTYPE_LEVEL,
+ GP2AP020A00F_PIN_ALS
+ },
+ [GP2AP020A00F_OPMODE_READ_RAW_IR] = {
+ GP2AP020A00F_OP_ALS | GP2AP020A00F_OP2_CONT_OPERATION
+ | GP2AP020A00F_OP3_OPERATION
+ | GP2AP020A00F_TYPE_MANUAL_CALC,
+ GP2AP020A00F_PRST_ONCE,
+ GP2AP020A00F_INTTYPE_LEVEL,
+ GP2AP020A00F_PIN_ALS
+ },
+ [GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY] = {
+ GP2AP020A00F_OP_PS | GP2AP020A00F_OP2_CONT_OPERATION
+ | GP2AP020A00F_OP3_OPERATION
+ | GP2AP020A00F_TYPE_MANUAL_CALC,
+ GP2AP020A00F_PRST_ONCE,
+ GP2AP020A00F_INTTYPE_LEVEL,
+ GP2AP020A00F_PIN_PS
+ },
+ [GP2AP020A00F_OPMODE_PROX_DETECT] = {
+ GP2AP020A00F_OP_PS | GP2AP020A00F_OP2_CONT_OPERATION
+ | GP2AP020A00F_OP3_OPERATION
+ | GP2AP020A00F_TYPE_MANUAL_CALC,
+ GP2AP020A00F_PRST_4_CYCLES,
+ GP2AP020A00F_INTTYPE_PULSE,
+ GP2AP020A00F_PIN_PS_DETECT
+ },
+ [GP2AP020A00F_OPMODE_ALS] = {
+ GP2AP020A00F_OP_ALS | GP2AP020A00F_OP2_CONT_OPERATION
+ | GP2AP020A00F_OP3_OPERATION
+ | GP2AP020A00F_TYPE_AUTO_CALC,
+ GP2AP020A00F_PRST_ONCE,
+ GP2AP020A00F_INTTYPE_LEVEL,
+ GP2AP020A00F_PIN_ALS
+ },
+ [GP2AP020A00F_OPMODE_PS] = {
+ GP2AP020A00F_OP_PS | GP2AP020A00F_OP2_CONT_OPERATION
+ | GP2AP020A00F_OP3_OPERATION
+ | GP2AP020A00F_TYPE_MANUAL_CALC,
+ GP2AP020A00F_PRST_4_CYCLES,
+ GP2AP020A00F_INTTYPE_LEVEL,
+ GP2AP020A00F_PIN_PS
+ },
+ [GP2AP020A00F_OPMODE_ALS_AND_PS] = {
+ GP2AP020A00F_OP_ALS_AND_PS
+ | GP2AP020A00F_OP2_CONT_OPERATION
+ | GP2AP020A00F_OP3_OPERATION
+ | GP2AP020A00F_TYPE_AUTO_CALC,
+ GP2AP020A00F_PRST_4_CYCLES,
+ GP2AP020A00F_INTTYPE_LEVEL,
+ GP2AP020A00F_PIN_ALS_OR_PS
+ },
+ [GP2AP020A00F_OPMODE_SHUTDOWN] = { GP2AP020A00F_OP3_SHUTDOWN, },
+};
+
+static int gp2ap020a00f_set_operation_mode(struct gp2ap020a00f_data *data,
+ enum gp2ap020a00f_opmode op)
+{
+ unsigned int op_reg_val;
+ int err;
+
+ if (op != GP2AP020A00F_OPMODE_SHUTDOWN) {
+ err = regmap_read(data->regmap, GP2AP020A00F_OP_REG,
+ &op_reg_val);
+ if (err < 0)
+ return err;
+ /*
+ * Shutdown the device if the operation being executed entails
+ * mode transition.
+ */
+ if ((opmode_regs_settings[op].op_reg & GP2AP020A00F_OP_MASK) !=
+ (op_reg_val & GP2AP020A00F_OP_MASK)) {
+ /* set shutdown mode */
+ err = regmap_update_bits(data->regmap,
+ GP2AP020A00F_OP_REG, GP2AP020A00F_OP3_MASK,
+ GP2AP020A00F_OP3_SHUTDOWN);
+ if (err < 0)
+ return err;
+ }
+
+ err = regmap_update_bits(data->regmap, GP2AP020A00F_ALS_REG,
+ GP2AP020A00F_PRST_MASK, opmode_regs_settings[op]
+ .als_reg);
+ if (err < 0)
+ return err;
+
+ err = regmap_update_bits(data->regmap, GP2AP020A00F_PS_REG,
+ GP2AP020A00F_INTTYPE_MASK, opmode_regs_settings[op]
+ .ps_reg);
+ if (err < 0)
+ return err;
+
+ err = regmap_update_bits(data->regmap, GP2AP020A00F_LED_REG,
+ GP2AP020A00F_PIN_MASK, opmode_regs_settings[op]
+ .led_reg);
+ if (err < 0)
+ return err;
+ }
+
+ /* Set OP_REG and apply operation mode (power on / off) */
+ err = regmap_update_bits(data->regmap,
+ GP2AP020A00F_OP_REG,
+ GP2AP020A00F_OP_MASK | GP2AP020A00F_OP2_MASK |
+ GP2AP020A00F_OP3_MASK | GP2AP020A00F_TYPE_MASK,
+ opmode_regs_settings[op].op_reg);
+ if (err < 0)
+ return err;
+
+ data->cur_opmode = op;
+
+ return 0;
+}
+
+static bool gp2ap020a00f_als_enabled(struct gp2ap020a00f_data *data)
+{
+ return test_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &data->flags) ||
+ test_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &data->flags) ||
+ test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags) ||
+ test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags);
+}
+
+static bool gp2ap020a00f_prox_detect_enabled(struct gp2ap020a00f_data *data)
+{
+ return test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags) ||
+ test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags);
+}
+
+static int gp2ap020a00f_write_event_threshold(struct gp2ap020a00f_data *data,
+ enum gp2ap020a00f_thresh_val_id th_val_id,
+ bool enable)
+{
+ __le16 thresh_buf = 0;
+ unsigned int thresh_reg_val;
+
+ if (!enable)
+ thresh_reg_val = 0;
+ else if (test_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags) &&
+ th_val_id != GP2AP020A00F_THRESH_PL &&
+ th_val_id != GP2AP020A00F_THRESH_PH)
+ /*
+ * For the high lux mode ALS threshold has to be scaled down
+ * to allow for proper comparison with the output value.
+ */
+ thresh_reg_val = data->thresh_val[th_val_id] / 16;
+ else
+ thresh_reg_val = data->thresh_val[th_val_id] > 16000 ?
+ 16000 :
+ data->thresh_val[th_val_id];
+
+ thresh_buf = cpu_to_le16(thresh_reg_val);
+
+ return regmap_bulk_write(data->regmap,
+ GP2AP020A00F_THRESH_REG(th_val_id),
+ (u8 *)&thresh_buf, 2);
+}
+
+static int gp2ap020a00f_alter_opmode(struct gp2ap020a00f_data *data,
+ enum gp2ap020a00f_opmode diff_mode, int add_sub)
+{
+ enum gp2ap020a00f_opmode new_mode;
+
+ if (diff_mode != GP2AP020A00F_OPMODE_ALS &&
+ diff_mode != GP2AP020A00F_OPMODE_PS)
+ return -EINVAL;
+
+ if (add_sub == GP2AP020A00F_ADD_MODE) {
+ if (data->cur_opmode == GP2AP020A00F_OPMODE_SHUTDOWN)
+ new_mode = diff_mode;
+ else
+ new_mode = GP2AP020A00F_OPMODE_ALS_AND_PS;
+ } else {
+ if (data->cur_opmode == GP2AP020A00F_OPMODE_ALS_AND_PS)
+ new_mode = (diff_mode == GP2AP020A00F_OPMODE_ALS) ?
+ GP2AP020A00F_OPMODE_PS :
+ GP2AP020A00F_OPMODE_ALS;
+ else
+ new_mode = GP2AP020A00F_OPMODE_SHUTDOWN;
+ }
+
+ return gp2ap020a00f_set_operation_mode(data, new_mode);
+}
+
+static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data,
+ enum gp2ap020a00f_cmd cmd)
+{
+ int err = 0;
+
+ switch (cmd) {
+ case GP2AP020A00F_CMD_READ_RAW_CLEAR:
+ if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN)
+ return -EBUSY;
+ err = gp2ap020a00f_set_operation_mode(data,
+ GP2AP020A00F_OPMODE_READ_RAW_CLEAR);
+ break;
+ case GP2AP020A00F_CMD_READ_RAW_IR:
+ if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN)
+ return -EBUSY;
+ err = gp2ap020a00f_set_operation_mode(data,
+ GP2AP020A00F_OPMODE_READ_RAW_IR);
+ break;
+ case GP2AP020A00F_CMD_READ_RAW_PROXIMITY:
+ if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN)
+ return -EBUSY;
+ err = gp2ap020a00f_set_operation_mode(data,
+ GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY);
+ break;
+ case GP2AP020A00F_CMD_TRIGGER_CLEAR_EN:
+ if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
+ return -EBUSY;
+ if (!gp2ap020a00f_als_enabled(data))
+ err = gp2ap020a00f_alter_opmode(data,
+ GP2AP020A00F_OPMODE_ALS,
+ GP2AP020A00F_ADD_MODE);
+ set_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &data->flags);
+ break;
+ case GP2AP020A00F_CMD_TRIGGER_CLEAR_DIS:
+ clear_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &data->flags);
+ if (gp2ap020a00f_als_enabled(data))
+ break;
+ err = gp2ap020a00f_alter_opmode(data,
+ GP2AP020A00F_OPMODE_ALS,
+ GP2AP020A00F_SUBTRACT_MODE);
+ break;
+ case GP2AP020A00F_CMD_TRIGGER_IR_EN:
+ if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
+ return -EBUSY;
+ if (!gp2ap020a00f_als_enabled(data))
+ err = gp2ap020a00f_alter_opmode(data,
+ GP2AP020A00F_OPMODE_ALS,
+ GP2AP020A00F_ADD_MODE);
+ set_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &data->flags);
+ break;
+ case GP2AP020A00F_CMD_TRIGGER_IR_DIS:
+ clear_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &data->flags);
+ if (gp2ap020a00f_als_enabled(data))
+ break;
+ err = gp2ap020a00f_alter_opmode(data,
+ GP2AP020A00F_OPMODE_ALS,
+ GP2AP020A00F_SUBTRACT_MODE);
+ break;
+ case GP2AP020A00F_CMD_TRIGGER_PROX_EN:
+ if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
+ return -EBUSY;
+ err = gp2ap020a00f_alter_opmode(data,
+ GP2AP020A00F_OPMODE_PS,
+ GP2AP020A00F_ADD_MODE);
+ set_bit(GP2AP020A00F_FLAG_PROX_TRIGGER, &data->flags);
+ break;
+ case GP2AP020A00F_CMD_TRIGGER_PROX_DIS:
+ clear_bit(GP2AP020A00F_FLAG_PROX_TRIGGER, &data->flags);
+ err = gp2ap020a00f_alter_opmode(data,
+ GP2AP020A00F_OPMODE_PS,
+ GP2AP020A00F_SUBTRACT_MODE);
+ break;
+ case GP2AP020A00F_CMD_ALS_HIGH_EV_EN:
+ if (test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags))
+ return 0;
+ if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
+ return -EBUSY;
+ if (!gp2ap020a00f_als_enabled(data)) {
+ err = gp2ap020a00f_alter_opmode(data,
+ GP2AP020A00F_OPMODE_ALS,
+ GP2AP020A00F_ADD_MODE);
+ if (err < 0)
+ return err;
+ }
+ set_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags);
+ err = gp2ap020a00f_write_event_threshold(data,
+ GP2AP020A00F_THRESH_TH, true);
+ break;
+ case GP2AP020A00F_CMD_ALS_HIGH_EV_DIS:
+ if (!test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags))
+ return 0;
+ clear_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags);
+ if (!gp2ap020a00f_als_enabled(data)) {
+ err = gp2ap020a00f_alter_opmode(data,
+ GP2AP020A00F_OPMODE_ALS,
+ GP2AP020A00F_SUBTRACT_MODE);
+ if (err < 0)
+ return err;
+ }
+ err = gp2ap020a00f_write_event_threshold(data,
+ GP2AP020A00F_THRESH_TH, false);
+ break;
+ case GP2AP020A00F_CMD_ALS_LOW_EV_EN:
+ if (test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags))
+ return 0;
+ if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
+ return -EBUSY;
+ if (!gp2ap020a00f_als_enabled(data)) {
+ err = gp2ap020a00f_alter_opmode(data,
+ GP2AP020A00F_OPMODE_ALS,
+ GP2AP020A00F_ADD_MODE);
+ if (err < 0)
+ return err;
+ }
+ set_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags);
+ err = gp2ap020a00f_write_event_threshold(data,
+ GP2AP020A00F_THRESH_TL, true);
+ break;
+ case GP2AP020A00F_CMD_ALS_LOW_EV_DIS:
+ if (!test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags))
+ return 0;
+ clear_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags);
+ if (!gp2ap020a00f_als_enabled(data)) {
+ err = gp2ap020a00f_alter_opmode(data,
+ GP2AP020A00F_OPMODE_ALS,
+ GP2AP020A00F_SUBTRACT_MODE);
+ if (err < 0)
+ return err;
+ }
+ err = gp2ap020a00f_write_event_threshold(data,
+ GP2AP020A00F_THRESH_TL, false);
+ break;
+ case GP2AP020A00F_CMD_PROX_HIGH_EV_EN:
+ if (test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags))
+ return 0;
+ if (gp2ap020a00f_als_enabled(data) ||
+ data->cur_opmode == GP2AP020A00F_OPMODE_PS)
+ return -EBUSY;
+ if (!gp2ap020a00f_prox_detect_enabled(data)) {
+ err = gp2ap020a00f_set_operation_mode(data,
+ GP2AP020A00F_OPMODE_PROX_DETECT);
+ if (err < 0)
+ return err;
+ }
+ set_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags);
+ err = gp2ap020a00f_write_event_threshold(data,
+ GP2AP020A00F_THRESH_PH, true);
+ break;
+ case GP2AP020A00F_CMD_PROX_HIGH_EV_DIS:
+ if (!test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags))
+ return 0;
+ clear_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags);
+ err = gp2ap020a00f_set_operation_mode(data,
+ GP2AP020A00F_OPMODE_SHUTDOWN);
+ if (err < 0)
+ return err;
+ err = gp2ap020a00f_write_event_threshold(data,
+ GP2AP020A00F_THRESH_PH, false);
+ break;
+ case GP2AP020A00F_CMD_PROX_LOW_EV_EN:
+ if (test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags))
+ return 0;
+ if (gp2ap020a00f_als_enabled(data) ||
+ data->cur_opmode == GP2AP020A00F_OPMODE_PS)
+ return -EBUSY;
+ if (!gp2ap020a00f_prox_detect_enabled(data)) {
+ err = gp2ap020a00f_set_operation_mode(data,
+ GP2AP020A00F_OPMODE_PROX_DETECT);
+ if (err < 0)
+ return err;
+ }
+ set_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags);
+ err = gp2ap020a00f_write_event_threshold(data,
+ GP2AP020A00F_THRESH_PL, true);
+ break;
+ case GP2AP020A00F_CMD_PROX_LOW_EV_DIS:
+ if (!test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags))
+ return 0;
+ clear_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags);
+ err = gp2ap020a00f_set_operation_mode(data,
+ GP2AP020A00F_OPMODE_SHUTDOWN);
+ if (err < 0)
+ return err;
+ err = gp2ap020a00f_write_event_threshold(data,
+ GP2AP020A00F_THRESH_PL, false);
+ break;
+ }
+
+ return err;
+}
+
+static int wait_conversion_complete_irq(struct gp2ap020a00f_data *data)
+{
+ int ret;
+
+ ret = wait_event_timeout(data->data_ready_queue,
+ test_bit(GP2AP020A00F_FLAG_DATA_READY,
+ &data->flags),
+ GP2AP020A00F_DATA_READY_TIMEOUT);
+ clear_bit(GP2AP020A00F_FLAG_DATA_READY, &data->flags);
+
+ return ret > 0 ? 0 : -ETIME;
+}
+
+static int gp2ap020a00f_read_output(struct gp2ap020a00f_data *data,
+ unsigned int output_reg, int *val)
+{
+ u8 reg_buf[2];
+ int err;
+
+ err = wait_conversion_complete_irq(data);
+ if (err < 0)
+ dev_dbg(&data->client->dev, "data ready timeout\n");
+
+ err = regmap_bulk_read(data->regmap, output_reg, reg_buf, 2);
+ if (err < 0)
+ return err;
+
+ *val = le16_to_cpup((__le16 *)reg_buf);
+
+ return err;
+}
+
+static bool gp2ap020a00f_adjust_lux_mode(struct gp2ap020a00f_data *data,
+ int output_val)
+{
+ u8 new_range = 0xff;
+ int err;
+
+ if (!test_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags)) {
+ if (output_val > 16000) {
+ set_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags);
+ new_range = GP2AP020A00F_RANGE_A_x128;
+ }
+ } else {
+ if (output_val < 1000) {
+ clear_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags);
+ new_range = GP2AP020A00F_RANGE_A_x8;
+ }
+ }
+
+ if (new_range != 0xff) {
+ /* Clear als threshold registers to avoid spurious
+ * events caused by lux mode transition.
+ */
+ err = gp2ap020a00f_write_event_threshold(data,
+ GP2AP020A00F_THRESH_TH, false);
+ if (err < 0) {
+ dev_err(&data->client->dev,
+ "Clearing als threshold register failed.\n");
+ return false;
+ }
+
+ err = gp2ap020a00f_write_event_threshold(data,
+ GP2AP020A00F_THRESH_TL, false);
+ if (err < 0) {
+ dev_err(&data->client->dev,
+ "Clearing als threshold register failed.\n");
+ return false;
+ }
+
+ /* Change lux mode */
+ err = regmap_update_bits(data->regmap,
+ GP2AP020A00F_OP_REG,
+ GP2AP020A00F_OP3_MASK,
+ GP2AP020A00F_OP3_SHUTDOWN);
+
+ if (err < 0) {
+ dev_err(&data->client->dev,
+ "Shutting down the device failed.\n");
+ return false;
+ }
+
+ err = regmap_update_bits(data->regmap,
+ GP2AP020A00F_ALS_REG,
+ GP2AP020A00F_RANGE_A_MASK,
+ new_range);
+
+ if (err < 0) {
+ dev_err(&data->client->dev,
+ "Adjusting device lux mode failed.\n");
+ return false;
+ }
+
+ err = regmap_update_bits(data->regmap,
+ GP2AP020A00F_OP_REG,
+ GP2AP020A00F_OP3_MASK,
+ GP2AP020A00F_OP3_OPERATION);
+
+ if (err < 0) {
+ dev_err(&data->client->dev,
+ "Powering up the device failed.\n");
+ return false;
+ }
+
+ /* Adjust als threshold register values to the new lux mode */
+ if (test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags)) {
+ err = gp2ap020a00f_write_event_threshold(data,
+ GP2AP020A00F_THRESH_TH, true);
+ if (err < 0) {
+ dev_err(&data->client->dev,
+ "Adjusting als threshold value failed.\n");
+ return false;
+ }
+ }
+
+ if (test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags)) {
+ err = gp2ap020a00f_write_event_threshold(data,
+ GP2AP020A00F_THRESH_TL, true);
+ if (err < 0) {
+ dev_err(&data->client->dev,
+ "Adjusting als threshold value failed.\n");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+static void gp2ap020a00f_output_to_lux(struct gp2ap020a00f_data *data,
+ int *output_val)
+{
+ if (test_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags))
+ *output_val *= 16;
+}
+
+static void gp2ap020a00f_iio_trigger_work(struct irq_work *work)
+{
+ struct gp2ap020a00f_data *data =
+ container_of(work, struct gp2ap020a00f_data, work);
+
+ iio_trigger_poll(data->trig, 0);
+}
+
+static irqreturn_t gp2ap020a00f_prox_sensing_handler(int irq, void *data)
+{
+ struct iio_dev *indio_dev = data;
+ struct gp2ap020a00f_data *priv = iio_priv(indio_dev);
+ unsigned int op_reg_val;
+ int ret;
+
+ /* Read interrupt flags */
+ ret = regmap_read(priv->regmap, GP2AP020A00F_OP_REG, &op_reg_val);
+ if (ret < 0)
+ return IRQ_HANDLED;
+
+ if (gp2ap020a00f_prox_detect_enabled(priv)) {
+ if (op_reg_val & GP2AP020A00F_PROX_DETECT) {
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(
+ IIO_PROXIMITY,
+ GP2AP020A00F_SCAN_MODE_PROXIMITY,
+ IIO_EV_TYPE_ROC,
+ IIO_EV_DIR_RISING),
+ iio_get_time_ns());
+ } else {
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(
+ IIO_PROXIMITY,
+ GP2AP020A00F_SCAN_MODE_PROXIMITY,
+ IIO_EV_TYPE_ROC,
+ IIO_EV_DIR_FALLING),
+ iio_get_time_ns());
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t gp2ap020a00f_thresh_event_handler(int irq, void *data)
+{
+ struct iio_dev *indio_dev = data;
+ struct gp2ap020a00f_data *priv = iio_priv(indio_dev);
+ u8 op_reg_flags, d0_reg_buf[2];
+ unsigned int output_val, op_reg_val;
+ int thresh_val_id, ret;
+
+ /* Read interrupt flags */
+ ret = regmap_read(priv->regmap, GP2AP020A00F_OP_REG,
+ &op_reg_val);
+ if (ret < 0)
+ goto done;
+
+ op_reg_flags = op_reg_val & (GP2AP020A00F_FLAG_A | GP2AP020A00F_FLAG_P
+ | GP2AP020A00F_PROX_DETECT);
+
+ op_reg_val &= (~GP2AP020A00F_FLAG_A & ~GP2AP020A00F_FLAG_P
+ & ~GP2AP020A00F_PROX_DETECT);
+
+ /* Clear interrupt flags (if not in INTTYPE_PULSE mode) */
+ if (priv->cur_opmode != GP2AP020A00F_OPMODE_PROX_DETECT) {
+ ret = regmap_write(priv->regmap, GP2AP020A00F_OP_REG,
+ op_reg_val);
+ if (ret < 0)
+ goto done;
+ }
+
+ if (op_reg_flags & GP2AP020A00F_FLAG_A) {
+ /* Check D0 register to assess if the lux mode
+ * transition is required.
+ */
+ ret = regmap_bulk_read(priv->regmap, GP2AP020A00F_D0_L_REG,
+ d0_reg_buf, 2);
+ if (ret < 0)
+ goto done;
+
+ output_val = le16_to_cpup((__le16 *)d0_reg_buf);
+
+ if (gp2ap020a00f_adjust_lux_mode(priv, output_val))
+ goto done;
+
+ gp2ap020a00f_output_to_lux(priv, &output_val);
+
+ /*
+ * We need to check output value to distinguish
+ * between high and low ambient light threshold event.
+ */
+ if (test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &priv->flags)) {
+ thresh_val_id =
+ GP2AP020A00F_THRESH_VAL_ID(GP2AP020A00F_TH_L_REG);
+ if (output_val > priv->thresh_val[thresh_val_id])
+ iio_push_event(indio_dev,
+ IIO_MOD_EVENT_CODE(
+ IIO_LIGHT,
+ GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR,
+ IIO_MOD_LIGHT_CLEAR,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ iio_get_time_ns());
+ }
+
+ if (test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &priv->flags)) {
+ thresh_val_id =
+ GP2AP020A00F_THRESH_VAL_ID(GP2AP020A00F_TL_L_REG);
+ if (output_val < priv->thresh_val[thresh_val_id])
+ iio_push_event(indio_dev,
+ IIO_MOD_EVENT_CODE(
+ IIO_LIGHT,
+ GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR,
+ IIO_MOD_LIGHT_CLEAR,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ iio_get_time_ns());
+ }
+ }
+
+ if (priv->cur_opmode == GP2AP020A00F_OPMODE_READ_RAW_CLEAR ||
+ priv->cur_opmode == GP2AP020A00F_OPMODE_READ_RAW_IR ||
+ priv->cur_opmode == GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY) {
+ set_bit(GP2AP020A00F_FLAG_DATA_READY, &priv->flags);
+ wake_up(&priv->data_ready_queue);
+ goto done;
+ }
+
+ if (test_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &priv->flags) ||
+ test_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &priv->flags) ||
+ test_bit(GP2AP020A00F_FLAG_PROX_TRIGGER, &priv->flags))
+ /* This fires off the trigger. */
+ irq_work_queue(&priv->work);
+
+done:
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t gp2ap020a00f_trigger_handler(int irq, void *data)
+{
+ struct iio_poll_func *pf = data;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct gp2ap020a00f_data *priv = iio_priv(indio_dev);
+ size_t d_size = 0;
+ __le32 light_lux;
+ int i, out_val, ret;
+
+ for_each_set_bit(i, indio_dev->active_scan_mask,
+ indio_dev->masklength) {
+ ret = regmap_bulk_read(priv->regmap,
+ GP2AP020A00F_DATA_REG(i),
+ &priv->buffer[d_size], 2);
+ if (ret < 0)
+ goto done;
+
+ if (i == GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR ||
+ i == GP2AP020A00F_SCAN_MODE_LIGHT_IR) {
+ out_val = le16_to_cpup((__le16 *)&priv->buffer[d_size]);
+ gp2ap020a00f_output_to_lux(priv, &out_val);
+ light_lux = cpu_to_le32(out_val);
+ memcpy(&priv->buffer[d_size], (u8 *)&light_lux, 4);
+ d_size += 4;
+ } else {
+ d_size += 2;
+ }
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, priv->buffer,
+ pf->timestamp);
+done:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static u8 gp2ap020a00f_get_reg_by_event_code(u64 event_code)
+{
+ int event_dir = IIO_EVENT_CODE_EXTRACT_DIR(event_code);
+
+ switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
+ case IIO_PROXIMITY:
+ if (event_dir == IIO_EV_DIR_RISING)
+ return GP2AP020A00F_PH_L_REG;
+ else
+ return GP2AP020A00F_PL_L_REG;
+ case IIO_LIGHT:
+ if (event_dir == IIO_EV_DIR_RISING)
+ return GP2AP020A00F_TH_L_REG;
+ else
+ return GP2AP020A00F_TL_L_REG;
+ }
+
+ return -EINVAL;
+}
+
+static int gp2ap020a00f_write_event_val(struct iio_dev *indio_dev,
+ u64 event_code, int val)
+{
+ struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+ bool event_en = false;
+ u8 thresh_val_id;
+ u8 thresh_reg_l;
+ int err = 0;
+
+ mutex_lock(&data->lock);
+
+ thresh_reg_l = gp2ap020a00f_get_reg_by_event_code(event_code);
+ thresh_val_id = GP2AP020A00F_THRESH_VAL_ID(thresh_reg_l);
+
+ if (thresh_val_id > GP2AP020A00F_THRESH_PH) {
+ err = -EINVAL;
+ goto error_unlock;
+ }
+
+ switch (thresh_reg_l) {
+ case GP2AP020A00F_TH_L_REG:
+ event_en = test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV,
+ &data->flags);
+ break;
+ case GP2AP020A00F_TL_L_REG:
+ event_en = test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV,
+ &data->flags);
+ break;
+ case GP2AP020A00F_PH_L_REG:
+ if (val == 0) {
+ err = -EINVAL;
+ goto error_unlock;
+ }
+ event_en = test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV,
+ &data->flags);
+ break;
+ case GP2AP020A00F_PL_L_REG:
+ if (val == 0) {
+ err = -EINVAL;
+ goto error_unlock;
+ }
+ event_en = test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV,
+ &data->flags);
+ break;
+ }
+
+ data->thresh_val[thresh_val_id] = val;
+ err = gp2ap020a00f_write_event_threshold(data, thresh_val_id,
+ event_en);
+error_unlock:
+ mutex_unlock(&data->lock);
+
+ return err;
+}
+
+static int gp2ap020a00f_read_event_val(struct iio_dev *indio_dev,
+ u64 event_code, int *val)
+{
+ struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+ u8 thresh_reg_l;
+ int err = 0;
+
+ mutex_lock(&data->lock);
+
+ thresh_reg_l = gp2ap020a00f_get_reg_by_event_code(event_code);
+
+ if (thresh_reg_l > GP2AP020A00F_PH_L_REG) {
+ err = -EINVAL;
+ goto error_unlock;
+ }
+
+ *val = data->thresh_val[GP2AP020A00F_THRESH_VAL_ID(thresh_reg_l)];
+
+error_unlock:
+ mutex_unlock(&data->lock);
+
+ return err;
+}
+
+static int gp2ap020a00f_write_prox_event_config(struct iio_dev *indio_dev,
+ u64 event_code, int state)
+{
+ struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+ enum gp2ap020a00f_cmd cmd_high_ev, cmd_low_ev;
+ int err;
+
+ cmd_high_ev = state ? GP2AP020A00F_CMD_PROX_HIGH_EV_EN :
+ GP2AP020A00F_CMD_PROX_HIGH_EV_DIS;
+ cmd_low_ev = state ? GP2AP020A00F_CMD_PROX_LOW_EV_EN :
+ GP2AP020A00F_CMD_PROX_LOW_EV_DIS;
+
+ /*
+ * In order to enable proximity detection feature in the device
+ * both high and low threshold registers have to be written
+ * with different values, greater than zero.
+ */
+ if (state) {
+ if (data->thresh_val[GP2AP020A00F_THRESH_PL] == 0)
+ return -EINVAL;
+
+ if (data->thresh_val[GP2AP020A00F_THRESH_PH] == 0)
+ return -EINVAL;
+ }
+
+ err = gp2ap020a00f_exec_cmd(data, cmd_high_ev);
+ if (err < 0)
+ return err;
+
+ err = gp2ap020a00f_exec_cmd(data, cmd_low_ev);
+ if (err < 0)
+ return err;
+
+ free_irq(data->client->irq, indio_dev);
+
+ if (state)
+ err = request_threaded_irq(data->client->irq, NULL,
+ &gp2ap020a00f_prox_sensing_handler,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ "gp2ap020a00f_prox_sensing",
+ indio_dev);
+ else {
+ err = request_threaded_irq(data->client->irq, NULL,
+ &gp2ap020a00f_thresh_event_handler,
+ IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ "gp2ap020a00f_thresh_event",
+ indio_dev);
+ }
+
+ return err;
+}
+
+static int gp2ap020a00f_write_event_config(struct iio_dev *indio_dev,
+ u64 event_code, int state)
+{
+ struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+ enum gp2ap020a00f_cmd cmd;
+ int err;
+
+ mutex_lock(&data->lock);
+
+ switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
+ case IIO_PROXIMITY:
+ err = gp2ap020a00f_write_prox_event_config(indio_dev,
+ event_code, state);
+ break;
+ case IIO_LIGHT:
+ if (IIO_EVENT_CODE_EXTRACT_DIR(event_code)
+ == IIO_EV_DIR_RISING) {
+ cmd = state ? GP2AP020A00F_CMD_ALS_HIGH_EV_EN :
+ GP2AP020A00F_CMD_ALS_HIGH_EV_DIS;
+ err = gp2ap020a00f_exec_cmd(data, cmd);
+ } else {
+ cmd = state ? GP2AP020A00F_CMD_ALS_LOW_EV_EN :
+ GP2AP020A00F_CMD_ALS_LOW_EV_DIS;
+ err = gp2ap020a00f_exec_cmd(data, cmd);
+ }
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ mutex_unlock(&data->lock);
+
+ return err;
+}
+
+static int gp2ap020a00f_read_event_config(struct iio_dev *indio_dev,
+ u64 event_code)
+{
+ struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+ int event_en = 0;
+
+ mutex_lock(&data->lock);
+
+ switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
+ case IIO_PROXIMITY:
+ if (IIO_EVENT_CODE_EXTRACT_DIR(event_code)
+ == IIO_EV_DIR_RISING)
+ event_en = test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV,
+ &data->flags);
+ else
+ event_en = test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV,
+ &data->flags);
+ break;
+ case IIO_LIGHT:
+ if (IIO_EVENT_CODE_EXTRACT_DIR(event_code)
+ == IIO_EV_DIR_RISING)
+ event_en = test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV,
+ &data->flags);
+ else
+ event_en = test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV,
+ &data->flags);
+ break;
+ }
+
+ mutex_unlock(&data->lock);
+
+ return event_en;
+}
+
+static int gp2ap020a00f_read_channel(struct gp2ap020a00f_data *data,
+ struct iio_chan_spec const *chan, int *val)
+{
+ enum gp2ap020a00f_cmd cmd;
+ int err;
+
+ switch (chan->scan_index) {
+ case GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR:
+ cmd = GP2AP020A00F_CMD_READ_RAW_CLEAR;
+ break;
+ case GP2AP020A00F_SCAN_MODE_LIGHT_IR:
+ cmd = GP2AP020A00F_CMD_READ_RAW_IR;
+ break;
+ case GP2AP020A00F_SCAN_MODE_PROXIMITY:
+ cmd = GP2AP020A00F_CMD_READ_RAW_PROXIMITY;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = gp2ap020a00f_exec_cmd(data, cmd);
+ if (err < 0) {
+ dev_err(&data->client->dev,
+ "gp2ap020a00f_exec_cmd failed\n");
+ goto error_ret;
+ }
+
+ err = gp2ap020a00f_read_output(data, chan->address, val);
+ if (err < 0)
+ dev_err(&data->client->dev,
+ "gp2ap020a00f_read_output failed\n");
+
+ err = gp2ap020a00f_set_operation_mode(data,
+ GP2AP020A00F_OPMODE_SHUTDOWN);
+ if (err < 0)
+ dev_err(&data->client->dev,
+ "Failed to shut down the device.\n");
+
+ if (cmd == GP2AP020A00F_CMD_READ_RAW_CLEAR ||
+ cmd == GP2AP020A00F_CMD_READ_RAW_IR)
+ gp2ap020a00f_output_to_lux(data, val);
+
+error_ret:
+ return err;
+}
+
+static int gp2ap020a00f_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2,
+ long mask)
+{
+ struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+ int err = -EINVAL;
+
+ mutex_lock(&data->lock);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (iio_buffer_enabled(indio_dev)) {
+ err = -EBUSY;
+ goto error_unlock;
+ }
+
+ err = gp2ap020a00f_read_channel(data, chan, val);
+ break;
+ }
+
+error_unlock:
+ mutex_unlock(&data->lock);
+
+ return err < 0 ? err : IIO_VAL_INT;
+}
+
+static const struct iio_chan_spec gp2ap020a00f_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .channel2 = IIO_MOD_LIGHT_CLEAR,
+ .modified = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 24,
+ .shift = 0,
+ .storagebits = 32,
+ .endianness = IIO_LE,
+ },
+ .scan_index = GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR,
+ .address = GP2AP020A00F_D0_L_REG,
+ .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING) |
+ IIO_EV_BIT(IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ },
+ {
+ .type = IIO_LIGHT,
+ .channel2 = IIO_MOD_LIGHT_IR,
+ .modified = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 24,
+ .shift = 0,
+ .storagebits = 32,
+ .endianness = IIO_LE,
+ },
+ .scan_index = GP2AP020A00F_SCAN_MODE_LIGHT_IR,
+ .address = GP2AP020A00F_D1_L_REG,
+ },
+ {
+ .type = IIO_PROXIMITY,
+ .modified = 0,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .shift = 0,
+ .storagebits = 16,
+ .endianness = IIO_LE,
+ },
+ .scan_index = GP2AP020A00F_SCAN_MODE_PROXIMITY,
+ .address = GP2AP020A00F_D2_L_REG,
+ .event_mask = IIO_EV_BIT(IIO_EV_TYPE_ROC,
+ IIO_EV_DIR_RISING) |
+ IIO_EV_BIT(IIO_EV_TYPE_ROC,
+ IIO_EV_DIR_FALLING),
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(GP2AP020A00F_CHAN_TIMESTAMP),
+};
+
+static const struct iio_info gp2ap020a00f_info = {
+ .read_raw = &gp2ap020a00f_read_raw,
+ .read_event_value = &gp2ap020a00f_read_event_val,
+ .read_event_config = &gp2ap020a00f_read_event_config,
+ .write_event_value = &gp2ap020a00f_write_event_val,
+ .write_event_config = &gp2ap020a00f_write_event_config,
+ .driver_module = THIS_MODULE,
+};
+
+static int gp2ap020a00f_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+ int i, err = 0;
+
+ mutex_lock(&data->lock);
+
+ /*
+ * Enable triggers according to the scan_mask. Enabling either
+ * LIGHT_CLEAR or LIGHT_IR scan mode results in enabling ALS
+ * module in the device, which generates samples in both D0 (clear)
+ * and D1 (ir) registers. As the two registers are bound to the
+ * two separate IIO channels they are treated in the driver logic
+ * as if they were controlled independently.
+ */
+ for_each_set_bit(i, indio_dev->active_scan_mask,
+ indio_dev->masklength) {
+ switch (i) {
+ case GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR:
+ err = gp2ap020a00f_exec_cmd(data,
+ GP2AP020A00F_CMD_TRIGGER_CLEAR_EN);
+ break;
+ case GP2AP020A00F_SCAN_MODE_LIGHT_IR:
+ err = gp2ap020a00f_exec_cmd(data,
+ GP2AP020A00F_CMD_TRIGGER_IR_EN);
+ break;
+ case GP2AP020A00F_SCAN_MODE_PROXIMITY:
+ err = gp2ap020a00f_exec_cmd(data,
+ GP2AP020A00F_CMD_TRIGGER_PROX_EN);
+ break;
+ }
+ }
+
+ if (err < 0)
+ goto error_unlock;
+
+ data->buffer = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+ if (!data->buffer) {
+ err = -ENOMEM;
+ goto error_unlock;
+ }
+
+ err = iio_triggered_buffer_postenable(indio_dev);
+
+error_unlock:
+ mutex_unlock(&data->lock);
+
+ return err;
+}
+
+static int gp2ap020a00f_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+ int i, err;
+
+ mutex_lock(&data->lock);
+
+ err = iio_triggered_buffer_predisable(indio_dev);
+ if (err < 0)
+ goto error_unlock;
+
+ for_each_set_bit(i, indio_dev->active_scan_mask,
+ indio_dev->masklength) {
+ switch (i) {
+ case GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR:
+ err = gp2ap020a00f_exec_cmd(data,
+ GP2AP020A00F_CMD_TRIGGER_CLEAR_DIS);
+ break;
+ case GP2AP020A00F_SCAN_MODE_LIGHT_IR:
+ err = gp2ap020a00f_exec_cmd(data,
+ GP2AP020A00F_CMD_TRIGGER_IR_DIS);
+ break;
+ case GP2AP020A00F_SCAN_MODE_PROXIMITY:
+ err = gp2ap020a00f_exec_cmd(data,
+ GP2AP020A00F_CMD_TRIGGER_PROX_DIS);
+ break;
+ }
+ }
+
+ if (err == 0)
+ kfree(data->buffer);
+
+error_unlock:
+ mutex_unlock(&data->lock);
+
+ return err;
+}
+
+static const struct iio_buffer_setup_ops gp2ap020a00f_buffer_setup_ops = {
+ .preenable = &iio_sw_buffer_preenable,
+ .postenable = &gp2ap020a00f_buffer_postenable,
+ .predisable = &gp2ap020a00f_buffer_predisable,
+};
+
+static const struct iio_trigger_ops gp2ap020a00f_trigger_ops = {
+ .owner = THIS_MODULE,
+};
+
+static int gp2ap020a00f_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct gp2ap020a00f_data *data;
+ struct iio_dev *indio_dev;
+ struct regmap *regmap;
+ int err;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+
+ data->vled_reg = devm_regulator_get(&client->dev, "vled");
+ if (IS_ERR(data->vled_reg))
+ return PTR_ERR(data->vled_reg);
+
+ err = regulator_enable(data->vled_reg);
+ if (err)
+ return err;
+
+ regmap = devm_regmap_init_i2c(client, &gp2ap020a00f_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(&client->dev, "Regmap initialization failed.\n");
+ err = PTR_ERR(regmap);
+ goto error_regulator_disable;
+ }
+
+ /* Initialize device registers */
+ err = regmap_bulk_write(regmap, GP2AP020A00F_OP_REG,
+ gp2ap020a00f_reg_init_tab,
+ ARRAY_SIZE(gp2ap020a00f_reg_init_tab));
+
+ if (err < 0) {
+ dev_err(&client->dev, "Device initialization failed.\n");
+ goto error_regulator_disable;
+ }
+
+ i2c_set_clientdata(client, indio_dev);
+
+ data->client = client;
+ data->cur_opmode = GP2AP020A00F_OPMODE_SHUTDOWN;
+ data->regmap = regmap;
+ init_waitqueue_head(&data->data_ready_queue);
+
+ mutex_init(&data->lock);
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->channels = gp2ap020a00f_channels;
+ indio_dev->num_channels = ARRAY_SIZE(gp2ap020a00f_channels);
+ indio_dev->info = &gp2ap020a00f_info;
+ indio_dev->name = id->name;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ /* Allocate buffer */
+ err = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+ &gp2ap020a00f_trigger_handler, &gp2ap020a00f_buffer_setup_ops);
+ if (err < 0)
+ goto error_regulator_disable;
+
+ /* Allocate trigger */
+ data->trig = devm_iio_trigger_alloc(&client->dev, "%s-trigger",
+ indio_dev->name);
+ if (data->trig == NULL) {
+ err = -ENOMEM;
+ dev_err(&indio_dev->dev, "Failed to allocate iio trigger.\n");
+ goto error_uninit_buffer;
+ }
+
+ /* This needs to be requested here for read_raw calls to work. */
+ err = request_threaded_irq(client->irq, NULL,
+ &gp2ap020a00f_thresh_event_handler,
+ IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ "gp2ap020a00f_als_event",
+ indio_dev);
+ if (err < 0) {
+ dev_err(&client->dev, "Irq request failed.\n");
+ goto error_uninit_buffer;
+ }
+
+ data->trig->ops = &gp2ap020a00f_trigger_ops;
+ data->trig->dev.parent = &data->client->dev;
+
+ init_irq_work(&data->work, gp2ap020a00f_iio_trigger_work);
+
+ err = iio_trigger_register(data->trig);
+ if (err < 0) {
+ dev_err(&client->dev, "Failed to register iio trigger.\n");
+ goto error_free_irq;
+ }
+
+ err = iio_device_register(indio_dev);
+ if (err < 0)
+ goto error_trigger_unregister;
+
+ return 0;
+
+error_trigger_unregister:
+ iio_trigger_unregister(data->trig);
+error_free_irq:
+ free_irq(client->irq, indio_dev);
+error_uninit_buffer:
+ iio_triggered_buffer_cleanup(indio_dev);
+error_regulator_disable:
+ regulator_disable(data->vled_reg);
+
+ return err;
+}
+
+static int gp2ap020a00f_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+ int err;
+
+ err = gp2ap020a00f_set_operation_mode(data,
+ GP2AP020A00F_OPMODE_SHUTDOWN);
+ if (err < 0)
+ dev_err(&indio_dev->dev, "Failed to power off the device.\n");
+
+ iio_device_unregister(indio_dev);
+ iio_trigger_unregister(data->trig);
+ free_irq(client->irq, indio_dev);
+ iio_triggered_buffer_cleanup(indio_dev);
+ regulator_disable(data->vled_reg);
+
+ return 0;
+}
+
+static const struct i2c_device_id gp2ap020a00f_id[] = {
+ { GP2A_I2C_NAME, 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, gp2ap020a00f_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id gp2ap020a00f_of_match[] = {
+ { .compatible = "sharp,gp2ap020a00f" },
+ { }
+};
+#endif
+
+static struct i2c_driver gp2ap020a00f_driver = {
+ .driver = {
+ .name = GP2A_I2C_NAME,
+ .of_match_table = of_match_ptr(gp2ap020a00f_of_match),
+ .owner = THIS_MODULE,
+ },
+ .probe = gp2ap020a00f_probe,
+ .remove = gp2ap020a00f_remove,
+ .id_table = gp2ap020a00f_id,
+};
+
+module_i2c_driver(gp2ap020a00f_driver);
+
+MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
+MODULE_DESCRIPTION("Sharp GP2AP020A00F Proximity/ALS sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index e59d00c3139c..fa6ae8cf89ea 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -161,10 +161,11 @@ static const struct iio_info als_info = {
};
/* Function to push data to buffer */
-static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
+static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data,
+ int len)
{
dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
- iio_push_to_buffers(indio_dev, (u8 *)data);
+ iio_push_to_buffers(indio_dev, data);
}
/* Callback handler to send event after all samples are received and captured */
@@ -179,7 +180,7 @@ static int als_proc_event(struct hid_sensor_hub_device *hsdev,
als_state->common_attributes.data_ready);
if (als_state->common_attributes.data_ready)
hid_sensor_push_data(indio_dev,
- (u8 *)&als_state->illum,
+ &als_state->illum,
sizeof(als_state->illum));
return 0;
diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c
new file mode 100644
index 000000000000..45df2204614a
--- /dev/null
+++ b/drivers/iio/light/tcs3472.c
@@ -0,0 +1,367 @@
+/*
+ * tcs3472.c - Support for TAOS TCS3472 color light-to-digital converter
+ *
+ * Copyright (c) 2013 Peter Meerwald <pmeerw@pmeerw.net>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License. See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * Color light sensor with 16-bit channels for red, green, blue, clear);
+ * 7-bit I2C slave address 0x39 (TCS34721, TCS34723) or 0x29 (TCS34725,
+ * TCS34727)
+ *
+ * TODO: interrupt support, thresholds, wait time
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define TCS3472_DRV_NAME "tcs3472"
+
+#define TCS3472_COMMAND BIT(7)
+#define TCS3472_AUTO_INCR BIT(5)
+
+#define TCS3472_ENABLE (TCS3472_COMMAND | 0x00)
+#define TCS3472_ATIME (TCS3472_COMMAND | 0x01)
+#define TCS3472_WTIME (TCS3472_COMMAND | 0x03)
+#define TCS3472_AILT (TCS3472_COMMAND | 0x04)
+#define TCS3472_AIHT (TCS3472_COMMAND | 0x06)
+#define TCS3472_PERS (TCS3472_COMMAND | 0x0c)
+#define TCS3472_CONFIG (TCS3472_COMMAND | 0x0d)
+#define TCS3472_CONTROL (TCS3472_COMMAND | 0x0f)
+#define TCS3472_ID (TCS3472_COMMAND | 0x12)
+#define TCS3472_STATUS (TCS3472_COMMAND | 0x13)
+#define TCS3472_CDATA (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x14)
+#define TCS3472_RDATA (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x16)
+#define TCS3472_GDATA (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x18)
+#define TCS3472_BDATA (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x1a)
+
+#define TCS3472_STATUS_AVALID BIT(0)
+#define TCS3472_ENABLE_AEN BIT(1)
+#define TCS3472_ENABLE_PON BIT(0)
+#define TCS3472_CONTROL_AGAIN_MASK (BIT(0) | BIT(1))
+
+struct tcs3472_data {
+ struct i2c_client *client;
+ u8 enable;
+ u8 control;
+ u8 atime;
+ u16 buffer[8]; /* 4 16-bit channels + 64-bit timestamp */
+};
+
+#define TCS3472_CHANNEL(_color, _si, _addr) { \
+ .type = IIO_INTENSITY, \
+ .modified = 1, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBSCALE) | \
+ BIT(IIO_CHAN_INFO_INT_TIME), \
+ .channel2 = IIO_MOD_LIGHT_##_color, \
+ .address = _addr, \
+ .scan_index = _si, \
+ .scan_type = IIO_ST('u', 16, 16, 0), \
+}
+
+static const int tcs3472_agains[] = { 1, 4, 16, 60 };
+
+static const struct iio_chan_spec tcs3472_channels[] = {
+ TCS3472_CHANNEL(CLEAR, 0, TCS3472_CDATA),
+ TCS3472_CHANNEL(RED, 1, TCS3472_RDATA),
+ TCS3472_CHANNEL(GREEN, 2, TCS3472_GDATA),
+ TCS3472_CHANNEL(BLUE, 3, TCS3472_BDATA),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+static int tcs3472_req_data(struct tcs3472_data *data)
+{
+ int tries = 50;
+ int ret;
+
+ while (tries--) {
+ ret = i2c_smbus_read_byte_data(data->client, TCS3472_STATUS);
+ if (ret < 0)
+ return ret;
+ if (ret & TCS3472_STATUS_AVALID)
+ break;
+ msleep(20);
+ }
+
+ if (tries < 0) {
+ dev_err(&data->client->dev, "data not ready\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int tcs3472_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct tcs3472_data *data = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = tcs3472_req_data(data);
+ if (ret < 0)
+ return ret;
+ ret = i2c_smbus_read_word_data(data->client, chan->address);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_CALIBSCALE:
+ *val = tcs3472_agains[data->control &
+ TCS3472_CONTROL_AGAIN_MASK];
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_INT_TIME:
+ *val = 0;
+ *val2 = (256 - data->atime) * 2400;
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+ return -EINVAL;
+}
+
+static int tcs3472_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct tcs3472_data *data = iio_priv(indio_dev);
+ int i;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_CALIBSCALE:
+ if (val2 != 0)
+ return -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(tcs3472_agains); i++) {
+ if (val == tcs3472_agains[i]) {
+ data->control &= ~TCS3472_CONTROL_AGAIN_MASK;
+ data->control |= i;
+ return i2c_smbus_write_byte_data(
+ data->client, TCS3472_CONTROL,
+ data->control);
+ }
+ }
+ return -EINVAL;
+ case IIO_CHAN_INFO_INT_TIME:
+ if (val != 0)
+ return -EINVAL;
+ for (i = 0; i < 256; i++) {
+ if (val2 == (256 - i) * 2400) {
+ data->atime = i;
+ return i2c_smbus_write_word_data(
+ data->client, TCS3472_ATIME,
+ data->atime);
+ }
+
+ }
+ return -EINVAL;
+ }
+ return -EINVAL;
+}
+
+static irqreturn_t tcs3472_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct tcs3472_data *data = iio_priv(indio_dev);
+ int len = 0;
+ int i, j = 0;
+
+ int ret = tcs3472_req_data(data);
+ if (ret < 0)
+ goto done;
+
+ for_each_set_bit(i, indio_dev->active_scan_mask,
+ indio_dev->masklength) {
+ ret = i2c_smbus_read_word_data(data->client,
+ TCS3472_CDATA + 2*i);
+ if (ret < 0)
+ goto done;
+
+ data->buffer[j++] = ret;
+ len += 2;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+ iio_get_time_ns());
+
+done:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static ssize_t tcs3472_show_int_time_available(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ size_t len = 0;
+ int i;
+
+ for (i = 1; i <= 256; i++)
+ len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06d ",
+ 2400 * i);
+
+ /* replace trailing space by newline */
+ buf[len - 1] = '\n';
+
+ return len;
+}
+
+static IIO_CONST_ATTR(calibscale_available, "1 4 16 60");
+static IIO_DEV_ATTR_INT_TIME_AVAIL(tcs3472_show_int_time_available);
+
+static struct attribute *tcs3472_attributes[] = {
+ &iio_const_attr_calibscale_available.dev_attr.attr,
+ &iio_dev_attr_integration_time_available.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group tcs3472_attribute_group = {
+ .attrs = tcs3472_attributes,
+};
+
+static const struct iio_info tcs3472_info = {
+ .read_raw = tcs3472_read_raw,
+ .write_raw = tcs3472_write_raw,
+ .attrs = &tcs3472_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
+static int tcs3472_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct tcs3472_data *data;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (indio_dev == NULL)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->info = &tcs3472_info;
+ indio_dev->name = TCS3472_DRV_NAME;
+ indio_dev->channels = tcs3472_channels;
+ indio_dev->num_channels = ARRAY_SIZE(tcs3472_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ ret = i2c_smbus_read_byte_data(data->client, TCS3472_ID);
+ if (ret < 0)
+ return ret;
+
+ if (ret == 0x44)
+ dev_info(&client->dev, "TCS34721/34725 found\n");
+ else if (ret == 0x4d)
+ dev_info(&client->dev, "TCS34723/34727 found\n");
+ else
+ return -ENODEV;
+
+ ret = i2c_smbus_read_byte_data(data->client, TCS3472_CONTROL);
+ if (ret < 0)
+ return ret;
+ data->control = ret;
+
+ ret = i2c_smbus_read_byte_data(data->client, TCS3472_ATIME);
+ if (ret < 0)
+ return ret;
+ data->atime = ret;
+
+ ret = i2c_smbus_read_byte_data(data->client, TCS3472_ENABLE);
+ if (ret < 0)
+ return ret;
+
+ /* enable device */
+ data->enable = ret | TCS3472_ENABLE_PON | TCS3472_ENABLE_AEN;
+ ret = i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE,
+ data->enable);
+ if (ret < 0)
+ return ret;
+
+ ret = iio_triggered_buffer_setup(indio_dev, NULL,
+ tcs3472_trigger_handler, NULL);
+ if (ret < 0)
+ return ret;
+
+ ret = iio_device_register(indio_dev);
+ if (ret < 0)
+ goto buffer_cleanup;
+
+ return 0;
+
+buffer_cleanup:
+ iio_triggered_buffer_cleanup(indio_dev);
+ return ret;
+}
+
+static int tcs3472_powerdown(struct tcs3472_data *data)
+{
+ return i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE,
+ data->enable & ~(TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON));
+}
+
+static int tcs3472_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+ iio_device_unregister(indio_dev);
+ iio_triggered_buffer_cleanup(indio_dev);
+ tcs3472_powerdown(iio_priv(indio_dev));
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tcs3472_suspend(struct device *dev)
+{
+ struct tcs3472_data *data = iio_priv(i2c_get_clientdata(
+ to_i2c_client(dev)));
+ return tcs3472_powerdown(data);
+}
+
+static int tcs3472_resume(struct device *dev)
+{
+ struct tcs3472_data *data = iio_priv(i2c_get_clientdata(
+ to_i2c_client(dev)));
+ return i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE,
+ data->enable | (TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON));
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tcs3472_pm_ops, tcs3472_suspend, tcs3472_resume);
+
+static const struct i2c_device_id tcs3472_id[] = {
+ { "tcs3472", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tcs3472_id);
+
+static struct i2c_driver tcs3472_driver = {
+ .driver = {
+ .name = TCS3472_DRV_NAME,
+ .pm = &tcs3472_pm_ops,
+ .owner = THIS_MODULE,
+ },
+ .probe = tcs3472_probe,
+ .remove = tcs3472_remove,
+ .id_table = tcs3472_id,
+};
+module_i2c_driver(tcs3472_driver);
+
+MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
+MODULE_DESCRIPTION("TCS3472 color light sensors driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/light/tsl4531.c b/drivers/iio/light/tsl4531.c
new file mode 100644
index 000000000000..a15006efa137
--- /dev/null
+++ b/drivers/iio/light/tsl4531.c
@@ -0,0 +1,258 @@
+/*
+ * tsl4531.c - Support for TAOS TSL4531 ambient light sensor
+ *
+ * Copyright 2013 Peter Meerwald <pmeerw@pmeerw.net>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License. See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * IIO driver for the TSL4531x family
+ * TSL45311/TSL45313: 7-bit I2C slave address 0x39
+ * TSL45315/TSL45317: 7-bit I2C slave address 0x29
+ *
+ * TODO: single cycle measurement
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define TSL4531_DRV_NAME "tsl4531"
+
+#define TCS3472_COMMAND BIT(7)
+
+#define TSL4531_CONTROL (TCS3472_COMMAND | 0x00)
+#define TSL4531_CONFIG (TCS3472_COMMAND | 0x01)
+#define TSL4531_DATA (TCS3472_COMMAND | 0x04)
+#define TSL4531_ID (TCS3472_COMMAND | 0x0a)
+
+/* operating modes in control register */
+#define TSL4531_MODE_POWERDOWN 0x00
+#define TSL4531_MODE_SINGLE_ADC 0x02
+#define TSL4531_MODE_NORMAL 0x03
+
+/* integration time control in config register */
+#define TSL4531_TCNTRL_400MS 0x00
+#define TSL4531_TCNTRL_200MS 0x01
+#define TSL4531_TCNTRL_100MS 0x02
+
+/* part number in id register */
+#define TSL45311_ID 0x8
+#define TSL45313_ID 0x9
+#define TSL45315_ID 0xa
+#define TSL45317_ID 0xb
+#define TSL4531_ID_SHIFT 4
+
+struct tsl4531_data {
+ struct i2c_client *client;
+ struct mutex lock;
+ int int_time;
+};
+
+static IIO_CONST_ATTR_INT_TIME_AVAIL("0.1 0.2 0.4");
+
+static struct attribute *tsl4531_attributes[] = {
+ &iio_const_attr_integration_time_available.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group tsl4531_attribute_group = {
+ .attrs = tsl4531_attributes,
+};
+
+static const struct iio_chan_spec tsl4531_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_INT_TIME)
+ }
+};
+
+static int tsl4531_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct tsl4531_data *data = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = i2c_smbus_read_word_data(data->client,
+ TSL4531_DATA);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ /* 0.. 1x, 1 .. 2x, 2 .. 4x */
+ *val = 1 << data->int_time;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_INT_TIME:
+ if (data->int_time == 0)
+ *val2 = 400000;
+ else if (data->int_time == 1)
+ *val2 = 200000;
+ else if (data->int_time == 2)
+ *val2 = 100000;
+ else
+ return -EINVAL;
+ *val = 0;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int tsl4531_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct tsl4531_data *data = iio_priv(indio_dev);
+ int int_time, ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ if (val != 0)
+ return -EINVAL;
+ if (val2 == 400000)
+ int_time = 0;
+ else if (val2 == 200000)
+ int_time = 1;
+ else if (val2 == 100000)
+ int_time = 2;
+ else
+ return -EINVAL;
+ mutex_lock(&data->lock);
+ ret = i2c_smbus_write_byte_data(data->client,
+ TSL4531_CONFIG, int_time);
+ if (ret >= 0)
+ data->int_time = int_time;
+ mutex_unlock(&data->lock);
+ return ret;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info tsl4531_info = {
+ .read_raw = tsl4531_read_raw,
+ .write_raw = tsl4531_write_raw,
+ .attrs = &tsl4531_attribute_group,
+ .driver_module = THIS_MODULE,
+};
+
+static int tsl4531_check_id(struct i2c_client *client)
+{
+ int ret = i2c_smbus_read_byte_data(client, TSL4531_ID);
+ if (ret < 0)
+ return ret;
+
+ switch (ret >> TSL4531_ID_SHIFT) {
+ case TSL45311_ID:
+ case TSL45313_ID:
+ case TSL45315_ID:
+ case TSL45317_ID:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int tsl4531_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct tsl4531_data *data;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+ mutex_init(&data->lock);
+
+ if (!tsl4531_check_id(client)) {
+ dev_err(&client->dev, "no TSL4531 sensor\n");
+ return -ENODEV;
+ }
+
+ ret = i2c_smbus_write_byte_data(data->client, TSL4531_CONTROL,
+ TSL4531_MODE_NORMAL);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_write_byte_data(data->client, TSL4531_CONFIG,
+ TSL4531_TCNTRL_400MS);
+ if (ret < 0)
+ return ret;
+
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->info = &tsl4531_info;
+ indio_dev->channels = tsl4531_channels;
+ indio_dev->num_channels = ARRAY_SIZE(tsl4531_channels);
+ indio_dev->name = TSL4531_DRV_NAME;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ return iio_device_register(indio_dev);
+}
+
+static int tsl4531_powerdown(struct i2c_client *client)
+{
+ return i2c_smbus_write_byte_data(client, TSL4531_CONTROL,
+ TSL4531_MODE_POWERDOWN);
+}
+
+static int tsl4531_remove(struct i2c_client *client)
+{
+ iio_device_unregister(i2c_get_clientdata(client));
+ tsl4531_powerdown(client);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tsl4531_suspend(struct device *dev)
+{
+ return tsl4531_powerdown(to_i2c_client(dev));
+}
+
+static int tsl4531_resume(struct device *dev)
+{
+ return i2c_smbus_write_byte_data(to_i2c_client(dev), TSL4531_CONTROL,
+ TSL4531_MODE_NORMAL);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tsl4531_pm_ops, tsl4531_suspend, tsl4531_resume);
+
+static const struct i2c_device_id tsl4531_id[] = {
+ { "tsl4531", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tsl4531_id);
+
+static struct i2c_driver tsl4531_driver = {
+ .driver = {
+ .name = TSL4531_DRV_NAME,
+ .pm = &tsl4531_pm_ops,
+ .owner = THIS_MODULE,
+ },
+ .probe = tsl4531_probe,
+ .remove = tsl4531_remove,
+ .id_table = tsl4531_id,
+};
+
+module_i2c_driver(tsl4531_driver);
+
+MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
+MODULE_DESCRIPTION("TAOS TSL4531 ambient light sensors driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index a98460b15e4b..2634920562fb 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -183,10 +183,11 @@ static const struct iio_info magn_3d_info = {
};
/* Function to push data to buffer */
-static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
+static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data,
+ int len)
{
dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
- iio_push_to_buffers(indio_dev, (u8 *)data);
+ iio_push_to_buffers(indio_dev, data);
}
/* Callback handler to send event after all samples are received and captured */
@@ -201,7 +202,7 @@ static int magn_3d_proc_event(struct hid_sensor_hub_device *hsdev,
magn_state->common_attributes.data_ready);
if (magn_state->common_attributes.data_ready)
hid_sensor_push_data(indio_dev,
- (u8 *)magn_state->magn_val,
+ magn_state->magn_val,
sizeof(magn_state->magn_val));
return 0;
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
index e8d2849cc81d..82461eff995a 100644
--- a/drivers/iio/magnetometer/st_magn_core.c
+++ b/drivers/iio/magnetometer/st_magn_core.c
@@ -348,8 +348,9 @@ static const struct iio_info magn_info = {
int st_magn_common_probe(struct iio_dev *indio_dev,
struct st_sensors_platform_data *pdata)
{
- int err;
struct st_sensor_data *mdata = iio_priv(indio_dev);
+ int irq = mdata->get_irq_data_ready(indio_dev);
+ int err;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &magn_info;
@@ -357,7 +358,7 @@ int st_magn_common_probe(struct iio_dev *indio_dev,
err = st_sensors_check_device_support(indio_dev,
ARRAY_SIZE(st_magn_sensors), st_magn_sensors);
if (err < 0)
- goto st_magn_common_probe_error;
+ return err;
mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS;
mdata->multiread_bit = mdata->sensor->multi_read_bit;
@@ -370,12 +371,13 @@ int st_magn_common_probe(struct iio_dev *indio_dev,
err = st_sensors_init_sensor(indio_dev, pdata);
if (err < 0)
- goto st_magn_common_probe_error;
+ return err;
- if (mdata->get_irq_data_ready(indio_dev) > 0) {
- err = st_magn_allocate_ring(indio_dev);
- if (err < 0)
- goto st_magn_common_probe_error;
+ err = st_magn_allocate_ring(indio_dev);
+ if (err < 0)
+ return err;
+
+ if (irq > 0) {
err = st_sensors_allocate_trigger(indio_dev, NULL);
if (err < 0)
goto st_magn_probe_trigger_error;
@@ -385,15 +387,14 @@ int st_magn_common_probe(struct iio_dev *indio_dev,
if (err)
goto st_magn_device_register_error;
- return err;
+ return 0;
st_magn_device_register_error:
- if (mdata->get_irq_data_ready(indio_dev) > 0)
+ if (irq > 0)
st_sensors_deallocate_trigger(indio_dev);
st_magn_probe_trigger_error:
- if (mdata->get_irq_data_ready(indio_dev) > 0)
- st_magn_deallocate_ring(indio_dev);
-st_magn_common_probe_error:
+ st_magn_deallocate_ring(indio_dev);
+
return err;
}
EXPORT_SYMBOL(st_magn_common_probe);
@@ -403,10 +404,10 @@ void st_magn_common_remove(struct iio_dev *indio_dev)
struct st_sensor_data *mdata = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
- if (mdata->get_irq_data_ready(indio_dev) > 0) {
+ if (mdata->get_irq_data_ready(indio_dev) > 0)
st_sensors_deallocate_trigger(indio_dev);
- st_magn_deallocate_ring(indio_dev);
- }
+
+ st_magn_deallocate_ring(indio_dev);
}
EXPORT_SYMBOL(st_magn_common_remove);
diff --git a/drivers/iio/pressure/st_pressure.h b/drivers/iio/pressure/st_pressure.h
index b0b630688da6..049c21acf1f0 100644
--- a/drivers/iio/pressure/st_pressure.h
+++ b/drivers/iio/pressure/st_pressure.h
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/iio/common/st_sensors.h>
+#define LPS001WP_PRESS_DEV_NAME "lps001wp"
#define LPS331AP_PRESS_DEV_NAME "lps331ap"
/**
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c
index ceebd3c27892..2da411b6925b 100644
--- a/drivers/iio/pressure/st_pressure_core.c
+++ b/drivers/iio/pressure/st_pressure_core.c
@@ -36,94 +36,200 @@
ST_PRESS_LSB_PER_CELSIUS)
#define ST_PRESS_NUMBER_DATA_CHANNELS 1
-/* DEFAULT VALUE FOR SENSORS */
-#define ST_PRESS_DEFAULT_OUT_XL_ADDR 0x28
-#define ST_TEMP_DEFAULT_OUT_L_ADDR 0x2b
-
/* FULLSCALE */
#define ST_PRESS_FS_AVL_1260MB 1260
-/* CUSTOM VALUES FOR SENSOR 1 */
-#define ST_PRESS_1_WAI_EXP 0xbb
-#define ST_PRESS_1_ODR_ADDR 0x20
-#define ST_PRESS_1_ODR_MASK 0x70
-#define ST_PRESS_1_ODR_AVL_1HZ_VAL 0x01
-#define ST_PRESS_1_ODR_AVL_7HZ_VAL 0x05
-#define ST_PRESS_1_ODR_AVL_13HZ_VAL 0x06
-#define ST_PRESS_1_ODR_AVL_25HZ_VAL 0x07
-#define ST_PRESS_1_PW_ADDR 0x20
-#define ST_PRESS_1_PW_MASK 0x80
-#define ST_PRESS_1_FS_ADDR 0x23
-#define ST_PRESS_1_FS_MASK 0x30
-#define ST_PRESS_1_FS_AVL_1260_VAL 0x00
-#define ST_PRESS_1_FS_AVL_1260_GAIN ST_PRESS_KPASCAL_NANO_SCALE
-#define ST_PRESS_1_FS_AVL_TEMP_GAIN ST_PRESS_CELSIUS_NANO_SCALE
-#define ST_PRESS_1_BDU_ADDR 0x20
-#define ST_PRESS_1_BDU_MASK 0x04
-#define ST_PRESS_1_DRDY_IRQ_ADDR 0x22
-#define ST_PRESS_1_DRDY_IRQ_INT1_MASK 0x04
-#define ST_PRESS_1_DRDY_IRQ_INT2_MASK 0x20
-#define ST_PRESS_1_MULTIREAD_BIT true
-#define ST_PRESS_1_TEMP_OFFSET 42500
-
-static const struct iio_chan_spec st_press_channels[] = {
- ST_SENSORS_LSM_CHANNELS(IIO_PRESSURE,
+/* CUSTOM VALUES FOR LPS331AP SENSOR */
+#define ST_PRESS_LPS331AP_WAI_EXP 0xbb
+#define ST_PRESS_LPS331AP_ODR_ADDR 0x20
+#define ST_PRESS_LPS331AP_ODR_MASK 0x70
+#define ST_PRESS_LPS331AP_ODR_AVL_1HZ_VAL 0x01
+#define ST_PRESS_LPS331AP_ODR_AVL_7HZ_VAL 0x05
+#define ST_PRESS_LPS331AP_ODR_AVL_13HZ_VAL 0x06
+#define ST_PRESS_LPS331AP_ODR_AVL_25HZ_VAL 0x07
+#define ST_PRESS_LPS331AP_PW_ADDR 0x20
+#define ST_PRESS_LPS331AP_PW_MASK 0x80
+#define ST_PRESS_LPS331AP_FS_ADDR 0x23
+#define ST_PRESS_LPS331AP_FS_MASK 0x30
+#define ST_PRESS_LPS331AP_FS_AVL_1260_VAL 0x00
+#define ST_PRESS_LPS331AP_FS_AVL_1260_GAIN ST_PRESS_KPASCAL_NANO_SCALE
+#define ST_PRESS_LPS331AP_FS_AVL_TEMP_GAIN ST_PRESS_CELSIUS_NANO_SCALE
+#define ST_PRESS_LPS331AP_BDU_ADDR 0x20
+#define ST_PRESS_LPS331AP_BDU_MASK 0x04
+#define ST_PRESS_LPS331AP_DRDY_IRQ_ADDR 0x22
+#define ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK 0x04
+#define ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK 0x20
+#define ST_PRESS_LPS331AP_MULTIREAD_BIT true
+#define ST_PRESS_LPS331AP_TEMP_OFFSET 42500
+#define ST_PRESS_LPS331AP_OUT_XL_ADDR 0x28
+#define ST_TEMP_LPS331AP_OUT_L_ADDR 0x2b
+
+/* CUSTOM VALUES FOR LPS001WP SENSOR */
+#define ST_PRESS_LPS001WP_WAI_EXP 0xba
+#define ST_PRESS_LPS001WP_ODR_ADDR 0x20
+#define ST_PRESS_LPS001WP_ODR_MASK 0x30
+#define ST_PRESS_LPS001WP_ODR_AVL_1HZ_VAL 0x01
+#define ST_PRESS_LPS001WP_ODR_AVL_7HZ_VAL 0x02
+#define ST_PRESS_LPS001WP_ODR_AVL_13HZ_VAL 0x03
+#define ST_PRESS_LPS001WP_PW_ADDR 0x20
+#define ST_PRESS_LPS001WP_PW_MASK 0x40
+#define ST_PRESS_LPS001WP_BDU_ADDR 0x20
+#define ST_PRESS_LPS001WP_BDU_MASK 0x04
+#define ST_PRESS_LPS001WP_MULTIREAD_BIT true
+#define ST_PRESS_LPS001WP_OUT_L_ADDR 0x28
+#define ST_TEMP_LPS001WP_OUT_L_ADDR 0x2a
+
+static const struct iio_chan_spec st_press_lps331ap_channels[] = {
+ {
+ .type = IIO_PRESSURE,
+ .channel2 = IIO_NO_MOD,
+ .address = ST_PRESS_LPS331AP_OUT_XL_ADDR,
+ .scan_index = ST_SENSORS_SCAN_X,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 24,
+ .storagebits = 24,
+ .endianness = IIO_LE,
+ },
+ .info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
- ST_SENSORS_SCAN_X, 0, IIO_NO_MOD, 'u', IIO_LE, 24, 24,
- ST_PRESS_DEFAULT_OUT_XL_ADDR),
- ST_SENSORS_LSM_CHANNELS(IIO_TEMP,
- BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) |
- BIT(IIO_CHAN_INFO_OFFSET),
- -1, 0, IIO_NO_MOD, 's', IIO_LE, 16, 16,
- ST_TEMP_DEFAULT_OUT_L_ADDR),
+ .modified = 0,
+ },
+ {
+ .type = IIO_TEMP,
+ .channel2 = IIO_NO_MOD,
+ .address = ST_TEMP_LPS331AP_OUT_L_ADDR,
+ .scan_index = -1,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_LE,
+ },
+ .info_mask_separate =
+ BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_OFFSET),
+ .modified = 0,
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(1)
+};
+
+static const struct iio_chan_spec st_press_lps001wp_channels[] = {
+ {
+ .type = IIO_PRESSURE,
+ .channel2 = IIO_NO_MOD,
+ .address = ST_PRESS_LPS001WP_OUT_L_ADDR,
+ .scan_index = ST_SENSORS_SCAN_X,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_LE,
+ },
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .modified = 0,
+ },
+ {
+ .type = IIO_TEMP,
+ .channel2 = IIO_NO_MOD,
+ .address = ST_TEMP_LPS001WP_OUT_L_ADDR,
+ .scan_index = -1,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_LE,
+ },
+ .info_mask_separate =
+ BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_OFFSET),
+ .modified = 0,
+ },
IIO_CHAN_SOFT_TIMESTAMP(1)
};
static const struct st_sensors st_press_sensors[] = {
{
- .wai = ST_PRESS_1_WAI_EXP,
+ .wai = ST_PRESS_LPS331AP_WAI_EXP,
.sensors_supported = {
[0] = LPS331AP_PRESS_DEV_NAME,
},
- .ch = (struct iio_chan_spec *)st_press_channels,
+ .ch = (struct iio_chan_spec *)st_press_lps331ap_channels,
+ .num_ch = ARRAY_SIZE(st_press_lps331ap_channels),
.odr = {
- .addr = ST_PRESS_1_ODR_ADDR,
- .mask = ST_PRESS_1_ODR_MASK,
+ .addr = ST_PRESS_LPS331AP_ODR_ADDR,
+ .mask = ST_PRESS_LPS331AP_ODR_MASK,
.odr_avl = {
- { 1, ST_PRESS_1_ODR_AVL_1HZ_VAL, },
- { 7, ST_PRESS_1_ODR_AVL_7HZ_VAL, },
- { 13, ST_PRESS_1_ODR_AVL_13HZ_VAL, },
- { 25, ST_PRESS_1_ODR_AVL_25HZ_VAL, },
+ { 1, ST_PRESS_LPS331AP_ODR_AVL_1HZ_VAL, },
+ { 7, ST_PRESS_LPS331AP_ODR_AVL_7HZ_VAL, },
+ { 13, ST_PRESS_LPS331AP_ODR_AVL_13HZ_VAL, },
+ { 25, ST_PRESS_LPS331AP_ODR_AVL_25HZ_VAL, },
},
},
.pw = {
- .addr = ST_PRESS_1_PW_ADDR,
- .mask = ST_PRESS_1_PW_MASK,
+ .addr = ST_PRESS_LPS331AP_PW_ADDR,
+ .mask = ST_PRESS_LPS331AP_PW_MASK,
.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
},
.fs = {
- .addr = ST_PRESS_1_FS_ADDR,
- .mask = ST_PRESS_1_FS_MASK,
+ .addr = ST_PRESS_LPS331AP_FS_ADDR,
+ .mask = ST_PRESS_LPS331AP_FS_MASK,
.fs_avl = {
[0] = {
.num = ST_PRESS_FS_AVL_1260MB,
- .value = ST_PRESS_1_FS_AVL_1260_VAL,
- .gain = ST_PRESS_1_FS_AVL_1260_GAIN,
- .gain2 = ST_PRESS_1_FS_AVL_TEMP_GAIN,
+ .value = ST_PRESS_LPS331AP_FS_AVL_1260_VAL,
+ .gain = ST_PRESS_LPS331AP_FS_AVL_1260_GAIN,
+ .gain2 = ST_PRESS_LPS331AP_FS_AVL_TEMP_GAIN,
},
},
},
.bdu = {
- .addr = ST_PRESS_1_BDU_ADDR,
- .mask = ST_PRESS_1_BDU_MASK,
+ .addr = ST_PRESS_LPS331AP_BDU_ADDR,
+ .mask = ST_PRESS_LPS331AP_BDU_MASK,
+ },
+ .drdy_irq = {
+ .addr = ST_PRESS_LPS331AP_DRDY_IRQ_ADDR,
+ .mask_int1 = ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK,
+ .mask_int2 = ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK,
+ },
+ .multi_read_bit = ST_PRESS_LPS331AP_MULTIREAD_BIT,
+ .bootime = 2,
+ },
+ {
+ .wai = ST_PRESS_LPS001WP_WAI_EXP,
+ .sensors_supported = {
+ [0] = LPS001WP_PRESS_DEV_NAME,
+ },
+ .ch = (struct iio_chan_spec *)st_press_lps001wp_channels,
+ .num_ch = ARRAY_SIZE(st_press_lps001wp_channels),
+ .odr = {
+ .addr = ST_PRESS_LPS001WP_ODR_ADDR,
+ .mask = ST_PRESS_LPS001WP_ODR_MASK,
+ .odr_avl = {
+ { 1, ST_PRESS_LPS001WP_ODR_AVL_1HZ_VAL, },
+ { 7, ST_PRESS_LPS001WP_ODR_AVL_7HZ_VAL, },
+ { 13, ST_PRESS_LPS001WP_ODR_AVL_13HZ_VAL, },
+ },
+ },
+ .pw = {
+ .addr = ST_PRESS_LPS001WP_PW_ADDR,
+ .mask = ST_PRESS_LPS001WP_PW_MASK,
+ .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
+ .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
+ },
+ .fs = {
+ .addr = 0,
+ },
+ .bdu = {
+ .addr = ST_PRESS_LPS001WP_BDU_ADDR,
+ .mask = ST_PRESS_LPS001WP_BDU_MASK,
},
.drdy_irq = {
- .addr = ST_PRESS_1_DRDY_IRQ_ADDR,
- .mask_int1 = ST_PRESS_1_DRDY_IRQ_INT1_MASK,
- .mask_int2 = ST_PRESS_1_DRDY_IRQ_INT2_MASK,
+ .addr = 0,
},
- .multi_read_bit = ST_PRESS_1_MULTIREAD_BIT,
+ .multi_read_bit = ST_PRESS_LPS001WP_MULTIREAD_BIT,
.bootime = 2,
},
};
@@ -210,41 +316,46 @@ static const struct iio_trigger_ops st_press_trigger_ops = {
int st_press_common_probe(struct iio_dev *indio_dev,
struct st_sensors_platform_data *plat_data)
{
- int err;
struct st_sensor_data *pdata = iio_priv(indio_dev);
+ int irq = pdata->get_irq_data_ready(indio_dev);
+ int err;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &press_info;
err = st_sensors_check_device_support(indio_dev,
- ARRAY_SIZE(st_press_sensors), st_press_sensors);
+ ARRAY_SIZE(st_press_sensors),
+ st_press_sensors);
if (err < 0)
- goto st_press_common_probe_error;
+ return err;
pdata->num_data_channels = ST_PRESS_NUMBER_DATA_CHANNELS;
- pdata->multiread_bit = pdata->sensor->multi_read_bit;
- indio_dev->channels = pdata->sensor->ch;
- indio_dev->num_channels = ARRAY_SIZE(st_press_channels);
+ pdata->multiread_bit = pdata->sensor->multi_read_bit;
+ indio_dev->channels = pdata->sensor->ch;
+ indio_dev->num_channels = pdata->sensor->num_ch;
+
+ if (pdata->sensor->fs.addr != 0)
+ pdata->current_fullscale = (struct st_sensor_fullscale_avl *)
+ &pdata->sensor->fs.fs_avl[0];
- pdata->current_fullscale = (struct st_sensor_fullscale_avl *)
- &pdata->sensor->fs.fs_avl[0];
pdata->odr = pdata->sensor->odr.odr_avl[0].hz;
- if (!plat_data)
+ /* Some devices don't support a data ready pin. */
+ if (!plat_data && pdata->sensor->drdy_irq.addr)
plat_data =
(struct st_sensors_platform_data *)&default_press_pdata;
err = st_sensors_init_sensor(indio_dev, plat_data);
if (err < 0)
- goto st_press_common_probe_error;
+ return err;
- if (pdata->get_irq_data_ready(indio_dev) > 0) {
- err = st_press_allocate_ring(indio_dev);
- if (err < 0)
- goto st_press_common_probe_error;
+ err = st_press_allocate_ring(indio_dev);
+ if (err < 0)
+ return err;
+ if (irq > 0) {
err = st_sensors_allocate_trigger(indio_dev,
- ST_PRESS_TRIGGER_OPS);
+ ST_PRESS_TRIGGER_OPS);
if (err < 0)
goto st_press_probe_trigger_error;
}
@@ -256,12 +367,11 @@ int st_press_common_probe(struct iio_dev *indio_dev,
return err;
st_press_device_register_error:
- if (pdata->get_irq_data_ready(indio_dev) > 0)
+ if (irq > 0)
st_sensors_deallocate_trigger(indio_dev);
st_press_probe_trigger_error:
- if (pdata->get_irq_data_ready(indio_dev) > 0)
- st_press_deallocate_ring(indio_dev);
-st_press_common_probe_error:
+ st_press_deallocate_ring(indio_dev);
+
return err;
}
EXPORT_SYMBOL(st_press_common_probe);
@@ -271,10 +381,10 @@ void st_press_common_remove(struct iio_dev *indio_dev)
struct st_sensor_data *pdata = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
- if (pdata->get_irq_data_ready(indio_dev) > 0) {
+ if (pdata->get_irq_data_ready(indio_dev) > 0)
st_sensors_deallocate_trigger(indio_dev);
- st_press_deallocate_ring(indio_dev);
- }
+
+ st_press_deallocate_ring(indio_dev);
}
EXPORT_SYMBOL(st_press_common_remove);
diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c
index 08aac5e6251d..51eab7fcb194 100644
--- a/drivers/iio/pressure/st_pressure_i2c.c
+++ b/drivers/iio/pressure/st_pressure_i2c.c
@@ -49,6 +49,7 @@ static int st_press_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id st_press_id_table[] = {
+ { LPS001WP_PRESS_DEV_NAME },
{ LPS331AP_PRESS_DEV_NAME },
{},
};
diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c
index 6d63883da1ab..84a0789c3d96 100644
--- a/drivers/iio/temperature/tmp006.c
+++ b/drivers/iio/temperature/tmp006.c
@@ -70,12 +70,16 @@ static int tmp006_read_measurement(struct tmp006_data *data, u8 reg)
return i2c_smbus_read_word_swapped(data->client, reg);
}
+static const int tmp006_freqs[5][2] = { {4, 0}, {2, 0}, {1, 0},
+ {0, 500000}, {0, 250000} };
+
static int tmp006_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *channel, int *val,
int *val2, long mask)
{
struct tmp006_data *data = iio_priv(indio_dev);
s32 ret;
+ int cr;
switch (mask) {
case IIO_CHAN_INFO_RAW:
@@ -106,6 +110,12 @@ static int tmp006_read_raw(struct iio_dev *indio_dev,
break;
}
return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ cr = (data->config & TMP006_CONFIG_CR_MASK)
+ >> TMP006_CONFIG_CR_SHIFT;
+ *val = tmp006_freqs[cr][0];
+ *val2 = tmp006_freqs[cr][1];
+ return IIO_VAL_INT_PLUS_MICRO;
default:
break;
}
@@ -113,48 +123,32 @@ static int tmp006_read_raw(struct iio_dev *indio_dev,
return -EINVAL;
}
-static const char * const tmp006_freqs[] = { "4", "2", "1", "0.5", "0.25" };
-
-static ssize_t tmp006_show_freq(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct tmp006_data *data = iio_priv(dev_to_iio_dev(dev));
- int cr = (data->config & TMP006_CONFIG_CR_MASK)
- >> TMP006_CONFIG_CR_SHIFT;
- return sprintf(buf, "%s\n", tmp006_freqs[cr]);
-}
-
-static ssize_t tmp006_store_freq(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
+static int tmp006_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
{
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct tmp006_data *data = iio_priv(indio_dev);
int i;
- bool found = false;
for (i = 0; i < ARRAY_SIZE(tmp006_freqs); i++)
- if (sysfs_streq(buf, tmp006_freqs[i])) {
- found = true;
- break;
- }
- if (!found)
- return -EINVAL;
+ if ((val == tmp006_freqs[i][0]) &&
+ (val2 == tmp006_freqs[i][1])) {
+ data->config &= ~TMP006_CONFIG_CR_MASK;
+ data->config |= i << TMP006_CONFIG_CR_SHIFT;
- data->config &= ~TMP006_CONFIG_CR_MASK;
- data->config |= i << TMP006_CONFIG_CR_SHIFT;
+ return i2c_smbus_write_word_swapped(data->client,
+ TMP006_CONFIG,
+ data->config);
- return i2c_smbus_write_word_swapped(data->client, TMP006_CONFIG,
- data->config);
+ }
+ return -EINVAL;
}
-static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR,
- tmp006_show_freq, tmp006_store_freq);
-
static IIO_CONST_ATTR(sampling_frequency_available, "4 2 1 0.5 0.25");
static struct attribute *tmp006_attributes[] = {
- &iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
NULL
};
@@ -168,16 +162,19 @@ static const struct iio_chan_spec tmp006_channels[] = {
.type = IIO_VOLTAGE,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
},
{
.type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
}
};
static const struct iio_info tmp006_info = {
.read_raw = tmp006_read_raw,
+ .write_raw = tmp006_write_raw,
.attrs = &tmp006_attribute_group,
.driver_module = THIS_MODULE,
};
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 134c3b404a54..a2e758d27584 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -786,10 +786,17 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
- if (pdata)
+ if (pdata) {
error = pxa27x_keypad_build_keycode(keypad);
- else
+ } else {
error = pxa27x_keypad_build_keycode_from_dt(keypad);
+ /*
+ * Data that we get from DT resides in dynamically
+ * allocated memory so we need to update our pdata
+ * pointer.
+ */
+ pdata = keypad->pdata;
+ }
if (error) {
dev_err(&pdev->dev, "failed to build keycode\n");
goto failed_put_clk;
diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c
index 61891486067c..3a90b710e309 100644
--- a/drivers/input/misc/ad714x-spi.c
+++ b/drivers/input/misc/ad714x-spi.c
@@ -108,7 +108,6 @@ static int ad714x_spi_remove(struct spi_device *spi)
struct ad714x_chip *chip = spi_get_drvdata(spi);
ad714x_remove(chip);
- spi_set_drvdata(spi, NULL);
return 0;
}
diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c
index 4f77f87847e8..b5d71d245854 100644
--- a/drivers/input/misc/cobalt_btns.c
+++ b/drivers/input/misc/cobalt_btns.c
@@ -131,7 +131,6 @@ static int cobalt_buttons_probe(struct platform_device *pdev)
err_free_mem:
input_free_polled_device(poll_dev);
kfree(bdev);
- dev_set_drvdata(&pdev->dev, NULL);
return error;
}
@@ -144,7 +143,6 @@ static int cobalt_buttons_remove(struct platform_device *pdev)
input_free_polled_device(bdev->poll_dev);
iounmap(bdev->reg);
kfree(bdev);
- dev_set_drvdata(dev, NULL);
return 0;
}
diff --git a/drivers/input/misc/rb532_button.c b/drivers/input/misc/rb532_button.c
index fb4f8ac3343b..83fff38b86b3 100644
--- a/drivers/input/misc/rb532_button.c
+++ b/drivers/input/misc/rb532_button.c
@@ -87,7 +87,6 @@ static int rb532_button_remove(struct platform_device *pdev)
input_unregister_polled_device(poll_dev);
input_free_polled_device(poll_dev);
- dev_set_drvdata(&pdev->dev, NULL);
return 0;
}
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index a0a4bbaef02c..772835938a52 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -430,20 +430,30 @@ static int uinput_setup_device(struct uinput_device *udev,
return retval;
}
-static ssize_t uinput_inject_event(struct uinput_device *udev,
- const char __user *buffer, size_t count)
+static ssize_t uinput_inject_events(struct uinput_device *udev,
+ const char __user *buffer, size_t count)
{
struct input_event ev;
+ size_t bytes = 0;
- if (count < input_event_size())
+ if (count != 0 && count < input_event_size())
return -EINVAL;
- if (input_event_from_user(buffer, &ev))
- return -EFAULT;
+ while (bytes + input_event_size() <= count) {
+ /*
+ * Note that even if some events were fetched successfully
+ * we are still going to return EFAULT instead of partial
+ * count to let userspace know that it got it's buffers
+ * all wrong.
+ */
+ if (input_event_from_user(buffer + bytes, &ev))
+ return -EFAULT;
- input_event(udev->dev, ev.type, ev.code, ev.value);
+ input_event(udev->dev, ev.type, ev.code, ev.value);
+ bytes += input_event_size();
+ }
- return input_event_size();
+ return bytes;
}
static ssize_t uinput_write(struct file *file, const char __user *buffer,
@@ -460,7 +470,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer,
return retval;
retval = udev->state == UIST_CREATED ?
- uinput_inject_event(udev, buffer, count) :
+ uinput_inject_events(udev, buffer, count) :
uinput_setup_device(udev, buffer, count);
mutex_unlock(&udev->mutex);
diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c
index f51765fff054..ef651ccf130f 100644
--- a/drivers/input/mouse/cypress_ps2.c
+++ b/drivers/input/mouse/cypress_ps2.c
@@ -679,7 +679,7 @@ int cypress_init(struct psmouse *psmouse)
{
struct cytp_data *cytp;
- cytp = (struct cytp_data *)kzalloc(sizeof(struct cytp_data), GFP_KERNEL);
+ cytp = kzalloc(sizeof(struct cytp_data), GFP_KERNEL);
psmouse->private = (void *)cytp;
if (cytp == NULL)
return -ENOMEM;
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index 33b3e88fe4a2..58efc7c3d09c 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -21,7 +21,7 @@ if SERIO
config SERIO_I8042
tristate "i8042 PC Keyboard controller" if EXPERT || !X86
default y
- depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \
+ depends on !PARISC && (!ARM || FOOTBRIDGE_HOST) && \
(!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN && !S390 && \
!ARC
help
@@ -266,4 +266,14 @@ config SERIO_OLPC_APSP
To compile this driver as a module, choose M here: the module will
be called olpc_apsp.
+config HYPERV_KEYBOARD
+ tristate "Microsoft Synthetic Keyboard driver"
+ depends on HYPERV
+ default HYPERV
+ help
+ Select this option to enable the Hyper-V Keyboard driver.
+
+ To compile this driver as a module, choose M here: the module will
+ be called hyperv_keyboard.
+
endif
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index 12298b1c0e71..815d874fe724 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -28,3 +28,4 @@ obj-$(CONFIG_SERIO_ALTERA_PS2) += altera_ps2.o
obj-$(CONFIG_SERIO_ARC_PS2) += arc_ps2.o
obj-$(CONFIG_SERIO_APBPS2) += apbps2.o
obj-$(CONFIG_SERIO_OLPC_APSP) += olpc_apsp.o
+obj-$(CONFIG_HYPERV_KEYBOARD) += hyperv-keyboard.o
diff --git a/drivers/input/serio/hyperv-keyboard.c b/drivers/input/serio/hyperv-keyboard.c
new file mode 100644
index 000000000000..3a83c3c14b23
--- /dev/null
+++ b/drivers/input/serio/hyperv-keyboard.c
@@ -0,0 +1,437 @@
+/*
+ * Copyright (c) 2013, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/completion.h>
+#include <linux/hyperv.h>
+#include <linux/serio.h>
+#include <linux/slab.h>
+
+/*
+ * Current version 1.0
+ *
+ */
+#define SYNTH_KBD_VERSION_MAJOR 1
+#define SYNTH_KBD_VERSION_MINOR 0
+#define SYNTH_KBD_VERSION (SYNTH_KBD_VERSION_MINOR | \
+ (SYNTH_KBD_VERSION_MAJOR << 16))
+
+
+/*
+ * Message types in the synthetic input protocol
+ */
+enum synth_kbd_msg_type {
+ SYNTH_KBD_PROTOCOL_REQUEST = 1,
+ SYNTH_KBD_PROTOCOL_RESPONSE = 2,
+ SYNTH_KBD_EVENT = 3,
+ SYNTH_KBD_LED_INDICATORS = 4,
+};
+
+/*
+ * Basic message structures.
+ */
+struct synth_kbd_msg_hdr {
+ __le32 type;
+};
+
+struct synth_kbd_msg {
+ struct synth_kbd_msg_hdr header;
+ char data[]; /* Enclosed message */
+};
+
+union synth_kbd_version {
+ __le32 version;
+};
+
+/*
+ * Protocol messages
+ */
+struct synth_kbd_protocol_request {
+ struct synth_kbd_msg_hdr header;
+ union synth_kbd_version version_requested;
+};
+
+#define PROTOCOL_ACCEPTED BIT(0)
+struct synth_kbd_protocol_response {
+ struct synth_kbd_msg_hdr header;
+ __le32 proto_status;
+};
+
+#define IS_UNICODE BIT(0)
+#define IS_BREAK BIT(1)
+#define IS_E0 BIT(2)
+#define IS_E1 BIT(3)
+struct synth_kbd_keystroke {
+ struct synth_kbd_msg_hdr header;
+ __le16 make_code;
+ __le16 reserved0;
+ __le32 info; /* Additional information */
+};
+
+
+#define HK_MAXIMUM_MESSAGE_SIZE 256
+
+#define KBD_VSC_SEND_RING_BUFFER_SIZE (10 * PAGE_SIZE)
+#define KBD_VSC_RECV_RING_BUFFER_SIZE (10 * PAGE_SIZE)
+
+#define XTKBD_EMUL0 0xe0
+#define XTKBD_EMUL1 0xe1
+#define XTKBD_RELEASE 0x80
+
+
+/*
+ * Represents a keyboard device
+ */
+struct hv_kbd_dev {
+ struct hv_device *hv_dev;
+ struct serio *hv_serio;
+ struct synth_kbd_protocol_request protocol_req;
+ struct synth_kbd_protocol_response protocol_resp;
+ /* Synchronize the request/response if needed */
+ struct completion wait_event;
+ spinlock_t lock; /* protects 'started' field */
+ bool started;
+};
+
+static void hv_kbd_on_receive(struct hv_device *hv_dev,
+ struct synth_kbd_msg *msg, u32 msg_length)
+{
+ struct hv_kbd_dev *kbd_dev = hv_get_drvdata(hv_dev);
+ struct synth_kbd_keystroke *ks_msg;
+ unsigned long flags;
+ u32 msg_type = __le32_to_cpu(msg->header.type);
+ u32 info;
+ u16 scan_code;
+
+ switch (msg_type) {
+ case SYNTH_KBD_PROTOCOL_RESPONSE:
+ /*
+ * Validate the information provided by the host.
+ * If the host is giving us a bogus packet,
+ * drop the packet (hoping the problem
+ * goes away).
+ */
+ if (msg_length < sizeof(struct synth_kbd_protocol_response)) {
+ dev_err(&hv_dev->device,
+ "Illegal protocol response packet (len: %d)\n",
+ msg_length);
+ break;
+ }
+
+ memcpy(&kbd_dev->protocol_resp, msg,
+ sizeof(struct synth_kbd_protocol_response));
+ complete(&kbd_dev->wait_event);
+ break;
+
+ case SYNTH_KBD_EVENT:
+ /*
+ * Validate the information provided by the host.
+ * If the host is giving us a bogus packet,
+ * drop the packet (hoping the problem
+ * goes away).
+ */
+ if (msg_length < sizeof(struct synth_kbd_keystroke)) {
+ dev_err(&hv_dev->device,
+ "Illegal keyboard event packet (len: %d)\n",
+ msg_length);
+ break;
+ }
+
+ ks_msg = (struct synth_kbd_keystroke *)msg;
+ info = __le32_to_cpu(ks_msg->info);
+
+ /*
+ * Inject the information through the serio interrupt.
+ */
+ spin_lock_irqsave(&kbd_dev->lock, flags);
+ if (kbd_dev->started) {
+ if (info & IS_E0)
+ serio_interrupt(kbd_dev->hv_serio,
+ XTKBD_EMUL0, 0);
+
+ scan_code = __le16_to_cpu(ks_msg->make_code);
+ if (info & IS_BREAK)
+ scan_code |= XTKBD_RELEASE;
+
+ serio_interrupt(kbd_dev->hv_serio, scan_code, 0);
+ }
+ spin_unlock_irqrestore(&kbd_dev->lock, flags);
+ break;
+
+ default:
+ dev_err(&hv_dev->device,
+ "unhandled message type %d\n", msg_type);
+ }
+}
+
+static void hv_kbd_handle_received_packet(struct hv_device *hv_dev,
+ struct vmpacket_descriptor *desc,
+ u32 bytes_recvd,
+ u64 req_id)
+{
+ struct synth_kbd_msg *msg;
+ u32 msg_sz;
+
+ switch (desc->type) {
+ case VM_PKT_COMP:
+ break;
+
+ case VM_PKT_DATA_INBAND:
+ /*
+ * We have a packet that has "inband" data. The API used
+ * for retrieving the packet guarantees that the complete
+ * packet is read. So, minimally, we should be able to
+ * parse the payload header safely (assuming that the host
+ * can be trusted. Trusting the host seems to be a
+ * reasonable assumption because in a virtualized
+ * environment there is not whole lot you can do if you
+ * don't trust the host.
+ *
+ * Nonetheless, let us validate if the host can be trusted
+ * (in a trivial way). The interesting aspect of this
+ * validation is how do you recover if we discover that the
+ * host is not to be trusted? Simply dropping the packet, I
+ * don't think is an appropriate recovery. In the interest
+ * of failing fast, it may be better to crash the guest.
+ * For now, I will just drop the packet!
+ */
+
+ msg_sz = bytes_recvd - (desc->offset8 << 3);
+ if (msg_sz <= sizeof(struct synth_kbd_msg_hdr)) {
+ /*
+ * Drop the packet and hope
+ * the problem magically goes away.
+ */
+ dev_err(&hv_dev->device,
+ "Illegal packet (type: %d, tid: %llx, size: %d)\n",
+ desc->type, req_id, msg_sz);
+ break;
+ }
+
+ msg = (void *)desc + (desc->offset8 << 3);
+ hv_kbd_on_receive(hv_dev, msg, msg_sz);
+ break;
+
+ default:
+ dev_err(&hv_dev->device,
+ "unhandled packet type %d, tid %llx len %d\n",
+ desc->type, req_id, bytes_recvd);
+ break;
+ }
+}
+
+static void hv_kbd_on_channel_callback(void *context)
+{
+ struct hv_device *hv_dev = context;
+ void *buffer;
+ int bufferlen = 0x100; /* Start with sensible size */
+ u32 bytes_recvd;
+ u64 req_id;
+ int error;
+
+ buffer = kmalloc(bufferlen, GFP_ATOMIC);
+ if (!buffer)
+ return;
+
+ while (1) {
+ error = vmbus_recvpacket_raw(hv_dev->channel, buffer, bufferlen,
+ &bytes_recvd, &req_id);
+ switch (error) {
+ case 0:
+ if (bytes_recvd == 0) {
+ kfree(buffer);
+ return;
+ }
+
+ hv_kbd_handle_received_packet(hv_dev, buffer,
+ bytes_recvd, req_id);
+ break;
+
+ case -ENOBUFS:
+ kfree(buffer);
+ /* Handle large packet */
+ bufferlen = bytes_recvd;
+ buffer = kmalloc(bytes_recvd, GFP_ATOMIC);
+ if (!buffer)
+ return;
+ break;
+ }
+ }
+}
+
+static int hv_kbd_connect_to_vsp(struct hv_device *hv_dev)
+{
+ struct hv_kbd_dev *kbd_dev = hv_get_drvdata(hv_dev);
+ struct synth_kbd_protocol_request *request;
+ struct synth_kbd_protocol_response *response;
+ u32 proto_status;
+ int error;
+
+ request = &kbd_dev->protocol_req;
+ memset(request, 0, sizeof(struct synth_kbd_protocol_request));
+ request->header.type = __cpu_to_le32(SYNTH_KBD_PROTOCOL_REQUEST);
+ request->version_requested.version = __cpu_to_le32(SYNTH_KBD_VERSION);
+
+ error = vmbus_sendpacket(hv_dev->channel, request,
+ sizeof(struct synth_kbd_protocol_request),
+ (unsigned long)request,
+ VM_PKT_DATA_INBAND,
+ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+ if (error)
+ return error;
+
+ if (!wait_for_completion_timeout(&kbd_dev->wait_event, 10 * HZ))
+ return -ETIMEDOUT;
+
+ response = &kbd_dev->protocol_resp;
+ proto_status = __le32_to_cpu(response->proto_status);
+ if (!(proto_status & PROTOCOL_ACCEPTED)) {
+ dev_err(&hv_dev->device,
+ "synth_kbd protocol request failed (version %d)\n",
+ SYNTH_KBD_VERSION);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int hv_kbd_start(struct serio *serio)
+{
+ struct hv_kbd_dev *kbd_dev = serio->port_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&kbd_dev->lock, flags);
+ kbd_dev->started = true;
+ spin_unlock_irqrestore(&kbd_dev->lock, flags);
+
+ return 0;
+}
+
+static void hv_kbd_stop(struct serio *serio)
+{
+ struct hv_kbd_dev *kbd_dev = serio->port_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&kbd_dev->lock, flags);
+ kbd_dev->started = false;
+ spin_unlock_irqrestore(&kbd_dev->lock, flags);
+}
+
+static int hv_kbd_probe(struct hv_device *hv_dev,
+ const struct hv_vmbus_device_id *dev_id)
+{
+ struct hv_kbd_dev *kbd_dev;
+ struct serio *hv_serio;
+ int error;
+
+ kbd_dev = kzalloc(sizeof(struct hv_kbd_dev), GFP_KERNEL);
+ hv_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
+ if (!kbd_dev || !hv_serio) {
+ error = -ENOMEM;
+ goto err_free_mem;
+ }
+
+ kbd_dev->hv_dev = hv_dev;
+ kbd_dev->hv_serio = hv_serio;
+ spin_lock_init(&kbd_dev->lock);
+ init_completion(&kbd_dev->wait_event);
+ hv_set_drvdata(hv_dev, kbd_dev);
+
+ hv_serio->dev.parent = &hv_dev->device;
+ hv_serio->id.type = SERIO_8042_XL;
+ hv_serio->port_data = kbd_dev;
+ strlcpy(hv_serio->name, dev_name(&hv_dev->device),
+ sizeof(hv_serio->name));
+ strlcpy(hv_serio->phys, dev_name(&hv_dev->device),
+ sizeof(hv_serio->phys));
+
+ hv_serio->start = hv_kbd_start;
+ hv_serio->stop = hv_kbd_stop;
+
+ error = vmbus_open(hv_dev->channel,
+ KBD_VSC_SEND_RING_BUFFER_SIZE,
+ KBD_VSC_RECV_RING_BUFFER_SIZE,
+ NULL, 0,
+ hv_kbd_on_channel_callback,
+ hv_dev);
+ if (error)
+ goto err_free_mem;
+
+ error = hv_kbd_connect_to_vsp(hv_dev);
+ if (error)
+ goto err_close_vmbus;
+
+ serio_register_port(kbd_dev->hv_serio);
+ return 0;
+
+err_close_vmbus:
+ vmbus_close(hv_dev->channel);
+err_free_mem:
+ kfree(hv_serio);
+ kfree(kbd_dev);
+ return error;
+}
+
+static int hv_kbd_remove(struct hv_device *hv_dev)
+{
+ struct hv_kbd_dev *kbd_dev = hv_get_drvdata(hv_dev);
+
+ serio_unregister_port(kbd_dev->hv_serio);
+ vmbus_close(hv_dev->channel);
+ kfree(kbd_dev);
+
+ hv_set_drvdata(hv_dev, NULL);
+
+ return 0;
+}
+
+/*
+ * Keyboard GUID
+ * {f912ad6d-2b17-48ea-bd65-f927a61c7684}
+ */
+#define HV_KBD_GUID \
+ .guid = { \
+ 0x6d, 0xad, 0x12, 0xf9, 0x17, 0x2b, 0xea, 0x48, \
+ 0xbd, 0x65, 0xf9, 0x27, 0xa6, 0x1c, 0x76, 0x84 \
+ }
+
+static const struct hv_vmbus_device_id id_table[] = {
+ /* Keyboard guid */
+ { HV_KBD_GUID, },
+ { },
+};
+
+MODULE_DEVICE_TABLE(vmbus, id_table);
+
+static struct hv_driver hv_kbd_drv = {
+ .name = KBUILD_MODNAME,
+ .id_table = id_table,
+ .probe = hv_kbd_probe,
+ .remove = hv_kbd_remove,
+};
+
+static int __init hv_kbd_init(void)
+{
+ return vmbus_driver_register(&hv_kbd_drv);
+}
+
+static void __exit hv_kbd_exit(void)
+{
+ vmbus_driver_unregister(&hv_kbd_drv);
+}
+
+MODULE_LICENSE("GPL");
+module_init(hv_kbd_init);
+module_exit(hv_kbd_exit);
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 78e4de42efaa..52c9ebf94729 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -223,21 +223,26 @@ static int i8042_flush(void)
{
unsigned long flags;
unsigned char data, str;
- int i = 0;
+ int count = 0;
+ int retval = 0;
spin_lock_irqsave(&i8042_lock, flags);
- while (((str = i8042_read_status()) & I8042_STR_OBF) && (i < I8042_BUFFER_SIZE)) {
- udelay(50);
- data = i8042_read_data();
- i++;
- dbg("%02x <- i8042 (flush, %s)\n",
- data, str & I8042_STR_AUXDATA ? "aux" : "kbd");
+ while ((str = i8042_read_status()) & I8042_STR_OBF) {
+ if (count++ < I8042_BUFFER_SIZE) {
+ udelay(50);
+ data = i8042_read_data();
+ dbg("%02x <- i8042 (flush, %s)\n",
+ data, str & I8042_STR_AUXDATA ? "aux" : "kbd");
+ } else {
+ retval = -EIO;
+ break;
+ }
}
spin_unlock_irqrestore(&i8042_lock, flags);
- return i;
+ return retval;
}
/*
@@ -849,7 +854,7 @@ static int __init i8042_check_aux(void)
static int i8042_controller_check(void)
{
- if (i8042_flush() == I8042_BUFFER_SIZE) {
+ if (i8042_flush()) {
pr_err("No controller found\n");
return -ENODEV;
}
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 79b69ea47f74..63971b8188b0 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -524,9 +524,6 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int
error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
report_id, rep_data, length, 1);
- if (error >= 0)
- error = wacom_get_report(intf, WAC_HID_FEATURE_REPORT,
- report_id, rep_data, length, 1);
} while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES);
kfree(rep_data);
@@ -548,7 +545,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
/* MT Tablet PC touch */
return wacom_set_device_mode(intf, 3, 4, 4);
}
- else if (features->type == WACOM_24HDT) {
+ else if (features->type == WACOM_24HDT || features->type == CINTIQ_HYBRID) {
return wacom_set_device_mode(intf, 18, 3, 2);
}
} else if (features->device_type == BTN_TOOL_PEN) {
@@ -719,7 +716,7 @@ static int wacom_led_control(struct wacom *wacom)
return -ENOMEM;
if (wacom->wacom_wac.features.type >= INTUOS5S &&
- wacom->wacom_wac.features.type <= INTUOS5L) {
+ wacom->wacom_wac.features.type <= INTUOSPL) {
/*
* Touch Ring and crop mark LED luminance may take on
* one of four values:
@@ -981,14 +978,20 @@ static int wacom_initialize_leds(struct wacom *wacom)
case INTUOS5S:
case INTUOS5:
case INTUOS5L:
- wacom->led.select[0] = 0;
- wacom->led.select[1] = 0;
- wacom->led.llv = 32;
- wacom->led.hlv = 0;
- wacom->led.img_lum = 0;
-
- error = sysfs_create_group(&wacom->intf->dev.kobj,
- &intuos5_led_attr_group);
+ case INTUOSPS:
+ case INTUOSPM:
+ case INTUOSPL:
+ if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN) {
+ wacom->led.select[0] = 0;
+ wacom->led.select[1] = 0;
+ wacom->led.llv = 32;
+ wacom->led.hlv = 0;
+ wacom->led.img_lum = 0;
+
+ error = sysfs_create_group(&wacom->intf->dev.kobj,
+ &intuos5_led_attr_group);
+ } else
+ return 0;
break;
default:
@@ -1024,8 +1027,12 @@ static void wacom_destroy_leds(struct wacom *wacom)
case INTUOS5S:
case INTUOS5:
case INTUOS5L:
- sysfs_remove_group(&wacom->intf->dev.kobj,
- &intuos5_led_attr_group);
+ case INTUOSPS:
+ case INTUOSPM:
+ case INTUOSPL:
+ if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN)
+ sysfs_remove_group(&wacom->intf->dev.kobj,
+ &intuos5_led_attr_group);
break;
}
}
@@ -1298,7 +1305,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
* HID descriptor. If this is the touch interface (wMaxPacketSize
* of WACOM_PKGLEN_BBTOUCH3), override the table values.
*/
- if (features->type >= INTUOS5S && features->type <= INTUOS5L) {
+ if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) {
features->device_type = BTN_TOOL_FINGER;
features->pktlen = WACOM_PKGLEN_BBTOUCH3;
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index b2aa503c16b1..9c8eded2e504 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -427,6 +427,13 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
(features->type == WACOM_21UX2))
return 1;
+ /* Range Report */
+ if ((data[1] & 0xfe) == 0x20) {
+ input_report_key(input, BTN_TOUCH, 0);
+ input_report_abs(input, ABS_PRESSURE, 0);
+ input_report_abs(input, ABS_DISTANCE, wacom->features.distance_max);
+ }
+
/* Exit report */
if ((data[1] & 0xfe) == 0x80) {
if (features->quirks == WACOM_QUIRK_MULTI_INPUT)
@@ -477,7 +484,7 @@ static void wacom_intuos_general(struct wacom_wac *wacom)
/* general pen packet */
if ((data[1] & 0xb8) == 0xa0) {
t = (data[6] << 2) | ((data[7] >> 6) & 3);
- if (features->type >= INTUOS4S && features->type <= WACOM_24HD) {
+ if (features->type >= INTUOS4S && features->type <= CINTIQ_HYBRID) {
t = (t << 1) | (data[1] & 1);
}
input_report_abs(input, ABS_PRESSURE, t);
@@ -621,14 +628,30 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
} else {
input_report_abs(input, ABS_MISC, 0);
}
- } else if (features->type >= INTUOS5S && features->type <= INTUOS5L) {
+ } else if (features->type == CINTIQ_HYBRID) {
+ /*
+ * Do not send hardware buttons under Android. They
+ * are already sent to the system through GPIO (and
+ * have different meaning).
+ */
+ input_report_key(input, BTN_1, (data[4] & 0x01));
+ input_report_key(input, BTN_2, (data[4] & 0x02));
+ input_report_key(input, BTN_3, (data[4] & 0x04));
+ input_report_key(input, BTN_4, (data[4] & 0x08));
+
+ input_report_key(input, BTN_5, (data[4] & 0x10)); /* Right */
+ input_report_key(input, BTN_6, (data[4] & 0x20)); /* Up */
+ input_report_key(input, BTN_7, (data[4] & 0x40)); /* Left */
+ input_report_key(input, BTN_8, (data[4] & 0x80)); /* Down */
+ input_report_key(input, BTN_0, (data[3] & 0x01)); /* Center */
+ } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
int i;
/* Touch ring mode switch has no capacitive sensor */
input_report_key(input, BTN_0, (data[3] & 0x01));
/*
- * ExpressKeys on Intuos5 have a capacitive sensor in
+ * ExpressKeys on Intuos5/Intuos Pro have a capacitive sensor in
* addition to the mechanical switch. Switch data is
* stored in data[4], capacitive data in data[5].
*/
@@ -716,7 +739,9 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
features->type == INTUOS4 ||
features->type == INTUOS4S ||
features->type == INTUOS5 ||
- features->type == INTUOS5S)) {
+ features->type == INTUOS5S ||
+ features->type == INTUOSPM ||
+ features->type == INTUOSPS)) {
return 0;
}
@@ -769,8 +794,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
} else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
/* I4 mouse */
- if ((features->type >= INTUOS4S && features->type <= INTUOS4L) ||
- (features->type >= INTUOS5S && features->type <= INTUOS5L)) {
+ if (features->type >= INTUOS4S && features->type <= INTUOSPL) {
input_report_key(input, BTN_LEFT, data[6] & 0x01);
input_report_key(input, BTN_MIDDLE, data[6] & 0x02);
input_report_key(input, BTN_RIGHT, data[6] & 0x04);
@@ -797,7 +821,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
}
}
} else if ((features->type < INTUOS3S || features->type == INTUOS3L ||
- features->type == INTUOS4L || features->type == INTUOS5L) &&
+ features->type == INTUOS4L || features->type == INTUOS5L ||
+ features->type == INTUOSPL) &&
wacom->tool[idx] == BTN_TOOL_LENS) {
/* Lens cursor packets */
input_report_key(input, BTN_LEFT, data[8] & 0x01);
@@ -1107,6 +1132,7 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
{
+ struct wacom_features *features = &wacom->features;
struct input_dev *input = wacom->input;
bool touch = data[1] & 0x80;
int slot = input_mt_get_slot_by_key(input, data[0]);
@@ -1122,14 +1148,23 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
if (touch) {
int x = (data[2] << 4) | (data[4] >> 4);
int y = (data[3] << 4) | (data[4] & 0x0f);
- int a = data[5];
+ int width, height;
- // "a" is a scaled-down area which we assume is roughly
- // circular and which can be described as: a=(pi*r^2)/C.
- int x_res = input_abs_get_res(input, ABS_X);
- int y_res = input_abs_get_res(input, ABS_Y);
- int width = 2 * int_sqrt(a * WACOM_CONTACT_AREA_SCALE);
- int height = width * y_res / x_res;
+ if (features->type >= INTUOSPS && features->type <= INTUOSPL) {
+ width = data[5];
+ height = data[6];
+ } else {
+ /*
+ * "a" is a scaled-down area which we assume is
+ * roughly circular and which can be described as:
+ * a=(pi*r^2)/C.
+ */
+ int a = data[5];
+ int x_res = input_abs_get_res(input, ABS_X);
+ int y_res = input_abs_get_res(input, ABS_Y);
+ width = 2 * int_sqrt(a * WACOM_CONTACT_AREA_SCALE);
+ height = width * y_res / x_res;
+ }
input_report_abs(input, ABS_MT_POSITION_X, x);
input_report_abs(input, ABS_MT_POSITION_Y, y);
@@ -1327,6 +1362,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
case WACOM_22HD:
case WACOM_24HD:
case DTK:
+ case CINTIQ_HYBRID:
sync = wacom_intuos_irq(wacom_wac);
break;
@@ -1337,6 +1373,9 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
case INTUOS5S:
case INTUOS5:
case INTUOS5L:
+ case INTUOSPS:
+ case INTUOSPM:
+ case INTUOSPL:
if (len == WACOM_PKGLEN_BBTOUCH3)
sync = wacom_bpt3_touch(wacom_wac);
else
@@ -1420,7 +1459,7 @@ void wacom_setup_device_quirks(struct wacom_features *features)
/* these device have multiple inputs */
if (features->type >= WIRELESS ||
- (features->type >= INTUOS5S && features->type <= INTUOS5L) ||
+ (features->type >= INTUOS5S && features->type <= INTUOSPL) ||
(features->oVid && features->oPid))
features->quirks |= WACOM_QUIRK_MULTI_INPUT;
@@ -1627,6 +1666,8 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
case INTUOS5:
case INTUOS5L:
+ case INTUOSPM:
+ case INTUOSPL:
if (features->device_type == BTN_TOOL_PEN) {
__set_bit(BTN_7, input_dev->keybit);
__set_bit(BTN_8, input_dev->keybit);
@@ -1634,6 +1675,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
/* fall through */
case INTUOS5S:
+ case INTUOSPS:
__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
if (features->device_type == BTN_TOOL_PEN) {
@@ -1765,6 +1807,24 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
0, 0);
}
break;
+
+ case CINTIQ_HYBRID:
+ __set_bit(BTN_1, input_dev->keybit);
+ __set_bit(BTN_2, input_dev->keybit);
+ __set_bit(BTN_3, input_dev->keybit);
+ __set_bit(BTN_4, input_dev->keybit);
+
+ __set_bit(BTN_5, input_dev->keybit);
+ __set_bit(BTN_6, input_dev->keybit);
+ __set_bit(BTN_7, input_dev->keybit);
+ __set_bit(BTN_8, input_dev->keybit);
+ __set_bit(BTN_0, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+ __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+ wacom_setup_cintiq(wacom_wac);
+ break;
}
return 0;
}
@@ -1952,6 +2012,18 @@ static const struct wacom_features wacom_features_0x29 =
static const struct wacom_features wacom_features_0x2A =
{ "Wacom Intuos5 M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047,
63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0x314 =
+ { "Wacom Intuos Pro S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047,
+ 63, INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+ .touch_max = 16 };
+static const struct wacom_features wacom_features_0x315 =
+ { "Wacom Intuos Pro M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047,
+ 63, INTUOSPM, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+ .touch_max = 16 };
+static const struct wacom_features wacom_features_0x317 =
+ { "Wacom Intuos Pro L", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047,
+ 63, INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+ .touch_max = 16 };
static const struct wacom_features wacom_features_0xF4 =
{ "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047,
63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
@@ -2125,6 +2197,13 @@ static const struct wacom_features wacom_features_0x301 =
static const struct wacom_features wacom_features_0x6004 =
{ "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255,
0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x0307 =
+ { "Wacom ISDv5 307", WACOM_PKGLEN_INTUOS, 59552, 33848, 2047,
+ 63, CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES,
+ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 };
+static const struct wacom_features wacom_features_0x0309 =
+ { "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */
+ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10 };
#define USB_DEVICE_WACOM(prod) \
USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \
@@ -2251,12 +2330,17 @@ const struct usb_device_id wacom_ids[] = {
{ USB_DEVICE_WACOM(0x300) },
{ USB_DEVICE_WACOM(0x301) },
{ USB_DEVICE_WACOM(0x304) },
+ { USB_DEVICE_DETAILED(0x314, USB_CLASS_HID, 0, 0) },
+ { USB_DEVICE_DETAILED(0x315, USB_CLASS_HID, 0, 0) },
+ { USB_DEVICE_DETAILED(0x317, USB_CLASS_HID, 0, 0) },
{ USB_DEVICE_WACOM(0x4001) },
{ USB_DEVICE_WACOM(0x47) },
{ USB_DEVICE_WACOM(0xF4) },
{ USB_DEVICE_WACOM(0xF8) },
{ USB_DEVICE_DETAILED(0xF6, USB_CLASS_HID, 0, 0) },
{ USB_DEVICE_WACOM(0xFA) },
+ { USB_DEVICE_WACOM(0x0307) },
+ { USB_DEVICE_DETAILED(0x0309, USB_CLASS_HID, 0, 0) },
{ USB_DEVICE_LENOVO(0x6004) },
{ }
};
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index dfc9e08e7f70..2a432e688e51 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -76,10 +76,14 @@ enum {
INTUOS5S,
INTUOS5,
INTUOS5L,
+ INTUOSPS,
+ INTUOSPM,
+ INTUOSPL,
WACOM_21UX2,
WACOM_22HD,
DTK,
WACOM_24HD,
+ CINTIQ_HYBRID,
CINTIQ,
WACOM_BEE,
WACOM_13HD,
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
index f3a174a83c82..69834dd3c313 100644
--- a/drivers/input/touchscreen/ad7877.c
+++ b/drivers/input/touchscreen/ad7877.c
@@ -806,7 +806,6 @@ err_free_irq:
err_free_mem:
input_free_device(input_dev);
kfree(ts);
- spi_set_drvdata(spi, NULL);
return err;
}
@@ -823,7 +822,6 @@ static int ad7877_remove(struct spi_device *spi)
kfree(ts);
dev_dbg(&spi->dev, "unregistered touchscreen\n");
- spi_set_drvdata(spi, NULL);
return 0;
}
diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c
index 606da5bd6115..1a7b1143536e 100644
--- a/drivers/input/touchscreen/ad7879-spi.c
+++ b/drivers/input/touchscreen/ad7879-spi.c
@@ -142,7 +142,6 @@ static int ad7879_spi_remove(struct spi_device *spi)
struct ad7879 *ts = spi_get_drvdata(spi);
ad7879_remove(ts);
- spi_set_drvdata(spi, NULL);
return 0;
}
diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c
index f8ed30f24c8c..a035a390f8e2 100644
--- a/drivers/input/touchscreen/cyttsp4_core.c
+++ b/drivers/input/touchscreen/cyttsp4_core.c
@@ -2112,7 +2112,6 @@ error_startup:
error_request_irq:
if (cd->cpdata->init)
cd->cpdata->init(cd->cpdata, 0, dev);
- dev_set_drvdata(dev, NULL);
error_free_xfer:
kfree(cd->xfer_buf);
error_free_cd:
@@ -2150,7 +2149,6 @@ int cyttsp4_remove(struct cyttsp4 *cd)
free_irq(cd->irq, cd);
if (cd->cpdata->init)
cd->cpdata->init(cd->cpdata, 0, dev);
- dev_set_drvdata(dev, NULL);
cyttsp4_free_si_ptrs(cd);
kfree(cd);
return 0;
diff --git a/drivers/input/touchscreen/htcpen.c b/drivers/input/touchscreen/htcpen.c
index 66500852341b..92e2243fb77d 100644
--- a/drivers/input/touchscreen/htcpen.c
+++ b/drivers/input/touchscreen/htcpen.c
@@ -186,8 +186,6 @@ static int htcpen_isa_remove(struct device *dev, unsigned int id)
release_region(HTCPEN_PORT_INIT, 1);
release_region(HTCPEN_PORT_IRQ_CLEAR, 1);
- dev_set_drvdata(dev, NULL);
-
return 0;
}
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index e1c5300cacfc..24e625c0b531 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -52,6 +52,7 @@ struct titsc {
u32 config_inp[4];
u32 bit_xp, bit_xn, bit_yp, bit_yn;
u32 inp_xp, inp_xn, inp_yp, inp_yn;
+ u32 step_mask;
};
static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
@@ -196,7 +197,8 @@ static void titsc_step_config(struct titsc *ts_dev)
/* The steps1 … end and bit 0 for TS_Charge */
stepenable = (1 << (end_step + 2)) - 1;
- am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable);
+ ts_dev->step_mask = stepenable;
+ am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
}
static void titsc_read_coordinates(struct titsc *ts_dev,
@@ -260,6 +262,10 @@ static irqreturn_t titsc_irq(int irq, void *dev)
unsigned int fsm;
status = titsc_readl(ts_dev, REG_IRQSTATUS);
+ /*
+ * ADC and touchscreen share the IRQ line.
+ * FIFO1 interrupts are used by ADC. Handle FIFO0 IRQs here only
+ */
if (status & IRQENB_FIFO0THRES) {
titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2);
@@ -316,7 +322,7 @@ static irqreturn_t titsc_irq(int irq, void *dev)
if (irqclr) {
titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
- am335x_tsc_se_update(ts_dev->mfd_tscadc);
+ am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
return IRQ_HANDLED;
}
return IRQ_NONE;
@@ -389,7 +395,7 @@ static int titsc_probe(struct platform_device *pdev)
}
err = request_irq(ts_dev->irq, titsc_irq,
- 0, pdev->dev.driver->name, ts_dev);
+ IRQF_SHARED, pdev->dev.driver->name, ts_dev);
if (err) {
dev_err(&pdev->dev, "failed to allocate irq.\n");
goto err_free_mem;
diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c
index 7213e8b07e79..811353353917 100644
--- a/drivers/input/touchscreen/tsc2005.c
+++ b/drivers/input/touchscreen/tsc2005.c
@@ -678,7 +678,6 @@ static int tsc2005_probe(struct spi_device *spi)
err_remove_sysfs:
sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group);
err_clear_drvdata:
- spi_set_drvdata(spi, NULL);
free_irq(spi->irq, ts);
err_free_mem:
input_free_device(input_dev);
@@ -696,7 +695,6 @@ static int tsc2005_remove(struct spi_device *spi)
input_unregister_device(ts->idev);
kfree(ts);
- spi_set_drvdata(spi, NULL);
return 0;
}
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 14c1f474cf11..5d58bf16e9e3 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_IOMMU_API) += iommu.o
+obj-$(CONFIG_IOMMU_API) += iommu-traces.o
obj-$(CONFIG_OF_IOMMU) += of_iommu.o
obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index f417e89e1e7e..181c9ba929cd 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -377,6 +377,7 @@ struct arm_smmu_cfg {
u32 cbar;
pgd_t *pgd;
};
+#define INVALID_IRPTNDX 0xff
#define ARM_SMMU_CB_ASID(cfg) ((cfg)->cbndx)
#define ARM_SMMU_CB_VMID(cfg) ((cfg)->cbndx + 1)
@@ -840,7 +841,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
if (IS_ERR_VALUE(ret)) {
dev_err(smmu->dev, "failed to request context IRQ %d (%u)\n",
root_cfg->irptndx, irq);
- root_cfg->irptndx = -1;
+ root_cfg->irptndx = INVALID_IRPTNDX;
goto out_free_context;
}
@@ -869,7 +870,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
writel_relaxed(0, cb_base + ARM_SMMU_CB_SCTLR);
arm_smmu_tlb_inv_context(root_cfg);
- if (root_cfg->irptndx != -1) {
+ if (root_cfg->irptndx != INVALID_IRPTNDX) {
irq = smmu->irqs[smmu->num_global_irqs + root_cfg->irptndx];
free_irq(irq, domain);
}
@@ -1857,8 +1858,6 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
goto out_put_parent;
}
- arm_smmu_device_reset(smmu);
-
for (i = 0; i < smmu->num_global_irqs; ++i) {
err = request_irq(smmu->irqs[i],
arm_smmu_global_fault,
@@ -1876,6 +1875,8 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
spin_lock(&arm_smmu_devices_lock);
list_add(&smmu->list, &arm_smmu_devices);
spin_unlock(&arm_smmu_devices_lock);
+
+ arm_smmu_device_reset(smmu);
return 0;
out_free_irqs:
@@ -1966,10 +1967,10 @@ static int __init arm_smmu_init(void)
return ret;
/* Oh, for a proper bus abstraction */
- if (!iommu_present(&platform_bus_type));
+ if (!iommu_present(&platform_bus_type))
bus_set_iommu(&platform_bus_type, &arm_smmu_ops);
- if (!iommu_present(&amba_bustype));
+ if (!iommu_present(&amba_bustype))
bus_set_iommu(&amba_bustype, &arm_smmu_ops);
return 0;
diff --git a/drivers/iommu/iommu-traces.c b/drivers/iommu/iommu-traces.c
new file mode 100644
index 000000000000..bf3b317ff0c1
--- /dev/null
+++ b/drivers/iommu/iommu-traces.c
@@ -0,0 +1,27 @@
+/*
+ * iommu trace points
+ *
+ * Copyright (C) 2013 Shuah Khan <shuah.kh@samsung.com>
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/types.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/iommu.h>
+
+/* iommu_group_event */
+EXPORT_TRACEPOINT_SYMBOL_GPL(add_device_to_group);
+EXPORT_TRACEPOINT_SYMBOL_GPL(remove_device_from_group);
+
+/* iommu_device_event */
+EXPORT_TRACEPOINT_SYMBOL_GPL(attach_device_to_domain);
+EXPORT_TRACEPOINT_SYMBOL_GPL(detach_device_from_domain);
+
+/* iommu_map_unmap */
+EXPORT_TRACEPOINT_SYMBOL_GPL(map);
+EXPORT_TRACEPOINT_SYMBOL_GPL(unmap);
+
+/* iommu_error */
+EXPORT_TRACEPOINT_SYMBOL_GPL(io_page_fault);
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index fbe9ca734f8f..e5555fcfe703 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -29,6 +29,7 @@
#include <linux/idr.h>
#include <linux/notifier.h>
#include <linux/err.h>
+#include <trace/events/iommu.h>
static struct kset *iommu_group_kset;
static struct ida iommu_group_ida;
@@ -363,6 +364,8 @@ rename:
/* Notify any listeners about change to group. */
blocking_notifier_call_chain(&group->notifier,
IOMMU_GROUP_NOTIFY_ADD_DEVICE, dev);
+
+ trace_add_device_to_group(group->id, dev);
return 0;
}
EXPORT_SYMBOL_GPL(iommu_group_add_device);
@@ -399,6 +402,8 @@ void iommu_group_remove_device(struct device *dev)
sysfs_remove_link(group->devices_kobj, device->name);
sysfs_remove_link(&dev->kobj, "iommu_group");
+ trace_remove_device_from_group(group->id, dev);
+
kfree(device->name);
kfree(device);
dev->iommu_group = NULL;
@@ -680,10 +685,14 @@ EXPORT_SYMBOL_GPL(iommu_domain_free);
int iommu_attach_device(struct iommu_domain *domain, struct device *dev)
{
+ int ret;
if (unlikely(domain->ops->attach_dev == NULL))
return -ENODEV;
- return domain->ops->attach_dev(domain, dev);
+ ret = domain->ops->attach_dev(domain, dev);
+ if (!ret)
+ trace_attach_device_to_domain(dev);
+ return ret;
}
EXPORT_SYMBOL_GPL(iommu_attach_device);
@@ -693,6 +702,7 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
return;
domain->ops->detach_dev(domain, dev);
+ trace_detach_device_from_domain(dev);
}
EXPORT_SYMBOL_GPL(iommu_detach_device);
@@ -807,17 +817,17 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova,
* size of the smallest page supported by the hardware
*/
if (!IS_ALIGNED(iova | paddr | size, min_pagesz)) {
- pr_err("unaligned: iova 0x%lx pa 0x%pa size 0x%zx min_pagesz 0x%x\n",
+ pr_err("unaligned: iova 0x%lx pa %pa size 0x%zx min_pagesz 0x%x\n",
iova, &paddr, size, min_pagesz);
return -EINVAL;
}
- pr_debug("map: iova 0x%lx pa 0x%pa size 0x%zx\n", iova, &paddr, size);
+ pr_debug("map: iova 0x%lx pa %pa size 0x%zx\n", iova, &paddr, size);
while (size) {
size_t pgsize = iommu_pgsize(domain, iova | paddr, size);
- pr_debug("mapping: iova 0x%lx pa 0x%pa pgsize 0x%zx\n",
+ pr_debug("mapping: iova 0x%lx pa %pa pgsize 0x%zx\n",
iova, &paddr, pgsize);
ret = domain->ops->map(domain, iova, paddr, pgsize, prot);
@@ -832,6 +842,8 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova,
/* unroll mapping in case something went wrong */
if (ret)
iommu_unmap(domain, orig_iova, orig_size - size);
+ else
+ trace_map(iova, paddr, size);
return ret;
}
@@ -880,6 +892,7 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size)
unmapped += unmapped_page;
}
+ trace_unmap(iova, 0, size);
return unmapped;
}
EXPORT_SYMBOL_GPL(iommu_unmap);
diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c
index 108c0e9c24d9..f75483a3a2ef 100644
--- a/drivers/iommu/tegra-gart.c
+++ b/drivers/iommu/tegra-gart.c
@@ -252,7 +252,7 @@ static int gart_iommu_map(struct iommu_domain *domain, unsigned long iova,
spin_lock_irqsave(&gart->pte_lock, flags);
pfn = __phys_to_pfn(pa);
if (!pfn_valid(pfn)) {
- dev_err(gart->dev, "Invalid page: %08x\n", pa);
+ dev_err(gart->dev, "Invalid page: %pa\n", &pa);
spin_unlock_irqrestore(&gart->pte_lock, flags);
return -EINVAL;
}
@@ -295,8 +295,8 @@ static phys_addr_t gart_iommu_iova_to_phys(struct iommu_domain *domain,
pa = (pte & GART_PAGE_MASK);
if (!pfn_valid(__phys_to_pfn(pa))) {
- dev_err(gart->dev, "No entry for %08llx:%08x\n",
- (unsigned long long)iova, pa);
+ dev_err(gart->dev, "No entry for %08llx:%pa\n",
+ (unsigned long long)iova, &pa);
gart_dump_table(gart);
return -EINVAL;
}
@@ -351,7 +351,6 @@ static int tegra_gart_probe(struct platform_device *pdev)
struct gart_device *gart;
struct resource *res, *res_remap;
void __iomem *gart_regs;
- int err;
struct device *dev = &pdev->dev;
if (gart_handle)
@@ -376,8 +375,7 @@ static int tegra_gart_probe(struct platform_device *pdev)
gart_regs = devm_ioremap(dev, res->start, resource_size(res));
if (!gart_regs) {
dev_err(dev, "failed to remap GART registers\n");
- err = -ENXIO;
- goto fail;
+ return -ENXIO;
}
gart->dev = &pdev->dev;
@@ -391,8 +389,7 @@ static int tegra_gart_probe(struct platform_device *pdev)
gart->savedata = vmalloc(sizeof(u32) * gart->page_count);
if (!gart->savedata) {
dev_err(dev, "failed to allocate context save area\n");
- err = -ENOMEM;
- goto fail;
+ return -ENOMEM;
}
platform_set_drvdata(pdev, gart);
@@ -401,27 +398,15 @@ static int tegra_gart_probe(struct platform_device *pdev)
gart_handle = gart;
bus_set_iommu(&platform_bus_type, &gart_iommu_ops);
return 0;
-
-fail:
- if (gart_regs)
- devm_iounmap(dev, gart_regs);
- if (gart && gart->savedata)
- vfree(gart->savedata);
- devm_kfree(dev, gart);
- return err;
}
static int tegra_gart_remove(struct platform_device *pdev)
{
struct gart_device *gart = platform_get_drvdata(pdev);
- struct device *dev = gart->dev;
writel(0, gart->regs + GART_CONFIG);
if (gart->savedata)
vfree(gart->savedata);
- if (gart->regs)
- devm_iounmap(dev, gart->regs);
- devm_kfree(dev, gart);
gart_handle = NULL;
return 0;
}
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index e0665603afd9..34374b3bc13b 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -731,7 +731,7 @@ static int smmu_iommu_map(struct iommu_domain *domain, unsigned long iova,
unsigned long pfn = __phys_to_pfn(pa);
unsigned long flags;
- dev_dbg(as->smmu->dev, "[%d] %08lx:%08x\n", as->asid, iova, pa);
+ dev_dbg(as->smmu->dev, "[%d] %08lx:%pa\n", as->asid, iova, &pa);
if (!pfn_valid(pfn))
return -ENOMEM;
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index bb328a366122..433cc8568dec 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -21,7 +21,10 @@
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include <linux/of_pci.h>
#include <linux/irqdomain.h>
+#include <linux/slab.h>
+#include <linux/msi.h>
#include <asm/mach/arch.h>
#include <asm/exception.h>
#include <asm/smp_plat.h>
@@ -51,12 +54,22 @@
#define IPI_DOORBELL_START (0)
#define IPI_DOORBELL_END (8)
#define IPI_DOORBELL_MASK 0xFF
+#define PCI_MSI_DOORBELL_START (16)
+#define PCI_MSI_DOORBELL_NR (16)
+#define PCI_MSI_DOORBELL_END (32)
+#define PCI_MSI_DOORBELL_MASK 0xFFFF0000
static DEFINE_RAW_SPINLOCK(irq_controller_lock);
static void __iomem *per_cpu_int_base;
static void __iomem *main_int_base;
static struct irq_domain *armada_370_xp_mpic_domain;
+#ifdef CONFIG_PCI_MSI
+static struct irq_domain *armada_370_xp_msi_domain;
+static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR);
+static DEFINE_MUTEX(msi_used_lock);
+static phys_addr_t msi_doorbell_addr;
+#endif
/*
* In SMP mode:
@@ -87,6 +100,144 @@ static void armada_370_xp_irq_unmask(struct irq_data *d)
ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
}
+#ifdef CONFIG_PCI_MSI
+
+static int armada_370_xp_alloc_msi(void)
+{
+ int hwirq;
+
+ mutex_lock(&msi_used_lock);
+ hwirq = find_first_zero_bit(&msi_used, PCI_MSI_DOORBELL_NR);
+ if (hwirq >= PCI_MSI_DOORBELL_NR)
+ hwirq = -ENOSPC;
+ else
+ set_bit(hwirq, msi_used);
+ mutex_unlock(&msi_used_lock);
+
+ return hwirq;
+}
+
+static void armada_370_xp_free_msi(int hwirq)
+{
+ mutex_lock(&msi_used_lock);
+ if (!test_bit(hwirq, msi_used))
+ pr_err("trying to free unused MSI#%d\n", hwirq);
+ else
+ clear_bit(hwirq, msi_used);
+ mutex_unlock(&msi_used_lock);
+}
+
+static int armada_370_xp_setup_msi_irq(struct msi_chip *chip,
+ struct pci_dev *pdev,
+ struct msi_desc *desc)
+{
+ struct msi_msg msg;
+ irq_hw_number_t hwirq;
+ int virq;
+
+ hwirq = armada_370_xp_alloc_msi();
+ if (hwirq < 0)
+ return hwirq;
+
+ virq = irq_create_mapping(armada_370_xp_msi_domain, hwirq);
+ if (!virq) {
+ armada_370_xp_free_msi(hwirq);
+ return -EINVAL;
+ }
+
+ irq_set_msi_desc(virq, desc);
+
+ msg.address_lo = msi_doorbell_addr;
+ msg.address_hi = 0;
+ msg.data = 0xf00 | (hwirq + 16);
+
+ write_msi_msg(virq, &msg);
+ return 0;
+}
+
+static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip,
+ unsigned int irq)
+{
+ struct irq_data *d = irq_get_irq_data(irq);
+ irq_dispose_mapping(irq);
+ armada_370_xp_free_msi(d->hwirq);
+}
+
+static struct irq_chip armada_370_xp_msi_irq_chip = {
+ .name = "armada_370_xp_msi_irq",
+ .irq_enable = unmask_msi_irq,
+ .irq_disable = mask_msi_irq,
+ .irq_mask = mask_msi_irq,
+ .irq_unmask = unmask_msi_irq,
+};
+
+static int armada_370_xp_msi_map(struct irq_domain *domain, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ irq_set_chip_and_handler(virq, &armada_370_xp_msi_irq_chip,
+ handle_simple_irq);
+ set_irq_flags(virq, IRQF_VALID);
+
+ return 0;
+}
+
+static const struct irq_domain_ops armada_370_xp_msi_irq_ops = {
+ .map = armada_370_xp_msi_map,
+};
+
+static int armada_370_xp_msi_init(struct device_node *node,
+ phys_addr_t main_int_phys_base)
+{
+ struct msi_chip *msi_chip;
+ u32 reg;
+ int ret;
+
+ msi_doorbell_addr = main_int_phys_base +
+ ARMADA_370_XP_SW_TRIG_INT_OFFS;
+
+ msi_chip = kzalloc(sizeof(*msi_chip), GFP_KERNEL);
+ if (!msi_chip)
+ return -ENOMEM;
+
+ msi_chip->setup_irq = armada_370_xp_setup_msi_irq;
+ msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq;
+ msi_chip->of_node = node;
+
+ armada_370_xp_msi_domain =
+ irq_domain_add_linear(NULL, PCI_MSI_DOORBELL_NR,
+ &armada_370_xp_msi_irq_ops,
+ NULL);
+ if (!armada_370_xp_msi_domain) {
+ kfree(msi_chip);
+ return -ENOMEM;
+ }
+
+ ret = of_pci_msi_chip_add(msi_chip);
+ if (ret < 0) {
+ irq_domain_remove(armada_370_xp_msi_domain);
+ kfree(msi_chip);
+ return ret;
+ }
+
+ reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS)
+ | PCI_MSI_DOORBELL_MASK;
+
+ writel(reg, per_cpu_int_base +
+ ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
+
+ /* Unmask IPI interrupt */
+ writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
+
+ return 0;
+}
+#else
+static inline int armada_370_xp_msi_init(struct device_node *node,
+ phys_addr_t main_int_phys_base)
+{
+ return 0;
+}
+#endif
+
#ifdef CONFIG_SMP
static int armada_xp_set_affinity(struct irq_data *d,
const struct cpumask *mask_val, bool force)
@@ -214,12 +365,39 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
if (irqnr > 1022)
break;
- if (irqnr > 0) {
+ if (irqnr > 1) {
irqnr = irq_find_mapping(armada_370_xp_mpic_domain,
irqnr);
handle_IRQ(irqnr, regs);
continue;
}
+
+#ifdef CONFIG_PCI_MSI
+ /* MSI handling */
+ if (irqnr == 1) {
+ u32 msimask, msinr;
+
+ msimask = readl_relaxed(per_cpu_int_base +
+ ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
+ & PCI_MSI_DOORBELL_MASK;
+
+ writel(~PCI_MSI_DOORBELL_MASK, per_cpu_int_base +
+ ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
+
+ for (msinr = PCI_MSI_DOORBELL_START;
+ msinr < PCI_MSI_DOORBELL_END; msinr++) {
+ int irq;
+
+ if (!(msimask & BIT(msinr)))
+ continue;
+
+ irq = irq_find_mapping(armada_370_xp_msi_domain,
+ msinr - 16);
+ handle_IRQ(irq, regs);
+ }
+ }
+#endif
+
#ifdef CONFIG_SMP
/* IPI Handling */
if (irqnr == 0) {
@@ -248,12 +426,25 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
static int __init armada_370_xp_mpic_of_init(struct device_node *node,
struct device_node *parent)
{
+ struct resource main_int_res, per_cpu_int_res;
u32 control;
- main_int_base = of_iomap(node, 0);
- per_cpu_int_base = of_iomap(node, 1);
+ BUG_ON(of_address_to_resource(node, 0, &main_int_res));
+ BUG_ON(of_address_to_resource(node, 1, &per_cpu_int_res));
+
+ BUG_ON(!request_mem_region(main_int_res.start,
+ resource_size(&main_int_res),
+ node->full_name));
+ BUG_ON(!request_mem_region(per_cpu_int_res.start,
+ resource_size(&per_cpu_int_res),
+ node->full_name));
+ main_int_base = ioremap(main_int_res.start,
+ resource_size(&main_int_res));
BUG_ON(!main_int_base);
+
+ per_cpu_int_base = ioremap(per_cpu_int_res.start,
+ resource_size(&per_cpu_int_res));
BUG_ON(!per_cpu_int_base);
control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL);
@@ -262,8 +453,7 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
irq_domain_add_linear(node, (control >> 2) & 0x3ff,
&armada_370_xp_mpic_irq_ops, NULL);
- if (!armada_370_xp_mpic_domain)
- panic("Unable to add Armada_370_Xp MPIC irq domain (DT)\n");
+ BUG_ON(!armada_370_xp_mpic_domain);
irq_set_default_host(armada_370_xp_mpic_domain);
@@ -280,6 +470,8 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
#endif
+ armada_370_xp_msi_init(node, main_int_res.start);
+
set_handle_irq(armada_370_xp_handle_irq);
return 0;
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index d0e948084eaf..6365b59181ee 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -253,10 +253,9 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
return -EINVAL;
+ raw_spin_lock(&irq_controller_lock);
mask = 0xff << shift;
bit = gic_cpu_map[cpu] << shift;
-
- raw_spin_lock(&irq_controller_lock);
val = readl_relaxed(reg) & ~mask;
writel_relaxed(val | bit, reg);
raw_spin_unlock(&irq_controller_lock);
@@ -652,7 +651,9 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
{
int cpu;
- unsigned long map = 0;
+ unsigned long flags, map = 0;
+
+ raw_spin_lock_irqsave(&irq_controller_lock, flags);
/* Convert our logical CPU mask into a physical one. */
for_each_cpu(cpu, mask)
@@ -666,6 +667,107 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
/* this always happens on GIC0 */
writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
+
+ raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
+}
+#endif
+
+#ifdef CONFIG_BL_SWITCHER
+/*
+ * gic_get_cpu_id - get the CPU interface ID for the specified CPU
+ *
+ * @cpu: the logical CPU number to get the GIC ID for.
+ *
+ * Return the CPU interface ID for the given logical CPU number,
+ * or -1 if the CPU number is too large or the interface ID is
+ * unknown (more than one bit set).
+ */
+int gic_get_cpu_id(unsigned int cpu)
+{
+ unsigned int cpu_bit;
+
+ if (cpu >= NR_GIC_CPU_IF)
+ return -1;
+ cpu_bit = gic_cpu_map[cpu];
+ if (cpu_bit & (cpu_bit - 1))
+ return -1;
+ return __ffs(cpu_bit);
+}
+
+/*
+ * gic_migrate_target - migrate IRQs to another CPU interface
+ *
+ * @new_cpu_id: the CPU target ID to migrate IRQs to
+ *
+ * Migrate all peripheral interrupts with a target matching the current CPU
+ * to the interface corresponding to @new_cpu_id. The CPU interface mapping
+ * is also updated. Targets to other CPU interfaces are unchanged.
+ * This must be called with IRQs locally disabled.
+ */
+void gic_migrate_target(unsigned int new_cpu_id)
+{
+ unsigned int cur_cpu_id, gic_irqs, gic_nr = 0;
+ void __iomem *dist_base;
+ int i, ror_val, cpu = smp_processor_id();
+ u32 val, cur_target_mask, active_mask;
+
+ if (gic_nr >= MAX_GIC_NR)
+ BUG();
+
+ dist_base = gic_data_dist_base(&gic_data[gic_nr]);
+ if (!dist_base)
+ return;
+ gic_irqs = gic_data[gic_nr].gic_irqs;
+
+ cur_cpu_id = __ffs(gic_cpu_map[cpu]);
+ cur_target_mask = 0x01010101 << cur_cpu_id;
+ ror_val = (cur_cpu_id - new_cpu_id) & 31;
+
+ raw_spin_lock(&irq_controller_lock);
+
+ /* Update the target interface for this logical CPU */
+ gic_cpu_map[cpu] = 1 << new_cpu_id;
+
+ /*
+ * Find all the peripheral interrupts targetting the current
+ * CPU interface and migrate them to the new CPU interface.
+ * We skip DIST_TARGET 0 to 7 as they are read-only.
+ */
+ for (i = 8; i < DIV_ROUND_UP(gic_irqs, 4); i++) {
+ val = readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
+ active_mask = val & cur_target_mask;
+ if (active_mask) {
+ val &= ~active_mask;
+ val |= ror32(active_mask, ror_val);
+ writel_relaxed(val, dist_base + GIC_DIST_TARGET + i*4);
+ }
+ }
+
+ raw_spin_unlock(&irq_controller_lock);
+
+ /*
+ * Now let's migrate and clear any potential SGIs that might be
+ * pending for us (cur_cpu_id). Since GIC_DIST_SGI_PENDING_SET
+ * is a banked register, we can only forward the SGI using
+ * GIC_DIST_SOFTINT. The original SGI source is lost but Linux
+ * doesn't use that information anyway.
+ *
+ * For the same reason we do not adjust SGI source information
+ * for previously sent SGIs by us to other CPUs either.
+ */
+ for (i = 0; i < 16; i += 4) {
+ int j;
+ val = readl_relaxed(dist_base + GIC_DIST_SGI_PENDING_SET + i);
+ if (!val)
+ continue;
+ writel_relaxed(val, dist_base + GIC_DIST_SGI_PENDING_CLEAR + i);
+ for (j = i; j < i + 4; j++) {
+ if (val & 0xff)
+ writel_relaxed((1 << (new_cpu_id + 16)) | j,
+ dist_base + GIC_DIST_SOFTINT);
+ val >>= 8;
+ }
+ }
}
#endif
diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c
index 2bbb00404cf5..8e21ae0bab46 100644
--- a/drivers/irqchip/irq-vic.c
+++ b/drivers/irqchip/irq-vic.c
@@ -469,6 +469,8 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
int __init vic_of_init(struct device_node *node, struct device_node *parent)
{
void __iomem *regs;
+ u32 interrupt_mask = ~0;
+ u32 wakeup_mask = ~0;
if (WARN(parent, "non-root VICs are not supported"))
return -EINVAL;
@@ -477,10 +479,13 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent)
if (WARN_ON(!regs))
return -EIO;
+ of_property_read_u32(node, "valid-mask", &interrupt_mask);
+ of_property_read_u32(node, "valid-wakeup-mask", &wakeup_mask);
+
/*
* Passing 0 as first IRQ makes the simple domain allocate descriptors
*/
- __vic_init(regs, 0, ~0, ~0, node);
+ __vic_init(regs, 0, interrupt_mask, wakeup_mask, node);
return 0;
}
diff --git a/drivers/leds/leds-blinkm.c b/drivers/leds/leds-blinkm.c
index a502678cc7f5..66d0a57db221 100644
--- a/drivers/leds/leds-blinkm.c
+++ b/drivers/leds/leds-blinkm.c
@@ -161,13 +161,10 @@ static ssize_t show_color_common(struct device *dev, char *buf, int color)
switch (color) {
case RED:
return scnprintf(buf, PAGE_SIZE, "%02X\n", data->red);
- break;
case GREEN:
return scnprintf(buf, PAGE_SIZE, "%02X\n", data->green);
- break;
case BLUE:
return scnprintf(buf, PAGE_SIZE, "%02X\n", data->blue);
- break;
default:
return -EINVAL;
}
diff --git a/drivers/leds/leds-dac124s085.c b/drivers/leds/leds-dac124s085.c
index 1f9d8e62d37e..db3ba8b42517 100644
--- a/drivers/leds/leds-dac124s085.c
+++ b/drivers/leds/leds-dac124s085.c
@@ -101,7 +101,6 @@ eledcr:
while (i--)
led_classdev_unregister(&dac->leds[i].ldev);
- spi_set_drvdata(spi, NULL);
return ret;
}
@@ -115,8 +114,6 @@ static int dac124s085_remove(struct spi_device *spi)
cancel_work_sync(&dac->leds[i].work);
}
- spi_set_drvdata(spi, NULL);
-
return 0;
}
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c
index 351825b96f16..075acf5b9fab 100644
--- a/drivers/leds/leds-lp55xx-common.c
+++ b/drivers/leds/leds-lp55xx-common.c
@@ -165,6 +165,7 @@ static int lp55xx_init_led(struct lp55xx_led *led,
led->led_current = pdata->led_config[chan].led_current;
led->max_current = pdata->led_config[chan].max_current;
led->chan_nr = pdata->led_config[chan].chan_nr;
+ led->cdev.default_trigger = pdata->led_config[chan].default_trigger;
if (led->chan_nr >= max_channel) {
dev_err(dev, "Use channel numbers between 0 and %d\n",
@@ -586,6 +587,8 @@ int lp55xx_of_populate_pdata(struct device *dev, struct device_node *np)
of_property_read_string(child, "chan-name", &cfg[i].name);
of_property_read_u8(child, "led-cur", &cfg[i].led_current);
of_property_read_u8(child, "max-cur", &cfg[i].max_current);
+ cfg[i].default_trigger =
+ of_get_property(child, "linux,default-trigger", NULL);
i++;
}
diff --git a/drivers/md/bcache/Kconfig b/drivers/md/bcache/Kconfig
index f950c9d29f3e..2638417b19aa 100644
--- a/drivers/md/bcache/Kconfig
+++ b/drivers/md/bcache/Kconfig
@@ -13,15 +13,8 @@ config BCACHE_DEBUG
---help---
Don't select this option unless you're a developer
- Enables extra debugging tools (primarily a fuzz tester)
-
-config BCACHE_EDEBUG
- bool "Extended runtime checks"
- depends on BCACHE
- ---help---
- Don't select this option unless you're a developer
-
- Enables extra runtime checks which significantly affect performance
+ Enables extra debugging tools, allows expensive runtime checks to be
+ turned on.
config BCACHE_CLOSURES_DEBUG
bool "Debug closures"
diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c
index e45f5575fd4d..2b46bf1d7e40 100644
--- a/drivers/md/bcache/alloc.c
+++ b/drivers/md/bcache/alloc.c
@@ -63,13 +63,12 @@
#include "bcache.h"
#include "btree.h"
+#include <linux/blkdev.h>
#include <linux/freezer.h>
#include <linux/kthread.h>
#include <linux/random.h>
#include <trace/events/bcache.h>
-#define MAX_IN_FLIGHT_DISCARDS 8U
-
/* Bucket heap / gen */
uint8_t bch_inc_gen(struct cache *ca, struct bucket *b)
@@ -121,75 +120,6 @@ void bch_rescale_priorities(struct cache_set *c, int sectors)
mutex_unlock(&c->bucket_lock);
}
-/* Discard/TRIM */
-
-struct discard {
- struct list_head list;
- struct work_struct work;
- struct cache *ca;
- long bucket;
-
- struct bio bio;
- struct bio_vec bv;
-};
-
-static void discard_finish(struct work_struct *w)
-{
- struct discard *d = container_of(w, struct discard, work);
- struct cache *ca = d->ca;
- char buf[BDEVNAME_SIZE];
-
- if (!test_bit(BIO_UPTODATE, &d->bio.bi_flags)) {
- pr_notice("discard error on %s, disabling",
- bdevname(ca->bdev, buf));
- d->ca->discard = 0;
- }
-
- mutex_lock(&ca->set->bucket_lock);
-
- fifo_push(&ca->free, d->bucket);
- list_add(&d->list, &ca->discards);
- atomic_dec(&ca->discards_in_flight);
-
- mutex_unlock(&ca->set->bucket_lock);
-
- closure_wake_up(&ca->set->bucket_wait);
- wake_up_process(ca->alloc_thread);
-
- closure_put(&ca->set->cl);
-}
-
-static void discard_endio(struct bio *bio, int error)
-{
- struct discard *d = container_of(bio, struct discard, bio);
- schedule_work(&d->work);
-}
-
-static void do_discard(struct cache *ca, long bucket)
-{
- struct discard *d = list_first_entry(&ca->discards,
- struct discard, list);
-
- list_del(&d->list);
- d->bucket = bucket;
-
- atomic_inc(&ca->discards_in_flight);
- closure_get(&ca->set->cl);
-
- bio_init(&d->bio);
-
- d->bio.bi_sector = bucket_to_sector(ca->set, d->bucket);
- d->bio.bi_bdev = ca->bdev;
- d->bio.bi_rw = REQ_WRITE|REQ_DISCARD;
- d->bio.bi_max_vecs = 1;
- d->bio.bi_io_vec = d->bio.bi_inline_vecs;
- d->bio.bi_size = bucket_bytes(ca);
- d->bio.bi_end_io = discard_endio;
- bio_set_prio(&d->bio, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0));
-
- submit_bio(0, &d->bio);
-}
-
/* Allocation */
static inline bool can_inc_bucket_gen(struct bucket *b)
@@ -280,7 +210,7 @@ static void invalidate_buckets_lru(struct cache *ca)
* multiple times when it can't do anything
*/
ca->invalidate_needs_gc = 1;
- bch_queue_gc(ca->set);
+ wake_up_gc(ca->set);
return;
}
@@ -305,7 +235,7 @@ static void invalidate_buckets_fifo(struct cache *ca)
if (++checked >= ca->sb.nbuckets) {
ca->invalidate_needs_gc = 1;
- bch_queue_gc(ca->set);
+ wake_up_gc(ca->set);
return;
}
}
@@ -330,7 +260,7 @@ static void invalidate_buckets_random(struct cache *ca)
if (++checked >= ca->sb.nbuckets / 2) {
ca->invalidate_needs_gc = 1;
- bch_queue_gc(ca->set);
+ wake_up_gc(ca->set);
return;
}
}
@@ -398,16 +328,18 @@ static int bch_allocator_thread(void *arg)
else
break;
- allocator_wait(ca, (int) fifo_free(&ca->free) >
- atomic_read(&ca->discards_in_flight));
-
if (ca->discard) {
- allocator_wait(ca, !list_empty(&ca->discards));
- do_discard(ca, bucket);
- } else {
- fifo_push(&ca->free, bucket);
- closure_wake_up(&ca->set->bucket_wait);
+ mutex_unlock(&ca->set->bucket_lock);
+ blkdev_issue_discard(ca->bdev,
+ bucket_to_sector(ca->set, bucket),
+ ca->sb.block_size, GFP_KERNEL, 0);
+ mutex_lock(&ca->set->bucket_lock);
}
+
+ allocator_wait(ca, !fifo_full(&ca->free));
+
+ fifo_push(&ca->free, bucket);
+ wake_up(&ca->set->bucket_wait);
}
/*
@@ -433,16 +365,40 @@ static int bch_allocator_thread(void *arg)
}
}
-long bch_bucket_alloc(struct cache *ca, unsigned watermark, struct closure *cl)
+long bch_bucket_alloc(struct cache *ca, unsigned watermark, bool wait)
{
- long r = -1;
-again:
+ DEFINE_WAIT(w);
+ struct bucket *b;
+ long r;
+
+ /* fastpath */
+ if (fifo_used(&ca->free) > ca->watermark[watermark]) {
+ fifo_pop(&ca->free, r);
+ goto out;
+ }
+
+ if (!wait)
+ return -1;
+
+ while (1) {
+ if (fifo_used(&ca->free) > ca->watermark[watermark]) {
+ fifo_pop(&ca->free, r);
+ break;
+ }
+
+ prepare_to_wait(&ca->set->bucket_wait, &w,
+ TASK_UNINTERRUPTIBLE);
+
+ mutex_unlock(&ca->set->bucket_lock);
+ schedule();
+ mutex_lock(&ca->set->bucket_lock);
+ }
+
+ finish_wait(&ca->set->bucket_wait, &w);
+out:
wake_up_process(ca->alloc_thread);
- if (fifo_used(&ca->free) > ca->watermark[watermark] &&
- fifo_pop(&ca->free, r)) {
- struct bucket *b = ca->buckets + r;
-#ifdef CONFIG_BCACHE_EDEBUG
+ if (expensive_debug_checks(ca->set)) {
size_t iter;
long i;
@@ -455,36 +411,23 @@ again:
BUG_ON(i == r);
fifo_for_each(i, &ca->unused, iter)
BUG_ON(i == r);
-#endif
- BUG_ON(atomic_read(&b->pin) != 1);
-
- SET_GC_SECTORS_USED(b, ca->sb.bucket_size);
-
- if (watermark <= WATERMARK_METADATA) {
- SET_GC_MARK(b, GC_MARK_METADATA);
- b->prio = BTREE_PRIO;
- } else {
- SET_GC_MARK(b, GC_MARK_RECLAIMABLE);
- b->prio = INITIAL_PRIO;
- }
-
- return r;
}
- trace_bcache_alloc_fail(ca);
+ b = ca->buckets + r;
- if (cl) {
- closure_wait(&ca->set->bucket_wait, cl);
+ BUG_ON(atomic_read(&b->pin) != 1);
- if (closure_blocking(cl)) {
- mutex_unlock(&ca->set->bucket_lock);
- closure_sync(cl);
- mutex_lock(&ca->set->bucket_lock);
- goto again;
- }
+ SET_GC_SECTORS_USED(b, ca->sb.bucket_size);
+
+ if (watermark <= WATERMARK_METADATA) {
+ SET_GC_MARK(b, GC_MARK_METADATA);
+ b->prio = BTREE_PRIO;
+ } else {
+ SET_GC_MARK(b, GC_MARK_RECLAIMABLE);
+ b->prio = INITIAL_PRIO;
}
- return -1;
+ return r;
}
void bch_bucket_free(struct cache_set *c, struct bkey *k)
@@ -501,7 +444,7 @@ void bch_bucket_free(struct cache_set *c, struct bkey *k)
}
int __bch_bucket_alloc_set(struct cache_set *c, unsigned watermark,
- struct bkey *k, int n, struct closure *cl)
+ struct bkey *k, int n, bool wait)
{
int i;
@@ -514,7 +457,7 @@ int __bch_bucket_alloc_set(struct cache_set *c, unsigned watermark,
for (i = 0; i < n; i++) {
struct cache *ca = c->cache_by_alloc[i];
- long b = bch_bucket_alloc(ca, watermark, cl);
+ long b = bch_bucket_alloc(ca, watermark, wait);
if (b == -1)
goto err;
@@ -529,22 +472,202 @@ int __bch_bucket_alloc_set(struct cache_set *c, unsigned watermark,
return 0;
err:
bch_bucket_free(c, k);
- __bkey_put(c, k);
+ bkey_put(c, k);
return -1;
}
int bch_bucket_alloc_set(struct cache_set *c, unsigned watermark,
- struct bkey *k, int n, struct closure *cl)
+ struct bkey *k, int n, bool wait)
{
int ret;
mutex_lock(&c->bucket_lock);
- ret = __bch_bucket_alloc_set(c, watermark, k, n, cl);
+ ret = __bch_bucket_alloc_set(c, watermark, k, n, wait);
mutex_unlock(&c->bucket_lock);
return ret;
}
+/* Sector allocator */
+
+struct open_bucket {
+ struct list_head list;
+ unsigned last_write_point;
+ unsigned sectors_free;
+ BKEY_PADDED(key);
+};
+
+/*
+ * We keep multiple buckets open for writes, and try to segregate different
+ * write streams for better cache utilization: first we look for a bucket where
+ * the last write to it was sequential with the current write, and failing that
+ * we look for a bucket that was last used by the same task.
+ *
+ * The ideas is if you've got multiple tasks pulling data into the cache at the
+ * same time, you'll get better cache utilization if you try to segregate their
+ * data and preserve locality.
+ *
+ * For example, say you've starting Firefox at the same time you're copying a
+ * bunch of files. Firefox will likely end up being fairly hot and stay in the
+ * cache awhile, but the data you copied might not be; if you wrote all that
+ * data to the same buckets it'd get invalidated at the same time.
+ *
+ * Both of those tasks will be doing fairly random IO so we can't rely on
+ * detecting sequential IO to segregate their data, but going off of the task
+ * should be a sane heuristic.
+ */
+static struct open_bucket *pick_data_bucket(struct cache_set *c,
+ const struct bkey *search,
+ unsigned write_point,
+ struct bkey *alloc)
+{
+ struct open_bucket *ret, *ret_task = NULL;
+
+ list_for_each_entry_reverse(ret, &c->data_buckets, list)
+ if (!bkey_cmp(&ret->key, search))
+ goto found;
+ else if (ret->last_write_point == write_point)
+ ret_task = ret;
+
+ ret = ret_task ?: list_first_entry(&c->data_buckets,
+ struct open_bucket, list);
+found:
+ if (!ret->sectors_free && KEY_PTRS(alloc)) {
+ ret->sectors_free = c->sb.bucket_size;
+ bkey_copy(&ret->key, alloc);
+ bkey_init(alloc);
+ }
+
+ if (!ret->sectors_free)
+ ret = NULL;
+
+ return ret;
+}
+
+/*
+ * Allocates some space in the cache to write to, and k to point to the newly
+ * allocated space, and updates KEY_SIZE(k) and KEY_OFFSET(k) (to point to the
+ * end of the newly allocated space).
+ *
+ * May allocate fewer sectors than @sectors, KEY_SIZE(k) indicates how many
+ * sectors were actually allocated.
+ *
+ * If s->writeback is true, will not fail.
+ */
+bool bch_alloc_sectors(struct cache_set *c, struct bkey *k, unsigned sectors,
+ unsigned write_point, unsigned write_prio, bool wait)
+{
+ struct open_bucket *b;
+ BKEY_PADDED(key) alloc;
+ unsigned i;
+
+ /*
+ * We might have to allocate a new bucket, which we can't do with a
+ * spinlock held. So if we have to allocate, we drop the lock, allocate
+ * and then retry. KEY_PTRS() indicates whether alloc points to
+ * allocated bucket(s).
+ */
+
+ bkey_init(&alloc.key);
+ spin_lock(&c->data_bucket_lock);
+
+ while (!(b = pick_data_bucket(c, k, write_point, &alloc.key))) {
+ unsigned watermark = write_prio
+ ? WATERMARK_MOVINGGC
+ : WATERMARK_NONE;
+
+ spin_unlock(&c->data_bucket_lock);
+
+ if (bch_bucket_alloc_set(c, watermark, &alloc.key, 1, wait))
+ return false;
+
+ spin_lock(&c->data_bucket_lock);
+ }
+
+ /*
+ * If we had to allocate, we might race and not need to allocate the
+ * second time we call find_data_bucket(). If we allocated a bucket but
+ * didn't use it, drop the refcount bch_bucket_alloc_set() took:
+ */
+ if (KEY_PTRS(&alloc.key))
+ bkey_put(c, &alloc.key);
+
+ for (i = 0; i < KEY_PTRS(&b->key); i++)
+ EBUG_ON(ptr_stale(c, &b->key, i));
+
+ /* Set up the pointer to the space we're allocating: */
+
+ for (i = 0; i < KEY_PTRS(&b->key); i++)
+ k->ptr[i] = b->key.ptr[i];
+
+ sectors = min(sectors, b->sectors_free);
+
+ SET_KEY_OFFSET(k, KEY_OFFSET(k) + sectors);
+ SET_KEY_SIZE(k, sectors);
+ SET_KEY_PTRS(k, KEY_PTRS(&b->key));
+
+ /*
+ * Move b to the end of the lru, and keep track of what this bucket was
+ * last used for:
+ */
+ list_move_tail(&b->list, &c->data_buckets);
+ bkey_copy_key(&b->key, k);
+ b->last_write_point = write_point;
+
+ b->sectors_free -= sectors;
+
+ for (i = 0; i < KEY_PTRS(&b->key); i++) {
+ SET_PTR_OFFSET(&b->key, i, PTR_OFFSET(&b->key, i) + sectors);
+
+ atomic_long_add(sectors,
+ &PTR_CACHE(c, &b->key, i)->sectors_written);
+ }
+
+ if (b->sectors_free < c->sb.block_size)
+ b->sectors_free = 0;
+
+ /*
+ * k takes refcounts on the buckets it points to until it's inserted
+ * into the btree, but if we're done with this bucket we just transfer
+ * get_data_bucket()'s refcount.
+ */
+ if (b->sectors_free)
+ for (i = 0; i < KEY_PTRS(&b->key); i++)
+ atomic_inc(&PTR_BUCKET(c, &b->key, i)->pin);
+
+ spin_unlock(&c->data_bucket_lock);
+ return true;
+}
+
/* Init */
+void bch_open_buckets_free(struct cache_set *c)
+{
+ struct open_bucket *b;
+
+ while (!list_empty(&c->data_buckets)) {
+ b = list_first_entry(&c->data_buckets,
+ struct open_bucket, list);
+ list_del(&b->list);
+ kfree(b);
+ }
+}
+
+int bch_open_buckets_alloc(struct cache_set *c)
+{
+ int i;
+
+ spin_lock_init(&c->data_bucket_lock);
+
+ for (i = 0; i < 6; i++) {
+ struct open_bucket *b = kzalloc(sizeof(*b), GFP_KERNEL);
+ if (!b)
+ return -ENOMEM;
+
+ list_add(&b->list, &c->data_buckets);
+ }
+
+ return 0;
+}
+
int bch_cache_allocator_start(struct cache *ca)
{
struct task_struct *k = kthread_run(bch_allocator_thread,
@@ -556,22 +679,8 @@ int bch_cache_allocator_start(struct cache *ca)
return 0;
}
-void bch_cache_allocator_exit(struct cache *ca)
-{
- struct discard *d;
-
- while (!list_empty(&ca->discards)) {
- d = list_first_entry(&ca->discards, struct discard, list);
- cancel_work_sync(&d->work);
- list_del(&d->list);
- kfree(d);
- }
-}
-
int bch_cache_allocator_init(struct cache *ca)
{
- unsigned i;
-
/*
* Reserve:
* Prio/gen writes first
@@ -589,15 +698,5 @@ int bch_cache_allocator_init(struct cache *ca)
ca->watermark[WATERMARK_NONE] = ca->free.size / 2 +
ca->watermark[WATERMARK_MOVINGGC];
- for (i = 0; i < MAX_IN_FLIGHT_DISCARDS; i++) {
- struct discard *d = kzalloc(sizeof(*d), GFP_KERNEL);
- if (!d)
- return -ENOMEM;
-
- d->ca = ca;
- INIT_WORK(&d->work, discard_finish);
- list_add(&d->list, &ca->discards);
- }
-
return 0;
}
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index 0f12382aa35d..4beb55a0ff30 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -177,6 +177,7 @@
#define pr_fmt(fmt) "bcache: %s() " fmt "\n", __func__
+#include <linux/bcache.h>
#include <linux/bio.h>
#include <linux/kobject.h>
#include <linux/list.h>
@@ -210,168 +211,6 @@ BITMASK(GC_MARK, struct bucket, gc_mark, 0, 2);
#define GC_MARK_METADATA 2
BITMASK(GC_SECTORS_USED, struct bucket, gc_mark, 2, 14);
-struct bkey {
- uint64_t high;
- uint64_t low;
- uint64_t ptr[];
-};
-
-/* Enough for a key with 6 pointers */
-#define BKEY_PAD 8
-
-#define BKEY_PADDED(key) \
- union { struct bkey key; uint64_t key ## _pad[BKEY_PAD]; }
-
-/* Version 0: Cache device
- * Version 1: Backing device
- * Version 2: Seed pointer into btree node checksum
- * Version 3: Cache device with new UUID format
- * Version 4: Backing device with data offset
- */
-#define BCACHE_SB_VERSION_CDEV 0
-#define BCACHE_SB_VERSION_BDEV 1
-#define BCACHE_SB_VERSION_CDEV_WITH_UUID 3
-#define BCACHE_SB_VERSION_BDEV_WITH_OFFSET 4
-#define BCACHE_SB_MAX_VERSION 4
-
-#define SB_SECTOR 8
-#define SB_SIZE 4096
-#define SB_LABEL_SIZE 32
-#define SB_JOURNAL_BUCKETS 256U
-/* SB_JOURNAL_BUCKETS must be divisible by BITS_PER_LONG */
-#define MAX_CACHES_PER_SET 8
-
-#define BDEV_DATA_START_DEFAULT 16 /* sectors */
-
-struct cache_sb {
- uint64_t csum;
- uint64_t offset; /* sector where this sb was written */
- uint64_t version;
-
- uint8_t magic[16];
-
- uint8_t uuid[16];
- union {
- uint8_t set_uuid[16];
- uint64_t set_magic;
- };
- uint8_t label[SB_LABEL_SIZE];
-
- uint64_t flags;
- uint64_t seq;
- uint64_t pad[8];
-
- union {
- struct {
- /* Cache devices */
- uint64_t nbuckets; /* device size */
-
- uint16_t block_size; /* sectors */
- uint16_t bucket_size; /* sectors */
-
- uint16_t nr_in_set;
- uint16_t nr_this_dev;
- };
- struct {
- /* Backing devices */
- uint64_t data_offset;
-
- /*
- * block_size from the cache device section is still used by
- * backing devices, so don't add anything here until we fix
- * things to not need it for backing devices anymore
- */
- };
- };
-
- uint32_t last_mount; /* time_t */
-
- uint16_t first_bucket;
- union {
- uint16_t njournal_buckets;
- uint16_t keys;
- };
- uint64_t d[SB_JOURNAL_BUCKETS]; /* journal buckets */
-};
-
-BITMASK(CACHE_SYNC, struct cache_sb, flags, 0, 1);
-BITMASK(CACHE_DISCARD, struct cache_sb, flags, 1, 1);
-BITMASK(CACHE_REPLACEMENT, struct cache_sb, flags, 2, 3);
-#define CACHE_REPLACEMENT_LRU 0U
-#define CACHE_REPLACEMENT_FIFO 1U
-#define CACHE_REPLACEMENT_RANDOM 2U
-
-BITMASK(BDEV_CACHE_MODE, struct cache_sb, flags, 0, 4);
-#define CACHE_MODE_WRITETHROUGH 0U
-#define CACHE_MODE_WRITEBACK 1U
-#define CACHE_MODE_WRITEAROUND 2U
-#define CACHE_MODE_NONE 3U
-BITMASK(BDEV_STATE, struct cache_sb, flags, 61, 2);
-#define BDEV_STATE_NONE 0U
-#define BDEV_STATE_CLEAN 1U
-#define BDEV_STATE_DIRTY 2U
-#define BDEV_STATE_STALE 3U
-
-/* Version 1: Seed pointer into btree node checksum
- */
-#define BCACHE_BSET_VERSION 1
-
-/*
- * This is the on disk format for btree nodes - a btree node on disk is a list
- * of these; within each set the keys are sorted
- */
-struct bset {
- uint64_t csum;
- uint64_t magic;
- uint64_t seq;
- uint32_t version;
- uint32_t keys;
-
- union {
- struct bkey start[0];
- uint64_t d[0];
- };
-};
-
-/*
- * On disk format for priorities and gens - see super.c near prio_write() for
- * more.
- */
-struct prio_set {
- uint64_t csum;
- uint64_t magic;
- uint64_t seq;
- uint32_t version;
- uint32_t pad;
-
- uint64_t next_bucket;
-
- struct bucket_disk {
- uint16_t prio;
- uint8_t gen;
- } __attribute((packed)) data[];
-};
-
-struct uuid_entry {
- union {
- struct {
- uint8_t uuid[16];
- uint8_t label[32];
- uint32_t first_reg;
- uint32_t last_reg;
- uint32_t invalidated;
-
- uint32_t flags;
- /* Size of flash only volumes */
- uint64_t sectors;
- };
-
- uint8_t pad[128];
- };
-};
-
-BITMASK(UUID_FLASH_ONLY, struct uuid_entry, flags, 0, 1);
-
#include "journal.h"
#include "stats.h"
struct search;
@@ -384,8 +223,6 @@ struct keybuf_key {
void *private;
};
-typedef bool (keybuf_pred_fn)(struct keybuf *, struct bkey *);
-
struct keybuf {
struct bkey last_scanned;
spinlock_t lock;
@@ -400,7 +237,7 @@ struct keybuf {
struct rb_root keys;
-#define KEYBUF_NR 100
+#define KEYBUF_NR 500
DECLARE_ARRAY_ALLOCATOR(struct keybuf_key, freelist, KEYBUF_NR);
};
@@ -429,16 +266,15 @@ struct bcache_device {
struct gendisk *disk;
- /* If nonzero, we're closing */
- atomic_t closing;
-
- /* If nonzero, we're detaching/unregistering from cache set */
- atomic_t detaching;
- int flush_done;
+ unsigned long flags;
+#define BCACHE_DEV_CLOSING 0
+#define BCACHE_DEV_DETACHING 1
+#define BCACHE_DEV_UNLINK_DONE 2
- uint64_t nr_stripes;
- unsigned stripe_size_bits;
+ unsigned nr_stripes;
+ unsigned stripe_size;
atomic_t *stripe_sectors_dirty;
+ unsigned long *full_dirty_stripes;
unsigned long sectors_dirty_last;
long sectors_dirty_derivative;
@@ -509,7 +345,7 @@ struct cached_dev {
/* Limit number of writeback bios in flight */
struct semaphore in_flight;
- struct closure_with_timer writeback;
+ struct task_struct *writeback_thread;
struct keybuf writeback_keys;
@@ -527,8 +363,8 @@ struct cached_dev {
unsigned sequential_cutoff;
unsigned readahead;
- unsigned sequential_merge:1;
unsigned verify:1;
+ unsigned bypass_torture_test:1;
unsigned partial_stripes_expensive:1;
unsigned writeback_metadata:1;
@@ -620,15 +456,6 @@ struct cache {
bool discard; /* Get rid of? */
- /*
- * We preallocate structs for issuing discards to buckets, and keep them
- * on this list when they're not in use; do_discard() issues discards
- * whenever there's work to do and is called by free_some_buckets() and
- * when a discard finishes.
- */
- atomic_t discards_in_flight;
- struct list_head discards;
-
struct journal_device journal;
/* The rest of this all shows up in sysfs */
@@ -649,7 +476,6 @@ struct gc_stat {
size_t nkeys;
uint64_t data; /* sectors */
- uint64_t dirty; /* sectors */
unsigned in_use; /* percent */
};
@@ -744,8 +570,8 @@ struct cache_set {
* basically a lock for this that we can wait on asynchronously. The
* btree_root() macro releases the lock when it returns.
*/
- struct closure *try_harder;
- struct closure_waitlist try_wait;
+ struct task_struct *try_harder;
+ wait_queue_head_t try_wait;
uint64_t try_harder_start;
/*
@@ -759,7 +585,7 @@ struct cache_set {
* written.
*/
atomic_t prio_blocked;
- struct closure_waitlist bucket_wait;
+ wait_queue_head_t bucket_wait;
/*
* For any bio we don't skip we subtract the number of sectors from
@@ -782,7 +608,7 @@ struct cache_set {
struct gc_stat gc_stats;
size_t nbuckets;
- struct closure_with_waitlist gc;
+ struct task_struct *gc_thread;
/* Where in the btree gc currently is */
struct bkey gc_done;
@@ -795,11 +621,10 @@ struct cache_set {
/* Counts how many sectors bio_insert has added to the cache */
atomic_t sectors_to_gc;
- struct closure moving_gc;
- struct closure_waitlist moving_gc_wait;
+ wait_queue_head_t moving_gc_wait;
struct keybuf moving_gc_keys;
/* Number of moving GC bios in flight */
- atomic_t in_flight;
+ struct semaphore moving_in_flight;
struct btree *root;
@@ -841,22 +666,27 @@ struct cache_set {
unsigned congested_read_threshold_us;
unsigned congested_write_threshold_us;
- spinlock_t sort_time_lock;
struct time_stats sort_time;
struct time_stats btree_gc_time;
struct time_stats btree_split_time;
- spinlock_t btree_read_time_lock;
struct time_stats btree_read_time;
struct time_stats try_harder_time;
atomic_long_t cache_read_races;
atomic_long_t writeback_keys_done;
atomic_long_t writeback_keys_failed;
+
+ enum {
+ ON_ERROR_UNREGISTER,
+ ON_ERROR_PANIC,
+ } on_error;
unsigned error_limit;
unsigned error_decay;
+
unsigned short journal_delay_ms;
unsigned verify:1;
unsigned key_merging_disabled:1;
+ unsigned expensive_debug_checks:1;
unsigned gc_always_rewrite:1;
unsigned shrinker_disabled:1;
unsigned copy_gc_enabled:1;
@@ -865,21 +695,6 @@ struct cache_set {
struct hlist_head bucket_hash[1 << BUCKET_HASH_BITS];
};
-static inline bool key_merging_disabled(struct cache_set *c)
-{
-#ifdef CONFIG_BCACHE_DEBUG
- return c->key_merging_disabled;
-#else
- return 0;
-#endif
-}
-
-static inline bool SB_IS_BDEV(const struct cache_sb *sb)
-{
- return sb->version == BCACHE_SB_VERSION_BDEV
- || sb->version == BCACHE_SB_VERSION_BDEV_WITH_OFFSET;
-}
-
struct bbio {
unsigned submit_time_us;
union {
@@ -933,59 +748,6 @@ static inline unsigned local_clock_us(void)
#define prio_buckets(c) \
DIV_ROUND_UP((size_t) (c)->sb.nbuckets, prios_per_bucket(c))
-#define JSET_MAGIC 0x245235c1a3625032ULL
-#define PSET_MAGIC 0x6750e15f87337f91ULL
-#define BSET_MAGIC 0x90135c78b99e07f5ULL
-
-#define jset_magic(c) ((c)->sb.set_magic ^ JSET_MAGIC)
-#define pset_magic(c) ((c)->sb.set_magic ^ PSET_MAGIC)
-#define bset_magic(c) ((c)->sb.set_magic ^ BSET_MAGIC)
-
-/* Bkey fields: all units are in sectors */
-
-#define KEY_FIELD(name, field, offset, size) \
- BITMASK(name, struct bkey, field, offset, size)
-
-#define PTR_FIELD(name, offset, size) \
- static inline uint64_t name(const struct bkey *k, unsigned i) \
- { return (k->ptr[i] >> offset) & ~(((uint64_t) ~0) << size); } \
- \
- static inline void SET_##name(struct bkey *k, unsigned i, uint64_t v)\
- { \
- k->ptr[i] &= ~(~((uint64_t) ~0 << size) << offset); \
- k->ptr[i] |= v << offset; \
- }
-
-KEY_FIELD(KEY_PTRS, high, 60, 3)
-KEY_FIELD(HEADER_SIZE, high, 58, 2)
-KEY_FIELD(KEY_CSUM, high, 56, 2)
-KEY_FIELD(KEY_PINNED, high, 55, 1)
-KEY_FIELD(KEY_DIRTY, high, 36, 1)
-
-KEY_FIELD(KEY_SIZE, high, 20, 16)
-KEY_FIELD(KEY_INODE, high, 0, 20)
-
-/* Next time I change the on disk format, KEY_OFFSET() won't be 64 bits */
-
-static inline uint64_t KEY_OFFSET(const struct bkey *k)
-{
- return k->low;
-}
-
-static inline void SET_KEY_OFFSET(struct bkey *k, uint64_t v)
-{
- k->low = v;
-}
-
-PTR_FIELD(PTR_DEV, 51, 12)
-PTR_FIELD(PTR_OFFSET, 8, 43)
-PTR_FIELD(PTR_GEN, 0, 8)
-
-#define PTR_CHECK_DEV ((1 << 12) - 1)
-
-#define PTR(gen, offset, dev) \
- ((((uint64_t) dev) << 51) | ((uint64_t) offset) << 8 | gen)
-
static inline size_t sector_to_bucket(struct cache_set *c, sector_t s)
{
return s >> c->bucket_bits;
@@ -1024,27 +786,11 @@ static inline struct bucket *PTR_BUCKET(struct cache_set *c,
/* Btree key macros */
-/*
- * The high bit being set is a relic from when we used it to do binary
- * searches - it told you where a key started. It's not used anymore,
- * and can probably be safely dropped.
- */
-#define KEY(dev, sector, len) \
-((struct bkey) { \
- .high = (1ULL << 63) | ((uint64_t) (len) << 20) | (dev), \
- .low = (sector) \
-})
-
static inline void bkey_init(struct bkey *k)
{
- *k = KEY(0, 0, 0);
+ *k = ZERO_KEY;
}
-#define KEY_START(k) (KEY_OFFSET(k) - KEY_SIZE(k))
-#define START_KEY(k) KEY(KEY_INODE(k), KEY_START(k), 0)
-#define MAX_KEY KEY(~(~0 << 20), ((uint64_t) ~0) >> 1, 0)
-#define ZERO_KEY KEY(0, 0, 0)
-
/*
* This is used for various on disk data structures - cache_sb, prio_set, bset,
* jset: The checksum is _always_ the first 8 bytes of these structs
@@ -1094,14 +840,6 @@ do { \
for (b = (ca)->buckets + (ca)->sb.first_bucket; \
b < (ca)->buckets + (ca)->sb.nbuckets; b++)
-static inline void __bkey_put(struct cache_set *c, struct bkey *k)
-{
- unsigned i;
-
- for (i = 0; i < KEY_PTRS(k); i++)
- atomic_dec_bug(&PTR_BUCKET(c, k, i)->pin);
-}
-
static inline void cached_dev_put(struct cached_dev *dc)
{
if (atomic_dec_and_test(&dc->count))
@@ -1173,13 +911,15 @@ uint8_t bch_inc_gen(struct cache *, struct bucket *);
void bch_rescale_priorities(struct cache_set *, int);
bool bch_bucket_add_unused(struct cache *, struct bucket *);
-long bch_bucket_alloc(struct cache *, unsigned, struct closure *);
+long bch_bucket_alloc(struct cache *, unsigned, bool);
void bch_bucket_free(struct cache_set *, struct bkey *);
int __bch_bucket_alloc_set(struct cache_set *, unsigned,
- struct bkey *, int, struct closure *);
+ struct bkey *, int, bool);
int bch_bucket_alloc_set(struct cache_set *, unsigned,
- struct bkey *, int, struct closure *);
+ struct bkey *, int, bool);
+bool bch_alloc_sectors(struct cache_set *, struct bkey *, unsigned,
+ unsigned, unsigned, bool);
__printf(2, 3)
bool bch_cache_set_error(struct cache_set *, const char *, ...);
@@ -1187,7 +927,7 @@ bool bch_cache_set_error(struct cache_set *, const char *, ...);
void bch_prio_write(struct cache *);
void bch_write_bdev_super(struct cached_dev *, struct closure *);
-extern struct workqueue_struct *bcache_wq, *bch_gc_wq;
+extern struct workqueue_struct *bcache_wq;
extern const char * const bch_cache_modes[];
extern struct mutex bch_register_lock;
extern struct list_head bch_cache_sets;
@@ -1220,15 +960,14 @@ struct cache_set *bch_cache_set_alloc(struct cache_sb *);
void bch_btree_cache_free(struct cache_set *);
int bch_btree_cache_alloc(struct cache_set *);
void bch_moving_init_cache_set(struct cache_set *);
+int bch_open_buckets_alloc(struct cache_set *);
+void bch_open_buckets_free(struct cache_set *);
int bch_cache_allocator_start(struct cache *ca);
-void bch_cache_allocator_exit(struct cache *ca);
int bch_cache_allocator_init(struct cache *ca);
void bch_debug_exit(void);
int bch_debug_init(struct kobject *);
-void bch_writeback_exit(void);
-int bch_writeback_init(void);
void bch_request_exit(void);
int bch_request_init(void);
void bch_btree_exit(void);
diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c
index 22d1ae72c282..7d388b8bb50e 100644
--- a/drivers/md/bcache/bset.c
+++ b/drivers/md/bcache/bset.c
@@ -14,22 +14,12 @@
/* Keylists */
-void bch_keylist_copy(struct keylist *dest, struct keylist *src)
-{
- *dest = *src;
-
- if (src->list == src->d) {
- size_t n = (uint64_t *) src->top - src->d;
- dest->top = (struct bkey *) &dest->d[n];
- dest->list = dest->d;
- }
-}
-
int bch_keylist_realloc(struct keylist *l, int nptrs, struct cache_set *c)
{
- unsigned oldsize = (uint64_t *) l->top - l->list;
- unsigned newsize = oldsize + 2 + nptrs;
- uint64_t *new;
+ size_t oldsize = bch_keylist_nkeys(l);
+ size_t newsize = oldsize + 2 + nptrs;
+ uint64_t *old_keys = l->keys_p == l->inline_keys ? NULL : l->keys_p;
+ uint64_t *new_keys;
/* The journalling code doesn't handle the case where the keys to insert
* is bigger than an empty write: If we just return -ENOMEM here,
@@ -45,24 +35,23 @@ int bch_keylist_realloc(struct keylist *l, int nptrs, struct cache_set *c)
roundup_pow_of_two(oldsize) == newsize)
return 0;
- new = krealloc(l->list == l->d ? NULL : l->list,
- sizeof(uint64_t) * newsize, GFP_NOIO);
+ new_keys = krealloc(old_keys, sizeof(uint64_t) * newsize, GFP_NOIO);
- if (!new)
+ if (!new_keys)
return -ENOMEM;
- if (l->list == l->d)
- memcpy(new, l->list, sizeof(uint64_t) * KEYLIST_INLINE);
+ if (!old_keys)
+ memcpy(new_keys, l->inline_keys, sizeof(uint64_t) * oldsize);
- l->list = new;
- l->top = (struct bkey *) (&l->list[oldsize]);
+ l->keys_p = new_keys;
+ l->top_p = new_keys + oldsize;
return 0;
}
struct bkey *bch_keylist_pop(struct keylist *l)
{
- struct bkey *k = l->bottom;
+ struct bkey *k = l->keys;
if (k == l->top)
return NULL;
@@ -73,21 +62,20 @@ struct bkey *bch_keylist_pop(struct keylist *l)
return l->top = k;
}
-/* Pointer validation */
-
-bool __bch_ptr_invalid(struct cache_set *c, int level, const struct bkey *k)
+void bch_keylist_pop_front(struct keylist *l)
{
- unsigned i;
- char buf[80];
+ l->top_p -= bkey_u64s(l->keys);
- if (level && (!KEY_PTRS(k) || !KEY_SIZE(k) || KEY_DIRTY(k)))
- goto bad;
+ memmove(l->keys,
+ bkey_next(l->keys),
+ bch_keylist_bytes(l));
+}
- if (!level && KEY_SIZE(k) > KEY_OFFSET(k))
- goto bad;
+/* Pointer validation */
- if (!KEY_SIZE(k))
- return true;
+static bool __ptr_invalid(struct cache_set *c, const struct bkey *k)
+{
+ unsigned i;
for (i = 0; i < KEY_PTRS(k); i++)
if (ptr_available(c, k, i)) {
@@ -98,13 +86,83 @@ bool __bch_ptr_invalid(struct cache_set *c, int level, const struct bkey *k)
if (KEY_SIZE(k) + r > c->sb.bucket_size ||
bucket < ca->sb.first_bucket ||
bucket >= ca->sb.nbuckets)
- goto bad;
+ return true;
}
return false;
+}
+
+bool bch_btree_ptr_invalid(struct cache_set *c, const struct bkey *k)
+{
+ char buf[80];
+
+ if (!KEY_PTRS(k) || !KEY_SIZE(k) || KEY_DIRTY(k))
+ goto bad;
+
+ if (__ptr_invalid(c, k))
+ goto bad;
+
+ return false;
+bad:
+ bch_bkey_to_text(buf, sizeof(buf), k);
+ cache_bug(c, "spotted btree ptr %s: %s", buf, bch_ptr_status(c, k));
+ return true;
+}
+
+bool bch_extent_ptr_invalid(struct cache_set *c, const struct bkey *k)
+{
+ char buf[80];
+
+ if (!KEY_SIZE(k))
+ return true;
+
+ if (KEY_SIZE(k) > KEY_OFFSET(k))
+ goto bad;
+
+ if (__ptr_invalid(c, k))
+ goto bad;
+
+ return false;
bad:
bch_bkey_to_text(buf, sizeof(buf), k);
- cache_bug(c, "spotted bad key %s: %s", buf, bch_ptr_status(c, k));
+ cache_bug(c, "spotted extent %s: %s", buf, bch_ptr_status(c, k));
+ return true;
+}
+
+static bool ptr_bad_expensive_checks(struct btree *b, const struct bkey *k,
+ unsigned ptr)
+{
+ struct bucket *g = PTR_BUCKET(b->c, k, ptr);
+ char buf[80];
+
+ if (mutex_trylock(&b->c->bucket_lock)) {
+ if (b->level) {
+ if (KEY_DIRTY(k) ||
+ g->prio != BTREE_PRIO ||
+ (b->c->gc_mark_valid &&
+ GC_MARK(g) != GC_MARK_METADATA))
+ goto err;
+
+ } else {
+ if (g->prio == BTREE_PRIO)
+ goto err;
+
+ if (KEY_DIRTY(k) &&
+ b->c->gc_mark_valid &&
+ GC_MARK(g) != GC_MARK_DIRTY)
+ goto err;
+ }
+ mutex_unlock(&b->c->bucket_lock);
+ }
+
+ return false;
+err:
+ mutex_unlock(&b->c->bucket_lock);
+ bch_bkey_to_text(buf, sizeof(buf), k);
+ btree_bug(b,
+"inconsistent pointer %s: bucket %zu pin %i prio %i gen %i last_gc %i mark %llu gc_gen %i",
+ buf, PTR_BUCKET_NR(b->c, k, ptr), atomic_read(&g->pin),
+ g->prio, g->gen, g->last_gc, GC_MARK(g), g->gc_gen);
return true;
}
@@ -118,64 +176,29 @@ bool bch_ptr_bad(struct btree *b, const struct bkey *k)
bch_ptr_invalid(b, k))
return true;
- if (KEY_PTRS(k) && PTR_DEV(k, 0) == PTR_CHECK_DEV)
- return true;
+ for (i = 0; i < KEY_PTRS(k); i++) {
+ if (!ptr_available(b->c, k, i))
+ return true;
- for (i = 0; i < KEY_PTRS(k); i++)
- if (ptr_available(b->c, k, i)) {
- g = PTR_BUCKET(b->c, k, i);
- stale = ptr_stale(b->c, k, i);
+ g = PTR_BUCKET(b->c, k, i);
+ stale = ptr_stale(b->c, k, i);
- btree_bug_on(stale > 96, b,
- "key too stale: %i, need_gc %u",
- stale, b->c->need_gc);
+ btree_bug_on(stale > 96, b,
+ "key too stale: %i, need_gc %u",
+ stale, b->c->need_gc);
- btree_bug_on(stale && KEY_DIRTY(k) && KEY_SIZE(k),
- b, "stale dirty pointer");
+ btree_bug_on(stale && KEY_DIRTY(k) && KEY_SIZE(k),
+ b, "stale dirty pointer");
- if (stale)
- return true;
+ if (stale)
+ return true;
-#ifdef CONFIG_BCACHE_EDEBUG
- if (!mutex_trylock(&b->c->bucket_lock))
- continue;
-
- if (b->level) {
- if (KEY_DIRTY(k) ||
- g->prio != BTREE_PRIO ||
- (b->c->gc_mark_valid &&
- GC_MARK(g) != GC_MARK_METADATA))
- goto bug;
-
- } else {
- if (g->prio == BTREE_PRIO)
- goto bug;
-
- if (KEY_DIRTY(k) &&
- b->c->gc_mark_valid &&
- GC_MARK(g) != GC_MARK_DIRTY)
- goto bug;
- }
- mutex_unlock(&b->c->bucket_lock);
-#endif
- }
+ if (expensive_debug_checks(b->c) &&
+ ptr_bad_expensive_checks(b, k, i))
+ return true;
+ }
return false;
-#ifdef CONFIG_BCACHE_EDEBUG
-bug:
- mutex_unlock(&b->c->bucket_lock);
-
- {
- char buf[80];
-
- bch_bkey_to_text(buf, sizeof(buf), k);
- btree_bug(b,
-"inconsistent pointer %s: bucket %zu pin %i prio %i gen %i last_gc %i mark %llu gc_gen %i",
- buf, PTR_BUCKET_NR(b->c, k, i), atomic_read(&g->pin),
- g->prio, g->gen, g->last_gc, GC_MARK(g), g->gc_gen);
- }
- return true;
-#endif
}
/* Key/pointer manipulation */
@@ -458,16 +481,8 @@ static struct bkey *table_to_bkey(struct bset_tree *t, unsigned cacheline)
static inline uint64_t shrd128(uint64_t high, uint64_t low, uint8_t shift)
{
-#ifdef CONFIG_X86_64
- asm("shrd %[shift],%[high],%[low]"
- : [low] "+Rm" (low)
- : [high] "R" (high),
- [shift] "ci" (shift)
- : "cc");
-#else
low >>= shift;
low |= (high << 1) << (63U - shift);
-#endif
return low;
}
@@ -686,7 +701,7 @@ void bch_bset_init_next(struct btree *b)
} else
get_random_bytes(&i->seq, sizeof(uint64_t));
- i->magic = bset_magic(b->c);
+ i->magic = bset_magic(&b->c->sb);
i->version = 0;
i->keys = 0;
@@ -824,16 +839,16 @@ struct bkey *__bch_bset_search(struct btree *b, struct bset_tree *t,
} else
i = bset_search_write_set(b, t, search);
-#ifdef CONFIG_BCACHE_EDEBUG
- BUG_ON(bset_written(b, t) &&
- i.l != t->data->start &&
- bkey_cmp(tree_to_prev_bkey(t,
- inorder_to_tree(bkey_to_cacheline(t, i.l), t)),
- search) > 0);
+ if (expensive_debug_checks(b->c)) {
+ BUG_ON(bset_written(b, t) &&
+ i.l != t->data->start &&
+ bkey_cmp(tree_to_prev_bkey(t,
+ inorder_to_tree(bkey_to_cacheline(t, i.l), t)),
+ search) > 0);
- BUG_ON(i.r != end(t->data) &&
- bkey_cmp(i.r, search) <= 0);
-#endif
+ BUG_ON(i.r != end(t->data) &&
+ bkey_cmp(i.r, search) <= 0);
+ }
while (likely(i.l != i.r) &&
bkey_cmp(i.l, search) <= 0)
@@ -844,6 +859,13 @@ struct bkey *__bch_bset_search(struct btree *b, struct bset_tree *t,
/* Btree iterator */
+/*
+ * Returns true if l > r - unless l == r, in which case returns true if l is
+ * older than r.
+ *
+ * Necessary for btree_sort_fixup() - if there are multiple keys that compare
+ * equal in different sets, we have to process them newest to oldest.
+ */
static inline bool btree_iter_cmp(struct btree_iter_set l,
struct btree_iter_set r)
{
@@ -867,12 +889,16 @@ void bch_btree_iter_push(struct btree_iter *iter, struct bkey *k,
}
struct bkey *__bch_btree_iter_init(struct btree *b, struct btree_iter *iter,
- struct bkey *search, struct bset_tree *start)
+ struct bkey *search, struct bset_tree *start)
{
struct bkey *ret = NULL;
iter->size = ARRAY_SIZE(iter->data);
iter->used = 0;
+#ifdef CONFIG_BCACHE_DEBUG
+ iter->b = b;
+#endif
+
for (; start <= &b->sets[b->nsets]; start++) {
ret = bch_bset_search(b, start, search);
bch_btree_iter_push(iter, ret, end(start->data));
@@ -887,6 +913,8 @@ struct bkey *bch_btree_iter_next(struct btree_iter *iter)
struct bkey *ret = NULL;
if (!btree_iter_end(iter)) {
+ bch_btree_iter_next_check(iter);
+
ret = iter->data->k;
iter->data->k = bkey_next(iter->data->k);
@@ -916,14 +944,6 @@ struct bkey *bch_btree_iter_next_filter(struct btree_iter *iter,
return ret;
}
-struct bkey *bch_next_recurse_key(struct btree *b, struct bkey *search)
-{
- struct btree_iter iter;
-
- bch_btree_iter_init(b, &iter, search);
- return bch_btree_iter_next_filter(&iter, b, bch_ptr_bad);
-}
-
/* Mergesort */
static void sort_key_next(struct btree_iter *iter,
@@ -998,7 +1018,6 @@ static void btree_mergesort(struct btree *b, struct bset *out,
out->keys = last ? (uint64_t *) bkey_next(last) - out->d : 0;
pr_debug("sorted %i keys", out->keys);
- bch_check_key_order(b, out);
}
static void __btree_sort(struct btree *b, struct btree_iter *iter,
@@ -1029,7 +1048,7 @@ static void __btree_sort(struct btree *b, struct btree_iter *iter,
* memcpy()
*/
- out->magic = bset_magic(b->c);
+ out->magic = bset_magic(&b->c->sb);
out->seq = b->sets[0].data->seq;
out->version = b->sets[0].data->version;
swap(out, b->sets[0].data);
@@ -1050,24 +1069,21 @@ static void __btree_sort(struct btree *b, struct btree_iter *iter,
if (b->written)
bset_build_written_tree(b);
- if (!start) {
- spin_lock(&b->c->sort_time_lock);
+ if (!start)
bch_time_stats_update(&b->c->sort_time, start_time);
- spin_unlock(&b->c->sort_time_lock);
- }
}
void bch_btree_sort_partial(struct btree *b, unsigned start)
{
- size_t oldsize = 0, order = b->page_order, keys = 0;
+ size_t order = b->page_order, keys = 0;
struct btree_iter iter;
+ int oldsize = bch_count_data(b);
+
__bch_btree_iter_init(b, &iter, NULL, &b->sets[start]);
BUG_ON(b->sets[b->nsets].data == write_block(b) &&
(b->sets[b->nsets].size || b->nsets));
- if (b->written)
- oldsize = bch_count_data(b);
if (start) {
unsigned i;
@@ -1083,7 +1099,7 @@ void bch_btree_sort_partial(struct btree *b, unsigned start)
__btree_sort(b, &iter, start, order, false);
- EBUG_ON(b->written && bch_count_data(b) != oldsize);
+ EBUG_ON(b->written && oldsize >= 0 && bch_count_data(b) != oldsize);
}
void bch_btree_sort_and_fix_extents(struct btree *b, struct btree_iter *iter)
@@ -1101,9 +1117,7 @@ void bch_btree_sort_into(struct btree *b, struct btree *new)
btree_mergesort(b, new->sets->data, &iter, false, true);
- spin_lock(&b->c->sort_time_lock);
bch_time_stats_update(&b->c->sort_time, start_time);
- spin_unlock(&b->c->sort_time_lock);
bkey_copy_key(&new->key, &b->key);
new->sets->size = 0;
@@ -1148,16 +1162,16 @@ out:
/* Sysfs stuff */
struct bset_stats {
+ struct btree_op op;
size_t nodes;
size_t sets_written, sets_unwritten;
size_t bytes_written, bytes_unwritten;
size_t floats, failed;
};
-static int bch_btree_bset_stats(struct btree *b, struct btree_op *op,
- struct bset_stats *stats)
+static int btree_bset_stats(struct btree_op *op, struct btree *b)
{
- struct bkey *k;
+ struct bset_stats *stats = container_of(op, struct bset_stats, op);
unsigned i;
stats->nodes++;
@@ -1182,30 +1196,19 @@ static int bch_btree_bset_stats(struct btree *b, struct btree_op *op,
}
}
- if (b->level) {
- struct btree_iter iter;
-
- for_each_key_filter(b, k, &iter, bch_ptr_bad) {
- int ret = btree(bset_stats, k, b, op, stats);
- if (ret)
- return ret;
- }
- }
-
- return 0;
+ return MAP_CONTINUE;
}
int bch_bset_print_stats(struct cache_set *c, char *buf)
{
- struct btree_op op;
struct bset_stats t;
int ret;
- bch_btree_op_init_stack(&op);
memset(&t, 0, sizeof(struct bset_stats));
+ bch_btree_op_init(&t.op, -1);
- ret = btree_root(bset_stats, c, &op, &t);
- if (ret)
+ ret = bch_btree_map_nodes(&t.op, c, &ZERO_KEY, btree_bset_stats);
+ if (ret < 0)
return ret;
return snprintf(buf, PAGE_SIZE,
diff --git a/drivers/md/bcache/bset.h b/drivers/md/bcache/bset.h
index ae115a253d73..d82c128d5b43 100644
--- a/drivers/md/bcache/bset.h
+++ b/drivers/md/bcache/bset.h
@@ -151,6 +151,9 @@ struct btree_iter {
struct btree_iter_set {
struct bkey *k, *end;
} data[MAX_BSETS];
+#ifdef CONFIG_BCACHE_DEBUG
+ struct btree *b;
+#endif
};
struct bset_tree {
@@ -193,54 +196,26 @@ static __always_inline int64_t bkey_cmp(const struct bkey *l,
: (int64_t) KEY_OFFSET(l) - (int64_t) KEY_OFFSET(r);
}
-static inline size_t bkey_u64s(const struct bkey *k)
-{
- BUG_ON(KEY_CSUM(k) > 1);
- return 2 + KEY_PTRS(k) + (KEY_CSUM(k) ? 1 : 0);
-}
-
-static inline size_t bkey_bytes(const struct bkey *k)
-{
- return bkey_u64s(k) * sizeof(uint64_t);
-}
-
-static inline void bkey_copy(struct bkey *dest, const struct bkey *src)
-{
- memcpy(dest, src, bkey_bytes(src));
-}
-
-static inline void bkey_copy_key(struct bkey *dest, const struct bkey *src)
-{
- if (!src)
- src = &KEY(0, 0, 0);
-
- SET_KEY_INODE(dest, KEY_INODE(src));
- SET_KEY_OFFSET(dest, KEY_OFFSET(src));
-}
-
-static inline struct bkey *bkey_next(const struct bkey *k)
-{
- uint64_t *d = (void *) k;
- return (struct bkey *) (d + bkey_u64s(k));
-}
-
/* Keylists */
struct keylist {
- struct bkey *top;
union {
- uint64_t *list;
- struct bkey *bottom;
+ struct bkey *keys;
+ uint64_t *keys_p;
+ };
+ union {
+ struct bkey *top;
+ uint64_t *top_p;
};
/* Enough room for btree_split's keys without realloc */
#define KEYLIST_INLINE 16
- uint64_t d[KEYLIST_INLINE];
+ uint64_t inline_keys[KEYLIST_INLINE];
};
static inline void bch_keylist_init(struct keylist *l)
{
- l->top = (void *) (l->list = l->d);
+ l->top_p = l->keys_p = l->inline_keys;
}
static inline void bch_keylist_push(struct keylist *l)
@@ -256,17 +231,32 @@ static inline void bch_keylist_add(struct keylist *l, struct bkey *k)
static inline bool bch_keylist_empty(struct keylist *l)
{
- return l->top == (void *) l->list;
+ return l->top == l->keys;
+}
+
+static inline void bch_keylist_reset(struct keylist *l)
+{
+ l->top = l->keys;
}
static inline void bch_keylist_free(struct keylist *l)
{
- if (l->list != l->d)
- kfree(l->list);
+ if (l->keys_p != l->inline_keys)
+ kfree(l->keys_p);
+}
+
+static inline size_t bch_keylist_nkeys(struct keylist *l)
+{
+ return l->top_p - l->keys_p;
+}
+
+static inline size_t bch_keylist_bytes(struct keylist *l)
+{
+ return bch_keylist_nkeys(l) * sizeof(uint64_t);
}
-void bch_keylist_copy(struct keylist *, struct keylist *);
struct bkey *bch_keylist_pop(struct keylist *);
+void bch_keylist_pop_front(struct keylist *);
int bch_keylist_realloc(struct keylist *, int, struct cache_set *);
void bch_bkey_copy_single_ptr(struct bkey *, const struct bkey *,
@@ -287,7 +277,9 @@ static inline bool bch_cut_back(const struct bkey *where, struct bkey *k)
}
const char *bch_ptr_status(struct cache_set *, const struct bkey *);
-bool __bch_ptr_invalid(struct cache_set *, int level, const struct bkey *);
+bool bch_btree_ptr_invalid(struct cache_set *, const struct bkey *);
+bool bch_extent_ptr_invalid(struct cache_set *, const struct bkey *);
+
bool bch_ptr_bad(struct btree *, const struct bkey *);
static inline uint8_t gen_after(uint8_t a, uint8_t b)
@@ -311,7 +303,6 @@ static inline bool ptr_available(struct cache_set *c, const struct bkey *k,
typedef bool (*ptr_filter_fn)(struct btree *, const struct bkey *);
-struct bkey *bch_next_recurse_key(struct btree *, struct bkey *);
struct bkey *bch_btree_iter_next(struct btree_iter *);
struct bkey *bch_btree_iter_next_filter(struct btree_iter *,
struct btree *, ptr_filter_fn);
@@ -361,12 +352,30 @@ void bch_bset_fix_lookup_table(struct btree *, struct bkey *);
struct bkey *__bch_bset_search(struct btree *, struct bset_tree *,
const struct bkey *);
+/*
+ * Returns the first key that is strictly greater than search
+ */
static inline struct bkey *bch_bset_search(struct btree *b, struct bset_tree *t,
const struct bkey *search)
{
return search ? __bch_bset_search(b, t, search) : t->data->start;
}
+#define PRECEDING_KEY(_k) \
+({ \
+ struct bkey *_ret = NULL; \
+ \
+ if (KEY_INODE(_k) || KEY_OFFSET(_k)) { \
+ _ret = &KEY(KEY_INODE(_k), KEY_OFFSET(_k), 0); \
+ \
+ if (!_ret->low) \
+ _ret->high--; \
+ _ret->low--; \
+ } \
+ \
+ _ret; \
+})
+
bool bch_bkey_try_merge(struct btree *, struct bkey *, struct bkey *);
void bch_btree_sort_lazy(struct btree *);
void bch_btree_sort_into(struct btree *, struct btree *);
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
index f42fc7ed9cd6..1ccb702c84d5 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -23,12 +23,13 @@
#include "bcache.h"
#include "btree.h"
#include "debug.h"
-#include "request.h"
#include "writeback.h"
#include <linux/slab.h>
#include <linux/bitops.h>
+#include <linux/freezer.h>
#include <linux/hash.h>
+#include <linux/kthread.h>
#include <linux/prefetch.h>
#include <linux/random.h>
#include <linux/rcupdate.h>
@@ -88,15 +89,13 @@
* Test module load/unload
*/
-static const char * const op_types[] = {
- "insert", "replace"
+enum {
+ BTREE_INSERT_STATUS_INSERT,
+ BTREE_INSERT_STATUS_BACK_MERGE,
+ BTREE_INSERT_STATUS_OVERWROTE,
+ BTREE_INSERT_STATUS_FRONT_MERGE,
};
-static const char *op_type(struct btree_op *op)
-{
- return op_types[op->type];
-}
-
#define MAX_NEED_GC 64
#define MAX_SAVE_PRIO 72
@@ -105,23 +104,89 @@ static const char *op_type(struct btree_op *op)
#define PTR_HASH(c, k) \
(((k)->ptr[0] >> c->bucket_bits) | PTR_GEN(k, 0))
-struct workqueue_struct *bch_gc_wq;
static struct workqueue_struct *btree_io_wq;
-void bch_btree_op_init_stack(struct btree_op *op)
+static inline bool should_split(struct btree *b)
{
- memset(op, 0, sizeof(struct btree_op));
- closure_init_stack(&op->cl);
- op->lock = -1;
- bch_keylist_init(&op->keys);
+ struct bset *i = write_block(b);
+ return b->written >= btree_blocks(b) ||
+ (b->written + __set_blocks(i, i->keys + 15, b->c)
+ > btree_blocks(b));
}
+#define insert_lock(s, b) ((b)->level <= (s)->lock)
+
+/*
+ * These macros are for recursing down the btree - they handle the details of
+ * locking and looking up nodes in the cache for you. They're best treated as
+ * mere syntax when reading code that uses them.
+ *
+ * op->lock determines whether we take a read or a write lock at a given depth.
+ * If you've got a read lock and find that you need a write lock (i.e. you're
+ * going to have to split), set op->lock and return -EINTR; btree_root() will
+ * call you again and you'll have the correct lock.
+ */
+
+/**
+ * btree - recurse down the btree on a specified key
+ * @fn: function to call, which will be passed the child node
+ * @key: key to recurse on
+ * @b: parent btree node
+ * @op: pointer to struct btree_op
+ */
+#define btree(fn, key, b, op, ...) \
+({ \
+ int _r, l = (b)->level - 1; \
+ bool _w = l <= (op)->lock; \
+ struct btree *_child = bch_btree_node_get((b)->c, key, l, _w); \
+ if (!IS_ERR(_child)) { \
+ _child->parent = (b); \
+ _r = bch_btree_ ## fn(_child, op, ##__VA_ARGS__); \
+ rw_unlock(_w, _child); \
+ } else \
+ _r = PTR_ERR(_child); \
+ _r; \
+})
+
+/**
+ * btree_root - call a function on the root of the btree
+ * @fn: function to call, which will be passed the child node
+ * @c: cache set
+ * @op: pointer to struct btree_op
+ */
+#define btree_root(fn, c, op, ...) \
+({ \
+ int _r = -EINTR; \
+ do { \
+ struct btree *_b = (c)->root; \
+ bool _w = insert_lock(op, _b); \
+ rw_lock(_w, _b, _b->level); \
+ if (_b == (c)->root && \
+ _w == insert_lock(op, _b)) { \
+ _b->parent = NULL; \
+ _r = bch_btree_ ## fn(_b, op, ##__VA_ARGS__); \
+ } \
+ rw_unlock(_w, _b); \
+ bch_cannibalize_unlock(c); \
+ if (_r == -ENOSPC) { \
+ wait_event((c)->try_wait, \
+ !(c)->try_harder); \
+ _r = -EINTR; \
+ } \
+ } while (_r == -EINTR); \
+ \
+ _r; \
+})
+
/* Btree key manipulation */
-static void bkey_put(struct cache_set *c, struct bkey *k, int level)
+void bkey_put(struct cache_set *c, struct bkey *k)
{
- if ((level && KEY_OFFSET(k)) || !level)
- __bkey_put(c, k);
+ unsigned i;
+
+ for (i = 0; i < KEY_PTRS(k); i++)
+ if (ptr_available(c, k, i))
+ atomic_dec_bug(&PTR_BUCKET(c, k, i)->pin);
}
/* Btree IO */
@@ -145,6 +210,10 @@ static void bch_btree_node_read_done(struct btree *b)
iter->size = b->c->sb.bucket_size / b->c->sb.block_size;
iter->used = 0;
+#ifdef CONFIG_BCACHE_DEBUG
+ iter->b = b;
+#endif
+
if (!i->seq)
goto err;
@@ -160,7 +229,7 @@ static void bch_btree_node_read_done(struct btree *b)
goto err;
err = "bad magic";
- if (i->magic != bset_magic(b->c))
+ if (i->magic != bset_magic(&b->c->sb))
goto err;
err = "bad checksum";
@@ -248,10 +317,7 @@ void bch_btree_node_read(struct btree *b)
goto err;
bch_btree_node_read_done(b);
-
- spin_lock(&b->c->btree_read_time_lock);
bch_time_stats_update(&b->c->btree_read_time, start_time);
- spin_unlock(&b->c->btree_read_time_lock);
return;
err:
@@ -327,7 +393,7 @@ static void do_btree_node_write(struct btree *b)
b->bio = bch_bbio_alloc(b->c);
b->bio->bi_end_io = btree_node_write_endio;
- b->bio->bi_private = &b->io.cl;
+ b->bio->bi_private = cl;
b->bio->bi_rw = REQ_META|WRITE_SYNC|REQ_FUA;
b->bio->bi_size = set_blocks(i, b->c) * block_bytes(b->c);
bch_bio_map(b->bio, i);
@@ -383,7 +449,7 @@ void bch_btree_node_write(struct btree *b, struct closure *parent)
BUG_ON(b->written >= btree_blocks(b));
BUG_ON(b->written && !i->keys);
BUG_ON(b->sets->data->seq != i->seq);
- bch_check_key_order(b, i);
+ bch_check_keys(b, "writing");
cancel_delayed_work(&b->work);
@@ -405,6 +471,15 @@ void bch_btree_node_write(struct btree *b, struct closure *parent)
bch_bset_init_next(b);
}
+static void bch_btree_node_write_sync(struct btree *b)
+{
+ struct closure cl;
+
+ closure_init_stack(&cl);
+ bch_btree_node_write(b, &cl);
+ closure_sync(&cl);
+}
+
static void btree_node_write_work(struct work_struct *w)
{
struct btree *b = container_of(to_delayed_work(w), struct btree, work);
@@ -416,7 +491,7 @@ static void btree_node_write_work(struct work_struct *w)
rw_unlock(true, b);
}
-static void bch_btree_leaf_dirty(struct btree *b, struct btree_op *op)
+static void bch_btree_leaf_dirty(struct btree *b, atomic_t *journal_ref)
{
struct bset *i = b->sets[b->nsets].data;
struct btree_write *w = btree_current_write(b);
@@ -429,15 +504,15 @@ static void bch_btree_leaf_dirty(struct btree *b, struct btree_op *op)
set_btree_node_dirty(b);
- if (op && op->journal) {
+ if (journal_ref) {
if (w->journal &&
- journal_pin_cmp(b->c, w, op)) {
+ journal_pin_cmp(b->c, w->journal, journal_ref)) {
atomic_dec_bug(w->journal);
w->journal = NULL;
}
if (!w->journal) {
- w->journal = op->journal;
+ w->journal = journal_ref;
atomic_inc(w->journal);
}
}
@@ -566,33 +641,32 @@ static struct btree *mca_bucket_alloc(struct cache_set *c,
return b;
}
-static int mca_reap(struct btree *b, struct closure *cl, unsigned min_order)
+static int mca_reap(struct btree *b, unsigned min_order, bool flush)
{
+ struct closure cl;
+
+ closure_init_stack(&cl);
lockdep_assert_held(&b->c->bucket_lock);
if (!down_write_trylock(&b->lock))
return -ENOMEM;
- if (b->page_order < min_order) {
+ BUG_ON(btree_node_dirty(b) && !b->sets[0].data);
+
+ if (b->page_order < min_order ||
+ (!flush &&
+ (btree_node_dirty(b) ||
+ atomic_read(&b->io.cl.remaining) != -1))) {
rw_unlock(true, b);
return -ENOMEM;
}
- BUG_ON(btree_node_dirty(b) && !b->sets[0].data);
-
- if (cl && btree_node_dirty(b))
- bch_btree_node_write(b, NULL);
-
- if (cl)
- closure_wait_event_async(&b->io.wait, cl,
- atomic_read(&b->io.cl.remaining) == -1);
+ if (btree_node_dirty(b))
+ bch_btree_node_write_sync(b);
- if (btree_node_dirty(b) ||
- !closure_is_unlocked(&b->io.cl) ||
- work_pending(&b->work.work)) {
- rw_unlock(true, b);
- return -EAGAIN;
- }
+ /* wait for any in flight btree write */
+ closure_wait_event(&b->io.wait, &cl,
+ atomic_read(&b->io.cl.remaining) == -1);
return 0;
}
@@ -633,7 +707,7 @@ static unsigned long bch_mca_scan(struct shrinker *shrink,
break;
if (++i > 3 &&
- !mca_reap(b, NULL, 0)) {
+ !mca_reap(b, 0, false)) {
mca_data_free(b);
rw_unlock(true, b);
freed++;
@@ -652,7 +726,7 @@ static unsigned long bch_mca_scan(struct shrinker *shrink,
list_rotate_left(&c->btree_cache);
if (!b->accessed &&
- !mca_reap(b, NULL, 0)) {
+ !mca_reap(b, 0, false)) {
mca_bucket_free(b);
mca_data_free(b);
rw_unlock(true, b);
@@ -723,12 +797,9 @@ int bch_btree_cache_alloc(struct cache_set *c)
{
unsigned i;
- /* XXX: doesn't check for errors */
-
- closure_init_unlocked(&c->gc);
-
for (i = 0; i < mca_reserve(c); i++)
- mca_bucket_alloc(c, &ZERO_KEY, GFP_KERNEL);
+ if (!mca_bucket_alloc(c, &ZERO_KEY, GFP_KERNEL))
+ return -ENOMEM;
list_splice_init(&c->btree_cache,
&c->btree_cache_freeable);
@@ -775,52 +846,27 @@ out:
return b;
}
-static struct btree *mca_cannibalize(struct cache_set *c, struct bkey *k,
- int level, struct closure *cl)
+static struct btree *mca_cannibalize(struct cache_set *c, struct bkey *k)
{
- int ret = -ENOMEM;
- struct btree *i;
+ struct btree *b;
trace_bcache_btree_cache_cannibalize(c);
- if (!cl)
- return ERR_PTR(-ENOMEM);
-
- /*
- * Trying to free up some memory - i.e. reuse some btree nodes - may
- * require initiating IO to flush the dirty part of the node. If we're
- * running under generic_make_request(), that IO will never finish and
- * we would deadlock. Returning -EAGAIN causes the cache lookup code to
- * punt to workqueue and retry.
- */
- if (current->bio_list)
- return ERR_PTR(-EAGAIN);
+ if (!c->try_harder) {
+ c->try_harder = current;
+ c->try_harder_start = local_clock();
+ } else if (c->try_harder != current)
+ return ERR_PTR(-ENOSPC);
- if (c->try_harder && c->try_harder != cl) {
- closure_wait_event_async(&c->try_wait, cl, !c->try_harder);
- return ERR_PTR(-EAGAIN);
- }
-
- c->try_harder = cl;
- c->try_harder_start = local_clock();
-retry:
- list_for_each_entry_reverse(i, &c->btree_cache, list) {
- int r = mca_reap(i, cl, btree_order(k));
- if (!r)
- return i;
- if (r != -ENOMEM)
- ret = r;
- }
+ list_for_each_entry_reverse(b, &c->btree_cache, list)
+ if (!mca_reap(b, btree_order(k), false))
+ return b;
- if (ret == -EAGAIN &&
- closure_blocking(cl)) {
- mutex_unlock(&c->bucket_lock);
- closure_sync(cl);
- mutex_lock(&c->bucket_lock);
- goto retry;
- }
+ list_for_each_entry_reverse(b, &c->btree_cache, list)
+ if (!mca_reap(b, btree_order(k), true))
+ return b;
- return ERR_PTR(ret);
+ return ERR_PTR(-ENOMEM);
}
/*
@@ -829,20 +875,21 @@ retry:
* cannibalize_bucket() will take. This means every time we unlock the root of
* the btree, we need to release this lock if we have it held.
*/
-void bch_cannibalize_unlock(struct cache_set *c, struct closure *cl)
+static void bch_cannibalize_unlock(struct cache_set *c)
{
- if (c->try_harder == cl) {
+ if (c->try_harder == current) {
bch_time_stats_update(&c->try_harder_time, c->try_harder_start);
c->try_harder = NULL;
- __closure_wake_up(&c->try_wait);
+ wake_up(&c->try_wait);
}
}
-static struct btree *mca_alloc(struct cache_set *c, struct bkey *k,
- int level, struct closure *cl)
+static struct btree *mca_alloc(struct cache_set *c, struct bkey *k, int level)
{
struct btree *b;
+ BUG_ON(current->bio_list);
+
lockdep_assert_held(&c->bucket_lock);
if (mca_find(c, k))
@@ -852,14 +899,14 @@ static struct btree *mca_alloc(struct cache_set *c, struct bkey *k,
* the list. Check if there's any freed nodes there:
*/
list_for_each_entry(b, &c->btree_cache_freeable, list)
- if (!mca_reap(b, NULL, btree_order(k)))
+ if (!mca_reap(b, btree_order(k), false))
goto out;
/* We never free struct btree itself, just the memory that holds the on
* disk node. Check the freed list before allocating a new one:
*/
list_for_each_entry(b, &c->btree_cache_freed, list)
- if (!mca_reap(b, NULL, 0)) {
+ if (!mca_reap(b, 0, false)) {
mca_data_alloc(b, k, __GFP_NOWARN|GFP_NOIO);
if (!b->sets[0].data)
goto err;
@@ -884,6 +931,7 @@ out:
lock_set_subclass(&b->lock.dep_map, level + 1, _THIS_IP_);
b->level = level;
+ b->parent = (void *) ~0UL;
mca_reinit(b);
@@ -892,7 +940,7 @@ err:
if (b)
rw_unlock(true, b);
- b = mca_cannibalize(c, k, level, cl);
+ b = mca_cannibalize(c, k);
if (!IS_ERR(b))
goto out;
@@ -903,17 +951,15 @@ err:
* bch_btree_node_get - find a btree node in the cache and lock it, reading it
* in from disk if necessary.
*
- * If IO is necessary, it uses the closure embedded in struct btree_op to wait;
- * if that closure is in non blocking mode, will return -EAGAIN.
+ * If IO is necessary and running under generic_make_request, returns -EAGAIN.
*
* The btree node will have either a read or a write lock held, depending on
* level and op->lock.
*/
struct btree *bch_btree_node_get(struct cache_set *c, struct bkey *k,
- int level, struct btree_op *op)
+ int level, bool write)
{
int i = 0;
- bool write = level <= op->lock;
struct btree *b;
BUG_ON(level < 0);
@@ -925,7 +971,7 @@ retry:
return ERR_PTR(-EAGAIN);
mutex_lock(&c->bucket_lock);
- b = mca_alloc(c, k, level, &op->cl);
+ b = mca_alloc(c, k, level);
mutex_unlock(&c->bucket_lock);
if (!b)
@@ -971,7 +1017,7 @@ static void btree_node_prefetch(struct cache_set *c, struct bkey *k, int level)
struct btree *b;
mutex_lock(&c->bucket_lock);
- b = mca_alloc(c, k, level, NULL);
+ b = mca_alloc(c, k, level);
mutex_unlock(&c->bucket_lock);
if (!IS_ERR_OR_NULL(b)) {
@@ -982,17 +1028,12 @@ static void btree_node_prefetch(struct cache_set *c, struct bkey *k, int level)
/* Btree alloc */
-static void btree_node_free(struct btree *b, struct btree_op *op)
+static void btree_node_free(struct btree *b)
{
unsigned i;
trace_bcache_btree_node_free(b);
- /*
- * The BUG_ON() in btree_node_get() implies that we must have a write
- * lock on parent to free or even invalidate a node
- */
- BUG_ON(op->lock <= b->level);
BUG_ON(b == b->c->root);
if (btree_node_dirty(b))
@@ -1015,27 +1056,26 @@ static void btree_node_free(struct btree *b, struct btree_op *op)
mutex_unlock(&b->c->bucket_lock);
}
-struct btree *bch_btree_node_alloc(struct cache_set *c, int level,
- struct closure *cl)
+struct btree *bch_btree_node_alloc(struct cache_set *c, int level, bool wait)
{
BKEY_PADDED(key) k;
struct btree *b = ERR_PTR(-EAGAIN);
mutex_lock(&c->bucket_lock);
retry:
- if (__bch_bucket_alloc_set(c, WATERMARK_METADATA, &k.key, 1, cl))
+ if (__bch_bucket_alloc_set(c, WATERMARK_METADATA, &k.key, 1, wait))
goto err;
+ bkey_put(c, &k.key);
SET_KEY_SIZE(&k.key, c->btree_pages * PAGE_SECTORS);
- b = mca_alloc(c, &k.key, level, cl);
+ b = mca_alloc(c, &k.key, level);
if (IS_ERR(b))
goto err_free;
if (!b) {
cache_bug(c,
"Tried to allocate bucket that was in btree cache");
- __bkey_put(c, &k.key);
goto retry;
}
@@ -1048,7 +1088,6 @@ retry:
return b;
err_free:
bch_bucket_free(c, &k.key);
- __bkey_put(c, &k.key);
err:
mutex_unlock(&c->bucket_lock);
@@ -1056,16 +1095,31 @@ err:
return b;
}
-static struct btree *btree_node_alloc_replacement(struct btree *b,
- struct closure *cl)
+static struct btree *btree_node_alloc_replacement(struct btree *b, bool wait)
{
- struct btree *n = bch_btree_node_alloc(b->c, b->level, cl);
+ struct btree *n = bch_btree_node_alloc(b->c, b->level, wait);
if (!IS_ERR_OR_NULL(n))
bch_btree_sort_into(b, n);
return n;
}
+static void make_btree_freeing_key(struct btree *b, struct bkey *k)
+{
+ unsigned i;
+
+ bkey_copy(k, &b->key);
+ bkey_copy_key(k, &ZERO_KEY);
+
+ for (i = 0; i < KEY_PTRS(k); i++) {
+ uint8_t g = PTR_BUCKET(b->c, k, i)->gen + 1;
+
+ SET_PTR_GEN(k, i, g);
+ }
+
+ atomic_inc(&b->c->prio_blocked);
+}
+
/* Garbage collection */
uint8_t __bch_btree_mark_key(struct cache_set *c, int level, struct bkey *k)
@@ -1119,12 +1173,10 @@ uint8_t __bch_btree_mark_key(struct cache_set *c, int level, struct bkey *k)
#define btree_mark_key(b, k) __bch_btree_mark_key(b->c, b->level, k)
-static int btree_gc_mark_node(struct btree *b, unsigned *keys,
- struct gc_stat *gc)
+static bool btree_gc_mark_node(struct btree *b, struct gc_stat *gc)
{
uint8_t stale = 0;
- unsigned last_dev = -1;
- struct bcache_device *d = NULL;
+ unsigned keys = 0, good_keys = 0;
struct bkey *k;
struct btree_iter iter;
struct bset_tree *t;
@@ -1132,27 +1184,17 @@ static int btree_gc_mark_node(struct btree *b, unsigned *keys,
gc->nodes++;
for_each_key_filter(b, k, &iter, bch_ptr_invalid) {
- if (last_dev != KEY_INODE(k)) {
- last_dev = KEY_INODE(k);
-
- d = KEY_INODE(k) < b->c->nr_uuids
- ? b->c->devices[last_dev]
- : NULL;
- }
-
stale = max(stale, btree_mark_key(b, k));
+ keys++;
if (bch_ptr_bad(b, k))
continue;
- *keys += bkey_u64s(k);
-
gc->key_bytes += bkey_u64s(k);
gc->nkeys++;
+ good_keys++;
gc->data += KEY_SIZE(k);
- if (KEY_DIRTY(k))
- gc->dirty += KEY_SIZE(k);
}
for (t = b->sets; t <= &b->sets[b->nsets]; t++)
@@ -1161,78 +1203,74 @@ static int btree_gc_mark_node(struct btree *b, unsigned *keys,
bkey_cmp(&b->key, &t->end) < 0,
b, "found short btree key in gc");
- return stale;
-}
-
-static struct btree *btree_gc_alloc(struct btree *b, struct bkey *k,
- struct btree_op *op)
-{
- /*
- * We block priorities from being written for the duration of garbage
- * collection, so we can't sleep in btree_alloc() ->
- * bch_bucket_alloc_set(), or we'd risk deadlock - so we don't pass it
- * our closure.
- */
- struct btree *n = btree_node_alloc_replacement(b, NULL);
+ if (b->c->gc_always_rewrite)
+ return true;
- if (!IS_ERR_OR_NULL(n)) {
- swap(b, n);
- __bkey_put(b->c, &b->key);
+ if (stale > 10)
+ return true;
- memcpy(k->ptr, b->key.ptr,
- sizeof(uint64_t) * KEY_PTRS(&b->key));
+ if ((keys - good_keys) * 2 > keys)
+ return true;
- btree_node_free(n, op);
- up_write(&n->lock);
- }
-
- return b;
+ return false;
}
-/*
- * Leaving this at 2 until we've got incremental garbage collection done; it
- * could be higher (and has been tested with 4) except that garbage collection
- * could take much longer, adversely affecting latency.
- */
-#define GC_MERGE_NODES 2U
+#define GC_MERGE_NODES 4U
struct gc_merge_info {
struct btree *b;
- struct bkey *k;
unsigned keys;
};
-static void btree_gc_coalesce(struct btree *b, struct btree_op *op,
- struct gc_stat *gc, struct gc_merge_info *r)
+static int bch_btree_insert_node(struct btree *, struct btree_op *,
+ struct keylist *, atomic_t *, struct bkey *);
+
+static int btree_gc_coalesce(struct btree *b, struct btree_op *op,
+ struct keylist *keylist, struct gc_stat *gc,
+ struct gc_merge_info *r)
{
- unsigned nodes = 0, keys = 0, blocks;
- int i;
+ unsigned i, nodes = 0, keys = 0, blocks;
+ struct btree *new_nodes[GC_MERGE_NODES];
+ struct closure cl;
+ struct bkey *k;
- while (nodes < GC_MERGE_NODES && r[nodes].b)
+ memset(new_nodes, 0, sizeof(new_nodes));
+ closure_init_stack(&cl);
+
+ while (nodes < GC_MERGE_NODES && !IS_ERR_OR_NULL(r[nodes].b))
keys += r[nodes++].keys;
blocks = btree_default_blocks(b->c) * 2 / 3;
if (nodes < 2 ||
__set_blocks(b->sets[0].data, keys, b->c) > blocks * (nodes - 1))
- return;
-
- for (i = nodes - 1; i >= 0; --i) {
- if (r[i].b->written)
- r[i].b = btree_gc_alloc(r[i].b, r[i].k, op);
+ return 0;
- if (r[i].b->written)
- return;
+ for (i = 0; i < nodes; i++) {
+ new_nodes[i] = btree_node_alloc_replacement(r[i].b, false);
+ if (IS_ERR_OR_NULL(new_nodes[i]))
+ goto out_nocoalesce;
}
for (i = nodes - 1; i > 0; --i) {
- struct bset *n1 = r[i].b->sets->data;
- struct bset *n2 = r[i - 1].b->sets->data;
+ struct bset *n1 = new_nodes[i]->sets->data;
+ struct bset *n2 = new_nodes[i - 1]->sets->data;
struct bkey *k, *last = NULL;
keys = 0;
- if (i == 1) {
+ if (i > 1) {
+ for (k = n2->start;
+ k < end(n2);
+ k = bkey_next(k)) {
+ if (__set_blocks(n1, n1->keys + keys +
+ bkey_u64s(k), b->c) > blocks)
+ break;
+
+ last = k;
+ keys += bkey_u64s(k);
+ }
+ } else {
/*
* Last node we're not getting rid of - we're getting
* rid of the node at r[0]. Have to try and fit all of
@@ -1241,37 +1279,27 @@ static void btree_gc_coalesce(struct btree *b, struct btree_op *op,
* length keys (shouldn't be possible in practice,
* though)
*/
- if (__set_blocks(n1, n1->keys + r->keys,
- b->c) > btree_blocks(r[i].b))
- return;
+ if (__set_blocks(n1, n1->keys + n2->keys,
+ b->c) > btree_blocks(new_nodes[i]))
+ goto out_nocoalesce;
keys = n2->keys;
+ /* Take the key of the node we're getting rid of */
last = &r->b->key;
- } else
- for (k = n2->start;
- k < end(n2);
- k = bkey_next(k)) {
- if (__set_blocks(n1, n1->keys + keys +
- bkey_u64s(k), b->c) > blocks)
- break;
-
- last = k;
- keys += bkey_u64s(k);
- }
+ }
BUG_ON(__set_blocks(n1, n1->keys + keys,
- b->c) > btree_blocks(r[i].b));
+ b->c) > btree_blocks(new_nodes[i]));
- if (last) {
- bkey_copy_key(&r[i].b->key, last);
- bkey_copy_key(r[i].k, last);
- }
+ if (last)
+ bkey_copy_key(&new_nodes[i]->key, last);
memcpy(end(n1),
n2->start,
(void *) node(n2, keys) - (void *) n2->start);
n1->keys += keys;
+ r[i].keys = n1->keys;
memmove(n2->start,
node(n2, keys),
@@ -1279,95 +1307,176 @@ static void btree_gc_coalesce(struct btree *b, struct btree_op *op,
n2->keys -= keys;
- r[i].keys = n1->keys;
- r[i - 1].keys = n2->keys;
+ if (bch_keylist_realloc(keylist,
+ KEY_PTRS(&new_nodes[i]->key), b->c))
+ goto out_nocoalesce;
+
+ bch_btree_node_write(new_nodes[i], &cl);
+ bch_keylist_add(keylist, &new_nodes[i]->key);
}
- btree_node_free(r->b, op);
- up_write(&r->b->lock);
+ for (i = 0; i < nodes; i++) {
+ if (bch_keylist_realloc(keylist, KEY_PTRS(&r[i].b->key), b->c))
+ goto out_nocoalesce;
- trace_bcache_btree_gc_coalesce(nodes);
+ make_btree_freeing_key(r[i].b, keylist->top);
+ bch_keylist_push(keylist);
+ }
+
+ /* We emptied out this node */
+ BUG_ON(new_nodes[0]->sets->data->keys);
+ btree_node_free(new_nodes[0]);
+ rw_unlock(true, new_nodes[0]);
+
+ closure_sync(&cl);
+
+ for (i = 0; i < nodes; i++) {
+ btree_node_free(r[i].b);
+ rw_unlock(true, r[i].b);
+
+ r[i].b = new_nodes[i];
+ }
+
+ bch_btree_insert_node(b, op, keylist, NULL, NULL);
+ BUG_ON(!bch_keylist_empty(keylist));
+ memmove(r, r + 1, sizeof(r[0]) * (nodes - 1));
+ r[nodes - 1].b = ERR_PTR(-EINTR);
+
+ trace_bcache_btree_gc_coalesce(nodes);
gc->nodes--;
- nodes--;
- memmove(&r[0], &r[1], sizeof(struct gc_merge_info) * nodes);
- memset(&r[nodes], 0, sizeof(struct gc_merge_info));
+ /* Invalidated our iterator */
+ return -EINTR;
+
+out_nocoalesce:
+ closure_sync(&cl);
+
+ while ((k = bch_keylist_pop(keylist)))
+ if (!bkey_cmp(k, &ZERO_KEY))
+ atomic_dec(&b->c->prio_blocked);
+
+ for (i = 0; i < nodes; i++)
+ if (!IS_ERR_OR_NULL(new_nodes[i])) {
+ btree_node_free(new_nodes[i]);
+ rw_unlock(true, new_nodes[i]);
+ }
+ return 0;
}
-static int btree_gc_recurse(struct btree *b, struct btree_op *op,
- struct closure *writes, struct gc_stat *gc)
+static unsigned btree_gc_count_keys(struct btree *b)
{
- void write(struct btree *r)
- {
- if (!r->written)
- bch_btree_node_write(r, &op->cl);
- else if (btree_node_dirty(r))
- bch_btree_node_write(r, writes);
+ struct bkey *k;
+ struct btree_iter iter;
+ unsigned ret = 0;
- up_write(&r->lock);
- }
+ for_each_key_filter(b, k, &iter, bch_ptr_bad)
+ ret += bkey_u64s(k);
+
+ return ret;
+}
- int ret = 0, stale;
+static int btree_gc_recurse(struct btree *b, struct btree_op *op,
+ struct closure *writes, struct gc_stat *gc)
+{
unsigned i;
+ int ret = 0;
+ bool should_rewrite;
+ struct btree *n;
+ struct bkey *k;
+ struct keylist keys;
+ struct btree_iter iter;
struct gc_merge_info r[GC_MERGE_NODES];
+ struct gc_merge_info *last = r + GC_MERGE_NODES - 1;
- memset(r, 0, sizeof(r));
+ bch_keylist_init(&keys);
+ bch_btree_iter_init(b, &iter, &b->c->gc_done);
- while ((r->k = bch_next_recurse_key(b, &b->c->gc_done))) {
- r->b = bch_btree_node_get(b->c, r->k, b->level - 1, op);
+ for (i = 0; i < GC_MERGE_NODES; i++)
+ r[i].b = ERR_PTR(-EINTR);
- if (IS_ERR(r->b)) {
- ret = PTR_ERR(r->b);
- break;
+ while (1) {
+ k = bch_btree_iter_next_filter(&iter, b, bch_ptr_bad);
+ if (k) {
+ r->b = bch_btree_node_get(b->c, k, b->level - 1, true);
+ if (IS_ERR(r->b)) {
+ ret = PTR_ERR(r->b);
+ break;
+ }
+
+ r->keys = btree_gc_count_keys(r->b);
+
+ ret = btree_gc_coalesce(b, op, &keys, gc, r);
+ if (ret)
+ break;
}
- r->keys = 0;
- stale = btree_gc_mark_node(r->b, &r->keys, gc);
+ if (!last->b)
+ break;
- if (!b->written &&
- (r->b->level || stale > 10 ||
- b->c->gc_always_rewrite))
- r->b = btree_gc_alloc(r->b, r->k, op);
+ if (!IS_ERR(last->b)) {
+ should_rewrite = btree_gc_mark_node(last->b, gc);
+ if (should_rewrite) {
+ n = btree_node_alloc_replacement(last->b,
+ false);
- if (r->b->level)
- ret = btree_gc_recurse(r->b, op, writes, gc);
+ if (!IS_ERR_OR_NULL(n)) {
+ bch_btree_node_write_sync(n);
+ bch_keylist_add(&keys, &n->key);
- if (ret) {
- write(r->b);
- break;
- }
+ make_btree_freeing_key(last->b,
+ keys.top);
+ bch_keylist_push(&keys);
- bkey_copy_key(&b->c->gc_done, r->k);
+ btree_node_free(last->b);
- if (!b->written)
- btree_gc_coalesce(b, op, gc, r);
+ bch_btree_insert_node(b, op, &keys,
+ NULL, NULL);
+ BUG_ON(!bch_keylist_empty(&keys));
- if (r[GC_MERGE_NODES - 1].b)
- write(r[GC_MERGE_NODES - 1].b);
+ rw_unlock(true, last->b);
+ last->b = n;
- memmove(&r[1], &r[0],
- sizeof(struct gc_merge_info) * (GC_MERGE_NODES - 1));
+ /* Invalidated our iterator */
+ ret = -EINTR;
+ break;
+ }
+ }
+
+ if (last->b->level) {
+ ret = btree_gc_recurse(last->b, op, writes, gc);
+ if (ret)
+ break;
+ }
+
+ bkey_copy_key(&b->c->gc_done, &last->b->key);
+
+ /*
+ * Must flush leaf nodes before gc ends, since replace
+ * operations aren't journalled
+ */
+ if (btree_node_dirty(last->b))
+ bch_btree_node_write(last->b, writes);
+ rw_unlock(true, last->b);
+ }
+
+ memmove(r + 1, r, sizeof(r[0]) * (GC_MERGE_NODES - 1));
+ r->b = NULL;
- /* When we've got incremental GC working, we'll want to do
- * if (should_resched())
- * return -EAGAIN;
- */
- cond_resched();
-#if 0
if (need_resched()) {
ret = -EAGAIN;
break;
}
-#endif
}
- for (i = 1; i < GC_MERGE_NODES && r[i].b; i++)
- write(r[i].b);
+ for (i = 0; i < GC_MERGE_NODES; i++)
+ if (!IS_ERR_OR_NULL(r[i].b)) {
+ if (btree_node_dirty(r[i].b))
+ bch_btree_node_write(r[i].b, writes);
+ rw_unlock(true, r[i].b);
+ }
- /* Might have freed some children, must remove their keys */
- if (!b->written)
- bch_btree_sort(b);
+ bch_keylist_free(&keys);
return ret;
}
@@ -1376,29 +1485,31 @@ static int bch_btree_gc_root(struct btree *b, struct btree_op *op,
struct closure *writes, struct gc_stat *gc)
{
struct btree *n = NULL;
- unsigned keys = 0;
- int ret = 0, stale = btree_gc_mark_node(b, &keys, gc);
-
- if (b->level || stale > 10)
- n = btree_node_alloc_replacement(b, NULL);
+ int ret = 0;
+ bool should_rewrite;
- if (!IS_ERR_OR_NULL(n))
- swap(b, n);
+ should_rewrite = btree_gc_mark_node(b, gc);
+ if (should_rewrite) {
+ n = btree_node_alloc_replacement(b, false);
- if (b->level)
- ret = btree_gc_recurse(b, op, writes, gc);
+ if (!IS_ERR_OR_NULL(n)) {
+ bch_btree_node_write_sync(n);
+ bch_btree_set_root(n);
+ btree_node_free(b);
+ rw_unlock(true, n);
- if (!b->written || btree_node_dirty(b)) {
- bch_btree_node_write(b, n ? &op->cl : NULL);
+ return -EINTR;
+ }
}
- if (!IS_ERR_OR_NULL(n)) {
- closure_sync(&op->cl);
- bch_btree_set_root(b);
- btree_node_free(n, op);
- rw_unlock(true, b);
+ if (b->level) {
+ ret = btree_gc_recurse(b, op, writes, gc);
+ if (ret)
+ return ret;
}
+ bkey_copy_key(&b->c->gc_done, &b->key);
+
return ret;
}
@@ -1479,9 +1590,8 @@ size_t bch_btree_gc_finish(struct cache_set *c)
return available;
}
-static void bch_btree_gc(struct closure *cl)
+static void bch_btree_gc(struct cache_set *c)
{
- struct cache_set *c = container_of(cl, struct cache_set, gc.cl);
int ret;
unsigned long available;
struct gc_stat stats;
@@ -1493,47 +1603,73 @@ static void bch_btree_gc(struct closure *cl)
memset(&stats, 0, sizeof(struct gc_stat));
closure_init_stack(&writes);
- bch_btree_op_init_stack(&op);
- op.lock = SHRT_MAX;
+ bch_btree_op_init(&op, SHRT_MAX);
btree_gc_start(c);
- atomic_inc(&c->prio_blocked);
-
- ret = btree_root(gc_root, c, &op, &writes, &stats);
- closure_sync(&op.cl);
- closure_sync(&writes);
-
- if (ret) {
- pr_warn("gc failed!");
- continue_at(cl, bch_btree_gc, bch_gc_wq);
- }
+ do {
+ ret = btree_root(gc_root, c, &op, &writes, &stats);
+ closure_sync(&writes);
- /* Possibly wait for new UUIDs or whatever to hit disk */
- bch_journal_meta(c, &op.cl);
- closure_sync(&op.cl);
+ if (ret && ret != -EAGAIN)
+ pr_warn("gc failed!");
+ } while (ret);
available = bch_btree_gc_finish(c);
-
- atomic_dec(&c->prio_blocked);
wake_up_allocators(c);
bch_time_stats_update(&c->btree_gc_time, start_time);
stats.key_bytes *= sizeof(uint64_t);
- stats.dirty <<= 9;
stats.data <<= 9;
stats.in_use = (c->nbuckets - available) * 100 / c->nbuckets;
memcpy(&c->gc_stats, &stats, sizeof(struct gc_stat));
trace_bcache_gc_end(c);
- continue_at(cl, bch_moving_gc, bch_gc_wq);
+ bch_moving_gc(c);
+}
+
+static int bch_gc_thread(void *arg)
+{
+ struct cache_set *c = arg;
+ struct cache *ca;
+ unsigned i;
+
+ while (1) {
+again:
+ bch_btree_gc(c);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (kthread_should_stop())
+ break;
+
+ mutex_lock(&c->bucket_lock);
+
+ for_each_cache(ca, c, i)
+ if (ca->invalidate_needs_gc) {
+ mutex_unlock(&c->bucket_lock);
+ set_current_state(TASK_RUNNING);
+ goto again;
+ }
+
+ mutex_unlock(&c->bucket_lock);
+
+ try_to_freeze();
+ schedule();
+ }
+
+ return 0;
}
-void bch_queue_gc(struct cache_set *c)
+int bch_gc_thread_start(struct cache_set *c)
{
- closure_trylock_call(&c->gc.cl, bch_btree_gc, bch_gc_wq, &c->cl);
+ c->gc_thread = kthread_create(bch_gc_thread, c, "bcache_gc");
+ if (IS_ERR(c->gc_thread))
+ return PTR_ERR(c->gc_thread);
+
+ set_task_state(c->gc_thread, TASK_INTERRUPTIBLE);
+ return 0;
}
/* Initial partial gc */
@@ -1541,9 +1677,9 @@ void bch_queue_gc(struct cache_set *c)
static int bch_btree_check_recurse(struct btree *b, struct btree_op *op,
unsigned long **seen)
{
- int ret;
+ int ret = 0;
unsigned i;
- struct bkey *k;
+ struct bkey *k, *p = NULL;
struct bucket *g;
struct btree_iter iter;
@@ -1570,31 +1706,32 @@ static int bch_btree_check_recurse(struct btree *b, struct btree_op *op,
}
if (b->level) {
- k = bch_next_recurse_key(b, &ZERO_KEY);
+ bch_btree_iter_init(b, &iter, NULL);
- while (k) {
- struct bkey *p = bch_next_recurse_key(b, k);
- if (p)
- btree_node_prefetch(b->c, p, b->level - 1);
+ do {
+ k = bch_btree_iter_next_filter(&iter, b, bch_ptr_bad);
+ if (k)
+ btree_node_prefetch(b->c, k, b->level - 1);
- ret = btree(check_recurse, k, b, op, seen);
- if (ret)
- return ret;
+ if (p)
+ ret = btree(check_recurse, p, b, op, seen);
- k = p;
- }
+ p = k;
+ } while (p && !ret);
}
return 0;
}
-int bch_btree_check(struct cache_set *c, struct btree_op *op)
+int bch_btree_check(struct cache_set *c)
{
int ret = -ENOMEM;
unsigned i;
unsigned long *seen[MAX_CACHES_PER_SET];
+ struct btree_op op;
memset(seen, 0, sizeof(seen));
+ bch_btree_op_init(&op, SHRT_MAX);
for (i = 0; c->cache[i]; i++) {
size_t n = DIV_ROUND_UP(c->cache[i]->sb.nbuckets, 8);
@@ -1606,7 +1743,7 @@ int bch_btree_check(struct cache_set *c, struct btree_op *op)
memset(seen[i], 0xFF, n);
}
- ret = btree_root(check_recurse, c, op, seen);
+ ret = btree_root(check_recurse, c, &op, seen);
err:
for (i = 0; i < MAX_CACHES_PER_SET; i++)
kfree(seen[i]);
@@ -1628,10 +1765,9 @@ static void shift_keys(struct btree *b, struct bkey *where, struct bkey *insert)
bch_bset_fix_lookup_table(b, where);
}
-static bool fix_overlapping_extents(struct btree *b,
- struct bkey *insert,
+static bool fix_overlapping_extents(struct btree *b, struct bkey *insert,
struct btree_iter *iter,
- struct btree_op *op)
+ struct bkey *replace_key)
{
void subtract_dirty(struct bkey *k, uint64_t offset, int sectors)
{
@@ -1659,39 +1795,38 @@ static bool fix_overlapping_extents(struct btree *b,
* We might overlap with 0 size extents; we can't skip these
* because if they're in the set we're inserting to we have to
* adjust them so they don't overlap with the key we're
- * inserting. But we don't want to check them for BTREE_REPLACE
+ * inserting. But we don't want to check them for replace
* operations.
*/
- if (op->type == BTREE_REPLACE &&
- KEY_SIZE(k)) {
+ if (replace_key && KEY_SIZE(k)) {
/*
* k might have been split since we inserted/found the
* key we're replacing
*/
unsigned i;
uint64_t offset = KEY_START(k) -
- KEY_START(&op->replace);
+ KEY_START(replace_key);
/* But it must be a subset of the replace key */
- if (KEY_START(k) < KEY_START(&op->replace) ||
- KEY_OFFSET(k) > KEY_OFFSET(&op->replace))
+ if (KEY_START(k) < KEY_START(replace_key) ||
+ KEY_OFFSET(k) > KEY_OFFSET(replace_key))
goto check_failed;
/* We didn't find a key that we were supposed to */
if (KEY_START(k) > KEY_START(insert) + sectors_found)
goto check_failed;
- if (KEY_PTRS(&op->replace) != KEY_PTRS(k))
+ if (KEY_PTRS(replace_key) != KEY_PTRS(k))
goto check_failed;
/* skip past gen */
offset <<= 8;
- BUG_ON(!KEY_PTRS(&op->replace));
+ BUG_ON(!KEY_PTRS(replace_key));
- for (i = 0; i < KEY_PTRS(&op->replace); i++)
- if (k->ptr[i] != op->replace.ptr[i] + offset)
+ for (i = 0; i < KEY_PTRS(replace_key); i++)
+ if (k->ptr[i] != replace_key->ptr[i] + offset)
goto check_failed;
sectors_found = KEY_OFFSET(k) - KEY_START(insert);
@@ -1759,9 +1894,8 @@ static bool fix_overlapping_extents(struct btree *b,
}
check_failed:
- if (op->type == BTREE_REPLACE) {
+ if (replace_key) {
if (!sectors_found) {
- op->insert_collision = true;
return true;
} else if (sectors_found < KEY_SIZE(insert)) {
SET_KEY_OFFSET(insert, KEY_OFFSET(insert) -
@@ -1774,7 +1908,7 @@ check_failed:
}
static bool btree_insert_key(struct btree *b, struct btree_op *op,
- struct bkey *k)
+ struct bkey *k, struct bkey *replace_key)
{
struct bset *i = b->sets[b->nsets].data;
struct bkey *m, *prev;
@@ -1786,22 +1920,19 @@ static bool btree_insert_key(struct btree *b, struct btree_op *op,
if (!b->level) {
struct btree_iter iter;
- struct bkey search = KEY(KEY_INODE(k), KEY_START(k), 0);
/*
* bset_search() returns the first key that is strictly greater
* than the search key - but for back merging, we want to find
- * the first key that is greater than or equal to KEY_START(k) -
- * unless KEY_START(k) is 0.
+ * the previous key.
*/
- if (KEY_OFFSET(&search))
- SET_KEY_OFFSET(&search, KEY_OFFSET(&search) - 1);
-
prev = NULL;
- m = bch_btree_iter_init(b, &iter, &search);
+ m = bch_btree_iter_init(b, &iter, PRECEDING_KEY(&START_KEY(k)));
- if (fix_overlapping_extents(b, k, &iter, op))
+ if (fix_overlapping_extents(b, k, &iter, replace_key)) {
+ op->insert_collision = true;
return false;
+ }
while (m != end(i) &&
bkey_cmp(k, &START_KEY(m)) > 0)
@@ -1825,8 +1956,10 @@ static bool btree_insert_key(struct btree *b, struct btree_op *op,
if (m != end(i) &&
bch_bkey_try_merge(b, k, m))
goto copy;
- } else
+ } else {
+ BUG_ON(replace_key);
m = bch_bset_search(b, &b->sets[b->nsets], k);
+ }
insert: shift_keys(b, m, k);
copy: bkey_copy(m, k);
@@ -1835,74 +1968,72 @@ merged:
bcache_dev_sectors_dirty_add(b->c, KEY_INODE(k),
KEY_START(k), KEY_SIZE(k));
- bch_check_keys(b, "%u for %s", status, op_type(op));
+ bch_check_keys(b, "%u for %s", status,
+ replace_key ? "replace" : "insert");
if (b->level && !KEY_OFFSET(k))
btree_current_write(b)->prio_blocked++;
- trace_bcache_btree_insert_key(b, k, op->type, status);
+ trace_bcache_btree_insert_key(b, k, replace_key != NULL, status);
return true;
}
-static bool bch_btree_insert_keys(struct btree *b, struct btree_op *op)
+static bool bch_btree_insert_keys(struct btree *b, struct btree_op *op,
+ struct keylist *insert_keys,
+ struct bkey *replace_key)
{
bool ret = false;
- struct bkey *k;
- unsigned oldsize = bch_count_data(b);
+ int oldsize = bch_count_data(b);
- while ((k = bch_keylist_pop(&op->keys))) {
- bkey_put(b->c, k, b->level);
- ret |= btree_insert_key(b, op, k);
- }
+ while (!bch_keylist_empty(insert_keys)) {
+ struct bset *i = write_block(b);
+ struct bkey *k = insert_keys->keys;
- BUG_ON(bch_count_data(b) < oldsize);
- return ret;
-}
-
-bool bch_btree_insert_check_key(struct btree *b, struct btree_op *op,
- struct bio *bio)
-{
- bool ret = false;
- uint64_t btree_ptr = b->key.ptr[0];
- unsigned long seq = b->seq;
- BKEY_PADDED(k) tmp;
-
- rw_unlock(false, b);
- rw_lock(true, b, b->level);
+ if (b->written + __set_blocks(i, i->keys + bkey_u64s(k), b->c)
+ > btree_blocks(b))
+ break;
- if (b->key.ptr[0] != btree_ptr ||
- b->seq != seq + 1 ||
- should_split(b))
- goto out;
+ if (bkey_cmp(k, &b->key) <= 0) {
+ if (!b->level)
+ bkey_put(b->c, k);
- op->replace = KEY(op->inode, bio_end_sector(bio), bio_sectors(bio));
+ ret |= btree_insert_key(b, op, k, replace_key);
+ bch_keylist_pop_front(insert_keys);
+ } else if (bkey_cmp(&START_KEY(k), &b->key) < 0) {
+ BKEY_PADDED(key) temp;
+ bkey_copy(&temp.key, insert_keys->keys);
- SET_KEY_PTRS(&op->replace, 1);
- get_random_bytes(&op->replace.ptr[0], sizeof(uint64_t));
+ bch_cut_back(&b->key, &temp.key);
+ bch_cut_front(&b->key, insert_keys->keys);
- SET_PTR_DEV(&op->replace, 0, PTR_CHECK_DEV);
+ ret |= btree_insert_key(b, op, &temp.key, replace_key);
+ break;
+ } else {
+ break;
+ }
+ }
- bkey_copy(&tmp.k, &op->replace);
+ BUG_ON(!bch_keylist_empty(insert_keys) && b->level);
- BUG_ON(op->type != BTREE_INSERT);
- BUG_ON(!btree_insert_key(b, op, &tmp.k));
- ret = true;
-out:
- downgrade_write(&b->lock);
+ BUG_ON(bch_count_data(b) < oldsize);
return ret;
}
-static int btree_split(struct btree *b, struct btree_op *op)
+static int btree_split(struct btree *b, struct btree_op *op,
+ struct keylist *insert_keys,
+ struct bkey *replace_key)
{
- bool split, root = b == b->c->root;
+ bool split;
struct btree *n1, *n2 = NULL, *n3 = NULL;
uint64_t start_time = local_clock();
+ struct closure cl;
+ struct keylist parent_keys;
- if (b->level)
- set_closure_blocking(&op->cl);
+ closure_init_stack(&cl);
+ bch_keylist_init(&parent_keys);
- n1 = btree_node_alloc_replacement(b, &op->cl);
+ n1 = btree_node_alloc_replacement(b, true);
if (IS_ERR(n1))
goto err;
@@ -1913,19 +2044,20 @@ static int btree_split(struct btree *b, struct btree_op *op)
trace_bcache_btree_node_split(b, n1->sets[0].data->keys);
- n2 = bch_btree_node_alloc(b->c, b->level, &op->cl);
+ n2 = bch_btree_node_alloc(b->c, b->level, true);
if (IS_ERR(n2))
goto err_free1;
- if (root) {
- n3 = bch_btree_node_alloc(b->c, b->level + 1, &op->cl);
+ if (!b->parent) {
+ n3 = bch_btree_node_alloc(b->c, b->level + 1, true);
if (IS_ERR(n3))
goto err_free2;
}
- bch_btree_insert_keys(n1, op);
+ bch_btree_insert_keys(n1, op, insert_keys, replace_key);
- /* Has to be a linear search because we don't have an auxiliary
+ /*
+ * Has to be a linear search because we don't have an auxiliary
* search tree yet
*/
@@ -1944,60 +2076,57 @@ static int btree_split(struct btree *b, struct btree_op *op)
bkey_copy_key(&n2->key, &b->key);
- bch_keylist_add(&op->keys, &n2->key);
- bch_btree_node_write(n2, &op->cl);
+ bch_keylist_add(&parent_keys, &n2->key);
+ bch_btree_node_write(n2, &cl);
rw_unlock(true, n2);
} else {
trace_bcache_btree_node_compact(b, n1->sets[0].data->keys);
- bch_btree_insert_keys(n1, op);
+ bch_btree_insert_keys(n1, op, insert_keys, replace_key);
}
- bch_keylist_add(&op->keys, &n1->key);
- bch_btree_node_write(n1, &op->cl);
+ bch_keylist_add(&parent_keys, &n1->key);
+ bch_btree_node_write(n1, &cl);
if (n3) {
+ /* Depth increases, make a new root */
bkey_copy_key(&n3->key, &MAX_KEY);
- bch_btree_insert_keys(n3, op);
- bch_btree_node_write(n3, &op->cl);
+ bch_btree_insert_keys(n3, op, &parent_keys, NULL);
+ bch_btree_node_write(n3, &cl);
- closure_sync(&op->cl);
+ closure_sync(&cl);
bch_btree_set_root(n3);
rw_unlock(true, n3);
- } else if (root) {
- op->keys.top = op->keys.bottom;
- closure_sync(&op->cl);
+
+ btree_node_free(b);
+ } else if (!b->parent) {
+ /* Root filled up but didn't need to be split */
+ closure_sync(&cl);
bch_btree_set_root(n1);
- } else {
- unsigned i;
- bkey_copy(op->keys.top, &b->key);
- bkey_copy_key(op->keys.top, &ZERO_KEY);
+ btree_node_free(b);
+ } else {
+ /* Split a non root node */
+ closure_sync(&cl);
+ make_btree_freeing_key(b, parent_keys.top);
+ bch_keylist_push(&parent_keys);
- for (i = 0; i < KEY_PTRS(&b->key); i++) {
- uint8_t g = PTR_BUCKET(b->c, &b->key, i)->gen + 1;
+ btree_node_free(b);
- SET_PTR_GEN(op->keys.top, i, g);
- }
-
- bch_keylist_push(&op->keys);
- closure_sync(&op->cl);
- atomic_inc(&b->c->prio_blocked);
+ bch_btree_insert_node(b->parent, op, &parent_keys, NULL, NULL);
+ BUG_ON(!bch_keylist_empty(&parent_keys));
}
rw_unlock(true, n1);
- btree_node_free(b, op);
bch_time_stats_update(&b->c->btree_split_time, start_time);
return 0;
err_free2:
- __bkey_put(n2->c, &n2->key);
- btree_node_free(n2, op);
+ btree_node_free(n2);
rw_unlock(true, n2);
err_free1:
- __bkey_put(n1->c, &n1->key);
- btree_node_free(n1, op);
+ btree_node_free(n1);
rw_unlock(true, n1);
err:
if (n3 == ERR_PTR(-EAGAIN) ||
@@ -2009,116 +2138,126 @@ err:
return -ENOMEM;
}
-static int bch_btree_insert_recurse(struct btree *b, struct btree_op *op,
- struct keylist *stack_keys)
+static int bch_btree_insert_node(struct btree *b, struct btree_op *op,
+ struct keylist *insert_keys,
+ atomic_t *journal_ref,
+ struct bkey *replace_key)
{
- if (b->level) {
- int ret;
- struct bkey *insert = op->keys.bottom;
- struct bkey *k = bch_next_recurse_key(b, &START_KEY(insert));
-
- if (!k) {
- btree_bug(b, "no key to recurse on at level %i/%i",
- b->level, b->c->root->level);
+ BUG_ON(b->level && replace_key);
- op->keys.top = op->keys.bottom;
- return -EIO;
+ if (should_split(b)) {
+ if (current->bio_list) {
+ op->lock = b->c->root->level + 1;
+ return -EAGAIN;
+ } else if (op->lock <= b->c->root->level) {
+ op->lock = b->c->root->level + 1;
+ return -EINTR;
+ } else {
+ /* Invalidated all iterators */
+ return btree_split(b, op, insert_keys, replace_key) ?:
+ -EINTR;
}
+ } else {
+ BUG_ON(write_block(b) != b->sets[b->nsets].data);
- if (bkey_cmp(insert, k) > 0) {
- unsigned i;
-
- if (op->type == BTREE_REPLACE) {
- __bkey_put(b->c, insert);
- op->keys.top = op->keys.bottom;
- op->insert_collision = true;
- return 0;
- }
+ if (bch_btree_insert_keys(b, op, insert_keys, replace_key)) {
+ if (!b->level)
+ bch_btree_leaf_dirty(b, journal_ref);
+ else
+ bch_btree_node_write_sync(b);
+ }
- for (i = 0; i < KEY_PTRS(insert); i++)
- atomic_inc(&PTR_BUCKET(b->c, insert, i)->pin);
+ return 0;
+ }
+}
- bkey_copy(stack_keys->top, insert);
+int bch_btree_insert_check_key(struct btree *b, struct btree_op *op,
+ struct bkey *check_key)
+{
+ int ret = -EINTR;
+ uint64_t btree_ptr = b->key.ptr[0];
+ unsigned long seq = b->seq;
+ struct keylist insert;
+ bool upgrade = op->lock == -1;
- bch_cut_back(k, insert);
- bch_cut_front(k, stack_keys->top);
+ bch_keylist_init(&insert);
- bch_keylist_push(stack_keys);
- }
+ if (upgrade) {
+ rw_unlock(false, b);
+ rw_lock(true, b, b->level);
- ret = btree(insert_recurse, k, b, op, stack_keys);
- if (ret)
- return ret;
+ if (b->key.ptr[0] != btree_ptr ||
+ b->seq != seq + 1)
+ goto out;
}
- if (!bch_keylist_empty(&op->keys)) {
- if (should_split(b)) {
- if (op->lock <= b->c->root->level) {
- BUG_ON(b->level);
- op->lock = b->c->root->level + 1;
- return -EINTR;
- }
- return btree_split(b, op);
- }
+ SET_KEY_PTRS(check_key, 1);
+ get_random_bytes(&check_key->ptr[0], sizeof(uint64_t));
- BUG_ON(write_block(b) != b->sets[b->nsets].data);
+ SET_PTR_DEV(check_key, 0, PTR_CHECK_DEV);
- if (bch_btree_insert_keys(b, op)) {
- if (!b->level)
- bch_btree_leaf_dirty(b, op);
- else
- bch_btree_node_write(b, &op->cl);
- }
- }
+ bch_keylist_add(&insert, check_key);
- return 0;
+ ret = bch_btree_insert_node(b, op, &insert, NULL, NULL);
+
+ BUG_ON(!ret && !bch_keylist_empty(&insert));
+out:
+ if (upgrade)
+ downgrade_write(&b->lock);
+ return ret;
}
-int bch_btree_insert(struct btree_op *op, struct cache_set *c)
+struct btree_insert_op {
+ struct btree_op op;
+ struct keylist *keys;
+ atomic_t *journal_ref;
+ struct bkey *replace_key;
+};
+
+int btree_insert_fn(struct btree_op *b_op, struct btree *b)
{
- int ret = 0;
- struct keylist stack_keys;
+ struct btree_insert_op *op = container_of(b_op,
+ struct btree_insert_op, op);
- /*
- * Don't want to block with the btree locked unless we have to,
- * otherwise we get deadlocks with try_harder and between split/gc
- */
- clear_closure_blocking(&op->cl);
-
- BUG_ON(bch_keylist_empty(&op->keys));
- bch_keylist_copy(&stack_keys, &op->keys);
- bch_keylist_init(&op->keys);
-
- while (!bch_keylist_empty(&stack_keys) ||
- !bch_keylist_empty(&op->keys)) {
- if (bch_keylist_empty(&op->keys)) {
- bch_keylist_add(&op->keys,
- bch_keylist_pop(&stack_keys));
- op->lock = 0;
- }
+ int ret = bch_btree_insert_node(b, &op->op, op->keys,
+ op->journal_ref, op->replace_key);
+ if (ret && !bch_keylist_empty(op->keys))
+ return ret;
+ else
+ return MAP_DONE;
+}
- ret = btree_root(insert_recurse, c, op, &stack_keys);
+int bch_btree_insert(struct cache_set *c, struct keylist *keys,
+ atomic_t *journal_ref, struct bkey *replace_key)
+{
+ struct btree_insert_op op;
+ int ret = 0;
- if (ret == -EAGAIN) {
- ret = 0;
- closure_sync(&op->cl);
- } else if (ret) {
- struct bkey *k;
+ BUG_ON(current->bio_list);
+ BUG_ON(bch_keylist_empty(keys));
+
+ bch_btree_op_init(&op.op, 0);
+ op.keys = keys;
+ op.journal_ref = journal_ref;
+ op.replace_key = replace_key;
+
+ while (!ret && !bch_keylist_empty(keys)) {
+ op.op.lock = 0;
+ ret = bch_btree_map_leaf_nodes(&op.op, c,
+ &START_KEY(keys->keys),
+ btree_insert_fn);
+ }
- pr_err("error %i trying to insert key for %s",
- ret, op_type(op));
+ if (ret) {
+ struct bkey *k;
- while ((k = bch_keylist_pop(&stack_keys) ?:
- bch_keylist_pop(&op->keys)))
- bkey_put(c, k, 0);
- }
- }
+ pr_err("error %i", ret);
- bch_keylist_free(&stack_keys);
+ while ((k = bch_keylist_pop(keys)))
+ bkey_put(c, k);
+ } else if (op.op.insert_collision)
+ ret = -ESRCH;
- if (op->journal)
- atomic_dec_bug(op->journal);
- op->journal = NULL;
return ret;
}
@@ -2141,132 +2280,81 @@ void bch_btree_set_root(struct btree *b)
mutex_unlock(&b->c->bucket_lock);
b->c->root = b;
- __bkey_put(b->c, &b->key);
bch_journal_meta(b->c, &cl);
closure_sync(&cl);
}
-/* Cache lookup */
+/* Map across nodes or keys */
-static int submit_partial_cache_miss(struct btree *b, struct btree_op *op,
- struct bkey *k)
+static int bch_btree_map_nodes_recurse(struct btree *b, struct btree_op *op,
+ struct bkey *from,
+ btree_map_nodes_fn *fn, int flags)
{
- struct search *s = container_of(op, struct search, op);
- struct bio *bio = &s->bio.bio;
- int ret = 0;
+ int ret = MAP_CONTINUE;
- while (!ret &&
- !op->lookup_done) {
- unsigned sectors = INT_MAX;
+ if (b->level) {
+ struct bkey *k;
+ struct btree_iter iter;
- if (KEY_INODE(k) == op->inode) {
- if (KEY_START(k) <= bio->bi_sector)
- break;
+ bch_btree_iter_init(b, &iter, from);
- sectors = min_t(uint64_t, sectors,
- KEY_START(k) - bio->bi_sector);
- }
+ while ((k = bch_btree_iter_next_filter(&iter, b,
+ bch_ptr_bad))) {
+ ret = btree(map_nodes_recurse, k, b,
+ op, from, fn, flags);
+ from = NULL;
- ret = s->d->cache_miss(b, s, bio, sectors);
+ if (ret != MAP_CONTINUE)
+ return ret;
+ }
}
+ if (!b->level || flags == MAP_ALL_NODES)
+ ret = fn(op, b);
+
return ret;
}
-/*
- * Read from a single key, handling the initial cache miss if the key starts in
- * the middle of the bio
- */
-static int submit_partial_cache_hit(struct btree *b, struct btree_op *op,
- struct bkey *k)
+int __bch_btree_map_nodes(struct btree_op *op, struct cache_set *c,
+ struct bkey *from, btree_map_nodes_fn *fn, int flags)
{
- struct search *s = container_of(op, struct search, op);
- struct bio *bio = &s->bio.bio;
- unsigned ptr;
- struct bio *n;
-
- int ret = submit_partial_cache_miss(b, op, k);
- if (ret || op->lookup_done)
- return ret;
-
- /* XXX: figure out best pointer - for multiple cache devices */
- ptr = 0;
-
- PTR_BUCKET(b->c, k, ptr)->prio = INITIAL_PRIO;
-
- while (!op->lookup_done &&
- KEY_INODE(k) == op->inode &&
- bio->bi_sector < KEY_OFFSET(k)) {
- struct bkey *bio_key;
- sector_t sector = PTR_OFFSET(k, ptr) +
- (bio->bi_sector - KEY_START(k));
- unsigned sectors = min_t(uint64_t, INT_MAX,
- KEY_OFFSET(k) - bio->bi_sector);
-
- n = bch_bio_split(bio, sectors, GFP_NOIO, s->d->bio_split);
- if (n == bio)
- op->lookup_done = true;
-
- bio_key = &container_of(n, struct bbio, bio)->key;
-
- /*
- * The bucket we're reading from might be reused while our bio
- * is in flight, and we could then end up reading the wrong
- * data.
- *
- * We guard against this by checking (in cache_read_endio()) if
- * the pointer is stale again; if so, we treat it as an error
- * and reread from the backing device (but we don't pass that
- * error up anywhere).
- */
-
- bch_bkey_copy_single_ptr(bio_key, k, ptr);
- SET_PTR_OFFSET(bio_key, 0, sector);
-
- n->bi_end_io = bch_cache_read_endio;
- n->bi_private = &s->cl;
-
- __bch_submit_bbio(n, b->c);
- }
-
- return 0;
+ return btree_root(map_nodes_recurse, c, op, from, fn, flags);
}
-int bch_btree_search_recurse(struct btree *b, struct btree_op *op)
+static int bch_btree_map_keys_recurse(struct btree *b, struct btree_op *op,
+ struct bkey *from, btree_map_keys_fn *fn,
+ int flags)
{
- struct search *s = container_of(op, struct search, op);
- struct bio *bio = &s->bio.bio;
-
- int ret = 0;
+ int ret = MAP_CONTINUE;
struct bkey *k;
struct btree_iter iter;
- bch_btree_iter_init(b, &iter, &KEY(op->inode, bio->bi_sector, 0));
- do {
- k = bch_btree_iter_next_filter(&iter, b, bch_ptr_bad);
- if (!k) {
- /*
- * b->key would be exactly what we want, except that
- * pointers to btree nodes have nonzero size - we
- * wouldn't go far enough
- */
+ bch_btree_iter_init(b, &iter, from);
- ret = submit_partial_cache_miss(b, op,
- &KEY(KEY_INODE(&b->key),
- KEY_OFFSET(&b->key), 0));
- break;
- }
+ while ((k = bch_btree_iter_next_filter(&iter, b, bch_ptr_bad))) {
+ ret = !b->level
+ ? fn(op, b, k)
+ : btree(map_keys_recurse, k, b, op, from, fn, flags);
+ from = NULL;
+
+ if (ret != MAP_CONTINUE)
+ return ret;
+ }
- ret = b->level
- ? btree(search_recurse, k, b, op)
- : submit_partial_cache_hit(b, op, k);
- } while (!ret &&
- !op->lookup_done);
+ if (!b->level && (flags & MAP_END_KEY))
+ ret = fn(op, b, &KEY(KEY_INODE(&b->key),
+ KEY_OFFSET(&b->key), 0));
return ret;
}
+int bch_btree_map_keys(struct btree_op *op, struct cache_set *c,
+ struct bkey *from, btree_map_keys_fn *fn, int flags)
+{
+ return btree_root(map_keys_recurse, c, op, from, fn, flags);
+}
+
/* Keybuf code */
static inline int keybuf_cmp(struct keybuf_key *l, struct keybuf_key *r)
@@ -2285,80 +2373,79 @@ static inline int keybuf_nonoverlapping_cmp(struct keybuf_key *l,
return clamp_t(int64_t, bkey_cmp(&l->key, &r->key), -1, 1);
}
-static int bch_btree_refill_keybuf(struct btree *b, struct btree_op *op,
- struct keybuf *buf, struct bkey *end,
- keybuf_pred_fn *pred)
-{
- struct btree_iter iter;
- bch_btree_iter_init(b, &iter, &buf->last_scanned);
-
- while (!array_freelist_empty(&buf->freelist)) {
- struct bkey *k = bch_btree_iter_next_filter(&iter, b,
- bch_ptr_bad);
-
- if (!b->level) {
- if (!k) {
- buf->last_scanned = b->key;
- break;
- }
+struct refill {
+ struct btree_op op;
+ unsigned nr_found;
+ struct keybuf *buf;
+ struct bkey *end;
+ keybuf_pred_fn *pred;
+};
- buf->last_scanned = *k;
- if (bkey_cmp(&buf->last_scanned, end) >= 0)
- break;
+static int refill_keybuf_fn(struct btree_op *op, struct btree *b,
+ struct bkey *k)
+{
+ struct refill *refill = container_of(op, struct refill, op);
+ struct keybuf *buf = refill->buf;
+ int ret = MAP_CONTINUE;
- if (pred(buf, k)) {
- struct keybuf_key *w;
+ if (bkey_cmp(k, refill->end) >= 0) {
+ ret = MAP_DONE;
+ goto out;
+ }
- spin_lock(&buf->lock);
+ if (!KEY_SIZE(k)) /* end key */
+ goto out;
- w = array_alloc(&buf->freelist);
+ if (refill->pred(buf, k)) {
+ struct keybuf_key *w;
- w->private = NULL;
- bkey_copy(&w->key, k);
+ spin_lock(&buf->lock);
- if (RB_INSERT(&buf->keys, w, node, keybuf_cmp))
- array_free(&buf->freelist, w);
+ w = array_alloc(&buf->freelist);
+ if (!w) {
+ spin_unlock(&buf->lock);
+ return MAP_DONE;
+ }
- spin_unlock(&buf->lock);
- }
- } else {
- if (!k)
- break;
+ w->private = NULL;
+ bkey_copy(&w->key, k);
- btree(refill_keybuf, k, b, op, buf, end, pred);
- /*
- * Might get an error here, but can't really do anything
- * and it'll get logged elsewhere. Just read what we
- * can.
- */
+ if (RB_INSERT(&buf->keys, w, node, keybuf_cmp))
+ array_free(&buf->freelist, w);
+ else
+ refill->nr_found++;
- if (bkey_cmp(&buf->last_scanned, end) >= 0)
- break;
+ if (array_freelist_empty(&buf->freelist))
+ ret = MAP_DONE;
- cond_resched();
- }
+ spin_unlock(&buf->lock);
}
-
- return 0;
+out:
+ buf->last_scanned = *k;
+ return ret;
}
void bch_refill_keybuf(struct cache_set *c, struct keybuf *buf,
struct bkey *end, keybuf_pred_fn *pred)
{
struct bkey start = buf->last_scanned;
- struct btree_op op;
- bch_btree_op_init_stack(&op);
+ struct refill refill;
cond_resched();
- btree_root(refill_keybuf, c, &op, buf, end, pred);
- closure_sync(&op.cl);
+ bch_btree_op_init(&refill.op, -1);
+ refill.nr_found = 0;
+ refill.buf = buf;
+ refill.end = end;
+ refill.pred = pred;
+
+ bch_btree_map_keys(&refill.op, c, &buf->last_scanned,
+ refill_keybuf_fn, MAP_END_KEY);
- pr_debug("found %s keys from %llu:%llu to %llu:%llu",
- RB_EMPTY_ROOT(&buf->keys) ? "no" :
- array_freelist_empty(&buf->freelist) ? "some" : "a few",
- KEY_INODE(&start), KEY_OFFSET(&start),
- KEY_INODE(&buf->last_scanned), KEY_OFFSET(&buf->last_scanned));
+ trace_bcache_keyscan(refill.nr_found,
+ KEY_INODE(&start), KEY_OFFSET(&start),
+ KEY_INODE(&buf->last_scanned),
+ KEY_OFFSET(&buf->last_scanned));
spin_lock(&buf->lock);
@@ -2436,9 +2523,9 @@ struct keybuf_key *bch_keybuf_next(struct keybuf *buf)
}
struct keybuf_key *bch_keybuf_next_rescan(struct cache_set *c,
- struct keybuf *buf,
- struct bkey *end,
- keybuf_pred_fn *pred)
+ struct keybuf *buf,
+ struct bkey *end,
+ keybuf_pred_fn *pred)
{
struct keybuf_key *ret;
@@ -2471,14 +2558,12 @@ void bch_btree_exit(void)
{
if (btree_io_wq)
destroy_workqueue(btree_io_wq);
- if (bch_gc_wq)
- destroy_workqueue(bch_gc_wq);
}
int __init bch_btree_init(void)
{
- if (!(bch_gc_wq = create_singlethread_workqueue("bch_btree_gc")) ||
- !(btree_io_wq = create_singlethread_workqueue("bch_btree_io")))
+ btree_io_wq = create_singlethread_workqueue("bch_btree_io");
+ if (!btree_io_wq)
return -ENOMEM;
return 0;
diff --git a/drivers/md/bcache/btree.h b/drivers/md/bcache/btree.h
index 3333d3723633..767e75570896 100644
--- a/drivers/md/bcache/btree.h
+++ b/drivers/md/bcache/btree.h
@@ -125,6 +125,7 @@ struct btree {
unsigned long seq;
struct rw_semaphore lock;
struct cache_set *c;
+ struct btree *parent;
unsigned long flags;
uint16_t written; /* would be nice to kill */
@@ -200,12 +201,7 @@ static inline bool bkey_written(struct btree *b, struct bkey *k)
static inline void set_gc_sectors(struct cache_set *c)
{
- atomic_set(&c->sectors_to_gc, c->sb.bucket_size * c->nbuckets / 8);
-}
-
-static inline bool bch_ptr_invalid(struct btree *b, const struct bkey *k)
-{
- return __bch_ptr_invalid(b->c, b->level, k);
+ atomic_set(&c->sectors_to_gc, c->sb.bucket_size * c->nbuckets / 16);
}
static inline struct bkey *bch_btree_iter_init(struct btree *b,
@@ -215,6 +211,16 @@ static inline struct bkey *bch_btree_iter_init(struct btree *b,
return __bch_btree_iter_init(b, iter, search, b->sets);
}
+static inline bool bch_ptr_invalid(struct btree *b, const struct bkey *k)
+{
+ if (b->level)
+ return bch_btree_ptr_invalid(b->c, k);
+ else
+ return bch_extent_ptr_invalid(b->c, k);
+}
+
+void bkey_put(struct cache_set *c, struct bkey *k);
+
/* Looping macros */
#define for_each_cached_btree(b, c, iter) \
@@ -234,51 +240,17 @@ static inline struct bkey *bch_btree_iter_init(struct btree *b,
/* Recursing down the btree */
struct btree_op {
- struct closure cl;
- struct cache_set *c;
-
- /* Journal entry we have a refcount on */
- atomic_t *journal;
-
- /* Bio to be inserted into the cache */
- struct bio *cache_bio;
-
- unsigned inode;
-
- uint16_t write_prio;
-
/* Btree level at which we start taking write locks */
short lock;
- /* Btree insertion type */
- enum {
- BTREE_INSERT,
- BTREE_REPLACE
- } type:8;
-
- unsigned csum:1;
- unsigned skip:1;
- unsigned flush_journal:1;
-
- unsigned insert_data_done:1;
- unsigned lookup_done:1;
unsigned insert_collision:1;
-
- /* Anything after this point won't get zeroed in do_bio_hook() */
-
- /* Keys to be inserted */
- struct keylist keys;
- BKEY_PADDED(replace);
};
-enum {
- BTREE_INSERT_STATUS_INSERT,
- BTREE_INSERT_STATUS_BACK_MERGE,
- BTREE_INSERT_STATUS_OVERWROTE,
- BTREE_INSERT_STATUS_FRONT_MERGE,
-};
-
-void bch_btree_op_init_stack(struct btree_op *);
+static inline void bch_btree_op_init(struct btree_op *op, int write_lock_level)
+{
+ memset(op, 0, sizeof(struct btree_op));
+ op->lock = write_lock_level;
+}
static inline void rw_lock(bool w, struct btree *b, int level)
{
@@ -290,108 +262,71 @@ static inline void rw_lock(bool w, struct btree *b, int level)
static inline void rw_unlock(bool w, struct btree *b)
{
-#ifdef CONFIG_BCACHE_EDEBUG
- unsigned i;
-
- if (w && b->key.ptr[0])
- for (i = 0; i <= b->nsets; i++)
- bch_check_key_order(b, b->sets[i].data);
-#endif
-
if (w)
b->seq++;
(w ? up_write : up_read)(&b->lock);
}
-#define insert_lock(s, b) ((b)->level <= (s)->lock)
+void bch_btree_node_read(struct btree *);
+void bch_btree_node_write(struct btree *, struct closure *);
-/*
- * These macros are for recursing down the btree - they handle the details of
- * locking and looking up nodes in the cache for you. They're best treated as
- * mere syntax when reading code that uses them.
- *
- * op->lock determines whether we take a read or a write lock at a given depth.
- * If you've got a read lock and find that you need a write lock (i.e. you're
- * going to have to split), set op->lock and return -EINTR; btree_root() will
- * call you again and you'll have the correct lock.
- */
+void bch_btree_set_root(struct btree *);
+struct btree *bch_btree_node_alloc(struct cache_set *, int, bool);
+struct btree *bch_btree_node_get(struct cache_set *, struct bkey *, int, bool);
-/**
- * btree - recurse down the btree on a specified key
- * @fn: function to call, which will be passed the child node
- * @key: key to recurse on
- * @b: parent btree node
- * @op: pointer to struct btree_op
- */
-#define btree(fn, key, b, op, ...) \
-({ \
- int _r, l = (b)->level - 1; \
- bool _w = l <= (op)->lock; \
- struct btree *_b = bch_btree_node_get((b)->c, key, l, op); \
- if (!IS_ERR(_b)) { \
- _r = bch_btree_ ## fn(_b, op, ##__VA_ARGS__); \
- rw_unlock(_w, _b); \
- } else \
- _r = PTR_ERR(_b); \
- _r; \
-})
-
-/**
- * btree_root - call a function on the root of the btree
- * @fn: function to call, which will be passed the child node
- * @c: cache set
- * @op: pointer to struct btree_op
- */
-#define btree_root(fn, c, op, ...) \
-({ \
- int _r = -EINTR; \
- do { \
- struct btree *_b = (c)->root; \
- bool _w = insert_lock(op, _b); \
- rw_lock(_w, _b, _b->level); \
- if (_b == (c)->root && \
- _w == insert_lock(op, _b)) \
- _r = bch_btree_ ## fn(_b, op, ##__VA_ARGS__); \
- rw_unlock(_w, _b); \
- bch_cannibalize_unlock(c, &(op)->cl); \
- } while (_r == -EINTR); \
- \
- _r; \
-})
+int bch_btree_insert_check_key(struct btree *, struct btree_op *,
+ struct bkey *);
+int bch_btree_insert(struct cache_set *, struct keylist *,
+ atomic_t *, struct bkey *);
+
+int bch_gc_thread_start(struct cache_set *);
+size_t bch_btree_gc_finish(struct cache_set *);
+void bch_moving_gc(struct cache_set *);
+int bch_btree_check(struct cache_set *);
+uint8_t __bch_btree_mark_key(struct cache_set *, int, struct bkey *);
-static inline bool should_split(struct btree *b)
+static inline void wake_up_gc(struct cache_set *c)
{
- struct bset *i = write_block(b);
- return b->written >= btree_blocks(b) ||
- (i->seq == b->sets[0].data->seq &&
- b->written + __set_blocks(i, i->keys + 15, b->c)
- > btree_blocks(b));
+ if (c->gc_thread)
+ wake_up_process(c->gc_thread);
}
-void bch_btree_node_read(struct btree *);
-void bch_btree_node_write(struct btree *, struct closure *);
+#define MAP_DONE 0
+#define MAP_CONTINUE 1
-void bch_cannibalize_unlock(struct cache_set *, struct closure *);
-void bch_btree_set_root(struct btree *);
-struct btree *bch_btree_node_alloc(struct cache_set *, int, struct closure *);
-struct btree *bch_btree_node_get(struct cache_set *, struct bkey *,
- int, struct btree_op *);
+#define MAP_ALL_NODES 0
+#define MAP_LEAF_NODES 1
-bool bch_btree_insert_check_key(struct btree *, struct btree_op *,
- struct bio *);
-int bch_btree_insert(struct btree_op *, struct cache_set *);
+#define MAP_END_KEY 1
-int bch_btree_search_recurse(struct btree *, struct btree_op *);
+typedef int (btree_map_nodes_fn)(struct btree_op *, struct btree *);
+int __bch_btree_map_nodes(struct btree_op *, struct cache_set *,
+ struct bkey *, btree_map_nodes_fn *, int);
-void bch_queue_gc(struct cache_set *);
-size_t bch_btree_gc_finish(struct cache_set *);
-void bch_moving_gc(struct closure *);
-int bch_btree_check(struct cache_set *, struct btree_op *);
-uint8_t __bch_btree_mark_key(struct cache_set *, int, struct bkey *);
+static inline int bch_btree_map_nodes(struct btree_op *op, struct cache_set *c,
+ struct bkey *from, btree_map_nodes_fn *fn)
+{
+ return __bch_btree_map_nodes(op, c, from, fn, MAP_ALL_NODES);
+}
+
+static inline int bch_btree_map_leaf_nodes(struct btree_op *op,
+ struct cache_set *c,
+ struct bkey *from,
+ btree_map_nodes_fn *fn)
+{
+ return __bch_btree_map_nodes(op, c, from, fn, MAP_LEAF_NODES);
+}
+
+typedef int (btree_map_keys_fn)(struct btree_op *, struct btree *,
+ struct bkey *);
+int bch_btree_map_keys(struct btree_op *, struct cache_set *,
+ struct bkey *, btree_map_keys_fn *, int);
+
+typedef bool (keybuf_pred_fn)(struct keybuf *, struct bkey *);
void bch_keybuf_init(struct keybuf *);
-void bch_refill_keybuf(struct cache_set *, struct keybuf *, struct bkey *,
- keybuf_pred_fn *);
+void bch_refill_keybuf(struct cache_set *, struct keybuf *,
+ struct bkey *, keybuf_pred_fn *);
bool bch_keybuf_check_overlapping(struct keybuf *, struct bkey *,
struct bkey *);
void bch_keybuf_del(struct keybuf *, struct keybuf_key *);
diff --git a/drivers/md/bcache/closure.c b/drivers/md/bcache/closure.c
index 9aba2017f0d1..a9b5b93ad48f 100644
--- a/drivers/md/bcache/closure.c
+++ b/drivers/md/bcache/closure.c
@@ -11,17 +11,6 @@
#include "closure.h"
-void closure_queue(struct closure *cl)
-{
- struct workqueue_struct *wq = cl->wq;
- if (wq) {
- INIT_WORK(&cl->work, cl->work.func);
- BUG_ON(!queue_work(wq, &cl->work));
- } else
- cl->fn(cl);
-}
-EXPORT_SYMBOL_GPL(closure_queue);
-
#define CL_FIELD(type, field) \
case TYPE_ ## type: \
return &container_of(cl, struct type, cl)->field
@@ -51,7 +40,7 @@ static inline void closure_put_after_sub(struct closure *cl, int flags)
int r = flags & CLOSURE_REMAINING_MASK;
BUG_ON(flags & CLOSURE_GUARD_MASK);
- BUG_ON(!r && (flags & ~(CLOSURE_DESTRUCTOR|CLOSURE_BLOCKING)));
+ BUG_ON(!r && (flags & ~CLOSURE_DESTRUCTOR));
/* Must deliver precisely one wakeup */
if (r == 1 && (flags & CLOSURE_SLEEPING))
@@ -59,7 +48,6 @@ static inline void closure_put_after_sub(struct closure *cl, int flags)
if (!r) {
if (cl->fn && !(flags & CLOSURE_DESTRUCTOR)) {
- /* CLOSURE_BLOCKING might be set - clear it */
atomic_set(&cl->remaining,
CLOSURE_REMAINING_INITIALIZER);
closure_queue(cl);
@@ -183,13 +171,13 @@ bool closure_trylock(struct closure *cl, struct closure *parent)
CLOSURE_REMAINING_INITIALIZER) != -1)
return false;
- closure_set_ret_ip(cl);
-
smp_mb();
+
cl->parent = parent;
if (parent)
closure_get(parent);
+ closure_set_ret_ip(cl);
closure_debug_create(cl);
return true;
}
@@ -205,8 +193,8 @@ void __closure_lock(struct closure *cl, struct closure *parent,
if (closure_trylock(cl, parent))
return;
- closure_wait_event_sync(wait_list, &wait,
- atomic_read(&cl->remaining) == -1);
+ closure_wait_event(wait_list, &wait,
+ atomic_read(&cl->remaining) == -1);
}
}
EXPORT_SYMBOL_GPL(__closure_lock);
@@ -304,11 +292,10 @@ static int debug_seq_show(struct seq_file *f, void *data)
cl, (void *) cl->ip, cl->fn, cl->parent,
r & CLOSURE_REMAINING_MASK);
- seq_printf(f, "%s%s%s%s%s%s\n",
+ seq_printf(f, "%s%s%s%s%s\n",
test_bit(WORK_STRUCT_PENDING,
work_data_bits(&cl->work)) ? "Q" : "",
r & CLOSURE_RUNNING ? "R" : "",
- r & CLOSURE_BLOCKING ? "B" : "",
r & CLOSURE_STACK ? "S" : "",
r & CLOSURE_SLEEPING ? "Sl" : "",
r & CLOSURE_TIMER ? "T" : "");
diff --git a/drivers/md/bcache/closure.h b/drivers/md/bcache/closure.h
index 00039924ea9d..8d580599de13 100644
--- a/drivers/md/bcache/closure.h
+++ b/drivers/md/bcache/closure.h
@@ -189,9 +189,6 @@ enum closure_type {
enum closure_state {
/*
- * CLOSURE_BLOCKING: Causes closure_wait_event() to block, instead of
- * waiting asynchronously
- *
* CLOSURE_WAITING: Set iff the closure is on a waitlist. Must be set by
* the thread that owns the closure, and cleared by the thread that's
* waking up the closure.
@@ -218,9 +215,8 @@ enum closure_state {
* closure with this flag set
*/
- CLOSURE_BITS_START = (1 << 19),
- CLOSURE_DESTRUCTOR = (1 << 19),
- CLOSURE_BLOCKING = (1 << 21),
+ CLOSURE_BITS_START = (1 << 21),
+ CLOSURE_DESTRUCTOR = (1 << 21),
CLOSURE_WAITING = (1 << 23),
CLOSURE_SLEEPING = (1 << 25),
CLOSURE_TIMER = (1 << 27),
@@ -229,8 +225,8 @@ enum closure_state {
};
#define CLOSURE_GUARD_MASK \
- ((CLOSURE_DESTRUCTOR|CLOSURE_BLOCKING|CLOSURE_WAITING| \
- CLOSURE_SLEEPING|CLOSURE_TIMER|CLOSURE_RUNNING|CLOSURE_STACK) << 1)
+ ((CLOSURE_DESTRUCTOR|CLOSURE_WAITING|CLOSURE_SLEEPING| \
+ CLOSURE_TIMER|CLOSURE_RUNNING|CLOSURE_STACK) << 1)
#define CLOSURE_REMAINING_MASK (CLOSURE_BITS_START - 1)
#define CLOSURE_REMAINING_INITIALIZER (1|CLOSURE_RUNNING)
@@ -296,7 +292,6 @@ extern unsigned invalid_closure_type(void);
void closure_sub(struct closure *cl, int v);
void closure_put(struct closure *cl);
-void closure_queue(struct closure *cl);
void __closure_wake_up(struct closure_waitlist *list);
bool closure_wait(struct closure_waitlist *list, struct closure *cl);
void closure_sync(struct closure *cl);
@@ -354,11 +349,6 @@ static inline void closure_set_stopped(struct closure *cl)
atomic_sub(CLOSURE_RUNNING, &cl->remaining);
}
-static inline bool closure_is_stopped(struct closure *cl)
-{
- return !(atomic_read(&cl->remaining) & CLOSURE_RUNNING);
-}
-
static inline bool closure_is_unlocked(struct closure *cl)
{
return atomic_read(&cl->remaining) == -1;
@@ -429,8 +419,7 @@ do { \
static inline void closure_init_stack(struct closure *cl)
{
memset(cl, 0, sizeof(struct closure));
- atomic_set(&cl->remaining, CLOSURE_REMAINING_INITIALIZER|
- CLOSURE_BLOCKING|CLOSURE_STACK);
+ atomic_set(&cl->remaining, CLOSURE_REMAINING_INITIALIZER|CLOSURE_STACK);
}
/**
@@ -498,40 +487,6 @@ static inline void __closure_start_sleep(struct closure *cl)
}
/**
- * closure_blocking() - returns true if the closure is in blocking mode.
- *
- * If a closure is in blocking mode, closure_wait_event() will sleep until the
- * condition is true instead of waiting asynchronously.
- */
-static inline bool closure_blocking(struct closure *cl)
-{
- return atomic_read(&cl->remaining) & CLOSURE_BLOCKING;
-}
-
-/**
- * set_closure_blocking() - put a closure in blocking mode.
- *
- * If a closure is in blocking mode, closure_wait_event() will sleep until the
- * condition is true instead of waiting asynchronously.
- *
- * Not thread safe - can only be called by the thread running the closure.
- */
-static inline void set_closure_blocking(struct closure *cl)
-{
- if (!closure_blocking(cl))
- atomic_add(CLOSURE_BLOCKING, &cl->remaining);
-}
-
-/*
- * Not thread safe - can only be called by the thread running the closure.
- */
-static inline void clear_closure_blocking(struct closure *cl)
-{
- if (closure_blocking(cl))
- atomic_sub(CLOSURE_BLOCKING, &cl->remaining);
-}
-
-/**
* closure_wake_up() - wake up all closures on a wait list.
*/
static inline void closure_wake_up(struct closure_waitlist *list)
@@ -561,63 +516,36 @@ static inline void closure_wake_up(struct closure_waitlist *list)
* refcount on our closure. If this was a stack allocated closure, that would be
* bad.
*/
-#define __closure_wait_event(list, cl, condition, _block) \
+#define closure_wait_event(list, cl, condition) \
({ \
- bool block = _block; \
typeof(condition) ret; \
\
while (1) { \
ret = (condition); \
if (ret) { \
__closure_wake_up(list); \
- if (block) \
- closure_sync(cl); \
- \
+ closure_sync(cl); \
break; \
} \
\
- if (block) \
- __closure_start_sleep(cl); \
- \
- if (!closure_wait(list, cl)) { \
- if (!block) \
- break; \
+ __closure_start_sleep(cl); \
\
+ if (!closure_wait(list, cl)) \
schedule(); \
- } \
} \
\
ret; \
})
-/**
- * closure_wait_event() - wait on a condition, synchronously or asynchronously.
- * @list: the wait list to wait on
- * @cl: the closure that is doing the waiting
- * @condition: a C expression for the event to wait for
- *
- * If the closure is in blocking mode, sleeps until the @condition evaluates to
- * true - exactly like wait_event().
- *
- * If the closure is not in blocking mode, waits asynchronously; if the
- * condition is currently false the @cl is put onto @list and returns. @list
- * owns a refcount on @cl; closure_sync() or continue_at() may be used later to
- * wait for another thread to wake up @list, which drops the refcount on @cl.
- *
- * Returns the value of @condition; @cl will be on @list iff @condition was
- * false.
- *
- * closure_wake_up(@list) must be called after changing any variable that could
- * cause @condition to become true.
- */
-#define closure_wait_event(list, cl, condition) \
- __closure_wait_event(list, cl, condition, closure_blocking(cl))
-
-#define closure_wait_event_async(list, cl, condition) \
- __closure_wait_event(list, cl, condition, false)
-
-#define closure_wait_event_sync(list, cl, condition) \
- __closure_wait_event(list, cl, condition, true)
+static inline void closure_queue(struct closure *cl)
+{
+ struct workqueue_struct *wq = cl->wq;
+ if (wq) {
+ INIT_WORK(&cl->work, cl->work.func);
+ BUG_ON(!queue_work(wq, &cl->work));
+ } else
+ cl->fn(cl);
+}
static inline void set_closure_fn(struct closure *cl, closure_fn *fn,
struct workqueue_struct *wq)
@@ -642,7 +570,7 @@ do { \
#define continue_at_nobarrier(_cl, _fn, _wq) \
do { \
set_closure_fn(_cl, _fn, _wq); \
- closure_queue(cl); \
+ closure_queue(_cl); \
return; \
} while (0)
diff --git a/drivers/md/bcache/debug.c b/drivers/md/bcache/debug.c
index 88e6411eab4f..fefbe9c93d11 100644
--- a/drivers/md/bcache/debug.c
+++ b/drivers/md/bcache/debug.c
@@ -8,7 +8,6 @@
#include "bcache.h"
#include "btree.h"
#include "debug.h"
-#include "request.h"
#include <linux/console.h>
#include <linux/debugfs.h>
@@ -77,29 +76,17 @@ int bch_bkey_to_text(char *buf, size_t size, const struct bkey *k)
return out - buf;
}
-int bch_btree_to_text(char *buf, size_t size, const struct btree *b)
-{
- return scnprintf(buf, size, "%zu level %i/%i",
- PTR_BUCKET_NR(b->c, &b->key, 0),
- b->level, b->c->root ? b->c->root->level : -1);
-}
-
-#if defined(CONFIG_BCACHE_DEBUG) || defined(CONFIG_BCACHE_EDEBUG)
-
-static bool skipped_backwards(struct btree *b, struct bkey *k)
-{
- return bkey_cmp(k, (!b->level)
- ? &START_KEY(bkey_next(k))
- : bkey_next(k)) > 0;
-}
+#ifdef CONFIG_BCACHE_DEBUG
static void dump_bset(struct btree *b, struct bset *i)
{
- struct bkey *k;
+ struct bkey *k, *next;
unsigned j;
char buf[80];
- for (k = i->start; k < end(i); k = bkey_next(k)) {
+ for (k = i->start; k < end(i); k = next) {
+ next = bkey_next(k);
+
bch_bkey_to_text(buf, sizeof(buf), k);
printk(KERN_ERR "block %zu key %zi/%u: %s", index(i, b),
(uint64_t *) k - i->d, i->keys, buf);
@@ -115,15 +102,21 @@ static void dump_bset(struct btree *b, struct bset *i)
printk(" %s\n", bch_ptr_status(b->c, k));
- if (bkey_next(k) < end(i) &&
- skipped_backwards(b, k))
+ if (next < end(i) &&
+ bkey_cmp(k, !b->level ? &START_KEY(next) : next) > 0)
printk(KERN_ERR "Key skipped backwards\n");
}
}
-#endif
+static void bch_dump_bucket(struct btree *b)
+{
+ unsigned i;
-#ifdef CONFIG_BCACHE_DEBUG
+ console_lock();
+ for (i = 0; i <= b->nsets; i++)
+ dump_bset(b, b->sets[i].data);
+ console_unlock();
+}
void bch_btree_verify(struct btree *b, struct bset *new)
{
@@ -182,20 +175,17 @@ static void data_verify_endio(struct bio *bio, int error)
closure_put(cl);
}
-void bch_data_verify(struct search *s)
+void bch_data_verify(struct cached_dev *dc, struct bio *bio)
{
char name[BDEVNAME_SIZE];
- struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
- struct closure *cl = &s->cl;
+ struct closure cl;
struct bio *check;
struct bio_vec *bv;
int i;
- if (!s->unaligned_bvec)
- bio_for_each_segment(bv, s->orig_bio, i)
- bv->bv_offset = 0, bv->bv_len = PAGE_SIZE;
+ closure_init_stack(&cl);
- check = bio_clone(s->orig_bio, GFP_NOIO);
+ check = bio_clone(bio, GFP_NOIO);
if (!check)
return;
@@ -203,23 +193,23 @@ void bch_data_verify(struct search *s)
goto out_put;
check->bi_rw = READ_SYNC;
- check->bi_private = cl;
+ check->bi_private = &cl;
check->bi_end_io = data_verify_endio;
- closure_bio_submit(check, cl, &dc->disk);
- closure_sync(cl);
+ closure_bio_submit(check, &cl, &dc->disk);
+ closure_sync(&cl);
- bio_for_each_segment(bv, s->orig_bio, i) {
+ bio_for_each_segment(bv, bio, i) {
void *p1 = kmap(bv->bv_page);
void *p2 = kmap(check->bi_io_vec[i].bv_page);
- if (memcmp(p1 + bv->bv_offset,
- p2 + bv->bv_offset,
- bv->bv_len))
- printk(KERN_ERR
- "bcache (%s): verify failed at sector %llu\n",
- bdevname(dc->bdev, name),
- (uint64_t) s->orig_bio->bi_sector);
+ cache_set_err_on(memcmp(p1 + bv->bv_offset,
+ p2 + bv->bv_offset,
+ bv->bv_len),
+ dc->disk.c,
+ "verify failed at dev %s sector %llu",
+ bdevname(dc->bdev, name),
+ (uint64_t) bio->bi_sector);
kunmap(bv->bv_page);
kunmap(check->bi_io_vec[i].bv_page);
@@ -231,11 +221,7 @@ out_put:
bio_put(check);
}
-#endif
-
-#ifdef CONFIG_BCACHE_EDEBUG
-
-unsigned bch_count_data(struct btree *b)
+int __bch_count_data(struct btree *b)
{
unsigned ret = 0;
struct btree_iter iter;
@@ -247,72 +233,60 @@ unsigned bch_count_data(struct btree *b)
return ret;
}
-static void vdump_bucket_and_panic(struct btree *b, const char *fmt,
- va_list args)
-{
- unsigned i;
- char buf[80];
-
- console_lock();
-
- for (i = 0; i <= b->nsets; i++)
- dump_bset(b, b->sets[i].data);
-
- vprintk(fmt, args);
-
- console_unlock();
-
- bch_btree_to_text(buf, sizeof(buf), b);
- panic("at %s\n", buf);
-}
-
-void bch_check_key_order_msg(struct btree *b, struct bset *i,
- const char *fmt, ...)
-{
- struct bkey *k;
-
- if (!i->keys)
- return;
-
- for (k = i->start; bkey_next(k) < end(i); k = bkey_next(k))
- if (skipped_backwards(b, k)) {
- va_list args;
- va_start(args, fmt);
-
- vdump_bucket_and_panic(b, fmt, args);
- va_end(args);
- }
-}
-
-void bch_check_keys(struct btree *b, const char *fmt, ...)
+void __bch_check_keys(struct btree *b, const char *fmt, ...)
{
va_list args;
struct bkey *k, *p = NULL;
struct btree_iter iter;
-
- if (b->level)
- return;
+ const char *err;
for_each_key(b, k, &iter) {
- if (p && bkey_cmp(&START_KEY(p), &START_KEY(k)) > 0) {
- printk(KERN_ERR "Keys out of order:\n");
- goto bug;
- }
-
- if (bch_ptr_invalid(b, k))
- continue;
-
- if (p && bkey_cmp(p, &START_KEY(k)) > 0) {
- printk(KERN_ERR "Overlapping keys:\n");
- goto bug;
+ if (!b->level) {
+ err = "Keys out of order";
+ if (p && bkey_cmp(&START_KEY(p), &START_KEY(k)) > 0)
+ goto bug;
+
+ if (bch_ptr_invalid(b, k))
+ continue;
+
+ err = "Overlapping keys";
+ if (p && bkey_cmp(p, &START_KEY(k)) > 0)
+ goto bug;
+ } else {
+ if (bch_ptr_bad(b, k))
+ continue;
+
+ err = "Duplicate keys";
+ if (p && !bkey_cmp(p, k))
+ goto bug;
}
p = k;
}
+
+ err = "Key larger than btree node key";
+ if (p && bkey_cmp(p, &b->key) > 0)
+ goto bug;
+
return;
bug:
+ bch_dump_bucket(b);
+
va_start(args, fmt);
- vdump_bucket_and_panic(b, fmt, args);
+ vprintk(fmt, args);
va_end(args);
+
+ panic("bcache error: %s:\n", err);
+}
+
+void bch_btree_iter_next_check(struct btree_iter *iter)
+{
+ struct bkey *k = iter->data->k, *next = bkey_next(k);
+
+ if (next < iter->data->end &&
+ bkey_cmp(k, iter->b->level ? next : &START_KEY(next)) > 0) {
+ bch_dump_bucket(iter->b);
+ panic("Key skipped backwards\n");
+ }
}
#endif
diff --git a/drivers/md/bcache/debug.h b/drivers/md/bcache/debug.h
index 1c39b5a2489b..2ede60e31874 100644
--- a/drivers/md/bcache/debug.h
+++ b/drivers/md/bcache/debug.h
@@ -4,40 +4,44 @@
/* Btree/bkey debug printing */
int bch_bkey_to_text(char *buf, size_t size, const struct bkey *k);
-int bch_btree_to_text(char *buf, size_t size, const struct btree *b);
-
-#ifdef CONFIG_BCACHE_EDEBUG
-
-unsigned bch_count_data(struct btree *);
-void bch_check_key_order_msg(struct btree *, struct bset *, const char *, ...);
-void bch_check_keys(struct btree *, const char *, ...);
-
-#define bch_check_key_order(b, i) \
- bch_check_key_order_msg(b, i, "keys out of order")
-#define EBUG_ON(cond) BUG_ON(cond)
-
-#else /* EDEBUG */
-
-#define bch_count_data(b) 0
-#define bch_check_key_order(b, i) do {} while (0)
-#define bch_check_key_order_msg(b, i, ...) do {} while (0)
-#define bch_check_keys(b, ...) do {} while (0)
-#define EBUG_ON(cond) do {} while (0)
-
-#endif
#ifdef CONFIG_BCACHE_DEBUG
void bch_btree_verify(struct btree *, struct bset *);
-void bch_data_verify(struct search *);
+void bch_data_verify(struct cached_dev *, struct bio *);
+int __bch_count_data(struct btree *);
+void __bch_check_keys(struct btree *, const char *, ...);
+void bch_btree_iter_next_check(struct btree_iter *);
+
+#define EBUG_ON(cond) BUG_ON(cond)
+#define expensive_debug_checks(c) ((c)->expensive_debug_checks)
+#define key_merging_disabled(c) ((c)->key_merging_disabled)
+#define bypass_torture_test(d) ((d)->bypass_torture_test)
#else /* DEBUG */
static inline void bch_btree_verify(struct btree *b, struct bset *i) {}
-static inline void bch_data_verify(struct search *s) {};
+static inline void bch_data_verify(struct cached_dev *dc, struct bio *bio) {}
+static inline int __bch_count_data(struct btree *b) { return -1; }
+static inline void __bch_check_keys(struct btree *b, const char *fmt, ...) {}
+static inline void bch_btree_iter_next_check(struct btree_iter *iter) {}
+
+#define EBUG_ON(cond) do { if (cond); } while (0)
+#define expensive_debug_checks(c) 0
+#define key_merging_disabled(c) 0
+#define bypass_torture_test(d) 0
#endif
+#define bch_count_data(b) \
+ (expensive_debug_checks((b)->c) ? __bch_count_data(b) : -1)
+
+#define bch_check_keys(b, ...) \
+do { \
+ if (expensive_debug_checks((b)->c)) \
+ __bch_check_keys(b, __VA_ARGS__); \
+} while (0)
+
#ifdef CONFIG_DEBUG_FS
void bch_debug_init_cache_set(struct cache_set *);
#else
diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c
index 8435f81e5d85..41d0b6af2540 100644
--- a/drivers/md/bcache/journal.c
+++ b/drivers/md/bcache/journal.c
@@ -7,7 +7,6 @@
#include "bcache.h"
#include "btree.h"
#include "debug.h"
-#include "request.h"
#include <trace/events/bcache.h>
@@ -31,17 +30,20 @@ static void journal_read_endio(struct bio *bio, int error)
}
static int journal_read_bucket(struct cache *ca, struct list_head *list,
- struct btree_op *op, unsigned bucket_index)
+ unsigned bucket_index)
{
struct journal_device *ja = &ca->journal;
struct bio *bio = &ja->bio;
struct journal_replay *i;
struct jset *j, *data = ca->set->journal.w[0].data;
+ struct closure cl;
unsigned len, left, offset = 0;
int ret = 0;
sector_t bucket = bucket_to_sector(ca->set, ca->sb.d[bucket_index]);
+ closure_init_stack(&cl);
+
pr_debug("reading %llu", (uint64_t) bucket);
while (offset < ca->sb.bucket_size) {
@@ -55,11 +57,11 @@ reread: left = ca->sb.bucket_size - offset;
bio->bi_size = len << 9;
bio->bi_end_io = journal_read_endio;
- bio->bi_private = &op->cl;
+ bio->bi_private = &cl;
bch_bio_map(bio, data);
- closure_bio_submit(bio, &op->cl, ca);
- closure_sync(&op->cl);
+ closure_bio_submit(bio, &cl, ca);
+ closure_sync(&cl);
/* This function could be simpler now since we no longer write
* journal entries that overlap bucket boundaries; this means
@@ -72,7 +74,7 @@ reread: left = ca->sb.bucket_size - offset;
struct list_head *where;
size_t blocks, bytes = set_bytes(j);
- if (j->magic != jset_magic(ca->set))
+ if (j->magic != jset_magic(&ca->sb))
return ret;
if (bytes > left << 9)
@@ -129,12 +131,11 @@ next_set:
return ret;
}
-int bch_journal_read(struct cache_set *c, struct list_head *list,
- struct btree_op *op)
+int bch_journal_read(struct cache_set *c, struct list_head *list)
{
#define read_bucket(b) \
({ \
- int ret = journal_read_bucket(ca, list, op, b); \
+ int ret = journal_read_bucket(ca, list, b); \
__set_bit(b, bitmap); \
if (ret < 0) \
return ret; \
@@ -292,8 +293,7 @@ void bch_journal_mark(struct cache_set *c, struct list_head *list)
}
}
-int bch_journal_replay(struct cache_set *s, struct list_head *list,
- struct btree_op *op)
+int bch_journal_replay(struct cache_set *s, struct list_head *list)
{
int ret = 0, keys = 0, entries = 0;
struct bkey *k;
@@ -301,31 +301,30 @@ int bch_journal_replay(struct cache_set *s, struct list_head *list,
list_entry(list->prev, struct journal_replay, list);
uint64_t start = i->j.last_seq, end = i->j.seq, n = start;
+ struct keylist keylist;
+
+ bch_keylist_init(&keylist);
list_for_each_entry(i, list, list) {
BUG_ON(i->pin && atomic_read(i->pin) != 1);
- if (n != i->j.seq)
- pr_err(
- "journal entries %llu-%llu missing! (replaying %llu-%llu)\n",
- n, i->j.seq - 1, start, end);
+ cache_set_err_on(n != i->j.seq, s,
+"bcache: journal entries %llu-%llu missing! (replaying %llu-%llu)",
+ n, i->j.seq - 1, start, end);
for (k = i->j.start;
k < end(&i->j);
k = bkey_next(k)) {
trace_bcache_journal_replay_key(k);
- bkey_copy(op->keys.top, k);
- bch_keylist_push(&op->keys);
-
- op->journal = i->pin;
- atomic_inc(op->journal);
+ bkey_copy(keylist.top, k);
+ bch_keylist_push(&keylist);
- ret = bch_btree_insert(op, s);
+ ret = bch_btree_insert(s, &keylist, i->pin, NULL);
if (ret)
goto err;
- BUG_ON(!bch_keylist_empty(&op->keys));
+ BUG_ON(!bch_keylist_empty(&keylist));
keys++;
cond_resched();
@@ -339,14 +338,13 @@ int bch_journal_replay(struct cache_set *s, struct list_head *list,
pr_info("journal replay done, %i keys in %i entries, seq %llu",
keys, entries, end);
-
+err:
while (!list_empty(list)) {
i = list_first_entry(list, struct journal_replay, list);
list_del(&i->list);
kfree(i);
}
-err:
- closure_sync(&op->cl);
+
return ret;
}
@@ -358,48 +356,35 @@ static void btree_flush_write(struct cache_set *c)
* Try to find the btree node with that references the oldest journal
* entry, best is our current candidate and is locked if non NULL:
*/
- struct btree *b, *best = NULL;
- unsigned iter;
+ struct btree *b, *best;
+ unsigned i;
+retry:
+ best = NULL;
+
+ for_each_cached_btree(b, c, i)
+ if (btree_current_write(b)->journal) {
+ if (!best)
+ best = b;
+ else if (journal_pin_cmp(c,
+ btree_current_write(best)->journal,
+ btree_current_write(b)->journal)) {
+ best = b;
+ }
+ }
- for_each_cached_btree(b, c, iter) {
- if (!down_write_trylock(&b->lock))
- continue;
+ b = best;
+ if (b) {
+ rw_lock(true, b, b->level);
- if (!btree_node_dirty(b) ||
- !btree_current_write(b)->journal) {
+ if (!btree_current_write(b)->journal) {
rw_unlock(true, b);
- continue;
+ /* We raced */
+ goto retry;
}
- if (!best)
- best = b;
- else if (journal_pin_cmp(c,
- btree_current_write(best),
- btree_current_write(b))) {
- rw_unlock(true, best);
- best = b;
- } else
- rw_unlock(true, b);
+ bch_btree_node_write(b, NULL);
+ rw_unlock(true, b);
}
-
- if (best)
- goto out;
-
- /* We can't find the best btree node, just pick the first */
- list_for_each_entry(b, &c->btree_cache, list)
- if (!b->level && btree_node_dirty(b)) {
- best = b;
- rw_lock(true, best, best->level);
- goto found;
- }
-
-out:
- if (!best)
- return;
-found:
- if (btree_node_dirty(best))
- bch_btree_node_write(best, NULL);
- rw_unlock(true, best);
}
#define last_seq(j) ((j)->seq - fifo_used(&(j)->pin) + 1)
@@ -495,7 +480,7 @@ static void journal_reclaim(struct cache_set *c)
do_journal_discard(ca);
if (c->journal.blocks_free)
- return;
+ goto out;
/*
* Allocate:
@@ -521,7 +506,7 @@ static void journal_reclaim(struct cache_set *c)
if (n)
c->journal.blocks_free = c->sb.bucket_size >> c->block_bits;
-
+out:
if (!journal_full(&c->journal))
__closure_wake_up(&c->journal.wait);
}
@@ -589,23 +574,7 @@ static void journal_write_unlocked(struct closure *cl)
struct bio_list list;
bio_list_init(&list);
- if (!w->need_write) {
- /*
- * XXX: have to unlock closure before we unlock journal lock,
- * else we race with bch_journal(). But this way we race
- * against cache set unregister. Doh.
- */
- set_closure_fn(cl, NULL, NULL);
- closure_sub(cl, CLOSURE_RUNNING + 1);
- spin_unlock(&c->journal.lock);
- return;
- } else if (journal_full(&c->journal)) {
- journal_reclaim(c);
- spin_unlock(&c->journal.lock);
-
- btree_flush_write(c);
- continue_at(cl, journal_write, system_wq);
- }
+ BUG_ON(journal_full(&c->journal));
c->journal.blocks_free -= set_blocks(w->data, c);
@@ -617,7 +586,7 @@ static void journal_write_unlocked(struct closure *cl)
for_each_cache(ca, c, i)
w->data->prio_bucket[ca->sb.nr_this_dev] = ca->prio_buckets[0];
- w->data->magic = jset_magic(c);
+ w->data->magic = jset_magic(&c->sb);
w->data->version = BCACHE_JSET_VERSION;
w->data->last_seq = last_seq(&c->journal);
w->data->csum = csum_set(w->data);
@@ -663,40 +632,79 @@ static void journal_write(struct closure *cl)
struct cache_set *c = container_of(cl, struct cache_set, journal.io.cl);
spin_lock(&c->journal.lock);
- journal_write_unlocked(cl);
+
+ if (!c->journal.cur->need_write) {
+ /*
+ * XXX: have to unlock closure before we unlock journal lock,
+ * else we race with bch_journal(). But this way we race
+ * against cache set unregister. Doh.
+ */
+ set_closure_fn(cl, NULL, NULL);
+ closure_sub(cl, CLOSURE_RUNNING + 1);
+ spin_unlock(&c->journal.lock);
+ } else
+ journal_write_unlocked(cl);
}
-static void __journal_try_write(struct cache_set *c, bool noflush)
+static void journal_try_write(struct cache_set *c)
__releases(c->journal.lock)
{
struct closure *cl = &c->journal.io.cl;
- if (!closure_trylock(cl, &c->cl))
- spin_unlock(&c->journal.lock);
- else if (noflush && journal_full(&c->journal)) {
- spin_unlock(&c->journal.lock);
- continue_at(cl, journal_write, system_wq);
- } else
+ if (closure_trylock(cl, &c->cl))
journal_write_unlocked(cl);
+ else
+ spin_unlock(&c->journal.lock);
}
-#define journal_try_write(c) __journal_try_write(c, false)
-
-void bch_journal_meta(struct cache_set *c, struct closure *cl)
+static struct journal_write *journal_wait_for_write(struct cache_set *c,
+ unsigned nkeys)
{
- struct journal_write *w;
+ size_t sectors;
+ struct closure cl;
- if (CACHE_SYNC(&c->sb)) {
- spin_lock(&c->journal.lock);
+ closure_init_stack(&cl);
- w = c->journal.cur;
- w->need_write = true;
+ spin_lock(&c->journal.lock);
- if (cl)
- BUG_ON(!closure_wait(&w->wait, cl));
+ while (1) {
+ struct journal_write *w = c->journal.cur;
- closure_flush(&c->journal.io);
- __journal_try_write(c, true);
+ sectors = __set_blocks(w->data, w->data->keys + nkeys,
+ c) * c->sb.block_size;
+
+ if (sectors <= min_t(size_t,
+ c->journal.blocks_free * c->sb.block_size,
+ PAGE_SECTORS << JSET_BITS))
+ return w;
+
+ /* XXX: tracepoint */
+ if (!journal_full(&c->journal)) {
+ trace_bcache_journal_entry_full(c);
+
+ /*
+ * XXX: If we were inserting so many keys that they
+ * won't fit in an _empty_ journal write, we'll
+ * deadlock. For now, handle this in
+ * bch_keylist_realloc() - but something to think about.
+ */
+ BUG_ON(!w->data->keys || !w->need_write);
+
+ closure_wait(&w->wait, &cl);
+ closure_flush(&c->journal.io);
+ journal_try_write(c); /* unlocks */
+ } else {
+ trace_bcache_journal_full(c);
+
+ closure_wait(&c->journal.wait, &cl);
+ journal_reclaim(c);
+ spin_unlock(&c->journal.lock);
+
+ btree_flush_write(c);
+ }
+
+ closure_sync(&cl);
+ spin_lock(&c->journal.lock);
}
}
@@ -706,75 +714,45 @@ void bch_journal_meta(struct cache_set *c, struct closure *cl)
* bch_journal() hands those same keys off to btree_insert_async()
*/
-void bch_journal(struct closure *cl)
+atomic_t *bch_journal(struct cache_set *c,
+ struct keylist *keys,
+ struct closure *parent)
{
- struct btree_op *op = container_of(cl, struct btree_op, cl);
- struct cache_set *c = op->c;
struct journal_write *w;
- size_t b, n = ((uint64_t *) op->keys.top) - op->keys.list;
-
- if (op->type != BTREE_INSERT ||
- !CACHE_SYNC(&c->sb))
- goto out;
-
- /*
- * If we're looping because we errored, might already be waiting on
- * another journal write:
- */
- while (atomic_read(&cl->parent->remaining) & CLOSURE_WAITING)
- closure_sync(cl->parent);
-
- spin_lock(&c->journal.lock);
-
- if (journal_full(&c->journal)) {
- trace_bcache_journal_full(c);
-
- closure_wait(&c->journal.wait, cl);
+ atomic_t *ret;
- journal_reclaim(c);
- spin_unlock(&c->journal.lock);
+ if (!CACHE_SYNC(&c->sb))
+ return NULL;
- btree_flush_write(c);
- continue_at(cl, bch_journal, bcache_wq);
- }
+ w = journal_wait_for_write(c, bch_keylist_nkeys(keys));
- w = c->journal.cur;
+ memcpy(end(w->data), keys->keys, bch_keylist_bytes(keys));
+ w->data->keys += bch_keylist_nkeys(keys);
w->need_write = true;
- b = __set_blocks(w->data, w->data->keys + n, c);
-
- if (b * c->sb.block_size > PAGE_SECTORS << JSET_BITS ||
- b > c->journal.blocks_free) {
- trace_bcache_journal_entry_full(c);
-
- /*
- * XXX: If we were inserting so many keys that they won't fit in
- * an _empty_ journal write, we'll deadlock. For now, handle
- * this in bch_keylist_realloc() - but something to think about.
- */
- BUG_ON(!w->data->keys);
- BUG_ON(!closure_wait(&w->wait, cl));
+ ret = &fifo_back(&c->journal.pin);
+ atomic_inc(ret);
+ if (parent) {
+ closure_wait(&w->wait, parent);
closure_flush(&c->journal.io);
-
- journal_try_write(c);
- continue_at(cl, bch_journal, bcache_wq);
}
- memcpy(end(w->data), op->keys.list, n * sizeof(uint64_t));
- w->data->keys += n;
+ journal_try_write(c);
- op->journal = &fifo_back(&c->journal.pin);
- atomic_inc(op->journal);
+ return ret;
+}
- if (op->flush_journal) {
- closure_flush(&c->journal.io);
- closure_wait(&w->wait, cl->parent);
- }
+void bch_journal_meta(struct cache_set *c, struct closure *cl)
+{
+ struct keylist keys;
+ atomic_t *ref;
- journal_try_write(c);
-out:
- bch_btree_insert_async(cl);
+ bch_keylist_init(&keys);
+
+ ref = bch_journal(c, &keys, cl);
+ if (ref)
+ atomic_dec_bug(ref);
}
void bch_journal_free(struct cache_set *c)
diff --git a/drivers/md/bcache/journal.h b/drivers/md/bcache/journal.h
index 3d7851274b04..b196fcb44bc6 100644
--- a/drivers/md/bcache/journal.h
+++ b/drivers/md/bcache/journal.h
@@ -75,43 +75,6 @@
* nodes that are pinning the oldest journal entries first.
*/
-#define BCACHE_JSET_VERSION_UUIDv1 1
-/* Always latest UUID format */
-#define BCACHE_JSET_VERSION_UUID 1
-#define BCACHE_JSET_VERSION 1
-
-/*
- * On disk format for a journal entry:
- * seq is monotonically increasing; every journal entry has its own unique
- * sequence number.
- *
- * last_seq is the oldest journal entry that still has keys the btree hasn't
- * flushed to disk yet.
- *
- * version is for on disk format changes.
- */
-struct jset {
- uint64_t csum;
- uint64_t magic;
- uint64_t seq;
- uint32_t version;
- uint32_t keys;
-
- uint64_t last_seq;
-
- BKEY_PADDED(uuid_bucket);
- BKEY_PADDED(btree_root);
- uint16_t btree_level;
- uint16_t pad[3];
-
- uint64_t prio_bucket[MAX_CACHES_PER_SET];
-
- union {
- struct bkey start[0];
- uint64_t d[0];
- };
-};
-
/*
* Only used for holding the journal entries we read in btree_journal_read()
* during cache_registration
@@ -188,8 +151,7 @@ struct journal_device {
};
#define journal_pin_cmp(c, l, r) \
- (fifo_idx(&(c)->journal.pin, (l)->journal) > \
- fifo_idx(&(c)->journal.pin, (r)->journal))
+ (fifo_idx(&(c)->journal.pin, (l)) > fifo_idx(&(c)->journal.pin, (r)))
#define JOURNAL_PIN 20000
@@ -199,15 +161,14 @@ struct journal_device {
struct closure;
struct cache_set;
struct btree_op;
+struct keylist;
-void bch_journal(struct closure *);
+atomic_t *bch_journal(struct cache_set *, struct keylist *, struct closure *);
void bch_journal_next(struct journal *);
void bch_journal_mark(struct cache_set *, struct list_head *);
void bch_journal_meta(struct cache_set *, struct closure *);
-int bch_journal_read(struct cache_set *, struct list_head *,
- struct btree_op *);
-int bch_journal_replay(struct cache_set *, struct list_head *,
- struct btree_op *);
+int bch_journal_read(struct cache_set *, struct list_head *);
+int bch_journal_replay(struct cache_set *, struct list_head *);
void bch_journal_free(struct cache_set *);
int bch_journal_alloc(struct cache_set *);
diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c
index 1a3b4f4786c3..db72d659efb1 100644
--- a/drivers/md/bcache/movinggc.c
+++ b/drivers/md/bcache/movinggc.c
@@ -12,8 +12,9 @@
#include <trace/events/bcache.h>
struct moving_io {
+ struct closure cl;
struct keybuf_key *w;
- struct search s;
+ struct data_insert_op op;
struct bbio bio;
};
@@ -38,13 +39,13 @@ static bool moving_pred(struct keybuf *buf, struct bkey *k)
static void moving_io_destructor(struct closure *cl)
{
- struct moving_io *io = container_of(cl, struct moving_io, s.cl);
+ struct moving_io *io = container_of(cl, struct moving_io, cl);
kfree(io);
}
static void write_moving_finish(struct closure *cl)
{
- struct moving_io *io = container_of(cl, struct moving_io, s.cl);
+ struct moving_io *io = container_of(cl, struct moving_io, cl);
struct bio *bio = &io->bio.bio;
struct bio_vec *bv;
int i;
@@ -52,13 +53,12 @@ static void write_moving_finish(struct closure *cl)
bio_for_each_segment_all(bv, bio, i)
__free_page(bv->bv_page);
- if (io->s.op.insert_collision)
+ if (io->op.replace_collision)
trace_bcache_gc_copy_collision(&io->w->key);
- bch_keybuf_del(&io->s.op.c->moving_gc_keys, io->w);
+ bch_keybuf_del(&io->op.c->moving_gc_keys, io->w);
- atomic_dec_bug(&io->s.op.c->in_flight);
- closure_wake_up(&io->s.op.c->moving_gc_wait);
+ up(&io->op.c->moving_in_flight);
closure_return_with_destructor(cl, moving_io_destructor);
}
@@ -66,12 +66,12 @@ static void write_moving_finish(struct closure *cl)
static void read_moving_endio(struct bio *bio, int error)
{
struct moving_io *io = container_of(bio->bi_private,
- struct moving_io, s.cl);
+ struct moving_io, cl);
if (error)
- io->s.error = error;
+ io->op.error = error;
- bch_bbio_endio(io->s.op.c, bio, error, "reading data to move");
+ bch_bbio_endio(io->op.c, bio, error, "reading data to move");
}
static void moving_init(struct moving_io *io)
@@ -85,32 +85,30 @@ static void moving_init(struct moving_io *io)
bio->bi_size = KEY_SIZE(&io->w->key) << 9;
bio->bi_max_vecs = DIV_ROUND_UP(KEY_SIZE(&io->w->key),
PAGE_SECTORS);
- bio->bi_private = &io->s.cl;
+ bio->bi_private = &io->cl;
bio->bi_io_vec = bio->bi_inline_vecs;
bch_bio_map(bio, NULL);
}
static void write_moving(struct closure *cl)
{
- struct search *s = container_of(cl, struct search, cl);
- struct moving_io *io = container_of(s, struct moving_io, s);
+ struct moving_io *io = container_of(cl, struct moving_io, cl);
+ struct data_insert_op *op = &io->op;
- if (!s->error) {
+ if (!op->error) {
moving_init(io);
- io->bio.bio.bi_sector = KEY_START(&io->w->key);
- s->op.lock = -1;
- s->op.write_prio = 1;
- s->op.cache_bio = &io->bio.bio;
+ io->bio.bio.bi_sector = KEY_START(&io->w->key);
+ op->write_prio = 1;
+ op->bio = &io->bio.bio;
- s->writeback = KEY_DIRTY(&io->w->key);
- s->op.csum = KEY_CSUM(&io->w->key);
+ op->writeback = KEY_DIRTY(&io->w->key);
+ op->csum = KEY_CSUM(&io->w->key);
- s->op.type = BTREE_REPLACE;
- bkey_copy(&s->op.replace, &io->w->key);
+ bkey_copy(&op->replace_key, &io->w->key);
+ op->replace = true;
- closure_init(&s->op.cl, cl);
- bch_insert_data(&s->op.cl);
+ closure_call(&op->cl, bch_data_insert, NULL, cl);
}
continue_at(cl, write_moving_finish, NULL);
@@ -118,21 +116,22 @@ static void write_moving(struct closure *cl)
static void read_moving_submit(struct closure *cl)
{
- struct search *s = container_of(cl, struct search, cl);
- struct moving_io *io = container_of(s, struct moving_io, s);
+ struct moving_io *io = container_of(cl, struct moving_io, cl);
struct bio *bio = &io->bio.bio;
- bch_submit_bbio(bio, s->op.c, &io->w->key, 0);
+ bch_submit_bbio(bio, io->op.c, &io->w->key, 0);
- continue_at(cl, write_moving, bch_gc_wq);
+ continue_at(cl, write_moving, system_wq);
}
-static void read_moving(struct closure *cl)
+static void read_moving(struct cache_set *c)
{
- struct cache_set *c = container_of(cl, struct cache_set, moving_gc);
struct keybuf_key *w;
struct moving_io *io;
struct bio *bio;
+ struct closure cl;
+
+ closure_init_stack(&cl);
/* XXX: if we error, background writeback could stall indefinitely */
@@ -150,8 +149,8 @@ static void read_moving(struct closure *cl)
w->private = io;
io->w = w;
- io->s.op.inode = KEY_INODE(&w->key);
- io->s.op.c = c;
+ io->op.inode = KEY_INODE(&w->key);
+ io->op.c = c;
moving_init(io);
bio = &io->bio.bio;
@@ -164,13 +163,8 @@ static void read_moving(struct closure *cl)
trace_bcache_gc_copy(&w->key);
- closure_call(&io->s.cl, read_moving_submit, NULL, &c->gc.cl);
-
- if (atomic_inc_return(&c->in_flight) >= 64) {
- closure_wait_event(&c->moving_gc_wait, cl,
- atomic_read(&c->in_flight) < 64);
- continue_at(cl, read_moving, bch_gc_wq);
- }
+ down(&c->moving_in_flight);
+ closure_call(&io->cl, read_moving_submit, NULL, &cl);
}
if (0) {
@@ -180,7 +174,7 @@ err: if (!IS_ERR_OR_NULL(w->private))
bch_keybuf_del(&c->moving_gc_keys, w);
}
- closure_return(cl);
+ closure_sync(&cl);
}
static bool bucket_cmp(struct bucket *l, struct bucket *r)
@@ -193,15 +187,14 @@ static unsigned bucket_heap_top(struct cache *ca)
return GC_SECTORS_USED(heap_peek(&ca->heap));
}
-void bch_moving_gc(struct closure *cl)
+void bch_moving_gc(struct cache_set *c)
{
- struct cache_set *c = container_of(cl, struct cache_set, gc.cl);
struct cache *ca;
struct bucket *b;
unsigned i;
if (!c->copy_gc_enabled)
- closure_return(cl);
+ return;
mutex_lock(&c->bucket_lock);
@@ -242,13 +235,11 @@ void bch_moving_gc(struct closure *cl)
c->moving_gc_keys.last_scanned = ZERO_KEY;
- closure_init(&c->moving_gc, cl);
- read_moving(&c->moving_gc);
-
- closure_return(cl);
+ read_moving(c);
}
void bch_moving_init_cache_set(struct cache_set *c)
{
bch_keybuf_init(&c->moving_gc_keys);
+ sema_init(&c->moving_in_flight, 64);
}
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index 71eb233b9ace..49ee1cff5a92 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -25,7 +25,7 @@
struct kmem_cache *bch_search_cache;
-static void check_should_skip(struct cached_dev *, struct search *);
+static void bch_data_insert_start(struct closure *);
/* Cgroup interface */
@@ -213,221 +213,79 @@ static void bio_csum(struct bio *bio, struct bkey *k)
/* Insert data into cache */
-static void bio_invalidate(struct closure *cl)
+static void bch_data_insert_keys(struct closure *cl)
{
- struct btree_op *op = container_of(cl, struct btree_op, cl);
- struct bio *bio = op->cache_bio;
-
- pr_debug("invalidating %i sectors from %llu",
- bio_sectors(bio), (uint64_t) bio->bi_sector);
-
- while (bio_sectors(bio)) {
- unsigned len = min(bio_sectors(bio), 1U << 14);
-
- if (bch_keylist_realloc(&op->keys, 0, op->c))
- goto out;
-
- bio->bi_sector += len;
- bio->bi_size -= len << 9;
-
- bch_keylist_add(&op->keys,
- &KEY(op->inode, bio->bi_sector, len));
- }
-
- op->insert_data_done = true;
- bio_put(bio);
-out:
- continue_at(cl, bch_journal, bcache_wq);
-}
-
-struct open_bucket {
- struct list_head list;
- struct task_struct *last;
- unsigned sectors_free;
- BKEY_PADDED(key);
-};
-
-void bch_open_buckets_free(struct cache_set *c)
-{
- struct open_bucket *b;
-
- while (!list_empty(&c->data_buckets)) {
- b = list_first_entry(&c->data_buckets,
- struct open_bucket, list);
- list_del(&b->list);
- kfree(b);
- }
-}
-
-int bch_open_buckets_alloc(struct cache_set *c)
-{
- int i;
-
- spin_lock_init(&c->data_bucket_lock);
-
- for (i = 0; i < 6; i++) {
- struct open_bucket *b = kzalloc(sizeof(*b), GFP_KERNEL);
- if (!b)
- return -ENOMEM;
-
- list_add(&b->list, &c->data_buckets);
- }
-
- return 0;
-}
-
-/*
- * We keep multiple buckets open for writes, and try to segregate different
- * write streams for better cache utilization: first we look for a bucket where
- * the last write to it was sequential with the current write, and failing that
- * we look for a bucket that was last used by the same task.
- *
- * The ideas is if you've got multiple tasks pulling data into the cache at the
- * same time, you'll get better cache utilization if you try to segregate their
- * data and preserve locality.
- *
- * For example, say you've starting Firefox at the same time you're copying a
- * bunch of files. Firefox will likely end up being fairly hot and stay in the
- * cache awhile, but the data you copied might not be; if you wrote all that
- * data to the same buckets it'd get invalidated at the same time.
- *
- * Both of those tasks will be doing fairly random IO so we can't rely on
- * detecting sequential IO to segregate their data, but going off of the task
- * should be a sane heuristic.
- */
-static struct open_bucket *pick_data_bucket(struct cache_set *c,
- const struct bkey *search,
- struct task_struct *task,
- struct bkey *alloc)
-{
- struct open_bucket *ret, *ret_task = NULL;
-
- list_for_each_entry_reverse(ret, &c->data_buckets, list)
- if (!bkey_cmp(&ret->key, search))
- goto found;
- else if (ret->last == task)
- ret_task = ret;
-
- ret = ret_task ?: list_first_entry(&c->data_buckets,
- struct open_bucket, list);
-found:
- if (!ret->sectors_free && KEY_PTRS(alloc)) {
- ret->sectors_free = c->sb.bucket_size;
- bkey_copy(&ret->key, alloc);
- bkey_init(alloc);
- }
-
- if (!ret->sectors_free)
- ret = NULL;
-
- return ret;
-}
-
-/*
- * Allocates some space in the cache to write to, and k to point to the newly
- * allocated space, and updates KEY_SIZE(k) and KEY_OFFSET(k) (to point to the
- * end of the newly allocated space).
- *
- * May allocate fewer sectors than @sectors, KEY_SIZE(k) indicates how many
- * sectors were actually allocated.
- *
- * If s->writeback is true, will not fail.
- */
-static bool bch_alloc_sectors(struct bkey *k, unsigned sectors,
- struct search *s)
-{
- struct cache_set *c = s->op.c;
- struct open_bucket *b;
- BKEY_PADDED(key) alloc;
- struct closure cl, *w = NULL;
- unsigned i;
-
- if (s->writeback) {
- closure_init_stack(&cl);
- w = &cl;
- }
+ struct data_insert_op *op = container_of(cl, struct data_insert_op, cl);
+ atomic_t *journal_ref = NULL;
+ struct bkey *replace_key = op->replace ? &op->replace_key : NULL;
+ int ret;
/*
- * We might have to allocate a new bucket, which we can't do with a
- * spinlock held. So if we have to allocate, we drop the lock, allocate
- * and then retry. KEY_PTRS() indicates whether alloc points to
- * allocated bucket(s).
+ * If we're looping, might already be waiting on
+ * another journal write - can't wait on more than one journal write at
+ * a time
+ *
+ * XXX: this looks wrong
*/
+#if 0
+ while (atomic_read(&s->cl.remaining) & CLOSURE_WAITING)
+ closure_sync(&s->cl);
+#endif
- bkey_init(&alloc.key);
- spin_lock(&c->data_bucket_lock);
-
- while (!(b = pick_data_bucket(c, k, s->task, &alloc.key))) {
- unsigned watermark = s->op.write_prio
- ? WATERMARK_MOVINGGC
- : WATERMARK_NONE;
-
- spin_unlock(&c->data_bucket_lock);
-
- if (bch_bucket_alloc_set(c, watermark, &alloc.key, 1, w))
- return false;
+ if (!op->replace)
+ journal_ref = bch_journal(op->c, &op->insert_keys,
+ op->flush_journal ? cl : NULL);
- spin_lock(&c->data_bucket_lock);
+ ret = bch_btree_insert(op->c, &op->insert_keys,
+ journal_ref, replace_key);
+ if (ret == -ESRCH) {
+ op->replace_collision = true;
+ } else if (ret) {
+ op->error = -ENOMEM;
+ op->insert_data_done = true;
}
- /*
- * If we had to allocate, we might race and not need to allocate the
- * second time we call find_data_bucket(). If we allocated a bucket but
- * didn't use it, drop the refcount bch_bucket_alloc_set() took:
- */
- if (KEY_PTRS(&alloc.key))
- __bkey_put(c, &alloc.key);
-
- for (i = 0; i < KEY_PTRS(&b->key); i++)
- EBUG_ON(ptr_stale(c, &b->key, i));
+ if (journal_ref)
+ atomic_dec_bug(journal_ref);
- /* Set up the pointer to the space we're allocating: */
+ if (!op->insert_data_done)
+ continue_at(cl, bch_data_insert_start, bcache_wq);
- for (i = 0; i < KEY_PTRS(&b->key); i++)
- k->ptr[i] = b->key.ptr[i];
+ bch_keylist_free(&op->insert_keys);
+ closure_return(cl);
+}
- sectors = min(sectors, b->sectors_free);
+static void bch_data_invalidate(struct closure *cl)
+{
+ struct data_insert_op *op = container_of(cl, struct data_insert_op, cl);
+ struct bio *bio = op->bio;
- SET_KEY_OFFSET(k, KEY_OFFSET(k) + sectors);
- SET_KEY_SIZE(k, sectors);
- SET_KEY_PTRS(k, KEY_PTRS(&b->key));
+ pr_debug("invalidating %i sectors from %llu",
+ bio_sectors(bio), (uint64_t) bio->bi_sector);
- /*
- * Move b to the end of the lru, and keep track of what this bucket was
- * last used for:
- */
- list_move_tail(&b->list, &c->data_buckets);
- bkey_copy_key(&b->key, k);
- b->last = s->task;
+ while (bio_sectors(bio)) {
+ unsigned sectors = min(bio_sectors(bio),
+ 1U << (KEY_SIZE_BITS - 1));
- b->sectors_free -= sectors;
+ if (bch_keylist_realloc(&op->insert_keys, 0, op->c))
+ goto out;
- for (i = 0; i < KEY_PTRS(&b->key); i++) {
- SET_PTR_OFFSET(&b->key, i, PTR_OFFSET(&b->key, i) + sectors);
+ bio->bi_sector += sectors;
+ bio->bi_size -= sectors << 9;
- atomic_long_add(sectors,
- &PTR_CACHE(c, &b->key, i)->sectors_written);
+ bch_keylist_add(&op->insert_keys,
+ &KEY(op->inode, bio->bi_sector, sectors));
}
- if (b->sectors_free < c->sb.block_size)
- b->sectors_free = 0;
-
- /*
- * k takes refcounts on the buckets it points to until it's inserted
- * into the btree, but if we're done with this bucket we just transfer
- * get_data_bucket()'s refcount.
- */
- if (b->sectors_free)
- for (i = 0; i < KEY_PTRS(&b->key); i++)
- atomic_inc(&PTR_BUCKET(c, &b->key, i)->pin);
-
- spin_unlock(&c->data_bucket_lock);
- return true;
+ op->insert_data_done = true;
+ bio_put(bio);
+out:
+ continue_at(cl, bch_data_insert_keys, bcache_wq);
}
-static void bch_insert_data_error(struct closure *cl)
+static void bch_data_insert_error(struct closure *cl)
{
- struct btree_op *op = container_of(cl, struct btree_op, cl);
+ struct data_insert_op *op = container_of(cl, struct data_insert_op, cl);
/*
* Our data write just errored, which means we've got a bunch of keys to
@@ -438,35 +296,34 @@ static void bch_insert_data_error(struct closure *cl)
* from the keys we'll accomplish just that.
*/
- struct bkey *src = op->keys.bottom, *dst = op->keys.bottom;
+ struct bkey *src = op->insert_keys.keys, *dst = op->insert_keys.keys;
- while (src != op->keys.top) {
+ while (src != op->insert_keys.top) {
struct bkey *n = bkey_next(src);
SET_KEY_PTRS(src, 0);
- bkey_copy(dst, src);
+ memmove(dst, src, bkey_bytes(src));
dst = bkey_next(dst);
src = n;
}
- op->keys.top = dst;
+ op->insert_keys.top = dst;
- bch_journal(cl);
+ bch_data_insert_keys(cl);
}
-static void bch_insert_data_endio(struct bio *bio, int error)
+static void bch_data_insert_endio(struct bio *bio, int error)
{
struct closure *cl = bio->bi_private;
- struct btree_op *op = container_of(cl, struct btree_op, cl);
- struct search *s = container_of(op, struct search, op);
+ struct data_insert_op *op = container_of(cl, struct data_insert_op, cl);
if (error) {
/* TODO: We could try to recover from this. */
- if (s->writeback)
- s->error = error;
- else if (s->write)
- set_closure_fn(cl, bch_insert_data_error, bcache_wq);
+ if (op->writeback)
+ op->error = error;
+ else if (!op->replace)
+ set_closure_fn(cl, bch_data_insert_error, bcache_wq);
else
set_closure_fn(cl, NULL, NULL);
}
@@ -474,18 +331,17 @@ static void bch_insert_data_endio(struct bio *bio, int error)
bch_bbio_endio(op->c, bio, error, "writing data to cache");
}
-static void bch_insert_data_loop(struct closure *cl)
+static void bch_data_insert_start(struct closure *cl)
{
- struct btree_op *op = container_of(cl, struct btree_op, cl);
- struct search *s = container_of(op, struct search, op);
- struct bio *bio = op->cache_bio, *n;
+ struct data_insert_op *op = container_of(cl, struct data_insert_op, cl);
+ struct bio *bio = op->bio, *n;
- if (op->skip)
- return bio_invalidate(cl);
+ if (op->bypass)
+ return bch_data_invalidate(cl);
if (atomic_sub_return(bio_sectors(bio), &op->c->sectors_to_gc) < 0) {
set_gc_sectors(op->c);
- bch_queue_gc(op->c);
+ wake_up_gc(op->c);
}
/*
@@ -497,29 +353,30 @@ static void bch_insert_data_loop(struct closure *cl)
do {
unsigned i;
struct bkey *k;
- struct bio_set *split = s->d
- ? s->d->bio_split : op->c->bio_split;
+ struct bio_set *split = op->c->bio_split;
/* 1 for the device pointer and 1 for the chksum */
- if (bch_keylist_realloc(&op->keys,
+ if (bch_keylist_realloc(&op->insert_keys,
1 + (op->csum ? 1 : 0),
op->c))
- continue_at(cl, bch_journal, bcache_wq);
+ continue_at(cl, bch_data_insert_keys, bcache_wq);
- k = op->keys.top;
+ k = op->insert_keys.top;
bkey_init(k);
SET_KEY_INODE(k, op->inode);
SET_KEY_OFFSET(k, bio->bi_sector);
- if (!bch_alloc_sectors(k, bio_sectors(bio), s))
+ if (!bch_alloc_sectors(op->c, k, bio_sectors(bio),
+ op->write_point, op->write_prio,
+ op->writeback))
goto err;
n = bch_bio_split(bio, KEY_SIZE(k), GFP_NOIO, split);
- n->bi_end_io = bch_insert_data_endio;
+ n->bi_end_io = bch_data_insert_endio;
n->bi_private = cl;
- if (s->writeback) {
+ if (op->writeback) {
SET_KEY_DIRTY(k, true);
for (i = 0; i < KEY_PTRS(k); i++)
@@ -532,17 +389,17 @@ static void bch_insert_data_loop(struct closure *cl)
bio_csum(n, k);
trace_bcache_cache_insert(k);
- bch_keylist_push(&op->keys);
+ bch_keylist_push(&op->insert_keys);
n->bi_rw |= REQ_WRITE;
bch_submit_bbio(n, op->c, k, 0);
} while (n != bio);
op->insert_data_done = true;
- continue_at(cl, bch_journal, bcache_wq);
+ continue_at(cl, bch_data_insert_keys, bcache_wq);
err:
/* bch_alloc_sectors() blocks if s->writeback = true */
- BUG_ON(s->writeback);
+ BUG_ON(op->writeback);
/*
* But if it's not a writeback write we'd rather just bail out if
@@ -550,15 +407,15 @@ err:
* we might be starving btree writes for gc or something.
*/
- if (s->write) {
+ if (!op->replace) {
/*
* Writethrough write: We can't complete the write until we've
* updated the index. But we don't want to delay the write while
* we wait for buckets to be freed up, so just invalidate the
* rest of the write.
*/
- op->skip = true;
- return bio_invalidate(cl);
+ op->bypass = true;
+ return bch_data_invalidate(cl);
} else {
/*
* From a cache miss, we can just insert the keys for the data
@@ -567,15 +424,15 @@ err:
op->insert_data_done = true;
bio_put(bio);
- if (!bch_keylist_empty(&op->keys))
- continue_at(cl, bch_journal, bcache_wq);
+ if (!bch_keylist_empty(&op->insert_keys))
+ continue_at(cl, bch_data_insert_keys, bcache_wq);
else
closure_return(cl);
}
}
/**
- * bch_insert_data - stick some data in the cache
+ * bch_data_insert - stick some data in the cache
*
* This is the starting point for any data to end up in a cache device; it could
* be from a normal write, or a writeback write, or a write to a flash only
@@ -587,56 +444,179 @@ err:
* data is written it calls bch_journal, and after the keys have been added to
* the next journal write they're inserted into the btree.
*
- * It inserts the data in op->cache_bio; bi_sector is used for the key offset,
+ * It inserts the data in s->cache_bio; bi_sector is used for the key offset,
* and op->inode is used for the key inode.
*
- * If op->skip is true, instead of inserting the data it invalidates the region
- * of the cache represented by op->cache_bio and op->inode.
+ * If s->bypass is true, instead of inserting the data it invalidates the
+ * region of the cache represented by s->cache_bio and op->inode.
*/
-void bch_insert_data(struct closure *cl)
+void bch_data_insert(struct closure *cl)
{
- struct btree_op *op = container_of(cl, struct btree_op, cl);
+ struct data_insert_op *op = container_of(cl, struct data_insert_op, cl);
+
+ trace_bcache_write(op->bio, op->writeback, op->bypass);
- bch_keylist_init(&op->keys);
- bio_get(op->cache_bio);
- bch_insert_data_loop(cl);
+ bch_keylist_init(&op->insert_keys);
+ bio_get(op->bio);
+ bch_data_insert_start(cl);
}
-void bch_btree_insert_async(struct closure *cl)
+/* Congested? */
+
+unsigned bch_get_congested(struct cache_set *c)
{
- struct btree_op *op = container_of(cl, struct btree_op, cl);
- struct search *s = container_of(op, struct search, op);
+ int i;
+ long rand;
- if (bch_btree_insert(op, op->c)) {
- s->error = -ENOMEM;
- op->insert_data_done = true;
- }
+ if (!c->congested_read_threshold_us &&
+ !c->congested_write_threshold_us)
+ return 0;
+
+ i = (local_clock_us() - c->congested_last_us) / 1024;
+ if (i < 0)
+ return 0;
+
+ i += atomic_read(&c->congested);
+ if (i >= 0)
+ return 0;
- if (op->insert_data_done) {
- bch_keylist_free(&op->keys);
- closure_return(cl);
- } else
- continue_at(cl, bch_insert_data_loop, bcache_wq);
+ i += CONGESTED_MAX;
+
+ if (i > 0)
+ i = fract_exp_two(i, 6);
+
+ rand = get_random_int();
+ i -= bitmap_weight(&rand, BITS_PER_LONG);
+
+ return i > 0 ? i : 1;
}
-/* Common code for the make_request functions */
+static void add_sequential(struct task_struct *t)
+{
+ ewma_add(t->sequential_io_avg,
+ t->sequential_io, 8, 0);
-static void request_endio(struct bio *bio, int error)
+ t->sequential_io = 0;
+}
+
+static struct hlist_head *iohash(struct cached_dev *dc, uint64_t k)
{
- struct closure *cl = bio->bi_private;
+ return &dc->io_hash[hash_64(k, RECENT_IO_BITS)];
+}
- if (error) {
- struct search *s = container_of(cl, struct search, cl);
- s->error = error;
- /* Only cache read errors are recoverable */
- s->recoverable = false;
+static bool check_should_bypass(struct cached_dev *dc, struct bio *bio)
+{
+ struct cache_set *c = dc->disk.c;
+ unsigned mode = cache_mode(dc, bio);
+ unsigned sectors, congested = bch_get_congested(c);
+ struct task_struct *task = current;
+ struct io *i;
+
+ if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) ||
+ c->gc_stats.in_use > CUTOFF_CACHE_ADD ||
+ (bio->bi_rw & REQ_DISCARD))
+ goto skip;
+
+ if (mode == CACHE_MODE_NONE ||
+ (mode == CACHE_MODE_WRITEAROUND &&
+ (bio->bi_rw & REQ_WRITE)))
+ goto skip;
+
+ if (bio->bi_sector & (c->sb.block_size - 1) ||
+ bio_sectors(bio) & (c->sb.block_size - 1)) {
+ pr_debug("skipping unaligned io");
+ goto skip;
}
- bio_put(bio);
- closure_put(cl);
+ if (bypass_torture_test(dc)) {
+ if ((get_random_int() & 3) == 3)
+ goto skip;
+ else
+ goto rescale;
+ }
+
+ if (!congested && !dc->sequential_cutoff)
+ goto rescale;
+
+ if (!congested &&
+ mode == CACHE_MODE_WRITEBACK &&
+ (bio->bi_rw & REQ_WRITE) &&
+ (bio->bi_rw & REQ_SYNC))
+ goto rescale;
+
+ spin_lock(&dc->io_lock);
+
+ hlist_for_each_entry(i, iohash(dc, bio->bi_sector), hash)
+ if (i->last == bio->bi_sector &&
+ time_before(jiffies, i->jiffies))
+ goto found;
+
+ i = list_first_entry(&dc->io_lru, struct io, lru);
+
+ add_sequential(task);
+ i->sequential = 0;
+found:
+ if (i->sequential + bio->bi_size > i->sequential)
+ i->sequential += bio->bi_size;
+
+ i->last = bio_end_sector(bio);
+ i->jiffies = jiffies + msecs_to_jiffies(5000);
+ task->sequential_io = i->sequential;
+
+ hlist_del(&i->hash);
+ hlist_add_head(&i->hash, iohash(dc, i->last));
+ list_move_tail(&i->lru, &dc->io_lru);
+
+ spin_unlock(&dc->io_lock);
+
+ sectors = max(task->sequential_io,
+ task->sequential_io_avg) >> 9;
+
+ if (dc->sequential_cutoff &&
+ sectors >= dc->sequential_cutoff >> 9) {
+ trace_bcache_bypass_sequential(bio);
+ goto skip;
+ }
+
+ if (congested && sectors >= congested) {
+ trace_bcache_bypass_congested(bio);
+ goto skip;
+ }
+
+rescale:
+ bch_rescale_priorities(c, bio_sectors(bio));
+ return false;
+skip:
+ bch_mark_sectors_bypassed(c, dc, bio_sectors(bio));
+ return true;
}
-void bch_cache_read_endio(struct bio *bio, int error)
+/* Cache lookup */
+
+struct search {
+ /* Stack frame for bio_complete */
+ struct closure cl;
+
+ struct bcache_device *d;
+
+ struct bbio bio;
+ struct bio *orig_bio;
+ struct bio *cache_miss;
+
+ unsigned insert_bio_sectors;
+
+ unsigned recoverable:1;
+ unsigned unaligned_bvec:1;
+ unsigned write:1;
+ unsigned read_dirty_data:1;
+
+ unsigned long start_time;
+
+ struct btree_op op;
+ struct data_insert_op iop;
+};
+
+static void bch_cache_read_endio(struct bio *bio, int error)
{
struct bbio *b = container_of(bio, struct bbio, bio);
struct closure *cl = bio->bi_private;
@@ -650,13 +630,113 @@ void bch_cache_read_endio(struct bio *bio, int error)
*/
if (error)
- s->error = error;
- else if (ptr_stale(s->op.c, &b->key, 0)) {
- atomic_long_inc(&s->op.c->cache_read_races);
- s->error = -EINTR;
+ s->iop.error = error;
+ else if (ptr_stale(s->iop.c, &b->key, 0)) {
+ atomic_long_inc(&s->iop.c->cache_read_races);
+ s->iop.error = -EINTR;
}
- bch_bbio_endio(s->op.c, bio, error, "reading from cache");
+ bch_bbio_endio(s->iop.c, bio, error, "reading from cache");
+}
+
+/*
+ * Read from a single key, handling the initial cache miss if the key starts in
+ * the middle of the bio
+ */
+static int cache_lookup_fn(struct btree_op *op, struct btree *b, struct bkey *k)
+{
+ struct search *s = container_of(op, struct search, op);
+ struct bio *n, *bio = &s->bio.bio;
+ struct bkey *bio_key;
+ unsigned ptr;
+
+ if (bkey_cmp(k, &KEY(s->iop.inode, bio->bi_sector, 0)) <= 0)
+ return MAP_CONTINUE;
+
+ if (KEY_INODE(k) != s->iop.inode ||
+ KEY_START(k) > bio->bi_sector) {
+ unsigned bio_sectors = bio_sectors(bio);
+ unsigned sectors = KEY_INODE(k) == s->iop.inode
+ ? min_t(uint64_t, INT_MAX,
+ KEY_START(k) - bio->bi_sector)
+ : INT_MAX;
+
+ int ret = s->d->cache_miss(b, s, bio, sectors);
+ if (ret != MAP_CONTINUE)
+ return ret;
+
+ /* if this was a complete miss we shouldn't get here */
+ BUG_ON(bio_sectors <= sectors);
+ }
+
+ if (!KEY_SIZE(k))
+ return MAP_CONTINUE;
+
+ /* XXX: figure out best pointer - for multiple cache devices */
+ ptr = 0;
+
+ PTR_BUCKET(b->c, k, ptr)->prio = INITIAL_PRIO;
+
+ if (KEY_DIRTY(k))
+ s->read_dirty_data = true;
+
+ n = bch_bio_split(bio, min_t(uint64_t, INT_MAX,
+ KEY_OFFSET(k) - bio->bi_sector),
+ GFP_NOIO, s->d->bio_split);
+
+ bio_key = &container_of(n, struct bbio, bio)->key;
+ bch_bkey_copy_single_ptr(bio_key, k, ptr);
+
+ bch_cut_front(&KEY(s->iop.inode, n->bi_sector, 0), bio_key);
+ bch_cut_back(&KEY(s->iop.inode, bio_end_sector(n), 0), bio_key);
+
+ n->bi_end_io = bch_cache_read_endio;
+ n->bi_private = &s->cl;
+
+ /*
+ * The bucket we're reading from might be reused while our bio
+ * is in flight, and we could then end up reading the wrong
+ * data.
+ *
+ * We guard against this by checking (in cache_read_endio()) if
+ * the pointer is stale again; if so, we treat it as an error
+ * and reread from the backing device (but we don't pass that
+ * error up anywhere).
+ */
+
+ __bch_submit_bbio(n, b->c);
+ return n == bio ? MAP_DONE : MAP_CONTINUE;
+}
+
+static void cache_lookup(struct closure *cl)
+{
+ struct search *s = container_of(cl, struct search, iop.cl);
+ struct bio *bio = &s->bio.bio;
+
+ int ret = bch_btree_map_keys(&s->op, s->iop.c,
+ &KEY(s->iop.inode, bio->bi_sector, 0),
+ cache_lookup_fn, MAP_END_KEY);
+ if (ret == -EAGAIN)
+ continue_at(cl, cache_lookup, bcache_wq);
+
+ closure_return(cl);
+}
+
+/* Common code for the make_request functions */
+
+static void request_endio(struct bio *bio, int error)
+{
+ struct closure *cl = bio->bi_private;
+
+ if (error) {
+ struct search *s = container_of(cl, struct search, cl);
+ s->iop.error = error;
+ /* Only cache read errors are recoverable */
+ s->recoverable = false;
+ }
+
+ bio_put(bio);
+ closure_put(cl);
}
static void bio_complete(struct search *s)
@@ -670,8 +750,8 @@ static void bio_complete(struct search *s)
part_stat_add(cpu, &s->d->disk->part0, ticks[rw], duration);
part_stat_unlock();
- trace_bcache_request_end(s, s->orig_bio);
- bio_endio(s->orig_bio, s->error);
+ trace_bcache_request_end(s->d, s->orig_bio);
+ bio_endio(s->orig_bio, s->iop.error);
s->orig_bio = NULL;
}
}
@@ -691,8 +771,8 @@ static void search_free(struct closure *cl)
struct search *s = container_of(cl, struct search, cl);
bio_complete(s);
- if (s->op.cache_bio)
- bio_put(s->op.cache_bio);
+ if (s->iop.bio)
+ bio_put(s->iop.bio);
if (s->unaligned_bvec)
mempool_free(s->bio.bio.bi_io_vec, s->d->unaligned_bvec);
@@ -704,20 +784,21 @@ static void search_free(struct closure *cl)
static struct search *search_alloc(struct bio *bio, struct bcache_device *d)
{
struct bio_vec *bv;
- struct search *s = mempool_alloc(d->c->search, GFP_NOIO);
- memset(s, 0, offsetof(struct search, op.keys));
+ struct search *s;
+
+ s = mempool_alloc(d->c->search, GFP_NOIO);
+ memset(s, 0, offsetof(struct search, iop.insert_keys));
__closure_init(&s->cl, NULL);
- s->op.inode = d->id;
- s->op.c = d->c;
+ s->iop.inode = d->id;
+ s->iop.c = d->c;
s->d = d;
s->op.lock = -1;
- s->task = current;
+ s->iop.write_point = hash_long((unsigned long) current, 16);
s->orig_bio = bio;
s->write = (bio->bi_rw & REQ_WRITE) != 0;
- s->op.flush_journal = (bio->bi_rw & (REQ_FLUSH|REQ_FUA)) != 0;
- s->op.skip = (bio->bi_rw & REQ_DISCARD) != 0;
+ s->iop.flush_journal = (bio->bi_rw & (REQ_FLUSH|REQ_FUA)) != 0;
s->recoverable = 1;
s->start_time = jiffies;
do_bio_hook(s);
@@ -734,18 +815,6 @@ static struct search *search_alloc(struct bio *bio, struct bcache_device *d)
return s;
}
-static void btree_read_async(struct closure *cl)
-{
- struct btree_op *op = container_of(cl, struct btree_op, cl);
-
- int ret = btree_root(search_recurse, op->c, op);
-
- if (ret == -EAGAIN)
- continue_at(cl, btree_read_async, bcache_wq);
-
- closure_return(cl);
-}
-
/* Cached devices */
static void cached_dev_bio_complete(struct closure *cl)
@@ -759,27 +828,28 @@ static void cached_dev_bio_complete(struct closure *cl)
/* Process reads */
-static void cached_dev_read_complete(struct closure *cl)
+static void cached_dev_cache_miss_done(struct closure *cl)
{
struct search *s = container_of(cl, struct search, cl);
- if (s->op.insert_collision)
- bch_mark_cache_miss_collision(s);
+ if (s->iop.replace_collision)
+ bch_mark_cache_miss_collision(s->iop.c, s->d);
- if (s->op.cache_bio) {
+ if (s->iop.bio) {
int i;
struct bio_vec *bv;
- __bio_for_each_segment(bv, s->op.cache_bio, i, 0)
+ bio_for_each_segment_all(bv, s->iop.bio, i)
__free_page(bv->bv_page);
}
cached_dev_bio_complete(cl);
}
-static void request_read_error(struct closure *cl)
+static void cached_dev_read_error(struct closure *cl)
{
struct search *s = container_of(cl, struct search, cl);
+ struct bio *bio = &s->bio.bio;
struct bio_vec *bv;
int i;
@@ -787,7 +857,7 @@ static void request_read_error(struct closure *cl)
/* Retry from the backing device: */
trace_bcache_read_retry(s->orig_bio);
- s->error = 0;
+ s->iop.error = 0;
bv = s->bio.bio.bi_io_vec;
do_bio_hook(s);
s->bio.bio.bi_io_vec = bv;
@@ -803,146 +873,148 @@ static void request_read_error(struct closure *cl)
/* XXX: invalidate cache */
- closure_bio_submit(&s->bio.bio, &s->cl, s->d);
+ closure_bio_submit(bio, cl, s->d);
}
- continue_at(cl, cached_dev_read_complete, NULL);
+ continue_at(cl, cached_dev_cache_miss_done, NULL);
}
-static void request_read_done(struct closure *cl)
+static void cached_dev_read_done(struct closure *cl)
{
struct search *s = container_of(cl, struct search, cl);
struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
/*
- * s->cache_bio != NULL implies that we had a cache miss; cache_bio now
- * contains data ready to be inserted into the cache.
+ * We had a cache miss; cache_bio now contains data ready to be inserted
+ * into the cache.
*
* First, we copy the data we just read from cache_bio's bounce buffers
* to the buffers the original bio pointed to:
*/
- if (s->op.cache_bio) {
- bio_reset(s->op.cache_bio);
- s->op.cache_bio->bi_sector = s->cache_miss->bi_sector;
- s->op.cache_bio->bi_bdev = s->cache_miss->bi_bdev;
- s->op.cache_bio->bi_size = s->cache_bio_sectors << 9;
- bch_bio_map(s->op.cache_bio, NULL);
+ if (s->iop.bio) {
+ bio_reset(s->iop.bio);
+ s->iop.bio->bi_sector = s->cache_miss->bi_sector;
+ s->iop.bio->bi_bdev = s->cache_miss->bi_bdev;
+ s->iop.bio->bi_size = s->insert_bio_sectors << 9;
+ bch_bio_map(s->iop.bio, NULL);
- bio_copy_data(s->cache_miss, s->op.cache_bio);
+ bio_copy_data(s->cache_miss, s->iop.bio);
bio_put(s->cache_miss);
s->cache_miss = NULL;
}
- if (verify(dc, &s->bio.bio) && s->recoverable)
- bch_data_verify(s);
+ if (verify(dc, &s->bio.bio) && s->recoverable &&
+ !s->unaligned_bvec && !s->read_dirty_data)
+ bch_data_verify(dc, s->orig_bio);
bio_complete(s);
- if (s->op.cache_bio &&
- !test_bit(CACHE_SET_STOPPING, &s->op.c->flags)) {
- s->op.type = BTREE_REPLACE;
- closure_call(&s->op.cl, bch_insert_data, NULL, cl);
+ if (s->iop.bio &&
+ !test_bit(CACHE_SET_STOPPING, &s->iop.c->flags)) {
+ BUG_ON(!s->iop.replace);
+ closure_call(&s->iop.cl, bch_data_insert, NULL, cl);
}
- continue_at(cl, cached_dev_read_complete, NULL);
+ continue_at(cl, cached_dev_cache_miss_done, NULL);
}
-static void request_read_done_bh(struct closure *cl)
+static void cached_dev_read_done_bh(struct closure *cl)
{
struct search *s = container_of(cl, struct search, cl);
struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
- bch_mark_cache_accounting(s, !s->cache_miss, s->op.skip);
- trace_bcache_read(s->orig_bio, !s->cache_miss, s->op.skip);
+ bch_mark_cache_accounting(s->iop.c, s->d,
+ !s->cache_miss, s->iop.bypass);
+ trace_bcache_read(s->orig_bio, !s->cache_miss, s->iop.bypass);
- if (s->error)
- continue_at_nobarrier(cl, request_read_error, bcache_wq);
- else if (s->op.cache_bio || verify(dc, &s->bio.bio))
- continue_at_nobarrier(cl, request_read_done, bcache_wq);
+ if (s->iop.error)
+ continue_at_nobarrier(cl, cached_dev_read_error, bcache_wq);
+ else if (s->iop.bio || verify(dc, &s->bio.bio))
+ continue_at_nobarrier(cl, cached_dev_read_done, bcache_wq);
else
- continue_at_nobarrier(cl, cached_dev_read_complete, NULL);
+ continue_at_nobarrier(cl, cached_dev_bio_complete, NULL);
}
static int cached_dev_cache_miss(struct btree *b, struct search *s,
struct bio *bio, unsigned sectors)
{
- int ret = 0;
- unsigned reada;
+ int ret = MAP_CONTINUE;
+ unsigned reada = 0;
struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
- struct bio *miss;
-
- miss = bch_bio_split(bio, sectors, GFP_NOIO, s->d->bio_split);
- if (miss == bio)
- s->op.lookup_done = true;
+ struct bio *miss, *cache_bio;
- miss->bi_end_io = request_endio;
- miss->bi_private = &s->cl;
-
- if (s->cache_miss || s->op.skip)
+ if (s->cache_miss || s->iop.bypass) {
+ miss = bch_bio_split(bio, sectors, GFP_NOIO, s->d->bio_split);
+ ret = miss == bio ? MAP_DONE : MAP_CONTINUE;
goto out_submit;
-
- if (miss != bio ||
- (bio->bi_rw & REQ_RAHEAD) ||
- (bio->bi_rw & REQ_META) ||
- s->op.c->gc_stats.in_use >= CUTOFF_CACHE_READA)
- reada = 0;
- else {
- reada = min(dc->readahead >> 9,
- sectors - bio_sectors(miss));
-
- if (bio_end_sector(miss) + reada > bdev_sectors(miss->bi_bdev))
- reada = bdev_sectors(miss->bi_bdev) -
- bio_end_sector(miss);
}
- s->cache_bio_sectors = bio_sectors(miss) + reada;
- s->op.cache_bio = bio_alloc_bioset(GFP_NOWAIT,
- DIV_ROUND_UP(s->cache_bio_sectors, PAGE_SECTORS),
- dc->disk.bio_split);
+ if (!(bio->bi_rw & REQ_RAHEAD) &&
+ !(bio->bi_rw & REQ_META) &&
+ s->iop.c->gc_stats.in_use < CUTOFF_CACHE_READA)
+ reada = min_t(sector_t, dc->readahead >> 9,
+ bdev_sectors(bio->bi_bdev) - bio_end_sector(bio));
- if (!s->op.cache_bio)
- goto out_submit;
+ s->insert_bio_sectors = min(sectors, bio_sectors(bio) + reada);
- s->op.cache_bio->bi_sector = miss->bi_sector;
- s->op.cache_bio->bi_bdev = miss->bi_bdev;
- s->op.cache_bio->bi_size = s->cache_bio_sectors << 9;
+ s->iop.replace_key = KEY(s->iop.inode,
+ bio->bi_sector + s->insert_bio_sectors,
+ s->insert_bio_sectors);
- s->op.cache_bio->bi_end_io = request_endio;
- s->op.cache_bio->bi_private = &s->cl;
+ ret = bch_btree_insert_check_key(b, &s->op, &s->iop.replace_key);
+ if (ret)
+ return ret;
+
+ s->iop.replace = true;
+
+ miss = bch_bio_split(bio, sectors, GFP_NOIO, s->d->bio_split);
/* btree_search_recurse()'s btree iterator is no good anymore */
- ret = -EINTR;
- if (!bch_btree_insert_check_key(b, &s->op, s->op.cache_bio))
- goto out_put;
+ ret = miss == bio ? MAP_DONE : -EINTR;
+
+ cache_bio = bio_alloc_bioset(GFP_NOWAIT,
+ DIV_ROUND_UP(s->insert_bio_sectors, PAGE_SECTORS),
+ dc->disk.bio_split);
+ if (!cache_bio)
+ goto out_submit;
+
+ cache_bio->bi_sector = miss->bi_sector;
+ cache_bio->bi_bdev = miss->bi_bdev;
+ cache_bio->bi_size = s->insert_bio_sectors << 9;
+
+ cache_bio->bi_end_io = request_endio;
+ cache_bio->bi_private = &s->cl;
- bch_bio_map(s->op.cache_bio, NULL);
- if (bio_alloc_pages(s->op.cache_bio, __GFP_NOWARN|GFP_NOIO))
+ bch_bio_map(cache_bio, NULL);
+ if (bio_alloc_pages(cache_bio, __GFP_NOWARN|GFP_NOIO))
goto out_put;
- s->cache_miss = miss;
- bio_get(s->op.cache_bio);
+ if (reada)
+ bch_mark_cache_readahead(s->iop.c, s->d);
- closure_bio_submit(s->op.cache_bio, &s->cl, s->d);
+ s->cache_miss = miss;
+ s->iop.bio = cache_bio;
+ bio_get(cache_bio);
+ closure_bio_submit(cache_bio, &s->cl, s->d);
return ret;
out_put:
- bio_put(s->op.cache_bio);
- s->op.cache_bio = NULL;
+ bio_put(cache_bio);
out_submit:
+ miss->bi_end_io = request_endio;
+ miss->bi_private = &s->cl;
closure_bio_submit(miss, &s->cl, s->d);
return ret;
}
-static void request_read(struct cached_dev *dc, struct search *s)
+static void cached_dev_read(struct cached_dev *dc, struct search *s)
{
struct closure *cl = &s->cl;
- check_should_skip(dc, s);
- closure_call(&s->op.cl, btree_read_async, NULL, cl);
-
- continue_at(cl, request_read_done_bh, NULL);
+ closure_call(&s->iop.cl, cache_lookup, NULL, cl);
+ continue_at(cl, cached_dev_read_done_bh, NULL);
}
/* Process writes */
@@ -956,45 +1028,50 @@ static void cached_dev_write_complete(struct closure *cl)
cached_dev_bio_complete(cl);
}
-static void request_write(struct cached_dev *dc, struct search *s)
+static void cached_dev_write(struct cached_dev *dc, struct search *s)
{
struct closure *cl = &s->cl;
struct bio *bio = &s->bio.bio;
- struct bkey start, end;
- start = KEY(dc->disk.id, bio->bi_sector, 0);
- end = KEY(dc->disk.id, bio_end_sector(bio), 0);
+ struct bkey start = KEY(dc->disk.id, bio->bi_sector, 0);
+ struct bkey end = KEY(dc->disk.id, bio_end_sector(bio), 0);
- bch_keybuf_check_overlapping(&s->op.c->moving_gc_keys, &start, &end);
+ bch_keybuf_check_overlapping(&s->iop.c->moving_gc_keys, &start, &end);
- check_should_skip(dc, s);
down_read_non_owner(&dc->writeback_lock);
-
if (bch_keybuf_check_overlapping(&dc->writeback_keys, &start, &end)) {
- s->op.skip = false;
- s->writeback = true;
+ /*
+ * We overlap with some dirty data undergoing background
+ * writeback, force this write to writeback
+ */
+ s->iop.bypass = false;
+ s->iop.writeback = true;
}
+ /*
+ * Discards aren't _required_ to do anything, so skipping if
+ * check_overlapping returned true is ok
+ *
+ * But check_overlapping drops dirty keys for which io hasn't started,
+ * so we still want to call it.
+ */
if (bio->bi_rw & REQ_DISCARD)
- goto skip;
+ s->iop.bypass = true;
if (should_writeback(dc, s->orig_bio,
cache_mode(dc, bio),
- s->op.skip)) {
- s->op.skip = false;
- s->writeback = true;
+ s->iop.bypass)) {
+ s->iop.bypass = false;
+ s->iop.writeback = true;
}
- if (s->op.skip)
- goto skip;
-
- trace_bcache_write(s->orig_bio, s->writeback, s->op.skip);
+ if (s->iop.bypass) {
+ s->iop.bio = s->orig_bio;
+ bio_get(s->iop.bio);
- if (!s->writeback) {
- s->op.cache_bio = bio_clone_bioset(bio, GFP_NOIO,
- dc->disk.bio_split);
-
- closure_bio_submit(bio, cl, s->d);
- } else {
+ if (!(bio->bi_rw & REQ_DISCARD) ||
+ blk_queue_discard(bdev_get_queue(dc->bdev)))
+ closure_bio_submit(bio, cl, s->d);
+ } else if (s->iop.writeback) {
bch_writeback_add(dc);
if (bio->bi_rw & REQ_FLUSH) {
@@ -1009,38 +1086,28 @@ static void request_write(struct cached_dev *dc, struct search *s)
closure_bio_submit(flush, cl, s->d);
} else {
- s->op.cache_bio = bio;
+ s->iop.bio = bio;
}
- }
-out:
- closure_call(&s->op.cl, bch_insert_data, NULL, cl);
- continue_at(cl, cached_dev_write_complete, NULL);
-skip:
- s->op.skip = true;
- s->op.cache_bio = s->orig_bio;
- bio_get(s->op.cache_bio);
+ } else {
+ s->iop.bio = bio_clone_bioset(bio, GFP_NOIO,
+ dc->disk.bio_split);
- if ((bio->bi_rw & REQ_DISCARD) &&
- !blk_queue_discard(bdev_get_queue(dc->bdev)))
- goto out;
+ closure_bio_submit(bio, cl, s->d);
+ }
- closure_bio_submit(bio, cl, s->d);
- goto out;
+ closure_call(&s->iop.cl, bch_data_insert, NULL, cl);
+ continue_at(cl, cached_dev_write_complete, NULL);
}
-static void request_nodata(struct cached_dev *dc, struct search *s)
+static void cached_dev_nodata(struct closure *cl)
{
- struct closure *cl = &s->cl;
+ struct search *s = container_of(cl, struct search, cl);
struct bio *bio = &s->bio.bio;
- if (bio->bi_rw & REQ_DISCARD) {
- request_write(dc, s);
- return;
- }
-
- if (s->op.flush_journal)
- bch_journal_meta(s->op.c, cl);
+ if (s->iop.flush_journal)
+ bch_journal_meta(s->iop.c, cl);
+ /* If it's a flush, we send the flush to the backing device too */
closure_bio_submit(bio, cl, s->d);
continue_at(cl, cached_dev_bio_complete, NULL);
@@ -1048,134 +1115,6 @@ static void request_nodata(struct cached_dev *dc, struct search *s)
/* Cached devices - read & write stuff */
-unsigned bch_get_congested(struct cache_set *c)
-{
- int i;
- long rand;
-
- if (!c->congested_read_threshold_us &&
- !c->congested_write_threshold_us)
- return 0;
-
- i = (local_clock_us() - c->congested_last_us) / 1024;
- if (i < 0)
- return 0;
-
- i += atomic_read(&c->congested);
- if (i >= 0)
- return 0;
-
- i += CONGESTED_MAX;
-
- if (i > 0)
- i = fract_exp_two(i, 6);
-
- rand = get_random_int();
- i -= bitmap_weight(&rand, BITS_PER_LONG);
-
- return i > 0 ? i : 1;
-}
-
-static void add_sequential(struct task_struct *t)
-{
- ewma_add(t->sequential_io_avg,
- t->sequential_io, 8, 0);
-
- t->sequential_io = 0;
-}
-
-static struct hlist_head *iohash(struct cached_dev *dc, uint64_t k)
-{
- return &dc->io_hash[hash_64(k, RECENT_IO_BITS)];
-}
-
-static void check_should_skip(struct cached_dev *dc, struct search *s)
-{
- struct cache_set *c = s->op.c;
- struct bio *bio = &s->bio.bio;
- unsigned mode = cache_mode(dc, bio);
- unsigned sectors, congested = bch_get_congested(c);
-
- if (atomic_read(&dc->disk.detaching) ||
- c->gc_stats.in_use > CUTOFF_CACHE_ADD ||
- (bio->bi_rw & REQ_DISCARD))
- goto skip;
-
- if (mode == CACHE_MODE_NONE ||
- (mode == CACHE_MODE_WRITEAROUND &&
- (bio->bi_rw & REQ_WRITE)))
- goto skip;
-
- if (bio->bi_sector & (c->sb.block_size - 1) ||
- bio_sectors(bio) & (c->sb.block_size - 1)) {
- pr_debug("skipping unaligned io");
- goto skip;
- }
-
- if (!congested && !dc->sequential_cutoff)
- goto rescale;
-
- if (!congested &&
- mode == CACHE_MODE_WRITEBACK &&
- (bio->bi_rw & REQ_WRITE) &&
- (bio->bi_rw & REQ_SYNC))
- goto rescale;
-
- if (dc->sequential_merge) {
- struct io *i;
-
- spin_lock(&dc->io_lock);
-
- hlist_for_each_entry(i, iohash(dc, bio->bi_sector), hash)
- if (i->last == bio->bi_sector &&
- time_before(jiffies, i->jiffies))
- goto found;
-
- i = list_first_entry(&dc->io_lru, struct io, lru);
-
- add_sequential(s->task);
- i->sequential = 0;
-found:
- if (i->sequential + bio->bi_size > i->sequential)
- i->sequential += bio->bi_size;
-
- i->last = bio_end_sector(bio);
- i->jiffies = jiffies + msecs_to_jiffies(5000);
- s->task->sequential_io = i->sequential;
-
- hlist_del(&i->hash);
- hlist_add_head(&i->hash, iohash(dc, i->last));
- list_move_tail(&i->lru, &dc->io_lru);
-
- spin_unlock(&dc->io_lock);
- } else {
- s->task->sequential_io = bio->bi_size;
-
- add_sequential(s->task);
- }
-
- sectors = max(s->task->sequential_io,
- s->task->sequential_io_avg) >> 9;
-
- if (dc->sequential_cutoff &&
- sectors >= dc->sequential_cutoff >> 9) {
- trace_bcache_bypass_sequential(s->orig_bio);
- goto skip;
- }
-
- if (congested && sectors >= congested) {
- trace_bcache_bypass_congested(s->orig_bio);
- goto skip;
- }
-
-rescale:
- bch_rescale_priorities(c, bio_sectors(bio));
- return;
-skip:
- bch_mark_sectors_bypassed(s, bio_sectors(bio));
- s->op.skip = true;
-}
-
static void cached_dev_make_request(struct request_queue *q, struct bio *bio)
{
struct search *s;
@@ -1193,14 +1132,24 @@ static void cached_dev_make_request(struct request_queue *q, struct bio *bio)
if (cached_dev_get(dc)) {
s = search_alloc(bio, d);
- trace_bcache_request_start(s, bio);
+ trace_bcache_request_start(s->d, bio);
+
+ if (!bio->bi_size) {
+ /*
+ * can't call bch_journal_meta from under
+ * generic_make_request
+ */
+ continue_at_nobarrier(&s->cl,
+ cached_dev_nodata,
+ bcache_wq);
+ } else {
+ s->iop.bypass = check_should_bypass(dc, bio);
- if (!bio_has_data(bio))
- request_nodata(dc, s);
- else if (rw)
- request_write(dc, s);
- else
- request_read(dc, s);
+ if (rw)
+ cached_dev_write(dc, s);
+ else
+ cached_dev_read(dc, s);
+ }
} else {
if ((bio->bi_rw & REQ_DISCARD) &&
!blk_queue_discard(bdev_get_queue(dc->bdev)))
@@ -1275,9 +1224,19 @@ static int flash_dev_cache_miss(struct btree *b, struct search *s,
bio_advance(bio, min(sectors << 9, bio->bi_size));
if (!bio->bi_size)
- s->op.lookup_done = true;
+ return MAP_DONE;
- return 0;
+ return MAP_CONTINUE;
+}
+
+static void flash_dev_nodata(struct closure *cl)
+{
+ struct search *s = container_of(cl, struct search, cl);
+
+ if (s->iop.flush_journal)
+ bch_journal_meta(s->iop.c, cl);
+
+ continue_at(cl, search_free, NULL);
}
static void flash_dev_make_request(struct request_queue *q, struct bio *bio)
@@ -1296,23 +1255,28 @@ static void flash_dev_make_request(struct request_queue *q, struct bio *bio)
cl = &s->cl;
bio = &s->bio.bio;
- trace_bcache_request_start(s, bio);
+ trace_bcache_request_start(s->d, bio);
- if (bio_has_data(bio) && !rw) {
- closure_call(&s->op.cl, btree_read_async, NULL, cl);
- } else if (bio_has_data(bio) || s->op.skip) {
- bch_keybuf_check_overlapping(&s->op.c->moving_gc_keys,
+ if (!bio->bi_size) {
+ /*
+ * can't call bch_journal_meta from under
+ * generic_make_request
+ */
+ continue_at_nobarrier(&s->cl,
+ flash_dev_nodata,
+ bcache_wq);
+ } else if (rw) {
+ bch_keybuf_check_overlapping(&s->iop.c->moving_gc_keys,
&KEY(d->id, bio->bi_sector, 0),
&KEY(d->id, bio_end_sector(bio), 0));
- s->writeback = true;
- s->op.cache_bio = bio;
+ s->iop.bypass = (bio->bi_rw & REQ_DISCARD) != 0;
+ s->iop.writeback = true;
+ s->iop.bio = bio;
- closure_call(&s->op.cl, bch_insert_data, NULL, cl);
+ closure_call(&s->iop.cl, bch_data_insert, NULL, cl);
} else {
- /* No data - probably a cache flush */
- if (s->op.flush_journal)
- bch_journal_meta(s->op.c, cl);
+ closure_call(&s->iop.cl, cache_lookup, NULL, cl);
}
continue_at(cl, search_free, NULL);
diff --git a/drivers/md/bcache/request.h b/drivers/md/bcache/request.h
index 57dc4784f4f4..2cd65bf073c2 100644
--- a/drivers/md/bcache/request.h
+++ b/drivers/md/bcache/request.h
@@ -3,40 +3,33 @@
#include <linux/cgroup.h>
-struct search {
- /* Stack frame for bio_complete */
+struct data_insert_op {
struct closure cl;
+ struct cache_set *c;
+ struct bio *bio;
- struct bcache_device *d;
- struct task_struct *task;
-
- struct bbio bio;
- struct bio *orig_bio;
- struct bio *cache_miss;
- unsigned cache_bio_sectors;
-
- unsigned recoverable:1;
- unsigned unaligned_bvec:1;
+ unsigned inode;
+ uint16_t write_point;
+ uint16_t write_prio;
+ short error;
- unsigned write:1;
+ unsigned bypass:1;
unsigned writeback:1;
+ unsigned flush_journal:1;
+ unsigned csum:1;
- /* IO error returned to s->bio */
- short error;
- unsigned long start_time;
+ unsigned replace:1;
+ unsigned replace_collision:1;
+
+ unsigned insert_data_done:1;
- /* Anything past op->keys won't get zeroed in do_bio_hook */
- struct btree_op op;
+ /* Anything past this point won't get zeroed in search_alloc() */
+ struct keylist insert_keys;
+ BKEY_PADDED(replace_key);
};
-void bch_cache_read_endio(struct bio *, int);
unsigned bch_get_congested(struct cache_set *);
-void bch_insert_data(struct closure *cl);
-void bch_btree_insert_async(struct closure *);
-void bch_cache_read_endio(struct bio *, int);
-
-void bch_open_buckets_free(struct cache_set *);
-int bch_open_buckets_alloc(struct cache_set *);
+void bch_data_insert(struct closure *cl);
void bch_cached_dev_request_init(struct cached_dev *dc);
void bch_flash_dev_request_init(struct bcache_device *d);
diff --git a/drivers/md/bcache/stats.c b/drivers/md/bcache/stats.c
index b8730e714d69..84d0782f702e 100644
--- a/drivers/md/bcache/stats.c
+++ b/drivers/md/bcache/stats.c
@@ -7,7 +7,6 @@
#include "bcache.h"
#include "stats.h"
#include "btree.h"
-#include "request.h"
#include "sysfs.h"
/*
@@ -196,35 +195,36 @@ static void mark_cache_stats(struct cache_stat_collector *stats,
atomic_inc(&stats->cache_bypass_misses);
}
-void bch_mark_cache_accounting(struct search *s, bool hit, bool bypass)
+void bch_mark_cache_accounting(struct cache_set *c, struct bcache_device *d,
+ bool hit, bool bypass)
{
- struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+ struct cached_dev *dc = container_of(d, struct cached_dev, disk);
mark_cache_stats(&dc->accounting.collector, hit, bypass);
- mark_cache_stats(&s->op.c->accounting.collector, hit, bypass);
+ mark_cache_stats(&c->accounting.collector, hit, bypass);
#ifdef CONFIG_CGROUP_BCACHE
mark_cache_stats(&(bch_bio_to_cgroup(s->orig_bio)->stats), hit, bypass);
#endif
}
-void bch_mark_cache_readahead(struct search *s)
+void bch_mark_cache_readahead(struct cache_set *c, struct bcache_device *d)
{
- struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+ struct cached_dev *dc = container_of(d, struct cached_dev, disk);
atomic_inc(&dc->accounting.collector.cache_readaheads);
- atomic_inc(&s->op.c->accounting.collector.cache_readaheads);
+ atomic_inc(&c->accounting.collector.cache_readaheads);
}
-void bch_mark_cache_miss_collision(struct search *s)
+void bch_mark_cache_miss_collision(struct cache_set *c, struct bcache_device *d)
{
- struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+ struct cached_dev *dc = container_of(d, struct cached_dev, disk);
atomic_inc(&dc->accounting.collector.cache_miss_collisions);
- atomic_inc(&s->op.c->accounting.collector.cache_miss_collisions);
+ atomic_inc(&c->accounting.collector.cache_miss_collisions);
}
-void bch_mark_sectors_bypassed(struct search *s, int sectors)
+void bch_mark_sectors_bypassed(struct cache_set *c, struct cached_dev *dc,
+ int sectors)
{
- struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
atomic_add(sectors, &dc->accounting.collector.sectors_bypassed);
- atomic_add(sectors, &s->op.c->accounting.collector.sectors_bypassed);
+ atomic_add(sectors, &c->accounting.collector.sectors_bypassed);
}
void bch_cache_accounting_init(struct cache_accounting *acc,
diff --git a/drivers/md/bcache/stats.h b/drivers/md/bcache/stats.h
index c7c7a8fd29fe..adbff141c887 100644
--- a/drivers/md/bcache/stats.h
+++ b/drivers/md/bcache/stats.h
@@ -38,7 +38,9 @@ struct cache_accounting {
struct cache_stats day;
};
-struct search;
+struct cache_set;
+struct cached_dev;
+struct bcache_device;
void bch_cache_accounting_init(struct cache_accounting *acc,
struct closure *parent);
@@ -50,9 +52,10 @@ void bch_cache_accounting_clear(struct cache_accounting *acc);
void bch_cache_accounting_destroy(struct cache_accounting *acc);
-void bch_mark_cache_accounting(struct search *s, bool hit, bool bypass);
-void bch_mark_cache_readahead(struct search *s);
-void bch_mark_cache_miss_collision(struct search *s);
-void bch_mark_sectors_bypassed(struct search *s, int sectors);
+void bch_mark_cache_accounting(struct cache_set *, struct bcache_device *,
+ bool, bool);
+void bch_mark_cache_readahead(struct cache_set *, struct bcache_device *);
+void bch_mark_cache_miss_collision(struct cache_set *, struct bcache_device *);
+void bch_mark_sectors_bypassed(struct cache_set *, struct cached_dev *, int);
#endif /* _BCACHE_STATS_H_ */
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 547c4c57b052..dec15cd2d797 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -16,6 +16,7 @@
#include <linux/buffer_head.h>
#include <linux/debugfs.h>
#include <linux/genhd.h>
+#include <linux/idr.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/random.h>
@@ -45,21 +46,13 @@ const char * const bch_cache_modes[] = {
NULL
};
-struct uuid_entry_v0 {
- uint8_t uuid[16];
- uint8_t label[32];
- uint32_t first_reg;
- uint32_t last_reg;
- uint32_t invalidated;
- uint32_t pad;
-};
-
static struct kobject *bcache_kobj;
struct mutex bch_register_lock;
LIST_HEAD(bch_cache_sets);
static LIST_HEAD(uncached_devices);
-static int bcache_major, bcache_minor;
+static int bcache_major;
+static DEFINE_IDA(bcache_minor);
static wait_queue_head_t unregister_wait;
struct workqueue_struct *bcache_wq;
@@ -382,7 +375,7 @@ static char *uuid_read(struct cache_set *c, struct jset *j, struct closure *cl)
{
struct bkey *k = &j->uuid_bucket;
- if (__bch_ptr_invalid(c, 1, k))
+ if (bch_btree_ptr_invalid(c, k))
return "bad uuid pointer";
bkey_copy(&c->uuid_bucket, k);
@@ -427,7 +420,7 @@ static int __uuid_write(struct cache_set *c)
lockdep_assert_held(&bch_register_lock);
- if (bch_bucket_alloc_set(c, WATERMARK_METADATA, &k.key, 1, &cl))
+ if (bch_bucket_alloc_set(c, WATERMARK_METADATA, &k.key, 1, true))
return 1;
SET_KEY_SIZE(&k.key, c->sb.bucket_size);
@@ -435,7 +428,7 @@ static int __uuid_write(struct cache_set *c)
closure_sync(&cl);
bkey_copy(&c->uuid_bucket, &k.key);
- __bkey_put(c, &k.key);
+ bkey_put(c, &k.key);
return 0;
}
@@ -562,10 +555,10 @@ void bch_prio_write(struct cache *ca)
}
p->next_bucket = ca->prio_buckets[i + 1];
- p->magic = pset_magic(ca);
+ p->magic = pset_magic(&ca->sb);
p->csum = bch_crc64(&p->magic, bucket_bytes(ca) - 8);
- bucket = bch_bucket_alloc(ca, WATERMARK_PRIO, &cl);
+ bucket = bch_bucket_alloc(ca, WATERMARK_PRIO, true);
BUG_ON(bucket == -1);
mutex_unlock(&ca->set->bucket_lock);
@@ -613,7 +606,7 @@ static void prio_read(struct cache *ca, uint64_t bucket)
if (p->csum != bch_crc64(&p->magic, bucket_bytes(ca) - 8))
pr_warn("bad csum reading priorities");
- if (p->magic != pset_magic(ca))
+ if (p->magic != pset_magic(&ca->sb))
pr_warn("bad magic reading priorities");
bucket = p->next_bucket;
@@ -630,7 +623,7 @@ static void prio_read(struct cache *ca, uint64_t bucket)
static int open_dev(struct block_device *b, fmode_t mode)
{
struct bcache_device *d = b->bd_disk->private_data;
- if (atomic_read(&d->closing))
+ if (test_bit(BCACHE_DEV_CLOSING, &d->flags))
return -ENXIO;
closure_get(&d->cl);
@@ -659,20 +652,24 @@ static const struct block_device_operations bcache_ops = {
void bcache_device_stop(struct bcache_device *d)
{
- if (!atomic_xchg(&d->closing, 1))
+ if (!test_and_set_bit(BCACHE_DEV_CLOSING, &d->flags))
closure_queue(&d->cl);
}
static void bcache_device_unlink(struct bcache_device *d)
{
- unsigned i;
- struct cache *ca;
+ lockdep_assert_held(&bch_register_lock);
- sysfs_remove_link(&d->c->kobj, d->name);
- sysfs_remove_link(&d->kobj, "cache");
+ if (d->c && !test_and_set_bit(BCACHE_DEV_UNLINK_DONE, &d->flags)) {
+ unsigned i;
+ struct cache *ca;
- for_each_cache(ca, d->c, i)
- bd_unlink_disk_holder(ca->bdev, d->disk);
+ sysfs_remove_link(&d->c->kobj, d->name);
+ sysfs_remove_link(&d->kobj, "cache");
+
+ for_each_cache(ca, d->c, i)
+ bd_unlink_disk_holder(ca->bdev, d->disk);
+ }
}
static void bcache_device_link(struct bcache_device *d, struct cache_set *c,
@@ -696,19 +693,16 @@ static void bcache_device_detach(struct bcache_device *d)
{
lockdep_assert_held(&bch_register_lock);
- if (atomic_read(&d->detaching)) {
+ if (test_bit(BCACHE_DEV_DETACHING, &d->flags)) {
struct uuid_entry *u = d->c->uuids + d->id;
SET_UUID_FLASH_ONLY(u, 0);
memcpy(u->uuid, invalid_uuid, 16);
u->invalidated = cpu_to_le32(get_seconds());
bch_uuid_write(d->c);
-
- atomic_set(&d->detaching, 0);
}
- if (!d->flush_done)
- bcache_device_unlink(d);
+ bcache_device_unlink(d);
d->c->devices[d->id] = NULL;
closure_put(&d->c->caching);
@@ -739,14 +733,20 @@ static void bcache_device_free(struct bcache_device *d)
del_gendisk(d->disk);
if (d->disk && d->disk->queue)
blk_cleanup_queue(d->disk->queue);
- if (d->disk)
+ if (d->disk) {
+ ida_simple_remove(&bcache_minor, d->disk->first_minor);
put_disk(d->disk);
+ }
bio_split_pool_free(&d->bio_split_hook);
if (d->unaligned_bvec)
mempool_destroy(d->unaligned_bvec);
if (d->bio_split)
bioset_free(d->bio_split);
+ if (is_vmalloc_addr(d->full_dirty_stripes))
+ vfree(d->full_dirty_stripes);
+ else
+ kfree(d->full_dirty_stripes);
if (is_vmalloc_addr(d->stripe_sectors_dirty))
vfree(d->stripe_sectors_dirty);
else
@@ -760,15 +760,19 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size,
{
struct request_queue *q;
size_t n;
+ int minor;
- if (!d->stripe_size_bits)
- d->stripe_size_bits = 31;
+ if (!d->stripe_size)
+ d->stripe_size = 1 << 31;
- d->nr_stripes = round_up(sectors, 1 << d->stripe_size_bits) >>
- d->stripe_size_bits;
+ d->nr_stripes = DIV_ROUND_UP_ULL(sectors, d->stripe_size);
- if (!d->nr_stripes || d->nr_stripes > SIZE_MAX / sizeof(atomic_t))
+ if (!d->nr_stripes ||
+ d->nr_stripes > INT_MAX ||
+ d->nr_stripes > SIZE_MAX / sizeof(atomic_t)) {
+ pr_err("nr_stripes too large");
return -ENOMEM;
+ }
n = d->nr_stripes * sizeof(atomic_t);
d->stripe_sectors_dirty = n < PAGE_SIZE << 6
@@ -777,22 +781,38 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size,
if (!d->stripe_sectors_dirty)
return -ENOMEM;
+ n = BITS_TO_LONGS(d->nr_stripes) * sizeof(unsigned long);
+ d->full_dirty_stripes = n < PAGE_SIZE << 6
+ ? kzalloc(n, GFP_KERNEL)
+ : vzalloc(n);
+ if (!d->full_dirty_stripes)
+ return -ENOMEM;
+
+ minor = ida_simple_get(&bcache_minor, 0, MINORMASK + 1, GFP_KERNEL);
+ if (minor < 0)
+ return minor;
+
if (!(d->bio_split = bioset_create(4, offsetof(struct bbio, bio))) ||
!(d->unaligned_bvec = mempool_create_kmalloc_pool(1,
sizeof(struct bio_vec) * BIO_MAX_PAGES)) ||
bio_split_pool_init(&d->bio_split_hook) ||
- !(d->disk = alloc_disk(1)) ||
- !(q = blk_alloc_queue(GFP_KERNEL)))
+ !(d->disk = alloc_disk(1))) {
+ ida_simple_remove(&bcache_minor, minor);
return -ENOMEM;
+ }
set_capacity(d->disk, sectors);
- snprintf(d->disk->disk_name, DISK_NAME_LEN, "bcache%i", bcache_minor);
+ snprintf(d->disk->disk_name, DISK_NAME_LEN, "bcache%i", minor);
d->disk->major = bcache_major;
- d->disk->first_minor = bcache_minor++;
+ d->disk->first_minor = minor;
d->disk->fops = &bcache_ops;
d->disk->private_data = d;
+ q = blk_alloc_queue(GFP_KERNEL);
+ if (!q)
+ return -ENOMEM;
+
blk_queue_make_request(q, NULL);
d->disk->queue = q;
q->queuedata = d;
@@ -874,7 +894,7 @@ static void cached_dev_detach_finish(struct work_struct *w)
struct closure cl;
closure_init_stack(&cl);
- BUG_ON(!atomic_read(&dc->disk.detaching));
+ BUG_ON(!test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags));
BUG_ON(atomic_read(&dc->count));
mutex_lock(&bch_register_lock);
@@ -888,6 +908,8 @@ static void cached_dev_detach_finish(struct work_struct *w)
bcache_device_detach(&dc->disk);
list_move(&dc->list, &uncached_devices);
+ clear_bit(BCACHE_DEV_DETACHING, &dc->disk.flags);
+
mutex_unlock(&bch_register_lock);
pr_info("Caching disabled for %s", bdevname(dc->bdev, buf));
@@ -900,10 +922,10 @@ void bch_cached_dev_detach(struct cached_dev *dc)
{
lockdep_assert_held(&bch_register_lock);
- if (atomic_read(&dc->disk.closing))
+ if (test_bit(BCACHE_DEV_CLOSING, &dc->disk.flags))
return;
- if (atomic_xchg(&dc->disk.detaching, 1))
+ if (test_and_set_bit(BCACHE_DEV_DETACHING, &dc->disk.flags))
return;
/*
@@ -1030,6 +1052,7 @@ static void cached_dev_free(struct closure *cl)
struct cached_dev *dc = container_of(cl, struct cached_dev, disk.cl);
cancel_delayed_work_sync(&dc->writeback_rate_update);
+ kthread_stop(dc->writeback_thread);
mutex_lock(&bch_register_lock);
@@ -1058,11 +1081,7 @@ static void cached_dev_flush(struct closure *cl)
struct bcache_device *d = &dc->disk;
mutex_lock(&bch_register_lock);
- d->flush_done = 1;
-
- if (d->c)
- bcache_device_unlink(d);
-
+ bcache_device_unlink(d);
mutex_unlock(&bch_register_lock);
bch_cache_accounting_destroy(&dc->accounting);
@@ -1088,7 +1107,6 @@ static int cached_dev_init(struct cached_dev *dc, unsigned block_size)
spin_lock_init(&dc->io_lock);
bch_cache_accounting_init(&dc->accounting, &dc->disk.cl);
- dc->sequential_merge = true;
dc->sequential_cutoff = 4 << 20;
for (io = dc->io; io < dc->io + RECENT_IO; io++) {
@@ -1260,7 +1278,8 @@ bool bch_cache_set_error(struct cache_set *c, const char *fmt, ...)
{
va_list args;
- if (test_bit(CACHE_SET_STOPPING, &c->flags))
+ if (c->on_error != ON_ERROR_PANIC &&
+ test_bit(CACHE_SET_STOPPING, &c->flags))
return false;
/* XXX: we can be called from atomic context
@@ -1275,6 +1294,9 @@ bool bch_cache_set_error(struct cache_set *c, const char *fmt, ...)
printk(", disabling caching\n");
+ if (c->on_error == ON_ERROR_PANIC)
+ panic("panic forced after error\n");
+
bch_cache_set_unregister(c);
return true;
}
@@ -1339,6 +1361,9 @@ static void cache_set_flush(struct closure *cl)
kobject_put(&c->internal);
kobject_del(&c->kobj);
+ if (c->gc_thread)
+ kthread_stop(c->gc_thread);
+
if (!IS_ERR_OR_NULL(c->root))
list_add(&c->root->list, &c->btree_cache);
@@ -1433,12 +1458,19 @@ struct cache_set *bch_cache_set_alloc(struct cache_sb *sb)
c->sort_crit_factor = int_sqrt(c->btree_pages);
- mutex_init(&c->bucket_lock);
- mutex_init(&c->sort_lock);
- spin_lock_init(&c->sort_time_lock);
closure_init_unlocked(&c->sb_write);
+ mutex_init(&c->bucket_lock);
+ init_waitqueue_head(&c->try_wait);
+ init_waitqueue_head(&c->bucket_wait);
closure_init_unlocked(&c->uuid_write);
- spin_lock_init(&c->btree_read_time_lock);
+ mutex_init(&c->sort_lock);
+
+ spin_lock_init(&c->sort_time.lock);
+ spin_lock_init(&c->btree_gc_time.lock);
+ spin_lock_init(&c->btree_split_time.lock);
+ spin_lock_init(&c->btree_read_time.lock);
+ spin_lock_init(&c->try_harder_time.lock);
+
bch_moving_init_cache_set(c);
INIT_LIST_HEAD(&c->list);
@@ -1483,11 +1515,10 @@ static void run_cache_set(struct cache_set *c)
const char *err = "cannot allocate memory";
struct cached_dev *dc, *t;
struct cache *ca;
+ struct closure cl;
unsigned i;
- struct btree_op op;
- bch_btree_op_init_stack(&op);
- op.lock = SHRT_MAX;
+ closure_init_stack(&cl);
for_each_cache(ca, c, i)
c->nbuckets += ca->sb.nbuckets;
@@ -1498,7 +1529,7 @@ static void run_cache_set(struct cache_set *c)
struct jset *j;
err = "cannot allocate memory for journal";
- if (bch_journal_read(c, &journal, &op))
+ if (bch_journal_read(c, &journal))
goto err;
pr_debug("btree_journal_read() done");
@@ -1522,23 +1553,23 @@ static void run_cache_set(struct cache_set *c)
k = &j->btree_root;
err = "bad btree root";
- if (__bch_ptr_invalid(c, j->btree_level + 1, k))
+ if (bch_btree_ptr_invalid(c, k))
goto err;
err = "error reading btree root";
- c->root = bch_btree_node_get(c, k, j->btree_level, &op);
+ c->root = bch_btree_node_get(c, k, j->btree_level, true);
if (IS_ERR_OR_NULL(c->root))
goto err;
list_del_init(&c->root->list);
rw_unlock(true, c->root);
- err = uuid_read(c, j, &op.cl);
+ err = uuid_read(c, j, &cl);
if (err)
goto err;
err = "error in recovery";
- if (bch_btree_check(c, &op))
+ if (bch_btree_check(c))
goto err;
bch_journal_mark(c, &journal);
@@ -1570,11 +1601,9 @@ static void run_cache_set(struct cache_set *c)
if (j->version < BCACHE_JSET_VERSION_UUID)
__uuid_write(c);
- bch_journal_replay(c, &journal, &op);
+ bch_journal_replay(c, &journal);
} else {
pr_notice("invalidating existing data");
- /* Don't want invalidate_buckets() to queue a gc yet */
- closure_lock(&c->gc, NULL);
for_each_cache(ca, c, i) {
unsigned j;
@@ -1600,15 +1629,15 @@ static void run_cache_set(struct cache_set *c)
err = "cannot allocate new UUID bucket";
if (__uuid_write(c))
- goto err_unlock_gc;
+ goto err;
err = "cannot allocate new btree root";
- c->root = bch_btree_node_alloc(c, 0, &op.cl);
+ c->root = bch_btree_node_alloc(c, 0, true);
if (IS_ERR_OR_NULL(c->root))
- goto err_unlock_gc;
+ goto err;
bkey_copy_key(&c->root->key, &MAX_KEY);
- bch_btree_node_write(c->root, &op.cl);
+ bch_btree_node_write(c->root, &cl);
bch_btree_set_root(c->root);
rw_unlock(true, c->root);
@@ -1621,14 +1650,14 @@ static void run_cache_set(struct cache_set *c)
SET_CACHE_SYNC(&c->sb, true);
bch_journal_next(&c->journal);
- bch_journal_meta(c, &op.cl);
-
- /* Unlock */
- closure_set_stopped(&c->gc.cl);
- closure_put(&c->gc.cl);
+ bch_journal_meta(c, &cl);
}
- closure_sync(&op.cl);
+ err = "error starting gc thread";
+ if (bch_gc_thread_start(c))
+ goto err;
+
+ closure_sync(&cl);
c->sb.last_mount = get_seconds();
bcache_write_super(c);
@@ -1638,13 +1667,10 @@ static void run_cache_set(struct cache_set *c)
flash_devs_run(c);
return;
-err_unlock_gc:
- closure_set_stopped(&c->gc.cl);
- closure_put(&c->gc.cl);
err:
- closure_sync(&op.cl);
+ closure_sync(&cl);
/* XXX: test this, it's broken */
- bch_cache_set_error(c, err);
+ bch_cache_set_error(c, "%s", err);
}
static bool can_attach_cache(struct cache *ca, struct cache_set *c)
@@ -1725,8 +1751,6 @@ void bch_cache_release(struct kobject *kobj)
if (ca->set)
ca->set->cache[ca->sb.nr_this_dev] = NULL;
- bch_cache_allocator_exit(ca);
-
bio_split_pool_free(&ca->bio_split_hook);
free_pages((unsigned long) ca->disk_buckets, ilog2(bucket_pages(ca)));
@@ -1758,8 +1782,6 @@ static int cache_alloc(struct cache_sb *sb, struct cache *ca)
__module_get(THIS_MODULE);
kobject_init(&ca->kobj, &bch_cache_ktype);
- INIT_LIST_HEAD(&ca->discards);
-
bio_init(&ca->journal.bio);
ca->journal.bio.bi_max_vecs = 8;
ca->journal.bio.bi_io_vec = ca->journal.bio.bi_inline_vecs;
@@ -2006,7 +2028,6 @@ static struct notifier_block reboot = {
static void bcache_exit(void)
{
bch_debug_exit();
- bch_writeback_exit();
bch_request_exit();
bch_btree_exit();
if (bcache_kobj)
@@ -2039,7 +2060,6 @@ static int __init bcache_init(void)
sysfs_create_files(bcache_kobj, files) ||
bch_btree_init() ||
bch_request_init() ||
- bch_writeback_init() ||
bch_debug_init(bcache_kobj))
goto err;
diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c
index 924dcfdae111..80d4c2bee18a 100644
--- a/drivers/md/bcache/sysfs.c
+++ b/drivers/md/bcache/sysfs.c
@@ -21,6 +21,12 @@ static const char * const cache_replacement_policies[] = {
NULL
};
+static const char * const error_actions[] = {
+ "unregister",
+ "panic",
+ NULL
+};
+
write_attribute(attach);
write_attribute(detach);
write_attribute(unregister);
@@ -66,7 +72,6 @@ rw_attribute(congested_read_threshold_us);
rw_attribute(congested_write_threshold_us);
rw_attribute(sequential_cutoff);
-rw_attribute(sequential_merge);
rw_attribute(data_csum);
rw_attribute(cache_mode);
rw_attribute(writeback_metadata);
@@ -90,11 +95,14 @@ rw_attribute(discard);
rw_attribute(running);
rw_attribute(label);
rw_attribute(readahead);
+rw_attribute(errors);
rw_attribute(io_error_limit);
rw_attribute(io_error_halflife);
rw_attribute(verify);
+rw_attribute(bypass_torture_test);
rw_attribute(key_merging_disabled);
rw_attribute(gc_always_rewrite);
+rw_attribute(expensive_debug_checks);
rw_attribute(freelist_percent);
rw_attribute(cache_replacement_policy);
rw_attribute(btree_shrinker_disabled);
@@ -116,6 +124,7 @@ SHOW(__bch_cached_dev)
sysfs_printf(data_csum, "%i", dc->disk.data_csum);
var_printf(verify, "%i");
+ var_printf(bypass_torture_test, "%i");
var_printf(writeback_metadata, "%i");
var_printf(writeback_running, "%i");
var_print(writeback_delay);
@@ -150,10 +159,9 @@ SHOW(__bch_cached_dev)
sysfs_hprint(dirty_data,
bcache_dev_sectors_dirty(&dc->disk) << 9);
- sysfs_hprint(stripe_size, (1 << dc->disk.stripe_size_bits) << 9);
+ sysfs_hprint(stripe_size, dc->disk.stripe_size << 9);
var_printf(partial_stripes_expensive, "%u");
- var_printf(sequential_merge, "%i");
var_hprint(sequential_cutoff);
var_hprint(readahead);
@@ -185,6 +193,7 @@ STORE(__cached_dev)
sysfs_strtoul(data_csum, dc->disk.data_csum);
d_strtoul(verify);
+ d_strtoul(bypass_torture_test);
d_strtoul(writeback_metadata);
d_strtoul(writeback_running);
d_strtoul(writeback_delay);
@@ -199,7 +208,6 @@ STORE(__cached_dev)
dc->writeback_rate_p_term_inverse, 1, INT_MAX);
d_strtoul(writeback_rate_d_smooth);
- d_strtoul(sequential_merge);
d_strtoi_h(sequential_cutoff);
d_strtoi_h(readahead);
@@ -311,7 +319,6 @@ static struct attribute *bch_cached_dev_files[] = {
&sysfs_stripe_size,
&sysfs_partial_stripes_expensive,
&sysfs_sequential_cutoff,
- &sysfs_sequential_merge,
&sysfs_clear_stats,
&sysfs_running,
&sysfs_state,
@@ -319,6 +326,7 @@ static struct attribute *bch_cached_dev_files[] = {
&sysfs_readahead,
#ifdef CONFIG_BCACHE_DEBUG
&sysfs_verify,
+ &sysfs_bypass_torture_test,
#endif
NULL
};
@@ -366,7 +374,7 @@ STORE(__bch_flash_dev)
}
if (attr == &sysfs_unregister) {
- atomic_set(&d->detaching, 1);
+ set_bit(BCACHE_DEV_DETACHING, &d->flags);
bcache_device_stop(d);
}
@@ -481,7 +489,6 @@ lock_root:
sysfs_print(btree_used_percent, btree_used(c));
sysfs_print(btree_nodes, c->gc_stats.nodes);
- sysfs_hprint(dirty_data, c->gc_stats.dirty);
sysfs_hprint(average_key_size, average_key_size(c));
sysfs_print(cache_read_races,
@@ -492,6 +499,10 @@ lock_root:
sysfs_print(writeback_keys_failed,
atomic_long_read(&c->writeback_keys_failed));
+ if (attr == &sysfs_errors)
+ return bch_snprint_string_list(buf, PAGE_SIZE, error_actions,
+ c->on_error);
+
/* See count_io_errors for why 88 */
sysfs_print(io_error_halflife, c->error_decay * 88);
sysfs_print(io_error_limit, c->error_limit >> IO_ERROR_SHIFT);
@@ -506,6 +517,8 @@ lock_root:
sysfs_print(active_journal_entries, fifo_used(&c->journal.pin));
sysfs_printf(verify, "%i", c->verify);
sysfs_printf(key_merging_disabled, "%i", c->key_merging_disabled);
+ sysfs_printf(expensive_debug_checks,
+ "%i", c->expensive_debug_checks);
sysfs_printf(gc_always_rewrite, "%i", c->gc_always_rewrite);
sysfs_printf(btree_shrinker_disabled, "%i", c->shrinker_disabled);
sysfs_printf(copy_gc_enabled, "%i", c->copy_gc_enabled);
@@ -555,7 +568,7 @@ STORE(__bch_cache_set)
}
if (attr == &sysfs_trigger_gc)
- bch_queue_gc(c);
+ wake_up_gc(c);
if (attr == &sysfs_prune_cache) {
struct shrink_control sc;
@@ -569,6 +582,15 @@ STORE(__bch_cache_set)
sysfs_strtoul(congested_write_threshold_us,
c->congested_write_threshold_us);
+ if (attr == &sysfs_errors) {
+ ssize_t v = bch_read_string_list(buf, error_actions);
+
+ if (v < 0)
+ return v;
+
+ c->on_error = v;
+ }
+
if (attr == &sysfs_io_error_limit)
c->error_limit = strtoul_or_return(buf) << IO_ERROR_SHIFT;
@@ -579,6 +601,7 @@ STORE(__bch_cache_set)
sysfs_strtoul(journal_delay_ms, c->journal_delay_ms);
sysfs_strtoul(verify, c->verify);
sysfs_strtoul(key_merging_disabled, c->key_merging_disabled);
+ sysfs_strtoul(expensive_debug_checks, c->expensive_debug_checks);
sysfs_strtoul(gc_always_rewrite, c->gc_always_rewrite);
sysfs_strtoul(btree_shrinker_disabled, c->shrinker_disabled);
sysfs_strtoul(copy_gc_enabled, c->copy_gc_enabled);
@@ -618,8 +641,8 @@ static struct attribute *bch_cache_set_files[] = {
&sysfs_cache_available_percent,
&sysfs_average_key_size,
- &sysfs_dirty_data,
+ &sysfs_errors,
&sysfs_io_error_limit,
&sysfs_io_error_halflife,
&sysfs_congested,
@@ -653,6 +676,7 @@ static struct attribute *bch_cache_set_internal_files[] = {
#ifdef CONFIG_BCACHE_DEBUG
&sysfs_verify,
&sysfs_key_merging_disabled,
+ &sysfs_expensive_debug_checks,
#endif
&sysfs_gc_always_rewrite,
&sysfs_btree_shrinker_disabled,
diff --git a/drivers/md/bcache/trace.c b/drivers/md/bcache/trace.c
index f7b6c197f90f..adbc3df17a80 100644
--- a/drivers/md/bcache/trace.c
+++ b/drivers/md/bcache/trace.c
@@ -1,6 +1,5 @@
#include "bcache.h"
#include "btree.h"
-#include "request.h"
#include <linux/blktrace_api.h>
#include <linux/module.h>
diff --git a/drivers/md/bcache/util.c b/drivers/md/bcache/util.c
index 420dad545c7d..462214eeacbe 100644
--- a/drivers/md/bcache/util.c
+++ b/drivers/md/bcache/util.c
@@ -168,10 +168,14 @@ int bch_parse_uuid(const char *s, char *uuid)
void bch_time_stats_update(struct time_stats *stats, uint64_t start_time)
{
- uint64_t now = local_clock();
- uint64_t duration = time_after64(now, start_time)
+ uint64_t now, duration, last;
+
+ spin_lock(&stats->lock);
+
+ now = local_clock();
+ duration = time_after64(now, start_time)
? now - start_time : 0;
- uint64_t last = time_after64(now, stats->last)
+ last = time_after64(now, stats->last)
? now - stats->last : 0;
stats->max_duration = max(stats->max_duration, duration);
@@ -188,6 +192,8 @@ void bch_time_stats_update(struct time_stats *stats, uint64_t start_time)
}
stats->last = now ?: 1;
+
+ spin_unlock(&stats->lock);
}
/**
diff --git a/drivers/md/bcache/util.h b/drivers/md/bcache/util.h
index ea345c6896f4..362c4b3f8b4a 100644
--- a/drivers/md/bcache/util.h
+++ b/drivers/md/bcache/util.h
@@ -15,28 +15,18 @@
struct closure;
-#ifdef CONFIG_BCACHE_EDEBUG
+#ifdef CONFIG_BCACHE_DEBUG
#define atomic_dec_bug(v) BUG_ON(atomic_dec_return(v) < 0)
#define atomic_inc_bug(v, i) BUG_ON(atomic_inc_return(v) <= i)
-#else /* EDEBUG */
+#else /* DEBUG */
#define atomic_dec_bug(v) atomic_dec(v)
#define atomic_inc_bug(v, i) atomic_inc(v)
#endif
-#define BITMASK(name, type, field, offset, size) \
-static inline uint64_t name(const type *k) \
-{ return (k->field >> offset) & ~(((uint64_t) ~0) << size); } \
- \
-static inline void SET_##name(type *k, uint64_t v) \
-{ \
- k->field &= ~(~((uint64_t) ~0 << size) << offset); \
- k->field |= v << offset; \
-}
-
#define DECLARE_HEAP(type, name) \
struct { \
size_t size, used; \
@@ -388,6 +378,7 @@ ssize_t bch_snprint_string_list(char *buf, size_t size, const char * const list[
ssize_t bch_read_string_list(const char *buf, const char * const list[]);
struct time_stats {
+ spinlock_t lock;
/*
* all fields are in nanoseconds, averages are ewmas stored left shifted
* by 8
diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
index ba3ee48320f2..99053b1251be 100644
--- a/drivers/md/bcache/writeback.c
+++ b/drivers/md/bcache/writeback.c
@@ -11,18 +11,11 @@
#include "debug.h"
#include "writeback.h"
+#include <linux/delay.h>
+#include <linux/freezer.h>
+#include <linux/kthread.h>
#include <trace/events/bcache.h>
-static struct workqueue_struct *dirty_wq;
-
-static void read_dirty(struct closure *);
-
-struct dirty_io {
- struct closure cl;
- struct cached_dev *dc;
- struct bio bio;
-};
-
/* Rate limiting */
static void __update_writeback_rate(struct cached_dev *dc)
@@ -72,9 +65,6 @@ out:
dc->writeback_rate_derivative = derivative;
dc->writeback_rate_change = change;
dc->writeback_rate_target = target;
-
- schedule_delayed_work(&dc->writeback_rate_update,
- dc->writeback_rate_update_seconds * HZ);
}
static void update_writeback_rate(struct work_struct *work)
@@ -90,13 +80,16 @@ static void update_writeback_rate(struct work_struct *work)
__update_writeback_rate(dc);
up_read(&dc->writeback_lock);
+
+ schedule_delayed_work(&dc->writeback_rate_update,
+ dc->writeback_rate_update_seconds * HZ);
}
static unsigned writeback_delay(struct cached_dev *dc, unsigned sectors)
{
uint64_t ret;
- if (atomic_read(&dc->disk.detaching) ||
+ if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) ||
!dc->writeback_percent)
return 0;
@@ -105,37 +98,11 @@ static unsigned writeback_delay(struct cached_dev *dc, unsigned sectors)
return min_t(uint64_t, ret, HZ);
}
-/* Background writeback */
-
-static bool dirty_pred(struct keybuf *buf, struct bkey *k)
-{
- return KEY_DIRTY(k);
-}
-
-static bool dirty_full_stripe_pred(struct keybuf *buf, struct bkey *k)
-{
- uint64_t stripe;
- unsigned nr_sectors = KEY_SIZE(k);
- struct cached_dev *dc = container_of(buf, struct cached_dev,
- writeback_keys);
- unsigned stripe_size = 1 << dc->disk.stripe_size_bits;
-
- if (!KEY_DIRTY(k))
- return false;
-
- stripe = KEY_START(k) >> dc->disk.stripe_size_bits;
- while (1) {
- if (atomic_read(dc->disk.stripe_sectors_dirty + stripe) !=
- stripe_size)
- return false;
-
- if (nr_sectors <= stripe_size)
- return true;
-
- nr_sectors -= stripe_size;
- stripe++;
- }
-}
+struct dirty_io {
+ struct closure cl;
+ struct cached_dev *dc;
+ struct bio bio;
+};
static void dirty_init(struct keybuf_key *w)
{
@@ -153,131 +120,6 @@ static void dirty_init(struct keybuf_key *w)
bch_bio_map(bio, NULL);
}
-static void refill_dirty(struct closure *cl)
-{
- struct cached_dev *dc = container_of(cl, struct cached_dev,
- writeback.cl);
- struct keybuf *buf = &dc->writeback_keys;
- bool searched_from_start = false;
- struct bkey end = MAX_KEY;
- SET_KEY_INODE(&end, dc->disk.id);
-
- if (!atomic_read(&dc->disk.detaching) &&
- !dc->writeback_running)
- closure_return(cl);
-
- down_write(&dc->writeback_lock);
-
- if (!atomic_read(&dc->has_dirty)) {
- SET_BDEV_STATE(&dc->sb, BDEV_STATE_CLEAN);
- bch_write_bdev_super(dc, NULL);
-
- up_write(&dc->writeback_lock);
- closure_return(cl);
- }
-
- if (bkey_cmp(&buf->last_scanned, &end) >= 0) {
- buf->last_scanned = KEY(dc->disk.id, 0, 0);
- searched_from_start = true;
- }
-
- if (dc->partial_stripes_expensive) {
- uint64_t i;
-
- for (i = 0; i < dc->disk.nr_stripes; i++)
- if (atomic_read(dc->disk.stripe_sectors_dirty + i) ==
- 1 << dc->disk.stripe_size_bits)
- goto full_stripes;
-
- goto normal_refill;
-full_stripes:
- bch_refill_keybuf(dc->disk.c, buf, &end,
- dirty_full_stripe_pred);
- } else {
-normal_refill:
- bch_refill_keybuf(dc->disk.c, buf, &end, dirty_pred);
- }
-
- if (bkey_cmp(&buf->last_scanned, &end) >= 0 && searched_from_start) {
- /* Searched the entire btree - delay awhile */
-
- if (RB_EMPTY_ROOT(&buf->keys)) {
- atomic_set(&dc->has_dirty, 0);
- cached_dev_put(dc);
- }
-
- if (!atomic_read(&dc->disk.detaching))
- closure_delay(&dc->writeback, dc->writeback_delay * HZ);
- }
-
- up_write(&dc->writeback_lock);
-
- bch_ratelimit_reset(&dc->writeback_rate);
-
- /* Punt to workqueue only so we don't recurse and blow the stack */
- continue_at(cl, read_dirty, dirty_wq);
-}
-
-void bch_writeback_queue(struct cached_dev *dc)
-{
- if (closure_trylock(&dc->writeback.cl, &dc->disk.cl)) {
- if (!atomic_read(&dc->disk.detaching))
- closure_delay(&dc->writeback, dc->writeback_delay * HZ);
-
- continue_at(&dc->writeback.cl, refill_dirty, dirty_wq);
- }
-}
-
-void bch_writeback_add(struct cached_dev *dc)
-{
- if (!atomic_read(&dc->has_dirty) &&
- !atomic_xchg(&dc->has_dirty, 1)) {
- atomic_inc(&dc->count);
-
- if (BDEV_STATE(&dc->sb) != BDEV_STATE_DIRTY) {
- SET_BDEV_STATE(&dc->sb, BDEV_STATE_DIRTY);
- /* XXX: should do this synchronously */
- bch_write_bdev_super(dc, NULL);
- }
-
- bch_writeback_queue(dc);
-
- if (dc->writeback_percent)
- schedule_delayed_work(&dc->writeback_rate_update,
- dc->writeback_rate_update_seconds * HZ);
- }
-}
-
-void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned inode,
- uint64_t offset, int nr_sectors)
-{
- struct bcache_device *d = c->devices[inode];
- unsigned stripe_size, stripe_offset;
- uint64_t stripe;
-
- if (!d)
- return;
-
- stripe_size = 1 << d->stripe_size_bits;
- stripe = offset >> d->stripe_size_bits;
- stripe_offset = offset & (stripe_size - 1);
-
- while (nr_sectors) {
- int s = min_t(unsigned, abs(nr_sectors),
- stripe_size - stripe_offset);
-
- if (nr_sectors < 0)
- s = -s;
-
- atomic_add(s, d->stripe_sectors_dirty + stripe);
- nr_sectors -= s;
- stripe_offset = 0;
- stripe++;
- }
-}
-
-/* Background writeback - IO loop */
-
static void dirty_io_destructor(struct closure *cl)
{
struct dirty_io *io = container_of(cl, struct dirty_io, cl);
@@ -297,26 +139,25 @@ static void write_dirty_finish(struct closure *cl)
/* This is kind of a dumb way of signalling errors. */
if (KEY_DIRTY(&w->key)) {
+ int ret;
unsigned i;
- struct btree_op op;
- bch_btree_op_init_stack(&op);
+ struct keylist keys;
- op.type = BTREE_REPLACE;
- bkey_copy(&op.replace, &w->key);
+ bch_keylist_init(&keys);
- SET_KEY_DIRTY(&w->key, false);
- bch_keylist_add(&op.keys, &w->key);
+ bkey_copy(keys.top, &w->key);
+ SET_KEY_DIRTY(keys.top, false);
+ bch_keylist_push(&keys);
for (i = 0; i < KEY_PTRS(&w->key); i++)
atomic_inc(&PTR_BUCKET(dc->disk.c, &w->key, i)->pin);
- bch_btree_insert(&op, dc->disk.c);
- closure_sync(&op.cl);
+ ret = bch_btree_insert(dc->disk.c, &keys, NULL, &w->key);
- if (op.insert_collision)
+ if (ret)
trace_bcache_writeback_collision(&w->key);
- atomic_long_inc(op.insert_collision
+ atomic_long_inc(ret
? &dc->disk.c->writeback_keys_failed
: &dc->disk.c->writeback_keys_done);
}
@@ -374,30 +215,33 @@ static void read_dirty_submit(struct closure *cl)
continue_at(cl, write_dirty, system_wq);
}
-static void read_dirty(struct closure *cl)
+static void read_dirty(struct cached_dev *dc)
{
- struct cached_dev *dc = container_of(cl, struct cached_dev,
- writeback.cl);
- unsigned delay = writeback_delay(dc, 0);
+ unsigned delay = 0;
struct keybuf_key *w;
struct dirty_io *io;
+ struct closure cl;
+
+ closure_init_stack(&cl);
/*
* XXX: if we error, background writeback just spins. Should use some
* mempools.
*/
- while (1) {
+ while (!kthread_should_stop()) {
+ try_to_freeze();
+
w = bch_keybuf_next(&dc->writeback_keys);
if (!w)
break;
BUG_ON(ptr_stale(dc->disk.c, &w->key, 0));
- if (delay > 0 &&
- (KEY_START(&w->key) != dc->last_read ||
- jiffies_to_msecs(delay) > 50))
- delay = schedule_timeout_uninterruptible(delay);
+ if (KEY_START(&w->key) != dc->last_read ||
+ jiffies_to_msecs(delay) > 50)
+ while (!kthread_should_stop() && delay)
+ delay = schedule_timeout_interruptible(delay);
dc->last_read = KEY_OFFSET(&w->key);
@@ -423,7 +267,7 @@ static void read_dirty(struct closure *cl)
trace_bcache_writeback(&w->key);
down(&dc->in_flight);
- closure_call(&io->cl, read_dirty_submit, NULL, cl);
+ closure_call(&io->cl, read_dirty_submit, NULL, &cl);
delay = writeback_delay(dc, KEY_SIZE(&w->key));
}
@@ -439,52 +283,205 @@ err:
* Wait for outstanding writeback IOs to finish (and keybuf slots to be
* freed) before refilling again
*/
- continue_at(cl, refill_dirty, dirty_wq);
+ closure_sync(&cl);
}
-/* Init */
+/* Scan for dirty data */
+
+void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned inode,
+ uint64_t offset, int nr_sectors)
+{
+ struct bcache_device *d = c->devices[inode];
+ unsigned stripe_offset, stripe, sectors_dirty;
+
+ if (!d)
+ return;
+
+ stripe = offset_to_stripe(d, offset);
+ stripe_offset = offset & (d->stripe_size - 1);
+
+ while (nr_sectors) {
+ int s = min_t(unsigned, abs(nr_sectors),
+ d->stripe_size - stripe_offset);
+
+ if (nr_sectors < 0)
+ s = -s;
+
+ if (stripe >= d->nr_stripes)
+ return;
+
+ sectors_dirty = atomic_add_return(s,
+ d->stripe_sectors_dirty + stripe);
+ if (sectors_dirty == d->stripe_size)
+ set_bit(stripe, d->full_dirty_stripes);
+ else
+ clear_bit(stripe, d->full_dirty_stripes);
+
+ nr_sectors -= s;
+ stripe_offset = 0;
+ stripe++;
+ }
+}
-static int bch_btree_sectors_dirty_init(struct btree *b, struct btree_op *op,
- struct cached_dev *dc)
+static bool dirty_pred(struct keybuf *buf, struct bkey *k)
{
- struct bkey *k;
- struct btree_iter iter;
-
- bch_btree_iter_init(b, &iter, &KEY(dc->disk.id, 0, 0));
- while ((k = bch_btree_iter_next_filter(&iter, b, bch_ptr_bad)))
- if (!b->level) {
- if (KEY_INODE(k) > dc->disk.id)
- break;
-
- if (KEY_DIRTY(k))
- bcache_dev_sectors_dirty_add(b->c, dc->disk.id,
- KEY_START(k),
- KEY_SIZE(k));
- } else {
- btree(sectors_dirty_init, k, b, op, dc);
- if (KEY_INODE(k) > dc->disk.id)
- break;
-
- cond_resched();
+ return KEY_DIRTY(k);
+}
+
+static void refill_full_stripes(struct cached_dev *dc)
+{
+ struct keybuf *buf = &dc->writeback_keys;
+ unsigned start_stripe, stripe, next_stripe;
+ bool wrapped = false;
+
+ stripe = offset_to_stripe(&dc->disk, KEY_OFFSET(&buf->last_scanned));
+
+ if (stripe >= dc->disk.nr_stripes)
+ stripe = 0;
+
+ start_stripe = stripe;
+
+ while (1) {
+ stripe = find_next_bit(dc->disk.full_dirty_stripes,
+ dc->disk.nr_stripes, stripe);
+
+ if (stripe == dc->disk.nr_stripes)
+ goto next;
+
+ next_stripe = find_next_zero_bit(dc->disk.full_dirty_stripes,
+ dc->disk.nr_stripes, stripe);
+
+ buf->last_scanned = KEY(dc->disk.id,
+ stripe * dc->disk.stripe_size, 0);
+
+ bch_refill_keybuf(dc->disk.c, buf,
+ &KEY(dc->disk.id,
+ next_stripe * dc->disk.stripe_size, 0),
+ dirty_pred);
+
+ if (array_freelist_empty(&buf->freelist))
+ return;
+
+ stripe = next_stripe;
+next:
+ if (wrapped && stripe > start_stripe)
+ return;
+
+ if (stripe == dc->disk.nr_stripes) {
+ stripe = 0;
+ wrapped = true;
}
+ }
+}
+
+static bool refill_dirty(struct cached_dev *dc)
+{
+ struct keybuf *buf = &dc->writeback_keys;
+ struct bkey end = KEY(dc->disk.id, MAX_KEY_OFFSET, 0);
+ bool searched_from_start = false;
+
+ if (dc->partial_stripes_expensive) {
+ refill_full_stripes(dc);
+ if (array_freelist_empty(&buf->freelist))
+ return false;
+ }
+
+ if (bkey_cmp(&buf->last_scanned, &end) >= 0) {
+ buf->last_scanned = KEY(dc->disk.id, 0, 0);
+ searched_from_start = true;
+ }
+
+ bch_refill_keybuf(dc->disk.c, buf, &end, dirty_pred);
+
+ return bkey_cmp(&buf->last_scanned, &end) >= 0 && searched_from_start;
+}
+
+static int bch_writeback_thread(void *arg)
+{
+ struct cached_dev *dc = arg;
+ bool searched_full_index;
+
+ while (!kthread_should_stop()) {
+ down_write(&dc->writeback_lock);
+ if (!atomic_read(&dc->has_dirty) ||
+ (!test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) &&
+ !dc->writeback_running)) {
+ up_write(&dc->writeback_lock);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if (kthread_should_stop())
+ return 0;
+
+ try_to_freeze();
+ schedule();
+ continue;
+ }
+
+ searched_full_index = refill_dirty(dc);
+
+ if (searched_full_index &&
+ RB_EMPTY_ROOT(&dc->writeback_keys.keys)) {
+ atomic_set(&dc->has_dirty, 0);
+ cached_dev_put(dc);
+ SET_BDEV_STATE(&dc->sb, BDEV_STATE_CLEAN);
+ bch_write_bdev_super(dc, NULL);
+ }
+
+ up_write(&dc->writeback_lock);
+
+ bch_ratelimit_reset(&dc->writeback_rate);
+ read_dirty(dc);
+
+ if (searched_full_index) {
+ unsigned delay = dc->writeback_delay * HZ;
+
+ while (delay &&
+ !kthread_should_stop() &&
+ !test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags))
+ delay = schedule_timeout_interruptible(delay);
+ }
+ }
return 0;
}
+/* Init */
+
+struct sectors_dirty_init {
+ struct btree_op op;
+ unsigned inode;
+};
+
+static int sectors_dirty_init_fn(struct btree_op *_op, struct btree *b,
+ struct bkey *k)
+{
+ struct sectors_dirty_init *op = container_of(_op,
+ struct sectors_dirty_init, op);
+ if (KEY_INODE(k) > op->inode)
+ return MAP_DONE;
+
+ if (KEY_DIRTY(k))
+ bcache_dev_sectors_dirty_add(b->c, KEY_INODE(k),
+ KEY_START(k), KEY_SIZE(k));
+
+ return MAP_CONTINUE;
+}
+
void bch_sectors_dirty_init(struct cached_dev *dc)
{
- struct btree_op op;
+ struct sectors_dirty_init op;
+
+ bch_btree_op_init(&op.op, -1);
+ op.inode = dc->disk.id;
- bch_btree_op_init_stack(&op);
- btree_root(sectors_dirty_init, dc->disk.c, &op, dc);
+ bch_btree_map_keys(&op.op, dc->disk.c, &KEY(op.inode, 0, 0),
+ sectors_dirty_init_fn, 0);
}
-void bch_cached_dev_writeback_init(struct cached_dev *dc)
+int bch_cached_dev_writeback_init(struct cached_dev *dc)
{
sema_init(&dc->in_flight, 64);
- closure_init_unlocked(&dc->writeback);
init_rwsem(&dc->writeback_lock);
-
bch_keybuf_init(&dc->writeback_keys);
dc->writeback_metadata = true;
@@ -498,22 +495,16 @@ void bch_cached_dev_writeback_init(struct cached_dev *dc)
dc->writeback_rate_p_term_inverse = 64;
dc->writeback_rate_d_smooth = 8;
+ dc->writeback_thread = kthread_create(bch_writeback_thread, dc,
+ "bcache_writeback");
+ if (IS_ERR(dc->writeback_thread))
+ return PTR_ERR(dc->writeback_thread);
+
+ set_task_state(dc->writeback_thread, TASK_INTERRUPTIBLE);
+
INIT_DELAYED_WORK(&dc->writeback_rate_update, update_writeback_rate);
schedule_delayed_work(&dc->writeback_rate_update,
dc->writeback_rate_update_seconds * HZ);
-}
-
-void bch_writeback_exit(void)
-{
- if (dirty_wq)
- destroy_workqueue(dirty_wq);
-}
-
-int __init bch_writeback_init(void)
-{
- dirty_wq = create_workqueue("bcache_writeback");
- if (!dirty_wq)
- return -ENOMEM;
return 0;
}
diff --git a/drivers/md/bcache/writeback.h b/drivers/md/bcache/writeback.h
index c91f61bb95b6..27d19168afb9 100644
--- a/drivers/md/bcache/writeback.h
+++ b/drivers/md/bcache/writeback.h
@@ -14,20 +14,27 @@ static inline uint64_t bcache_dev_sectors_dirty(struct bcache_device *d)
return ret;
}
-static inline bool bcache_dev_stripe_dirty(struct bcache_device *d,
+static inline unsigned offset_to_stripe(struct bcache_device *d,
+ uint64_t offset)
+{
+ do_div(offset, d->stripe_size);
+ return offset;
+}
+
+static inline bool bcache_dev_stripe_dirty(struct cached_dev *dc,
uint64_t offset,
unsigned nr_sectors)
{
- uint64_t stripe = offset >> d->stripe_size_bits;
+ unsigned stripe = offset_to_stripe(&dc->disk, offset);
while (1) {
- if (atomic_read(d->stripe_sectors_dirty + stripe))
+ if (atomic_read(dc->disk.stripe_sectors_dirty + stripe))
return true;
- if (nr_sectors <= 1 << d->stripe_size_bits)
+ if (nr_sectors <= dc->disk.stripe_size)
return false;
- nr_sectors -= 1 << d->stripe_size_bits;
+ nr_sectors -= dc->disk.stripe_size;
stripe++;
}
}
@@ -38,13 +45,12 @@ static inline bool should_writeback(struct cached_dev *dc, struct bio *bio,
unsigned in_use = dc->disk.c->gc_stats.in_use;
if (cache_mode != CACHE_MODE_WRITEBACK ||
- atomic_read(&dc->disk.detaching) ||
+ test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) ||
in_use > CUTOFF_WRITEBACK_SYNC)
return false;
if (dc->partial_stripes_expensive &&
- bcache_dev_stripe_dirty(&dc->disk, bio->bi_sector,
- bio_sectors(bio)))
+ bcache_dev_stripe_dirty(dc, bio->bi_sector, bio_sectors(bio)))
return true;
if (would_skip)
@@ -54,11 +60,30 @@ static inline bool should_writeback(struct cached_dev *dc, struct bio *bio,
in_use <= CUTOFF_WRITEBACK;
}
+static inline void bch_writeback_queue(struct cached_dev *dc)
+{
+ wake_up_process(dc->writeback_thread);
+}
+
+static inline void bch_writeback_add(struct cached_dev *dc)
+{
+ if (!atomic_read(&dc->has_dirty) &&
+ !atomic_xchg(&dc->has_dirty, 1)) {
+ atomic_inc(&dc->count);
+
+ if (BDEV_STATE(&dc->sb) != BDEV_STATE_DIRTY) {
+ SET_BDEV_STATE(&dc->sb, BDEV_STATE_DIRTY);
+ /* XXX: should do this synchronously */
+ bch_write_bdev_super(dc, NULL);
+ }
+
+ bch_writeback_queue(dc);
+ }
+}
+
void bcache_dev_sectors_dirty_add(struct cache_set *, unsigned, uint64_t, int);
-void bch_writeback_queue(struct cached_dev *);
-void bch_writeback_add(struct cached_dev *);
void bch_sectors_dirty_init(struct cached_dev *dc);
-void bch_cached_dev_writeback_init(struct cached_dev *);
+int bch_cached_dev_writeback_init(struct cached_dev *);
#endif
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index a7fd82133b12..12dc29ba7399 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -1654,9 +1654,9 @@ int bitmap_create(struct mddev *mddev)
bitmap->mddev = mddev;
if (mddev->kobj.sd)
- bm = sysfs_get_dirent(mddev->kobj.sd, NULL, "bitmap");
+ bm = sysfs_get_dirent(mddev->kobj.sd, "bitmap");
if (bm) {
- bitmap->sysfs_can_clear = sysfs_get_dirent(bm, NULL, "can_clear");
+ bitmap->sysfs_can_clear = sysfs_get_dirent(bm, "can_clear");
sysfs_put(bm);
} else
bitmap->sysfs_can_clear = NULL;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index adf4d7e1d5e1..8a0d7625681c 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -3555,7 +3555,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
printk(KERN_WARNING
"md: cannot register extra attributes for %s\n",
mdname(mddev));
- mddev->sysfs_action = sysfs_get_dirent(mddev->kobj.sd, NULL, "sync_action");
+ mddev->sysfs_action = sysfs_get_dirent(mddev->kobj.sd, "sync_action");
}
if (mddev->pers->sync_request != NULL &&
pers->sync_request == NULL) {
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 608050c43f17..b0051f2fbc0c 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -501,7 +501,7 @@ extern struct attribute_group md_bitmap_group;
static inline struct sysfs_dirent *sysfs_get_dirent_safe(struct sysfs_dirent *sd, char *name)
{
if (sd)
- return sysfs_get_dirent(sd, NULL, name);
+ return sysfs_get_dirent(sd, name);
return sd;
}
static inline void sysfs_notify_dirent_safe(struct sysfs_dirent *sd)
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 5184887b155c..32fab30a9105 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -1221,16 +1221,16 @@ static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb)
{
struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
- struct vb2_dma_sg_desc *sgd = vb2_dma_sg_plane_desc(vb, 0);
+ struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0);
struct mcam_dma_desc *desc = mvb->dma_desc;
struct scatterlist *sg;
int i;
- mvb->dma_desc_nent = dma_map_sg(cam->dev, sgd->sglist, sgd->num_pages,
- DMA_FROM_DEVICE);
+ mvb->dma_desc_nent = dma_map_sg(cam->dev, sg_table->sgl,
+ sg_table->nents, DMA_FROM_DEVICE);
if (mvb->dma_desc_nent <= 0)
return -EIO; /* Not sure what's right here */
- for_each_sg(sgd->sglist, sg, mvb->dma_desc_nent, i) {
+ for_each_sg(sg_table->sgl, sg, mvb->dma_desc_nent, i) {
desc->dma_addr = sg_dma_address(sg);
desc->segment_len = sg_dma_len(sg);
desc++;
@@ -1241,9 +1241,11 @@ static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb)
static int mcam_vb_sg_buf_finish(struct vb2_buffer *vb)
{
struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
- struct vb2_dma_sg_desc *sgd = vb2_dma_sg_plane_desc(vb, 0);
+ struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0);
- dma_unmap_sg(cam->dev, sgd->sglist, sgd->num_pages, DMA_FROM_DEVICE);
+ if (sg_table)
+ dma_unmap_sg(cam->dev, sg_table->sgl,
+ sg_table->nents, DMA_FROM_DEVICE);
return 0;
}
diff --git a/drivers/media/usb/gspca/conex.c b/drivers/media/usb/gspca/conex.c
index 38714df31ac4..2e15c80d6e3d 100644
--- a/drivers/media/usb/gspca/conex.c
+++ b/drivers/media/usb/gspca/conex.c
@@ -783,7 +783,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
/* create the JPEG header */
- jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+ jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
+ gspca_dev->pixfmt.width,
0x22); /* JPEG 411 */
jpeg_set_qual(sd->jpeg_hdr, QUALITY);
diff --git a/drivers/media/usb/gspca/cpia1.c b/drivers/media/usb/gspca/cpia1.c
index 064b53043b15..f23df4a9d8c5 100644
--- a/drivers/media/usb/gspca/cpia1.c
+++ b/drivers/media/usb/gspca/cpia1.c
@@ -1553,9 +1553,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
sd->params.format.videoSize = VIDEOSIZE_CIF;
sd->params.roi.colEnd = sd->params.roi.colStart +
- (gspca_dev->width >> 3);
+ (gspca_dev->pixfmt.width >> 3);
sd->params.roi.rowEnd = sd->params.roi.rowStart +
- (gspca_dev->height >> 2);
+ (gspca_dev->pixfmt.height >> 2);
/* And now set the camera to a known state */
ret = do_command(gspca_dev, CPIA_COMMAND_SetGrabMode,
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
index 048507b27bb2..f3a7ace0fac9 100644
--- a/drivers/media/usb/gspca/gspca.c
+++ b/drivers/media/usb/gspca/gspca.c
@@ -504,8 +504,7 @@ static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file,
unsigned int frsz;
int i;
- i = gspca_dev->curr_mode;
- frsz = gspca_dev->cam.cam_mode[i].sizeimage;
+ frsz = gspca_dev->pixfmt.sizeimage;
PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz);
frsz = PAGE_ALIGN(frsz);
if (count >= GSPCA_MAX_FRAMES)
@@ -627,16 +626,14 @@ static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
static u32 which_bandwidth(struct gspca_dev *gspca_dev)
{
u32 bandwidth;
- int i;
/* get the (max) image size */
- i = gspca_dev->curr_mode;
- bandwidth = gspca_dev->cam.cam_mode[i].sizeimage;
+ bandwidth = gspca_dev->pixfmt.sizeimage;
/* if the image is compressed, estimate its mean size */
if (!gspca_dev->cam.needs_full_bandwidth &&
- bandwidth < gspca_dev->cam.cam_mode[i].width *
- gspca_dev->cam.cam_mode[i].height)
+ bandwidth < gspca_dev->pixfmt.width *
+ gspca_dev->pixfmt.height)
bandwidth = bandwidth * 3 / 8; /* 0.375 */
/* estimate the frame rate */
@@ -650,7 +647,7 @@ static u32 which_bandwidth(struct gspca_dev *gspca_dev)
/* don't hope more than 15 fps with USB 1.1 and
* image resolution >= 640x480 */
- if (gspca_dev->width >= 640
+ if (gspca_dev->pixfmt.width >= 640
&& gspca_dev->dev->speed == USB_SPEED_FULL)
bandwidth *= 15; /* 15 fps */
else
@@ -982,9 +979,7 @@ static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
i = gspca_dev->cam.nmodes - 1; /* take the highest mode */
gspca_dev->curr_mode = i;
- gspca_dev->width = gspca_dev->cam.cam_mode[i].width;
- gspca_dev->height = gspca_dev->cam.cam_mode[i].height;
- gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixelformat;
+ gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i];
/* does nothing if ctrl_handler == NULL */
v4l2_ctrl_handler_setup(gspca_dev->vdev.ctrl_handler);
@@ -1105,10 +1100,8 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *fmt)
{
struct gspca_dev *gspca_dev = video_drvdata(file);
- int mode;
- mode = gspca_dev->curr_mode;
- fmt->fmt.pix = gspca_dev->cam.cam_mode[mode];
+ fmt->fmt.pix = gspca_dev->pixfmt;
/* some drivers use priv internally, zero it before giving it to
userspace */
fmt->fmt.pix.priv = 0;
@@ -1140,6 +1133,12 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
mode = mode2;
}
fmt->fmt.pix = gspca_dev->cam.cam_mode[mode];
+ if (gspca_dev->sd_desc->try_fmt) {
+ /* pass original resolution to subdriver try_fmt */
+ fmt->fmt.pix.width = w;
+ fmt->fmt.pix.height = h;
+ gspca_dev->sd_desc->try_fmt(gspca_dev, fmt);
+ }
/* some drivers use priv internally, zero it before giving it to
userspace */
fmt->fmt.pix.priv = 0;
@@ -1178,19 +1177,16 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
goto out;
}
- if (ret == gspca_dev->curr_mode) {
- ret = 0;
- goto out; /* same mode */
- }
-
if (gspca_dev->streaming) {
ret = -EBUSY;
goto out;
}
- gspca_dev->width = fmt->fmt.pix.width;
- gspca_dev->height = fmt->fmt.pix.height;
- gspca_dev->pixfmt = fmt->fmt.pix.pixelformat;
gspca_dev->curr_mode = ret;
+ if (gspca_dev->sd_desc->try_fmt)
+ /* subdriver try_fmt can modify format parameters */
+ gspca_dev->pixfmt = fmt->fmt.pix;
+ else
+ gspca_dev->pixfmt = gspca_dev->cam.cam_mode[ret];
ret = 0;
out:
@@ -1205,6 +1201,9 @@ static int vidioc_enum_framesizes(struct file *file, void *priv,
int i;
__u32 index = 0;
+ if (gspca_dev->sd_desc->enum_framesizes)
+ return gspca_dev->sd_desc->enum_framesizes(gspca_dev, fsize);
+
for (i = 0; i < gspca_dev->cam.nmodes; i++) {
if (fsize->pixel_format !=
gspca_dev->cam.cam_mode[i].pixelformat)
@@ -1471,8 +1470,9 @@ static int vidioc_streamon(struct file *file, void *priv,
if (ret < 0)
goto out;
}
- PDEBUG_MODE(gspca_dev, D_STREAM, "stream on OK", gspca_dev->pixfmt,
- gspca_dev->width, gspca_dev->height);
+ PDEBUG_MODE(gspca_dev, D_STREAM, "stream on OK",
+ gspca_dev->pixfmt.pixelformat,
+ gspca_dev->pixfmt.width, gspca_dev->pixfmt.height);
ret = 0;
out:
mutex_unlock(&gspca_dev->queue_lock);
diff --git a/drivers/media/usb/gspca/gspca.h b/drivers/media/usb/gspca/gspca.h
index ac0b11f46f50..300642dc1a17 100644
--- a/drivers/media/usb/gspca/gspca.h
+++ b/drivers/media/usb/gspca/gspca.h
@@ -88,6 +88,10 @@ typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev,
typedef int (*cam_int_pkt_op) (struct gspca_dev *gspca_dev,
u8 *data,
int len);
+typedef void (*cam_format_op) (struct gspca_dev *gspca_dev,
+ struct v4l2_format *fmt);
+typedef int (*cam_frmsize_op) (struct gspca_dev *gspca_dev,
+ struct v4l2_frmsizeenum *fsize);
/* subdriver description */
struct sd_desc {
@@ -109,6 +113,8 @@ struct sd_desc {
cam_set_jpg_op set_jcomp;
cam_streamparm_op get_streamparm;
cam_streamparm_op set_streamparm;
+ cam_format_op try_fmt;
+ cam_frmsize_op enum_framesizes;
#ifdef CONFIG_VIDEO_ADV_DEBUG
cam_set_reg_op set_register;
cam_get_reg_op get_register;
@@ -183,9 +189,7 @@ struct gspca_dev {
__u8 streaming; /* protected by both mutexes (*) */
__u8 curr_mode; /* current camera mode */
- __u32 pixfmt; /* current mode parameters */
- __u16 width;
- __u16 height;
+ struct v4l2_pix_format pixfmt; /* current mode parameters */
__u32 sequence; /* frame sequence number */
wait_queue_head_t wq; /* wait queue */
diff --git a/drivers/media/usb/gspca/jeilinj.c b/drivers/media/usb/gspca/jeilinj.c
index 8da3dde38385..19736e237b37 100644
--- a/drivers/media/usb/gspca/jeilinj.c
+++ b/drivers/media/usb/gspca/jeilinj.c
@@ -378,11 +378,12 @@ static int sd_start(struct gspca_dev *gspca_dev)
struct sd *dev = (struct sd *) gspca_dev;
/* create the JPEG header */
- jpeg_define(dev->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+ jpeg_define(dev->jpeg_hdr, gspca_dev->pixfmt.height,
+ gspca_dev->pixfmt.width,
0x21); /* JPEG 422 */
jpeg_set_qual(dev->jpeg_hdr, dev->quality);
PDEBUG(D_STREAM, "Start streaming at %dx%d",
- gspca_dev->height, gspca_dev->width);
+ gspca_dev->pixfmt.height, gspca_dev->pixfmt.width);
jlj_start(gspca_dev);
return gspca_dev->usb_err;
}
diff --git a/drivers/media/usb/gspca/jl2005bcd.c b/drivers/media/usb/gspca/jl2005bcd.c
index fdaeeb14453f..5b481fa43099 100644
--- a/drivers/media/usb/gspca/jl2005bcd.c
+++ b/drivers/media/usb/gspca/jl2005bcd.c
@@ -455,7 +455,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
sd->cap_mode = gspca_dev->cam.cam_mode;
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 640:
PDEBUG(D_STREAM, "Start streaming at vga resolution");
jl2005c_stream_start_vga_lg(gspca_dev);
diff --git a/drivers/media/usb/gspca/m5602/m5602_mt9m111.c b/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
index cfa4663f8934..27fcef11aef4 100644
--- a/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
+++ b/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
@@ -266,7 +266,7 @@ static int mt9m111_set_hvflip(struct gspca_dev *gspca_dev)
return err;
data[0] = MT9M111_RMB_OVER_SIZED;
- if (gspca_dev->width == 640) {
+ if (gspca_dev->pixfmt.width == 640) {
data[1] = MT9M111_RMB_ROW_SKIP_2X |
MT9M111_RMB_COLUMN_SKIP_2X |
(hflip << 1) | vflip;
diff --git a/drivers/media/usb/gspca/mars.c b/drivers/media/usb/gspca/mars.c
index ff2c5abf115b..779a8785f421 100644
--- a/drivers/media/usb/gspca/mars.c
+++ b/drivers/media/usb/gspca/mars.c
@@ -254,7 +254,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
int i;
/* create the JPEG header */
- jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+ jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
+ gspca_dev->pixfmt.width,
0x21); /* JPEG 422 */
jpeg_set_qual(sd->jpeg_hdr, QUALITY);
@@ -270,8 +271,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
data[0] = 0x00; /* address */
data[1] = 0x0c | 0x01; /* reg 0 */
data[2] = 0x01; /* reg 1 */
- data[3] = gspca_dev->width / 8; /* h_size , reg 2 */
- data[4] = gspca_dev->height / 8; /* v_size , reg 3 */
+ data[3] = gspca_dev->pixfmt.width / 8; /* h_size , reg 2 */
+ data[4] = gspca_dev->pixfmt.height / 8; /* v_size , reg 3 */
data[5] = 0x30; /* reg 4, MI, PAS5101 :
* 0x30 for 24mhz , 0x28 for 12mhz */
data[6] = 0x02; /* reg 5, H start - was 0x04 */
diff --git a/drivers/media/usb/gspca/mr97310a.c b/drivers/media/usb/gspca/mr97310a.c
index 68bb2f359666..f006e29ca019 100644
--- a/drivers/media/usb/gspca/mr97310a.c
+++ b/drivers/media/usb/gspca/mr97310a.c
@@ -521,7 +521,7 @@ static int start_cif_cam(struct gspca_dev *gspca_dev)
if (sd->sensor_type)
data[5] = 0xbb;
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 160:
data[9] |= 0x04; /* reg 8, 2:1 scale down from 320 */
/* fall thru */
@@ -618,7 +618,7 @@ static int start_vga_cam(struct gspca_dev *gspca_dev)
data[10] = 0x18;
}
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 160:
data[9] |= 0x0c; /* reg 8, 4:1 scale down */
/* fall thru */
@@ -847,7 +847,7 @@ static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 min_clockdiv)
u8 clockdiv = (60 * expo + 7999) / 8000;
/* Limit framerate to not exceed usb bandwidth */
- if (clockdiv < min_clockdiv && gspca_dev->width >= 320)
+ if (clockdiv < min_clockdiv && gspca_dev->pixfmt.width >= 320)
clockdiv = min_clockdiv;
else if (clockdiv < 2)
clockdiv = 2;
diff --git a/drivers/media/usb/gspca/nw80x.c b/drivers/media/usb/gspca/nw80x.c
index 44c9964b1b3e..599f755e75b8 100644
--- a/drivers/media/usb/gspca/nw80x.c
+++ b/drivers/media/usb/gspca/nw80x.c
@@ -1708,7 +1708,7 @@ static void setautogain(struct gspca_dev *gspca_dev, s32 val)
reg_r(gspca_dev, 0x1004, 1);
if (gspca_dev->usb_buf[0] & 0x04) { /* if AE_FULL_FRM */
- sd->ae_res = gspca_dev->width * gspca_dev->height;
+ sd->ae_res = gspca_dev->pixfmt.width * gspca_dev->pixfmt.height;
} else { /* get the AE window size */
reg_r(gspca_dev, 0x1011, 8);
w = (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0]
@@ -1717,7 +1717,8 @@ static void setautogain(struct gspca_dev *gspca_dev, s32 val)
- (gspca_dev->usb_buf[7] << 8) - gspca_dev->usb_buf[6];
sd->ae_res = h * w;
if (sd->ae_res == 0)
- sd->ae_res = gspca_dev->width * gspca_dev->height;
+ sd->ae_res = gspca_dev->pixfmt.width *
+ gspca_dev->pixfmt.height;
}
}
@@ -1856,21 +1857,21 @@ static int sd_start(struct gspca_dev *gspca_dev)
reg_w_buf(gspca_dev, cmd);
switch (sd->webcam) {
case P35u:
- if (gspca_dev->width == 320)
+ if (gspca_dev->pixfmt.width == 320)
reg_w_buf(gspca_dev, nw801_start_qvga);
else
reg_w_buf(gspca_dev, nw801_start_vga);
reg_w_buf(gspca_dev, nw801_start_2);
break;
case Kr651us:
- if (gspca_dev->width == 320)
+ if (gspca_dev->pixfmt.width == 320)
reg_w_buf(gspca_dev, kr651_start_qvga);
else
reg_w_buf(gspca_dev, kr651_start_vga);
reg_w_buf(gspca_dev, kr651_start_2);
break;
case Proscope:
- if (gspca_dev->width == 320)
+ if (gspca_dev->pixfmt.width == 320)
reg_w_buf(gspca_dev, proscope_start_qvga);
else
reg_w_buf(gspca_dev, proscope_start_vga);
diff --git a/drivers/media/usb/gspca/ov519.c b/drivers/media/usb/gspca/ov519.c
index 8937d79fd176..c95f32a0c02b 100644
--- a/drivers/media/usb/gspca/ov519.c
+++ b/drivers/media/usb/gspca/ov519.c
@@ -3468,7 +3468,7 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev)
switch (sd->bridge) {
case BRIDGE_OVFX2:
- if (gspca_dev->width != 800)
+ if (gspca_dev->pixfmt.width != 800)
gspca_dev->cam.bulk_size = OVFX2_BULK_SIZE;
else
gspca_dev->cam.bulk_size = 7 * 4096;
@@ -3507,8 +3507,8 @@ static void ov511_mode_init_regs(struct sd *sd)
/* Here I'm assuming that snapshot size == image size.
* I hope that's always true. --claudio
*/
- hsegs = (sd->gspca_dev.width >> 3) - 1;
- vsegs = (sd->gspca_dev.height >> 3) - 1;
+ hsegs = (sd->gspca_dev.pixfmt.width >> 3) - 1;
+ vsegs = (sd->gspca_dev.pixfmt.height >> 3) - 1;
reg_w(sd, R511_CAM_PXCNT, hsegs);
reg_w(sd, R511_CAM_LNCNT, vsegs);
@@ -3541,7 +3541,7 @@ static void ov511_mode_init_regs(struct sd *sd)
case SEN_OV7640:
case SEN_OV7648:
case SEN_OV76BE:
- if (sd->gspca_dev.width == 320)
+ if (sd->gspca_dev.pixfmt.width == 320)
interlaced = 1;
/* Fall through */
case SEN_OV6630:
@@ -3551,7 +3551,7 @@ static void ov511_mode_init_regs(struct sd *sd)
case 30:
case 25:
/* Not enough bandwidth to do 640x480 @ 30 fps */
- if (sd->gspca_dev.width != 640) {
+ if (sd->gspca_dev.pixfmt.width != 640) {
sd->clockdiv = 0;
break;
}
@@ -3584,7 +3584,8 @@ static void ov511_mode_init_regs(struct sd *sd)
/* Check if we have enough bandwidth to disable compression */
fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1;
- needed = fps * sd->gspca_dev.width * sd->gspca_dev.height * 3 / 2;
+ needed = fps * sd->gspca_dev.pixfmt.width *
+ sd->gspca_dev.pixfmt.height * 3 / 2;
/* 1000 isoc packets/sec */
if (needed > 1000 * packet_size) {
/* Enable Y and UV quantization and compression */
@@ -3646,8 +3647,8 @@ static void ov518_mode_init_regs(struct sd *sd)
reg_w(sd, 0x38, 0x80);
}
- hsegs = sd->gspca_dev.width / 16;
- vsegs = sd->gspca_dev.height / 4;
+ hsegs = sd->gspca_dev.pixfmt.width / 16;
+ vsegs = sd->gspca_dev.pixfmt.height / 4;
reg_w(sd, 0x29, hsegs);
reg_w(sd, 0x2a, vsegs);
@@ -3686,7 +3687,8 @@ static void ov518_mode_init_regs(struct sd *sd)
* happened to be with revision < 2 cams using an
* OV7620 and revision 2 cams using an OV7620AE.
*/
- if (sd->revision > 0 && sd->gspca_dev.width == 640) {
+ if (sd->revision > 0 &&
+ sd->gspca_dev.pixfmt.width == 640) {
reg_w(sd, 0x20, 0x60);
reg_w(sd, 0x21, 0x1f);
} else {
@@ -3812,8 +3814,8 @@ static void ov519_mode_init_regs(struct sd *sd)
break;
}
- reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4);
- reg_w(sd, OV519_R11_V_SIZE, sd->gspca_dev.height >> 3);
+ reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.pixfmt.width >> 4);
+ reg_w(sd, OV519_R11_V_SIZE, sd->gspca_dev.pixfmt.height >> 3);
if (sd->sensor == SEN_OV7670 &&
sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
reg_w(sd, OV519_R12_X_OFFSETL, 0x04);
@@ -3947,14 +3949,16 @@ static void mode_init_ov_sensor_regs(struct sd *sd)
}
case SEN_OV3610:
if (qvga) {
- xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4);
- ystart = (776 - gspca_dev->height) / 2;
+ xstart = (1040 - gspca_dev->pixfmt.width) / 2 +
+ (0x1f << 4);
+ ystart = (776 - gspca_dev->pixfmt.height) / 2;
} else {
- xstart = (2076 - gspca_dev->width) / 2 + (0x10 << 4);
- ystart = (1544 - gspca_dev->height) / 2;
+ xstart = (2076 - gspca_dev->pixfmt.width) / 2 +
+ (0x10 << 4);
+ ystart = (1544 - gspca_dev->pixfmt.height) / 2;
}
- xend = xstart + gspca_dev->width;
- yend = ystart + gspca_dev->height;
+ xend = xstart + gspca_dev->pixfmt.width;
+ yend = ystart + gspca_dev->pixfmt.height;
/* Writing to the COMH register resets the other windowing regs
to their default values, so we must do this first. */
i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0xf0);
@@ -4229,8 +4233,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
/* Default for most bridges, allow bridge_mode_init_regs to override */
- sd->sensor_width = sd->gspca_dev.width;
- sd->sensor_height = sd->gspca_dev.height;
+ sd->sensor_width = sd->gspca_dev.pixfmt.width;
+ sd->sensor_height = sd->gspca_dev.pixfmt.height;
switch (sd->bridge) {
case BRIDGE_OV511:
@@ -4345,12 +4349,13 @@ static void ov511_pkt_scan(struct gspca_dev *gspca_dev,
ov51x_handle_button(gspca_dev, (in[8] >> 2) & 1);
if (in[8] & 0x80) {
/* Frame end */
- if ((in[9] + 1) * 8 != gspca_dev->width ||
- (in[10] + 1) * 8 != gspca_dev->height) {
+ if ((in[9] + 1) * 8 != gspca_dev->pixfmt.width ||
+ (in[10] + 1) * 8 != gspca_dev->pixfmt.height) {
PERR("Invalid frame size, got: %dx%d,"
" requested: %dx%d\n",
(in[9] + 1) * 8, (in[10] + 1) * 8,
- gspca_dev->width, gspca_dev->height);
+ gspca_dev->pixfmt.width,
+ gspca_dev->pixfmt.height);
gspca_dev->last_packet_type = DISCARD_PACKET;
return;
}
@@ -4470,7 +4475,8 @@ static void ovfx2_pkt_scan(struct gspca_dev *gspca_dev,
if (sd->first_frame) {
sd->first_frame--;
if (gspca_dev->image_len <
- sd->gspca_dev.width * sd->gspca_dev.height)
+ sd->gspca_dev.pixfmt.width *
+ sd->gspca_dev.pixfmt.height)
gspca_dev->last_packet_type = DISCARD_PACKET;
}
gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
diff --git a/drivers/media/usb/gspca/ov534.c b/drivers/media/usb/gspca/ov534.c
index 03a33c46ca2c..90f0d637cd9d 100644
--- a/drivers/media/usb/gspca/ov534.c
+++ b/drivers/media/usb/gspca/ov534.c
@@ -1440,9 +1440,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
/* If this packet is marked as EOF, end the frame */
} else if (data[1] & UVC_STREAM_EOF) {
sd->last_pts = 0;
- if (gspca_dev->pixfmt == V4L2_PIX_FMT_YUYV
+ if (gspca_dev->pixfmt.pixelformat == V4L2_PIX_FMT_YUYV
&& gspca_dev->image_len + len - 12 !=
- gspca_dev->width * gspca_dev->height * 2) {
+ gspca_dev->pixfmt.width *
+ gspca_dev->pixfmt.height * 2) {
PDEBUG(D_PACK, "wrong sized frame");
goto discard;
}
diff --git a/drivers/media/usb/gspca/pac207.c b/drivers/media/usb/gspca/pac207.c
index 83519be94e58..cd79c180f67b 100644
--- a/drivers/media/usb/gspca/pac207.c
+++ b/drivers/media/usb/gspca/pac207.c
@@ -299,7 +299,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[3], 8);
/* Compression Balance */
- if (gspca_dev->width == 176)
+ if (gspca_dev->pixfmt.width == 176)
pac207_write_reg(gspca_dev, 0x4a, 0xff);
else
pac207_write_reg(gspca_dev, 0x4a, 0x30);
@@ -317,7 +317,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
mode = 0x00;
else
mode = 0x02;
- if (gspca_dev->width == 176) { /* 176x144 */
+ if (gspca_dev->pixfmt.width == 176) { /* 176x144 */
mode |= 0x01;
PDEBUG(D_STREAM, "pac207_start mode 176x144");
} else { /* 352x288 */
diff --git a/drivers/media/usb/gspca/pac7311.c b/drivers/media/usb/gspca/pac7311.c
index 1a5bdc853a80..25f86b1e74a8 100644
--- a/drivers/media/usb/gspca/pac7311.c
+++ b/drivers/media/usb/gspca/pac7311.c
@@ -326,7 +326,7 @@ static void setexposure(struct gspca_dev *gspca_dev, s32 val)
* 640x480 mode and page 4 reg 2 <= 3 then it must be 9
*/
reg_w(gspca_dev, 0xff, 0x01);
- if (gspca_dev->width != 640 && val <= 3)
+ if (gspca_dev->pixfmt.width != 640 && val <= 3)
reg_w(gspca_dev, 0x08, 0x09);
else
reg_w(gspca_dev, 0x08, 0x08);
@@ -337,7 +337,7 @@ static void setexposure(struct gspca_dev *gspca_dev, s32 val)
* camera to use higher compression or we may run out of
* bandwidth.
*/
- if (gspca_dev->width == 640 && val == 2)
+ if (gspca_dev->pixfmt.width == 640 && val == 2)
reg_w(gspca_dev, 0x80, 0x01);
else
reg_w(gspca_dev, 0x80, 0x1c);
@@ -615,7 +615,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
/* Start the new frame with the jpeg header */
pac_start_frame(gspca_dev,
- gspca_dev->height, gspca_dev->width);
+ gspca_dev->pixfmt.height, gspca_dev->pixfmt.width);
}
gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
}
diff --git a/drivers/media/usb/gspca/se401.c b/drivers/media/usb/gspca/se401.c
index 5f729b8aa2bd..5102cea50471 100644
--- a/drivers/media/usb/gspca/se401.c
+++ b/drivers/media/usb/gspca/se401.c
@@ -354,9 +354,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
/* set size + mode */
se401_write_req(gspca_dev, SE401_REQ_SET_WIDTH,
- gspca_dev->width * mult, 0);
+ gspca_dev->pixfmt.width * mult, 0);
se401_write_req(gspca_dev, SE401_REQ_SET_HEIGHT,
- gspca_dev->height * mult, 0);
+ gspca_dev->pixfmt.height * mult, 0);
/*
* HDG: disabled this as it does not seem to do anything
* se401_write_req(gspca_dev, SE401_REQ_SET_OUTPUT_MODE,
@@ -480,7 +480,7 @@ static void sd_complete_frame(struct gspca_dev *gspca_dev, u8 *data, int len)
static void sd_pkt_scan_janggu(struct gspca_dev *gspca_dev, u8 *data, int len)
{
struct sd *sd = (struct sd *)gspca_dev;
- int imagesize = gspca_dev->width * gspca_dev->height;
+ int imagesize = gspca_dev->pixfmt.width * gspca_dev->pixfmt.height;
int i, plen, bits, pixels, info, count;
if (sd->restart_stream)
diff --git a/drivers/media/usb/gspca/sn9c20x.c b/drivers/media/usb/gspca/sn9c20x.c
index f4453d52801b..2a38621cf718 100644
--- a/drivers/media/usb/gspca/sn9c20x.c
+++ b/drivers/media/usb/gspca/sn9c20x.c
@@ -1955,7 +1955,7 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev)
return 0;
}
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 160: /* 160x120 */
gspca_dev->alt = 2;
break;
@@ -1985,8 +1985,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
- int width = gspca_dev->width;
- int height = gspca_dev->height;
+ int width = gspca_dev->pixfmt.width;
+ int height = gspca_dev->pixfmt.height;
u8 fmt, scale = 0;
jpeg_define(sd->jpeg_hdr, height, width,
diff --git a/drivers/media/usb/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c
index d7ff3b9687c5..7277dbd2afcd 100644
--- a/drivers/media/usb/gspca/sonixb.c
+++ b/drivers/media/usb/gspca/sonixb.c
@@ -513,10 +513,7 @@ static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buf)
if (gspca_dev->usb_buf[0] & 0x04) {
if (gspca_dev->usb_buf[0] & 0x08) {
dev_err(gspca_dev->v4l2_dev.dev,
- "i2c error writing %02x %02x %02x %02x"
- " %02x %02x %02x %02x\n",
- buf[0], buf[1], buf[2], buf[3],
- buf[4], buf[5], buf[6], buf[7]);
+ "i2c error writing %8ph\n", buf);
gspca_dev->usb_err = -EIO;
}
return;
@@ -753,7 +750,7 @@ static void setexposure(struct gspca_dev *gspca_dev)
/* In 640x480, if the reg11 has less than 4, the image is
unstable (the bridge goes into a higher compression mode
which we have not reverse engineered yet). */
- if (gspca_dev->width == 640 && reg11 < 4)
+ if (gspca_dev->pixfmt.width == 640 && reg11 < 4)
reg11 = 4;
/* frame exposure time in ms = 1000 * reg11 / 30 ->
diff --git a/drivers/media/usb/gspca/sonixj.c b/drivers/media/usb/gspca/sonixj.c
index 3b5ccb1c4cdf..c69b45d7cfbf 100644
--- a/drivers/media/usb/gspca/sonixj.c
+++ b/drivers/media/usb/gspca/sonixj.c
@@ -2204,7 +2204,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
{ 0x14, 0xe7, 0x1e, 0xdd };
/* create the JPEG header */
- jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+ jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
+ gspca_dev->pixfmt.width,
0x21); /* JPEG 422 */
/* initialize the bridge */
diff --git a/drivers/media/usb/gspca/spca1528.c b/drivers/media/usb/gspca/spca1528.c
index 688592b289ea..f38fd8949609 100644
--- a/drivers/media/usb/gspca/spca1528.c
+++ b/drivers/media/usb/gspca/spca1528.c
@@ -255,7 +255,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
/* initialize the JPEG header */
- jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+ jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
+ gspca_dev->pixfmt.width,
0x22); /* JPEG 411 */
/* the JPEG quality shall be 85% */
diff --git a/drivers/media/usb/gspca/spca500.c b/drivers/media/usb/gspca/spca500.c
index 9f8bf51fd64b..f011a309dd65 100644
--- a/drivers/media/usb/gspca/spca500.c
+++ b/drivers/media/usb/gspca/spca500.c
@@ -608,7 +608,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
__u8 xmult, ymult;
/* create the JPEG header */
- jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+ jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
+ gspca_dev->pixfmt.width,
0x22); /* JPEG 411 */
jpeg_set_qual(sd->jpeg_hdr, QUALITY);
diff --git a/drivers/media/usb/gspca/sq905c.c b/drivers/media/usb/gspca/sq905c.c
index acb19fb9a3df..aa21edc9502d 100644
--- a/drivers/media/usb/gspca/sq905c.c
+++ b/drivers/media/usb/gspca/sq905c.c
@@ -272,7 +272,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
dev->cap_mode = gspca_dev->cam.cam_mode;
/* "Open the shutter" and set size, to start capture */
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 640:
PDEBUG(D_STREAM, "Start streaming at high resolution");
dev->cap_mode++;
diff --git a/drivers/media/usb/gspca/sq930x.c b/drivers/media/usb/gspca/sq930x.c
index b10d0821111c..e274cf19a3ea 100644
--- a/drivers/media/usb/gspca/sq930x.c
+++ b/drivers/media/usb/gspca/sq930x.c
@@ -906,7 +906,8 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev)
gspca_dev->cam.bulk_nurbs = 1; /* there must be one URB only */
sd->do_ctrl = 0;
- gspca_dev->cam.bulk_size = gspca_dev->width * gspca_dev->height + 8;
+ gspca_dev->cam.bulk_size = gspca_dev->pixfmt.width *
+ gspca_dev->pixfmt.height + 8;
return 0;
}
diff --git a/drivers/media/usb/gspca/stk014.c b/drivers/media/usb/gspca/stk014.c
index 8c0982607f25..b0c70fea760b 100644
--- a/drivers/media/usb/gspca/stk014.c
+++ b/drivers/media/usb/gspca/stk014.c
@@ -250,7 +250,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
int ret, value;
/* create the JPEG header */
- jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+ jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
+ gspca_dev->pixfmt.width,
0x22); /* JPEG 411 */
jpeg_set_qual(sd->jpeg_hdr, QUALITY);
@@ -261,7 +262,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
set_par(gspca_dev, 0x00000000);
set_par(gspca_dev, 0x8002e001);
set_par(gspca_dev, 0x14000000);
- if (gspca_dev->width > 320)
+ if (gspca_dev->pixfmt.width > 320)
value = 0x8002e001; /* 640x480 */
else
value = 0x4001f000; /* 320x240 */
diff --git a/drivers/media/usb/gspca/stk1135.c b/drivers/media/usb/gspca/stk1135.c
index 585868835ace..8add2f74deda 100644
--- a/drivers/media/usb/gspca/stk1135.c
+++ b/drivers/media/usb/gspca/stk1135.c
@@ -48,42 +48,11 @@ struct sd {
};
static const struct v4l2_pix_format stk1135_modes[] = {
- {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
- .bytesperline = 160,
- .sizeimage = 160 * 120,
- .colorspace = V4L2_COLORSPACE_SRGB},
- {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
- .bytesperline = 176,
- .sizeimage = 176 * 144,
- .colorspace = V4L2_COLORSPACE_SRGB},
- {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
- .bytesperline = 320,
- .sizeimage = 320 * 240,
- .colorspace = V4L2_COLORSPACE_SRGB},
- {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
- .bytesperline = 352,
- .sizeimage = 352 * 288,
- .colorspace = V4L2_COLORSPACE_SRGB},
+ /* default mode (this driver supports variable resolution) */
{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
.bytesperline = 640,
.sizeimage = 640 * 480,
.colorspace = V4L2_COLORSPACE_SRGB},
- {720, 576, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
- .bytesperline = 720,
- .sizeimage = 720 * 576,
- .colorspace = V4L2_COLORSPACE_SRGB},
- {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
- .bytesperline = 800,
- .sizeimage = 800 * 600,
- .colorspace = V4L2_COLORSPACE_SRGB},
- {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
- .bytesperline = 1024,
- .sizeimage = 1024 * 768,
- .colorspace = V4L2_COLORSPACE_SRGB},
- {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
- .bytesperline = 1280,
- .sizeimage = 1280 * 1024,
- .colorspace = V4L2_COLORSPACE_SRGB},
};
/* -- read a register -- */
@@ -347,16 +316,16 @@ static void stk1135_configure_mt9m112(struct gspca_dev *gspca_dev)
sensor_write(gspca_dev, cfg[i].reg, cfg[i].val);
/* set output size */
- width = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].width;
- height = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].height;
- if (width <= 640) { /* use context A (half readout speed by default) */
+ width = gspca_dev->pixfmt.width;
+ height = gspca_dev->pixfmt.height;
+ if (width <= 640 && height <= 512) { /* context A (half readout speed)*/
sensor_write(gspca_dev, 0x1a7, width);
sensor_write(gspca_dev, 0x1aa, height);
/* set read mode context A */
sensor_write(gspca_dev, 0x0c8, 0x0000);
/* set resize, read mode, vblank, hblank context A */
sensor_write(gspca_dev, 0x2c8, 0x0000);
- } else { /* use context B (full readout speed by default) */
+ } else { /* context B (full readout speed) */
sensor_write(gspca_dev, 0x1a1, width);
sensor_write(gspca_dev, 0x1a4, height);
/* set read mode context B */
@@ -484,8 +453,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, STK1135_REG_CISPO + 3, 0x00);
/* set capture end position */
- width = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].width;
- height = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].height;
+ width = gspca_dev->pixfmt.width;
+ height = gspca_dev->pixfmt.height;
reg_w(gspca_dev, STK1135_REG_CIEPO + 0, width & 0xff);
reg_w(gspca_dev, STK1135_REG_CIEPO + 1, width >> 8);
reg_w(gspca_dev, STK1135_REG_CIEPO + 2, height & 0xff);
@@ -643,6 +612,35 @@ static int sd_init_controls(struct gspca_dev *gspca_dev)
return 0;
}
+void stk1135_try_fmt(struct gspca_dev *gspca_dev, struct v4l2_format *fmt)
+{
+ fmt->fmt.pix.width = clamp(fmt->fmt.pix.width, 32U, 1280U);
+ fmt->fmt.pix.height = clamp(fmt->fmt.pix.height, 32U, 1024U);
+ /* round up to even numbers */
+ fmt->fmt.pix.width += (fmt->fmt.pix.width & 1);
+ fmt->fmt.pix.height += (fmt->fmt.pix.height & 1);
+
+ fmt->fmt.pix.bytesperline = fmt->fmt.pix.width;
+ fmt->fmt.pix.sizeimage = fmt->fmt.pix.width * fmt->fmt.pix.height;
+}
+
+int stk1135_enum_framesizes(struct gspca_dev *gspca_dev,
+ struct v4l2_frmsizeenum *fsize)
+{
+ if (fsize->index != 0 || fsize->pixel_format != V4L2_PIX_FMT_SBGGR8)
+ return -EINVAL;
+
+ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+ fsize->stepwise.min_width = 32;
+ fsize->stepwise.min_height = 32;
+ fsize->stepwise.max_width = 1280;
+ fsize->stepwise.max_height = 1024;
+ fsize->stepwise.step_width = 2;
+ fsize->stepwise.step_height = 2;
+
+ return 0;
+}
+
/* sub-driver description */
static const struct sd_desc sd_desc = {
.name = MODULE_NAME,
@@ -653,6 +651,8 @@ static const struct sd_desc sd_desc = {
.stopN = sd_stopN,
.pkt_scan = sd_pkt_scan,
.dq_callback = stk1135_dq_callback,
+ .try_fmt = stk1135_try_fmt,
+ .enum_framesizes = stk1135_enum_framesizes,
};
/* -- module initialisation -- */
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx.c b/drivers/media/usb/gspca/stv06xx/stv06xx.c
index 55ee7a61c67f..49d209bbf9ee 100644
--- a/drivers/media/usb/gspca/stv06xx/stv06xx.c
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx.c
@@ -452,7 +452,7 @@ frame_data:
NULL, 0);
if (sd->bridge == BRIDGE_ST6422)
- sd->to_skip = gspca_dev->width * 4;
+ sd->to_skip = gspca_dev->pixfmt.width * 4;
if (chunk_len)
PERR("Chunk length is "
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
index 8206b7743300..8d785edcccf2 100644
--- a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
+++ b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
@@ -421,7 +421,7 @@ static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val)
/* Number of pixels counted by the sensor when subsampling the pixels.
* Slightly larger than the real value to avoid oscillation */
- totalpixels = gspca_dev->width * gspca_dev->height;
+ totalpixels = gspca_dev->pixfmt.width * gspca_dev->pixfmt.height;
totalpixels = totalpixels/(8*8) + totalpixels/(64*64);
brightpixels = (totalpixels * val) >> 8;
diff --git a/drivers/media/usb/gspca/sunplus.c b/drivers/media/usb/gspca/sunplus.c
index af8767a9bd4c..a517d185febe 100644
--- a/drivers/media/usb/gspca/sunplus.c
+++ b/drivers/media/usb/gspca/sunplus.c
@@ -715,7 +715,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
int enable;
/* create the JPEG header */
- jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+ jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
+ gspca_dev->pixfmt.width,
0x22); /* JPEG 411 */
jpeg_set_qual(sd->jpeg_hdr, QUALITY);
diff --git a/drivers/media/usb/gspca/topro.c b/drivers/media/usb/gspca/topro.c
index 4cb511ccc5f6..640c2fe760b3 100644
--- a/drivers/media/usb/gspca/topro.c
+++ b/drivers/media/usb/gspca/topro.c
@@ -3856,7 +3856,7 @@ static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
if (sd->bridge == BRIDGE_TP6800) {
val |= 0x08; /* grid compensation enable */
- if (gspca_dev->width == 640)
+ if (gspca_dev->pixfmt.width == 640)
reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */
else
val |= 0x04; /* scaling down enable */
@@ -3880,7 +3880,7 @@ static void set_resolution(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
- if (gspca_dev->width == 320) {
+ if (gspca_dev->pixfmt.width == 320) {
reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x06);
msleep(100);
i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
@@ -3924,7 +3924,7 @@ static int get_fr_idx(struct gspca_dev *gspca_dev)
/* 640x480 * 30 fps does not work */
if (i == 6 /* if 30 fps */
- && gspca_dev->width == 640)
+ && gspca_dev->pixfmt.width == 640)
i = 0x05; /* 15 fps */
} else {
for (i = 0; i < ARRAY_SIZE(rates_6810) - 1; i++) {
@@ -3935,7 +3935,7 @@ static int get_fr_idx(struct gspca_dev *gspca_dev)
/* 640x480 * 30 fps does not work */
if (i == 7 /* if 30 fps */
- && gspca_dev->width == 640)
+ && gspca_dev->pixfmt.width == 640)
i = 6; /* 15 fps */
i |= 0x80; /* clock * 1 */
}
@@ -4554,7 +4554,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width);
+ jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
+ gspca_dev->pixfmt.width);
set_dqt(gspca_dev, sd->quality);
if (sd->bridge == BRIDGE_TP6800) {
if (sd->sensor == SENSOR_CX0342)
@@ -4737,7 +4738,7 @@ static void sd_dq_callback(struct gspca_dev *gspca_dev)
(gspca_dev->usb_buf[26] << 8) + gspca_dev->usb_buf[25] +
(gspca_dev->usb_buf[29] << 8) + gspca_dev->usb_buf[28])
/ 8;
- if (gspca_dev->width == 640)
+ if (gspca_dev->pixfmt.width == 640)
luma /= 4;
reg_w(gspca_dev, 0x7d, 0x00);
diff --git a/drivers/media/usb/gspca/tv8532.c b/drivers/media/usb/gspca/tv8532.c
index 8591324a53e1..d497ba38af0d 100644
--- a/drivers/media/usb/gspca/tv8532.c
+++ b/drivers/media/usb/gspca/tv8532.c
@@ -268,7 +268,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
packet_type0 = packet_type1 = INTER_PACKET;
if (gspca_dev->empty_packet) {
gspca_dev->empty_packet = 0;
- sd->packet = gspca_dev->height / 2;
+ sd->packet = gspca_dev->pixfmt.height / 2;
packet_type0 = FIRST_PACKET;
} else if (sd->packet == 0)
return; /* 2 more lines in 352x288 ! */
@@ -284,9 +284,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
* - 4 bytes
*/
gspca_frame_add(gspca_dev, packet_type0,
- data + 2, gspca_dev->width);
+ data + 2, gspca_dev->pixfmt.width);
gspca_frame_add(gspca_dev, packet_type1,
- data + gspca_dev->width + 5, gspca_dev->width);
+ data + gspca_dev->pixfmt.width + 5,
+ gspca_dev->pixfmt.width);
}
static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
diff --git a/drivers/media/usb/gspca/vicam.c b/drivers/media/usb/gspca/vicam.c
index a2275cfe0b81..103f6c4236b0 100644
--- a/drivers/media/usb/gspca/vicam.c
+++ b/drivers/media/usb/gspca/vicam.c
@@ -121,13 +121,13 @@ static int vicam_read_frame(struct gspca_dev *gspca_dev, u8 *data, int size)
memset(req_data, 0, 16);
req_data[0] = gain;
- if (gspca_dev->width == 256)
+ if (gspca_dev->pixfmt.width == 256)
req_data[1] |= 0x01; /* low nibble x-scale */
- if (gspca_dev->height <= 122) {
+ if (gspca_dev->pixfmt.height <= 122) {
req_data[1] |= 0x10; /* high nibble y-scale */
- unscaled_height = gspca_dev->height * 2;
+ unscaled_height = gspca_dev->pixfmt.height * 2;
} else
- unscaled_height = gspca_dev->height;
+ unscaled_height = gspca_dev->pixfmt.height;
req_data[2] = 0x90; /* unknown, does not seem to do anything */
if (unscaled_height <= 200)
req_data[3] = 0x06; /* vend? */
diff --git a/drivers/media/usb/gspca/w996Xcf.c b/drivers/media/usb/gspca/w996Xcf.c
index 2165da0c7ce1..fb9fe2ef3a6f 100644
--- a/drivers/media/usb/gspca/w996Xcf.c
+++ b/drivers/media/usb/gspca/w996Xcf.c
@@ -430,11 +430,11 @@ static void w9968cf_set_crop_window(struct sd *sd)
#define SC(x) ((x) << 10)
/* Scaling factors */
- fw = SC(sd->gspca_dev.width) / max_width;
- fh = SC(sd->gspca_dev.height) / max_height;
+ fw = SC(sd->gspca_dev.pixfmt.width) / max_width;
+ fh = SC(sd->gspca_dev.pixfmt.height) / max_height;
- cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width) / fh;
- ch = (fw >= fh) ? SC(sd->gspca_dev.height) / fw : max_height;
+ cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.pixfmt.width) / fh;
+ ch = (fw >= fh) ? SC(sd->gspca_dev.pixfmt.height) / fw : max_height;
sd->sensor_width = max_width;
sd->sensor_height = max_height;
@@ -454,34 +454,34 @@ static void w9968cf_mode_init_regs(struct sd *sd)
w9968cf_set_crop_window(sd);
- reg_w(sd, 0x14, sd->gspca_dev.width);
- reg_w(sd, 0x15, sd->gspca_dev.height);
+ reg_w(sd, 0x14, sd->gspca_dev.pixfmt.width);
+ reg_w(sd, 0x15, sd->gspca_dev.pixfmt.height);
/* JPEG width & height */
- reg_w(sd, 0x30, sd->gspca_dev.width);
- reg_w(sd, 0x31, sd->gspca_dev.height);
+ reg_w(sd, 0x30, sd->gspca_dev.pixfmt.width);
+ reg_w(sd, 0x31, sd->gspca_dev.pixfmt.height);
/* Y & UV frame buffer strides (in WORD) */
if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
V4L2_PIX_FMT_JPEG) {
- reg_w(sd, 0x2c, sd->gspca_dev.width / 2);
- reg_w(sd, 0x2d, sd->gspca_dev.width / 4);
+ reg_w(sd, 0x2c, sd->gspca_dev.pixfmt.width / 2);
+ reg_w(sd, 0x2d, sd->gspca_dev.pixfmt.width / 4);
} else
- reg_w(sd, 0x2c, sd->gspca_dev.width);
+ reg_w(sd, 0x2c, sd->gspca_dev.pixfmt.width);
reg_w(sd, 0x00, 0xbf17); /* reset everything */
reg_w(sd, 0x00, 0xbf10); /* normal operation */
/* Transfer size in WORDS (for UYVY format only) */
- val = sd->gspca_dev.width * sd->gspca_dev.height;
+ val = sd->gspca_dev.pixfmt.width * sd->gspca_dev.pixfmt.height;
reg_w(sd, 0x3d, val & 0xffff); /* low bits */
reg_w(sd, 0x3e, val >> 16); /* high bits */
if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
V4L2_PIX_FMT_JPEG) {
/* We may get called multiple times (usb isoc bw negotiat.) */
- jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height,
- sd->gspca_dev.width, 0x22); /* JPEG 420 */
+ jpeg_define(sd->jpeg_hdr, sd->gspca_dev.pixfmt.height,
+ sd->gspca_dev.pixfmt.width, 0x22); /* JPEG 420 */
jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual));
w9968cf_upload_quantizationtables(sd);
v4l2_ctrl_grab(sd->jpegqual, true);
diff --git a/drivers/media/usb/gspca/xirlink_cit.c b/drivers/media/usb/gspca/xirlink_cit.c
index 7eaf64eb867c..a41aa7817c54 100644
--- a/drivers/media/usb/gspca/xirlink_cit.c
+++ b/drivers/media/usb/gspca/xirlink_cit.c
@@ -1471,14 +1471,14 @@ static int cit_get_clock_div(struct gspca_dev *gspca_dev)
while (clock_div > 3 &&
1000 * packet_size >
- gspca_dev->width * gspca_dev->height *
+ gspca_dev->pixfmt.width * gspca_dev->pixfmt.height *
fps[clock_div - 1] * 3 / 2)
clock_div--;
PDEBUG(D_PROBE,
"PacketSize: %d, res: %dx%d -> using clockdiv: %d (%d fps)",
- packet_size, gspca_dev->width, gspca_dev->height, clock_div,
- fps[clock_div]);
+ packet_size, gspca_dev->pixfmt.width, gspca_dev->pixfmt.height,
+ clock_div, fps[clock_div]);
return clock_div;
}
@@ -1502,7 +1502,7 @@ static int cit_start_model0(struct gspca_dev *gspca_dev)
cit_write_reg(gspca_dev, 0x0002, 0x0426);
cit_write_reg(gspca_dev, 0x0014, 0x0427);
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 160: /* 160x120 */
cit_write_reg(gspca_dev, 0x0004, 0x010b);
cit_write_reg(gspca_dev, 0x0001, 0x010a);
@@ -1643,7 +1643,7 @@ static int cit_start_model1(struct gspca_dev *gspca_dev)
cit_write_reg(gspca_dev, 0x00, 0x0101);
cit_write_reg(gspca_dev, 0x00, 0x010a);
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 128: /* 128x96 */
cit_write_reg(gspca_dev, 0x80, 0x0103);
cit_write_reg(gspca_dev, 0x60, 0x0105);
@@ -1700,7 +1700,7 @@ static int cit_start_model1(struct gspca_dev *gspca_dev)
}
/* Assorted init */
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 128: /* 128x96 */
cit_Packet_Format1(gspca_dev, 0x2b, 0x1e);
cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */
@@ -1753,7 +1753,7 @@ static int cit_start_model2(struct gspca_dev *gspca_dev)
cit_write_reg(gspca_dev, 0x0000, 0x0108);
cit_write_reg(gspca_dev, 0x0001, 0x0133);
cit_write_reg(gspca_dev, 0x0001, 0x0102);
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 176: /* 176x144 */
cit_write_reg(gspca_dev, 0x002c, 0x0103); /* All except 320x240 */
cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */
@@ -1792,7 +1792,7 @@ static int cit_start_model2(struct gspca_dev *gspca_dev)
cit_write_reg(gspca_dev, 0x0000, 0x0100); /* LED on */
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 176: /* 176x144 */
cit_write_reg(gspca_dev, 0x0050, 0x0111);
cit_write_reg(gspca_dev, 0x00d0, 0x0111);
@@ -1840,7 +1840,7 @@ static int cit_start_model2(struct gspca_dev *gspca_dev)
* Magic control of CMOS sensor. Only lower values like
* 0-3 work, and picture shifts left or right. Don't change.
*/
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 176: /* 176x144 */
cit_model2_Packet1(gspca_dev, 0x0014, 0x0002);
cit_model2_Packet1(gspca_dev, 0x0016, 0x0002); /* Horizontal shift */
@@ -1899,7 +1899,7 @@ static int cit_start_model2(struct gspca_dev *gspca_dev)
* does not allow arbitrary values and apparently is a bit mask, to
* be activated only at appropriate time. Don't change it randomly!
*/
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 176: /* 176x144 */
cit_model2_Packet1(gspca_dev, 0x0026, 0x00c2);
break;
@@ -2023,7 +2023,7 @@ static int cit_start_model3(struct gspca_dev *gspca_dev)
cit_model3_Packet1(gspca_dev, 0x009e, 0x0096);
cit_model3_Packet1(gspca_dev, 0x009f, 0x000a);
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 160:
cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */
cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */
@@ -2134,7 +2134,7 @@ static int cit_start_model3(struct gspca_dev *gspca_dev)
like with the IBM netcam pro). */
cit_write_reg(gspca_dev, clock_div, 0x0111); /* Clock Divider */
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 160:
cit_model3_Packet1(gspca_dev, 0x001f, 0x0000); /* Same */
cit_model3_Packet1(gspca_dev, 0x0039, 0x001f); /* Same */
@@ -2211,7 +2211,7 @@ static int cit_start_model4(struct gspca_dev *gspca_dev)
cit_write_reg(gspca_dev, 0xfffa, 0x0124);
cit_model4_Packet1(gspca_dev, 0x0034, 0x0000);
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 128: /* 128x96 */
cit_write_reg(gspca_dev, 0x0070, 0x0119);
cit_write_reg(gspca_dev, 0x00d0, 0x0111);
@@ -2531,7 +2531,7 @@ static int cit_start_ibm_netcam_pro(struct gspca_dev *gspca_dev)
cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 160: /* 160x120 */
cit_write_reg(gspca_dev, 0x0024, 0x010b);
cit_write_reg(gspca_dev, 0x0089, 0x0119);
@@ -2635,7 +2635,7 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev)
struct usb_host_interface *alt;
int max_packet_size;
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 160:
max_packet_size = 450;
break;
@@ -2659,7 +2659,7 @@ static int sd_isoc_nego(struct gspca_dev *gspca_dev)
int ret, packet_size, min_packet_size;
struct usb_host_interface *alt;
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 160:
min_packet_size = 200;
break;
@@ -2780,7 +2780,7 @@ static u8 *cit_find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
case CIT_MODEL1:
case CIT_MODEL3:
case CIT_IBM_NETCAM_PRO:
- switch (gspca_dev->width) {
+ switch (gspca_dev->pixfmt.width) {
case 160: /* 160x120 */
byte3 = 0x02;
byte4 = 0x0a;
@@ -2864,20 +2864,16 @@ static u8 *cit_find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
if (data[i] == 0xff) {
if (i >= 4)
PDEBUG(D_FRAM,
- "header found at offset: %d: %02x %02x 00 %02x %02x %02x\n",
+ "header found at offset: %d: %02x %02x 00 %3ph\n",
i - 1,
data[i - 4],
data[i - 3],
- data[i],
- data[i + 1],
- data[i + 2]);
+ &data[i]);
else
PDEBUG(D_FRAM,
- "header found at offset: %d: 00 %02x %02x %02x\n",
+ "header found at offset: %d: 00 %3ph\n",
i - 1,
- data[i],
- data[i + 1],
- data[i + 2]);
+ &data[i]);
return data + i + (sd->sof_len - 1);
}
break;
diff --git a/drivers/media/usb/gspca/zc3xx.c b/drivers/media/usb/gspca/zc3xx.c
index cbfc2f921427..7b95d8e88a20 100644
--- a/drivers/media/usb/gspca/zc3xx.c
+++ b/drivers/media/usb/gspca/zc3xx.c
@@ -6700,7 +6700,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
};
/* create the JPEG header */
- jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+ jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
+ gspca_dev->pixfmt.width,
0x21); /* JPEG 422 */
mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c
index c43c8d32be40..be77482c3070 100644
--- a/drivers/media/usb/stkwebcam/stk-webcam.c
+++ b/drivers/media/usb/stkwebcam/stk-webcam.c
@@ -111,6 +111,13 @@ static const struct dmi_system_id stk_upside_down_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "F3JC")
}
},
+ {
+ .ident = "T12Rg-H",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HCL Infosystems Limited"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "T12Rg-H")
+ }
+ },
{}
};
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 594c75eab5a5..fc8af507beac 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -1013,6 +1013,10 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
/* Check if the provided plane buffer is large enough */
if (planes[plane].length < q->plane_sizes[plane]) {
+ dprintk(1, "qbuf: provided buffer size %u is less than "
+ "setup size %u for plane %d\n",
+ planes[plane].length,
+ q->plane_sizes[plane], plane);
ret = -EINVAL;
goto err;
}
@@ -1203,8 +1207,11 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
int ret;
ret = __verify_length(vb, b);
- if (ret < 0)
+ if (ret < 0) {
+ dprintk(1, "%s(): plane parameters verification failed: %d\n",
+ __func__, ret);
return ret;
+ }
switch (q->memory) {
case V4L2_MEMORY_MMAP:
@@ -2467,10 +2474,11 @@ size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
}
EXPORT_SYMBOL_GPL(vb2_read);
-size_t vb2_write(struct vb2_queue *q, char __user *data, size_t count,
+size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
loff_t *ppos, int nonblocking)
{
- return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 0);
+ return __vb2_perform_fileio(q, (char __user *) data, count,
+ ppos, nonblocking, 0);
}
EXPORT_SYMBOL_GPL(vb2_write);
@@ -2631,7 +2639,7 @@ int vb2_fop_release(struct file *file)
}
EXPORT_SYMBOL_GPL(vb2_fop_release);
-ssize_t vb2_fop_write(struct file *file, char __user *buf,
+ssize_t vb2_fop_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
struct video_device *vdev = video_devdata(file);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 16ae3dcc7e29..2f860543912c 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -35,17 +35,61 @@ struct vb2_dma_sg_buf {
struct page **pages;
int write;
int offset;
- struct vb2_dma_sg_desc sg_desc;
+ struct sg_table sg_table;
+ size_t size;
+ unsigned int num_pages;
atomic_t refcount;
struct vb2_vmarea_handler handler;
};
static void vb2_dma_sg_put(void *buf_priv);
+static int vb2_dma_sg_alloc_compacted(struct vb2_dma_sg_buf *buf,
+ gfp_t gfp_flags)
+{
+ unsigned int last_page = 0;
+ int size = buf->size;
+
+ while (size > 0) {
+ struct page *pages;
+ int order;
+ int i;
+
+ order = get_order(size);
+ /* Dont over allocate*/
+ if ((PAGE_SIZE << order) > size)
+ order--;
+
+ pages = NULL;
+ while (!pages) {
+ pages = alloc_pages(GFP_KERNEL | __GFP_ZERO |
+ __GFP_NOWARN | gfp_flags, order);
+ if (pages)
+ break;
+
+ if (order == 0) {
+ while (last_page--)
+ __free_page(buf->pages[last_page]);
+ return -ENOMEM;
+ }
+ order--;
+ }
+
+ split_page(pages, order);
+ for (i = 0; i < (1 << order); i++)
+ buf->pages[last_page++] = &pages[i];
+
+ size -= PAGE_SIZE << order;
+ }
+
+ return 0;
+}
+
static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
{
struct vb2_dma_sg_buf *buf;
- int i;
+ int ret;
+ int num_pages;
buf = kzalloc(sizeof *buf, GFP_KERNEL);
if (!buf)
@@ -54,29 +98,23 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_fla
buf->vaddr = NULL;
buf->write = 0;
buf->offset = 0;
- buf->sg_desc.size = size;
+ buf->size = size;
/* size is already page aligned */
- buf->sg_desc.num_pages = size >> PAGE_SHIFT;
+ buf->num_pages = size >> PAGE_SHIFT;
- buf->sg_desc.sglist = vzalloc(buf->sg_desc.num_pages *
- sizeof(*buf->sg_desc.sglist));
- if (!buf->sg_desc.sglist)
- goto fail_sglist_alloc;
- sg_init_table(buf->sg_desc.sglist, buf->sg_desc.num_pages);
-
- buf->pages = kzalloc(buf->sg_desc.num_pages * sizeof(struct page *),
+ buf->pages = kzalloc(buf->num_pages * sizeof(struct page *),
GFP_KERNEL);
if (!buf->pages)
goto fail_pages_array_alloc;
- for (i = 0; i < buf->sg_desc.num_pages; ++i) {
- buf->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO |
- __GFP_NOWARN | gfp_flags);
- if (NULL == buf->pages[i])
- goto fail_pages_alloc;
- sg_set_page(&buf->sg_desc.sglist[i],
- buf->pages[i], PAGE_SIZE, 0);
- }
+ ret = vb2_dma_sg_alloc_compacted(buf, gfp_flags);
+ if (ret)
+ goto fail_pages_alloc;
+
+ ret = sg_alloc_table_from_pages(&buf->sg_table, buf->pages,
+ buf->num_pages, 0, size, gfp_flags);
+ if (ret)
+ goto fail_table_alloc;
buf->handler.refcount = &buf->refcount;
buf->handler.put = vb2_dma_sg_put;
@@ -85,18 +123,16 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_fla
atomic_inc(&buf->refcount);
dprintk(1, "%s: Allocated buffer of %d pages\n",
- __func__, buf->sg_desc.num_pages);
+ __func__, buf->num_pages);
return buf;
+fail_table_alloc:
+ num_pages = buf->num_pages;
+ while (num_pages--)
+ __free_page(buf->pages[num_pages]);
fail_pages_alloc:
- while (--i >= 0)
- __free_page(buf->pages[i]);
kfree(buf->pages);
-
fail_pages_array_alloc:
- vfree(buf->sg_desc.sglist);
-
-fail_sglist_alloc:
kfree(buf);
return NULL;
}
@@ -104,14 +140,14 @@ fail_sglist_alloc:
static void vb2_dma_sg_put(void *buf_priv)
{
struct vb2_dma_sg_buf *buf = buf_priv;
- int i = buf->sg_desc.num_pages;
+ int i = buf->num_pages;
if (atomic_dec_and_test(&buf->refcount)) {
dprintk(1, "%s: Freeing buffer of %d pages\n", __func__,
- buf->sg_desc.num_pages);
+ buf->num_pages);
if (buf->vaddr)
- vm_unmap_ram(buf->vaddr, buf->sg_desc.num_pages);
- vfree(buf->sg_desc.sglist);
+ vm_unmap_ram(buf->vaddr, buf->num_pages);
+ sg_free_table(&buf->sg_table);
while (--i >= 0)
__free_page(buf->pages[i]);
kfree(buf->pages);
@@ -124,7 +160,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
{
struct vb2_dma_sg_buf *buf;
unsigned long first, last;
- int num_pages_from_user, i;
+ int num_pages_from_user;
buf = kzalloc(sizeof *buf, GFP_KERNEL);
if (!buf)
@@ -133,56 +169,41 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
buf->vaddr = NULL;
buf->write = write;
buf->offset = vaddr & ~PAGE_MASK;
- buf->sg_desc.size = size;
+ buf->size = size;
first = (vaddr & PAGE_MASK) >> PAGE_SHIFT;
last = ((vaddr + size - 1) & PAGE_MASK) >> PAGE_SHIFT;
- buf->sg_desc.num_pages = last - first + 1;
-
- buf->sg_desc.sglist = vzalloc(
- buf->sg_desc.num_pages * sizeof(*buf->sg_desc.sglist));
- if (!buf->sg_desc.sglist)
- goto userptr_fail_sglist_alloc;
-
- sg_init_table(buf->sg_desc.sglist, buf->sg_desc.num_pages);
+ buf->num_pages = last - first + 1;
- buf->pages = kzalloc(buf->sg_desc.num_pages * sizeof(struct page *),
+ buf->pages = kzalloc(buf->num_pages * sizeof(struct page *),
GFP_KERNEL);
if (!buf->pages)
- goto userptr_fail_pages_array_alloc;
+ return NULL;
num_pages_from_user = get_user_pages(current, current->mm,
vaddr & PAGE_MASK,
- buf->sg_desc.num_pages,
+ buf->num_pages,
write,
1, /* force */
buf->pages,
NULL);
- if (num_pages_from_user != buf->sg_desc.num_pages)
+ if (num_pages_from_user != buf->num_pages)
goto userptr_fail_get_user_pages;
- sg_set_page(&buf->sg_desc.sglist[0], buf->pages[0],
- PAGE_SIZE - buf->offset, buf->offset);
- size -= PAGE_SIZE - buf->offset;
- for (i = 1; i < buf->sg_desc.num_pages; ++i) {
- sg_set_page(&buf->sg_desc.sglist[i], buf->pages[i],
- min_t(size_t, PAGE_SIZE, size), 0);
- size -= min_t(size_t, PAGE_SIZE, size);
- }
+ if (sg_alloc_table_from_pages(&buf->sg_table, buf->pages,
+ buf->num_pages, buf->offset, size, 0))
+ goto userptr_fail_alloc_table_from_pages;
+
return buf;
+userptr_fail_alloc_table_from_pages:
userptr_fail_get_user_pages:
dprintk(1, "get_user_pages requested/got: %d/%d]\n",
- num_pages_from_user, buf->sg_desc.num_pages);
+ num_pages_from_user, buf->num_pages);
while (--num_pages_from_user >= 0)
put_page(buf->pages[num_pages_from_user]);
kfree(buf->pages);
-
-userptr_fail_pages_array_alloc:
- vfree(buf->sg_desc.sglist);
-
-userptr_fail_sglist_alloc:
kfree(buf);
return NULL;
}
@@ -194,18 +215,18 @@ userptr_fail_sglist_alloc:
static void vb2_dma_sg_put_userptr(void *buf_priv)
{
struct vb2_dma_sg_buf *buf = buf_priv;
- int i = buf->sg_desc.num_pages;
+ int i = buf->num_pages;
dprintk(1, "%s: Releasing userspace buffer of %d pages\n",
- __func__, buf->sg_desc.num_pages);
+ __func__, buf->num_pages);
if (buf->vaddr)
- vm_unmap_ram(buf->vaddr, buf->sg_desc.num_pages);
+ vm_unmap_ram(buf->vaddr, buf->num_pages);
+ sg_free_table(&buf->sg_table);
while (--i >= 0) {
if (buf->write)
set_page_dirty_lock(buf->pages[i]);
put_page(buf->pages[i]);
}
- vfree(buf->sg_desc.sglist);
kfree(buf->pages);
kfree(buf);
}
@@ -218,7 +239,7 @@ static void *vb2_dma_sg_vaddr(void *buf_priv)
if (!buf->vaddr)
buf->vaddr = vm_map_ram(buf->pages,
- buf->sg_desc.num_pages,
+ buf->num_pages,
-1,
PAGE_KERNEL);
@@ -274,7 +295,7 @@ static void *vb2_dma_sg_cookie(void *buf_priv)
{
struct vb2_dma_sg_buf *buf = buf_priv;
- return &buf->sg_desc;
+ return &buf->sg_table;
}
const struct vb2_mem_ops vb2_dma_sg_memops = {
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 914c3d142f78..d078fe4a82ef 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1151,6 +1151,16 @@ config MFD_WM8994
core support for the WM8994, in order to use the actual
functionaltiy of the device other drivers must be enabled.
+config MFD_STW481X
+ bool "Support for ST Microelectronics STw481x"
+ depends on I2C && ARCH_NOMADIK
+ select REGMAP_I2C
+ select MFD_CORE
+ help
+ Select this option to enable the STw481x chip driver used
+ in various ST Microelectronics and ST-Ericsson embedded
+ Nomadik series.
+
endmenu
endif
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 15b905c6553c..656cec90a1e5 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -162,3 +162,4 @@ obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o
obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o vexpress-sysreg.o
obj-$(CONFIG_MFD_RETU) += retu-mfd.o
obj-$(CONFIG_MFD_AS3711) += as3711.o
+obj-$(CONFIG_MFD_STW481X) += stw481x.o
diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c
index 6f68472e0ca6..14d9542a4eed 100644
--- a/drivers/mfd/aat2870-core.c
+++ b/drivers/mfd/aat2870-core.c
@@ -293,7 +293,7 @@ static ssize_t aat2870_reg_write_file(struct file *file,
unsigned long addr, val;
int ret;
- buf_size = min(count, (sizeof(buf)-1));
+ buf_size = min(count, (size_t)(sizeof(buf)-1));
if (copy_from_user(buf, user_buf, buf_size)) {
dev_err(aat2870->dev, "Failed to copy from user\n");
return -EFAULT;
diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c
index 6a9fec40d018..c319c4ef5d49 100644
--- a/drivers/mfd/da9052-i2c.c
+++ b/drivers/mfd/da9052-i2c.c
@@ -86,7 +86,11 @@ static int da9052_i2c_fix(struct da9052 *da9052, unsigned char reg)
return 0;
}
-static int da9052_i2c_enable_multiwrite(struct da9052 *da9052)
+/*
+ * According to errata item 24, multiwrite mode should be avoided
+ * in order to prevent register data corruption after power-down.
+ */
+static int da9052_i2c_disable_multiwrite(struct da9052 *da9052)
{
int reg_val, ret;
@@ -94,8 +98,8 @@ static int da9052_i2c_enable_multiwrite(struct da9052 *da9052)
if (ret < 0)
return ret;
- if (reg_val & DA9052_CONTROL_B_WRITEMODE) {
- reg_val &= ~DA9052_CONTROL_B_WRITEMODE;
+ if (!(reg_val & DA9052_CONTROL_B_WRITEMODE)) {
+ reg_val |= DA9052_CONTROL_B_WRITEMODE;
ret = regmap_write(da9052->regmap, DA9052_CONTROL_B_REG,
reg_val);
if (ret < 0)
@@ -154,7 +158,7 @@ static int da9052_i2c_probe(struct i2c_client *client,
return ret;
}
- ret = da9052_i2c_enable_multiwrite(da9052);
+ ret = da9052_i2c_disable_multiwrite(da9052);
if (ret < 0)
return ret;
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c
index 7245b0c5b794..2ed774e7d342 100644
--- a/drivers/mfd/ezx-pcap.c
+++ b/drivers/mfd/ezx-pcap.c
@@ -394,16 +394,12 @@ static int pcap_add_subdev(struct pcap_chip *pcap,
static int ezx_pcap_remove(struct spi_device *spi)
{
struct pcap_chip *pcap = spi_get_drvdata(spi);
- struct pcap_platform_data *pdata = dev_get_platdata(&spi->dev);
- int i, adc_irq;
+ int i;
/* remove all registered subdevs */
device_for_each_child(&spi->dev, NULL, pcap_remove_subdev);
/* cleanup ADC */
- adc_irq = pcap_to_irq(pcap, (pdata->config & PCAP_SECOND_PORT) ?
- PCAP_IRQ_ADCDONE2 : PCAP_IRQ_ADCDONE);
- devm_free_irq(&spi->dev, adc_irq, pcap);
mutex_lock(&pcap->adc_mutex);
for (i = 0; i < PCAP_ADC_MAXQ; i++)
kfree(pcap->adc_queue[i]);
@@ -509,8 +505,6 @@ static int ezx_pcap_probe(struct spi_device *spi)
remove_subdevs:
device_for_each_child(&spi->dev, NULL, pcap_remove_subdev);
-/* free_adc: */
- devm_free_irq(&spi->dev, adc_irq, pcap);
free_irqchip:
for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++)
irq_set_chip_and_handler(i, NULL, NULL);
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index 9483bc8472a5..316af07ede3f 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -969,7 +969,6 @@ static int lpc_ich_probe(struct pci_dev *dev,
if (!cell_added) {
dev_warn(&dev->dev, "No MFD cells added\n");
lpc_ich_restore_config_space(dev);
- pci_set_drvdata(dev, NULL);
return -ENODEV;
}
@@ -980,7 +979,6 @@ static void lpc_ich_remove(struct pci_dev *dev)
{
mfd_remove_devices(&dev->dev);
lpc_ich_restore_config_space(dev);
- pci_set_drvdata(dev, NULL);
}
static struct pci_driver lpc_ich_driver = {
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index 2a9b100c4825..dbbf8ee3f592 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -158,8 +158,6 @@ int mc13xxx_reg_read(struct mc13xxx *mc13xxx, unsigned int offset, u32 *val)
{
int ret;
- BUG_ON(!mutex_is_locked(&mc13xxx->lock));
-
if (offset > MC13XXX_NUMREGS)
return -EINVAL;
@@ -172,8 +170,6 @@ EXPORT_SYMBOL(mc13xxx_reg_read);
int mc13xxx_reg_write(struct mc13xxx *mc13xxx, unsigned int offset, u32 val)
{
- BUG_ON(!mutex_is_locked(&mc13xxx->lock));
-
dev_vdbg(mc13xxx->dev, "[0x%02x] <- 0x%06x\n", offset, val);
if (offset > MC13XXX_NUMREGS || val > 0xffffff)
@@ -186,7 +182,6 @@ EXPORT_SYMBOL(mc13xxx_reg_write);
int mc13xxx_reg_rmw(struct mc13xxx *mc13xxx, unsigned int offset,
u32 mask, u32 val)
{
- BUG_ON(!mutex_is_locked(&mc13xxx->lock));
BUG_ON(val & ~mask);
dev_vdbg(mc13xxx->dev, "[0x%02x] <- 0x%06x (mask: 0x%06x)\n",
offset, val, mask);
diff --git a/drivers/mfd/mc13xxx-i2c.c b/drivers/mfd/mc13xxx-i2c.c
index f745e27ee874..898bd335cd8e 100644
--- a/drivers/mfd/mc13xxx-i2c.c
+++ b/drivers/mfd/mc13xxx-i2c.c
@@ -78,7 +78,6 @@ static int mc13xxx_i2c_probe(struct i2c_client *client,
ret = PTR_ERR(mc13xxx->regmap);
dev_err(mc13xxx->dev, "Failed to initialize register map: %d\n",
ret);
- dev_set_drvdata(&client->dev, NULL);
return ret;
}
diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c
index 77189daadf1e..5f14ef6693c2 100644
--- a/drivers/mfd/mc13xxx-spi.c
+++ b/drivers/mfd/mc13xxx-spi.c
@@ -94,10 +94,15 @@ static int mc13xxx_spi_write(void *context, const void *data, size_t count)
{
struct device *dev = context;
struct spi_device *spi = to_spi_device(dev);
+ const char *reg = data;
if (count != 4)
return -ENOTSUPP;
+ /* include errata fix for spi audio problems */
+ if (*reg == MC13783_AUDIO_CODEC || *reg == MC13783_AUDIO_DAC)
+ spi_write(spi, data, count);
+
return spi_write(spi, data, count);
}
diff --git a/drivers/mfd/rts5249.c b/drivers/mfd/rts5249.c
index 3b835f593e35..573de7bfcced 100644
--- a/drivers/mfd/rts5249.c
+++ b/drivers/mfd/rts5249.c
@@ -130,13 +130,57 @@ static int rts5249_optimize_phy(struct rtsx_pcr *pcr)
{
int err;
- err = rtsx_pci_write_phy_register(pcr, PHY_REG_REV, 0xFE46);
+ err = rtsx_pci_write_phy_register(pcr, PHY_REG_REV,
+ PHY_REG_REV_RESV | PHY_REG_REV_RXIDLE_LATCHED |
+ PHY_REG_REV_P1_EN | PHY_REG_REV_RXIDLE_EN |
+ PHY_REG_REV_RX_PWST | PHY_REG_REV_CLKREQ_DLY_TIMER_1_0 |
+ PHY_REG_REV_STOP_CLKRD | PHY_REG_REV_STOP_CLKWR);
if (err < 0)
return err;
msleep(1);
- return rtsx_pci_write_phy_register(pcr, PHY_BPCR, 0x05C0);
+ err = rtsx_pci_write_phy_register(pcr, PHY_BPCR,
+ PHY_BPCR_IBRXSEL | PHY_BPCR_IBTXSEL |
+ PHY_BPCR_IB_FILTER | PHY_BPCR_CMIRROR_EN);
+ if (err < 0)
+ return err;
+ err = rtsx_pci_write_phy_register(pcr, PHY_PCR,
+ PHY_PCR_FORCE_CODE | PHY_PCR_OOBS_CALI_50 |
+ PHY_PCR_OOBS_VCM_08 | PHY_PCR_OOBS_SEN_90 |
+ PHY_PCR_RSSI_EN);
+ if (err < 0)
+ return err;
+ err = rtsx_pci_write_phy_register(pcr, PHY_RCR2,
+ PHY_RCR2_EMPHASE_EN | PHY_RCR2_NADJR |
+ PHY_RCR2_CDR_CP_10 | PHY_RCR2_CDR_SR_2 |
+ PHY_RCR2_FREQSEL_12 | PHY_RCR2_CPADJEN |
+ PHY_RCR2_CDR_SC_8 | PHY_RCR2_CALIB_LATE);
+ if (err < 0)
+ return err;
+ err = rtsx_pci_write_phy_register(pcr, PHY_FLD4,
+ PHY_FLD4_FLDEN_SEL | PHY_FLD4_REQ_REF |
+ PHY_FLD4_RXAMP_OFF | PHY_FLD4_REQ_ADDA |
+ PHY_FLD4_BER_COUNT | PHY_FLD4_BER_TIMER |
+ PHY_FLD4_BER_CHK_EN);
+ if (err < 0)
+ return err;
+ err = rtsx_pci_write_phy_register(pcr, PHY_RDR, PHY_RDR_RXDSEL_1_9);
+ if (err < 0)
+ return err;
+ err = rtsx_pci_write_phy_register(pcr, PHY_RCR1,
+ PHY_RCR1_ADP_TIME | PHY_RCR1_VCO_COARSE);
+ if (err < 0)
+ return err;
+ err = rtsx_pci_write_phy_register(pcr, PHY_FLD3,
+ PHY_FLD3_TIMER_4 | PHY_FLD3_TIMER_6 |
+ PHY_FLD3_RXDELINK);
+ if (err < 0)
+ return err;
+ return rtsx_pci_write_phy_register(pcr, PHY_TUNE,
+ PHY_TUNE_TUNEREF_1_0 | PHY_TUNE_VBGSEL_1252 |
+ PHY_TUNE_SDBUS_33 | PHY_TUNE_TUNED18 |
+ PHY_TUNE_TUNED12);
}
static int rts5249_turn_on_led(struct rtsx_pcr *pcr)
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c
index e6ae7720f9e1..11e20afbdcac 100644
--- a/drivers/mfd/rtsx_pcr.c
+++ b/drivers/mfd/rtsx_pcr.c
@@ -1149,7 +1149,7 @@ static int rtsx_pci_probe(struct pci_dev *pcidev,
pcr->remap_addr = ioremap_nocache(base, len);
if (!pcr->remap_addr) {
ret = -ENOMEM;
- goto free_host;
+ goto free_handle;
}
pcr->rtsx_resv_buf = dma_alloc_coherent(&(pcidev->dev),
@@ -1209,8 +1209,6 @@ disable_msi:
pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr);
unmap:
iounmap(pcr->remap_addr);
-free_host:
- dev_set_drvdata(&pcidev->dev, NULL);
free_handle:
kfree(handle);
free_pcr:
@@ -1242,7 +1240,6 @@ static void rtsx_pci_remove(struct pci_dev *pcidev)
pci_disable_msi(pcr->pci);
iounmap(pcr->remap_addr);
- dev_set_drvdata(&pcidev->dev, NULL);
pci_release_regions(pcidev);
pci_disable_device(pcidev);
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 33f040c558d0..c2c8c91c6c7b 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1232,7 +1232,7 @@ static ssize_t sm501_dbg_regs(struct device *dev,
}
-static DEVICE_ATTR(dbg_regs, 0666, sm501_dbg_regs, NULL);
+static DEVICE_ATTR(dbg_regs, 0444, sm501_dbg_regs, NULL);
/* sm501_init_reg
*
@@ -1660,7 +1660,6 @@ static int sm501_pci_probe(struct pci_dev *dev,
err3:
pci_disable_device(dev);
err2:
- pci_set_drvdata(dev, NULL);
kfree(sm);
err1:
return err;
@@ -1695,7 +1694,6 @@ static void sm501_pci_remove(struct pci_dev *dev)
release_resource(sm->regs_claim);
kfree(sm->regs_claim);
- pci_set_drvdata(dev, NULL);
pci_disable_device(dev);
}
diff --git a/drivers/mfd/stw481x.c b/drivers/mfd/stw481x.c
new file mode 100644
index 000000000000..1243d5c6a448
--- /dev/null
+++ b/drivers/mfd/stw481x.c
@@ -0,0 +1,250 @@
+/*
+ * Core driver for STw4810/STw4811
+ *
+ * Copyright (C) 2013 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ *
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/stw481x.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+
+/*
+ * This driver can only access the non-USB portions of STw4811, the register
+ * range 0x00-0x10 dealing with USB is bound to the two special I2C pins used
+ * for USB control.
+ */
+
+/* Registers inside the power control address space */
+#define STW_PC_VCORE_SEL 0x05U
+#define STW_PC_VAUX_SEL 0x06U
+#define STW_PC_VPLL_SEL 0x07U
+
+/**
+ * stw481x_get_pctl_reg() - get a power control register
+ * @stw481x: handle to the stw481x chip
+ * @reg: power control register to fetch
+ *
+ * The power control registers is a set of one-time-programmable registers
+ * in its own register space, accessed by writing addess bits to these
+ * two registers: bits 7,6,5 of PCTL_REG_LO corresponds to the 3 LSBs of
+ * the address and bits 8,9 of PCTL_REG_HI corresponds to the 2 MSBs of
+ * the address, forming an address space of 5 bits, i.e. 32 registers
+ * 0x00 ... 0x1f can be obtained.
+ */
+static int stw481x_get_pctl_reg(struct stw481x *stw481x, u8 reg)
+{
+ u8 msb = (reg >> 3) & 0x03;
+ u8 lsb = (reg << 5) & 0xe0;
+ unsigned int val;
+ u8 vrfy;
+ int ret;
+
+ ret = regmap_write(stw481x->map, STW_PCTL_REG_HI, msb);
+ if (ret)
+ return ret;
+ ret = regmap_write(stw481x->map, STW_PCTL_REG_LO, lsb);
+ if (ret)
+ return ret;
+ ret = regmap_read(stw481x->map, STW_PCTL_REG_HI, &val);
+ if (ret)
+ return ret;
+ vrfy = (val & 0x03) << 3;
+ ret = regmap_read(stw481x->map, STW_PCTL_REG_LO, &val);
+ if (ret)
+ return ret;
+ vrfy |= ((val >> 5) & 0x07);
+ if (vrfy != reg)
+ return -EIO;
+ return (val >> 1) & 0x0f;
+}
+
+static int stw481x_startup(struct stw481x *stw481x)
+{
+ /* Voltages multiplied by 100 */
+ u8 vcore_val[] = { 100, 105, 110, 115, 120, 122, 124, 126, 128,
+ 130, 132, 134, 136, 138, 140, 145 };
+ u8 vpll_val[] = { 105, 120, 130, 180 };
+ u8 vaux_val[] = { 15, 18, 25, 28 };
+ u8 vcore;
+ u8 vcore_slp;
+ u8 vpll;
+ u8 vaux;
+ bool vaux_en;
+ bool it_warn;
+ int ret;
+ unsigned int val;
+
+ ret = regmap_read(stw481x->map, STW_CONF1, &val);
+ if (ret)
+ return ret;
+ vaux_en = !!(val & STW_CONF1_PDN_VAUX);
+ it_warn = !!(val & STW_CONF1_IT_WARN);
+
+ dev_info(&stw481x->client->dev, "voltages %s\n",
+ (val & STW_CONF1_V_MONITORING) ? "OK" : "LOW");
+ dev_info(&stw481x->client->dev, "MMC level shifter %s\n",
+ (val & STW_CONF1_MMC_LS_STATUS) ? "high impedance" : "ON");
+ dev_info(&stw481x->client->dev, "VMMC: %s\n",
+ (val & STW_CONF1_PDN_VMMC) ? "ON" : "disabled");
+
+ dev_info(&stw481x->client->dev, "STw481x power control registers:\n");
+
+ ret = stw481x_get_pctl_reg(stw481x, STW_PC_VCORE_SEL);
+ if (ret < 0)
+ return ret;
+ vcore = ret & 0x0f;
+
+ ret = stw481x_get_pctl_reg(stw481x, STW_PC_VAUX_SEL);
+ if (ret < 0)
+ return ret;
+ vaux = (ret >> 2) & 3;
+ vpll = (ret >> 4) & 1; /* Save bit 4 */
+
+ ret = stw481x_get_pctl_reg(stw481x, STW_PC_VPLL_SEL);
+ if (ret < 0)
+ return ret;
+ vpll |= (ret >> 1) & 2;
+
+ dev_info(&stw481x->client->dev, "VCORE: %u.%uV %s\n",
+ vcore_val[vcore] / 100, vcore_val[vcore] % 100,
+ (ret & 4) ? "ON" : "OFF");
+
+ dev_info(&stw481x->client->dev, "VPLL: %u.%uV %s\n",
+ vpll_val[vpll] / 100, vpll_val[vpll] % 100,
+ (ret & 0x10) ? "ON" : "OFF");
+
+ dev_info(&stw481x->client->dev, "VAUX: %u.%uV %s\n",
+ vaux_val[vaux] / 10, vaux_val[vaux] % 10,
+ vaux_en ? "ON" : "OFF");
+
+ ret = regmap_read(stw481x->map, STW_CONF2, &val);
+ if (ret)
+ return ret;
+
+ dev_info(&stw481x->client->dev, "TWARN: %s threshold, %s\n",
+ it_warn ? "below" : "above",
+ (val & STW_CONF2_MASK_TWARN) ?
+ "enabled" : "mask through VDDOK");
+ dev_info(&stw481x->client->dev, "VMMC: %s\n",
+ (val & STW_CONF2_VMMC_EXT) ? "internal" : "external");
+ dev_info(&stw481x->client->dev, "IT WAKE UP: %s\n",
+ (val & STW_CONF2_MASK_IT_WAKE_UP) ? "enabled" : "masked");
+ dev_info(&stw481x->client->dev, "GPO1: %s\n",
+ (val & STW_CONF2_GPO1) ? "low" : "high impedance");
+ dev_info(&stw481x->client->dev, "GPO2: %s\n",
+ (val & STW_CONF2_GPO2) ? "low" : "high impedance");
+
+ ret = regmap_read(stw481x->map, STW_VCORE_SLEEP, &val);
+ if (ret)
+ return ret;
+ vcore_slp = val & 0x0f;
+ dev_info(&stw481x->client->dev, "VCORE SLEEP: %u.%uV\n",
+ vcore_val[vcore_slp] / 100, vcore_val[vcore_slp] % 100);
+
+ return 0;
+}
+
+/*
+ * MFD cells - we have one cell which is selected operation
+ * mode, and we always have a GPIO cell.
+ */
+static struct mfd_cell stw481x_cells[] = {
+ {
+ .of_compatible = "st,stw481x-vmmc",
+ .name = "stw481x-vmmc-regulator",
+ .id = -1,
+ },
+};
+
+const struct regmap_config stw481x_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int stw481x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct stw481x *stw481x;
+ int ret;
+ int i;
+
+ stw481x = devm_kzalloc(&client->dev, sizeof(*stw481x), GFP_KERNEL);
+ if (!stw481x)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, stw481x);
+ stw481x->client = client;
+ stw481x->map = devm_regmap_init_i2c(client, &stw481x_regmap_config);
+
+ ret = stw481x_startup(stw481x);
+ if (ret) {
+ dev_err(&client->dev, "chip initialization failed\n");
+ return ret;
+ }
+
+ /* Set up and register the platform devices. */
+ for (i = 0; i < ARRAY_SIZE(stw481x_cells); i++) {
+ /* One state holder for all drivers, this is simple */
+ stw481x_cells[i].platform_data = stw481x;
+ stw481x_cells[i].pdata_size = sizeof(*stw481x);
+ }
+
+ ret = mfd_add_devices(&client->dev, 0, stw481x_cells,
+ ARRAY_SIZE(stw481x_cells), NULL, 0, NULL);
+ if (ret)
+ return ret;
+
+ dev_info(&client->dev, "initialized STw481x device\n");
+
+ return ret;
+}
+
+static int stw481x_remove(struct i2c_client *client)
+{
+ mfd_remove_devices(&client->dev);
+ return 0;
+}
+
+/*
+ * This ID table is completely unused, as this is a pure
+ * device-tree probed driver, but it has to be here due to
+ * the structure of the I2C core.
+ */
+static const struct i2c_device_id stw481x_id[] = {
+ { "stw481x", 0 },
+ { },
+};
+
+static const struct of_device_id stw481x_match[] = {
+ { .compatible = "st,stw4810", },
+ { .compatible = "st,stw4811", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, stw481x_match);
+
+static struct i2c_driver stw481x_driver = {
+ .driver = {
+ .name = "stw481x",
+ .of_match_table = stw481x_match,
+ },
+ .probe = stw481x_probe,
+ .remove = stw481x_remove,
+ .id_table = stw481x_id,
+};
+
+module_i2c_driver(stw481x_driver);
+
+MODULE_AUTHOR("Linus Walleij");
+MODULE_DESCRIPTION("STw481x PMIC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c
index 1c2b994e1f6c..71e3e0c5bf73 100644
--- a/drivers/mfd/ti-ssp.c
+++ b/drivers/mfd/ti-ssp.c
@@ -445,7 +445,6 @@ static int ti_ssp_remove(struct platform_device *pdev)
iounmap(ssp->regs);
release_mem_region(ssp->res->start, resource_size(ssp->res));
kfree(ssp);
- dev_set_drvdata(dev, NULL);
return 0;
}
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index baaf5a8123bb..a3685d6ef674 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -95,7 +95,7 @@ static int ti_tscadc_probe(struct platform_device *pdev)
const __be32 *cur;
u32 val;
int err, ctrl;
- int clk_value, clock_rate;
+ int clock_rate;
int tsc_wires = 0, adc_channels = 0, total_channels;
int readouts = 0;
@@ -196,11 +196,11 @@ static int ti_tscadc_probe(struct platform_device *pdev)
}
clock_rate = clk_get_rate(clk);
clk_put(clk);
- clk_value = clock_rate / ADC_CLK;
+ tscadc->clk_div = clock_rate / ADC_CLK;
/* TSCADC_CLKDIV needs to be configured to the value minus 1 */
- clk_value = clk_value - 1;
- tscadc_writel(tscadc, REG_CLKDIV, clk_value);
+ tscadc->clk_div--;
+ tscadc_writel(tscadc, REG_CLKDIV, tscadc->clk_div);
/* Set the control register bits */
ctrl = CNTRLREG_STEPCONFIGWRT |
@@ -303,6 +303,8 @@ static int tscadc_resume(struct device *dev)
tscadc_writel(tscadc_dev, REG_CTRL,
(restore | CNTRLREG_TSCSSENB));
+ tscadc_writel(tscadc_dev, REG_CLKDIV, tscadc_dev->clk_div);
+
return 0;
}
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
index a6755ec7bd6a..dbb34f94e5e3 100644
--- a/drivers/mfd/timberdale.c
+++ b/drivers/mfd/timberdale.c
@@ -678,7 +678,7 @@ static int timb_probe(struct pci_dev *dev,
priv->ctl_mapbase = mapbase + CHIPCTLOFFSET;
if (!request_mem_region(priv->ctl_mapbase, CHIPCTLSIZE, "timb-ctl")) {
dev_err(&dev->dev, "Failed to request ctl mem\n");
- goto err_request;
+ goto err_start;
}
priv->ctl_membase = ioremap(priv->ctl_mapbase, CHIPCTLSIZE);
@@ -828,13 +828,10 @@ err_config:
iounmap(priv->ctl_membase);
err_ioremap:
release_mem_region(priv->ctl_mapbase, CHIPCTLSIZE);
-err_request:
- pci_set_drvdata(dev, NULL);
err_start:
pci_disable_device(dev);
err_enable:
kfree(priv);
- pci_set_drvdata(dev, NULL);
return -ENODEV;
}
@@ -851,7 +848,6 @@ static void timb_remove(struct pci_dev *dev)
pci_disable_msix(dev);
pci_disable_device(dev);
- pci_set_drvdata(dev, NULL);
kfree(priv);
}
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index f54fe4d4f77b..68906b17ee52 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -124,6 +124,7 @@ struct tps6586x {
struct i2c_client *client;
struct regmap *regmap;
+ int irq;
struct irq_chip irq_chip;
struct mutex irq_lock;
int irq_base;
@@ -261,12 +262,23 @@ static void tps6586x_irq_sync_unlock(struct irq_data *data)
mutex_unlock(&tps6586x->irq_lock);
}
+#ifdef CONFIG_PM_SLEEP
+static int tps6586x_irq_set_wake(struct irq_data *irq_data, unsigned int on)
+{
+ struct tps6586x *tps6586x = irq_data_get_irq_chip_data(irq_data);
+ return irq_set_irq_wake(tps6586x->irq, on);
+}
+#else
+#define tps6586x_irq_set_wake NULL
+#endif
+
static struct irq_chip tps6586x_irq_chip = {
.name = "tps6586x",
.irq_bus_lock = tps6586x_irq_lock,
.irq_bus_sync_unlock = tps6586x_irq_sync_unlock,
.irq_disable = tps6586x_irq_disable,
.irq_enable = tps6586x_irq_enable,
+ .irq_set_wake = tps6586x_irq_set_wake,
};
static int tps6586x_irq_map(struct irq_domain *h, unsigned int virq,
@@ -331,6 +343,8 @@ static int tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
int new_irq_base;
int irq_num = ARRAY_SIZE(tps6586x_irqs);
+ tps6586x->irq = irq;
+
mutex_init(&tps6586x->irq_lock);
for (i = 0; i < 5; i++) {
tps6586x->mask_reg[i] = 0xff;
@@ -360,10 +374,8 @@ static int tps6586x_irq_init(struct tps6586x *tps6586x, int irq,
ret = request_threaded_irq(irq, NULL, tps6586x_irq, IRQF_ONESHOT,
"tps6586x", tps6586x);
- if (!ret) {
+ if (!ret)
device_init_wakeup(tps6586x->dev, 1);
- enable_irq_wake(irq);
- }
return ret;
}
diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c
index daf66942071c..7361dbe96be8 100644
--- a/drivers/mfd/twl6040.c
+++ b/drivers/mfd/twl6040.c
@@ -619,7 +619,7 @@ static int twl6040_probe(struct i2c_client *client,
"twl6040_irq_th", twl6040);
if (ret) {
dev_err(twl6040->dev, "Thermal IRQ request failed: %d\n", ret);
- goto thirq_err;
+ goto readyirq_err;
}
/* dual-access registers controlled by I2C only */
@@ -659,14 +659,10 @@ static int twl6040_probe(struct i2c_client *client,
ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children,
NULL, 0, NULL);
if (ret)
- goto mfd_err;
+ goto readyirq_err;
return 0;
-mfd_err:
- devm_free_irq(&client->dev, twl6040->irq_th, twl6040);
-thirq_err:
- devm_free_irq(&client->dev, twl6040->irq_ready, twl6040);
readyirq_err:
regmap_del_irq_chip(twl6040->irq, twl6040->irq_data);
gpio_err:
@@ -684,8 +680,6 @@ static int twl6040_remove(struct i2c_client *client)
if (twl6040->power_count)
twl6040_power(twl6040, 0);
- devm_free_irq(&client->dev, twl6040->irq_ready, twl6040);
- devm_free_irq(&client->dev, twl6040->irq_th, twl6040);
regmap_del_irq_chip(twl6040->irq, twl6040->irq_data);
mfd_remove_devices(&client->dev);
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index d5966e6b5a7d..0313f839e8fa 100644
--- a/drivers/mfd/ucb1x00-core.c
+++ b/drivers/mfd/ucb1x00-core.c
@@ -553,6 +553,7 @@ static int ucb1x00_probe(struct mcp *mcp)
if (ucb->irq_base < 0) {
dev_err(&ucb->dev, "unable to allocate 16 irqs: %d\n",
ucb->irq_base);
+ ret = ucb->irq_base;
goto err_irq_alloc;
}
diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c
index 3113e39b318e..f71bd9b3d0a2 100644
--- a/drivers/mfd/wm5110-tables.c
+++ b/drivers/mfd/wm5110-tables.c
@@ -592,7 +592,7 @@ static const struct reg_default wm5110_reg_default[] = {
{ 0x0000043E, 0x0080 }, /* R1086 - DAC Volume Limit 6R */
{ 0x0000043F, 0x0800 }, /* R1087 - Noise Gate Select 6R */
{ 0x00000450, 0x0000 }, /* R1104 - DAC AEC Control 1 */
- { 0x00000458, 0x0001 }, /* R1112 - Noise Gate Control */
+ { 0x00000458, 0x0000 }, /* R1112 - Noise Gate Control */
{ 0x00000480, 0x0040 }, /* R1152 - Class W ANC Threshold 1 */
{ 0x00000481, 0x0040 }, /* R1153 - Class W ANC Threshold 2 */
{ 0x00000490, 0x0069 }, /* R1168 - PDM SPK1 CTRL 1 */
@@ -2291,21 +2291,37 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
case ARIZONA_DSP1_STATUS_1:
case ARIZONA_DSP1_STATUS_2:
case ARIZONA_DSP1_STATUS_3:
+ case ARIZONA_DSP1_SCRATCH_0:
+ case ARIZONA_DSP1_SCRATCH_1:
+ case ARIZONA_DSP1_SCRATCH_2:
+ case ARIZONA_DSP1_SCRATCH_3:
case ARIZONA_DSP2_CONTROL_1:
case ARIZONA_DSP2_CLOCKING_1:
case ARIZONA_DSP2_STATUS_1:
case ARIZONA_DSP2_STATUS_2:
case ARIZONA_DSP2_STATUS_3:
+ case ARIZONA_DSP2_SCRATCH_0:
+ case ARIZONA_DSP2_SCRATCH_1:
+ case ARIZONA_DSP2_SCRATCH_2:
+ case ARIZONA_DSP2_SCRATCH_3:
case ARIZONA_DSP3_CONTROL_1:
case ARIZONA_DSP3_CLOCKING_1:
case ARIZONA_DSP3_STATUS_1:
case ARIZONA_DSP3_STATUS_2:
case ARIZONA_DSP3_STATUS_3:
+ case ARIZONA_DSP3_SCRATCH_0:
+ case ARIZONA_DSP3_SCRATCH_1:
+ case ARIZONA_DSP3_SCRATCH_2:
+ case ARIZONA_DSP3_SCRATCH_3:
case ARIZONA_DSP4_CONTROL_1:
case ARIZONA_DSP4_CLOCKING_1:
case ARIZONA_DSP4_STATUS_1:
case ARIZONA_DSP4_STATUS_2:
case ARIZONA_DSP4_STATUS_3:
+ case ARIZONA_DSP4_SCRATCH_0:
+ case ARIZONA_DSP4_SCRATCH_1:
+ case ARIZONA_DSP4_SCRATCH_2:
+ case ARIZONA_DSP4_SCRATCH_3:
return true;
default:
return false;
@@ -2352,20 +2368,34 @@ static bool wm5110_volatile_register(struct device *dev, unsigned int reg)
case ARIZONA_FX_CTRL2:
case ARIZONA_ASRC_STATUS:
case ARIZONA_DSP_STATUS:
- case ARIZONA_DSP1_CONTROL_1:
- case ARIZONA_DSP1_CLOCKING_1:
case ARIZONA_DSP1_STATUS_1:
case ARIZONA_DSP1_STATUS_2:
case ARIZONA_DSP1_STATUS_3:
+ case ARIZONA_DSP1_SCRATCH_0:
+ case ARIZONA_DSP1_SCRATCH_1:
+ case ARIZONA_DSP1_SCRATCH_2:
+ case ARIZONA_DSP1_SCRATCH_3:
case ARIZONA_DSP2_STATUS_1:
case ARIZONA_DSP2_STATUS_2:
case ARIZONA_DSP2_STATUS_3:
+ case ARIZONA_DSP2_SCRATCH_0:
+ case ARIZONA_DSP2_SCRATCH_1:
+ case ARIZONA_DSP2_SCRATCH_2:
+ case ARIZONA_DSP2_SCRATCH_3:
case ARIZONA_DSP3_STATUS_1:
case ARIZONA_DSP3_STATUS_2:
case ARIZONA_DSP3_STATUS_3:
+ case ARIZONA_DSP3_SCRATCH_0:
+ case ARIZONA_DSP3_SCRATCH_1:
+ case ARIZONA_DSP3_SCRATCH_2:
+ case ARIZONA_DSP3_SCRATCH_3:
case ARIZONA_DSP4_STATUS_1:
case ARIZONA_DSP4_STATUS_2:
case ARIZONA_DSP4_STATUS_3:
+ case ARIZONA_DSP4_SCRATCH_0:
+ case ARIZONA_DSP4_SCRATCH_1:
+ case ARIZONA_DSP4_SCRATCH_2:
+ case ARIZONA_DSP4_SCRATCH_3:
return true;
default:
return false;
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index e1c283e6d4e5..030827511667 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -33,84 +33,6 @@
#include "wm8994.h"
-/**
- * wm8994_reg_read: Read a single WM8994 register.
- *
- * @wm8994: Device to read from.
- * @reg: Register to read.
- */
-int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg)
-{
- unsigned int val;
- int ret;
-
- ret = regmap_read(wm8994->regmap, reg, &val);
-
- if (ret < 0)
- return ret;
- else
- return val;
-}
-EXPORT_SYMBOL_GPL(wm8994_reg_read);
-
-/**
- * wm8994_bulk_read: Read multiple WM8994 registers
- *
- * @wm8994: Device to read from
- * @reg: First register
- * @count: Number of registers
- * @buf: Buffer to fill. The data will be returned big endian.
- */
-int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
- int count, u16 *buf)
-{
- return regmap_bulk_read(wm8994->regmap, reg, buf, count);
-}
-
-/**
- * wm8994_reg_write: Write a single WM8994 register.
- *
- * @wm8994: Device to write to.
- * @reg: Register to write to.
- * @val: Value to write.
- */
-int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg,
- unsigned short val)
-{
- return regmap_write(wm8994->regmap, reg, val);
-}
-EXPORT_SYMBOL_GPL(wm8994_reg_write);
-
-/**
- * wm8994_bulk_write: Write multiple WM8994 registers
- *
- * @wm8994: Device to write to
- * @reg: First register
- * @count: Number of registers
- * @buf: Buffer to write from. Data must be big-endian formatted.
- */
-int wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg,
- int count, const u16 *buf)
-{
- return regmap_raw_write(wm8994->regmap, reg, buf, count * sizeof(u16));
-}
-EXPORT_SYMBOL_GPL(wm8994_bulk_write);
-
-/**
- * wm8994_set_bits: Set the value of a bitfield in a WM8994 register
- *
- * @wm8994: Device to write to.
- * @reg: Register to write to.
- * @mask: Mask of bits to set.
- * @val: Value to set (unshifted)
- */
-int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
- unsigned short mask, unsigned short val)
-{
- return regmap_update_bits(wm8994->regmap, reg, mask, val);
-}
-EXPORT_SYMBOL_GPL(wm8994_set_bits);
-
static struct mfd_cell wm8994_regulator_devs[] = {
{
.name = "wm8994-ldo",
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 8dacd4c9ee87..e760715bd9cb 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -537,4 +537,5 @@ source "drivers/misc/carma/Kconfig"
source "drivers/misc/altera-stapl/Kconfig"
source "drivers/misc/mei/Kconfig"
source "drivers/misc/vmw_vmci/Kconfig"
+source "drivers/misc/mic/Kconfig"
endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index c235d5b68311..0b7ea3ea8bb8 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,3 +53,4 @@ obj-$(CONFIG_INTEL_MEI) += mei/
obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/
obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o
obj-$(CONFIG_SRAM) += sram.o
+obj-y += mic/
diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c
index 849e2fed4da2..2704d885a9b3 100644
--- a/drivers/misc/bmp085.c
+++ b/drivers/misc/bmp085.c
@@ -374,7 +374,7 @@ int bmp085_detect(struct device *dev)
}
EXPORT_SYMBOL_GPL(bmp085_detect);
-static void __init bmp085_get_of_properties(struct bmp085_data *data)
+static void bmp085_get_of_properties(struct bmp085_data *data)
{
#ifdef CONFIG_OF
struct device_node *np = data->dev->of_node;
diff --git a/drivers/misc/cb710/core.c b/drivers/misc/cb710/core.c
index 2e50f811ff59..fb397e7d1cce 100644
--- a/drivers/misc/cb710/core.c
+++ b/drivers/misc/cb710/core.c
@@ -176,7 +176,7 @@ static int cb710_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct cb710_chip *chip = pci_get_drvdata(pdev);
- free_irq(pdev->irq, chip);
+ devm_free_irq(&pdev->dev, pdev->irq, chip);
pci_save_state(pdev);
pci_disable_device(pdev);
if (state.event & PM_EVENT_SLEEP)
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 04f2e1fa9dd1..9536852fd4c6 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -96,4 +96,17 @@ config EEPROM_DIGSY_MTC_CFG
If unsure, say N.
+config EEPROM_SUNXI_SID
+ tristate "Allwinner sunxi security ID support"
+ depends on ARCH_SUNXI && SYSFS
+ help
+ This is a driver for the 'security ID' available on various Allwinner
+ devices.
+
+ Due to the potential risks involved with changing e-fuses,
+ this driver is read-only.
+
+ This driver can also be built as a module. If so, the module
+ will be called sunxi_sid.
+
endmenu
diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile
index fc1e81d29267..9507aec95e94 100644
--- a/drivers/misc/eeprom/Makefile
+++ b/drivers/misc/eeprom/Makefile
@@ -4,4 +4,5 @@ obj-$(CONFIG_EEPROM_LEGACY) += eeprom.o
obj-$(CONFIG_EEPROM_MAX6875) += max6875.o
obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
obj-$(CONFIG_EEPROM_93XX46) += eeprom_93xx46.o
+obj-$(CONFIG_EEPROM_SUNXI_SID) += sunxi_sid.o
obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o
diff --git a/drivers/misc/eeprom/sunxi_sid.c b/drivers/misc/eeprom/sunxi_sid.c
new file mode 100644
index 000000000000..9c34e5704304
--- /dev/null
+++ b/drivers/misc/eeprom/sunxi_sid.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2013 Oliver Schinagl <oliver@schinagl.nl>
+ * http://www.linux-sunxi.org
+ *
+ * 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.
+ *
+ * This driver exposes the Allwinner security ID, efuses exported in byte-
+ * sized chunks.
+ */
+
+#include <linux/compiler.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+
+#define DRV_NAME "sunxi-sid"
+
+struct sunxi_sid_data {
+ void __iomem *reg_base;
+ unsigned int keysize;
+};
+
+/* We read the entire key, due to a 32 bit read alignment requirement. Since we
+ * want to return the requested byte, this results in somewhat slower code and
+ * uses 4 times more reads as needed but keeps code simpler. Since the SID is
+ * only very rarely probed, this is not really an issue.
+ */
+static u8 sunxi_sid_read_byte(const struct sunxi_sid_data *sid_data,
+ const unsigned int offset)
+{
+ u32 sid_key;
+
+ if (offset >= sid_data->keysize)
+ return 0;
+
+ sid_key = ioread32be(sid_data->reg_base + round_down(offset, 4));
+ sid_key >>= (offset % 4) * 8;
+
+ return sid_key; /* Only return the last byte */
+}
+
+static ssize_t sid_read(struct file *fd, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t pos, size_t size)
+{
+ struct platform_device *pdev;
+ struct sunxi_sid_data *sid_data;
+ int i;
+
+ pdev = to_platform_device(kobj_to_dev(kobj));
+ sid_data = platform_get_drvdata(pdev);
+
+ if (pos < 0 || pos >= sid_data->keysize)
+ return 0;
+ if (size > sid_data->keysize - pos)
+ size = sid_data->keysize - pos;
+
+ for (i = 0; i < size; i++)
+ buf[i] = sunxi_sid_read_byte(sid_data, pos + i);
+
+ return i;
+}
+
+static struct bin_attribute sid_bin_attr = {
+ .attr = { .name = "eeprom", .mode = S_IRUGO, },
+ .read = sid_read,
+};
+
+static int sunxi_sid_remove(struct platform_device *pdev)
+{
+ device_remove_bin_file(&pdev->dev, &sid_bin_attr);
+ dev_dbg(&pdev->dev, "driver unloaded\n");
+
+ return 0;
+}
+
+static const struct of_device_id sunxi_sid_of_match[] = {
+ { .compatible = "allwinner,sun4i-sid", .data = (void *)16},
+ { .compatible = "allwinner,sun7i-a20-sid", .data = (void *)512},
+ {/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
+
+static int sunxi_sid_probe(struct platform_device *pdev)
+{
+ struct sunxi_sid_data *sid_data;
+ struct resource *res;
+ const struct of_device_id *of_dev_id;
+ u8 *entropy;
+ unsigned int i;
+
+ sid_data = devm_kzalloc(&pdev->dev, sizeof(struct sunxi_sid_data),
+ GFP_KERNEL);
+ if (!sid_data)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ sid_data->reg_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(sid_data->reg_base))
+ return PTR_ERR(sid_data->reg_base);
+
+ of_dev_id = of_match_device(sunxi_sid_of_match, &pdev->dev);
+ if (!of_dev_id)
+ return -ENODEV;
+ sid_data->keysize = (int)of_dev_id->data;
+
+ platform_set_drvdata(pdev, sid_data);
+
+ sid_bin_attr.size = sid_data->keysize;
+ if (device_create_bin_file(&pdev->dev, &sid_bin_attr))
+ return -ENODEV;
+
+ entropy = kzalloc(sizeof(u8) * sid_data->keysize, GFP_KERNEL);
+ for (i = 0; i < sid_data->keysize; i++)
+ entropy[i] = sunxi_sid_read_byte(sid_data, i);
+ add_device_randomness(entropy, sid_data->keysize);
+ kfree(entropy);
+
+ dev_dbg(&pdev->dev, "loaded\n");
+
+ return 0;
+}
+
+static struct platform_driver sunxi_sid_driver = {
+ .probe = sunxi_sid_probe,
+ .remove = sunxi_sid_remove,
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = sunxi_sid_of_match,
+ },
+};
+module_platform_driver(sunxi_sid_driver);
+
+MODULE_AUTHOR("Oliver Schinagl <oliver@schinagl.nl>");
+MODULE_DESCRIPTION("Allwinner sunxi security id driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
index 0346d87c5fed..6b3bf9ab051d 100644
--- a/drivers/misc/ibmasm/module.c
+++ b/drivers/misc/ibmasm/module.c
@@ -153,7 +153,6 @@ error_ioremap:
error_heartbeat:
ibmasm_event_buffer_exit(sp);
error_eventbuffer:
- pci_set_drvdata(pdev, NULL);
kfree(sp);
error_kmalloc:
pci_release_regions(pdev);
@@ -165,7 +164,7 @@ error_resources:
static void ibmasm_remove_one(struct pci_dev *pdev)
{
- struct service_processor *sp = (struct service_processor *)pci_get_drvdata(pdev);
+ struct service_processor *sp = pci_get_drvdata(pdev);
dbg("Unregistering UART\n");
ibmasm_unregister_uart(sp);
@@ -182,7 +181,6 @@ static void ibmasm_remove_one(struct pci_dev *pdev)
ibmasm_free_remote_input_dev(sp);
iounmap(sp->base_address);
ibmasm_event_buffer_exit(sp);
- pci_set_drvdata(pdev, NULL);
kfree(sp);
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index d0fdc134068a..226c3f3cd3e8 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -57,6 +57,7 @@ void mei_amthif_reset_params(struct mei_device *dev)
dev->iamthif_ioctl = false;
dev->iamthif_state = MEI_IAMTHIF_IDLE;
dev->iamthif_timer = 0;
+ dev->iamthif_stall_timer = 0;
}
/**
@@ -312,13 +313,13 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
mei_hdr.me_addr = dev->iamthif_cl.me_client_id;
mei_hdr.reserved = 0;
dev->iamthif_msg_buf_index += mei_hdr.length;
- if (mei_write_message(dev, &mei_hdr,
- (unsigned char *)dev->iamthif_msg_buf))
- return -ENODEV;
+ ret = mei_write_message(dev, &mei_hdr, dev->iamthif_msg_buf);
+ if (ret)
+ return ret;
if (mei_hdr.msg_complete) {
if (mei_cl_flow_ctrl_reduce(&dev->iamthif_cl))
- return -ENODEV;
+ return -EIO;
dev->iamthif_flow_control_pending = true;
dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
dev_dbg(&dev->pdev->dev, "add amthif cb to write waiting list\n");
@@ -458,6 +459,16 @@ int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
struct mei_msg_hdr mei_hdr;
size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index;
u32 msg_slots = mei_data2slots(len);
+ int rets;
+
+ rets = mei_cl_flow_ctrl_creds(cl);
+ if (rets < 0)
+ return rets;
+
+ if (rets == 0) {
+ cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
+ return 0;
+ }
mei_hdr.host_addr = cl->host_client_id;
mei_hdr.me_addr = cl->me_client_id;
@@ -480,16 +491,17 @@ int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(&mei_hdr));
*slots -= msg_slots;
- if (mei_write_message(dev, &mei_hdr,
- dev->iamthif_msg_buf + dev->iamthif_msg_buf_index)) {
- dev->iamthif_state = MEI_IAMTHIF_IDLE;
- cl->status = -ENODEV;
- list_del(&cb->list);
- return -ENODEV;
+ rets = mei_write_message(dev, &mei_hdr,
+ dev->iamthif_msg_buf + dev->iamthif_msg_buf_index);
+ if (rets) {
+ dev->iamthif_state = MEI_IAMTHIF_IDLE;
+ cl->status = rets;
+ list_del(&cb->list);
+ return rets;
}
if (mei_cl_flow_ctrl_reduce(cl))
- return -ENODEV;
+ return -EIO;
dev->iamthif_msg_buf_index += mei_hdr.length;
cl->status = 0;
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 6d0282c08a06..cd2033cd7120 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -297,10 +297,13 @@ int __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
if (cl->reading_state != MEI_READ_COMPLETE &&
!waitqueue_active(&cl->rx_wait)) {
+
mutex_unlock(&dev->device_lock);
if (wait_event_interruptible(cl->rx_wait,
- (MEI_READ_COMPLETE == cl->reading_state))) {
+ cl->reading_state == MEI_READ_COMPLETE ||
+ mei_cl_is_transitioning(cl))) {
+
if (signal_pending(current))
return -EINTR;
return -ERESTARTSYS;
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index e0684b4d9a08..fbd319c506e6 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -187,10 +187,14 @@ int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length)
*/
int mei_cl_flush_queues(struct mei_cl *cl)
{
+ struct mei_device *dev;
+
if (WARN_ON(!cl || !cl->dev))
return -EINVAL;
- dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n");
+ dev = cl->dev;
+
+ cl_dbg(dev, cl, "remove list entry belonging to cl\n");
mei_io_list_flush(&cl->dev->read_list, cl);
mei_io_list_flush(&cl->dev->write_list, cl);
mei_io_list_flush(&cl->dev->write_waiting_list, cl);
@@ -287,6 +291,12 @@ int mei_cl_link(struct mei_cl *cl, int id)
return -ENOENT;
}
+ if (dev->open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) {
+ dev_err(&dev->pdev->dev, "open_handle_count exceded %d",
+ MEI_MAX_OPEN_HANDLE_COUNT);
+ return -ENOENT;
+ }
+
dev->open_handle_count++;
cl->host_client_id = id;
@@ -296,7 +306,7 @@ int mei_cl_link(struct mei_cl *cl, int id)
cl->state = MEI_FILE_INITIALIZING;
- dev_dbg(&dev->pdev->dev, "link cl host id = %d\n", cl->host_client_id);
+ cl_dbg(dev, cl, "link cl\n");
return 0;
}
@@ -308,7 +318,6 @@ int mei_cl_link(struct mei_cl *cl, int id)
int mei_cl_unlink(struct mei_cl *cl)
{
struct mei_device *dev;
- struct mei_cl *pos, *next;
/* don't shout on error exit path */
if (!cl)
@@ -320,14 +329,10 @@ int mei_cl_unlink(struct mei_cl *cl)
dev = cl->dev;
- list_for_each_entry_safe(pos, next, &dev->file_list, link) {
- if (cl->host_client_id == pos->host_client_id) {
- dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n",
- pos->host_client_id, pos->me_client_id);
- list_del_init(&pos->link);
- break;
- }
- }
+ cl_dbg(dev, cl, "unlink client");
+
+ list_del_init(&cl->link);
+
return 0;
}
@@ -390,6 +395,8 @@ int mei_cl_disconnect(struct mei_cl *cl)
dev = cl->dev;
+ cl_dbg(dev, cl, "disconnecting");
+
if (cl->state != MEI_FILE_DISCONNECTING)
return 0;
@@ -402,13 +409,13 @@ int mei_cl_disconnect(struct mei_cl *cl)
dev->hbuf_is_ready = false;
if (mei_hbm_cl_disconnect_req(dev, cl)) {
rets = -ENODEV;
- dev_err(&dev->pdev->dev, "failed to disconnect.\n");
+ cl_err(dev, cl, "failed to disconnect.\n");
goto free;
}
mdelay(10); /* Wait for hardware disconnection ready */
list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
} else {
- dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n");
+ cl_dbg(dev, cl, "add disconnect cb to control write list\n");
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
}
@@ -421,18 +428,17 @@ int mei_cl_disconnect(struct mei_cl *cl)
mutex_lock(&dev->device_lock);
if (MEI_FILE_DISCONNECTED == cl->state) {
rets = 0;
- dev_dbg(&dev->pdev->dev, "successfully disconnected from FW client.\n");
+ cl_dbg(dev, cl, "successfully disconnected from FW client.\n");
} else {
rets = -ENODEV;
if (MEI_FILE_DISCONNECTED != cl->state)
- dev_dbg(&dev->pdev->dev, "wrong status client disconnect.\n");
+ cl_err(dev, cl, "wrong status client disconnect.\n");
if (err)
- dev_dbg(&dev->pdev->dev,
- "wait failed disconnect err=%08x\n",
+ cl_dbg(dev, cl, "wait failed disconnect err=%08x\n",
err);
- dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n");
+ cl_err(dev, cl, "failed to disconnect from FW client.\n");
}
mei_io_list_flush(&dev->ctrl_rd_list, cl);
@@ -639,13 +645,12 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
return -ENODEV;
if (cl->read_cb) {
- dev_dbg(&dev->pdev->dev, "read is pending.\n");
+ cl_dbg(dev, cl, "read is pending.\n");
return -EBUSY;
}
i = mei_me_cl_by_id(dev, cl->me_client_id);
if (i < 0) {
- dev_err(&dev->pdev->dev, "no such me client %d\n",
- cl->me_client_id);
+ cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
return -ENODEV;
}
@@ -664,6 +669,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
if (dev->hbuf_is_ready) {
dev->hbuf_is_ready = false;
if (mei_hbm_cl_flow_control_req(dev, cl)) {
+ cl_err(dev, cl, "flow control send failed\n");
rets = -ENODEV;
goto err;
}
@@ -691,10 +697,32 @@ err:
int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
s32 *slots, struct mei_cl_cb *cmpl_list)
{
- struct mei_device *dev = cl->dev;
+ struct mei_device *dev;
+ struct mei_msg_data *buf;
struct mei_msg_hdr mei_hdr;
- size_t len = cb->request_buffer.size - cb->buf_idx;
- u32 msg_slots = mei_data2slots(len);
+ size_t len;
+ u32 msg_slots;
+ int rets;
+
+
+ if (WARN_ON(!cl || !cl->dev))
+ return -ENODEV;
+
+ dev = cl->dev;
+
+ buf = &cb->request_buffer;
+
+ rets = mei_cl_flow_ctrl_creds(cl);
+ if (rets < 0)
+ return rets;
+
+ if (rets == 0) {
+ cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
+ return 0;
+ }
+
+ len = buf->size - cb->buf_idx;
+ msg_slots = mei_data2slots(len);
mei_hdr.host_addr = cl->host_client_id;
mei_hdr.me_addr = cl->me_client_id;
@@ -714,16 +742,15 @@ int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
return 0;
}
- dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n",
+ cl_dbg(dev, cl, "buf: size = %d idx = %lu\n",
cb->request_buffer.size, cb->buf_idx);
- dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(&mei_hdr));
*slots -= msg_slots;
- if (mei_write_message(dev, &mei_hdr,
- cb->request_buffer.data + cb->buf_idx)) {
- cl->status = -ENODEV;
+ rets = mei_write_message(dev, &mei_hdr, buf->data + cb->buf_idx);
+ if (rets) {
+ cl->status = rets;
list_move_tail(&cb->list, &cmpl_list->list);
- return -ENODEV;
+ return rets;
}
cl->status = 0;
@@ -732,7 +759,7 @@ int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
if (mei_hdr.msg_complete) {
if (mei_cl_flow_ctrl_reduce(cl))
- return -ENODEV;
+ return -EIO;
list_move_tail(&cb->list, &dev->write_waiting_list.list);
}
@@ -767,7 +794,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
buf = &cb->request_buffer;
- dev_dbg(&dev->pdev->dev, "mei_cl_write %d\n", buf->size);
+ cl_dbg(dev, cl, "mei_cl_write %d\n", buf->size);
cb->fop_type = MEI_FOP_WRITE;
@@ -800,14 +827,10 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
mei_hdr.me_addr = cl->me_client_id;
mei_hdr.reserved = 0;
- dev_dbg(&dev->pdev->dev, "write " MEI_HDR_FMT "\n",
- MEI_HDR_PRM(&mei_hdr));
-
- if (mei_write_message(dev, &mei_hdr, buf->data)) {
- rets = -EIO;
+ rets = mei_write_message(dev, &mei_hdr, buf->data);
+ if (rets)
goto err;
- }
cl->writing_state = MEI_WRITING;
cb->buf_idx = mei_hdr.length;
@@ -898,11 +921,11 @@ void mei_cl_all_wakeup(struct mei_device *dev)
struct mei_cl *cl, *next;
list_for_each_entry_safe(cl, next, &dev->file_list, link) {
if (waitqueue_active(&cl->rx_wait)) {
- dev_dbg(&dev->pdev->dev, "Waking up reading client!\n");
+ cl_dbg(dev, cl, "Waking up reading client!\n");
wake_up_interruptible(&cl->rx_wait);
}
if (waitqueue_active(&cl->tx_wait)) {
- dev_dbg(&dev->pdev->dev, "Waking up writing client!\n");
+ cl_dbg(dev, cl, "Waking up writing client!\n");
wake_up_interruptible(&cl->tx_wait);
}
}
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index 9eb031e92070..c8396e582f1c 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -90,6 +90,12 @@ static inline bool mei_cl_is_connected(struct mei_cl *cl)
cl->dev->dev_state == MEI_DEV_ENABLED &&
cl->state == MEI_FILE_CONNECTED);
}
+static inline bool mei_cl_is_transitioning(struct mei_cl *cl)
+{
+ return (MEI_FILE_INITIALIZING == cl->state ||
+ MEI_FILE_DISCONNECTED == cl->state ||
+ MEI_FILE_DISCONNECTING == cl->state);
+}
bool mei_cl_is_other_connecting(struct mei_cl *cl);
int mei_cl_disconnect(struct mei_cl *cl);
@@ -109,4 +115,13 @@ void mei_cl_all_disconnect(struct mei_device *dev);
void mei_cl_all_wakeup(struct mei_device *dev);
void mei_cl_all_write_clear(struct mei_device *dev);
+#define MEI_CL_FMT "cl:host=%02d me=%02d "
+#define MEI_CL_PRM(cl) (cl)->host_client_id, (cl)->me_client_id
+
+#define cl_dbg(dev, cl, format, arg...) \
+ dev_dbg(&(dev)->pdev->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg)
+
+#define cl_err(dev, cl, format, arg...) \
+ dev_err(&(dev)->pdev->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg)
+
#endif /* _MEI_CLIENT_H_ */
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index 6127ab64bb39..9b3a0fb7f265 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -35,17 +35,21 @@ static void mei_hbm_me_cl_allocate(struct mei_device *dev)
struct mei_me_client *clients;
int b;
+ dev->me_clients_num = 0;
+ dev->me_client_presentation_num = 0;
+ dev->me_client_index = 0;
+
/* count how many ME clients we have */
for_each_set_bit(b, dev->me_clients_map, MEI_CLIENTS_MAX)
dev->me_clients_num++;
- if (dev->me_clients_num <= 0)
+ if (dev->me_clients_num == 0)
return;
kfree(dev->me_clients);
dev->me_clients = NULL;
- dev_dbg(&dev->pdev->dev, "memory allocation for ME clients size=%zd.\n",
+ dev_dbg(&dev->pdev->dev, "memory allocation for ME clients size=%ld.\n",
dev->me_clients_num * sizeof(struct mei_me_client));
/* allocate storage for ME clients representation */
clients = kcalloc(dev->me_clients_num,
@@ -170,7 +174,7 @@ int mei_hbm_start_req(struct mei_device *dev)
dev_err(&dev->pdev->dev, "version message write failed\n");
dev->dev_state = MEI_DEV_RESETTING;
mei_reset(dev, 1);
- return -ENODEV;
+ return -EIO;
}
dev->hbm_state = MEI_HBM_START;
dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
@@ -221,7 +225,7 @@ static int mei_hbm_prop_req(struct mei_device *dev)
struct hbm_props_request *prop_req;
const size_t len = sizeof(struct hbm_props_request);
unsigned long next_client_index;
- u8 client_num;
+ unsigned long client_num;
client_num = dev->me_client_presentation_num;
@@ -673,12 +677,13 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
case HOST_ENUM_RES_CMD:
enum_res = (struct hbm_host_enum_response *) mei_msg;
- memcpy(dev->me_clients_map, enum_res->valid_addresses, 32);
+ BUILD_BUG_ON(sizeof(dev->me_clients_map)
+ < sizeof(enum_res->valid_addresses));
+ memcpy(dev->me_clients_map, enum_res->valid_addresses,
+ sizeof(enum_res->valid_addresses));
if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
dev->hbm_state == MEI_HBM_ENUM_CLIENTS) {
dev->init_clients_timer = 0;
- dev->me_client_presentation_num = 0;
- dev->me_client_index = 0;
mei_hbm_me_cl_allocate(dev);
dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES;
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 92c73118b13c..6197018e2f16 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -175,6 +175,9 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg));
}
+ /* we're already in reset, cancel the init timer */
+ dev->init_clients_timer = 0;
+
dev->me_clients_num = 0;
dev->rd_msg_hdr = 0;
dev->wd_pending = false;
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 4b59cb742dee..7a95c07e59a6 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -113,13 +113,13 @@ static int mei_cl_irq_read_msg(struct mei_device *dev,
if (cb->response_buffer.size == 0 ||
cb->response_buffer.data == NULL) {
- dev_err(&dev->pdev->dev, "response buffer is not allocated.\n");
+ cl_err(dev, cl, "response buffer is not allocated.\n");
list_del(&cb->list);
return -ENOMEM;
}
if (cb->response_buffer.size < mei_hdr->length + cb->buf_idx) {
- dev_dbg(&dev->pdev->dev, "message overflow. size %d len %d idx %ld\n",
+ cl_dbg(dev, cl, "message overflow. size %d len %d idx %ld\n",
cb->response_buffer.size,
mei_hdr->length, cb->buf_idx);
buffer = krealloc(cb->response_buffer.data,
@@ -127,7 +127,7 @@ static int mei_cl_irq_read_msg(struct mei_device *dev,
GFP_KERNEL);
if (!buffer) {
- dev_err(&dev->pdev->dev, "allocation failed.\n");
+ cl_err(dev, cl, "allocation failed.\n");
list_del(&cb->list);
return -ENOMEM;
}
@@ -143,9 +143,7 @@ static int mei_cl_irq_read_msg(struct mei_device *dev,
if (mei_hdr->msg_complete) {
cl->status = 0;
list_del(&cb->list);
- dev_dbg(&dev->pdev->dev, "completed read H cl = %d, ME cl = %d, length = %lu\n",
- cl->host_client_id,
- cl->me_client_id,
+ cl_dbg(dev, cl, "completed read length = %lu\n",
cb->buf_idx);
list_add_tail(&cb->list, &complete_list->list);
}
@@ -218,9 +216,11 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
s32 *slots, struct mei_cl_cb *cmpl_list)
{
struct mei_device *dev = cl->dev;
-
u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
+ int ret;
+
+
if (*slots < msg_slots) {
/* return the cancel routine */
list_del(&cb->list);
@@ -229,12 +229,14 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
*slots -= msg_slots;
- if (mei_hbm_cl_flow_control_req(dev, cl)) {
- cl->status = -ENODEV;
+ ret = mei_hbm_cl_flow_control_req(dev, cl);
+ if (ret) {
+ cl->status = ret;
cb->buf_idx = 0;
list_move_tail(&cb->list, &cmpl_list->list);
- return -ENODEV;
+ return ret;
}
+
list_move_tail(&cb->list, &dev->read_list.list);
return 0;
@@ -256,6 +258,7 @@ static int mei_cl_irq_ioctl(struct mei_cl *cl, struct mei_cl_cb *cb,
s32 *slots, struct mei_cl_cb *cmpl_list)
{
struct mei_device *dev = cl->dev;
+ int ret;
u32 msg_slots =
mei_data2slots(sizeof(struct hbm_client_connect_request));
@@ -270,11 +273,12 @@ static int mei_cl_irq_ioctl(struct mei_cl *cl, struct mei_cl_cb *cb,
cl->state = MEI_FILE_CONNECTING;
- if (mei_hbm_cl_connect_req(dev, cl)) {
- cl->status = -ENODEV;
+ ret = mei_hbm_cl_connect_req(dev, cl);
+ if (ret) {
+ cl->status = ret;
cb->buf_idx = 0;
list_del(&cb->list);
- return -ENODEV;
+ return ret;
}
list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
@@ -345,14 +349,14 @@ int mei_irq_read_handler(struct mei_device *dev,
/* decide where to read the message too */
if (!mei_hdr->host_addr) {
- dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n");
+ dev_dbg(&dev->pdev->dev, "call mei_hbm_dispatch.\n");
mei_hbm_dispatch(dev, mei_hdr);
- dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n");
+ dev_dbg(&dev->pdev->dev, "end mei_hbm_dispatch.\n");
} else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
(MEI_FILE_CONNECTED == dev->iamthif_cl.state) &&
(dev->iamthif_state == MEI_IAMTHIF_READING)) {
- dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n");
+ dev_dbg(&dev->pdev->dev, "call mei_amthif_irq_read_msg.\n");
dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr));
ret = mei_amthif_irq_read_msg(dev, mei_hdr, cmpl_list);
@@ -423,12 +427,12 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
if (MEI_WRITING == cl->writing_state &&
cb->fop_type == MEI_FOP_WRITE &&
cl != &dev->iamthif_cl) {
- dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n");
+ cl_dbg(dev, cl, "MEI WRITE COMPLETE\n");
cl->writing_state = MEI_WRITE_COMPLETE;
list_add_tail(&cb->list, &cmpl_list->list);
}
if (cl == &dev->iamthif_cl) {
- dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
+ cl_dbg(dev, cl, "check iamthif flow control.\n");
if (dev->iamthif_flow_control_pending) {
ret = mei_amthif_irq_read(dev, &slots);
if (ret)
@@ -509,13 +513,6 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
cl = cb->cl;
if (cl == NULL)
continue;
- if (mei_cl_flow_ctrl_creds(cl) <= 0) {
- dev_dbg(&dev->pdev->dev,
- "No flow control credentials for client %d, not sending.\n",
- cl->host_client_id);
- continue;
- }
-
if (cl == &dev->iamthif_cl)
ret = mei_amthif_irq_write_complete(cl, cb,
&slots, cmpl_list);
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 173ff095be0d..c71420ef1e37 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -165,10 +165,7 @@ static int mei_release(struct inode *inode, struct file *file)
file->private_data = NULL;
- if (cb) {
- mei_io_cb_free(cb);
- cb = NULL;
- }
+ mei_io_cb_free(cb);
kfree(cl);
out:
@@ -203,12 +200,18 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
dev = cl->dev;
+
mutex_lock(&dev->device_lock);
if (dev->dev_state != MEI_DEV_ENABLED) {
rets = -ENODEV;
goto out;
}
+ if (length == 0) {
+ rets = 0;
+ goto out;
+ }
+
if (cl == &dev->iamthif_cl) {
rets = mei_amthif_read(dev, file, ubuf, length, offset);
goto out;
@@ -249,19 +252,16 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
mutex_unlock(&dev->device_lock);
if (wait_event_interruptible(cl->rx_wait,
- (MEI_READ_COMPLETE == cl->reading_state ||
- MEI_FILE_INITIALIZING == cl->state ||
- MEI_FILE_DISCONNECTED == cl->state ||
- MEI_FILE_DISCONNECTING == cl->state))) {
+ MEI_READ_COMPLETE == cl->reading_state ||
+ mei_cl_is_transitioning(cl))) {
+
if (signal_pending(current))
return -EINTR;
return -ERESTARTSYS;
}
mutex_lock(&dev->device_lock);
- if (MEI_FILE_INITIALIZING == cl->state ||
- MEI_FILE_DISCONNECTED == cl->state ||
- MEI_FILE_DISCONNECTING == cl->state) {
+ if (mei_cl_is_transitioning(cl)) {
rets = -EBUSY;
goto out;
}
@@ -350,8 +350,14 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
rets = -ENODEV;
goto out;
}
- if (length > dev->me_clients[id].props.max_msg_length || length <= 0) {
- rets = -EMSGSIZE;
+
+ if (length == 0) {
+ rets = 0;
+ goto out;
+ }
+
+ if (length > dev->me_clients[id].props.max_msg_length) {
+ rets = -EFBIG;
goto out;
}
@@ -404,8 +410,11 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
goto out;
rets = copy_from_user(write_cb->request_buffer.data, ubuf, length);
- if (rets)
+ if (rets) {
+ dev_err(&dev->pdev->dev, "failed to copy data from userland\n");
+ rets = -EFAULT;
goto out;
+ }
if (cl == &dev->iamthif_cl) {
rets = mei_amthif_write(dev, write_cb);
@@ -567,7 +576,7 @@ static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data)
dev_dbg(&dev->pdev->dev, "copy connect data from user\n");
if (copy_from_user(connect_data, (char __user *)data,
sizeof(struct mei_connect_client_data))) {
- dev_dbg(&dev->pdev->dev, "failed to copy data from userland\n");
+ dev_err(&dev->pdev->dev, "failed to copy data from userland\n");
rets = -EFAULT;
goto out;
}
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 7b918b2fb894..456b322013e2 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -396,9 +396,9 @@ struct mei_device {
struct mei_me_client *me_clients; /* Note: memory has to be allocated */
DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX);
DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX);
- u8 me_clients_num;
- u8 me_client_presentation_num;
- u8 me_client_index;
+ unsigned long me_clients_num;
+ unsigned long me_client_presentation_num;
+ unsigned long me_client_index;
struct mei_cl wd_cl;
enum mei_wd_states wd_state;
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 1b3844e82379..1b8a4c6d0cf8 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -239,7 +239,6 @@ static void mei_me_remove(struct pci_dev *pdev)
free_irq(pdev->irq, dev);
pci_disable_msi(pdev);
- pci_set_drvdata(pdev, NULL);
if (hw->mem_addr)
pci_iounmap(pdev, hw->mem_addr);
diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig
new file mode 100644
index 000000000000..d453768e9cee
--- /dev/null
+++ b/drivers/misc/mic/Kconfig
@@ -0,0 +1,39 @@
+comment "Intel MIC Host Driver"
+
+config INTEL_MIC_HOST
+ tristate "Intel MIC Host Driver"
+ depends on 64BIT && PCI
+ select VHOST_RING
+ default N
+ help
+ This enables Host Driver support for the Intel Many Integrated
+ Core (MIC) family of PCIe form factor coprocessor devices that
+ run a 64 bit Linux OS. The driver manages card OS state and
+ enables communication between host and card. Intel MIC X100
+ devices are currently supported.
+
+ If you are building a host kernel with an Intel MIC device then
+ say M (recommended) or Y, else say N. If unsure say N.
+
+ More information about the Intel MIC family as well as the Linux
+ OS and tools for MIC to use with this driver are available from
+ <http://software.intel.com/en-us/mic-developer>.
+
+comment "Intel MIC Card Driver"
+
+config INTEL_MIC_CARD
+ tristate "Intel MIC Card Driver"
+ depends on 64BIT
+ select VIRTIO
+ default N
+ help
+ This enables card driver support for the Intel Many Integrated
+ Core (MIC) device family. The card driver communicates shutdown/
+ crash events to the host and allows registration/configuration of
+ virtio devices. Intel MIC X100 devices are currently supported.
+
+ If you are building a card kernel for an Intel MIC device then
+ say M (recommended) or Y, else say N. If unsure say N.
+
+ For more information see
+ <http://software.intel.com/en-us/mic-developer>.
diff --git a/drivers/misc/mic/Makefile b/drivers/misc/mic/Makefile
new file mode 100644
index 000000000000..05b34d683a58
--- /dev/null
+++ b/drivers/misc/mic/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile - Intel MIC Linux driver.
+# Copyright(c) 2013, Intel Corporation.
+#
+obj-$(CONFIG_INTEL_MIC_HOST) += host/
+obj-$(CONFIG_INTEL_MIC_CARD) += card/
diff --git a/drivers/misc/mic/card/Makefile b/drivers/misc/mic/card/Makefile
new file mode 100644
index 000000000000..69d58bef92ce
--- /dev/null
+++ b/drivers/misc/mic/card/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile - Intel MIC Linux driver.
+# Copyright(c) 2013, Intel Corporation.
+#
+ccflags-y += -DINTEL_MIC_CARD
+
+obj-$(CONFIG_INTEL_MIC_CARD) += mic_card.o
+mic_card-y += mic_x100.o
+mic_card-y += mic_device.o
+mic_card-y += mic_debugfs.o
+mic_card-y += mic_virtio.o
diff --git a/drivers/misc/mic/card/mic_debugfs.c b/drivers/misc/mic/card/mic_debugfs.c
new file mode 100644
index 000000000000..95cf186ff73a
--- /dev/null
+++ b/drivers/misc/mic/card/mic_debugfs.c
@@ -0,0 +1,130 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Disclaimer: The codes contained in these modules may be specific to
+ * the Intel Software Development Platform codenamed: Knights Ferry, and
+ * the Intel product codenamed: Knights Corner, and are not backward
+ * compatible with other Intel products. Additionally, Intel will NOT
+ * support the codes or instruction set in future products.
+ *
+ * Intel MIC Card driver.
+ *
+ */
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+
+#include "../common/mic_device.h"
+#include "mic_device.h"
+
+/* Debugfs parent dir */
+static struct dentry *mic_dbg;
+
+/**
+ * mic_intr_test - Send interrupts to host.
+ */
+static int mic_intr_test(struct seq_file *s, void *unused)
+{
+ struct mic_driver *mdrv = s->private;
+ struct mic_device *mdev = &mdrv->mdev;
+
+ mic_send_intr(mdev, 0);
+ msleep(1000);
+ mic_send_intr(mdev, 1);
+ msleep(1000);
+ mic_send_intr(mdev, 2);
+ msleep(1000);
+ mic_send_intr(mdev, 3);
+ msleep(1000);
+
+ return 0;
+}
+
+static int mic_intr_test_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mic_intr_test, inode->i_private);
+}
+
+static int mic_intr_test_release(struct inode *inode, struct file *file)
+{
+ return single_release(inode, file);
+}
+
+static const struct file_operations intr_test_ops = {
+ .owner = THIS_MODULE,
+ .open = mic_intr_test_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = mic_intr_test_release
+};
+
+/**
+ * mic_create_card_debug_dir - Initialize MIC debugfs entries.
+ */
+void __init mic_create_card_debug_dir(struct mic_driver *mdrv)
+{
+ struct dentry *d;
+
+ if (!mic_dbg)
+ return;
+
+ mdrv->dbg_dir = debugfs_create_dir(mdrv->name, mic_dbg);
+ if (!mdrv->dbg_dir) {
+ dev_err(mdrv->dev, "Cant create dbg_dir %s\n", mdrv->name);
+ return;
+ }
+
+ d = debugfs_create_file("intr_test", 0444, mdrv->dbg_dir,
+ mdrv, &intr_test_ops);
+
+ if (!d) {
+ dev_err(mdrv->dev,
+ "Cant create dbg intr_test %s\n", mdrv->name);
+ return;
+ }
+}
+
+/**
+ * mic_delete_card_debug_dir - Uninitialize MIC debugfs entries.
+ */
+void mic_delete_card_debug_dir(struct mic_driver *mdrv)
+{
+ if (!mdrv->dbg_dir)
+ return;
+
+ debugfs_remove_recursive(mdrv->dbg_dir);
+}
+
+/**
+ * mic_init_card_debugfs - Initialize global debugfs entry.
+ */
+void __init mic_init_card_debugfs(void)
+{
+ mic_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
+ if (!mic_dbg)
+ pr_err("can't create debugfs dir\n");
+}
+
+/**
+ * mic_exit_card_debugfs - Uninitialize global debugfs entry
+ */
+void mic_exit_card_debugfs(void)
+{
+ debugfs_remove(mic_dbg);
+}
diff --git a/drivers/misc/mic/card/mic_device.c b/drivers/misc/mic/card/mic_device.c
new file mode 100644
index 000000000000..4125217579af
--- /dev/null
+++ b/drivers/misc/mic/card/mic_device.c
@@ -0,0 +1,306 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Disclaimer: The codes contained in these modules may be specific to
+ * the Intel Software Development Platform codenamed: Knights Ferry, and
+ * the Intel product codenamed: Knights Corner, and are not backward
+ * compatible with other Intel products. Additionally, Intel will NOT
+ * support the codes or instruction set in future products.
+ *
+ * Intel MIC Card driver.
+ *
+ */
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+
+#include <linux/mic_common.h>
+#include "../common/mic_device.h"
+#include "mic_device.h"
+#include "mic_virtio.h"
+
+static struct mic_driver *g_drv;
+static struct mic_irq *shutdown_cookie;
+
+static void mic_notify_host(u8 state)
+{
+ struct mic_driver *mdrv = g_drv;
+ struct mic_bootparam __iomem *bootparam = mdrv->dp;
+
+ iowrite8(state, &bootparam->shutdown_status);
+ dev_dbg(mdrv->dev, "%s %d system_state %d\n",
+ __func__, __LINE__, state);
+ mic_send_intr(&mdrv->mdev, ioread8(&bootparam->c2h_shutdown_db));
+}
+
+static int mic_panic_event(struct notifier_block *this, unsigned long event,
+ void *ptr)
+{
+ struct mic_driver *mdrv = g_drv;
+ struct mic_bootparam __iomem *bootparam = mdrv->dp;
+
+ iowrite8(-1, &bootparam->h2c_config_db);
+ iowrite8(-1, &bootparam->h2c_shutdown_db);
+ mic_notify_host(MIC_CRASHED);
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block mic_panic = {
+ .notifier_call = mic_panic_event,
+};
+
+static irqreturn_t mic_shutdown_isr(int irq, void *data)
+{
+ struct mic_driver *mdrv = g_drv;
+ struct mic_bootparam __iomem *bootparam = mdrv->dp;
+
+ mic_ack_interrupt(&g_drv->mdev);
+ if (ioread8(&bootparam->shutdown_card))
+ orderly_poweroff(true);
+ return IRQ_HANDLED;
+}
+
+static int mic_shutdown_init(void)
+{
+ int rc = 0;
+ struct mic_driver *mdrv = g_drv;
+ struct mic_bootparam __iomem *bootparam = mdrv->dp;
+ int shutdown_db;
+
+ shutdown_db = mic_next_card_db();
+ shutdown_cookie = mic_request_card_irq(mic_shutdown_isr,
+ "Shutdown", mdrv, shutdown_db);
+ if (IS_ERR(shutdown_cookie))
+ rc = PTR_ERR(shutdown_cookie);
+ else
+ iowrite8(shutdown_db, &bootparam->h2c_shutdown_db);
+ return rc;
+}
+
+static void mic_shutdown_uninit(void)
+{
+ struct mic_driver *mdrv = g_drv;
+ struct mic_bootparam __iomem *bootparam = mdrv->dp;
+
+ iowrite8(-1, &bootparam->h2c_shutdown_db);
+ mic_free_card_irq(shutdown_cookie, mdrv);
+}
+
+static int __init mic_dp_init(void)
+{
+ struct mic_driver *mdrv = g_drv;
+ struct mic_device *mdev = &mdrv->mdev;
+ struct mic_bootparam __iomem *bootparam;
+ u64 lo, hi, dp_dma_addr;
+ u32 magic;
+
+ lo = mic_read_spad(&mdrv->mdev, MIC_DPLO_SPAD);
+ hi = mic_read_spad(&mdrv->mdev, MIC_DPHI_SPAD);
+
+ dp_dma_addr = lo | (hi << 32);
+ mdrv->dp = mic_card_map(mdev, dp_dma_addr, MIC_DP_SIZE);
+ if (!mdrv->dp) {
+ dev_err(mdrv->dev, "Cannot remap Aperture BAR\n");
+ return -ENOMEM;
+ }
+ bootparam = mdrv->dp;
+ magic = ioread32(&bootparam->magic);
+ if (MIC_MAGIC != magic) {
+ dev_err(mdrv->dev, "bootparam magic mismatch 0x%x\n", magic);
+ return -EIO;
+ }
+ return 0;
+}
+
+/* Uninitialize the device page */
+static void mic_dp_uninit(void)
+{
+ mic_card_unmap(&g_drv->mdev, g_drv->dp);
+}
+
+/**
+ * mic_request_card_irq - request an irq.
+ *
+ * @func: The callback function that handles the interrupt.
+ * @name: The ASCII name of the callee requesting the irq.
+ * @data: private data that is returned back when calling the
+ * function handler.
+ * @index: The doorbell index of the requester.
+ *
+ * returns: The cookie that is transparent to the caller. Passed
+ * back when calling mic_free_irq. An appropriate error code
+ * is returned on failure. Caller needs to use IS_ERR(return_val)
+ * to check for failure and PTR_ERR(return_val) to obtained the
+ * error code.
+ *
+ */
+struct mic_irq *mic_request_card_irq(irqreturn_t (*func)(int irq, void *data),
+ const char *name, void *data, int index)
+{
+ int rc = 0;
+ unsigned long cookie;
+ struct mic_driver *mdrv = g_drv;
+
+ rc = request_irq(mic_db_to_irq(mdrv, index), func,
+ 0, name, data);
+ if (rc) {
+ dev_err(mdrv->dev, "request_irq failed rc = %d\n", rc);
+ goto err;
+ }
+ mdrv->irq_info.irq_usage_count[index]++;
+ cookie = index;
+ return (struct mic_irq *)cookie;
+err:
+ return ERR_PTR(rc);
+
+}
+
+/**
+ * mic_free_card_irq - free irq.
+ *
+ * @cookie: cookie obtained during a successful call to mic_request_irq
+ * @data: private data specified by the calling function during the
+ * mic_request_irq
+ *
+ * returns: none.
+ */
+void mic_free_card_irq(struct mic_irq *cookie, void *data)
+{
+ int index;
+ struct mic_driver *mdrv = g_drv;
+
+ index = (unsigned long)cookie & 0xFFFFU;
+ free_irq(mic_db_to_irq(mdrv, index), data);
+ mdrv->irq_info.irq_usage_count[index]--;
+}
+
+/**
+ * mic_next_card_db - Get the doorbell with minimum usage count.
+ *
+ * Returns the irq index.
+ */
+int mic_next_card_db(void)
+{
+ int i;
+ int index = 0;
+ struct mic_driver *mdrv = g_drv;
+
+ for (i = 0; i < mdrv->intr_info.num_intr; i++) {
+ if (mdrv->irq_info.irq_usage_count[i] <
+ mdrv->irq_info.irq_usage_count[index])
+ index = i;
+ }
+
+ return index;
+}
+
+/**
+ * mic_init_irq - Initialize irq information.
+ *
+ * Returns 0 in success. Appropriate error code on failure.
+ */
+static int mic_init_irq(void)
+{
+ struct mic_driver *mdrv = g_drv;
+
+ mdrv->irq_info.irq_usage_count = kzalloc((sizeof(u32) *
+ mdrv->intr_info.num_intr),
+ GFP_KERNEL);
+ if (!mdrv->irq_info.irq_usage_count)
+ return -ENOMEM;
+ return 0;
+}
+
+/**
+ * mic_uninit_irq - Uninitialize irq information.
+ *
+ * None.
+ */
+static void mic_uninit_irq(void)
+{
+ struct mic_driver *mdrv = g_drv;
+
+ kfree(mdrv->irq_info.irq_usage_count);
+}
+
+/*
+ * mic_driver_init - MIC driver initialization tasks.
+ *
+ * Returns 0 in success. Appropriate error code on failure.
+ */
+int __init mic_driver_init(struct mic_driver *mdrv)
+{
+ int rc;
+
+ g_drv = mdrv;
+ /*
+ * Unloading the card module is not supported. The MIC card module
+ * handles fundamental operations like host/card initiated shutdowns
+ * and informing the host about card crashes and cannot be unloaded.
+ */
+ if (!try_module_get(mdrv->dev->driver->owner)) {
+ rc = -ENODEV;
+ goto done;
+ }
+ rc = mic_dp_init();
+ if (rc)
+ goto put;
+ rc = mic_init_irq();
+ if (rc)
+ goto dp_uninit;
+ rc = mic_shutdown_init();
+ if (rc)
+ goto irq_uninit;
+ rc = mic_devices_init(mdrv);
+ if (rc)
+ goto shutdown_uninit;
+ mic_create_card_debug_dir(mdrv);
+ atomic_notifier_chain_register(&panic_notifier_list, &mic_panic);
+done:
+ return rc;
+shutdown_uninit:
+ mic_shutdown_uninit();
+irq_uninit:
+ mic_uninit_irq();
+dp_uninit:
+ mic_dp_uninit();
+put:
+ module_put(mdrv->dev->driver->owner);
+ return rc;
+}
+
+/*
+ * mic_driver_uninit - MIC driver uninitialization tasks.
+ *
+ * Returns None
+ */
+void mic_driver_uninit(struct mic_driver *mdrv)
+{
+ mic_delete_card_debug_dir(mdrv);
+ mic_devices_uninit(mdrv);
+ /*
+ * Inform the host about the shutdown status i.e. poweroff/restart etc.
+ * The module cannot be unloaded so the only code path to call
+ * mic_devices_uninit(..) is the shutdown callback.
+ */
+ mic_notify_host(system_state);
+ mic_shutdown_uninit();
+ mic_uninit_irq();
+ mic_dp_uninit();
+ module_put(mdrv->dev->driver->owner);
+}
diff --git a/drivers/misc/mic/card/mic_device.h b/drivers/misc/mic/card/mic_device.h
new file mode 100644
index 000000000000..347b9b3b7916
--- /dev/null
+++ b/drivers/misc/mic/card/mic_device.h
@@ -0,0 +1,133 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Disclaimer: The codes contained in these modules may be specific to
+ * the Intel Software Development Platform codenamed: Knights Ferry, and
+ * the Intel product codenamed: Knights Corner, and are not backward
+ * compatible with other Intel products. Additionally, Intel will NOT
+ * support the codes or instruction set in future products.
+ *
+ * Intel MIC Card driver.
+ *
+ */
+#ifndef _MIC_CARD_DEVICE_H_
+#define _MIC_CARD_DEVICE_H_
+
+#include <linux/workqueue.h>
+#include <linux/io.h>
+
+/**
+ * struct mic_intr_info - Contains h/w specific interrupt sources info
+ *
+ * @num_intr: The number of irqs available
+ */
+struct mic_intr_info {
+ u32 num_intr;
+};
+
+/**
+ * struct mic_irq_info - OS specific irq information
+ *
+ * @irq_usage_count: usage count array tracking the number of sources
+ * assigned for each irq.
+ */
+struct mic_irq_info {
+ int *irq_usage_count;
+};
+
+/**
+ * struct mic_device - MIC device information.
+ *
+ * @mmio: MMIO bar information.
+ */
+struct mic_device {
+ struct mic_mw mmio;
+};
+
+/**
+ * struct mic_driver - MIC card driver information.
+ *
+ * @name: Name for MIC driver.
+ * @dbg_dir: debugfs directory of this MIC device.
+ * @dev: The device backing this MIC.
+ * @dp: The pointer to the virtio device page.
+ * @mdev: MIC device information for the host.
+ * @hotplug_work: Hot plug work for adding/removing virtio devices.
+ * @irq_info: The OS specific irq information
+ * @intr_info: H/W specific interrupt information.
+ */
+struct mic_driver {
+ char name[20];
+ struct dentry *dbg_dir;
+ struct device *dev;
+ void __iomem *dp;
+ struct mic_device mdev;
+ struct work_struct hotplug_work;
+ struct mic_irq_info irq_info;
+ struct mic_intr_info intr_info;
+};
+
+/**
+ * struct mic_irq - opaque pointer used as cookie
+ */
+struct mic_irq;
+
+/**
+ * mic_mmio_read - read from an MMIO register.
+ * @mw: MMIO register base virtual address.
+ * @offset: register offset.
+ *
+ * RETURNS: register value.
+ */
+static inline u32 mic_mmio_read(struct mic_mw *mw, u32 offset)
+{
+ return ioread32(mw->va + offset);
+}
+
+/**
+ * mic_mmio_write - write to an MMIO register.
+ * @mw: MMIO register base virtual address.
+ * @val: the data value to put into the register
+ * @offset: register offset.
+ *
+ * RETURNS: none.
+ */
+static inline void
+mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset)
+{
+ iowrite32(val, mw->va + offset);
+}
+
+int mic_driver_init(struct mic_driver *mdrv);
+void mic_driver_uninit(struct mic_driver *mdrv);
+int mic_next_card_db(void);
+struct mic_irq *mic_request_card_irq(irqreturn_t (*func)(int irq, void *data),
+ const char *name, void *data, int intr_src);
+void mic_free_card_irq(struct mic_irq *cookie, void *data);
+u32 mic_read_spad(struct mic_device *mdev, unsigned int idx);
+void mic_send_intr(struct mic_device *mdev, int doorbell);
+int mic_db_to_irq(struct mic_driver *mdrv, int db);
+u32 mic_ack_interrupt(struct mic_device *mdev);
+void mic_hw_intr_init(struct mic_driver *mdrv);
+void __iomem *
+mic_card_map(struct mic_device *mdev, dma_addr_t addr, size_t size);
+void mic_card_unmap(struct mic_device *mdev, void __iomem *addr);
+void __init mic_create_card_debug_dir(struct mic_driver *mdrv);
+void mic_delete_card_debug_dir(struct mic_driver *mdrv);
+void __init mic_init_card_debugfs(void);
+void mic_exit_card_debugfs(void);
+#endif
diff --git a/drivers/misc/mic/card/mic_virtio.c b/drivers/misc/mic/card/mic_virtio.c
new file mode 100644
index 000000000000..38275c1b9e03
--- /dev/null
+++ b/drivers/misc/mic/card/mic_virtio.c
@@ -0,0 +1,631 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Disclaimer: The codes contained in these modules may be specific to
+ * the Intel Software Development Platform codenamed: Knights Ferry, and
+ * the Intel product codenamed: Knights Corner, and are not backward
+ * compatible with other Intel products. Additionally, Intel will NOT
+ * support the codes or instruction set in future products.
+ *
+ * Adapted from:
+ *
+ * virtio for kvm on s390
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ * Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
+ *
+ * Intel MIC Card driver.
+ *
+ */
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/virtio_config.h>
+
+#include "../common/mic_device.h"
+#include "mic_virtio.h"
+
+#define VIRTIO_SUBCODE_64 0x0D00
+
+#define MIC_MAX_VRINGS 4
+struct mic_vdev {
+ struct virtio_device vdev;
+ struct mic_device_desc __iomem *desc;
+ struct mic_device_ctrl __iomem *dc;
+ struct mic_device *mdev;
+ void __iomem *vr[MIC_MAX_VRINGS];
+ int used_size[MIC_MAX_VRINGS];
+ struct completion reset_done;
+ struct mic_irq *virtio_cookie;
+ int c2h_vdev_db;
+};
+
+static struct mic_irq *virtio_config_cookie;
+#define to_micvdev(vd) container_of(vd, struct mic_vdev, vdev)
+
+/* Helper API to obtain the parent of the virtio device */
+static inline struct device *mic_dev(struct mic_vdev *mvdev)
+{
+ return mvdev->vdev.dev.parent;
+}
+
+/* This gets the device's feature bits. */
+static u32 mic_get_features(struct virtio_device *vdev)
+{
+ unsigned int i, bits;
+ u32 features = 0;
+ struct mic_device_desc __iomem *desc = to_micvdev(vdev)->desc;
+ u8 __iomem *in_features = mic_vq_features(desc);
+ int feature_len = ioread8(&desc->feature_len);
+
+ bits = min_t(unsigned, feature_len,
+ sizeof(vdev->features)) * 8;
+ for (i = 0; i < bits; i++)
+ if (ioread8(&in_features[i / 8]) & (BIT(i % 8)))
+ features |= BIT(i);
+
+ return features;
+}
+
+static void mic_finalize_features(struct virtio_device *vdev)
+{
+ unsigned int i, bits;
+ struct mic_device_desc __iomem *desc = to_micvdev(vdev)->desc;
+ u8 feature_len = ioread8(&desc->feature_len);
+ /* Second half of bitmap is features we accept. */
+ u8 __iomem *out_features =
+ mic_vq_features(desc) + feature_len;
+
+ /* Give virtio_ring a chance to accept features. */
+ vring_transport_features(vdev);
+
+ memset_io(out_features, 0, feature_len);
+ bits = min_t(unsigned, feature_len,
+ sizeof(vdev->features)) * 8;
+ for (i = 0; i < bits; i++) {
+ if (test_bit(i, vdev->features))
+ iowrite8(ioread8(&out_features[i / 8]) | (1 << (i % 8)),
+ &out_features[i / 8]);
+ }
+}
+
+/*
+ * Reading and writing elements in config space
+ */
+static void mic_get(struct virtio_device *vdev, unsigned int offset,
+ void *buf, unsigned len)
+{
+ struct mic_device_desc __iomem *desc = to_micvdev(vdev)->desc;
+
+ if (offset + len > ioread8(&desc->config_len))
+ return;
+ memcpy_fromio(buf, mic_vq_configspace(desc) + offset, len);
+}
+
+static void mic_set(struct virtio_device *vdev, unsigned int offset,
+ const void *buf, unsigned len)
+{
+ struct mic_device_desc __iomem *desc = to_micvdev(vdev)->desc;
+
+ if (offset + len > ioread8(&desc->config_len))
+ return;
+ memcpy_toio(mic_vq_configspace(desc) + offset, buf, len);
+}
+
+/*
+ * The operations to get and set the status word just access the status
+ * field of the device descriptor. set_status also interrupts the host
+ * to tell about status changes.
+ */
+static u8 mic_get_status(struct virtio_device *vdev)
+{
+ return ioread8(&to_micvdev(vdev)->desc->status);
+}
+
+static void mic_set_status(struct virtio_device *vdev, u8 status)
+{
+ struct mic_vdev *mvdev = to_micvdev(vdev);
+ if (!status)
+ return;
+ iowrite8(status, &mvdev->desc->status);
+ mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
+}
+
+/* Inform host on a virtio device reset and wait for ack from host */
+static void mic_reset_inform_host(struct virtio_device *vdev)
+{
+ struct mic_vdev *mvdev = to_micvdev(vdev);
+ struct mic_device_ctrl __iomem *dc = mvdev->dc;
+ int retry = 100, i;
+
+ iowrite8(0, &dc->host_ack);
+ iowrite8(1, &dc->vdev_reset);
+ mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
+
+ /* Wait till host completes all card accesses and acks the reset */
+ for (i = retry; i--;) {
+ if (ioread8(&dc->host_ack))
+ break;
+ msleep(100);
+ };
+
+ dev_dbg(mic_dev(mvdev), "%s: retry: %d\n", __func__, retry);
+
+ /* Reset status to 0 in case we timed out */
+ iowrite8(0, &mvdev->desc->status);
+}
+
+static void mic_reset(struct virtio_device *vdev)
+{
+ struct mic_vdev *mvdev = to_micvdev(vdev);
+
+ dev_dbg(mic_dev(mvdev), "%s: virtio id %d\n",
+ __func__, vdev->id.device);
+
+ mic_reset_inform_host(vdev);
+ complete_all(&mvdev->reset_done);
+}
+
+/*
+ * The virtio_ring code calls this API when it wants to notify the Host.
+ */
+static void mic_notify(struct virtqueue *vq)
+{
+ struct mic_vdev *mvdev = vq->priv;
+
+ mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
+}
+
+static void mic_del_vq(struct virtqueue *vq, int n)
+{
+ struct mic_vdev *mvdev = to_micvdev(vq->vdev);
+ struct vring *vr = (struct vring *) (vq + 1);
+
+ free_pages((unsigned long) vr->used,
+ get_order(mvdev->used_size[n]));
+ vring_del_virtqueue(vq);
+ mic_card_unmap(mvdev->mdev, mvdev->vr[n]);
+ mvdev->vr[n] = NULL;
+}
+
+static void mic_del_vqs(struct virtio_device *vdev)
+{
+ struct mic_vdev *mvdev = to_micvdev(vdev);
+ struct virtqueue *vq, *n;
+ int idx = 0;
+
+ dev_dbg(mic_dev(mvdev), "%s\n", __func__);
+
+ list_for_each_entry_safe(vq, n, &vdev->vqs, list)
+ mic_del_vq(vq, idx++);
+}
+
+/*
+ * This routine will assign vring's allocated in host/io memory. Code in
+ * virtio_ring.c however continues to access this io memory as if it were local
+ * memory without io accessors.
+ */
+static struct virtqueue *mic_find_vq(struct virtio_device *vdev,
+ unsigned index,
+ void (*callback)(struct virtqueue *vq),
+ const char *name)
+{
+ struct mic_vdev *mvdev = to_micvdev(vdev);
+ struct mic_vqconfig __iomem *vqconfig;
+ struct mic_vqconfig config;
+ struct virtqueue *vq;
+ void __iomem *va;
+ struct _mic_vring_info __iomem *info;
+ void *used;
+ int vr_size, _vr_size, err, magic;
+ struct vring *vr;
+ u8 type = ioread8(&mvdev->desc->type);
+
+ if (index >= ioread8(&mvdev->desc->num_vq))
+ return ERR_PTR(-ENOENT);
+
+ if (!name)
+ return ERR_PTR(-ENOENT);
+
+ /* First assign the vring's allocated in host memory */
+ vqconfig = mic_vq_config(mvdev->desc) + index;
+ memcpy_fromio(&config, vqconfig, sizeof(config));
+ _vr_size = vring_size(config.num, MIC_VIRTIO_RING_ALIGN);
+ vr_size = PAGE_ALIGN(_vr_size + sizeof(struct _mic_vring_info));
+ va = mic_card_map(mvdev->mdev, config.address, vr_size);
+ if (!va)
+ return ERR_PTR(-ENOMEM);
+ mvdev->vr[index] = va;
+ memset_io(va, 0x0, _vr_size);
+ vq = vring_new_virtqueue(index,
+ config.num, MIC_VIRTIO_RING_ALIGN, vdev,
+ false,
+ va, mic_notify, callback, name);
+ if (!vq) {
+ err = -ENOMEM;
+ goto unmap;
+ }
+ info = va + _vr_size;
+ magic = ioread32(&info->magic);
+
+ if (WARN(magic != MIC_MAGIC + type + index, "magic mismatch")) {
+ err = -EIO;
+ goto unmap;
+ }
+
+ /* Allocate and reassign used ring now */
+ mvdev->used_size[index] = PAGE_ALIGN(sizeof(__u16) * 3 +
+ sizeof(struct vring_used_elem) * config.num);
+ used = (void *) __get_free_pages(GFP_KERNEL | __GFP_ZERO,
+ get_order(mvdev->used_size[index]));
+ if (!used) {
+ err = -ENOMEM;
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, err);
+ goto del_vq;
+ }
+ iowrite64(virt_to_phys(used), &vqconfig->used_address);
+
+ /*
+ * To reassign the used ring here we are directly accessing
+ * struct vring_virtqueue which is a private data structure
+ * in virtio_ring.c. At the minimum, a BUILD_BUG_ON() in
+ * vring_new_virtqueue() would ensure that
+ * (&vq->vring == (struct vring *) (&vq->vq + 1));
+ */
+ vr = (struct vring *) (vq + 1);
+ vr->used = used;
+
+ vq->priv = mvdev;
+ return vq;
+del_vq:
+ vring_del_virtqueue(vq);
+unmap:
+ mic_card_unmap(mvdev->mdev, mvdev->vr[index]);
+ return ERR_PTR(err);
+}
+
+static int mic_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+ struct virtqueue *vqs[],
+ vq_callback_t *callbacks[],
+ const char *names[])
+{
+ struct mic_vdev *mvdev = to_micvdev(vdev);
+ struct mic_device_ctrl __iomem *dc = mvdev->dc;
+ int i, err, retry = 100;
+
+ /* We must have this many virtqueues. */
+ if (nvqs > ioread8(&mvdev->desc->num_vq))
+ return -ENOENT;
+
+ for (i = 0; i < nvqs; ++i) {
+ dev_dbg(mic_dev(mvdev), "%s: %d: %s\n",
+ __func__, i, names[i]);
+ vqs[i] = mic_find_vq(vdev, i, callbacks[i], names[i]);
+ if (IS_ERR(vqs[i])) {
+ err = PTR_ERR(vqs[i]);
+ goto error;
+ }
+ }
+
+ iowrite8(1, &dc->used_address_updated);
+ /*
+ * Send an interrupt to the host to inform it that used
+ * rings have been re-assigned.
+ */
+ mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
+ for (i = retry; i--;) {
+ if (!ioread8(&dc->used_address_updated))
+ break;
+ msleep(100);
+ };
+
+ dev_dbg(mic_dev(mvdev), "%s: retry: %d\n", __func__, retry);
+ if (!retry) {
+ err = -ENODEV;
+ goto error;
+ }
+
+ return 0;
+error:
+ mic_del_vqs(vdev);
+ return err;
+}
+
+/*
+ * The config ops structure as defined by virtio config
+ */
+static struct virtio_config_ops mic_vq_config_ops = {
+ .get_features = mic_get_features,
+ .finalize_features = mic_finalize_features,
+ .get = mic_get,
+ .set = mic_set,
+ .get_status = mic_get_status,
+ .set_status = mic_set_status,
+ .reset = mic_reset,
+ .find_vqs = mic_find_vqs,
+ .del_vqs = mic_del_vqs,
+};
+
+static irqreturn_t
+mic_virtio_intr_handler(int irq, void *data)
+{
+ struct mic_vdev *mvdev = data;
+ struct virtqueue *vq;
+
+ mic_ack_interrupt(mvdev->mdev);
+ list_for_each_entry(vq, &mvdev->vdev.vqs, list)
+ vring_interrupt(0, vq);
+
+ return IRQ_HANDLED;
+}
+
+static void mic_virtio_release_dev(struct device *_d)
+{
+ /*
+ * No need for a release method similar to virtio PCI.
+ * Provide an empty one to avoid getting a warning from core.
+ */
+}
+
+/*
+ * adds a new device and register it with virtio
+ * appropriate drivers are loaded by the device model
+ */
+static int mic_add_device(struct mic_device_desc __iomem *d,
+ unsigned int offset, struct mic_driver *mdrv)
+{
+ struct mic_vdev *mvdev;
+ int ret;
+ int virtio_db;
+ u8 type = ioread8(&d->type);
+
+ mvdev = kzalloc(sizeof(*mvdev), GFP_KERNEL);
+ if (!mvdev) {
+ dev_err(mdrv->dev, "Cannot allocate mic dev %u type %u\n",
+ offset, type);
+ return -ENOMEM;
+ }
+
+ mvdev->mdev = &mdrv->mdev;
+ mvdev->vdev.dev.parent = mdrv->dev;
+ mvdev->vdev.dev.release = mic_virtio_release_dev;
+ mvdev->vdev.id.device = type;
+ mvdev->vdev.config = &mic_vq_config_ops;
+ mvdev->desc = d;
+ mvdev->dc = (void __iomem *)d + mic_aligned_desc_size(d);
+ init_completion(&mvdev->reset_done);
+
+ virtio_db = mic_next_card_db();
+ mvdev->virtio_cookie = mic_request_card_irq(mic_virtio_intr_handler,
+ "virtio intr", mvdev, virtio_db);
+ if (IS_ERR(mvdev->virtio_cookie)) {
+ ret = PTR_ERR(mvdev->virtio_cookie);
+ goto kfree;
+ }
+ iowrite8((u8)virtio_db, &mvdev->dc->h2c_vdev_db);
+ mvdev->c2h_vdev_db = ioread8(&mvdev->dc->c2h_vdev_db);
+
+ ret = register_virtio_device(&mvdev->vdev);
+ if (ret) {
+ dev_err(mic_dev(mvdev),
+ "Failed to register mic device %u type %u\n",
+ offset, type);
+ goto free_irq;
+ }
+ iowrite64((u64)mvdev, &mvdev->dc->vdev);
+ dev_dbg(mic_dev(mvdev), "%s: registered mic device %u type %u mvdev %p\n",
+ __func__, offset, type, mvdev);
+
+ return 0;
+
+free_irq:
+ mic_free_card_irq(mvdev->virtio_cookie, mvdev);
+kfree:
+ kfree(mvdev);
+ return ret;
+}
+
+/*
+ * match for a mic device with a specific desc pointer
+ */
+static int mic_match_desc(struct device *dev, void *data)
+{
+ struct virtio_device *vdev = dev_to_virtio(dev);
+ struct mic_vdev *mvdev = to_micvdev(vdev);
+
+ return mvdev->desc == (void __iomem *)data;
+}
+
+static void mic_handle_config_change(struct mic_device_desc __iomem *d,
+ unsigned int offset, struct mic_driver *mdrv)
+{
+ struct mic_device_ctrl __iomem *dc
+ = (void __iomem *)d + mic_aligned_desc_size(d);
+ struct mic_vdev *mvdev = (struct mic_vdev *)ioread64(&dc->vdev);
+ struct virtio_driver *drv;
+
+ if (ioread8(&dc->config_change) != MIC_VIRTIO_PARAM_CONFIG_CHANGED)
+ return;
+
+ dev_dbg(mdrv->dev, "%s %d\n", __func__, __LINE__);
+ drv = container_of(mvdev->vdev.dev.driver,
+ struct virtio_driver, driver);
+ if (drv->config_changed)
+ drv->config_changed(&mvdev->vdev);
+ iowrite8(1, &dc->guest_ack);
+}
+
+/*
+ * removes a virtio device if a hot remove event has been
+ * requested by the host.
+ */
+static int mic_remove_device(struct mic_device_desc __iomem *d,
+ unsigned int offset, struct mic_driver *mdrv)
+{
+ struct mic_device_ctrl __iomem *dc
+ = (void __iomem *)d + mic_aligned_desc_size(d);
+ struct mic_vdev *mvdev = (struct mic_vdev *)ioread64(&dc->vdev);
+ u8 status;
+ int ret = -1;
+
+ if (ioread8(&dc->config_change) == MIC_VIRTIO_PARAM_DEV_REMOVE) {
+ dev_dbg(mdrv->dev,
+ "%s %d config_change %d type %d mvdev %p\n",
+ __func__, __LINE__,
+ ioread8(&dc->config_change), ioread8(&d->type), mvdev);
+
+ status = ioread8(&d->status);
+ INIT_COMPLETION(mvdev->reset_done);
+ unregister_virtio_device(&mvdev->vdev);
+ mic_free_card_irq(mvdev->virtio_cookie, mvdev);
+ if (status & VIRTIO_CONFIG_S_DRIVER_OK)
+ wait_for_completion(&mvdev->reset_done);
+ kfree(mvdev);
+ iowrite8(1, &dc->guest_ack);
+ dev_dbg(mdrv->dev, "%s %d guest_ack %d\n",
+ __func__, __LINE__, ioread8(&dc->guest_ack));
+ ret = 0;
+ }
+
+ return ret;
+}
+
+#define REMOVE_DEVICES true
+
+static void mic_scan_devices(struct mic_driver *mdrv, bool remove)
+{
+ s8 type;
+ unsigned int i;
+ struct mic_device_desc __iomem *d;
+ struct mic_device_ctrl __iomem *dc;
+ struct device *dev;
+ int ret;
+
+ for (i = mic_aligned_size(struct mic_bootparam);
+ i < MIC_DP_SIZE; i += mic_total_desc_size(d)) {
+ d = mdrv->dp + i;
+ dc = (void __iomem *)d + mic_aligned_desc_size(d);
+ /*
+ * This read barrier is paired with the corresponding write
+ * barrier on the host which is inserted before adding or
+ * removing a virtio device descriptor, by updating the type.
+ */
+ rmb();
+ type = ioread8(&d->type);
+
+ /* end of list */
+ if (type == 0)
+ break;
+
+ if (type == -1)
+ continue;
+
+ /* device already exists */
+ dev = device_find_child(mdrv->dev, d, mic_match_desc);
+ if (dev) {
+ if (remove)
+ iowrite8(MIC_VIRTIO_PARAM_DEV_REMOVE,
+ &dc->config_change);
+ put_device(dev);
+ mic_handle_config_change(d, i, mdrv);
+ ret = mic_remove_device(d, i, mdrv);
+ if (!ret && !remove)
+ iowrite8(-1, &d->type);
+ if (remove) {
+ iowrite8(0, &dc->config_change);
+ iowrite8(0, &dc->guest_ack);
+ }
+ continue;
+ }
+
+ /* new device */
+ dev_dbg(mdrv->dev, "%s %d Adding new virtio device %p\n",
+ __func__, __LINE__, d);
+ if (!remove)
+ mic_add_device(d, i, mdrv);
+ }
+}
+
+/*
+ * mic_hotplug_device tries to find changes in the device page.
+ */
+static void mic_hotplug_devices(struct work_struct *work)
+{
+ struct mic_driver *mdrv = container_of(work,
+ struct mic_driver, hotplug_work);
+
+ mic_scan_devices(mdrv, !REMOVE_DEVICES);
+}
+
+/*
+ * Interrupt handler for hot plug/config changes etc.
+ */
+static irqreturn_t
+mic_extint_handler(int irq, void *data)
+{
+ struct mic_driver *mdrv = (struct mic_driver *)data;
+
+ dev_dbg(mdrv->dev, "%s %d hotplug work\n",
+ __func__, __LINE__);
+ mic_ack_interrupt(&mdrv->mdev);
+ schedule_work(&mdrv->hotplug_work);
+ return IRQ_HANDLED;
+}
+
+/*
+ * Init function for virtio
+ */
+int mic_devices_init(struct mic_driver *mdrv)
+{
+ int rc;
+ struct mic_bootparam __iomem *bootparam;
+ int config_db;
+
+ INIT_WORK(&mdrv->hotplug_work, mic_hotplug_devices);
+ mic_scan_devices(mdrv, !REMOVE_DEVICES);
+
+ config_db = mic_next_card_db();
+ virtio_config_cookie = mic_request_card_irq(mic_extint_handler,
+ "virtio_config_intr", mdrv, config_db);
+ if (IS_ERR(virtio_config_cookie)) {
+ rc = PTR_ERR(virtio_config_cookie);
+ goto exit;
+ }
+
+ bootparam = mdrv->dp;
+ iowrite8(config_db, &bootparam->h2c_config_db);
+ return 0;
+exit:
+ return rc;
+}
+
+/*
+ * Uninit function for virtio
+ */
+void mic_devices_uninit(struct mic_driver *mdrv)
+{
+ struct mic_bootparam __iomem *bootparam = mdrv->dp;
+ iowrite8(-1, &bootparam->h2c_config_db);
+ mic_free_card_irq(virtio_config_cookie, mdrv);
+ flush_work(&mdrv->hotplug_work);
+ mic_scan_devices(mdrv, REMOVE_DEVICES);
+}
diff --git a/drivers/misc/mic/card/mic_virtio.h b/drivers/misc/mic/card/mic_virtio.h
new file mode 100644
index 000000000000..2c5c22c93ba8
--- /dev/null
+++ b/drivers/misc/mic/card/mic_virtio.h
@@ -0,0 +1,77 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Disclaimer: The codes contained in these modules may be specific to
+ * the Intel Software Development Platform codenamed: Knights Ferry, and
+ * the Intel product codenamed: Knights Corner, and are not backward
+ * compatible with other Intel products. Additionally, Intel will NOT
+ * support the codes or instruction set in future products.
+ *
+ * Intel MIC Card driver.
+ *
+ */
+#ifndef __MIC_CARD_VIRTIO_H
+#define __MIC_CARD_VIRTIO_H
+
+#include <linux/mic_common.h>
+#include "mic_device.h"
+
+/*
+ * 64 bit I/O access
+ */
+#ifndef ioread64
+#define ioread64 readq
+#endif
+#ifndef iowrite64
+#define iowrite64 writeq
+#endif
+
+static inline unsigned mic_desc_size(struct mic_device_desc __iomem *desc)
+{
+ return mic_aligned_size(*desc)
+ + ioread8(&desc->num_vq) * mic_aligned_size(struct mic_vqconfig)
+ + ioread8(&desc->feature_len) * 2
+ + ioread8(&desc->config_len);
+}
+
+static inline struct mic_vqconfig __iomem *
+mic_vq_config(struct mic_device_desc __iomem *desc)
+{
+ return (struct mic_vqconfig __iomem *)(desc + 1);
+}
+
+static inline __u8 __iomem *
+mic_vq_features(struct mic_device_desc __iomem *desc)
+{
+ return (__u8 __iomem *)(mic_vq_config(desc) + ioread8(&desc->num_vq));
+}
+
+static inline __u8 __iomem *
+mic_vq_configspace(struct mic_device_desc __iomem *desc)
+{
+ return mic_vq_features(desc) + ioread8(&desc->feature_len) * 2;
+}
+static inline unsigned mic_total_desc_size(struct mic_device_desc __iomem *desc)
+{
+ return mic_aligned_desc_size(desc) +
+ mic_aligned_size(struct mic_device_ctrl);
+}
+
+int mic_devices_init(struct mic_driver *mdrv);
+void mic_devices_uninit(struct mic_driver *mdrv);
+
+#endif
diff --git a/drivers/misc/mic/card/mic_x100.c b/drivers/misc/mic/card/mic_x100.c
new file mode 100644
index 000000000000..7cb3469cf684
--- /dev/null
+++ b/drivers/misc/mic/card/mic_x100.c
@@ -0,0 +1,256 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Disclaimer: The codes contained in these modules may be specific to
+ * the Intel Software Development Platform codenamed: Knights Ferry, and
+ * the Intel product codenamed: Knights Corner, and are not backward
+ * compatible with other Intel products. Additionally, Intel will NOT
+ * support the codes or instruction set in future products.
+ *
+ * Intel MIC Card driver.
+ *
+ */
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+
+#include "../common/mic_device.h"
+#include "mic_device.h"
+#include "mic_x100.h"
+
+static const char mic_driver_name[] = "mic";
+
+static struct mic_driver g_drv;
+
+/**
+ * mic_read_spad - read from the scratchpad register
+ * @mdev: pointer to mic_device instance
+ * @idx: index to scratchpad register, 0 based
+ *
+ * This function allows reading of the 32bit scratchpad register.
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+u32 mic_read_spad(struct mic_device *mdev, unsigned int idx)
+{
+ return mic_mmio_read(&mdev->mmio,
+ MIC_X100_SBOX_BASE_ADDRESS +
+ MIC_X100_SBOX_SPAD0 + idx * 4);
+}
+
+/**
+ * __mic_send_intr - Send interrupt to Host.
+ * @mdev: pointer to mic_device instance
+ * @doorbell: Doorbell number.
+ */
+void mic_send_intr(struct mic_device *mdev, int doorbell)
+{
+ struct mic_mw *mw = &mdev->mmio;
+
+ if (doorbell > MIC_X100_MAX_DOORBELL_IDX)
+ return;
+ /* Ensure that the interrupt is ordered w.r.t previous stores. */
+ wmb();
+ mic_mmio_write(mw, MIC_X100_SBOX_SDBIC0_DBREQ_BIT,
+ MIC_X100_SBOX_BASE_ADDRESS +
+ (MIC_X100_SBOX_SDBIC0 + (4 * doorbell)));
+}
+
+/**
+ * mic_ack_interrupt - Device specific interrupt handling.
+ * @mdev: pointer to mic_device instance
+ *
+ * Returns: bitmask of doorbell events triggered.
+ */
+u32 mic_ack_interrupt(struct mic_device *mdev)
+{
+ return 0;
+}
+
+static inline int mic_get_sbox_irq(int db)
+{
+ return MIC_X100_IRQ_BASE + db;
+}
+
+static inline int mic_get_rdmasr_irq(int index)
+{
+ return MIC_X100_RDMASR_IRQ_BASE + index;
+}
+
+/**
+ * mic_hw_intr_init - Initialize h/w specific interrupt
+ * information.
+ * @mdrv: pointer to mic_driver
+ */
+void mic_hw_intr_init(struct mic_driver *mdrv)
+{
+ mdrv->intr_info.num_intr = MIC_X100_NUM_SBOX_IRQ +
+ MIC_X100_NUM_RDMASR_IRQ;
+}
+
+/**
+ * mic_db_to_irq - Retrieve irq number corresponding to a doorbell.
+ * @mdrv: pointer to mic_driver
+ * @db: The doorbell obtained for which the irq is needed. Doorbell
+ * may correspond to an sbox doorbell or an rdmasr index.
+ *
+ * Returns the irq corresponding to the doorbell.
+ */
+int mic_db_to_irq(struct mic_driver *mdrv, int db)
+{
+ int rdmasr_index;
+ if (db < MIC_X100_NUM_SBOX_IRQ) {
+ return mic_get_sbox_irq(db);
+ } else {
+ rdmasr_index = db - MIC_X100_NUM_SBOX_IRQ +
+ MIC_X100_RDMASR_IRQ_BASE;
+ return mic_get_rdmasr_irq(rdmasr_index);
+ }
+}
+
+/*
+ * mic_card_map - Allocate virtual address for a remote memory region.
+ * @mdev: pointer to mic_device instance.
+ * @addr: Remote DMA address.
+ * @size: Size of the region.
+ *
+ * Returns: Virtual address backing the remote memory region.
+ */
+void __iomem *
+mic_card_map(struct mic_device *mdev, dma_addr_t addr, size_t size)
+{
+ return ioremap(addr, size);
+}
+
+/*
+ * mic_card_unmap - Unmap the virtual address for a remote memory region.
+ * @mdev: pointer to mic_device instance.
+ * @addr: Virtual address for remote memory region.
+ *
+ * Returns: None.
+ */
+void mic_card_unmap(struct mic_device *mdev, void __iomem *addr)
+{
+ iounmap(addr);
+}
+
+static int __init mic_probe(struct platform_device *pdev)
+{
+ struct mic_driver *mdrv = &g_drv;
+ struct mic_device *mdev = &mdrv->mdev;
+ int rc = 0;
+
+ mdrv->dev = &pdev->dev;
+ snprintf(mdrv->name, sizeof(mic_driver_name), mic_driver_name);
+
+ mdev->mmio.pa = MIC_X100_MMIO_BASE;
+ mdev->mmio.len = MIC_X100_MMIO_LEN;
+ mdev->mmio.va = ioremap(MIC_X100_MMIO_BASE, MIC_X100_MMIO_LEN);
+ if (!mdev->mmio.va) {
+ dev_err(&pdev->dev, "Cannot remap MMIO BAR\n");
+ rc = -EIO;
+ goto done;
+ }
+ mic_hw_intr_init(mdrv);
+ rc = mic_driver_init(mdrv);
+ if (rc) {
+ dev_err(&pdev->dev, "mic_driver_init failed rc %d\n", rc);
+ goto iounmap;
+ }
+done:
+ return rc;
+iounmap:
+ iounmap(mdev->mmio.va);
+ return rc;
+}
+
+static int mic_remove(struct platform_device *pdev)
+{
+ struct mic_driver *mdrv = &g_drv;
+ struct mic_device *mdev = &mdrv->mdev;
+
+ mic_driver_uninit(mdrv);
+ iounmap(mdev->mmio.va);
+ return 0;
+}
+
+static void mic_platform_shutdown(struct platform_device *pdev)
+{
+ mic_remove(pdev);
+}
+
+static struct platform_device mic_platform_dev = {
+ .name = mic_driver_name,
+ .id = 0,
+ .num_resources = 0,
+};
+
+static struct platform_driver __refdata mic_platform_driver = {
+ .probe = mic_probe,
+ .remove = mic_remove,
+ .shutdown = mic_platform_shutdown,
+ .driver = {
+ .name = mic_driver_name,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init mic_init(void)
+{
+ int ret;
+ struct cpuinfo_x86 *c = &cpu_data(0);
+
+ if (!(c->x86 == 11 && c->x86_model == 1)) {
+ ret = -ENODEV;
+ pr_err("%s not running on X100 ret %d\n", __func__, ret);
+ goto done;
+ }
+
+ mic_init_card_debugfs();
+ ret = platform_device_register(&mic_platform_dev);
+ if (ret) {
+ pr_err("platform_device_register ret %d\n", ret);
+ goto cleanup_debugfs;
+ }
+ ret = platform_driver_register(&mic_platform_driver);
+ if (ret) {
+ pr_err("platform_driver_register ret %d\n", ret);
+ goto device_unregister;
+ }
+ return ret;
+
+device_unregister:
+ platform_device_unregister(&mic_platform_dev);
+cleanup_debugfs:
+ mic_exit_card_debugfs();
+done:
+ return ret;
+}
+
+static void __exit mic_exit(void)
+{
+ platform_driver_unregister(&mic_platform_driver);
+ platform_device_unregister(&mic_platform_dev);
+ mic_exit_card_debugfs();
+}
+
+module_init(mic_init);
+module_exit(mic_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Intel(R) MIC X100 Card driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/card/mic_x100.h b/drivers/misc/mic/card/mic_x100.h
new file mode 100644
index 000000000000..d66ea55639c3
--- /dev/null
+++ b/drivers/misc/mic/card/mic_x100.h
@@ -0,0 +1,48 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Disclaimer: The codes contained in these modules may be specific to
+ * the Intel Software Development Platform codenamed: Knights Ferry, and
+ * the Intel product codenamed: Knights Corner, and are not backward
+ * compatible with other Intel products. Additionally, Intel will NOT
+ * support the codes or instruction set in future products.
+ *
+ * Intel MIC Card driver.
+ *
+ */
+#ifndef _MIC_X100_CARD_H_
+#define _MIC_X100_CARD_H_
+
+#define MIC_X100_MMIO_BASE 0x08007C0000ULL
+#define MIC_X100_MMIO_LEN 0x00020000ULL
+#define MIC_X100_SBOX_BASE_ADDRESS 0x00010000ULL
+
+#define MIC_X100_SBOX_SPAD0 0x0000AB20
+#define MIC_X100_SBOX_SDBIC0 0x0000CC90
+#define MIC_X100_SBOX_SDBIC0_DBREQ_BIT 0x80000000
+#define MIC_X100_SBOX_RDMASR0 0x0000B180
+
+#define MIC_X100_MAX_DOORBELL_IDX 8
+
+#define MIC_X100_NUM_SBOX_IRQ 8
+#define MIC_X100_NUM_RDMASR_IRQ 8
+#define MIC_X100_SBOX_IRQ_BASE 0
+#define MIC_X100_RDMASR_IRQ_BASE 17
+
+#define MIC_X100_IRQ_BASE 26
+
+#endif
diff --git a/drivers/misc/mic/common/mic_device.h b/drivers/misc/mic/common/mic_device.h
new file mode 100644
index 000000000000..01eb74faae6b
--- /dev/null
+++ b/drivers/misc/mic/common/mic_device.h
@@ -0,0 +1,51 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC driver.
+ *
+ */
+#ifndef __MIC_COMMON_DEVICE_H_
+#define __MIC_COMMON_DEVICE_H_
+
+/**
+ * struct mic_mw - MIC memory window
+ *
+ * @pa: Base physical address.
+ * @va: Base ioremap'd virtual address.
+ * @len: Size of the memory window.
+ */
+struct mic_mw {
+ phys_addr_t pa;
+ void __iomem *va;
+ resource_size_t len;
+};
+
+/*
+ * Scratch pad register offsets used by the host to communicate
+ * device page DMA address to the card.
+ */
+#define MIC_DPLO_SPAD 14
+#define MIC_DPHI_SPAD 15
+
+/*
+ * These values are supposed to be in the config_change field of the
+ * device page when the host sends a config change interrupt to the card.
+ */
+#define MIC_VIRTIO_PARAM_DEV_REMOVE 0x1
+#define MIC_VIRTIO_PARAM_CONFIG_CHANGED 0x2
+
+#endif
diff --git a/drivers/misc/mic/host/Makefile b/drivers/misc/mic/host/Makefile
new file mode 100644
index 000000000000..c2197f999394
--- /dev/null
+++ b/drivers/misc/mic/host/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile - Intel MIC Linux driver.
+# Copyright(c) 2013, Intel Corporation.
+#
+obj-$(CONFIG_INTEL_MIC_HOST) += mic_host.o
+mic_host-objs := mic_main.o
+mic_host-objs += mic_x100.o
+mic_host-objs += mic_sysfs.o
+mic_host-objs += mic_smpt.o
+mic_host-objs += mic_intr.o
+mic_host-objs += mic_boot.o
+mic_host-objs += mic_debugfs.o
+mic_host-objs += mic_fops.o
+mic_host-objs += mic_virtio.o
diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c
new file mode 100644
index 000000000000..fd9ff6d3784e
--- /dev/null
+++ b/drivers/misc/mic/host/mic_boot.c
@@ -0,0 +1,185 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#include <linux/delay.h>
+#include <linux/firmware.h>
+
+#include <linux/mic_common.h>
+#include "../common/mic_device.h"
+#include "mic_device.h"
+#include "mic_smpt.h"
+#include "mic_virtio.h"
+
+/**
+ * mic_reset - Reset the MIC device.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_reset(struct mic_device *mdev)
+{
+ int i;
+
+#define MIC_RESET_TO (45)
+
+ mdev->ops->reset_fw_ready(mdev);
+ mdev->ops->reset(mdev);
+
+ for (i = 0; i < MIC_RESET_TO; i++) {
+ if (mdev->ops->is_fw_ready(mdev))
+ return;
+ /*
+ * Resets typically take 10s of seconds to complete.
+ * Since an MMIO read is required to check if the
+ * firmware is ready or not, a 1 second delay works nicely.
+ */
+ msleep(1000);
+ }
+ mic_set_state(mdev, MIC_RESET_FAILED);
+}
+
+/* Initialize the MIC bootparams */
+void mic_bootparam_init(struct mic_device *mdev)
+{
+ struct mic_bootparam *bootparam = mdev->dp;
+
+ bootparam->magic = MIC_MAGIC;
+ bootparam->c2h_shutdown_db = mdev->shutdown_db;
+ bootparam->h2c_shutdown_db = -1;
+ bootparam->h2c_config_db = -1;
+ bootparam->shutdown_status = 0;
+ bootparam->shutdown_card = 0;
+}
+
+/**
+ * mic_start - Start the MIC.
+ * @mdev: pointer to mic_device instance
+ * @buf: buffer containing boot string including firmware/ramdisk path.
+ *
+ * This function prepares an MIC for boot and initiates boot.
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+int mic_start(struct mic_device *mdev, const char *buf)
+{
+ int rc;
+ mutex_lock(&mdev->mic_mutex);
+retry:
+ if (MIC_OFFLINE != mdev->state) {
+ rc = -EINVAL;
+ goto unlock_ret;
+ }
+ if (!mdev->ops->is_fw_ready(mdev)) {
+ mic_reset(mdev);
+ /*
+ * The state will either be MIC_OFFLINE if the reset succeeded
+ * or MIC_RESET_FAILED if the firmware reset failed.
+ */
+ goto retry;
+ }
+ rc = mdev->ops->load_mic_fw(mdev, buf);
+ if (rc)
+ goto unlock_ret;
+ mic_smpt_restore(mdev);
+ mic_intr_restore(mdev);
+ mdev->intr_ops->enable_interrupts(mdev);
+ mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr);
+ mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
+ mdev->ops->send_firmware_intr(mdev);
+ mic_set_state(mdev, MIC_ONLINE);
+unlock_ret:
+ mutex_unlock(&mdev->mic_mutex);
+ return rc;
+}
+
+/**
+ * mic_stop - Prepare the MIC for reset and trigger reset.
+ * @mdev: pointer to mic_device instance
+ * @force: force a MIC to reset even if it is already offline.
+ *
+ * RETURNS: None.
+ */
+void mic_stop(struct mic_device *mdev, bool force)
+{
+ mutex_lock(&mdev->mic_mutex);
+ if (MIC_OFFLINE != mdev->state || force) {
+ mic_virtio_reset_devices(mdev);
+ mic_bootparam_init(mdev);
+ mic_reset(mdev);
+ if (MIC_RESET_FAILED == mdev->state)
+ goto unlock;
+ mic_set_shutdown_status(mdev, MIC_NOP);
+ mic_set_state(mdev, MIC_OFFLINE);
+ }
+unlock:
+ mutex_unlock(&mdev->mic_mutex);
+}
+
+/**
+ * mic_shutdown - Initiate MIC shutdown.
+ * @mdev: pointer to mic_device instance
+ *
+ * RETURNS: None.
+ */
+void mic_shutdown(struct mic_device *mdev)
+{
+ struct mic_bootparam *bootparam = mdev->dp;
+ s8 db = bootparam->h2c_shutdown_db;
+
+ mutex_lock(&mdev->mic_mutex);
+ if (MIC_ONLINE == mdev->state && db != -1) {
+ bootparam->shutdown_card = 1;
+ mdev->ops->send_intr(mdev, db);
+ mic_set_state(mdev, MIC_SHUTTING_DOWN);
+ }
+ mutex_unlock(&mdev->mic_mutex);
+}
+
+/**
+ * mic_shutdown_work - Handle shutdown interrupt from MIC.
+ * @work: The work structure.
+ *
+ * This work is scheduled whenever the host has received a shutdown
+ * interrupt from the MIC.
+ */
+void mic_shutdown_work(struct work_struct *work)
+{
+ struct mic_device *mdev = container_of(work, struct mic_device,
+ shutdown_work);
+ struct mic_bootparam *bootparam = mdev->dp;
+
+ mutex_lock(&mdev->mic_mutex);
+ mic_set_shutdown_status(mdev, bootparam->shutdown_status);
+ bootparam->shutdown_status = 0;
+ if (MIC_SHUTTING_DOWN != mdev->state)
+ mic_set_state(mdev, MIC_SHUTTING_DOWN);
+ mutex_unlock(&mdev->mic_mutex);
+}
+
+/**
+ * mic_reset_trigger_work - Trigger MIC reset.
+ * @work: The work structure.
+ *
+ * This work is scheduled whenever the host wants to reset the MIC.
+ */
+void mic_reset_trigger_work(struct work_struct *work)
+{
+ struct mic_device *mdev = container_of(work, struct mic_device,
+ reset_trigger_work);
+
+ mic_stop(mdev, false);
+}
diff --git a/drivers/misc/mic/host/mic_debugfs.c b/drivers/misc/mic/host/mic_debugfs.c
new file mode 100644
index 000000000000..e22fb7bbbb98
--- /dev/null
+++ b/drivers/misc/mic/host/mic_debugfs.c
@@ -0,0 +1,495 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#include <linux/debugfs.h>
+#include <linux/pci.h>
+#include <linux/seq_file.h>
+
+#include <linux/mic_common.h>
+#include "../common/mic_device.h"
+#include "mic_device.h"
+#include "mic_smpt.h"
+#include "mic_virtio.h"
+
+/* Debugfs parent dir */
+static struct dentry *mic_dbg;
+
+/**
+ * mic_log_buf_show - Display MIC kernel log buffer.
+ *
+ * log_buf addr/len is read from System.map by user space
+ * and populated in sysfs entries.
+ */
+static int mic_log_buf_show(struct seq_file *s, void *unused)
+{
+ void __iomem *log_buf_va;
+ int __iomem *log_buf_len_va;
+ struct mic_device *mdev = s->private;
+ void *kva;
+ int size;
+ unsigned long aper_offset;
+
+ if (!mdev || !mdev->log_buf_addr || !mdev->log_buf_len)
+ goto done;
+ /*
+ * Card kernel will never be relocated and any kernel text/data mapping
+ * can be translated to phys address by subtracting __START_KERNEL_map.
+ */
+ aper_offset = (unsigned long)mdev->log_buf_len - __START_KERNEL_map;
+ log_buf_len_va = mdev->aper.va + aper_offset;
+ aper_offset = (unsigned long)mdev->log_buf_addr - __START_KERNEL_map;
+ log_buf_va = mdev->aper.va + aper_offset;
+ size = ioread32(log_buf_len_va);
+
+ kva = kmalloc(size, GFP_KERNEL);
+ if (!kva)
+ goto done;
+ mutex_lock(&mdev->mic_mutex);
+ memcpy_fromio(kva, log_buf_va, size);
+ switch (mdev->state) {
+ case MIC_ONLINE:
+ /* Fall through */
+ case MIC_SHUTTING_DOWN:
+ seq_write(s, kva, size);
+ break;
+ default:
+ break;
+ }
+ mutex_unlock(&mdev->mic_mutex);
+ kfree(kva);
+done:
+ return 0;
+}
+
+static int mic_log_buf_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mic_log_buf_show, inode->i_private);
+}
+
+static int mic_log_buf_release(struct inode *inode, struct file *file)
+{
+ return single_release(inode, file);
+}
+
+static const struct file_operations log_buf_ops = {
+ .owner = THIS_MODULE,
+ .open = mic_log_buf_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = mic_log_buf_release
+};
+
+static int mic_smpt_show(struct seq_file *s, void *pos)
+{
+ int i;
+ struct mic_device *mdev = s->private;
+ unsigned long flags;
+
+ seq_printf(s, "MIC %-2d |%-10s| %-14s %-10s\n",
+ mdev->id, "SMPT entry", "SW DMA addr", "RefCount");
+ seq_puts(s, "====================================================\n");
+
+ if (mdev->smpt) {
+ struct mic_smpt_info *smpt_info = mdev->smpt;
+ spin_lock_irqsave(&smpt_info->smpt_lock, flags);
+ for (i = 0; i < smpt_info->info.num_reg; i++) {
+ seq_printf(s, "%9s|%-10d| %-#14llx %-10lld\n",
+ " ", i, smpt_info->entry[i].dma_addr,
+ smpt_info->entry[i].ref_count);
+ }
+ spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
+ }
+ seq_puts(s, "====================================================\n");
+ return 0;
+}
+
+static int mic_smpt_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mic_smpt_show, inode->i_private);
+}
+
+static int mic_smpt_debug_release(struct inode *inode, struct file *file)
+{
+ return single_release(inode, file);
+}
+
+static const struct file_operations smpt_file_ops = {
+ .owner = THIS_MODULE,
+ .open = mic_smpt_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = mic_smpt_debug_release
+};
+
+static int mic_soft_reset_show(struct seq_file *s, void *pos)
+{
+ struct mic_device *mdev = s->private;
+
+ mic_stop(mdev, true);
+ return 0;
+}
+
+static int mic_soft_reset_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mic_soft_reset_show, inode->i_private);
+}
+
+static int mic_soft_reset_debug_release(struct inode *inode, struct file *file)
+{
+ return single_release(inode, file);
+}
+
+static const struct file_operations soft_reset_ops = {
+ .owner = THIS_MODULE,
+ .open = mic_soft_reset_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = mic_soft_reset_debug_release
+};
+
+static int mic_post_code_show(struct seq_file *s, void *pos)
+{
+ struct mic_device *mdev = s->private;
+ u32 reg = mdev->ops->get_postcode(mdev);
+
+ seq_printf(s, "%c%c", reg & 0xff, (reg >> 8) & 0xff);
+ return 0;
+}
+
+static int mic_post_code_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mic_post_code_show, inode->i_private);
+}
+
+static int mic_post_code_debug_release(struct inode *inode, struct file *file)
+{
+ return single_release(inode, file);
+}
+
+static const struct file_operations post_code_ops = {
+ .owner = THIS_MODULE,
+ .open = mic_post_code_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = mic_post_code_debug_release
+};
+
+static int mic_dp_show(struct seq_file *s, void *pos)
+{
+ struct mic_device *mdev = s->private;
+ struct mic_device_desc *d;
+ struct mic_device_ctrl *dc;
+ struct mic_vqconfig *vqconfig;
+ __u32 *features;
+ __u8 *config;
+ struct mic_bootparam *bootparam = mdev->dp;
+ int i, j;
+
+ seq_printf(s, "Bootparam: magic 0x%x\n",
+ bootparam->magic);
+ seq_printf(s, "Bootparam: h2c_shutdown_db %d\n",
+ bootparam->h2c_shutdown_db);
+ seq_printf(s, "Bootparam: h2c_config_db %d\n",
+ bootparam->h2c_config_db);
+ seq_printf(s, "Bootparam: c2h_shutdown_db %d\n",
+ bootparam->c2h_shutdown_db);
+ seq_printf(s, "Bootparam: shutdown_status %d\n",
+ bootparam->shutdown_status);
+ seq_printf(s, "Bootparam: shutdown_card %d\n",
+ bootparam->shutdown_card);
+
+ for (i = sizeof(*bootparam); i < MIC_DP_SIZE;
+ i += mic_total_desc_size(d)) {
+ d = mdev->dp + i;
+ dc = (void *)d + mic_aligned_desc_size(d);
+
+ /* end of list */
+ if (d->type == 0)
+ break;
+
+ if (d->type == -1)
+ continue;
+
+ seq_printf(s, "Type %d ", d->type);
+ seq_printf(s, "Num VQ %d ", d->num_vq);
+ seq_printf(s, "Feature Len %d\n", d->feature_len);
+ seq_printf(s, "Config Len %d ", d->config_len);
+ seq_printf(s, "Shutdown Status %d\n", d->status);
+
+ for (j = 0; j < d->num_vq; j++) {
+ vqconfig = mic_vq_config(d) + j;
+ seq_printf(s, "vqconfig[%d]: ", j);
+ seq_printf(s, "address 0x%llx ", vqconfig->address);
+ seq_printf(s, "num %d ", vqconfig->num);
+ seq_printf(s, "used address 0x%llx\n",
+ vqconfig->used_address);
+ }
+
+ features = (__u32 *) mic_vq_features(d);
+ seq_printf(s, "Features: Host 0x%x ", features[0]);
+ seq_printf(s, "Guest 0x%x\n", features[1]);
+
+ config = mic_vq_configspace(d);
+ for (j = 0; j < d->config_len; j++)
+ seq_printf(s, "config[%d]=%d\n", j, config[j]);
+
+ seq_puts(s, "Device control:\n");
+ seq_printf(s, "Config Change %d ", dc->config_change);
+ seq_printf(s, "Vdev reset %d\n", dc->vdev_reset);
+ seq_printf(s, "Guest Ack %d ", dc->guest_ack);
+ seq_printf(s, "Host ack %d\n", dc->host_ack);
+ seq_printf(s, "Used address updated %d ",
+ dc->used_address_updated);
+ seq_printf(s, "Vdev 0x%llx\n", dc->vdev);
+ seq_printf(s, "c2h doorbell %d ", dc->c2h_vdev_db);
+ seq_printf(s, "h2c doorbell %d\n", dc->h2c_vdev_db);
+ }
+
+ return 0;
+}
+
+static int mic_dp_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mic_dp_show, inode->i_private);
+}
+
+static int mic_dp_debug_release(struct inode *inode, struct file *file)
+{
+ return single_release(inode, file);
+}
+
+static const struct file_operations dp_ops = {
+ .owner = THIS_MODULE,
+ .open = mic_dp_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = mic_dp_debug_release
+};
+
+static int mic_vdev_info_show(struct seq_file *s, void *unused)
+{
+ struct mic_device *mdev = s->private;
+ struct list_head *pos, *tmp;
+ struct mic_vdev *mvdev;
+ int i, j;
+
+ mutex_lock(&mdev->mic_mutex);
+ list_for_each_safe(pos, tmp, &mdev->vdev_list) {
+ mvdev = list_entry(pos, struct mic_vdev, list);
+ seq_printf(s, "VDEV type %d state %s in %ld out %ld\n",
+ mvdev->virtio_id,
+ mic_vdevup(mvdev) ? "UP" : "DOWN",
+ mvdev->in_bytes,
+ mvdev->out_bytes);
+ for (i = 0; i < MIC_MAX_VRINGS; i++) {
+ struct vring_desc *desc;
+ struct vring_avail *avail;
+ struct vring_used *used;
+ struct mic_vringh *mvr = &mvdev->mvr[i];
+ struct vringh *vrh = &mvr->vrh;
+ int num = vrh->vring.num;
+ if (!num)
+ continue;
+ desc = vrh->vring.desc;
+ seq_printf(s, "vring i %d avail_idx %d",
+ i, mvr->vring.info->avail_idx & (num - 1));
+ seq_printf(s, " vring i %d avail_idx %d\n",
+ i, mvr->vring.info->avail_idx);
+ seq_printf(s, "vrh i %d weak_barriers %d",
+ i, vrh->weak_barriers);
+ seq_printf(s, " last_avail_idx %d last_used_idx %d",
+ vrh->last_avail_idx, vrh->last_used_idx);
+ seq_printf(s, " completed %d\n", vrh->completed);
+ for (j = 0; j < num; j++) {
+ seq_printf(s, "desc[%d] addr 0x%llx len %d",
+ j, desc->addr, desc->len);
+ seq_printf(s, " flags 0x%x next %d\n",
+ desc->flags,
+ desc->next);
+ desc++;
+ }
+ avail = vrh->vring.avail;
+ seq_printf(s, "avail flags 0x%x idx %d\n",
+ avail->flags, avail->idx & (num - 1));
+ seq_printf(s, "avail flags 0x%x idx %d\n",
+ avail->flags, avail->idx);
+ for (j = 0; j < num; j++)
+ seq_printf(s, "avail ring[%d] %d\n",
+ j, avail->ring[j]);
+ used = vrh->vring.used;
+ seq_printf(s, "used flags 0x%x idx %d\n",
+ used->flags, used->idx & (num - 1));
+ seq_printf(s, "used flags 0x%x idx %d\n",
+ used->flags, used->idx);
+ for (j = 0; j < num; j++)
+ seq_printf(s, "used ring[%d] id %d len %d\n",
+ j, used->ring[j].id, used->ring[j].len);
+ }
+ }
+ mutex_unlock(&mdev->mic_mutex);
+
+ return 0;
+}
+
+static int mic_vdev_info_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mic_vdev_info_show, inode->i_private);
+}
+
+static int mic_vdev_info_debug_release(struct inode *inode, struct file *file)
+{
+ return single_release(inode, file);
+}
+
+static const struct file_operations vdev_info_ops = {
+ .owner = THIS_MODULE,
+ .open = mic_vdev_info_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = mic_vdev_info_debug_release
+};
+
+static int mic_msi_irq_info_show(struct seq_file *s, void *pos)
+{
+ struct mic_device *mdev = s->private;
+ int reg;
+ int i, j;
+ u16 entry;
+ u16 vector;
+ struct pci_dev *pdev = container_of(mdev->sdev->parent,
+ struct pci_dev, dev);
+
+ if (pci_dev_msi_enabled(pdev)) {
+ for (i = 0; i < mdev->irq_info.num_vectors; i++) {
+ if (pdev->msix_enabled) {
+ entry = mdev->irq_info.msix_entries[i].entry;
+ vector = mdev->irq_info.msix_entries[i].vector;
+ } else {
+ entry = 0;
+ vector = pdev->irq;
+ }
+
+ reg = mdev->intr_ops->read_msi_to_src_map(mdev, entry);
+
+ seq_printf(s, "%s %-10d %s %-10d MXAR[%d]: %08X\n",
+ "IRQ:", vector, "Entry:", entry, i, reg);
+
+ seq_printf(s, "%-10s", "offset:");
+ for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--)
+ seq_printf(s, "%4d ", j);
+ seq_puts(s, "\n");
+
+
+ seq_printf(s, "%-10s", "count:");
+ for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--)
+ seq_printf(s, "%4d ",
+ (mdev->irq_info.mic_msi_map[i] & BIT(j)) ?
+ 1 : 0);
+ seq_puts(s, "\n\n");
+ }
+ } else {
+ seq_puts(s, "MSI/MSIx interrupts not enabled\n");
+ }
+
+ return 0;
+
+}
+
+static int mic_msi_irq_info_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mic_msi_irq_info_show, inode->i_private);
+}
+
+static int
+mic_msi_irq_info_debug_release(struct inode *inode, struct file *file)
+{
+ return single_release(inode, file);
+}
+
+static const struct file_operations msi_irq_info_ops = {
+ .owner = THIS_MODULE,
+ .open = mic_msi_irq_info_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = mic_msi_irq_info_debug_release
+};
+
+/**
+ * mic_create_debug_dir - Initialize MIC debugfs entries.
+ */
+void mic_create_debug_dir(struct mic_device *mdev)
+{
+ if (!mic_dbg)
+ return;
+
+ mdev->dbg_dir = debugfs_create_dir(dev_name(mdev->sdev), mic_dbg);
+ if (!mdev->dbg_dir)
+ return;
+
+ debugfs_create_file("log_buf", 0444, mdev->dbg_dir,
+ mdev, &log_buf_ops);
+
+ debugfs_create_file("smpt", 0444, mdev->dbg_dir,
+ mdev, &smpt_file_ops);
+
+ debugfs_create_file("soft_reset", 0444, mdev->dbg_dir,
+ mdev, &soft_reset_ops);
+
+ debugfs_create_file("post_code", 0444, mdev->dbg_dir,
+ mdev, &post_code_ops);
+
+ debugfs_create_file("dp", 0444, mdev->dbg_dir,
+ mdev, &dp_ops);
+
+ debugfs_create_file("vdev_info", 0444, mdev->dbg_dir,
+ mdev, &vdev_info_ops);
+
+ debugfs_create_file("msi_irq_info", 0444, mdev->dbg_dir,
+ mdev, &msi_irq_info_ops);
+}
+
+/**
+ * mic_delete_debug_dir - Uninitialize MIC debugfs entries.
+ */
+void mic_delete_debug_dir(struct mic_device *mdev)
+{
+ if (!mdev->dbg_dir)
+ return;
+
+ debugfs_remove_recursive(mdev->dbg_dir);
+}
+
+/**
+ * mic_init_debugfs - Initialize global debugfs entry.
+ */
+void __init mic_init_debugfs(void)
+{
+ mic_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
+ if (!mic_dbg)
+ pr_err("can't create debugfs dir\n");
+}
+
+/**
+ * mic_exit_debugfs - Uninitialize global debugfs entry
+ */
+void mic_exit_debugfs(void)
+{
+ debugfs_remove(mic_dbg);
+}
diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h
new file mode 100644
index 000000000000..dcba2a59e77f
--- /dev/null
+++ b/drivers/misc/mic/host/mic_device.h
@@ -0,0 +1,195 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#ifndef _MIC_DEVICE_H_
+#define _MIC_DEVICE_H_
+
+#include <linux/cdev.h>
+#include <linux/idr.h>
+
+#include "mic_intr.h"
+
+/* The maximum number of MIC devices supported in a single host system. */
+#define MIC_MAX_NUM_DEVS 256
+
+/**
+ * enum mic_hw_family - The hardware family to which a device belongs.
+ */
+enum mic_hw_family {
+ MIC_FAMILY_X100 = 0,
+ MIC_FAMILY_UNKNOWN
+};
+
+/**
+ * enum mic_stepping - MIC stepping ids.
+ */
+enum mic_stepping {
+ MIC_A0_STEP = 0x0,
+ MIC_B0_STEP = 0x10,
+ MIC_B1_STEP = 0x11,
+ MIC_C0_STEP = 0x20,
+};
+
+/**
+ * struct mic_device - MIC device information for each card.
+ *
+ * @mmio: MMIO bar information.
+ * @aper: Aperture bar information.
+ * @family: The MIC family to which this device belongs.
+ * @ops: MIC HW specific operations.
+ * @id: The unique device id for this MIC device.
+ * @stepping: Stepping ID.
+ * @attr_group: Pointer to list of sysfs attribute groups.
+ * @sdev: Device for sysfs entries.
+ * @mic_mutex: Mutex for synchronizing access to mic_device.
+ * @intr_ops: HW specific interrupt operations.
+ * @smpt_ops: Hardware specific SMPT operations.
+ * @smpt: MIC SMPT information.
+ * @intr_info: H/W specific interrupt information.
+ * @irq_info: The OS specific irq information
+ * @dbg_dir: debugfs directory of this MIC device.
+ * @cmdline: Kernel command line.
+ * @firmware: Firmware file name.
+ * @ramdisk: Ramdisk file name.
+ * @bootmode: Boot mode i.e. "linux" or "elf" for flash updates.
+ * @bootaddr: MIC boot address.
+ * @reset_trigger_work: Work for triggering reset requests.
+ * @shutdown_work: Work for handling shutdown interrupts.
+ * @state: MIC state.
+ * @shutdown_status: MIC status reported by card for shutdown/crashes.
+ * @state_sysfs: Sysfs dirent for notifying ring 3 about MIC state changes.
+ * @log_buf_addr: Log buffer address for MIC.
+ * @log_buf_len: Log buffer length address for MIC.
+ * @dp: virtio device page
+ * @dp_dma_addr: virtio device page DMA address.
+ * @shutdown_db: shutdown doorbell.
+ * @shutdown_cookie: shutdown cookie.
+ * @cdev: Character device for MIC.
+ * @vdev_list: list of virtio devices.
+ */
+struct mic_device {
+ struct mic_mw mmio;
+ struct mic_mw aper;
+ enum mic_hw_family family;
+ struct mic_hw_ops *ops;
+ int id;
+ enum mic_stepping stepping;
+ const struct attribute_group **attr_group;
+ struct device *sdev;
+ struct mutex mic_mutex;
+ struct mic_hw_intr_ops *intr_ops;
+ struct mic_smpt_ops *smpt_ops;
+ struct mic_smpt_info *smpt;
+ struct mic_intr_info *intr_info;
+ struct mic_irq_info irq_info;
+ struct dentry *dbg_dir;
+ char *cmdline;
+ char *firmware;
+ char *ramdisk;
+ char *bootmode;
+ u32 bootaddr;
+ struct work_struct reset_trigger_work;
+ struct work_struct shutdown_work;
+ u8 state;
+ u8 shutdown_status;
+ struct sysfs_dirent *state_sysfs;
+ void *log_buf_addr;
+ int *log_buf_len;
+ void *dp;
+ dma_addr_t dp_dma_addr;
+ int shutdown_db;
+ struct mic_irq *shutdown_cookie;
+ struct cdev cdev;
+ struct list_head vdev_list;
+};
+
+/**
+ * struct mic_hw_ops - MIC HW specific operations.
+ * @aper_bar: Aperture bar resource number.
+ * @mmio_bar: MMIO bar resource number.
+ * @read_spad: Read from scratch pad register.
+ * @write_spad: Write to scratch pad register.
+ * @send_intr: Send an interrupt for a particular doorbell on the card.
+ * @ack_interrupt: Hardware specific operations to ack the h/w on
+ * receipt of an interrupt.
+ * @reset: Reset the remote processor.
+ * @reset_fw_ready: Reset firmware ready field.
+ * @is_fw_ready: Check if firmware is ready for OS download.
+ * @send_firmware_intr: Send an interrupt to the card firmware.
+ * @load_mic_fw: Load firmware segments required to boot the card
+ * into card memory. This includes the kernel, command line, ramdisk etc.
+ * @get_postcode: Get post code status from firmware.
+ */
+struct mic_hw_ops {
+ u8 aper_bar;
+ u8 mmio_bar;
+ u32 (*read_spad)(struct mic_device *mdev, unsigned int idx);
+ void (*write_spad)(struct mic_device *mdev, unsigned int idx, u32 val);
+ void (*send_intr)(struct mic_device *mdev, int doorbell);
+ u32 (*ack_interrupt)(struct mic_device *mdev);
+ void (*reset)(struct mic_device *mdev);
+ void (*reset_fw_ready)(struct mic_device *mdev);
+ bool (*is_fw_ready)(struct mic_device *mdev);
+ void (*send_firmware_intr)(struct mic_device *mdev);
+ int (*load_mic_fw)(struct mic_device *mdev, const char *buf);
+ u32 (*get_postcode)(struct mic_device *mdev);
+};
+
+/**
+ * mic_mmio_read - read from an MMIO register.
+ * @mw: MMIO register base virtual address.
+ * @offset: register offset.
+ *
+ * RETURNS: register value.
+ */
+static inline u32 mic_mmio_read(struct mic_mw *mw, u32 offset)
+{
+ return ioread32(mw->va + offset);
+}
+
+/**
+ * mic_mmio_write - write to an MMIO register.
+ * @mw: MMIO register base virtual address.
+ * @val: the data value to put into the register
+ * @offset: register offset.
+ *
+ * RETURNS: none.
+ */
+static inline void
+mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset)
+{
+ iowrite32(val, mw->va + offset);
+}
+
+void mic_sysfs_init(struct mic_device *mdev);
+int mic_start(struct mic_device *mdev, const char *buf);
+void mic_stop(struct mic_device *mdev, bool force);
+void mic_shutdown(struct mic_device *mdev);
+void mic_reset_delayed_work(struct work_struct *work);
+void mic_reset_trigger_work(struct work_struct *work);
+void mic_shutdown_work(struct work_struct *work);
+void mic_bootparam_init(struct mic_device *mdev);
+void mic_set_state(struct mic_device *mdev, u8 state);
+void mic_set_shutdown_status(struct mic_device *mdev, u8 status);
+void mic_create_debug_dir(struct mic_device *dev);
+void mic_delete_debug_dir(struct mic_device *dev);
+void __init mic_init_debugfs(void);
+void mic_exit_debugfs(void);
+#endif
diff --git a/drivers/misc/mic/host/mic_fops.c b/drivers/misc/mic/host/mic_fops.c
new file mode 100644
index 000000000000..661469ad339d
--- /dev/null
+++ b/drivers/misc/mic/host/mic_fops.c
@@ -0,0 +1,221 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#include <linux/poll.h>
+
+#include <linux/mic_common.h>
+#include "../common/mic_device.h"
+#include "mic_device.h"
+#include "mic_fops.h"
+#include "mic_virtio.h"
+
+int mic_open(struct inode *inode, struct file *f)
+{
+ struct mic_vdev *mvdev;
+ struct mic_device *mdev = container_of(inode->i_cdev,
+ struct mic_device, cdev);
+
+ mvdev = kzalloc(sizeof(*mvdev), GFP_KERNEL);
+ if (!mvdev)
+ return -ENOMEM;
+
+ init_waitqueue_head(&mvdev->waitq);
+ INIT_LIST_HEAD(&mvdev->list);
+ mvdev->mdev = mdev;
+ mvdev->virtio_id = -1;
+
+ f->private_data = mvdev;
+ return 0;
+}
+
+int mic_release(struct inode *inode, struct file *f)
+{
+ struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
+
+ if (-1 != mvdev->virtio_id)
+ mic_virtio_del_device(mvdev);
+ f->private_data = NULL;
+ kfree(mvdev);
+ return 0;
+}
+
+long mic_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+ struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
+ void __user *argp = (void __user *)arg;
+ int ret;
+
+ switch (cmd) {
+ case MIC_VIRTIO_ADD_DEVICE:
+ {
+ ret = mic_virtio_add_device(mvdev, argp);
+ if (ret < 0) {
+ dev_err(mic_dev(mvdev),
+ "%s %d errno ret %d\n",
+ __func__, __LINE__, ret);
+ return ret;
+ }
+ break;
+ }
+ case MIC_VIRTIO_COPY_DESC:
+ {
+ struct mic_copy_desc copy;
+
+ ret = mic_vdev_inited(mvdev);
+ if (ret)
+ return ret;
+
+ if (copy_from_user(&copy, argp, sizeof(copy)))
+ return -EFAULT;
+
+ dev_dbg(mic_dev(mvdev),
+ "%s %d === iovcnt 0x%x vr_idx 0x%x update_used %d\n",
+ __func__, __LINE__, copy.iovcnt, copy.vr_idx,
+ copy.update_used);
+
+ ret = mic_virtio_copy_desc(mvdev, &copy);
+ if (ret < 0) {
+ dev_err(mic_dev(mvdev),
+ "%s %d errno ret %d\n",
+ __func__, __LINE__, ret);
+ return ret;
+ }
+ if (copy_to_user(
+ &((struct mic_copy_desc __user *)argp)->out_len,
+ &copy.out_len, sizeof(copy.out_len))) {
+ dev_err(mic_dev(mvdev), "%s %d errno ret %d\n",
+ __func__, __LINE__, -EFAULT);
+ return -EFAULT;
+ }
+ break;
+ }
+ case MIC_VIRTIO_CONFIG_CHANGE:
+ {
+ ret = mic_vdev_inited(mvdev);
+ if (ret)
+ return ret;
+
+ ret = mic_virtio_config_change(mvdev, argp);
+ if (ret < 0) {
+ dev_err(mic_dev(mvdev),
+ "%s %d errno ret %d\n",
+ __func__, __LINE__, ret);
+ return ret;
+ }
+ break;
+ }
+ default:
+ return -ENOIOCTLCMD;
+ };
+ return 0;
+}
+
+/*
+ * We return POLLIN | POLLOUT from poll when new buffers are enqueued, and
+ * not when previously enqueued buffers may be available. This means that
+ * in the card->host (TX) path, when userspace is unblocked by poll it
+ * must drain all available descriptors or it can stall.
+ */
+unsigned int mic_poll(struct file *f, poll_table *wait)
+{
+ struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
+ int mask = 0;
+
+ poll_wait(f, &mvdev->waitq, wait);
+
+ if (mic_vdev_inited(mvdev))
+ mask = POLLERR;
+ else if (mvdev->poll_wake) {
+ mvdev->poll_wake = 0;
+ mask = POLLIN | POLLOUT;
+ }
+
+ return mask;
+}
+
+static inline int
+mic_query_offset(struct mic_vdev *mvdev, unsigned long offset,
+ unsigned long *size, unsigned long *pa)
+{
+ struct mic_device *mdev = mvdev->mdev;
+ unsigned long start = MIC_DP_SIZE;
+ int i;
+
+ /*
+ * MMAP interface is as follows:
+ * offset region
+ * 0x0 virtio device_page
+ * 0x1000 first vring
+ * 0x1000 + size of 1st vring second vring
+ * ....
+ */
+ if (!offset) {
+ *pa = virt_to_phys(mdev->dp);
+ *size = MIC_DP_SIZE;
+ return 0;
+ }
+
+ for (i = 0; i < mvdev->dd->num_vq; i++) {
+ struct mic_vringh *mvr = &mvdev->mvr[i];
+ if (offset == start) {
+ *pa = virt_to_phys(mvr->vring.va);
+ *size = mvr->vring.len;
+ return 0;
+ }
+ start += mvr->vring.len;
+ }
+ return -1;
+}
+
+/*
+ * Maps the device page and virtio rings to user space for readonly access.
+ */
+int
+mic_mmap(struct file *f, struct vm_area_struct *vma)
+{
+ struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ unsigned long pa, size = vma->vm_end - vma->vm_start, size_rem = size;
+ int i, err;
+
+ err = mic_vdev_inited(mvdev);
+ if (err)
+ return err;
+
+ if (vma->vm_flags & VM_WRITE)
+ return -EACCES;
+
+ while (size_rem) {
+ i = mic_query_offset(mvdev, offset, &size, &pa);
+ if (i < 0)
+ return -EINVAL;
+ err = remap_pfn_range(vma, vma->vm_start + offset,
+ pa >> PAGE_SHIFT, size, vma->vm_page_prot);
+ if (err)
+ return err;
+ dev_dbg(mic_dev(mvdev),
+ "%s %d type %d size 0x%lx off 0x%lx pa 0x%lx vma 0x%lx\n",
+ __func__, __LINE__, mvdev->virtio_id, size, offset,
+ pa, vma->vm_start + offset);
+ size_rem -= size;
+ offset += size;
+ }
+ return 0;
+}
diff --git a/drivers/misc/mic/host/mic_fops.h b/drivers/misc/mic/host/mic_fops.h
new file mode 100644
index 000000000000..dc3893dff667
--- /dev/null
+++ b/drivers/misc/mic/host/mic_fops.h
@@ -0,0 +1,32 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#ifndef _MIC_FOPS_H_
+#define _MIC_FOPS_H_
+
+int mic_open(struct inode *inode, struct file *filp);
+int mic_release(struct inode *inode, struct file *filp);
+ssize_t mic_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *pos);
+long mic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+int mic_mmap(struct file *f, struct vm_area_struct *vma);
+unsigned int mic_poll(struct file *f, poll_table *wait);
+
+#endif
diff --git a/drivers/misc/mic/host/mic_intr.c b/drivers/misc/mic/host/mic_intr.c
new file mode 100644
index 000000000000..cdae3141dbb9
--- /dev/null
+++ b/drivers/misc/mic/host/mic_intr.c
@@ -0,0 +1,628 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
+#include "../common/mic_device.h"
+#include "mic_device.h"
+
+/*
+ * mic_invoke_callback - Invoke callback functions registered for
+ * the corresponding source id.
+ *
+ * @mdev: pointer to the mic_device instance
+ * @idx: The interrupt source id.
+ *
+ * Returns none.
+ */
+static inline void mic_invoke_callback(struct mic_device *mdev, int idx)
+{
+ struct mic_intr_cb *intr_cb;
+ struct pci_dev *pdev = container_of(mdev->sdev->parent,
+ struct pci_dev, dev);
+
+ spin_lock(&mdev->irq_info.mic_intr_lock);
+ list_for_each_entry(intr_cb, &mdev->irq_info.cb_list[idx], list)
+ if (intr_cb->func)
+ intr_cb->func(pdev->irq, intr_cb->data);
+ spin_unlock(&mdev->irq_info.mic_intr_lock);
+}
+
+/**
+ * mic_interrupt - Generic interrupt handler for
+ * MSI and INTx based interrupts.
+ */
+static irqreturn_t mic_interrupt(int irq, void *dev)
+{
+ struct mic_device *mdev = dev;
+ struct mic_intr_info *info = mdev->intr_info;
+ u32 mask;
+ int i;
+
+ mask = mdev->ops->ack_interrupt(mdev);
+ if (!mask)
+ return IRQ_NONE;
+
+ for (i = info->intr_start_idx[MIC_INTR_DB];
+ i < info->intr_len[MIC_INTR_DB]; i++)
+ if (mask & BIT(i))
+ mic_invoke_callback(mdev, i);
+
+ return IRQ_HANDLED;
+}
+
+/* Return the interrupt offset from the index. Index is 0 based. */
+static u16 mic_map_src_to_offset(struct mic_device *mdev,
+ int intr_src, enum mic_intr_type type) {
+
+ if (type >= MIC_NUM_INTR_TYPES)
+ return MIC_NUM_OFFSETS;
+ if (intr_src >= mdev->intr_info->intr_len[type])
+ return MIC_NUM_OFFSETS;
+
+ return mdev->intr_info->intr_start_idx[type] + intr_src;
+}
+
+/* Return next available msix_entry. */
+static struct msix_entry *mic_get_available_vector(struct mic_device *mdev)
+{
+ int i;
+ struct mic_irq_info *info = &mdev->irq_info;
+
+ for (i = 0; i < info->num_vectors; i++)
+ if (!info->mic_msi_map[i])
+ return &info->msix_entries[i];
+ return NULL;
+}
+
+/**
+ * mic_register_intr_callback - Register a callback handler for the
+ * given source id.
+ *
+ * @mdev: pointer to the mic_device instance
+ * @idx: The source id to be registered.
+ * @func: The function to be called when the source id receives
+ * the interrupt.
+ * @data: Private data of the requester.
+ * Return the callback structure that was registered or an
+ * appropriate error on failure.
+ */
+static struct mic_intr_cb *mic_register_intr_callback(struct mic_device *mdev,
+ u8 idx, irqreturn_t (*func) (int irq, void *dev),
+ void *data)
+{
+ struct mic_intr_cb *intr_cb;
+ unsigned long flags;
+ int rc;
+ intr_cb = kmalloc(sizeof(struct mic_intr_cb), GFP_KERNEL);
+
+ if (!intr_cb)
+ return ERR_PTR(-ENOMEM);
+
+ intr_cb->func = func;
+ intr_cb->data = data;
+ intr_cb->cb_id = ida_simple_get(&mdev->irq_info.cb_ida,
+ 0, 0, GFP_KERNEL);
+ if (intr_cb->cb_id < 0) {
+ rc = intr_cb->cb_id;
+ goto ida_fail;
+ }
+
+ spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
+ list_add_tail(&intr_cb->list, &mdev->irq_info.cb_list[idx]);
+ spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
+
+ return intr_cb;
+ida_fail:
+ kfree(intr_cb);
+ return ERR_PTR(rc);
+}
+
+/**
+ * mic_unregister_intr_callback - Unregister the callback handler
+ * identified by its callback id.
+ *
+ * @mdev: pointer to the mic_device instance
+ * @idx: The callback structure id to be unregistered.
+ * Return the source id that was unregistered or MIC_NUM_OFFSETS if no
+ * such callback handler was found.
+ */
+static u8 mic_unregister_intr_callback(struct mic_device *mdev, u32 idx)
+{
+ struct list_head *pos, *tmp;
+ struct mic_intr_cb *intr_cb;
+ unsigned long flags;
+ int i;
+
+ for (i = 0; i < MIC_NUM_OFFSETS; i++) {
+ spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
+ list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
+ intr_cb = list_entry(pos, struct mic_intr_cb, list);
+ if (intr_cb->cb_id == idx) {
+ list_del(pos);
+ ida_simple_remove(&mdev->irq_info.cb_ida,
+ intr_cb->cb_id);
+ kfree(intr_cb);
+ spin_unlock_irqrestore(
+ &mdev->irq_info.mic_intr_lock, flags);
+ return i;
+ }
+ }
+ spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
+ }
+ return MIC_NUM_OFFSETS;
+}
+
+/**
+ * mic_setup_msix - Initializes MSIx interrupts.
+ *
+ * @mdev: pointer to mic_device instance
+ *
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+static int mic_setup_msix(struct mic_device *mdev, struct pci_dev *pdev)
+{
+ int rc, i;
+
+ mdev->irq_info.msix_entries = kmalloc(sizeof(struct msix_entry) *
+ MIC_MIN_MSIX, GFP_KERNEL);
+ if (!mdev->irq_info.msix_entries) {
+ rc = -ENOMEM;
+ goto err_nomem1;
+ }
+
+ for (i = 0; i < MIC_MIN_MSIX; i++)
+ mdev->irq_info.msix_entries[i].entry = i;
+
+ rc = pci_enable_msix(pdev, mdev->irq_info.msix_entries,
+ MIC_MIN_MSIX);
+ if (rc) {
+ dev_dbg(&pdev->dev, "Error enabling MSIx. rc = %d\n", rc);
+ goto err_enable_msix;
+ }
+
+ mdev->irq_info.num_vectors = MIC_MIN_MSIX;
+ mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) *
+ mdev->irq_info.num_vectors), GFP_KERNEL);
+
+ if (!mdev->irq_info.mic_msi_map) {
+ rc = -ENOMEM;
+ goto err_nomem2;
+ }
+
+ dev_dbg(mdev->sdev->parent,
+ "%d MSIx irqs setup\n", mdev->irq_info.num_vectors);
+ return 0;
+err_nomem2:
+ pci_disable_msix(pdev);
+err_enable_msix:
+ kfree(mdev->irq_info.msix_entries);
+err_nomem1:
+ mdev->irq_info.num_vectors = 0;
+ return rc;
+}
+
+/**
+ * mic_setup_callbacks - Initialize data structures needed
+ * to handle callbacks.
+ *
+ * @mdev: pointer to mic_device instance
+ */
+static int mic_setup_callbacks(struct mic_device *mdev)
+{
+ int i;
+
+ mdev->irq_info.cb_list = kmalloc(sizeof(struct list_head) *
+ MIC_NUM_OFFSETS, GFP_KERNEL);
+ if (!mdev->irq_info.cb_list)
+ return -ENOMEM;
+
+ for (i = 0; i < MIC_NUM_OFFSETS; i++)
+ INIT_LIST_HEAD(&mdev->irq_info.cb_list[i]);
+ ida_init(&mdev->irq_info.cb_ida);
+ spin_lock_init(&mdev->irq_info.mic_intr_lock);
+ return 0;
+}
+
+/**
+ * mic_release_callbacks - Uninitialize data structures needed
+ * to handle callbacks.
+ *
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_release_callbacks(struct mic_device *mdev)
+{
+ unsigned long flags;
+ struct list_head *pos, *tmp;
+ struct mic_intr_cb *intr_cb;
+ int i;
+
+ for (i = 0; i < MIC_NUM_OFFSETS; i++) {
+ spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
+
+ if (list_empty(&mdev->irq_info.cb_list[i])) {
+ spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock,
+ flags);
+ break;
+ }
+
+ list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
+ intr_cb = list_entry(pos, struct mic_intr_cb, list);
+ list_del(pos);
+ ida_simple_remove(&mdev->irq_info.cb_ida,
+ intr_cb->cb_id);
+ kfree(intr_cb);
+ }
+ spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
+ }
+ ida_destroy(&mdev->irq_info.cb_ida);
+ kfree(mdev->irq_info.cb_list);
+}
+
+/**
+ * mic_setup_msi - Initializes MSI interrupts.
+ *
+ * @mdev: pointer to mic_device instance
+ * @pdev: PCI device structure
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+static int mic_setup_msi(struct mic_device *mdev, struct pci_dev *pdev)
+{
+ int rc;
+
+ rc = pci_enable_msi(pdev);
+ if (rc) {
+ dev_dbg(&pdev->dev, "Error enabling MSI. rc = %d\n", rc);
+ return rc;
+ }
+
+ mdev->irq_info.num_vectors = 1;
+ mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) *
+ mdev->irq_info.num_vectors), GFP_KERNEL);
+
+ if (!mdev->irq_info.mic_msi_map) {
+ rc = -ENOMEM;
+ goto err_nomem1;
+ }
+
+ rc = mic_setup_callbacks(mdev);
+ if (rc) {
+ dev_err(&pdev->dev, "Error setting up callbacks\n");
+ goto err_nomem2;
+ }
+
+ rc = request_irq(pdev->irq, mic_interrupt, 0 , "mic-msi", mdev);
+ if (rc) {
+ dev_err(&pdev->dev, "Error allocating MSI interrupt\n");
+ goto err_irq_req_fail;
+ }
+
+ dev_dbg(&pdev->dev, "%d MSI irqs setup\n", mdev->irq_info.num_vectors);
+ return 0;
+err_irq_req_fail:
+ mic_release_callbacks(mdev);
+err_nomem2:
+ kfree(mdev->irq_info.mic_msi_map);
+err_nomem1:
+ pci_disable_msi(pdev);
+ mdev->irq_info.num_vectors = 0;
+ return rc;
+}
+
+/**
+ * mic_setup_intx - Initializes legacy interrupts.
+ *
+ * @mdev: pointer to mic_device instance
+ * @pdev: PCI device structure
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+static int mic_setup_intx(struct mic_device *mdev, struct pci_dev *pdev)
+{
+ int rc;
+
+ pci_msi_off(pdev);
+
+ /* Enable intx */
+ pci_intx(pdev, 1);
+ rc = mic_setup_callbacks(mdev);
+ if (rc) {
+ dev_err(&pdev->dev, "Error setting up callbacks\n");
+ goto err_nomem;
+ }
+
+ rc = request_irq(pdev->irq, mic_interrupt,
+ IRQF_SHARED, "mic-intx", mdev);
+ if (rc)
+ goto err;
+
+ dev_dbg(&pdev->dev, "intx irq setup\n");
+ return 0;
+err:
+ mic_release_callbacks(mdev);
+err_nomem:
+ return rc;
+}
+
+/**
+ * mic_next_db - Retrieve the next doorbell interrupt source id.
+ * The id is picked sequentially from the available pool of
+ * doorlbell ids.
+ *
+ * @mdev: pointer to the mic_device instance.
+ *
+ * Returns the next doorbell interrupt source.
+ */
+int mic_next_db(struct mic_device *mdev)
+{
+ int next_db;
+
+ next_db = mdev->irq_info.next_avail_src %
+ mdev->intr_info->intr_len[MIC_INTR_DB];
+ mdev->irq_info.next_avail_src++;
+ return next_db;
+}
+
+#define COOKIE_ID_SHIFT 16
+#define GET_ENTRY(cookie) ((cookie) & 0xFFFF)
+#define GET_OFFSET(cookie) ((cookie) >> COOKIE_ID_SHIFT)
+#define MK_COOKIE(x, y) ((x) | (y) << COOKIE_ID_SHIFT)
+
+/**
+ * mic_request_irq - request an irq. mic_mutex needs
+ * to be held before calling this function.
+ *
+ * @mdev: pointer to mic_device instance
+ * @func: The callback function that handles the interrupt.
+ * The function needs to call ack_interrupts
+ * (mdev->ops->ack_interrupt(mdev)) when handling the interrupts.
+ * @name: The ASCII name of the callee requesting the irq.
+ * @data: private data that is returned back when calling the
+ * function handler.
+ * @intr_src: The source id of the requester. Its the doorbell id
+ * for Doorbell interrupts and DMA channel id for DMA interrupts.
+ * @type: The type of interrupt. Values defined in mic_intr_type
+ *
+ * returns: The cookie that is transparent to the caller. Passed
+ * back when calling mic_free_irq. An appropriate error code
+ * is returned on failure. Caller needs to use IS_ERR(return_val)
+ * to check for failure and PTR_ERR(return_val) to obtained the
+ * error code.
+ *
+ */
+struct mic_irq *mic_request_irq(struct mic_device *mdev,
+ irqreturn_t (*func)(int irq, void *dev),
+ const char *name, void *data, int intr_src,
+ enum mic_intr_type type)
+{
+ u16 offset;
+ int rc = 0;
+ struct msix_entry *msix = NULL;
+ unsigned long cookie = 0;
+ u16 entry;
+ struct mic_intr_cb *intr_cb;
+ struct pci_dev *pdev = container_of(mdev->sdev->parent,
+ struct pci_dev, dev);
+
+ offset = mic_map_src_to_offset(mdev, intr_src, type);
+ if (offset >= MIC_NUM_OFFSETS) {
+ dev_err(mdev->sdev->parent,
+ "Error mapping index %d to a valid source id.\n",
+ intr_src);
+ rc = -EINVAL;
+ goto err;
+ }
+
+ if (mdev->irq_info.num_vectors > 1) {
+ msix = mic_get_available_vector(mdev);
+ if (!msix) {
+ dev_err(mdev->sdev->parent,
+ "No MSIx vectors available for use.\n");
+ rc = -ENOSPC;
+ goto err;
+ }
+
+ rc = request_irq(msix->vector, func, 0, name, data);
+ if (rc) {
+ dev_dbg(mdev->sdev->parent,
+ "request irq failed rc = %d\n", rc);
+ goto err;
+ }
+ entry = msix->entry;
+ mdev->irq_info.mic_msi_map[entry] |= BIT(offset);
+ mdev->intr_ops->program_msi_to_src_map(mdev,
+ entry, offset, true);
+ cookie = MK_COOKIE(entry, offset);
+ dev_dbg(mdev->sdev->parent, "irq: %d assigned for src: %d\n",
+ msix->vector, intr_src);
+ } else {
+ intr_cb = mic_register_intr_callback(mdev,
+ offset, func, data);
+ if (IS_ERR(intr_cb)) {
+ dev_err(mdev->sdev->parent,
+ "No available callback entries for use\n");
+ rc = PTR_ERR(intr_cb);
+ goto err;
+ }
+
+ entry = 0;
+ if (pci_dev_msi_enabled(pdev)) {
+ mdev->irq_info.mic_msi_map[entry] |= (1 << offset);
+ mdev->intr_ops->program_msi_to_src_map(mdev,
+ entry, offset, true);
+ }
+ cookie = MK_COOKIE(entry, intr_cb->cb_id);
+ dev_dbg(mdev->sdev->parent, "callback %d registered for src: %d\n",
+ intr_cb->cb_id, intr_src);
+ }
+ return (struct mic_irq *)cookie;
+err:
+ return ERR_PTR(rc);
+}
+
+/**
+ * mic_free_irq - free irq. mic_mutex
+ * needs to be held before calling this function.
+ *
+ * @mdev: pointer to mic_device instance
+ * @cookie: cookie obtained during a successful call to mic_request_irq
+ * @data: private data specified by the calling function during the
+ * mic_request_irq
+ *
+ * returns: none.
+ */
+void mic_free_irq(struct mic_device *mdev,
+ struct mic_irq *cookie, void *data)
+{
+ u32 offset;
+ u32 entry;
+ u8 src_id;
+ unsigned int irq;
+ struct pci_dev *pdev = container_of(mdev->sdev->parent,
+ struct pci_dev, dev);
+
+ entry = GET_ENTRY((unsigned long)cookie);
+ offset = GET_OFFSET((unsigned long)cookie);
+ if (mdev->irq_info.num_vectors > 1) {
+ if (entry >= mdev->irq_info.num_vectors) {
+ dev_warn(mdev->sdev->parent,
+ "entry %d should be < num_irq %d\n",
+ entry, mdev->irq_info.num_vectors);
+ return;
+ }
+ irq = mdev->irq_info.msix_entries[entry].vector;
+ free_irq(irq, data);
+ mdev->irq_info.mic_msi_map[entry] &= ~(BIT(offset));
+ mdev->intr_ops->program_msi_to_src_map(mdev,
+ entry, offset, false);
+
+ dev_dbg(mdev->sdev->parent, "irq: %d freed\n", irq);
+ } else {
+ irq = pdev->irq;
+ src_id = mic_unregister_intr_callback(mdev, offset);
+ if (src_id >= MIC_NUM_OFFSETS) {
+ dev_warn(mdev->sdev->parent, "Error unregistering callback\n");
+ return;
+ }
+ if (pci_dev_msi_enabled(pdev)) {
+ mdev->irq_info.mic_msi_map[entry] &= ~(BIT(src_id));
+ mdev->intr_ops->program_msi_to_src_map(mdev,
+ entry, src_id, false);
+ }
+ dev_dbg(mdev->sdev->parent, "callback %d unregistered for src: %d\n",
+ offset, src_id);
+ }
+}
+
+/**
+ * mic_setup_interrupts - Initializes interrupts.
+ *
+ * @mdev: pointer to mic_device instance
+ * @pdev: PCI device structure
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
+{
+ int rc;
+
+ rc = mic_setup_msix(mdev, pdev);
+ if (!rc)
+ goto done;
+
+ rc = mic_setup_msi(mdev, pdev);
+ if (!rc)
+ goto done;
+
+ rc = mic_setup_intx(mdev, pdev);
+ if (rc) {
+ dev_err(mdev->sdev->parent, "no usable interrupts\n");
+ return rc;
+ }
+done:
+ mdev->intr_ops->enable_interrupts(mdev);
+ return 0;
+}
+
+/**
+ * mic_free_interrupts - Frees interrupts setup by mic_setup_interrupts
+ *
+ * @mdev: pointer to mic_device instance
+ * @pdev: PCI device structure
+ *
+ * returns none.
+ */
+void mic_free_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
+{
+ int i;
+
+ mdev->intr_ops->disable_interrupts(mdev);
+ if (mdev->irq_info.num_vectors > 1) {
+ for (i = 0; i < mdev->irq_info.num_vectors; i++) {
+ if (mdev->irq_info.mic_msi_map[i])
+ dev_warn(&pdev->dev, "irq %d may still be in use.\n",
+ mdev->irq_info.msix_entries[i].vector);
+ }
+ kfree(mdev->irq_info.mic_msi_map);
+ kfree(mdev->irq_info.msix_entries);
+ pci_disable_msix(pdev);
+ } else {
+ if (pci_dev_msi_enabled(pdev)) {
+ free_irq(pdev->irq, mdev);
+ kfree(mdev->irq_info.mic_msi_map);
+ pci_disable_msi(pdev);
+ } else {
+ free_irq(pdev->irq, mdev);
+ }
+ mic_release_callbacks(mdev);
+ }
+}
+
+/**
+ * mic_intr_restore - Restore MIC interrupt registers.
+ *
+ * @mdev: pointer to mic_device instance.
+ *
+ * Restore the interrupt registers to values previously
+ * stored in the SW data structures. mic_mutex needs to
+ * be held before calling this function.
+ *
+ * returns None.
+ */
+void mic_intr_restore(struct mic_device *mdev)
+{
+ int entry, offset;
+ struct pci_dev *pdev = container_of(mdev->sdev->parent,
+ struct pci_dev, dev);
+
+ if (!pci_dev_msi_enabled(pdev))
+ return;
+
+ for (entry = 0; entry < mdev->irq_info.num_vectors; entry++) {
+ for (offset = 0; offset < MIC_NUM_OFFSETS; offset++) {
+ if (mdev->irq_info.mic_msi_map[entry] & BIT(offset))
+ mdev->intr_ops->program_msi_to_src_map(mdev,
+ entry, offset, true);
+ }
+ }
+}
diff --git a/drivers/misc/mic/host/mic_intr.h b/drivers/misc/mic/host/mic_intr.h
new file mode 100644
index 000000000000..6091aa97e116
--- /dev/null
+++ b/drivers/misc/mic/host/mic_intr.h
@@ -0,0 +1,137 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#ifndef _MIC_INTR_H_
+#define _MIC_INTR_H_
+
+/*
+ * The minimum number of msix vectors required for normal operation.
+ * 3 for virtio network, console and block devices.
+ * 1 for card shutdown notifications.
+ */
+#define MIC_MIN_MSIX 4
+#define MIC_NUM_OFFSETS 32
+
+/**
+ * mic_intr_source - The type of source that will generate
+ * the interrupt.The number of types needs to be in sync with
+ * MIC_NUM_INTR_TYPES
+ *
+ * MIC_INTR_DB: The source is a doorbell
+ * MIC_INTR_DMA: The source is a DMA channel
+ * MIC_INTR_ERR: The source is an error interrupt e.g. SBOX ERR
+ * MIC_NUM_INTR_TYPES: Total number of interrupt sources.
+ */
+enum mic_intr_type {
+ MIC_INTR_DB = 0,
+ MIC_INTR_DMA,
+ MIC_INTR_ERR,
+ MIC_NUM_INTR_TYPES
+};
+
+/**
+ * struct mic_intr_info - Contains h/w specific interrupt sources
+ * information.
+ *
+ * @intr_start_idx: Contains the starting indexes of the
+ * interrupt types.
+ * @intr_len: Contains the length of the interrupt types.
+ */
+struct mic_intr_info {
+ u16 intr_start_idx[MIC_NUM_INTR_TYPES];
+ u16 intr_len[MIC_NUM_INTR_TYPES];
+};
+
+/**
+ * struct mic_irq_info - OS specific irq information
+ *
+ * @next_avail_src: next available doorbell that can be assigned.
+ * @msix_entries: msix entries allocated while setting up MSI-x
+ * @mic_msi_map: The MSI/MSI-x mapping information.
+ * @num_vectors: The number of MSI/MSI-x vectors that have been allocated.
+ * @cb_ida: callback ID allocator to track the callbacks registered.
+ * @mic_intr_lock: spinlock to protect the interrupt callback list.
+ * @cb_list: Array of callback lists one for each source.
+ */
+struct mic_irq_info {
+ int next_avail_src;
+ struct msix_entry *msix_entries;
+ u32 *mic_msi_map;
+ u16 num_vectors;
+ struct ida cb_ida;
+ spinlock_t mic_intr_lock;
+ struct list_head *cb_list;
+};
+
+/**
+ * struct mic_intr_cb - Interrupt callback structure.
+ *
+ * @func: The callback function
+ * @data: Private data of the requester.
+ * @cb_id: The callback id. Identifies this callback.
+ * @list: list head pointing to the next callback structure.
+ */
+struct mic_intr_cb {
+ irqreturn_t (*func) (int irq, void *data);
+ void *data;
+ int cb_id;
+ struct list_head list;
+};
+
+/**
+ * struct mic_irq - opaque pointer used as cookie
+ */
+struct mic_irq;
+
+/* Forward declaration */
+struct mic_device;
+
+/**
+ * struct mic_hw_intr_ops: MIC HW specific interrupt operations
+ * @intr_init: Initialize H/W specific interrupt information.
+ * @enable_interrupts: Enable interrupts from the hardware.
+ * @disable_interrupts: Disable interrupts from the hardware.
+ * @program_msi_to_src_map: Update MSI mapping registers with
+ * irq information.
+ * @read_msi_to_src_map: Read MSI mapping registers containing
+ * irq information.
+ */
+struct mic_hw_intr_ops {
+ void (*intr_init)(struct mic_device *mdev);
+ void (*enable_interrupts)(struct mic_device *mdev);
+ void (*disable_interrupts)(struct mic_device *mdev);
+ void (*program_msi_to_src_map) (struct mic_device *mdev,
+ int idx, int intr_src, bool set);
+ u32 (*read_msi_to_src_map) (struct mic_device *mdev,
+ int idx);
+};
+
+int mic_next_db(struct mic_device *mdev);
+struct mic_irq *mic_request_irq(struct mic_device *mdev,
+ irqreturn_t (*func)(int irq, void *data),
+ const char *name, void *data, int intr_src,
+ enum mic_intr_type type);
+
+void mic_free_irq(struct mic_device *mdev,
+ struct mic_irq *cookie, void *data);
+int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev);
+void mic_free_interrupts(struct mic_device *mdev, struct pci_dev *pdev);
+void mic_intr_restore(struct mic_device *mdev);
+#endif
diff --git a/drivers/misc/mic/host/mic_main.c b/drivers/misc/mic/host/mic_main.c
new file mode 100644
index 000000000000..28c8490a10af
--- /dev/null
+++ b/drivers/misc/mic/host/mic_main.c
@@ -0,0 +1,477 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ * Global TODO's across the driver to be added after initial base
+ * patches are accepted upstream:
+ * 1) Enable DMA support.
+ * 2) Enable per vring interrupt support.
+ */
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/poll.h>
+
+#include <linux/mic_common.h>
+#include "../common/mic_device.h"
+#include "mic_device.h"
+#include "mic_x100.h"
+#include "mic_smpt.h"
+#include "mic_fops.h"
+#include "mic_virtio.h"
+
+static const char mic_driver_name[] = "mic";
+
+static DEFINE_PCI_DEVICE_TABLE(mic_pci_tbl) = {
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2250)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2251)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2252)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2253)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2254)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2255)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2256)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2257)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2258)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2259)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225a)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225b)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225c)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225d)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225e)},
+
+ /* required last entry */
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, mic_pci_tbl);
+
+/* ID allocator for MIC devices */
+static struct ida g_mic_ida;
+/* Class of MIC devices for sysfs accessibility. */
+static struct class *g_mic_class;
+/* Base device node number for MIC devices */
+static dev_t g_mic_devno;
+
+static const struct file_operations mic_fops = {
+ .open = mic_open,
+ .release = mic_release,
+ .unlocked_ioctl = mic_ioctl,
+ .poll = mic_poll,
+ .mmap = mic_mmap,
+ .owner = THIS_MODULE,
+};
+
+/* Initialize the device page */
+static int mic_dp_init(struct mic_device *mdev)
+{
+ mdev->dp = kzalloc(MIC_DP_SIZE, GFP_KERNEL);
+ if (!mdev->dp) {
+ dev_err(mdev->sdev->parent, "%s %d err %d\n",
+ __func__, __LINE__, -ENOMEM);
+ return -ENOMEM;
+ }
+
+ mdev->dp_dma_addr = mic_map_single(mdev,
+ mdev->dp, MIC_DP_SIZE);
+ if (mic_map_error(mdev->dp_dma_addr)) {
+ kfree(mdev->dp);
+ dev_err(mdev->sdev->parent, "%s %d err %d\n",
+ __func__, __LINE__, -ENOMEM);
+ return -ENOMEM;
+ }
+ mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr);
+ mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
+ return 0;
+}
+
+/* Uninitialize the device page */
+static void mic_dp_uninit(struct mic_device *mdev)
+{
+ mic_unmap_single(mdev, mdev->dp_dma_addr, MIC_DP_SIZE);
+ kfree(mdev->dp);
+}
+
+/**
+ * mic_shutdown_db - Shutdown doorbell interrupt handler.
+ */
+static irqreturn_t mic_shutdown_db(int irq, void *data)
+{
+ struct mic_device *mdev = data;
+ struct mic_bootparam *bootparam = mdev->dp;
+
+ mdev->ops->ack_interrupt(mdev);
+
+ switch (bootparam->shutdown_status) {
+ case MIC_HALTED:
+ case MIC_POWER_OFF:
+ case MIC_RESTART:
+ /* Fall through */
+ case MIC_CRASHED:
+ schedule_work(&mdev->shutdown_work);
+ break;
+ default:
+ break;
+ };
+ return IRQ_HANDLED;
+}
+
+/**
+ * mic_ops_init: Initialize HW specific operation tables.
+ *
+ * @mdev: pointer to mic_device instance
+ *
+ * returns none.
+ */
+static void mic_ops_init(struct mic_device *mdev)
+{
+ switch (mdev->family) {
+ case MIC_FAMILY_X100:
+ mdev->ops = &mic_x100_ops;
+ mdev->intr_ops = &mic_x100_intr_ops;
+ mdev->smpt_ops = &mic_x100_smpt_ops;
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * mic_get_family - Determine hardware family to which this MIC belongs.
+ *
+ * @pdev: The pci device structure
+ *
+ * returns family.
+ */
+static enum mic_hw_family mic_get_family(struct pci_dev *pdev)
+{
+ enum mic_hw_family family;
+
+ switch (pdev->device) {
+ case MIC_X100_PCI_DEVICE_2250:
+ case MIC_X100_PCI_DEVICE_2251:
+ case MIC_X100_PCI_DEVICE_2252:
+ case MIC_X100_PCI_DEVICE_2253:
+ case MIC_X100_PCI_DEVICE_2254:
+ case MIC_X100_PCI_DEVICE_2255:
+ case MIC_X100_PCI_DEVICE_2256:
+ case MIC_X100_PCI_DEVICE_2257:
+ case MIC_X100_PCI_DEVICE_2258:
+ case MIC_X100_PCI_DEVICE_2259:
+ case MIC_X100_PCI_DEVICE_225a:
+ case MIC_X100_PCI_DEVICE_225b:
+ case MIC_X100_PCI_DEVICE_225c:
+ case MIC_X100_PCI_DEVICE_225d:
+ case MIC_X100_PCI_DEVICE_225e:
+ family = MIC_FAMILY_X100;
+ break;
+ default:
+ family = MIC_FAMILY_UNKNOWN;
+ break;
+ }
+ return family;
+}
+
+/**
+ * mic_device_init - Allocates and initializes the MIC device structure
+ *
+ * @mdev: pointer to mic_device instance
+ * @pdev: The pci device structure
+ *
+ * returns none.
+ */
+static void
+mic_device_init(struct mic_device *mdev, struct pci_dev *pdev)
+{
+ mdev->family = mic_get_family(pdev);
+ mdev->stepping = pdev->revision;
+ mic_ops_init(mdev);
+ mic_sysfs_init(mdev);
+ mutex_init(&mdev->mic_mutex);
+ mdev->irq_info.next_avail_src = 0;
+ INIT_WORK(&mdev->reset_trigger_work, mic_reset_trigger_work);
+ INIT_WORK(&mdev->shutdown_work, mic_shutdown_work);
+ INIT_LIST_HEAD(&mdev->vdev_list);
+}
+
+/**
+ * mic_device_uninit - Frees resources allocated during mic_device_init(..)
+ *
+ * @mdev: pointer to mic_device instance
+ *
+ * returns none
+ */
+static void mic_device_uninit(struct mic_device *mdev)
+{
+ /* The cmdline sysfs entry might have allocated cmdline */
+ kfree(mdev->cmdline);
+ kfree(mdev->firmware);
+ kfree(mdev->ramdisk);
+ kfree(mdev->bootmode);
+ flush_work(&mdev->reset_trigger_work);
+ flush_work(&mdev->shutdown_work);
+}
+
+/**
+ * mic_probe - Device Initialization Routine
+ *
+ * @pdev: PCI device structure
+ * @ent: entry in mic_pci_tbl
+ *
+ * returns 0 on success, < 0 on failure.
+ */
+static int mic_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int rc;
+ struct mic_device *mdev;
+
+ mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+ if (!mdev) {
+ rc = -ENOMEM;
+ dev_err(&pdev->dev, "mdev kmalloc failed rc %d\n", rc);
+ goto mdev_alloc_fail;
+ }
+ mdev->id = ida_simple_get(&g_mic_ida, 0, MIC_MAX_NUM_DEVS, GFP_KERNEL);
+ if (mdev->id < 0) {
+ rc = mdev->id;
+ dev_err(&pdev->dev, "ida_simple_get failed rc %d\n", rc);
+ goto ida_fail;
+ }
+
+ mic_device_init(mdev, pdev);
+
+ rc = pci_enable_device(pdev);
+ if (rc) {
+ dev_err(&pdev->dev, "failed to enable pci device.\n");
+ goto uninit_device;
+ }
+
+ pci_set_master(pdev);
+
+ rc = pci_request_regions(pdev, mic_driver_name);
+ if (rc) {
+ dev_err(&pdev->dev, "failed to get pci regions.\n");
+ goto disable_device;
+ }
+
+ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+ if (rc) {
+ dev_err(&pdev->dev, "Cannot set DMA mask\n");
+ goto release_regions;
+ }
+
+ mdev->mmio.pa = pci_resource_start(pdev, mdev->ops->mmio_bar);
+ mdev->mmio.len = pci_resource_len(pdev, mdev->ops->mmio_bar);
+ mdev->mmio.va = pci_ioremap_bar(pdev, mdev->ops->mmio_bar);
+ if (!mdev->mmio.va) {
+ dev_err(&pdev->dev, "Cannot remap MMIO BAR\n");
+ rc = -EIO;
+ goto release_regions;
+ }
+
+ mdev->aper.pa = pci_resource_start(pdev, mdev->ops->aper_bar);
+ mdev->aper.len = pci_resource_len(pdev, mdev->ops->aper_bar);
+ mdev->aper.va = ioremap_wc(mdev->aper.pa, mdev->aper.len);
+ if (!mdev->aper.va) {
+ dev_err(&pdev->dev, "Cannot remap Aperture BAR\n");
+ rc = -EIO;
+ goto unmap_mmio;
+ }
+
+ mdev->intr_ops->intr_init(mdev);
+ rc = mic_setup_interrupts(mdev, pdev);
+ if (rc) {
+ dev_err(&pdev->dev, "mic_setup_interrupts failed %d\n", rc);
+ goto unmap_aper;
+ }
+ rc = mic_smpt_init(mdev);
+ if (rc) {
+ dev_err(&pdev->dev, "smpt_init failed %d\n", rc);
+ goto free_interrupts;
+ }
+
+ pci_set_drvdata(pdev, mdev);
+
+ mdev->sdev = device_create_with_groups(g_mic_class, &pdev->dev,
+ MKDEV(MAJOR(g_mic_devno), mdev->id), NULL,
+ mdev->attr_group, "mic%d", mdev->id);
+ if (IS_ERR(mdev->sdev)) {
+ rc = PTR_ERR(mdev->sdev);
+ dev_err(&pdev->dev,
+ "device_create_with_groups failed rc %d\n", rc);
+ goto smpt_uninit;
+ }
+ mdev->state_sysfs = sysfs_get_dirent(mdev->sdev->kobj.sd, "state");
+ if (!mdev->state_sysfs) {
+ rc = -ENODEV;
+ dev_err(&pdev->dev, "sysfs_get_dirent failed rc %d\n", rc);
+ goto destroy_device;
+ }
+
+ rc = mic_dp_init(mdev);
+ if (rc) {
+ dev_err(&pdev->dev, "mic_dp_init failed rc %d\n", rc);
+ goto sysfs_put;
+ }
+ mutex_lock(&mdev->mic_mutex);
+
+ mdev->shutdown_db = mic_next_db(mdev);
+ mdev->shutdown_cookie = mic_request_irq(mdev, mic_shutdown_db,
+ "shutdown-interrupt", mdev, mdev->shutdown_db, MIC_INTR_DB);
+ if (IS_ERR(mdev->shutdown_cookie)) {
+ rc = PTR_ERR(mdev->shutdown_cookie);
+ mutex_unlock(&mdev->mic_mutex);
+ goto dp_uninit;
+ }
+ mutex_unlock(&mdev->mic_mutex);
+ mic_bootparam_init(mdev);
+
+ mic_create_debug_dir(mdev);
+ cdev_init(&mdev->cdev, &mic_fops);
+ mdev->cdev.owner = THIS_MODULE;
+ rc = cdev_add(&mdev->cdev, MKDEV(MAJOR(g_mic_devno), mdev->id), 1);
+ if (rc) {
+ dev_err(&pdev->dev, "cdev_add err id %d rc %d\n", mdev->id, rc);
+ goto cleanup_debug_dir;
+ }
+ return 0;
+cleanup_debug_dir:
+ mic_delete_debug_dir(mdev);
+ mutex_lock(&mdev->mic_mutex);
+ mic_free_irq(mdev, mdev->shutdown_cookie, mdev);
+ mutex_unlock(&mdev->mic_mutex);
+dp_uninit:
+ mic_dp_uninit(mdev);
+sysfs_put:
+ sysfs_put(mdev->state_sysfs);
+destroy_device:
+ device_destroy(g_mic_class, MKDEV(MAJOR(g_mic_devno), mdev->id));
+smpt_uninit:
+ mic_smpt_uninit(mdev);
+free_interrupts:
+ mic_free_interrupts(mdev, pdev);
+unmap_aper:
+ iounmap(mdev->aper.va);
+unmap_mmio:
+ iounmap(mdev->mmio.va);
+release_regions:
+ pci_release_regions(pdev);
+disable_device:
+ pci_disable_device(pdev);
+uninit_device:
+ mic_device_uninit(mdev);
+ ida_simple_remove(&g_mic_ida, mdev->id);
+ida_fail:
+ kfree(mdev);
+mdev_alloc_fail:
+ dev_err(&pdev->dev, "Probe failed rc %d\n", rc);
+ return rc;
+}
+
+/**
+ * mic_remove - Device Removal Routine
+ * mic_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device.
+ *
+ * @pdev: PCI device structure
+ */
+static void mic_remove(struct pci_dev *pdev)
+{
+ struct mic_device *mdev;
+
+ mdev = pci_get_drvdata(pdev);
+ if (!mdev)
+ return;
+
+ mic_stop(mdev, false);
+ cdev_del(&mdev->cdev);
+ mic_delete_debug_dir(mdev);
+ mutex_lock(&mdev->mic_mutex);
+ mic_free_irq(mdev, mdev->shutdown_cookie, mdev);
+ mutex_unlock(&mdev->mic_mutex);
+ flush_work(&mdev->shutdown_work);
+ mic_dp_uninit(mdev);
+ sysfs_put(mdev->state_sysfs);
+ device_destroy(g_mic_class, MKDEV(MAJOR(g_mic_devno), mdev->id));
+ mic_smpt_uninit(mdev);
+ mic_free_interrupts(mdev, pdev);
+ iounmap(mdev->mmio.va);
+ iounmap(mdev->aper.va);
+ mic_device_uninit(mdev);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ ida_simple_remove(&g_mic_ida, mdev->id);
+ kfree(mdev);
+}
+static struct pci_driver mic_driver = {
+ .name = mic_driver_name,
+ .id_table = mic_pci_tbl,
+ .probe = mic_probe,
+ .remove = mic_remove
+};
+
+static int __init mic_init(void)
+{
+ int ret;
+
+ ret = alloc_chrdev_region(&g_mic_devno, 0,
+ MIC_MAX_NUM_DEVS, mic_driver_name);
+ if (ret) {
+ pr_err("alloc_chrdev_region failed ret %d\n", ret);
+ goto error;
+ }
+
+ g_mic_class = class_create(THIS_MODULE, mic_driver_name);
+ if (IS_ERR(g_mic_class)) {
+ ret = PTR_ERR(g_mic_class);
+ pr_err("class_create failed ret %d\n", ret);
+ goto cleanup_chrdev;
+ }
+
+ mic_init_debugfs();
+ ida_init(&g_mic_ida);
+ ret = pci_register_driver(&mic_driver);
+ if (ret) {
+ pr_err("pci_register_driver failed ret %d\n", ret);
+ goto cleanup_debugfs;
+ }
+ return ret;
+cleanup_debugfs:
+ mic_exit_debugfs();
+ class_destroy(g_mic_class);
+cleanup_chrdev:
+ unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS);
+error:
+ return ret;
+}
+
+static void __exit mic_exit(void)
+{
+ pci_unregister_driver(&mic_driver);
+ ida_destroy(&g_mic_ida);
+ mic_exit_debugfs();
+ class_destroy(g_mic_class);
+ unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS);
+}
+
+module_init(mic_init);
+module_exit(mic_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Intel(R) MIC X100 Host driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/host/mic_smpt.c b/drivers/misc/mic/host/mic_smpt.c
new file mode 100644
index 000000000000..a3462076bc57
--- /dev/null
+++ b/drivers/misc/mic/host/mic_smpt.c
@@ -0,0 +1,442 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#include <linux/pci.h>
+
+#include "../common/mic_device.h"
+#include "mic_device.h"
+#include "mic_smpt.h"
+
+static inline u64 mic_system_page_mask(struct mic_device *mdev)
+{
+ return (1ULL << mdev->smpt->info.page_shift) - 1ULL;
+}
+
+static inline u8 mic_sys_addr_to_smpt(struct mic_device *mdev, dma_addr_t pa)
+{
+ return (pa - mdev->smpt->info.base) >> mdev->smpt->info.page_shift;
+}
+
+static inline u64 mic_smpt_to_pa(struct mic_device *mdev, u8 index)
+{
+ return mdev->smpt->info.base + (index * mdev->smpt->info.page_size);
+}
+
+static inline u64 mic_smpt_offset(struct mic_device *mdev, dma_addr_t pa)
+{
+ return pa & mic_system_page_mask(mdev);
+}
+
+static inline u64 mic_smpt_align_low(struct mic_device *mdev, dma_addr_t pa)
+{
+ return ALIGN(pa - mic_system_page_mask(mdev),
+ mdev->smpt->info.page_size);
+}
+
+static inline u64 mic_smpt_align_high(struct mic_device *mdev, dma_addr_t pa)
+{
+ return ALIGN(pa, mdev->smpt->info.page_size);
+}
+
+/* Total Cumulative system memory accessible by MIC across all SMPT entries */
+static inline u64 mic_max_system_memory(struct mic_device *mdev)
+{
+ return mdev->smpt->info.num_reg * mdev->smpt->info.page_size;
+}
+
+/* Maximum system memory address accessible by MIC */
+static inline u64 mic_max_system_addr(struct mic_device *mdev)
+{
+ return mdev->smpt->info.base + mic_max_system_memory(mdev) - 1ULL;
+}
+
+/* Check if the DMA address is a MIC system memory address */
+static inline bool
+mic_is_system_addr(struct mic_device *mdev, dma_addr_t pa)
+{
+ return pa >= mdev->smpt->info.base && pa <= mic_max_system_addr(mdev);
+}
+
+/* Populate an SMPT entry and update the reference counts. */
+static void mic_add_smpt_entry(int spt, s64 *ref, u64 addr,
+ int entries, struct mic_device *mdev)
+{
+ struct mic_smpt_info *smpt_info = mdev->smpt;
+ int i;
+
+ for (i = spt; i < spt + entries; i++,
+ addr += smpt_info->info.page_size) {
+ if (!smpt_info->entry[i].ref_count &&
+ (smpt_info->entry[i].dma_addr != addr)) {
+ mdev->smpt_ops->set(mdev, addr, i);
+ smpt_info->entry[i].dma_addr = addr;
+ }
+ smpt_info->entry[i].ref_count += ref[i - spt];
+ }
+}
+
+/*
+ * Find an available MIC address in MIC SMPT address space
+ * for a given DMA address and size.
+ */
+static dma_addr_t mic_smpt_op(struct mic_device *mdev, u64 dma_addr,
+ int entries, s64 *ref, size_t size)
+{
+ int spt;
+ int ae = 0;
+ int i;
+ unsigned long flags;
+ dma_addr_t mic_addr = 0;
+ dma_addr_t addr = dma_addr;
+ struct mic_smpt_info *smpt_info = mdev->smpt;
+
+ spin_lock_irqsave(&smpt_info->smpt_lock, flags);
+
+ /* find existing entries */
+ for (i = 0; i < smpt_info->info.num_reg; i++) {
+ if (smpt_info->entry[i].dma_addr == addr) {
+ ae++;
+ addr += smpt_info->info.page_size;
+ } else if (ae) /* cannot find contiguous entries */
+ goto not_found;
+
+ if (ae == entries)
+ goto found;
+ }
+
+ /* find free entry */
+ for (ae = 0, i = 0; i < smpt_info->info.num_reg; i++) {
+ ae = (smpt_info->entry[i].ref_count == 0) ? ae + 1 : 0;
+ if (ae == entries)
+ goto found;
+ }
+
+not_found:
+ spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
+ return mic_addr;
+
+found:
+ spt = i - entries + 1;
+ mic_addr = mic_smpt_to_pa(mdev, spt);
+ mic_add_smpt_entry(spt, ref, dma_addr, entries, mdev);
+ smpt_info->map_count++;
+ smpt_info->ref_count += (s64)size;
+ spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
+ return mic_addr;
+}
+
+/*
+ * Returns number of smpt entries needed for dma_addr to dma_addr + size
+ * also returns the reference count array for each of those entries
+ * and the starting smpt address
+ */
+static int mic_get_smpt_ref_count(struct mic_device *mdev, dma_addr_t dma_addr,
+ size_t size, s64 *ref, u64 *smpt_start)
+{
+ u64 start = dma_addr;
+ u64 end = dma_addr + size;
+ int i = 0;
+
+ while (start < end) {
+ ref[i++] = min(mic_smpt_align_high(mdev, start + 1),
+ end) - start;
+ start = mic_smpt_align_high(mdev, start + 1);
+ }
+
+ if (smpt_start)
+ *smpt_start = mic_smpt_align_low(mdev, dma_addr);
+
+ return i;
+}
+
+/*
+ * mic_to_dma_addr - Converts a MIC address to a DMA address.
+ *
+ * @mdev: pointer to mic_device instance.
+ * @mic_addr: MIC address.
+ *
+ * returns a DMA address.
+ */
+static dma_addr_t
+mic_to_dma_addr(struct mic_device *mdev, dma_addr_t mic_addr)
+{
+ struct mic_smpt_info *smpt_info = mdev->smpt;
+ int spt;
+ dma_addr_t dma_addr;
+
+ if (!mic_is_system_addr(mdev, mic_addr)) {
+ dev_err(mdev->sdev->parent,
+ "mic_addr is invalid. mic_addr = 0x%llx\n", mic_addr);
+ return -EINVAL;
+ }
+ spt = mic_sys_addr_to_smpt(mdev, mic_addr);
+ dma_addr = smpt_info->entry[spt].dma_addr +
+ mic_smpt_offset(mdev, mic_addr);
+ return dma_addr;
+}
+
+/**
+ * mic_map - Maps a DMA address to a MIC physical address.
+ *
+ * @mdev: pointer to mic_device instance.
+ * @dma_addr: DMA address.
+ * @size: Size of the region to be mapped.
+ *
+ * This API converts the DMA address provided to a DMA address understood
+ * by MIC. Caller should check for errors by calling mic_map_error(..).
+ *
+ * returns DMA address as required by MIC.
+ */
+dma_addr_t mic_map(struct mic_device *mdev, dma_addr_t dma_addr, size_t size)
+{
+ dma_addr_t mic_addr = 0;
+ int num_entries;
+ s64 *ref;
+ u64 smpt_start;
+
+ if (!size || size > mic_max_system_memory(mdev))
+ return mic_addr;
+
+ ref = kmalloc(mdev->smpt->info.num_reg * sizeof(s64), GFP_KERNEL);
+ if (!ref)
+ return mic_addr;
+
+ num_entries = mic_get_smpt_ref_count(mdev, dma_addr, size,
+ ref, &smpt_start);
+
+ /* Set the smpt table appropriately and get 16G aligned mic address */
+ mic_addr = mic_smpt_op(mdev, smpt_start, num_entries, ref, size);
+
+ kfree(ref);
+
+ /*
+ * If mic_addr is zero then its an error case
+ * since mic_addr can never be zero.
+ * else generate mic_addr by adding the 16G offset in dma_addr
+ */
+ if (!mic_addr && MIC_FAMILY_X100 == mdev->family) {
+ dev_err(mdev->sdev->parent,
+ "mic_map failed dma_addr 0x%llx size 0x%lx\n",
+ dma_addr, size);
+ return mic_addr;
+ } else {
+ return mic_addr + mic_smpt_offset(mdev, dma_addr);
+ }
+}
+
+/**
+ * mic_unmap - Unmaps a MIC physical address.
+ *
+ * @mdev: pointer to mic_device instance.
+ * @mic_addr: MIC physical address.
+ * @size: Size of the region to be unmapped.
+ *
+ * This API unmaps the mappings created by mic_map(..).
+ *
+ * returns None.
+ */
+void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
+{
+ struct mic_smpt_info *smpt_info = mdev->smpt;
+ s64 *ref;
+ int num_smpt;
+ int spt;
+ int i;
+ unsigned long flags;
+
+ if (!size)
+ return;
+
+ if (!mic_is_system_addr(mdev, mic_addr)) {
+ dev_err(mdev->sdev->parent,
+ "invalid address: 0x%llx\n", mic_addr);
+ return;
+ }
+
+ spt = mic_sys_addr_to_smpt(mdev, mic_addr);
+ ref = kmalloc(mdev->smpt->info.num_reg * sizeof(s64), GFP_KERNEL);
+ if (!ref)
+ return;
+
+ /* Get number of smpt entries to be mapped, ref count array */
+ num_smpt = mic_get_smpt_ref_count(mdev, mic_addr, size, ref, NULL);
+
+ spin_lock_irqsave(&smpt_info->smpt_lock, flags);
+ smpt_info->unmap_count++;
+ smpt_info->ref_count -= (s64)size;
+
+ for (i = spt; i < spt + num_smpt; i++) {
+ smpt_info->entry[i].ref_count -= ref[i - spt];
+ if (smpt_info->entry[i].ref_count < 0)
+ dev_warn(mdev->sdev->parent,
+ "ref count for entry %d is negative\n", i);
+ }
+ spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
+ kfree(ref);
+}
+
+/**
+ * mic_map_single - Maps a virtual address to a MIC physical address.
+ *
+ * @mdev: pointer to mic_device instance.
+ * @va: Kernel direct mapped virtual address.
+ * @size: Size of the region to be mapped.
+ *
+ * This API calls pci_map_single(..) for the direct mapped virtual address
+ * and then converts the DMA address provided to a DMA address understood
+ * by MIC. Caller should check for errors by calling mic_map_error(..).
+ *
+ * returns DMA address as required by MIC.
+ */
+dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size)
+{
+ dma_addr_t mic_addr = 0;
+ struct pci_dev *pdev = container_of(mdev->sdev->parent,
+ struct pci_dev, dev);
+ dma_addr_t dma_addr =
+ pci_map_single(pdev, va, size, PCI_DMA_BIDIRECTIONAL);
+
+ if (!pci_dma_mapping_error(pdev, dma_addr)) {
+ mic_addr = mic_map(mdev, dma_addr, size);
+ if (!mic_addr) {
+ dev_err(mdev->sdev->parent,
+ "mic_map failed dma_addr 0x%llx size 0x%lx\n",
+ dma_addr, size);
+ pci_unmap_single(pdev, dma_addr,
+ size, PCI_DMA_BIDIRECTIONAL);
+ }
+ }
+ return mic_addr;
+}
+
+/**
+ * mic_unmap_single - Unmaps a MIC physical address.
+ *
+ * @mdev: pointer to mic_device instance.
+ * @mic_addr: MIC physical address.
+ * @size: Size of the region to be unmapped.
+ *
+ * This API unmaps the mappings created by mic_map_single(..).
+ *
+ * returns None.
+ */
+void
+mic_unmap_single(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
+{
+ struct pci_dev *pdev = container_of(mdev->sdev->parent,
+ struct pci_dev, dev);
+ dma_addr_t dma_addr = mic_to_dma_addr(mdev, mic_addr);
+ mic_unmap(mdev, mic_addr, size);
+ pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
+}
+
+/**
+ * mic_smpt_init - Initialize MIC System Memory Page Tables.
+ *
+ * @mdev: pointer to mic_device instance.
+ *
+ * returns 0 for success and -errno for error.
+ */
+int mic_smpt_init(struct mic_device *mdev)
+{
+ int i, err = 0;
+ dma_addr_t dma_addr;
+ struct mic_smpt_info *smpt_info;
+
+ mdev->smpt = kmalloc(sizeof(*mdev->smpt), GFP_KERNEL);
+ if (!mdev->smpt)
+ return -ENOMEM;
+
+ smpt_info = mdev->smpt;
+ mdev->smpt_ops->init(mdev);
+ smpt_info->entry = kmalloc(sizeof(struct mic_smpt)
+ * smpt_info->info.num_reg, GFP_KERNEL);
+ if (!smpt_info->entry) {
+ err = -ENOMEM;
+ goto free_smpt;
+ }
+ spin_lock_init(&smpt_info->smpt_lock);
+ for (i = 0; i < smpt_info->info.num_reg; i++) {
+ dma_addr = i * smpt_info->info.page_size;
+ smpt_info->entry[i].dma_addr = dma_addr;
+ smpt_info->entry[i].ref_count = 0;
+ mdev->smpt_ops->set(mdev, dma_addr, i);
+ }
+ smpt_info->ref_count = 0;
+ smpt_info->map_count = 0;
+ smpt_info->unmap_count = 0;
+ return 0;
+free_smpt:
+ kfree(smpt_info);
+ return err;
+}
+
+/**
+ * mic_smpt_uninit - UnInitialize MIC System Memory Page Tables.
+ *
+ * @mdev: pointer to mic_device instance.
+ *
+ * returns None.
+ */
+void mic_smpt_uninit(struct mic_device *mdev)
+{
+ struct mic_smpt_info *smpt_info = mdev->smpt;
+ int i;
+
+ dev_dbg(mdev->sdev->parent,
+ "nodeid %d SMPT ref count %lld map %lld unmap %lld\n",
+ mdev->id, smpt_info->ref_count,
+ smpt_info->map_count, smpt_info->unmap_count);
+
+ for (i = 0; i < smpt_info->info.num_reg; i++) {
+ dev_dbg(mdev->sdev->parent,
+ "SMPT entry[%d] dma_addr = 0x%llx ref_count = %lld\n",
+ i, smpt_info->entry[i].dma_addr,
+ smpt_info->entry[i].ref_count);
+ if (smpt_info->entry[i].ref_count)
+ dev_warn(mdev->sdev->parent,
+ "ref count for entry %d is not zero\n", i);
+ }
+ kfree(smpt_info->entry);
+ kfree(smpt_info);
+}
+
+/**
+ * mic_smpt_restore - Restore MIC System Memory Page Tables.
+ *
+ * @mdev: pointer to mic_device instance.
+ *
+ * Restore the SMPT registers to values previously stored in the
+ * SW data structures. Some MIC steppings lose register state
+ * across resets and this API should be called for performing
+ * a restore operation if required.
+ *
+ * returns None.
+ */
+void mic_smpt_restore(struct mic_device *mdev)
+{
+ int i;
+ dma_addr_t dma_addr;
+
+ for (i = 0; i < mdev->smpt->info.num_reg; i++) {
+ dma_addr = mdev->smpt->entry[i].dma_addr;
+ mdev->smpt_ops->set(mdev, dma_addr, i);
+ }
+}
diff --git a/drivers/misc/mic/host/mic_smpt.h b/drivers/misc/mic/host/mic_smpt.h
new file mode 100644
index 000000000000..51970abfe7df
--- /dev/null
+++ b/drivers/misc/mic/host/mic_smpt.h
@@ -0,0 +1,98 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#ifndef MIC_SMPT_H
+#define MIC_SMPT_H
+/**
+ * struct mic_smpt_ops - MIC HW specific SMPT operations.
+ * @init: Initialize hardware specific SMPT information in mic_smpt_hw_info.
+ * @set: Set the value for a particular SMPT entry.
+ */
+struct mic_smpt_ops {
+ void (*init)(struct mic_device *mdev);
+ void (*set)(struct mic_device *mdev, dma_addr_t dma_addr, u8 index);
+};
+
+/**
+ * struct mic_smpt - MIC SMPT entry information.
+ * @dma_addr: Base DMA address for this SMPT entry.
+ * @ref_count: Number of active mappings for this SMPT entry in bytes.
+ */
+struct mic_smpt {
+ dma_addr_t dma_addr;
+ s64 ref_count;
+};
+
+/**
+ * struct mic_smpt_hw_info - MIC SMPT hardware specific information.
+ * @num_reg: Number of SMPT registers.
+ * @page_shift: System memory page shift.
+ * @page_size: System memory page size.
+ * @base: System address base.
+ */
+struct mic_smpt_hw_info {
+ u8 num_reg;
+ u8 page_shift;
+ u64 page_size;
+ u64 base;
+};
+
+/**
+ * struct mic_smpt_info - MIC SMPT information.
+ * @entry: Array of SMPT entries.
+ * @smpt_lock: Spin lock protecting access to SMPT data structures.
+ * @info: Hardware specific SMPT information.
+ * @ref_count: Number of active SMPT mappings (for debug).
+ * @map_count: Number of SMPT mappings created (for debug).
+ * @unmap_count: Number of SMPT mappings destroyed (for debug).
+ */
+struct mic_smpt_info {
+ struct mic_smpt *entry;
+ spinlock_t smpt_lock;
+ struct mic_smpt_hw_info info;
+ s64 ref_count;
+ s64 map_count;
+ s64 unmap_count;
+};
+
+dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size);
+void mic_unmap_single(struct mic_device *mdev,
+ dma_addr_t mic_addr, size_t size);
+dma_addr_t mic_map(struct mic_device *mdev,
+ dma_addr_t dma_addr, size_t size);
+void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size);
+
+/**
+ * mic_map_error - Check a MIC address for errors.
+ *
+ * @mdev: pointer to mic_device instance.
+ *
+ * returns Whether there was an error during mic_map..(..) APIs.
+ */
+static inline bool mic_map_error(dma_addr_t mic_addr)
+{
+ return !mic_addr;
+}
+
+int mic_smpt_init(struct mic_device *mdev);
+void mic_smpt_uninit(struct mic_device *mdev);
+void mic_smpt_restore(struct mic_device *mdev);
+
+#endif
diff --git a/drivers/misc/mic/host/mic_sysfs.c b/drivers/misc/mic/host/mic_sysfs.c
new file mode 100644
index 000000000000..aaf849945111
--- /dev/null
+++ b/drivers/misc/mic/host/mic_sysfs.c
@@ -0,0 +1,466 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#include <linux/pci.h>
+
+#include <linux/mic_common.h>
+#include "../common/mic_device.h"
+#include "mic_device.h"
+
+/*
+ * A state-to-string lookup table, for exposing a human readable state
+ * via sysfs. Always keep in sync with enum mic_states
+ */
+static const char * const mic_state_string[] = {
+ [MIC_OFFLINE] = "offline",
+ [MIC_ONLINE] = "online",
+ [MIC_SHUTTING_DOWN] = "shutting_down",
+ [MIC_RESET_FAILED] = "reset_failed",
+};
+
+/*
+ * A shutdown-status-to-string lookup table, for exposing a human
+ * readable state via sysfs. Always keep in sync with enum mic_shutdown_status
+ */
+static const char * const mic_shutdown_status_string[] = {
+ [MIC_NOP] = "nop",
+ [MIC_CRASHED] = "crashed",
+ [MIC_HALTED] = "halted",
+ [MIC_POWER_OFF] = "poweroff",
+ [MIC_RESTART] = "restart",
+};
+
+void mic_set_shutdown_status(struct mic_device *mdev, u8 shutdown_status)
+{
+ dev_dbg(mdev->sdev->parent, "Shutdown Status %s -> %s\n",
+ mic_shutdown_status_string[mdev->shutdown_status],
+ mic_shutdown_status_string[shutdown_status]);
+ mdev->shutdown_status = shutdown_status;
+}
+
+void mic_set_state(struct mic_device *mdev, u8 state)
+{
+ dev_dbg(mdev->sdev->parent, "State %s -> %s\n",
+ mic_state_string[mdev->state],
+ mic_state_string[state]);
+ mdev->state = state;
+ sysfs_notify_dirent(mdev->state_sysfs);
+}
+
+static ssize_t
+mic_show_family(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ static const char x100[] = "x100";
+ static const char unknown[] = "Unknown";
+ const char *card = NULL;
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+ if (!mdev)
+ return -EINVAL;
+
+ switch (mdev->family) {
+ case MIC_FAMILY_X100:
+ card = x100;
+ break;
+ default:
+ card = unknown;
+ break;
+ }
+ return scnprintf(buf, PAGE_SIZE, "%s\n", card);
+}
+static DEVICE_ATTR(family, S_IRUGO, mic_show_family, NULL);
+
+static ssize_t
+mic_show_stepping(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+ char *string = "??";
+
+ if (!mdev)
+ return -EINVAL;
+
+ switch (mdev->stepping) {
+ case MIC_A0_STEP:
+ string = "A0";
+ break;
+ case MIC_B0_STEP:
+ string = "B0";
+ break;
+ case MIC_B1_STEP:
+ string = "B1";
+ break;
+ case MIC_C0_STEP:
+ string = "C0";
+ break;
+ default:
+ break;
+ }
+ return scnprintf(buf, PAGE_SIZE, "%s\n", string);
+}
+static DEVICE_ATTR(stepping, S_IRUGO, mic_show_stepping, NULL);
+
+static ssize_t
+mic_show_state(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+ if (!mdev || mdev->state >= MIC_LAST)
+ return -EINVAL;
+
+ return scnprintf(buf, PAGE_SIZE, "%s\n",
+ mic_state_string[mdev->state]);
+}
+
+static ssize_t
+mic_store_state(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int rc = 0;
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+ if (!mdev)
+ return -EINVAL;
+ if (sysfs_streq(buf, "boot")) {
+ rc = mic_start(mdev, buf);
+ if (rc) {
+ dev_err(mdev->sdev->parent,
+ "mic_boot failed rc %d\n", rc);
+ count = rc;
+ }
+ goto done;
+ }
+
+ if (sysfs_streq(buf, "reset")) {
+ schedule_work(&mdev->reset_trigger_work);
+ goto done;
+ }
+
+ if (sysfs_streq(buf, "shutdown")) {
+ mic_shutdown(mdev);
+ goto done;
+ }
+
+ count = -EINVAL;
+done:
+ return count;
+}
+static DEVICE_ATTR(state, S_IRUGO|S_IWUSR, mic_show_state, mic_store_state);
+
+static ssize_t mic_show_shutdown_status(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+ if (!mdev || mdev->shutdown_status >= MIC_STATUS_LAST)
+ return -EINVAL;
+
+ return scnprintf(buf, PAGE_SIZE, "%s\n",
+ mic_shutdown_status_string[mdev->shutdown_status]);
+}
+static DEVICE_ATTR(shutdown_status, S_IRUGO|S_IWUSR,
+ mic_show_shutdown_status, NULL);
+
+static ssize_t
+mic_show_cmdline(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+ char *cmdline;
+
+ if (!mdev)
+ return -EINVAL;
+
+ cmdline = mdev->cmdline;
+
+ if (cmdline)
+ return scnprintf(buf, PAGE_SIZE, "%s\n", cmdline);
+ return 0;
+}
+
+static ssize_t
+mic_store_cmdline(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+ if (!mdev)
+ return -EINVAL;
+
+ mutex_lock(&mdev->mic_mutex);
+ kfree(mdev->cmdline);
+
+ mdev->cmdline = kmalloc(count + 1, GFP_KERNEL);
+ if (!mdev->cmdline) {
+ count = -ENOMEM;
+ goto unlock;
+ }
+
+ strncpy(mdev->cmdline, buf, count);
+
+ if (mdev->cmdline[count - 1] == '\n')
+ mdev->cmdline[count - 1] = '\0';
+ else
+ mdev->cmdline[count] = '\0';
+unlock:
+ mutex_unlock(&mdev->mic_mutex);
+ return count;
+}
+static DEVICE_ATTR(cmdline, S_IRUGO | S_IWUSR,
+ mic_show_cmdline, mic_store_cmdline);
+
+static ssize_t
+mic_show_firmware(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+ char *firmware;
+
+ if (!mdev)
+ return -EINVAL;
+
+ firmware = mdev->firmware;
+
+ if (firmware)
+ return scnprintf(buf, PAGE_SIZE, "%s\n", firmware);
+ return 0;
+}
+
+static ssize_t
+mic_store_firmware(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+ if (!mdev)
+ return -EINVAL;
+
+ mutex_lock(&mdev->mic_mutex);
+ kfree(mdev->firmware);
+
+ mdev->firmware = kmalloc(count + 1, GFP_KERNEL);
+ if (!mdev->firmware) {
+ count = -ENOMEM;
+ goto unlock;
+ }
+ strncpy(mdev->firmware, buf, count);
+
+ if (mdev->firmware[count - 1] == '\n')
+ mdev->firmware[count - 1] = '\0';
+ else
+ mdev->firmware[count] = '\0';
+unlock:
+ mutex_unlock(&mdev->mic_mutex);
+ return count;
+}
+static DEVICE_ATTR(firmware, S_IRUGO | S_IWUSR,
+ mic_show_firmware, mic_store_firmware);
+
+static ssize_t
+mic_show_ramdisk(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+ char *ramdisk;
+
+ if (!mdev)
+ return -EINVAL;
+
+ ramdisk = mdev->ramdisk;
+
+ if (ramdisk)
+ return scnprintf(buf, PAGE_SIZE, "%s\n", ramdisk);
+ return 0;
+}
+
+static ssize_t
+mic_store_ramdisk(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+ if (!mdev)
+ return -EINVAL;
+
+ mutex_lock(&mdev->mic_mutex);
+ kfree(mdev->ramdisk);
+
+ mdev->ramdisk = kmalloc(count + 1, GFP_KERNEL);
+ if (!mdev->ramdisk) {
+ count = -ENOMEM;
+ goto unlock;
+ }
+
+ strncpy(mdev->ramdisk, buf, count);
+
+ if (mdev->ramdisk[count - 1] == '\n')
+ mdev->ramdisk[count - 1] = '\0';
+ else
+ mdev->ramdisk[count] = '\0';
+unlock:
+ mutex_unlock(&mdev->mic_mutex);
+ return count;
+}
+static DEVICE_ATTR(ramdisk, S_IRUGO | S_IWUSR,
+ mic_show_ramdisk, mic_store_ramdisk);
+
+static ssize_t
+mic_show_bootmode(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+ char *bootmode;
+
+ if (!mdev)
+ return -EINVAL;
+
+ bootmode = mdev->bootmode;
+
+ if (bootmode)
+ return scnprintf(buf, PAGE_SIZE, "%s\n", bootmode);
+ return 0;
+}
+
+static ssize_t
+mic_store_bootmode(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+ if (!mdev)
+ return -EINVAL;
+
+ if (!sysfs_streq(buf, "linux") && !sysfs_streq(buf, "elf"))
+ return -EINVAL;
+
+ mutex_lock(&mdev->mic_mutex);
+ kfree(mdev->bootmode);
+
+ mdev->bootmode = kmalloc(count + 1, GFP_KERNEL);
+ if (!mdev->bootmode) {
+ count = -ENOMEM;
+ goto unlock;
+ }
+
+ strncpy(mdev->bootmode, buf, count);
+
+ if (mdev->bootmode[count - 1] == '\n')
+ mdev->bootmode[count - 1] = '\0';
+ else
+ mdev->bootmode[count] = '\0';
+unlock:
+ mutex_unlock(&mdev->mic_mutex);
+ return count;
+}
+static DEVICE_ATTR(bootmode, S_IRUGO | S_IWUSR,
+ mic_show_bootmode, mic_store_bootmode);
+
+static ssize_t
+mic_show_log_buf_addr(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+ if (!mdev)
+ return -EINVAL;
+
+ return scnprintf(buf, PAGE_SIZE, "%p\n", mdev->log_buf_addr);
+}
+
+static ssize_t
+mic_store_log_buf_addr(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+ int ret;
+ unsigned long addr;
+
+ if (!mdev)
+ return -EINVAL;
+
+ ret = kstrtoul(buf, 16, &addr);
+ if (ret)
+ goto exit;
+
+ mdev->log_buf_addr = (void *)addr;
+ ret = count;
+exit:
+ return ret;
+}
+static DEVICE_ATTR(log_buf_addr, S_IRUGO | S_IWUSR,
+ mic_show_log_buf_addr, mic_store_log_buf_addr);
+
+static ssize_t
+mic_show_log_buf_len(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+ if (!mdev)
+ return -EINVAL;
+
+ return scnprintf(buf, PAGE_SIZE, "%p\n", mdev->log_buf_len);
+}
+
+static ssize_t
+mic_store_log_buf_len(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mic_device *mdev = dev_get_drvdata(dev->parent);
+ int ret;
+ unsigned long addr;
+
+ if (!mdev)
+ return -EINVAL;
+
+ ret = kstrtoul(buf, 16, &addr);
+ if (ret)
+ goto exit;
+
+ mdev->log_buf_len = (int *)addr;
+ ret = count;
+exit:
+ return ret;
+}
+static DEVICE_ATTR(log_buf_len, S_IRUGO | S_IWUSR,
+ mic_show_log_buf_len, mic_store_log_buf_len);
+
+static struct attribute *mic_default_attrs[] = {
+ &dev_attr_family.attr,
+ &dev_attr_stepping.attr,
+ &dev_attr_state.attr,
+ &dev_attr_shutdown_status.attr,
+ &dev_attr_cmdline.attr,
+ &dev_attr_firmware.attr,
+ &dev_attr_ramdisk.attr,
+ &dev_attr_bootmode.attr,
+ &dev_attr_log_buf_addr.attr,
+ &dev_attr_log_buf_len.attr,
+
+ NULL
+};
+
+static struct attribute_group mic_attr_group = {
+ .attrs = mic_default_attrs,
+};
+
+static const struct attribute_group *__mic_attr_group[] = {
+ &mic_attr_group,
+ NULL
+};
+
+void mic_sysfs_init(struct mic_device *mdev)
+{
+ mdev->attr_group = __mic_attr_group;
+}
diff --git a/drivers/misc/mic/host/mic_virtio.c b/drivers/misc/mic/host/mic_virtio.c
new file mode 100644
index 000000000000..be2a1f06c4ca
--- /dev/null
+++ b/drivers/misc/mic/host/mic_virtio.c
@@ -0,0 +1,703 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+
+#include <linux/mic_common.h>
+#include "../common/mic_device.h"
+#include "mic_device.h"
+#include "mic_smpt.h"
+#include "mic_virtio.h"
+
+/*
+ * Initiates the copies across the PCIe bus from card memory to
+ * a user space buffer.
+ */
+static int mic_virtio_copy_to_user(struct mic_vdev *mvdev,
+ void __user *ubuf, size_t len, u64 addr)
+{
+ int err;
+ void __iomem *dbuf = mvdev->mdev->aper.va + addr;
+ /*
+ * We are copying from IO below an should ideally use something
+ * like copy_to_user_fromio(..) if it existed.
+ */
+ if (copy_to_user(ubuf, dbuf, len)) {
+ err = -EFAULT;
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, err);
+ goto err;
+ }
+ mvdev->in_bytes += len;
+ err = 0;
+err:
+ return err;
+}
+
+/*
+ * Initiates copies across the PCIe bus from a user space
+ * buffer to card memory.
+ */
+static int mic_virtio_copy_from_user(struct mic_vdev *mvdev,
+ void __user *ubuf, size_t len, u64 addr)
+{
+ int err;
+ void __iomem *dbuf = mvdev->mdev->aper.va + addr;
+ /*
+ * We are copying to IO below and should ideally use something
+ * like copy_from_user_toio(..) if it existed.
+ */
+ if (copy_from_user(dbuf, ubuf, len)) {
+ err = -EFAULT;
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, err);
+ goto err;
+ }
+ mvdev->out_bytes += len;
+ err = 0;
+err:
+ return err;
+}
+
+#define MIC_VRINGH_READ true
+
+/* The function to call to notify the card about added buffers */
+static void mic_notify(struct vringh *vrh)
+{
+ struct mic_vringh *mvrh = container_of(vrh, struct mic_vringh, vrh);
+ struct mic_vdev *mvdev = mvrh->mvdev;
+ s8 db = mvdev->dc->h2c_vdev_db;
+
+ if (db != -1)
+ mvdev->mdev->ops->send_intr(mvdev->mdev, db);
+}
+
+/* Determine the total number of bytes consumed in a VRINGH KIOV */
+static inline u32 mic_vringh_iov_consumed(struct vringh_kiov *iov)
+{
+ int i;
+ u32 total = iov->consumed;
+
+ for (i = 0; i < iov->i; i++)
+ total += iov->iov[i].iov_len;
+ return total;
+}
+
+/*
+ * Traverse the VRINGH KIOV and issue the APIs to trigger the copies.
+ * This API is heavily based on the vringh_iov_xfer(..) implementation
+ * in vringh.c. The reason we cannot reuse vringh_iov_pull_kern(..)
+ * and vringh_iov_push_kern(..) directly is because there is no
+ * way to override the VRINGH xfer(..) routines as of v3.10.
+ */
+static int mic_vringh_copy(struct mic_vdev *mvdev, struct vringh_kiov *iov,
+ void __user *ubuf, size_t len, bool read, size_t *out_len)
+{
+ int ret = 0;
+ size_t partlen, tot_len = 0;
+
+ while (len && iov->i < iov->used) {
+ partlen = min(iov->iov[iov->i].iov_len, len);
+ if (read)
+ ret = mic_virtio_copy_to_user(mvdev,
+ ubuf, partlen,
+ (u64)iov->iov[iov->i].iov_base);
+ else
+ ret = mic_virtio_copy_from_user(mvdev,
+ ubuf, partlen,
+ (u64)iov->iov[iov->i].iov_base);
+ if (ret) {
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, ret);
+ break;
+ }
+ len -= partlen;
+ ubuf += partlen;
+ tot_len += partlen;
+ iov->consumed += partlen;
+ iov->iov[iov->i].iov_len -= partlen;
+ iov->iov[iov->i].iov_base += partlen;
+ if (!iov->iov[iov->i].iov_len) {
+ /* Fix up old iov element then increment. */
+ iov->iov[iov->i].iov_len = iov->consumed;
+ iov->iov[iov->i].iov_base -= iov->consumed;
+
+ iov->consumed = 0;
+ iov->i++;
+ }
+ }
+ *out_len = tot_len;
+ return ret;
+}
+
+/*
+ * Use the standard VRINGH infrastructure in the kernel to fetch new
+ * descriptors, initiate the copies and update the used ring.
+ */
+static int _mic_virtio_copy(struct mic_vdev *mvdev,
+ struct mic_copy_desc *copy)
+{
+ int ret = 0, iovcnt = copy->iovcnt;
+ struct iovec iov;
+ struct iovec __user *u_iov = copy->iov;
+ void __user *ubuf = NULL;
+ struct mic_vringh *mvr = &mvdev->mvr[copy->vr_idx];
+ struct vringh_kiov *riov = &mvr->riov;
+ struct vringh_kiov *wiov = &mvr->wiov;
+ struct vringh *vrh = &mvr->vrh;
+ u16 *head = &mvr->head;
+ struct mic_vring *vr = &mvr->vring;
+ size_t len = 0, out_len;
+
+ copy->out_len = 0;
+ /* Fetch a new IOVEC if all previous elements have been processed */
+ if (riov->i == riov->used && wiov->i == wiov->used) {
+ ret = vringh_getdesc_kern(vrh, riov, wiov,
+ head, GFP_KERNEL);
+ /* Check if there are available descriptors */
+ if (ret <= 0)
+ return ret;
+ }
+ while (iovcnt) {
+ if (!len) {
+ /* Copy over a new iovec from user space. */
+ ret = copy_from_user(&iov, u_iov, sizeof(*u_iov));
+ if (ret) {
+ ret = -EINVAL;
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, ret);
+ break;
+ }
+ len = iov.iov_len;
+ ubuf = iov.iov_base;
+ }
+ /* Issue all the read descriptors first */
+ ret = mic_vringh_copy(mvdev, riov, ubuf, len,
+ MIC_VRINGH_READ, &out_len);
+ if (ret) {
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, ret);
+ break;
+ }
+ len -= out_len;
+ ubuf += out_len;
+ copy->out_len += out_len;
+ /* Issue the write descriptors next */
+ ret = mic_vringh_copy(mvdev, wiov, ubuf, len,
+ !MIC_VRINGH_READ, &out_len);
+ if (ret) {
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, ret);
+ break;
+ }
+ len -= out_len;
+ ubuf += out_len;
+ copy->out_len += out_len;
+ if (!len) {
+ /* One user space iovec is now completed */
+ iovcnt--;
+ u_iov++;
+ }
+ /* Exit loop if all elements in KIOVs have been processed. */
+ if (riov->i == riov->used && wiov->i == wiov->used)
+ break;
+ }
+ /*
+ * Update the used ring if a descriptor was available and some data was
+ * copied in/out and the user asked for a used ring update.
+ */
+ if (*head != USHRT_MAX && copy->out_len &&
+ copy->update_used) {
+ u32 total = 0;
+
+ /* Determine the total data consumed */
+ total += mic_vringh_iov_consumed(riov);
+ total += mic_vringh_iov_consumed(wiov);
+ vringh_complete_kern(vrh, *head, total);
+ *head = USHRT_MAX;
+ if (vringh_need_notify_kern(vrh) > 0)
+ vringh_notify(vrh);
+ vringh_kiov_cleanup(riov);
+ vringh_kiov_cleanup(wiov);
+ /* Update avail idx for user space */
+ vr->info->avail_idx = vrh->last_avail_idx;
+ }
+ return ret;
+}
+
+static inline int mic_verify_copy_args(struct mic_vdev *mvdev,
+ struct mic_copy_desc *copy)
+{
+ if (copy->vr_idx >= mvdev->dd->num_vq) {
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, -EINVAL);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/* Copy a specified number of virtio descriptors in a chain */
+int mic_virtio_copy_desc(struct mic_vdev *mvdev,
+ struct mic_copy_desc *copy)
+{
+ int err;
+ struct mic_vringh *mvr = &mvdev->mvr[copy->vr_idx];
+
+ err = mic_verify_copy_args(mvdev, copy);
+ if (err)
+ return err;
+
+ mutex_lock(&mvr->vr_mutex);
+ if (!mic_vdevup(mvdev)) {
+ err = -ENODEV;
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, err);
+ goto err;
+ }
+ err = _mic_virtio_copy(mvdev, copy);
+ if (err) {
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, err);
+ }
+err:
+ mutex_unlock(&mvr->vr_mutex);
+ return err;
+}
+
+static void mic_virtio_init_post(struct mic_vdev *mvdev)
+{
+ struct mic_vqconfig *vqconfig = mic_vq_config(mvdev->dd);
+ int i;
+
+ for (i = 0; i < mvdev->dd->num_vq; i++) {
+ if (!le64_to_cpu(vqconfig[i].used_address)) {
+ dev_warn(mic_dev(mvdev), "used_address zero??\n");
+ continue;
+ }
+ mvdev->mvr[i].vrh.vring.used =
+ mvdev->mdev->aper.va +
+ le64_to_cpu(vqconfig[i].used_address);
+ }
+
+ mvdev->dc->used_address_updated = 0;
+
+ dev_dbg(mic_dev(mvdev), "%s: device type %d LINKUP\n",
+ __func__, mvdev->virtio_id);
+}
+
+static inline void mic_virtio_device_reset(struct mic_vdev *mvdev)
+{
+ int i;
+
+ dev_dbg(mic_dev(mvdev), "%s: status %d device type %d RESET\n",
+ __func__, mvdev->dd->status, mvdev->virtio_id);
+
+ for (i = 0; i < mvdev->dd->num_vq; i++)
+ /*
+ * Avoid lockdep false positive. The + 1 is for the mic
+ * mutex which is held in the reset devices code path.
+ */
+ mutex_lock_nested(&mvdev->mvr[i].vr_mutex, i + 1);
+
+ /* 0 status means "reset" */
+ mvdev->dd->status = 0;
+ mvdev->dc->vdev_reset = 0;
+ mvdev->dc->host_ack = 1;
+
+ for (i = 0; i < mvdev->dd->num_vq; i++) {
+ struct vringh *vrh = &mvdev->mvr[i].vrh;
+ mvdev->mvr[i].vring.info->avail_idx = 0;
+ vrh->completed = 0;
+ vrh->last_avail_idx = 0;
+ vrh->last_used_idx = 0;
+ }
+
+ for (i = 0; i < mvdev->dd->num_vq; i++)
+ mutex_unlock(&mvdev->mvr[i].vr_mutex);
+}
+
+void mic_virtio_reset_devices(struct mic_device *mdev)
+{
+ struct list_head *pos, *tmp;
+ struct mic_vdev *mvdev;
+
+ dev_dbg(mdev->sdev->parent, "%s\n", __func__);
+
+ list_for_each_safe(pos, tmp, &mdev->vdev_list) {
+ mvdev = list_entry(pos, struct mic_vdev, list);
+ mic_virtio_device_reset(mvdev);
+ mvdev->poll_wake = 1;
+ wake_up(&mvdev->waitq);
+ }
+}
+
+void mic_bh_handler(struct work_struct *work)
+{
+ struct mic_vdev *mvdev = container_of(work, struct mic_vdev,
+ virtio_bh_work);
+
+ if (mvdev->dc->used_address_updated)
+ mic_virtio_init_post(mvdev);
+
+ if (mvdev->dc->vdev_reset)
+ mic_virtio_device_reset(mvdev);
+
+ mvdev->poll_wake = 1;
+ wake_up(&mvdev->waitq);
+}
+
+static irqreturn_t mic_virtio_intr_handler(int irq, void *data)
+{
+
+ struct mic_vdev *mvdev = data;
+ struct mic_device *mdev = mvdev->mdev;
+
+ mdev->ops->ack_interrupt(mdev);
+ schedule_work(&mvdev->virtio_bh_work);
+ return IRQ_HANDLED;
+}
+
+int mic_virtio_config_change(struct mic_vdev *mvdev,
+ void __user *argp)
+{
+ DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
+ int ret = 0, retry = 100, i;
+ struct mic_bootparam *bootparam = mvdev->mdev->dp;
+ s8 db = bootparam->h2c_config_db;
+
+ mutex_lock(&mvdev->mdev->mic_mutex);
+ for (i = 0; i < mvdev->dd->num_vq; i++)
+ mutex_lock_nested(&mvdev->mvr[i].vr_mutex, i + 1);
+
+ if (db == -1 || mvdev->dd->type == -1) {
+ ret = -EIO;
+ goto exit;
+ }
+
+ if (copy_from_user(mic_vq_configspace(mvdev->dd),
+ argp, mvdev->dd->config_len)) {
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, -EFAULT);
+ ret = -EFAULT;
+ goto exit;
+ }
+ mvdev->dc->config_change = MIC_VIRTIO_PARAM_CONFIG_CHANGED;
+ mvdev->mdev->ops->send_intr(mvdev->mdev, db);
+
+ for (i = retry; i--;) {
+ ret = wait_event_timeout(wake,
+ mvdev->dc->guest_ack, msecs_to_jiffies(100));
+ if (ret)
+ break;
+ }
+
+ dev_dbg(mic_dev(mvdev),
+ "%s %d retry: %d\n", __func__, __LINE__, retry);
+ mvdev->dc->config_change = 0;
+ mvdev->dc->guest_ack = 0;
+exit:
+ for (i = 0; i < mvdev->dd->num_vq; i++)
+ mutex_unlock(&mvdev->mvr[i].vr_mutex);
+ mutex_unlock(&mvdev->mdev->mic_mutex);
+ return ret;
+}
+
+static int mic_copy_dp_entry(struct mic_vdev *mvdev,
+ void __user *argp,
+ __u8 *type,
+ struct mic_device_desc **devpage)
+{
+ struct mic_device *mdev = mvdev->mdev;
+ struct mic_device_desc dd, *dd_config, *devp;
+ struct mic_vqconfig *vqconfig;
+ int ret = 0, i;
+ bool slot_found = false;
+
+ if (copy_from_user(&dd, argp, sizeof(dd))) {
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, -EFAULT);
+ return -EFAULT;
+ }
+
+ if (mic_aligned_desc_size(&dd) > MIC_MAX_DESC_BLK_SIZE
+ || dd.num_vq > MIC_MAX_VRINGS) {
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, -EINVAL);
+ return -EINVAL;
+ }
+
+ dd_config = kmalloc(mic_desc_size(&dd), GFP_KERNEL);
+ if (dd_config == NULL) {
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, -ENOMEM);
+ return -ENOMEM;
+ }
+ if (copy_from_user(dd_config, argp, mic_desc_size(&dd))) {
+ ret = -EFAULT;
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, ret);
+ goto exit;
+ }
+
+ vqconfig = mic_vq_config(dd_config);
+ for (i = 0; i < dd.num_vq; i++) {
+ if (le16_to_cpu(vqconfig[i].num) > MIC_MAX_VRING_ENTRIES) {
+ ret = -EINVAL;
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, ret);
+ goto exit;
+ }
+ }
+
+ /* Find the first free device page entry */
+ for (i = mic_aligned_size(struct mic_bootparam);
+ i < MIC_DP_SIZE - mic_total_desc_size(dd_config);
+ i += mic_total_desc_size(devp)) {
+ devp = mdev->dp + i;
+ if (devp->type == 0 || devp->type == -1) {
+ slot_found = true;
+ break;
+ }
+ }
+ if (!slot_found) {
+ ret = -EINVAL;
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, ret);
+ goto exit;
+ }
+ /*
+ * Save off the type before doing the memcpy. Type will be set in the
+ * end after completing all initialization for the new device.
+ */
+ *type = dd_config->type;
+ dd_config->type = 0;
+ memcpy(devp, dd_config, mic_desc_size(dd_config));
+
+ *devpage = devp;
+exit:
+ kfree(dd_config);
+ return ret;
+}
+
+static void mic_init_device_ctrl(struct mic_vdev *mvdev,
+ struct mic_device_desc *devpage)
+{
+ struct mic_device_ctrl *dc;
+
+ dc = mvdev->dc = (void *)devpage + mic_aligned_desc_size(devpage);
+
+ dc->config_change = 0;
+ dc->guest_ack = 0;
+ dc->vdev_reset = 0;
+ dc->host_ack = 0;
+ dc->used_address_updated = 0;
+ dc->c2h_vdev_db = -1;
+ dc->h2c_vdev_db = -1;
+}
+
+int mic_virtio_add_device(struct mic_vdev *mvdev,
+ void __user *argp)
+{
+ struct mic_device *mdev = mvdev->mdev;
+ struct mic_device_desc *dd;
+ struct mic_vqconfig *vqconfig;
+ int vr_size, i, j, ret;
+ u8 type;
+ s8 db;
+ char irqname[10];
+ struct mic_bootparam *bootparam = mdev->dp;
+ u16 num;
+
+ mutex_lock(&mdev->mic_mutex);
+
+ ret = mic_copy_dp_entry(mvdev, argp, &type, &dd);
+ if (ret) {
+ mutex_unlock(&mdev->mic_mutex);
+ return ret;
+ }
+
+ mic_init_device_ctrl(mvdev, dd);
+
+ mvdev->dd = dd;
+ mvdev->virtio_id = type;
+ vqconfig = mic_vq_config(dd);
+ INIT_WORK(&mvdev->virtio_bh_work, mic_bh_handler);
+
+ for (i = 0; i < dd->num_vq; i++) {
+ struct mic_vringh *mvr = &mvdev->mvr[i];
+ struct mic_vring *vr = &mvdev->mvr[i].vring;
+ num = le16_to_cpu(vqconfig[i].num);
+ mutex_init(&mvr->vr_mutex);
+ vr_size = PAGE_ALIGN(vring_size(num, MIC_VIRTIO_RING_ALIGN) +
+ sizeof(struct _mic_vring_info));
+ vr->va = (void *)
+ __get_free_pages(GFP_KERNEL | __GFP_ZERO,
+ get_order(vr_size));
+ if (!vr->va) {
+ ret = -ENOMEM;
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, ret);
+ goto err;
+ }
+ vr->len = vr_size;
+ vr->info = vr->va + vring_size(num, MIC_VIRTIO_RING_ALIGN);
+ vr->info->magic = MIC_MAGIC + mvdev->virtio_id + i;
+ vqconfig[i].address = mic_map_single(mdev,
+ vr->va, vr_size);
+ if (mic_map_error(vqconfig[i].address)) {
+ free_pages((unsigned long)vr->va,
+ get_order(vr_size));
+ ret = -ENOMEM;
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, ret);
+ goto err;
+ }
+ vqconfig[i].address = cpu_to_le64(vqconfig[i].address);
+
+ vring_init(&vr->vr, num,
+ vr->va, MIC_VIRTIO_RING_ALIGN);
+ ret = vringh_init_kern(&mvr->vrh,
+ *(u32 *)mic_vq_features(mvdev->dd), num, false,
+ vr->vr.desc, vr->vr.avail, vr->vr.used);
+ if (ret) {
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, ret);
+ goto err;
+ }
+ vringh_kiov_init(&mvr->riov, NULL, 0);
+ vringh_kiov_init(&mvr->wiov, NULL, 0);
+ mvr->head = USHRT_MAX;
+ mvr->mvdev = mvdev;
+ mvr->vrh.notify = mic_notify;
+ dev_dbg(mdev->sdev->parent,
+ "%s %d index %d va %p info %p vr_size 0x%x\n",
+ __func__, __LINE__, i, vr->va, vr->info, vr_size);
+ }
+
+ snprintf(irqname, sizeof(irqname),
+ "mic%dvirtio%d", mdev->id, mvdev->virtio_id);
+ mvdev->virtio_db = mic_next_db(mdev);
+ mvdev->virtio_cookie = mic_request_irq(mdev, mic_virtio_intr_handler,
+ irqname, mvdev, mvdev->virtio_db, MIC_INTR_DB);
+ if (IS_ERR(mvdev->virtio_cookie)) {
+ ret = PTR_ERR(mvdev->virtio_cookie);
+ dev_dbg(mdev->sdev->parent, "request irq failed\n");
+ goto err;
+ }
+
+ mvdev->dc->c2h_vdev_db = mvdev->virtio_db;
+
+ list_add_tail(&mvdev->list, &mdev->vdev_list);
+ /*
+ * Order the type update with previous stores. This write barrier
+ * is paired with the corresponding read barrier before the uncached
+ * system memory read of the type, on the card while scanning the
+ * device page.
+ */
+ smp_wmb();
+ dd->type = type;
+
+ dev_dbg(mdev->sdev->parent, "Added virtio device id %d\n", dd->type);
+
+ db = bootparam->h2c_config_db;
+ if (db != -1)
+ mdev->ops->send_intr(mdev, db);
+ mutex_unlock(&mdev->mic_mutex);
+ return 0;
+err:
+ vqconfig = mic_vq_config(dd);
+ for (j = 0; j < i; j++) {
+ struct mic_vringh *mvr = &mvdev->mvr[j];
+ mic_unmap_single(mdev, le64_to_cpu(vqconfig[j].address),
+ mvr->vring.len);
+ free_pages((unsigned long)mvr->vring.va,
+ get_order(mvr->vring.len));
+ }
+ mutex_unlock(&mdev->mic_mutex);
+ return ret;
+}
+
+void mic_virtio_del_device(struct mic_vdev *mvdev)
+{
+ struct list_head *pos, *tmp;
+ struct mic_vdev *tmp_mvdev;
+ struct mic_device *mdev = mvdev->mdev;
+ DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
+ int i, ret, retry = 100;
+ struct mic_vqconfig *vqconfig;
+ struct mic_bootparam *bootparam = mdev->dp;
+ s8 db;
+
+ mutex_lock(&mdev->mic_mutex);
+ db = bootparam->h2c_config_db;
+ if (db == -1)
+ goto skip_hot_remove;
+ dev_dbg(mdev->sdev->parent,
+ "Requesting hot remove id %d\n", mvdev->virtio_id);
+ mvdev->dc->config_change = MIC_VIRTIO_PARAM_DEV_REMOVE;
+ mdev->ops->send_intr(mdev, db);
+ for (i = retry; i--;) {
+ ret = wait_event_timeout(wake,
+ mvdev->dc->guest_ack, msecs_to_jiffies(100));
+ if (ret)
+ break;
+ }
+ dev_dbg(mdev->sdev->parent,
+ "Device id %d config_change %d guest_ack %d\n",
+ mvdev->virtio_id, mvdev->dc->config_change,
+ mvdev->dc->guest_ack);
+ mvdev->dc->config_change = 0;
+ mvdev->dc->guest_ack = 0;
+skip_hot_remove:
+ mic_free_irq(mdev, mvdev->virtio_cookie, mvdev);
+ flush_work(&mvdev->virtio_bh_work);
+ vqconfig = mic_vq_config(mvdev->dd);
+ for (i = 0; i < mvdev->dd->num_vq; i++) {
+ struct mic_vringh *mvr = &mvdev->mvr[i];
+ vringh_kiov_cleanup(&mvr->riov);
+ vringh_kiov_cleanup(&mvr->wiov);
+ mic_unmap_single(mdev, le64_to_cpu(vqconfig[i].address),
+ mvr->vring.len);
+ free_pages((unsigned long)mvr->vring.va,
+ get_order(mvr->vring.len));
+ }
+
+ list_for_each_safe(pos, tmp, &mdev->vdev_list) {
+ tmp_mvdev = list_entry(pos, struct mic_vdev, list);
+ if (tmp_mvdev == mvdev) {
+ list_del(pos);
+ dev_dbg(mdev->sdev->parent,
+ "Removing virtio device id %d\n",
+ mvdev->virtio_id);
+ break;
+ }
+ }
+ /*
+ * Order the type update with previous stores. This write barrier
+ * is paired with the corresponding read barrier before the uncached
+ * system memory read of the type, on the card while scanning the
+ * device page.
+ */
+ smp_wmb();
+ mvdev->dd->type = -1;
+ mutex_unlock(&mdev->mic_mutex);
+}
diff --git a/drivers/misc/mic/host/mic_virtio.h b/drivers/misc/mic/host/mic_virtio.h
new file mode 100644
index 000000000000..184f3c84805b
--- /dev/null
+++ b/drivers/misc/mic/host/mic_virtio.h
@@ -0,0 +1,138 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#ifndef MIC_VIRTIO_H
+#define MIC_VIRTIO_H
+
+#include <linux/virtio_config.h>
+#include <linux/mic_ioctl.h>
+
+/*
+ * Note on endianness.
+ * 1. Host can be both BE or LE
+ * 2. Guest/card is LE. Host uses le_to_cpu to access desc/avail
+ * rings and ioreadXX/iowriteXX to access used ring.
+ * 3. Device page exposed by host to guest contains LE values. Guest
+ * accesses these using ioreadXX/iowriteXX etc. This way in general we
+ * obey the virtio spec according to which guest works with native
+ * endianness and host is aware of guest endianness and does all
+ * required endianness conversion.
+ * 4. Data provided from user space to guest (in ADD_DEVICE and
+ * CONFIG_CHANGE ioctl's) is not interpreted by the driver and should be
+ * in guest endianness.
+ */
+
+/**
+ * struct mic_vringh - Virtio ring host information.
+ *
+ * @vring: The MIC vring used for setting up user space mappings.
+ * @vrh: The host VRINGH used for accessing the card vrings.
+ * @riov: The VRINGH read kernel IOV.
+ * @wiov: The VRINGH write kernel IOV.
+ * @head: The VRINGH head index address passed to vringh_getdesc_kern(..).
+ * @vr_mutex: Mutex for synchronizing access to the VRING.
+ * @mvdev: Back pointer to MIC virtio device for vringh_notify(..).
+ */
+struct mic_vringh {
+ struct mic_vring vring;
+ struct vringh vrh;
+ struct vringh_kiov riov;
+ struct vringh_kiov wiov;
+ u16 head;
+ struct mutex vr_mutex;
+ struct mic_vdev *mvdev;
+};
+
+/**
+ * struct mic_vdev - Host information for a card Virtio device.
+ *
+ * @virtio_id - Virtio device id.
+ * @waitq - Waitqueue to allow ring3 apps to poll.
+ * @mdev - Back pointer to host MIC device.
+ * @poll_wake - Used for waking up threads blocked in poll.
+ * @out_bytes - Debug stats for number of bytes copied from host to card.
+ * @in_bytes - Debug stats for number of bytes copied from card to host.
+ * @mvr - Store per VRING data structures.
+ * @virtio_bh_work - Work struct used to schedule virtio bottom half handling.
+ * @dd - Virtio device descriptor.
+ * @dc - Virtio device control fields.
+ * @list - List of Virtio devices.
+ * @virtio_db - The doorbell used by the card to interrupt the host.
+ * @virtio_cookie - The cookie returned while requesting interrupts.
+ */
+struct mic_vdev {
+ int virtio_id;
+ wait_queue_head_t waitq;
+ struct mic_device *mdev;
+ int poll_wake;
+ unsigned long out_bytes;
+ unsigned long in_bytes;
+ struct mic_vringh mvr[MIC_MAX_VRINGS];
+ struct work_struct virtio_bh_work;
+ struct mic_device_desc *dd;
+ struct mic_device_ctrl *dc;
+ struct list_head list;
+ int virtio_db;
+ struct mic_irq *virtio_cookie;
+};
+
+void mic_virtio_uninit(struct mic_device *mdev);
+int mic_virtio_add_device(struct mic_vdev *mvdev,
+ void __user *argp);
+void mic_virtio_del_device(struct mic_vdev *mvdev);
+int mic_virtio_config_change(struct mic_vdev *mvdev,
+ void __user *argp);
+int mic_virtio_copy_desc(struct mic_vdev *mvdev,
+ struct mic_copy_desc *request);
+void mic_virtio_reset_devices(struct mic_device *mdev);
+void mic_bh_handler(struct work_struct *work);
+
+/* Helper API to obtain the MIC PCIe device */
+static inline struct device *mic_dev(struct mic_vdev *mvdev)
+{
+ return mvdev->mdev->sdev->parent;
+}
+
+/* Helper API to check if a virtio device is initialized */
+static inline int mic_vdev_inited(struct mic_vdev *mvdev)
+{
+ /* Device has not been created yet */
+ if (!mvdev->dd || !mvdev->dd->type) {
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, -EINVAL);
+ return -EINVAL;
+ }
+
+ /* Device has been removed/deleted */
+ if (mvdev->dd->type == -1) {
+ dev_err(mic_dev(mvdev), "%s %d err %d\n",
+ __func__, __LINE__, -ENODEV);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/* Helper API to check if a virtio device is running */
+static inline bool mic_vdevup(struct mic_vdev *mvdev)
+{
+ return !!mvdev->dd->status;
+}
+#endif
diff --git a/drivers/misc/mic/host/mic_x100.c b/drivers/misc/mic/host/mic_x100.c
new file mode 100644
index 000000000000..a12ae5c8844d
--- /dev/null
+++ b/drivers/misc/mic/host/mic_x100.c
@@ -0,0 +1,573 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+
+#include "../common/mic_device.h"
+#include "mic_device.h"
+#include "mic_x100.h"
+#include "mic_smpt.h"
+
+/**
+ * mic_x100_write_spad - write to the scratchpad register
+ * @mdev: pointer to mic_device instance
+ * @idx: index to the scratchpad register, 0 based
+ * @val: the data value to put into the register
+ *
+ * This function allows writing of a 32bit value to the indexed scratchpad
+ * register.
+ *
+ * RETURNS: none.
+ */
+static void
+mic_x100_write_spad(struct mic_device *mdev, unsigned int idx, u32 val)
+{
+ dev_dbg(mdev->sdev->parent, "Writing 0x%x to scratch pad index %d\n",
+ val, idx);
+ mic_mmio_write(&mdev->mmio, val,
+ MIC_X100_SBOX_BASE_ADDRESS +
+ MIC_X100_SBOX_SPAD0 + idx * 4);
+}
+
+/**
+ * mic_x100_read_spad - read from the scratchpad register
+ * @mdev: pointer to mic_device instance
+ * @idx: index to scratchpad register, 0 based
+ *
+ * This function allows reading of the 32bit scratchpad register.
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+static u32
+mic_x100_read_spad(struct mic_device *mdev, unsigned int idx)
+{
+ u32 val = mic_mmio_read(&mdev->mmio,
+ MIC_X100_SBOX_BASE_ADDRESS +
+ MIC_X100_SBOX_SPAD0 + idx * 4);
+
+ dev_dbg(mdev->sdev->parent,
+ "Reading 0x%x from scratch pad index %d\n", val, idx);
+ return val;
+}
+
+/**
+ * mic_x100_enable_interrupts - Enable interrupts.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_x100_enable_interrupts(struct mic_device *mdev)
+{
+ u32 reg;
+ struct mic_mw *mw = &mdev->mmio;
+ u32 sice0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICE0;
+ u32 siac0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SIAC0;
+
+ reg = mic_mmio_read(mw, sice0);
+ reg |= MIC_X100_SBOX_DBR_BITS(0xf) | MIC_X100_SBOX_DMA_BITS(0xff);
+ mic_mmio_write(mw, reg, sice0);
+
+ /*
+ * Enable auto-clear when enabling interrupts. Applicable only for
+ * MSI-x. Legacy and MSI mode cannot have auto-clear enabled.
+ */
+ if (mdev->irq_info.num_vectors > 1) {
+ reg = mic_mmio_read(mw, siac0);
+ reg |= MIC_X100_SBOX_DBR_BITS(0xf) |
+ MIC_X100_SBOX_DMA_BITS(0xff);
+ mic_mmio_write(mw, reg, siac0);
+ }
+}
+
+/**
+ * mic_x100_disable_interrupts - Disable interrupts.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_x100_disable_interrupts(struct mic_device *mdev)
+{
+ u32 reg;
+ struct mic_mw *mw = &mdev->mmio;
+ u32 sice0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICE0;
+ u32 siac0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SIAC0;
+ u32 sicc0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICC0;
+
+ reg = mic_mmio_read(mw, sice0);
+ mic_mmio_write(mw, reg, sicc0);
+
+ if (mdev->irq_info.num_vectors > 1) {
+ reg = mic_mmio_read(mw, siac0);
+ reg &= ~(MIC_X100_SBOX_DBR_BITS(0xf) |
+ MIC_X100_SBOX_DMA_BITS(0xff));
+ mic_mmio_write(mw, reg, siac0);
+ }
+}
+
+/**
+ * mic_x100_send_sbox_intr - Send an MIC_X100_SBOX interrupt to MIC.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_x100_send_sbox_intr(struct mic_device *mdev,
+ int doorbell)
+{
+ struct mic_mw *mw = &mdev->mmio;
+ u64 apic_icr_offset = MIC_X100_SBOX_APICICR0 + doorbell * 8;
+ u32 apicicr_low = mic_mmio_read(mw,
+ MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
+
+ /* for MIC we need to make sure we "hit" the send_icr bit (13) */
+ apicicr_low = (apicicr_low | (1 << 13));
+
+ /* Ensure that the interrupt is ordered w.r.t. previous stores. */
+ wmb();
+ mic_mmio_write(mw, apicicr_low,
+ MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
+}
+
+/**
+ * mic_x100_send_rdmasr_intr - Send an RDMASR interrupt to MIC.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_x100_send_rdmasr_intr(struct mic_device *mdev,
+ int doorbell)
+{
+ int rdmasr_offset = MIC_X100_SBOX_RDMASR0 + (doorbell << 2);
+ /* Ensure that the interrupt is ordered w.r.t. previous stores. */
+ wmb();
+ mic_mmio_write(&mdev->mmio, 0,
+ MIC_X100_SBOX_BASE_ADDRESS + rdmasr_offset);
+}
+
+/**
+ * __mic_x100_send_intr - Send interrupt to MIC.
+ * @mdev: pointer to mic_device instance
+ * @doorbell: doorbell number.
+ */
+static void mic_x100_send_intr(struct mic_device *mdev, int doorbell)
+{
+ int rdmasr_db;
+ if (doorbell < MIC_X100_NUM_SBOX_IRQ) {
+ mic_x100_send_sbox_intr(mdev, doorbell);
+ } else {
+ rdmasr_db = doorbell - MIC_X100_NUM_SBOX_IRQ +
+ MIC_X100_RDMASR_IRQ_BASE;
+ mic_x100_send_rdmasr_intr(mdev, rdmasr_db);
+ }
+}
+
+/**
+ * mic_ack_interrupt - Device specific interrupt handling.
+ * @mdev: pointer to mic_device instance
+ *
+ * Returns: bitmask of doorbell events triggered.
+ */
+static u32 mic_x100_ack_interrupt(struct mic_device *mdev)
+{
+ u32 reg = 0;
+ struct mic_mw *mw = &mdev->mmio;
+ u32 sicr0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICR0;
+
+ /* Clear pending bit array. */
+ if (MIC_A0_STEP == mdev->stepping)
+ mic_mmio_write(mw, 1, MIC_X100_SBOX_BASE_ADDRESS +
+ MIC_X100_SBOX_MSIXPBACR);
+
+ if (mdev->irq_info.num_vectors <= 1) {
+ reg = mic_mmio_read(mw, sicr0);
+
+ if (unlikely(!reg))
+ goto done;
+
+ mic_mmio_write(mw, reg, sicr0);
+ }
+
+ if (mdev->stepping >= MIC_B0_STEP)
+ mdev->intr_ops->enable_interrupts(mdev);
+done:
+ return reg;
+}
+
+/**
+ * mic_x100_hw_intr_init - Initialize h/w specific interrupt
+ * information.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_x100_hw_intr_init(struct mic_device *mdev)
+{
+ mdev->intr_info = (struct mic_intr_info *) mic_x100_intr_init;
+}
+
+/**
+ * mic_x100_read_msi_to_src_map - read from the MSI mapping registers
+ * @mdev: pointer to mic_device instance
+ * @idx: index to the mapping register, 0 based
+ *
+ * This function allows reading of the 32bit MSI mapping register.
+ *
+ * RETURNS: The value in the register.
+ */
+static u32
+mic_x100_read_msi_to_src_map(struct mic_device *mdev, int idx)
+{
+ return mic_mmio_read(&mdev->mmio,
+ MIC_X100_SBOX_BASE_ADDRESS +
+ MIC_X100_SBOX_MXAR0 + idx * 4);
+}
+
+/**
+ * mic_x100_program_msi_to_src_map - program the MSI mapping registers
+ * @mdev: pointer to mic_device instance
+ * @idx: index to the mapping register, 0 based
+ * @offset: The bit offset in the register that needs to be updated.
+ * @set: boolean specifying if the bit in the specified offset needs
+ * to be set or cleared.
+ *
+ * RETURNS: None.
+ */
+static void
+mic_x100_program_msi_to_src_map(struct mic_device *mdev,
+ int idx, int offset, bool set)
+{
+ unsigned long reg;
+ struct mic_mw *mw = &mdev->mmio;
+ u32 mxar = MIC_X100_SBOX_BASE_ADDRESS +
+ MIC_X100_SBOX_MXAR0 + idx * 4;
+
+ reg = mic_mmio_read(mw, mxar);
+ if (set)
+ __set_bit(offset, &reg);
+ else
+ __clear_bit(offset, &reg);
+ mic_mmio_write(mw, reg, mxar);
+}
+
+/*
+ * mic_x100_reset_fw_ready - Reset Firmware ready status field.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_x100_reset_fw_ready(struct mic_device *mdev)
+{
+ mdev->ops->write_spad(mdev, MIC_X100_DOWNLOAD_INFO, 0);
+}
+
+/*
+ * mic_x100_is_fw_ready - Check if firmware is ready.
+ * @mdev: pointer to mic_device instance
+ */
+static bool mic_x100_is_fw_ready(struct mic_device *mdev)
+{
+ u32 scratch2 = mdev->ops->read_spad(mdev, MIC_X100_DOWNLOAD_INFO);
+ return MIC_X100_SPAD2_DOWNLOAD_STATUS(scratch2) ? true : false;
+}
+
+/**
+ * mic_x100_get_apic_id - Get bootstrap APIC ID.
+ * @mdev: pointer to mic_device instance
+ */
+static u32 mic_x100_get_apic_id(struct mic_device *mdev)
+{
+ u32 scratch2 = 0;
+
+ scratch2 = mdev->ops->read_spad(mdev, MIC_X100_DOWNLOAD_INFO);
+ return MIC_X100_SPAD2_APIC_ID(scratch2);
+}
+
+/**
+ * mic_x100_send_firmware_intr - Send an interrupt to the firmware on MIC.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_x100_send_firmware_intr(struct mic_device *mdev)
+{
+ u32 apicicr_low;
+ u64 apic_icr_offset = MIC_X100_SBOX_APICICR7;
+ int vector = MIC_X100_BSP_INTERRUPT_VECTOR;
+ struct mic_mw *mw = &mdev->mmio;
+
+ /*
+ * For MIC we need to make sure we "hit"
+ * the send_icr bit (13).
+ */
+ apicicr_low = (vector | (1 << 13));
+
+ mic_mmio_write(mw, mic_x100_get_apic_id(mdev),
+ MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset + 4);
+
+ /* Ensure that the interrupt is ordered w.r.t. previous stores. */
+ wmb();
+ mic_mmio_write(mw, apicicr_low,
+ MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
+}
+
+/**
+ * mic_x100_hw_reset - Reset the MIC device.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_x100_hw_reset(struct mic_device *mdev)
+{
+ u32 reset_reg;
+ u32 rgcr = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_RGCR;
+ struct mic_mw *mw = &mdev->mmio;
+
+ /* Ensure that the reset is ordered w.r.t. previous loads and stores */
+ mb();
+ /* Trigger reset */
+ reset_reg = mic_mmio_read(mw, rgcr);
+ reset_reg |= 0x1;
+ mic_mmio_write(mw, reset_reg, rgcr);
+ /*
+ * It seems we really want to delay at least 1 second
+ * after touching reset to prevent a lot of problems.
+ */
+ msleep(1000);
+}
+
+/**
+ * mic_x100_load_command_line - Load command line to MIC.
+ * @mdev: pointer to mic_device instance
+ * @fw: the firmware image
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+static int
+mic_x100_load_command_line(struct mic_device *mdev, const struct firmware *fw)
+{
+ u32 len = 0;
+ u32 boot_mem;
+ char *buf;
+ void __iomem *cmd_line_va = mdev->aper.va + mdev->bootaddr + fw->size;
+#define CMDLINE_SIZE 2048
+
+ boot_mem = mdev->aper.len >> 20;
+ buf = kzalloc(CMDLINE_SIZE, GFP_KERNEL);
+ if (!buf) {
+ dev_err(mdev->sdev->parent,
+ "%s %d allocation failed\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+ len += snprintf(buf, CMDLINE_SIZE - len,
+ " mem=%dM", boot_mem);
+ if (mdev->cmdline)
+ snprintf(buf + len, CMDLINE_SIZE - len,
+ " %s", mdev->cmdline);
+ memcpy_toio(cmd_line_va, buf, strlen(buf) + 1);
+ kfree(buf);
+ return 0;
+}
+
+/**
+ * mic_x100_load_ramdisk - Load ramdisk to MIC.
+ * @mdev: pointer to mic_device instance
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+static int
+mic_x100_load_ramdisk(struct mic_device *mdev)
+{
+ const struct firmware *fw;
+ int rc;
+ struct boot_params __iomem *bp = mdev->aper.va + mdev->bootaddr;
+
+ rc = request_firmware(&fw,
+ mdev->ramdisk, mdev->sdev->parent);
+ if (rc < 0) {
+ dev_err(mdev->sdev->parent,
+ "ramdisk request_firmware failed: %d %s\n",
+ rc, mdev->ramdisk);
+ goto error;
+ }
+ /*
+ * Typically the bootaddr for card OS is 64M
+ * so copy over the ramdisk @ 128M.
+ */
+ memcpy_toio(mdev->aper.va + (mdev->bootaddr << 1),
+ fw->data, fw->size);
+ iowrite32(cpu_to_le32(mdev->bootaddr << 1), &bp->hdr.ramdisk_image);
+ iowrite32(cpu_to_le32(fw->size), &bp->hdr.ramdisk_size);
+ release_firmware(fw);
+error:
+ return rc;
+}
+
+/**
+ * mic_x100_get_boot_addr - Get MIC boot address.
+ * @mdev: pointer to mic_device instance
+ *
+ * This function is called during firmware load to determine
+ * the address at which the OS should be downloaded in card
+ * memory i.e. GDDR.
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+static int
+mic_x100_get_boot_addr(struct mic_device *mdev)
+{
+ u32 scratch2, boot_addr;
+ int rc = 0;
+
+ scratch2 = mdev->ops->read_spad(mdev, MIC_X100_DOWNLOAD_INFO);
+ boot_addr = MIC_X100_SPAD2_DOWNLOAD_ADDR(scratch2);
+ dev_dbg(mdev->sdev->parent, "%s %d boot_addr 0x%x\n",
+ __func__, __LINE__, boot_addr);
+ if (boot_addr > (1 << 31)) {
+ dev_err(mdev->sdev->parent,
+ "incorrect bootaddr 0x%x\n",
+ boot_addr);
+ rc = -EINVAL;
+ goto error;
+ }
+ mdev->bootaddr = boot_addr;
+error:
+ return rc;
+}
+
+/**
+ * mic_x100_load_firmware - Load firmware to MIC.
+ * @mdev: pointer to mic_device instance
+ * @buf: buffer containing boot string including firmware/ramdisk path.
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+static int
+mic_x100_load_firmware(struct mic_device *mdev, const char *buf)
+{
+ int rc;
+ const struct firmware *fw;
+
+ rc = mic_x100_get_boot_addr(mdev);
+ if (rc)
+ goto error;
+ /* load OS */
+ rc = request_firmware(&fw, mdev->firmware, mdev->sdev->parent);
+ if (rc < 0) {
+ dev_err(mdev->sdev->parent,
+ "ramdisk request_firmware failed: %d %s\n",
+ rc, mdev->firmware);
+ goto error;
+ }
+ if (mdev->bootaddr > mdev->aper.len - fw->size) {
+ rc = -EINVAL;
+ dev_err(mdev->sdev->parent, "%s %d rc %d bootaddr 0x%x\n",
+ __func__, __LINE__, rc, mdev->bootaddr);
+ release_firmware(fw);
+ goto error;
+ }
+ memcpy_toio(mdev->aper.va + mdev->bootaddr, fw->data, fw->size);
+ mdev->ops->write_spad(mdev, MIC_X100_FW_SIZE, fw->size);
+ if (!strcmp(mdev->bootmode, "elf"))
+ goto done;
+ /* load command line */
+ rc = mic_x100_load_command_line(mdev, fw);
+ if (rc) {
+ dev_err(mdev->sdev->parent, "%s %d rc %d\n",
+ __func__, __LINE__, rc);
+ goto error;
+ }
+ release_firmware(fw);
+ /* load ramdisk */
+ if (mdev->ramdisk)
+ rc = mic_x100_load_ramdisk(mdev);
+error:
+ dev_dbg(mdev->sdev->parent, "%s %d rc %d\n",
+ __func__, __LINE__, rc);
+done:
+ return rc;
+}
+
+/**
+ * mic_x100_get_postcode - Get postcode status from firmware.
+ * @mdev: pointer to mic_device instance
+ *
+ * RETURNS: postcode.
+ */
+static u32 mic_x100_get_postcode(struct mic_device *mdev)
+{
+ return mic_mmio_read(&mdev->mmio, MIC_X100_POSTCODE);
+}
+
+/**
+ * mic_x100_smpt_set - Update an SMPT entry with a DMA address.
+ * @mdev: pointer to mic_device instance
+ *
+ * RETURNS: none.
+ */
+static void
+mic_x100_smpt_set(struct mic_device *mdev, dma_addr_t dma_addr, u8 index)
+{
+#define SNOOP_ON (0 << 0)
+#define SNOOP_OFF (1 << 0)
+/*
+ * Sbox Smpt Reg Bits:
+ * Bits 31:2 Host address
+ * Bits 1 RSVD
+ * Bits 0 No snoop
+ */
+#define BUILD_SMPT(NO_SNOOP, HOST_ADDR) \
+ (u32)(((HOST_ADDR) << 2) | ((NO_SNOOP) & 0x01))
+
+ uint32_t smpt_reg_val = BUILD_SMPT(SNOOP_ON,
+ dma_addr >> mdev->smpt->info.page_shift);
+ mic_mmio_write(&mdev->mmio, smpt_reg_val,
+ MIC_X100_SBOX_BASE_ADDRESS +
+ MIC_X100_SBOX_SMPT00 + (4 * index));
+}
+
+/**
+ * mic_x100_smpt_hw_init - Initialize SMPT X100 specific fields.
+ * @mdev: pointer to mic_device instance
+ *
+ * RETURNS: none.
+ */
+static void mic_x100_smpt_hw_init(struct mic_device *mdev)
+{
+ struct mic_smpt_hw_info *info = &mdev->smpt->info;
+
+ info->num_reg = 32;
+ info->page_shift = 34;
+ info->page_size = (1ULL << info->page_shift);
+ info->base = 0x8000000000ULL;
+}
+
+struct mic_smpt_ops mic_x100_smpt_ops = {
+ .init = mic_x100_smpt_hw_init,
+ .set = mic_x100_smpt_set,
+};
+
+struct mic_hw_ops mic_x100_ops = {
+ .aper_bar = MIC_X100_APER_BAR,
+ .mmio_bar = MIC_X100_MMIO_BAR,
+ .read_spad = mic_x100_read_spad,
+ .write_spad = mic_x100_write_spad,
+ .send_intr = mic_x100_send_intr,
+ .ack_interrupt = mic_x100_ack_interrupt,
+ .reset = mic_x100_hw_reset,
+ .reset_fw_ready = mic_x100_reset_fw_ready,
+ .is_fw_ready = mic_x100_is_fw_ready,
+ .send_firmware_intr = mic_x100_send_firmware_intr,
+ .load_mic_fw = mic_x100_load_firmware,
+ .get_postcode = mic_x100_get_postcode,
+};
+
+struct mic_hw_intr_ops mic_x100_intr_ops = {
+ .intr_init = mic_x100_hw_intr_init,
+ .enable_interrupts = mic_x100_enable_interrupts,
+ .disable_interrupts = mic_x100_disable_interrupts,
+ .program_msi_to_src_map = mic_x100_program_msi_to_src_map,
+ .read_msi_to_src_map = mic_x100_read_msi_to_src_map,
+};
diff --git a/drivers/misc/mic/host/mic_x100.h b/drivers/misc/mic/host/mic_x100.h
new file mode 100644
index 000000000000..8b7daa182e54
--- /dev/null
+++ b/drivers/misc/mic/host/mic_x100.h
@@ -0,0 +1,98 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#ifndef _MIC_X100_HW_H_
+#define _MIC_X100_HW_H_
+
+#define MIC_X100_PCI_DEVICE_2250 0x2250
+#define MIC_X100_PCI_DEVICE_2251 0x2251
+#define MIC_X100_PCI_DEVICE_2252 0x2252
+#define MIC_X100_PCI_DEVICE_2253 0x2253
+#define MIC_X100_PCI_DEVICE_2254 0x2254
+#define MIC_X100_PCI_DEVICE_2255 0x2255
+#define MIC_X100_PCI_DEVICE_2256 0x2256
+#define MIC_X100_PCI_DEVICE_2257 0x2257
+#define MIC_X100_PCI_DEVICE_2258 0x2258
+#define MIC_X100_PCI_DEVICE_2259 0x2259
+#define MIC_X100_PCI_DEVICE_225a 0x225a
+#define MIC_X100_PCI_DEVICE_225b 0x225b
+#define MIC_X100_PCI_DEVICE_225c 0x225c
+#define MIC_X100_PCI_DEVICE_225d 0x225d
+#define MIC_X100_PCI_DEVICE_225e 0x225e
+
+#define MIC_X100_APER_BAR 0
+#define MIC_X100_MMIO_BAR 4
+
+#define MIC_X100_SBOX_BASE_ADDRESS 0x00010000
+#define MIC_X100_SBOX_SPAD0 0x0000AB20
+#define MIC_X100_SBOX_SICR0_DBR(x) ((x) & 0xf)
+#define MIC_X100_SBOX_SICR0_DMA(x) (((x) >> 8) & 0xff)
+#define MIC_X100_SBOX_SICE0_DBR(x) ((x) & 0xf)
+#define MIC_X100_SBOX_DBR_BITS(x) ((x) & 0xf)
+#define MIC_X100_SBOX_SICE0_DMA(x) (((x) >> 8) & 0xff)
+#define MIC_X100_SBOX_DMA_BITS(x) (((x) & 0xff) << 8)
+
+#define MIC_X100_SBOX_APICICR0 0x0000A9D0
+#define MIC_X100_SBOX_SICR0 0x00009004
+#define MIC_X100_SBOX_SICE0 0x0000900C
+#define MIC_X100_SBOX_SICC0 0x00009010
+#define MIC_X100_SBOX_SIAC0 0x00009014
+#define MIC_X100_SBOX_MSIXPBACR 0x00009084
+#define MIC_X100_SBOX_MXAR0 0x00009044
+#define MIC_X100_SBOX_SMPT00 0x00003100
+#define MIC_X100_SBOX_RDMASR0 0x0000B180
+
+#define MIC_X100_DOORBELL_IDX_START 0
+#define MIC_X100_NUM_DOORBELL 4
+#define MIC_X100_DMA_IDX_START 8
+#define MIC_X100_NUM_DMA 8
+#define MIC_X100_ERR_IDX_START 30
+#define MIC_X100_NUM_ERR 1
+
+#define MIC_X100_NUM_SBOX_IRQ 8
+#define MIC_X100_NUM_RDMASR_IRQ 8
+#define MIC_X100_RDMASR_IRQ_BASE 17
+#define MIC_X100_SPAD2_DOWNLOAD_STATUS(x) ((x) & 0x1)
+#define MIC_X100_SPAD2_APIC_ID(x) (((x) >> 1) & 0x1ff)
+#define MIC_X100_SPAD2_DOWNLOAD_ADDR(x) ((x) & 0xfffff000)
+#define MIC_X100_SBOX_APICICR7 0x0000AA08
+#define MIC_X100_SBOX_RGCR 0x00004010
+#define MIC_X100_SBOX_SDBIC0 0x0000CC90
+#define MIC_X100_DOWNLOAD_INFO 2
+#define MIC_X100_FW_SIZE 5
+#define MIC_X100_POSTCODE 0x242c
+
+static const u16 mic_x100_intr_init[] = {
+ MIC_X100_DOORBELL_IDX_START,
+ MIC_X100_DMA_IDX_START,
+ MIC_X100_ERR_IDX_START,
+ MIC_X100_NUM_DOORBELL,
+ MIC_X100_NUM_DMA,
+ MIC_X100_NUM_ERR,
+};
+
+/* Host->Card(bootstrap) Interrupt Vector */
+#define MIC_X100_BSP_INTERRUPT_VECTOR 229
+
+extern struct mic_hw_ops mic_x100_ops;
+extern struct mic_smpt_ops mic_x100_smpt_ops;
+extern struct mic_hw_intr_ops mic_x100_intr_ops;
+
+#endif
diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c
index f84ff0c06035..eda38cbe8530 100644
--- a/drivers/misc/pti.c
+++ b/drivers/misc/pti.c
@@ -892,7 +892,6 @@ static void pti_pci_remove(struct pci_dev *pdev)
}
iounmap(drv_data->pti_ioaddr);
- pci_set_drvdata(pdev, NULL);
kfree(drv_data);
pci_release_region(pdev, 1);
pci_disable_device(pdev);
diff --git a/drivers/misc/ti_dac7512.c b/drivers/misc/ti_dac7512.c
index 9b237221bc4e..83da711ce9f1 100644
--- a/drivers/misc/ti_dac7512.c
+++ b/drivers/misc/ti_dac7512.c
@@ -22,9 +22,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/spi/spi.h>
-
-#define DAC7512_DRV_NAME "dac7512"
-#define DRIVER_VERSION "1.0"
+#include <linux/of.h>
static ssize_t dac7512_store_val(struct device *dev,
struct device_attribute *attr,
@@ -75,13 +73,29 @@ static int dac7512_remove(struct spi_device *spi)
return 0;
}
+static const struct spi_device_id dac7512_id_table[] = {
+ { "dac7512", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, dac7512_id_table);
+
+#ifdef CONFIG_OF
+static const struct of_device_id dac7512_of_match[] = {
+ { .compatible = "ti,dac7512", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, dac7512_of_match);
+#endif
+
static struct spi_driver dac7512_driver = {
.driver = {
- .name = DAC7512_DRV_NAME,
+ .name = "dac7512",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(dac7512_of_match),
},
.probe = dac7512_probe,
.remove = dac7512_remove,
+ .id_table = dac7512_id_table,
};
module_spi_driver(dac7512_driver);
@@ -89,4 +103,3 @@ module_spi_driver(dac7512_driver);
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
MODULE_DESCRIPTION("DAC7512 16-bit DAC");
MODULE_LICENSE("GPL v2");
-MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c
index f8d6654391e5..ae282a100429 100644
--- a/drivers/misc/tifm_7xx1.c
+++ b/drivers/misc/tifm_7xx1.c
@@ -378,7 +378,6 @@ err_out_irq:
err_out_unmap:
iounmap(fm->addr);
err_out_free:
- pci_set_drvdata(dev, NULL);
tifm_free_adapter(fm);
err_out_int:
pci_intx(dev, 0);
@@ -405,8 +404,6 @@ static void tifm_7xx1_remove(struct pci_dev *dev)
for (cnt = 0; cnt < fm->num_sockets; cnt++)
tifm_7xx1_sock_power_off(tifm_7xx1_sock_addr(fm->addr, cnt));
- pci_set_drvdata(dev, NULL);
-
iounmap(fm->addr);
pci_intx(dev, 0);
pci_release_regions(dev);
diff --git a/drivers/misc/vmw_vmci/vmci_guest.c b/drivers/misc/vmw_vmci/vmci_guest.c
index b3a2b763ecf2..c98b03b99353 100644
--- a/drivers/misc/vmw_vmci/vmci_guest.c
+++ b/drivers/misc/vmw_vmci/vmci_guest.c
@@ -649,7 +649,7 @@ static int vmci_guest_probe_device(struct pci_dev *pdev,
return 0;
err_free_irq:
- free_irq(vmci_dev->irq, &vmci_dev);
+ free_irq(vmci_dev->irq, vmci_dev);
tasklet_kill(&vmci_dev->datagram_tasklet);
tasklet_kill(&vmci_dev->bm_tasklet);
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 704bf66f5873..cdca8a70da38 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -340,7 +340,7 @@ int mmc_add_card(struct mmc_card *card)
break;
}
- if (mmc_sd_card_uhs(card) &&
+ if (mmc_card_uhs(card) &&
(card->sd_bus_speed < ARRAY_SIZE(uhs_speeds)))
uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed];
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index bf18b6bfce48..006ead2fb701 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -918,31 +918,6 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
EXPORT_SYMBOL(__mmc_claim_host);
/**
- * mmc_try_claim_host - try exclusively to claim a host
- * @host: mmc host to claim
- *
- * Returns %1 if the host is claimed, %0 otherwise.
- */
-int mmc_try_claim_host(struct mmc_host *host)
-{
- int claimed_host = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&host->lock, flags);
- if (!host->claimed || host->claimer == current) {
- host->claimed = 1;
- host->claimer = current;
- host->claim_cnt += 1;
- claimed_host = 1;
- }
- spin_unlock_irqrestore(&host->lock, flags);
- if (host->ops->enable && claimed_host && host->claim_cnt == 1)
- host->ops->enable(host);
- return claimed_host;
-}
-EXPORT_SYMBOL(mmc_try_claim_host);
-
-/**
* mmc_release_host - release a host
* @host: mmc host to release
*
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index ef183483d5b6..37f7d7059ab7 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -23,6 +23,40 @@
#define MMC_OPS_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */
+static inline int __mmc_send_status(struct mmc_card *card, u32 *status,
+ bool ignore_crc)
+{
+ int err;
+ struct mmc_command cmd = {0};
+
+ BUG_ON(!card);
+ BUG_ON(!card->host);
+
+ cmd.opcode = MMC_SEND_STATUS;
+ if (!mmc_host_is_spi(card->host))
+ cmd.arg = card->rca << 16;
+ cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
+ if (ignore_crc)
+ cmd.flags &= ~MMC_RSP_CRC;
+
+ err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
+ if (err)
+ return err;
+
+ /* NOTE: callers are required to understand the difference
+ * between "native" and SPI format status words!
+ */
+ if (status)
+ *status = cmd.resp[0];
+
+ return 0;
+}
+
+int mmc_send_status(struct mmc_card *card, u32 *status)
+{
+ return __mmc_send_status(card, status, false);
+}
+
static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
{
int err;
@@ -380,6 +414,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
struct mmc_command cmd = {0};
unsigned long timeout;
u32 status;
+ bool ignore_crc = false;
BUG_ON(!card);
BUG_ON(!card->host);
@@ -408,10 +443,18 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
if (!use_busy_signal)
return 0;
- /* Must check status to be sure of no errors */
+ /*
+ * Must check status to be sure of no errors
+ * If CMD13 is to check the busy completion of the timing change,
+ * disable the check of CRC error.
+ */
+ if (index == EXT_CSD_HS_TIMING &&
+ !(card->host->caps & MMC_CAP_WAIT_WHILE_BUSY))
+ ignore_crc = true;
+
timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS);
do {
- err = mmc_send_status(card, &status);
+ err = __mmc_send_status(card, &status, ignore_crc);
if (err)
return err;
if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
@@ -449,32 +492,6 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
}
EXPORT_SYMBOL_GPL(mmc_switch);
-int mmc_send_status(struct mmc_card *card, u32 *status)
-{
- int err;
- struct mmc_command cmd = {0};
-
- BUG_ON(!card);
- BUG_ON(!card->host);
-
- cmd.opcode = MMC_SEND_STATUS;
- if (!mmc_host_is_spi(card->host))
- cmd.arg = card->rca << 16;
- cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
-
- err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
- if (err)
- return err;
-
- /* NOTE: callers are required to understand the difference
- * between "native" and SPI format status words!
- */
- if (status)
- *status = cmd.resp[0];
-
- return 0;
-}
-
static int
mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
u8 len)
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 69e438ee043e..92c18779d47e 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -589,6 +589,13 @@ static void atmci_timeout_timer(unsigned long data)
if (host->mrq->cmd->data) {
host->mrq->cmd->data->error = -ETIMEDOUT;
host->data = NULL;
+ /*
+ * With some SDIO modules, sometimes DMA transfer hangs. If
+ * stop_transfer() is not called then the DMA request is not
+ * removed, following ones are queued and never computed.
+ */
+ if (host->state == STATE_DATA_XFER)
+ host->stop_transfer(host);
} else {
host->mrq->cmd->error = -ETIMEDOUT;
host->cmd = NULL;
@@ -1803,12 +1810,14 @@ static void atmci_tasklet_func(unsigned long priv)
if (unlikely(status)) {
host->stop_transfer(host);
host->data = NULL;
- if (status & ATMCI_DTOE) {
- data->error = -ETIMEDOUT;
- } else if (status & ATMCI_DCRCE) {
- data->error = -EILSEQ;
- } else {
- data->error = -EIO;
+ if (data) {
+ if (status & ATMCI_DTOE) {
+ data->error = -ETIMEDOUT;
+ } else if (status & ATMCI_DCRCE) {
+ data->error = -EILSEQ;
+ } else {
+ data->error = -EIO;
+ }
}
}
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
index 6a1fa2110a05..d42e664e78bc 100644
--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -14,8 +14,10 @@
#include <linux/clk.h>
#include <linux/mmc/host.h>
#include <linux/mmc/dw_mmc.h>
+#include <linux/mmc/mmc.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
+#include <linux/slab.h>
#include "dw_mmc.h"
#include "dw_mmc-pltfm.h"
@@ -30,16 +32,39 @@
#define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \
SDMMC_CLKSEL_CCLK_DRIVE(y) | \
SDMMC_CLKSEL_CCLK_DIVIDER(z))
+#define SDMMC_CLKSEL_WAKEUP_INT BIT(11)
#define EXYNOS4210_FIXED_CIU_CLK_DIV 2
#define EXYNOS4412_FIXED_CIU_CLK_DIV 4
+/* Block number in eMMC */
+#define DWMCI_BLOCK_NUM 0xFFFFFFFF
+
+#define SDMMC_EMMCP_BASE 0x1000
+#define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010)
+#define SDMMC_MPSBEGIN0 (SDMMC_EMMCP_BASE + 0x0200)
+#define SDMMC_MPSEND0 (SDMMC_EMMCP_BASE + 0x0204)
+#define SDMMC_MPSCTRL0 (SDMMC_EMMCP_BASE + 0x020C)
+
+/* SMU control bits */
+#define DWMCI_MPSCTRL_SECURE_READ_BIT BIT(7)
+#define DWMCI_MPSCTRL_SECURE_WRITE_BIT BIT(6)
+#define DWMCI_MPSCTRL_NON_SECURE_READ_BIT BIT(5)
+#define DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT BIT(4)
+#define DWMCI_MPSCTRL_USE_FUSE_KEY BIT(3)
+#define DWMCI_MPSCTRL_ECB_MODE BIT(2)
+#define DWMCI_MPSCTRL_ENCRYPTION BIT(1)
+#define DWMCI_MPSCTRL_VALID BIT(0)
+
+#define EXYNOS_CCLKIN_MIN 50000000 /* unit: HZ */
+
/* Variations in Exynos specific dw-mshc controller */
enum dw_mci_exynos_type {
DW_MCI_TYPE_EXYNOS4210,
DW_MCI_TYPE_EXYNOS4412,
DW_MCI_TYPE_EXYNOS5250,
DW_MCI_TYPE_EXYNOS5420,
+ DW_MCI_TYPE_EXYNOS5420_SMU,
};
/* Exynos implementation specific driver private data */
@@ -48,6 +73,7 @@ struct dw_mci_exynos_priv_data {
u8 ciu_div;
u32 sdr_timing;
u32 ddr_timing;
+ u32 cur_speed;
};
static struct dw_mci_exynos_compatible {
@@ -66,44 +92,80 @@ static struct dw_mci_exynos_compatible {
}, {
.compatible = "samsung,exynos5420-dw-mshc",
.ctrl_type = DW_MCI_TYPE_EXYNOS5420,
+ }, {
+ .compatible = "samsung,exynos5420-dw-mshc-smu",
+ .ctrl_type = DW_MCI_TYPE_EXYNOS5420_SMU,
},
};
static int dw_mci_exynos_priv_init(struct dw_mci *host)
{
- struct dw_mci_exynos_priv_data *priv;
- int idx;
-
- priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- dev_err(host->dev, "mem alloc failed for private data\n");
- return -ENOMEM;
- }
+ struct dw_mci_exynos_priv_data *priv = host->priv;
- for (idx = 0; idx < ARRAY_SIZE(exynos_compat); idx++) {
- if (of_device_is_compatible(host->dev->of_node,
- exynos_compat[idx].compatible))
- priv->ctrl_type = exynos_compat[idx].ctrl_type;
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420_SMU) {
+ mci_writel(host, MPSBEGIN0, 0);
+ mci_writel(host, MPSEND0, DWMCI_BLOCK_NUM);
+ mci_writel(host, MPSCTRL0, DWMCI_MPSCTRL_SECURE_WRITE_BIT |
+ DWMCI_MPSCTRL_NON_SECURE_READ_BIT |
+ DWMCI_MPSCTRL_VALID |
+ DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT);
}
- host->priv = priv;
return 0;
}
static int dw_mci_exynos_setup_clock(struct dw_mci *host)
{
struct dw_mci_exynos_priv_data *priv = host->priv;
+ unsigned long rate = clk_get_rate(host->ciu_clk);
- if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5250 ||
- priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420)
- host->bus_hz /= (priv->ciu_div + 1);
- else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412)
- host->bus_hz /= EXYNOS4412_FIXED_CIU_CLK_DIV;
- else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210)
- host->bus_hz /= EXYNOS4210_FIXED_CIU_CLK_DIV;
+ host->bus_hz = rate / (priv->ciu_div + 1);
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int dw_mci_exynos_suspend(struct device *dev)
+{
+ struct dw_mci *host = dev_get_drvdata(dev);
+
+ return dw_mci_suspend(host);
+}
+
+static int dw_mci_exynos_resume(struct device *dev)
+{
+ struct dw_mci *host = dev_get_drvdata(dev);
+
+ dw_mci_exynos_priv_init(host);
+ return dw_mci_resume(host);
+}
+
+/**
+ * dw_mci_exynos_resume_noirq - Exynos-specific resume code
+ *
+ * On exynos5420 there is a silicon errata that will sometimes leave the
+ * WAKEUP_INT bit in the CLKSEL register asserted. This bit is 1 to indicate
+ * that it fired and we can clear it by writing a 1 back. Clear it to prevent
+ * interrupts from going off constantly.
+ *
+ * We run this code on all exynos variants because it doesn't hurt.
+ */
+
+static int dw_mci_exynos_resume_noirq(struct device *dev)
+{
+ struct dw_mci *host = dev_get_drvdata(dev);
+ u32 clksel;
+
+ clksel = mci_readl(host, CLKSEL);
+ if (clksel & SDMMC_CLKSEL_WAKEUP_INT)
+ mci_writel(host, CLKSEL, clksel);
return 0;
}
+#else
+#define dw_mci_exynos_suspend NULL
+#define dw_mci_exynos_resume NULL
+#define dw_mci_exynos_resume_noirq NULL
+#endif /* CONFIG_PM_SLEEP */
static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr)
{
@@ -121,40 +183,206 @@ static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr)
static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios)
{
struct dw_mci_exynos_priv_data *priv = host->priv;
+ unsigned int wanted = ios->clock;
+ unsigned long actual;
+ u8 div = priv->ciu_div + 1;
- if (ios->timing == MMC_TIMING_UHS_DDR50)
+ if (ios->timing == MMC_TIMING_UHS_DDR50) {
mci_writel(host, CLKSEL, priv->ddr_timing);
- else
+ /* Should be double rate for DDR mode */
+ if (ios->bus_width == MMC_BUS_WIDTH_8)
+ wanted <<= 1;
+ } else {
mci_writel(host, CLKSEL, priv->sdr_timing);
+ }
+
+ /* Don't care if wanted clock is zero */
+ if (!wanted)
+ return;
+
+ /* Guaranteed minimum frequency for cclkin */
+ if (wanted < EXYNOS_CCLKIN_MIN)
+ wanted = EXYNOS_CCLKIN_MIN;
+
+ if (wanted != priv->cur_speed) {
+ int ret = clk_set_rate(host->ciu_clk, wanted * div);
+ if (ret)
+ dev_warn(host->dev,
+ "failed to set clk-rate %u error: %d\n",
+ wanted * div, ret);
+ actual = clk_get_rate(host->ciu_clk);
+ host->bus_hz = actual / div;
+ priv->cur_speed = wanted;
+ host->current_speed = 0;
+ }
}
static int dw_mci_exynos_parse_dt(struct dw_mci *host)
{
- struct dw_mci_exynos_priv_data *priv = host->priv;
+ struct dw_mci_exynos_priv_data *priv;
struct device_node *np = host->dev->of_node;
u32 timing[2];
u32 div = 0;
+ int idx;
int ret;
- of_property_read_u32(np, "samsung,dw-mshc-ciu-div", &div);
- priv->ciu_div = div;
+ priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(host->dev, "mem alloc failed for private data\n");
+ return -ENOMEM;
+ }
+
+ for (idx = 0; idx < ARRAY_SIZE(exynos_compat); idx++) {
+ if (of_device_is_compatible(np, exynos_compat[idx].compatible))
+ priv->ctrl_type = exynos_compat[idx].ctrl_type;
+ }
+
+ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412)
+ priv->ciu_div = EXYNOS4412_FIXED_CIU_CLK_DIV - 1;
+ else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210)
+ priv->ciu_div = EXYNOS4210_FIXED_CIU_CLK_DIV - 1;
+ else {
+ of_property_read_u32(np, "samsung,dw-mshc-ciu-div", &div);
+ priv->ciu_div = div;
+ }
ret = of_property_read_u32_array(np,
"samsung,dw-mshc-sdr-timing", timing, 2);
if (ret)
return ret;
- priv->sdr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div);
-
ret = of_property_read_u32_array(np,
"samsung,dw-mshc-ddr-timing", timing, 2);
if (ret)
return ret;
+ priv->sdr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div);
priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div);
+ host->priv = priv;
return 0;
}
+static inline u8 dw_mci_exynos_get_clksmpl(struct dw_mci *host)
+{
+ return SDMMC_CLKSEL_CCLK_SAMPLE(mci_readl(host, CLKSEL));
+}
+
+static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample)
+{
+ u32 clksel;
+ clksel = mci_readl(host, CLKSEL);
+ clksel = (clksel & ~0x7) | SDMMC_CLKSEL_CCLK_SAMPLE(sample);
+ mci_writel(host, CLKSEL, clksel);
+}
+
+static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host)
+{
+ u32 clksel;
+ u8 sample;
+
+ clksel = mci_readl(host, CLKSEL);
+ sample = (clksel + 1) & 0x7;
+ clksel = (clksel & ~0x7) | sample;
+ mci_writel(host, CLKSEL, clksel);
+ return sample;
+}
+
+static s8 dw_mci_exynos_get_best_clksmpl(u8 candiates)
+{
+ const u8 iter = 8;
+ u8 __c;
+ s8 i, loc = -1;
+
+ for (i = 0; i < iter; i++) {
+ __c = ror8(candiates, i);
+ if ((__c & 0xc7) == 0xc7) {
+ loc = i;
+ goto out;
+ }
+ }
+
+ for (i = 0; i < iter; i++) {
+ __c = ror8(candiates, i);
+ if ((__c & 0x83) == 0x83) {
+ loc = i;
+ goto out;
+ }
+ }
+
+out:
+ return loc;
+}
+
+static int dw_mci_exynos_execute_tuning(struct dw_mci_slot *slot, u32 opcode,
+ struct dw_mci_tuning_data *tuning_data)
+{
+ struct dw_mci *host = slot->host;
+ struct mmc_host *mmc = slot->mmc;
+ const u8 *blk_pattern = tuning_data->blk_pattern;
+ u8 *blk_test;
+ unsigned int blksz = tuning_data->blksz;
+ u8 start_smpl, smpl, candiates = 0;
+ s8 found = -1;
+ int ret = 0;
+
+ blk_test = kmalloc(blksz, GFP_KERNEL);
+ if (!blk_test)
+ return -ENOMEM;
+
+ start_smpl = dw_mci_exynos_get_clksmpl(host);
+
+ do {
+ struct mmc_request mrq = {NULL};
+ struct mmc_command cmd = {0};
+ struct mmc_command stop = {0};
+ struct mmc_data data = {0};
+ struct scatterlist sg;
+
+ cmd.opcode = opcode;
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+ stop.opcode = MMC_STOP_TRANSMISSION;
+ stop.arg = 0;
+ stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
+
+ data.blksz = blksz;
+ data.blocks = 1;
+ data.flags = MMC_DATA_READ;
+ data.sg = &sg;
+ data.sg_len = 1;
+
+ sg_init_one(&sg, blk_test, blksz);
+ mrq.cmd = &cmd;
+ mrq.stop = &stop;
+ mrq.data = &data;
+ host->mrq = &mrq;
+
+ mci_writel(host, TMOUT, ~0);
+ smpl = dw_mci_exynos_move_next_clksmpl(host);
+
+ mmc_wait_for_req(mmc, &mrq);
+
+ if (!cmd.error && !data.error) {
+ if (!memcmp(blk_pattern, blk_test, blksz))
+ candiates |= (1 << smpl);
+ } else {
+ dev_dbg(host->dev,
+ "Tuning error: cmd.error:%d, data.error:%d\n",
+ cmd.error, data.error);
+ }
+ } while (start_smpl != smpl);
+
+ found = dw_mci_exynos_get_best_clksmpl(candiates);
+ if (found >= 0)
+ dw_mci_exynos_set_clksmpl(host, found);
+ else
+ ret = -EIO;
+
+ kfree(blk_test);
+ return ret;
+}
+
/* Common capabilities of Exynos4/Exynos5 SoC */
static unsigned long exynos_dwmmc_caps[4] = {
MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR |
@@ -171,6 +399,7 @@ static const struct dw_mci_drv_data exynos_drv_data = {
.prepare_command = dw_mci_exynos_prepare_command,
.set_ios = dw_mci_exynos_set_ios,
.parse_dt = dw_mci_exynos_parse_dt,
+ .execute_tuning = dw_mci_exynos_execute_tuning,
};
static const struct of_device_id dw_mci_exynos_match[] = {
@@ -180,6 +409,8 @@ static const struct of_device_id dw_mci_exynos_match[] = {
.data = &exynos_drv_data, },
{ .compatible = "samsung,exynos5420-dw-mshc",
.data = &exynos_drv_data, },
+ { .compatible = "samsung,exynos5420-dw-mshc-smu",
+ .data = &exynos_drv_data, },
{},
};
MODULE_DEVICE_TABLE(of, dw_mci_exynos_match);
@@ -194,13 +425,20 @@ static int dw_mci_exynos_probe(struct platform_device *pdev)
return dw_mci_pltfm_register(pdev, drv_data);
}
+const struct dev_pm_ops dw_mci_exynos_pmops = {
+ SET_SYSTEM_SLEEP_PM_OPS(dw_mci_exynos_suspend, dw_mci_exynos_resume)
+ .resume_noirq = dw_mci_exynos_resume_noirq,
+ .thaw_noirq = dw_mci_exynos_resume_noirq,
+ .restore_noirq = dw_mci_exynos_resume_noirq,
+};
+
static struct platform_driver dw_mci_exynos_pltfm_driver = {
.probe = dw_mci_exynos_probe,
.remove = __exit_p(dw_mci_pltfm_remove),
.driver = {
.name = "dwmmc_exynos",
.of_match_table = dw_mci_exynos_match,
- .pm = &dw_mci_pltfm_pmops,
+ .pm = &dw_mci_exynos_pmops,
},
};
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
index 20897529ea5e..5c4965655297 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.c
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -39,7 +39,6 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
{
struct dw_mci *host;
struct resource *regs;
- int ret;
host = devm_kzalloc(&pdev->dev, sizeof(struct dw_mci), GFP_KERNEL);
if (!host)
@@ -59,12 +58,6 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
if (IS_ERR(host->regs))
return PTR_ERR(host->regs);
- if (drv_data && drv_data->init) {
- ret = drv_data->init(host);
- if (ret)
- return ret;
- }
-
platform_set_drvdata(pdev, host);
return dw_mci_probe(host);
}
diff --git a/drivers/mmc/host/dw_mmc-socfpga.c b/drivers/mmc/host/dw_mmc-socfpga.c
index 14b5961a851c..3e8e53ae3302 100644
--- a/drivers/mmc/host/dw_mmc-socfpga.c
+++ b/drivers/mmc/host/dw_mmc-socfpga.c
@@ -38,21 +38,6 @@ struct dw_mci_socfpga_priv_data {
static int dw_mci_socfpga_priv_init(struct dw_mci *host)
{
- struct dw_mci_socfpga_priv_data *priv;
-
- priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- dev_err(host->dev, "mem alloc failed for private data\n");
- return -ENOMEM;
- }
-
- priv->sysreg = syscon_regmap_lookup_by_compatible("altr,sys-mgr");
- if (IS_ERR(priv->sysreg)) {
- dev_err(host->dev, "regmap for altr,sys-mgr lookup failed.\n");
- return PTR_ERR(priv->sysreg);
- }
- host->priv = priv;
-
return 0;
}
@@ -79,12 +64,24 @@ static void dw_mci_socfpga_prepare_command(struct dw_mci *host, u32 *cmdr)
static int dw_mci_socfpga_parse_dt(struct dw_mci *host)
{
- struct dw_mci_socfpga_priv_data *priv = host->priv;
+ struct dw_mci_socfpga_priv_data *priv;
struct device_node *np = host->dev->of_node;
u32 timing[2];
u32 div = 0;
int ret;
+ priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(host->dev, "mem alloc failed for private data\n");
+ return -ENOMEM;
+ }
+
+ priv->sysreg = syscon_regmap_lookup_by_compatible("altr,sys-mgr");
+ if (IS_ERR(priv->sysreg)) {
+ dev_err(host->dev, "regmap for altr,sys-mgr lookup failed.\n");
+ return PTR_ERR(priv->sysreg);
+ }
+
ret = of_property_read_u32(np, "altr,dw-mshc-ciu-div", &div);
if (ret)
dev_info(host->dev, "No dw-mshc-ciu-div specified, assuming 1");
@@ -96,6 +93,7 @@ static int dw_mci_socfpga_parse_dt(struct dw_mci *host)
return ret;
priv->hs_timing = SYSMGR_SDMMC_CTRL_SET(timing[0], timing[1]);
+ host->priv = priv;
return 0;
}
@@ -113,7 +111,7 @@ static const struct of_device_id dw_mci_socfpga_match[] = {
};
MODULE_DEVICE_TABLE(of, dw_mci_socfpga_match);
-int dw_mci_socfpga_probe(struct platform_device *pdev)
+static int dw_mci_socfpga_probe(struct platform_device *pdev)
{
const struct dw_mci_drv_data *drv_data;
const struct of_device_id *match;
@@ -128,7 +126,7 @@ static struct platform_driver dw_mci_socfpga_pltfm_driver = {
.remove = __exit_p(dw_mci_pltfm_remove),
.driver = {
.name = "dwmmc_socfpga",
- .of_match_table = of_match_ptr(dw_mci_socfpga_match),
+ .of_match_table = dw_mci_socfpga_match,
.pm = &dw_mci_pltfm_pmops,
},
};
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 018f365e5ae4..0a6a51238b7f 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -29,6 +29,7 @@
#include <linux/irq.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
+#include <linux/mmc/sdio.h>
#include <linux/mmc/dw_mmc.h>
#include <linux/bitops.h>
#include <linux/regulator/consumer.h>
@@ -50,6 +51,9 @@
#define DW_MCI_RECV_STATUS 2
#define DW_MCI_DMA_THRESHOLD 16
+#define DW_MCI_FREQ_MAX 200000000 /* unit: HZ */
+#define DW_MCI_FREQ_MIN 400000 /* unit: HZ */
+
#ifdef CONFIG_MMC_DW_IDMAC
#define IDMAC_INT_CLR (SDMMC_IDMAC_INT_AI | SDMMC_IDMAC_INT_NI | \
SDMMC_IDMAC_INT_CES | SDMMC_IDMAC_INT_DU | \
@@ -76,42 +80,39 @@ struct idmac_desc {
};
#endif /* CONFIG_MMC_DW_IDMAC */
-/**
- * struct dw_mci_slot - MMC slot state
- * @mmc: The mmc_host representing this slot.
- * @host: The MMC controller this slot is using.
- * @quirks: Slot-level quirks (DW_MCI_SLOT_QUIRK_XXX)
- * @wp_gpio: If gpio_is_valid() we'll use this to read write protect.
- * @ctype: Card type for this slot.
- * @mrq: mmc_request currently being processed or waiting to be
- * processed, or NULL when the slot is idle.
- * @queue_node: List node for placing this node in the @queue list of
- * &struct dw_mci.
- * @clock: Clock rate configured by set_ios(). Protected by host->lock.
- * @flags: Random state bits associated with the slot.
- * @id: Number of this slot.
- * @last_detect_state: Most recently observed card detect state.
- */
-struct dw_mci_slot {
- struct mmc_host *mmc;
- struct dw_mci *host;
-
- int quirks;
- int wp_gpio;
-
- u32 ctype;
-
- struct mmc_request *mrq;
- struct list_head queue_node;
+static const u8 tuning_blk_pattern_4bit[] = {
+ 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
+ 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
+ 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
+ 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
+ 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
+ 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
+ 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
+ 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
+};
- unsigned int clock;
- unsigned long flags;
-#define DW_MMC_CARD_PRESENT 0
-#define DW_MMC_CARD_NEED_INIT 1
- int id;
- int last_detect_state;
+static const u8 tuning_blk_pattern_8bit[] = {
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
+ 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
+ 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
+ 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
+ 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
+ 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
+ 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
+ 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
+ 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
+ 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
+ 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
+ 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
+ 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
+ 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
};
+static inline bool dw_mci_fifo_reset(struct dw_mci *host);
+static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host);
+
#if defined(CONFIG_DEBUG_FS)
static int dw_mci_req_show(struct seq_file *s, void *v)
{
@@ -249,10 +250,15 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
cmdr = cmd->opcode;
- if (cmdr == MMC_STOP_TRANSMISSION)
+ if (cmd->opcode == MMC_STOP_TRANSMISSION ||
+ cmd->opcode == MMC_GO_IDLE_STATE ||
+ cmd->opcode == MMC_GO_INACTIVE_STATE ||
+ (cmd->opcode == SD_IO_RW_DIRECT &&
+ ((cmd->arg >> 9) & 0x1FFFF) == SDIO_CCCR_ABORT))
cmdr |= SDMMC_CMD_STOP;
else
- cmdr |= SDMMC_CMD_PRV_DAT_WAIT;
+ if (cmd->opcode != MMC_SEND_STATUS && cmd->data)
+ cmdr |= SDMMC_CMD_PRV_DAT_WAIT;
if (cmd->flags & MMC_RSP_PRESENT) {
/* We expect a response, so set this bit */
@@ -279,6 +285,40 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
return cmdr;
}
+static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd)
+{
+ struct mmc_command *stop;
+ u32 cmdr;
+
+ if (!cmd->data)
+ return 0;
+
+ stop = &host->stop_abort;
+ cmdr = cmd->opcode;
+ memset(stop, 0, sizeof(struct mmc_command));
+
+ if (cmdr == MMC_READ_SINGLE_BLOCK ||
+ cmdr == MMC_READ_MULTIPLE_BLOCK ||
+ cmdr == MMC_WRITE_BLOCK ||
+ cmdr == MMC_WRITE_MULTIPLE_BLOCK) {
+ stop->opcode = MMC_STOP_TRANSMISSION;
+ stop->arg = 0;
+ stop->flags = MMC_RSP_R1B | MMC_CMD_AC;
+ } else if (cmdr == SD_IO_RW_EXTENDED) {
+ stop->opcode = SD_IO_RW_DIRECT;
+ stop->arg |= (1 << 31) | (0 << 28) | (SDIO_CCCR_ABORT << 9) |
+ ((cmd->arg >> 28) & 0x7);
+ stop->flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC;
+ } else {
+ return 0;
+ }
+
+ cmdr = stop->opcode | SDMMC_CMD_STOP |
+ SDMMC_CMD_RESP_CRC | SDMMC_CMD_RESP_EXP;
+
+ return cmdr;
+}
+
static void dw_mci_start_command(struct dw_mci *host,
struct mmc_command *cmd, u32 cmd_flags)
{
@@ -293,9 +333,10 @@ static void dw_mci_start_command(struct dw_mci *host,
mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START);
}
-static void send_stop_cmd(struct dw_mci *host, struct mmc_data *data)
+static inline void send_stop_abort(struct dw_mci *host, struct mmc_data *data)
{
- dw_mci_start_command(host, data->stop, host->stop_cmdr);
+ struct mmc_command *stop = data->stop ? data->stop : &host->stop_abort;
+ dw_mci_start_command(host, stop, host->stop_cmdr);
}
/* DMA interface functions */
@@ -304,10 +345,10 @@ static void dw_mci_stop_dma(struct dw_mci *host)
if (host->using_dma) {
host->dma_ops->stop(host);
host->dma_ops->cleanup(host);
- } else {
- /* Data transfer was stopped by the interrupt handler */
- set_bit(EVENT_XFER_COMPLETE, &host->pending_events);
}
+
+ /* Data transfer was stopped by the interrupt handler */
+ set_bit(EVENT_XFER_COMPLETE, &host->pending_events);
}
static int dw_mci_get_dma_dir(struct mmc_data *data)
@@ -331,6 +372,14 @@ static void dw_mci_dma_cleanup(struct dw_mci *host)
dw_mci_get_dma_dir(data));
}
+static void dw_mci_idmac_reset(struct dw_mci *host)
+{
+ u32 bmod = mci_readl(host, BMOD);
+ /* Software reset of DMA */
+ bmod |= SDMMC_IDMAC_SWRESET;
+ mci_writel(host, BMOD, bmod);
+}
+
static void dw_mci_idmac_stop_dma(struct dw_mci *host)
{
u32 temp;
@@ -344,6 +393,7 @@ static void dw_mci_idmac_stop_dma(struct dw_mci *host)
/* Stop the IDMAC running */
temp = mci_readl(host, BMOD);
temp &= ~(SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB);
+ temp |= SDMMC_IDMAC_SWRESET;
mci_writel(host, BMOD, temp);
}
@@ -435,7 +485,7 @@ static int dw_mci_idmac_init(struct dw_mci *host)
p->des3 = host->sg_dma;
p->des0 = IDMAC_DES0_ER;
- mci_writel(host, BMOD, SDMMC_IDMAC_SWRESET);
+ dw_mci_idmac_reset(host);
/* Mask out interrupts - get Tx & Rx complete only */
mci_writel(host, IDSTS, IDMAC_INT_CLR);
@@ -532,6 +582,78 @@ static void dw_mci_post_req(struct mmc_host *mmc,
data->host_cookie = 0;
}
+static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data)
+{
+#ifdef CONFIG_MMC_DW_IDMAC
+ unsigned int blksz = data->blksz;
+ const u32 mszs[] = {1, 4, 8, 16, 32, 64, 128, 256};
+ u32 fifo_width = 1 << host->data_shift;
+ u32 blksz_depth = blksz / fifo_width, fifoth_val;
+ u32 msize = 0, rx_wmark = 1, tx_wmark, tx_wmark_invers;
+ int idx = (sizeof(mszs) / sizeof(mszs[0])) - 1;
+
+ tx_wmark = (host->fifo_depth) / 2;
+ tx_wmark_invers = host->fifo_depth - tx_wmark;
+
+ /*
+ * MSIZE is '1',
+ * if blksz is not a multiple of the FIFO width
+ */
+ if (blksz % fifo_width) {
+ msize = 0;
+ rx_wmark = 1;
+ goto done;
+ }
+
+ do {
+ if (!((blksz_depth % mszs[idx]) ||
+ (tx_wmark_invers % mszs[idx]))) {
+ msize = idx;
+ rx_wmark = mszs[idx] - 1;
+ break;
+ }
+ } while (--idx > 0);
+ /*
+ * If idx is '0', it won't be tried
+ * Thus, initial values are uesed
+ */
+done:
+ fifoth_val = SDMMC_SET_FIFOTH(msize, rx_wmark, tx_wmark);
+ mci_writel(host, FIFOTH, fifoth_val);
+#endif
+}
+
+static void dw_mci_ctrl_rd_thld(struct dw_mci *host, struct mmc_data *data)
+{
+ unsigned int blksz = data->blksz;
+ u32 blksz_depth, fifo_depth;
+ u16 thld_size;
+
+ WARN_ON(!(data->flags & MMC_DATA_READ));
+
+ if (host->timing != MMC_TIMING_MMC_HS200 &&
+ host->timing != MMC_TIMING_UHS_SDR104)
+ goto disable;
+
+ blksz_depth = blksz / (1 << host->data_shift);
+ fifo_depth = host->fifo_depth;
+
+ if (blksz_depth > fifo_depth)
+ goto disable;
+
+ /*
+ * If (blksz_depth) >= (fifo_depth >> 1), should be 'thld_size <= blksz'
+ * If (blksz_depth) < (fifo_depth >> 1), should be thld_size = blksz
+ * Currently just choose blksz.
+ */
+ thld_size = blksz;
+ mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(thld_size, 1));
+ return;
+
+disable:
+ mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(0, 0));
+}
+
static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
{
int sg_len;
@@ -556,6 +678,14 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
(unsigned long)host->sg_cpu, (unsigned long)host->sg_dma,
sg_len);
+ /*
+ * Decide the MSIZE and RX/TX Watermark.
+ * If current block size is same with previous size,
+ * no need to update fifoth.
+ */
+ if (host->prev_blksz != data->blksz)
+ dw_mci_adjust_fifoth(host, data);
+
/* Enable the DMA interface */
temp = mci_readl(host, CTRL);
temp |= SDMMC_CTRL_DMA_ENABLE;
@@ -581,10 +711,12 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
host->sg = NULL;
host->data = data;
- if (data->flags & MMC_DATA_READ)
+ if (data->flags & MMC_DATA_READ) {
host->dir_status = DW_MCI_RECV_STATUS;
- else
+ dw_mci_ctrl_rd_thld(host, data);
+ } else {
host->dir_status = DW_MCI_SEND_STATUS;
+ }
if (dw_mci_submit_data_dma(host, data)) {
int flags = SG_MITER_ATOMIC;
@@ -606,6 +738,21 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
temp = mci_readl(host, CTRL);
temp &= ~SDMMC_CTRL_DMA_ENABLE;
mci_writel(host, CTRL, temp);
+
+ /*
+ * Use the initial fifoth_val for PIO mode.
+ * If next issued data may be transfered by DMA mode,
+ * prev_blksz should be invalidated.
+ */
+ mci_writel(host, FIFOTH, host->fifoth_val);
+ host->prev_blksz = 0;
+ } else {
+ /*
+ * Keep the current block size.
+ * It will be used to decide whether to update
+ * fifoth register next time.
+ */
+ host->prev_blksz = data->blksz;
}
}
@@ -632,24 +779,31 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg)
static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
{
struct dw_mci *host = slot->host;
+ unsigned int clock = slot->clock;
u32 div;
u32 clk_en_a;
- if (slot->clock != host->current_speed || force_clkinit) {
- div = host->bus_hz / slot->clock;
- if (host->bus_hz % slot->clock && host->bus_hz > slot->clock)
+ if (!clock) {
+ mci_writel(host, CLKENA, 0);
+ mci_send_cmd(slot,
+ SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
+ } else if (clock != host->current_speed || force_clkinit) {
+ div = host->bus_hz / clock;
+ if (host->bus_hz % clock && host->bus_hz > clock)
/*
* move the + 1 after the divide to prevent
* over-clocking the card.
*/
div += 1;
- div = (host->bus_hz != slot->clock) ? DIV_ROUND_UP(div, 2) : 0;
+ div = (host->bus_hz != clock) ? DIV_ROUND_UP(div, 2) : 0;
- dev_info(&slot->mmc->class_dev,
- "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ"
- " div = %d)\n", slot->id, host->bus_hz, slot->clock,
- div ? ((host->bus_hz / div) >> 1) : host->bus_hz, div);
+ if ((clock << div) != slot->__clk_old || force_clkinit)
+ dev_info(&slot->mmc->class_dev,
+ "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ div = %d)\n",
+ slot->id, host->bus_hz, clock,
+ div ? ((host->bus_hz / div) >> 1) :
+ host->bus_hz, div);
/* disable clock */
mci_writel(host, CLKENA, 0);
@@ -676,9 +830,12 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
mci_send_cmd(slot,
SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
- host->current_speed = slot->clock;
+ /* keep the clock with reflecting clock dividor */
+ slot->__clk_old = clock << div;
}
+ host->current_speed = clock;
+
/* Set the current slot bus width */
mci_writel(host, CTYPE, (slot->ctype << slot->id));
}
@@ -700,7 +857,9 @@ static void __dw_mci_start_request(struct dw_mci *host,
host->pending_events = 0;
host->completed_events = 0;
+ host->cmd_status = 0;
host->data_status = 0;
+ host->dir_status = 0;
data = cmd->data;
if (data) {
@@ -724,6 +883,8 @@ static void __dw_mci_start_request(struct dw_mci *host,
if (mrq->stop)
host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop);
+ else
+ host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd);
}
static void dw_mci_start_request(struct dw_mci *host,
@@ -806,14 +967,13 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
regs &= ~((0x1 << slot->id) << 16);
mci_writel(slot->host, UHS_REG, regs);
+ slot->host->timing = ios->timing;
- if (ios->clock) {
- /*
- * Use mirror of ios->clock to prevent race with mmc
- * core ios update when finding the minimum.
- */
- slot->clock = ios->clock;
- }
+ /*
+ * Use mirror of ios->clock to prevent race with mmc
+ * core ios update when finding the minimum.
+ */
+ slot->clock = ios->clock;
if (drv_data && drv_data->set_ios)
drv_data->set_ios(slot->host, ios);
@@ -939,6 +1099,38 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
}
}
+static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+ struct dw_mci_slot *slot = mmc_priv(mmc);
+ struct dw_mci *host = slot->host;
+ const struct dw_mci_drv_data *drv_data = host->drv_data;
+ struct dw_mci_tuning_data tuning_data;
+ int err = -ENOSYS;
+
+ if (opcode == MMC_SEND_TUNING_BLOCK_HS200) {
+ if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) {
+ tuning_data.blk_pattern = tuning_blk_pattern_8bit;
+ tuning_data.blksz = sizeof(tuning_blk_pattern_8bit);
+ } else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4) {
+ tuning_data.blk_pattern = tuning_blk_pattern_4bit;
+ tuning_data.blksz = sizeof(tuning_blk_pattern_4bit);
+ } else {
+ return -EINVAL;
+ }
+ } else if (opcode == MMC_SEND_TUNING_BLOCK) {
+ tuning_data.blk_pattern = tuning_blk_pattern_4bit;
+ tuning_data.blksz = sizeof(tuning_blk_pattern_4bit);
+ } else {
+ dev_err(host->dev,
+ "Undefined command(%d) for tuning\n", opcode);
+ return -EINVAL;
+ }
+
+ if (drv_data && drv_data->execute_tuning)
+ err = drv_data->execute_tuning(slot, opcode, &tuning_data);
+ return err;
+}
+
static const struct mmc_host_ops dw_mci_ops = {
.request = dw_mci_request,
.pre_req = dw_mci_pre_req,
@@ -947,6 +1139,7 @@ static const struct mmc_host_ops dw_mci_ops = {
.get_ro = dw_mci_get_ro,
.get_cd = dw_mci_get_cd,
.enable_sdio_irq = dw_mci_enable_sdio_irq,
+ .execute_tuning = dw_mci_execute_tuning,
};
static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
@@ -978,7 +1171,7 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
spin_lock(&host->lock);
}
-static void dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd)
+static int dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd)
{
u32 status = host->cmd_status;
@@ -1012,12 +1205,52 @@ static void dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd
/* newer ip versions need a delay between retries */
if (host->quirks & DW_MCI_QUIRK_RETRY_DELAY)
mdelay(20);
+ }
- if (cmd->data) {
- dw_mci_stop_dma(host);
- host->data = NULL;
+ return cmd->error;
+}
+
+static int dw_mci_data_complete(struct dw_mci *host, struct mmc_data *data)
+{
+ u32 status = host->data_status;
+
+ if (status & DW_MCI_DATA_ERROR_FLAGS) {
+ if (status & SDMMC_INT_DRTO) {
+ data->error = -ETIMEDOUT;
+ } else if (status & SDMMC_INT_DCRC) {
+ data->error = -EILSEQ;
+ } else if (status & SDMMC_INT_EBE) {
+ if (host->dir_status ==
+ DW_MCI_SEND_STATUS) {
+ /*
+ * No data CRC status was returned.
+ * The number of bytes transferred
+ * will be exaggerated in PIO mode.
+ */
+ data->bytes_xfered = 0;
+ data->error = -ETIMEDOUT;
+ } else if (host->dir_status ==
+ DW_MCI_RECV_STATUS) {
+ data->error = -EIO;
+ }
+ } else {
+ /* SDMMC_INT_SBE is included */
+ data->error = -EIO;
}
+
+ dev_err(host->dev, "data error, status 0x%08x\n", status);
+
+ /*
+ * After an error, there may be data lingering
+ * in the FIFO
+ */
+ dw_mci_fifo_reset(host);
+ } else {
+ data->bytes_xfered = data->blocks * data->blksz;
+ data->error = 0;
}
+
+ return data->error;
}
static void dw_mci_tasklet_func(unsigned long priv)
@@ -1025,14 +1258,16 @@ static void dw_mci_tasklet_func(unsigned long priv)
struct dw_mci *host = (struct dw_mci *)priv;
struct mmc_data *data;
struct mmc_command *cmd;
+ struct mmc_request *mrq;
enum dw_mci_state state;
enum dw_mci_state prev_state;
- u32 status, ctrl;
+ unsigned int err;
spin_lock(&host->lock);
state = host->state;
data = host->data;
+ mrq = host->mrq;
do {
prev_state = state;
@@ -1049,16 +1284,23 @@ static void dw_mci_tasklet_func(unsigned long priv)
cmd = host->cmd;
host->cmd = NULL;
set_bit(EVENT_CMD_COMPLETE, &host->completed_events);
- dw_mci_command_complete(host, cmd);
- if (cmd == host->mrq->sbc && !cmd->error) {
+ err = dw_mci_command_complete(host, cmd);
+ if (cmd == mrq->sbc && !err) {
prev_state = state = STATE_SENDING_CMD;
__dw_mci_start_request(host, host->cur_slot,
- host->mrq->cmd);
+ mrq->cmd);
goto unlock;
}
- if (!host->mrq->data || cmd->error) {
- dw_mci_request_end(host, host->mrq);
+ if (cmd->data && err) {
+ dw_mci_stop_dma(host);
+ send_stop_abort(host, data);
+ state = STATE_SENDING_STOP;
+ break;
+ }
+
+ if (!cmd->data || err) {
+ dw_mci_request_end(host, mrq);
goto unlock;
}
@@ -1069,8 +1311,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
if (test_and_clear_bit(EVENT_DATA_ERROR,
&host->pending_events)) {
dw_mci_stop_dma(host);
- if (data->stop)
- send_stop_cmd(host, data);
+ send_stop_abort(host, data);
state = STATE_DATA_ERROR;
break;
}
@@ -1090,60 +1331,27 @@ static void dw_mci_tasklet_func(unsigned long priv)
host->data = NULL;
set_bit(EVENT_DATA_COMPLETE, &host->completed_events);
- status = host->data_status;
-
- if (status & DW_MCI_DATA_ERROR_FLAGS) {
- if (status & SDMMC_INT_DRTO) {
- data->error = -ETIMEDOUT;
- } else if (status & SDMMC_INT_DCRC) {
- data->error = -EILSEQ;
- } else if (status & SDMMC_INT_EBE &&
- host->dir_status ==
- DW_MCI_SEND_STATUS) {
- /*
- * No data CRC status was returned.
- * The number of bytes transferred will
- * be exaggerated in PIO mode.
- */
- data->bytes_xfered = 0;
- data->error = -ETIMEDOUT;
- } else {
- dev_err(host->dev,
- "data FIFO error "
- "(status=%08x)\n",
- status);
- data->error = -EIO;
- }
- /*
- * After an error, there may be data lingering
- * in the FIFO, so reset it - doing so
- * generates a block interrupt, hence setting
- * the scatter-gather pointer to NULL.
- */
- sg_miter_stop(&host->sg_miter);
- host->sg = NULL;
- ctrl = mci_readl(host, CTRL);
- ctrl |= SDMMC_CTRL_FIFO_RESET;
- mci_writel(host, CTRL, ctrl);
- } else {
- data->bytes_xfered = data->blocks * data->blksz;
- data->error = 0;
- }
+ err = dw_mci_data_complete(host, data);
- if (!data->stop) {
- dw_mci_request_end(host, host->mrq);
- goto unlock;
- }
+ if (!err) {
+ if (!data->stop || mrq->sbc) {
+ if (mrq->sbc)
+ data->stop->error = 0;
+ dw_mci_request_end(host, mrq);
+ goto unlock;
+ }
- if (host->mrq->sbc && !data->error) {
- data->stop->error = 0;
- dw_mci_request_end(host, host->mrq);
- goto unlock;
+ /* stop command for open-ended transfer*/
+ if (data->stop)
+ send_stop_abort(host, data);
}
+ /*
+ * If err has non-zero,
+ * stop-abort command has been already issued.
+ */
prev_state = state = STATE_SENDING_STOP;
- if (!data->error)
- send_stop_cmd(host, data);
+
/* fall through */
case STATE_SENDING_STOP:
@@ -1151,9 +1359,19 @@ static void dw_mci_tasklet_func(unsigned long priv)
&host->pending_events))
break;
+ /* CMD error in data command */
+ if (mrq->cmd->error && mrq->data)
+ dw_mci_fifo_reset(host);
+
host->cmd = NULL;
- dw_mci_command_complete(host, host->mrq->stop);
- dw_mci_request_end(host, host->mrq);
+ host->data = NULL;
+
+ if (mrq->stop)
+ dw_mci_command_complete(host, mrq->stop);
+ else
+ host->cmd_status = 0;
+
+ dw_mci_request_end(host, mrq);
goto unlock;
case STATE_DATA_ERROR:
@@ -1697,7 +1915,6 @@ static void dw_mci_work_routine_card(struct work_struct *work)
struct mmc_host *mmc = slot->mmc;
struct mmc_request *mrq;
int present;
- u32 ctrl;
present = dw_mci_get_cd(mmc);
while (present != slot->last_detect_state) {
@@ -1736,11 +1953,10 @@ static void dw_mci_work_routine_card(struct work_struct *work)
case STATE_DATA_ERROR:
if (mrq->data->error == -EINPROGRESS)
mrq->data->error = -ENOMEDIUM;
- if (!mrq->stop)
- break;
/* fall through */
case STATE_SENDING_STOP:
- mrq->stop->error = -ENOMEDIUM;
+ if (mrq->stop)
+ mrq->stop->error = -ENOMEDIUM;
break;
}
@@ -1763,23 +1979,10 @@ static void dw_mci_work_routine_card(struct work_struct *work)
if (present == 0) {
clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
- /*
- * Clear down the FIFO - doing so generates a
- * block interrupt, hence setting the
- * scatter-gather pointer to NULL.
- */
- sg_miter_stop(&host->sg_miter);
- host->sg = NULL;
-
- ctrl = mci_readl(host, CTRL);
- ctrl |= SDMMC_CTRL_FIFO_RESET;
- mci_writel(host, CTRL, ctrl);
-
+ /* Clear down the FIFO */
+ dw_mci_fifo_reset(host);
#ifdef CONFIG_MMC_DW_IDMAC
- ctrl = mci_readl(host, BMOD);
- /* Software reset of DMA */
- ctrl |= SDMMC_IDMAC_SWRESET;
- mci_writel(host, BMOD, ctrl);
+ dw_mci_idmac_reset(host);
#endif
}
@@ -1901,6 +2104,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
struct dw_mci_slot *slot;
const struct dw_mci_drv_data *drv_data = host->drv_data;
int ctrl_id, ret;
+ u32 freq[2];
u8 bus_width;
mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev);
@@ -1916,8 +2120,14 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
slot->quirks = dw_mci_of_get_slot_quirks(host->dev, slot->id);
mmc->ops = &dw_mci_ops;
- mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510);
- mmc->f_max = host->bus_hz;
+ if (of_property_read_u32_array(host->dev->of_node,
+ "clock-freq-min-max", freq, 2)) {
+ mmc->f_min = DW_MCI_FREQ_MIN;
+ mmc->f_max = DW_MCI_FREQ_MAX;
+ } else {
+ mmc->f_min = freq[0];
+ mmc->f_max = freq[1];
+ }
if (host->pdata->get_ocr)
mmc->ocr_avail = host->pdata->get_ocr(id);
@@ -1964,9 +2174,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
mmc->caps |= MMC_CAP_4_BIT_DATA;
}
- if (host->pdata->quirks & DW_MCI_QUIRK_HIGHSPEED)
- mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
-
if (host->pdata->blk_settings) {
mmc->max_segs = host->pdata->blk_settings->max_segs;
mmc->max_blk_size = host->pdata->blk_settings->max_blk_size;
@@ -2008,12 +2215,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
/* Card initially undetected */
slot->last_detect_state = 0;
- /*
- * Card may have been plugged in prior to boot so we
- * need to run the detect tasklet
- */
- queue_work(host->card_workqueue, &host->card_work);
-
return 0;
err_setup_bus:
@@ -2074,36 +2275,57 @@ no_dma:
return;
}
-static bool mci_wait_reset(struct device *dev, struct dw_mci *host)
+static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset)
{
unsigned long timeout = jiffies + msecs_to_jiffies(500);
- unsigned int ctrl;
+ u32 ctrl;
- mci_writel(host, CTRL, (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET |
- SDMMC_CTRL_DMA_RESET));
+ ctrl = mci_readl(host, CTRL);
+ ctrl |= reset;
+ mci_writel(host, CTRL, ctrl);
/* wait till resets clear */
do {
ctrl = mci_readl(host, CTRL);
- if (!(ctrl & (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET |
- SDMMC_CTRL_DMA_RESET)))
+ if (!(ctrl & reset))
return true;
} while (time_before(jiffies, timeout));
- dev_err(dev, "Timeout resetting block (ctrl %#x)\n", ctrl);
+ dev_err(host->dev,
+ "Timeout resetting block (ctrl reset %#x)\n",
+ ctrl & reset);
return false;
}
+static inline bool dw_mci_fifo_reset(struct dw_mci *host)
+{
+ /*
+ * Reseting generates a block interrupt, hence setting
+ * the scatter-gather pointer to NULL.
+ */
+ if (host->sg) {
+ sg_miter_stop(&host->sg_miter);
+ host->sg = NULL;
+ }
+
+ return dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET);
+}
+
+static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host)
+{
+ return dw_mci_ctrl_reset(host,
+ SDMMC_CTRL_FIFO_RESET |
+ SDMMC_CTRL_RESET |
+ SDMMC_CTRL_DMA_RESET);
+}
+
#ifdef CONFIG_OF
static struct dw_mci_of_quirks {
char *quirk;
int id;
} of_quirks[] = {
{
- .quirk = "supports-highspeed",
- .id = DW_MCI_QUIRK_HIGHSPEED,
- }, {
.quirk = "broken-cd",
.id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION,
},
@@ -2158,6 +2380,15 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
if (of_find_property(np, "enable-sdio-wakeup", NULL))
pdata->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
+ if (of_find_property(np, "supports-highspeed", NULL))
+ pdata->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
+
+ if (of_find_property(np, "caps2-mmc-hs200-1_8v", NULL))
+ pdata->caps2 |= MMC_CAP2_HS200_1_8V_SDR;
+
+ if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL))
+ pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
+
return pdata;
}
@@ -2221,6 +2452,15 @@ int dw_mci_probe(struct dw_mci *host)
host->bus_hz = clk_get_rate(host->ciu_clk);
}
+ if (drv_data && drv_data->init) {
+ ret = drv_data->init(host);
+ if (ret) {
+ dev_err(host->dev,
+ "implementation specific init failed\n");
+ goto err_clk_ciu;
+ }
+ }
+
if (drv_data && drv_data->setup_clock) {
ret = drv_data->setup_clock(host);
if (ret) {
@@ -2287,7 +2527,7 @@ int dw_mci_probe(struct dw_mci *host)
}
/* Reset all blocks */
- if (!mci_wait_reset(host->dev, host))
+ if (!dw_mci_ctrl_all_reset(host))
return -ENODEV;
host->dma_ops = host->pdata->dma_ops;
@@ -2317,8 +2557,8 @@ int dw_mci_probe(struct dw_mci *host)
fifo_size = host->pdata->fifo_depth;
}
host->fifo_depth = fifo_size;
- host->fifoth_val = ((0x2 << 28) | ((fifo_size/2 - 1) << 16) |
- ((fifo_size/2) << 0));
+ host->fifoth_val =
+ SDMMC_SET_FIFOTH(0x2, fifo_size / 2 - 1, fifo_size / 2);
mci_writel(host, FIFOTH, host->fifoth_val);
/* disable clock to CIU */
@@ -2493,7 +2733,7 @@ int dw_mci_resume(struct dw_mci *host)
}
}
- if (!mci_wait_reset(host->dev, host)) {
+ if (!dw_mci_ctrl_all_reset(host)) {
ret = -ENODEV;
return ret;
}
@@ -2501,8 +2741,15 @@ int dw_mci_resume(struct dw_mci *host)
if (host->use_dma && host->dma_ops->init)
host->dma_ops->init(host);
- /* Restore the old value at FIFOTH register */
+ /*
+ * Restore the initial value at FIFOTH register
+ * And Invalidate the prev_blksz with zero
+ */
mci_writel(host, FIFOTH, host->fifoth_val);
+ host->prev_blksz = 0;
+
+ /* Put in max timeout */
+ mci_writel(host, TMOUT, 0xFFFFFFFF);
mci_writel(host, RINTSTS, 0xFFFFFFFF);
mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 81b29941c5b9..6bf24ab917e6 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -53,6 +53,7 @@
#define SDMMC_IDINTEN 0x090
#define SDMMC_DSCADDR 0x094
#define SDMMC_BUFADDR 0x098
+#define SDMMC_CDTHRCTL 0x100
#define SDMMC_DATA(x) (x)
/*
@@ -128,6 +129,10 @@
#define SDMMC_CMD_INDX(n) ((n) & 0x1F)
/* Status register defines */
#define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FFF)
+/* FIFOTH register defines */
+#define SDMMC_SET_FIFOTH(m, r, t) (((m) & 0x7) << 28 | \
+ ((r) & 0xFFF) << 16 | \
+ ((t) & 0xFFF))
/* Internal DMAC interrupt defines */
#define SDMMC_IDMAC_INT_AI BIT(9)
#define SDMMC_IDMAC_INT_NI BIT(8)
@@ -142,6 +147,8 @@
#define SDMMC_IDMAC_SWRESET BIT(0)
/* Version ID register define */
#define SDMMC_GET_VERID(x) ((x) & 0xFFFF)
+/* Card read threshold */
+#define SDMMC_SET_RD_THLD(v, x) (((v) & 0x1FFF) << 16 | (x))
/* Register access macros */
#define mci_readl(dev, reg) \
@@ -184,6 +191,52 @@ extern int dw_mci_resume(struct dw_mci *host);
#endif
/**
+ * struct dw_mci_slot - MMC slot state
+ * @mmc: The mmc_host representing this slot.
+ * @host: The MMC controller this slot is using.
+ * @quirks: Slot-level quirks (DW_MCI_SLOT_QUIRK_XXX)
+ * @wp_gpio: If gpio_is_valid() we'll use this to read write protect.
+ * @ctype: Card type for this slot.
+ * @mrq: mmc_request currently being processed or waiting to be
+ * processed, or NULL when the slot is idle.
+ * @queue_node: List node for placing this node in the @queue list of
+ * &struct dw_mci.
+ * @clock: Clock rate configured by set_ios(). Protected by host->lock.
+ * @__clk_old: The last updated clock with reflecting clock divider.
+ * Keeping track of this helps us to avoid spamming the console
+ * with CONFIG_MMC_CLKGATE.
+ * @flags: Random state bits associated with the slot.
+ * @id: Number of this slot.
+ * @last_detect_state: Most recently observed card detect state.
+ */
+struct dw_mci_slot {
+ struct mmc_host *mmc;
+ struct dw_mci *host;
+
+ int quirks;
+ int wp_gpio;
+
+ u32 ctype;
+
+ struct mmc_request *mrq;
+ struct list_head queue_node;
+
+ unsigned int clock;
+ unsigned int __clk_old;
+
+ unsigned long flags;
+#define DW_MMC_CARD_PRESENT 0
+#define DW_MMC_CARD_NEED_INIT 1
+ int id;
+ int last_detect_state;
+};
+
+struct dw_mci_tuning_data {
+ const u8 *blk_pattern;
+ unsigned int blksz;
+};
+
+/**
* dw_mci driver data - dw-mshc implementation specific driver data.
* @caps: mmc subsystem specified capabilities of the controller(s).
* @init: early implementation specific initialization.
@@ -203,5 +256,7 @@ struct dw_mci_drv_data {
void (*prepare_command)(struct dw_mci *host, u32 *cmdr);
void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios);
int (*parse_dt)(struct dw_mci *host);
+ int (*execute_tuning)(struct dw_mci_slot *slot, u32 opcode,
+ struct dw_mci_tuning_data *tuning_data);
};
#endif /* _DW_MMC_H_ */
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index c3785edc0e92..d135c76c4855 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -62,6 +62,7 @@ static unsigned int fmax = 515633;
* @signal_direction: input/out direction of bus signals can be indicated
* @pwrreg_clkgate: MMCIPOWER register must be used to gate the clock
* @busy_detect: true if busy detection on dat0 is supported
+ * @pwrreg_nopower: bits in MMCIPOWER don't controls ext. power supply
*/
struct variant_data {
unsigned int clkreg;
@@ -76,6 +77,7 @@ struct variant_data {
bool signal_direction;
bool pwrreg_clkgate;
bool busy_detect;
+ bool pwrreg_nopower;
};
static struct variant_data variant_arm = {
@@ -109,6 +111,7 @@ static struct variant_data variant_u300 = {
.pwrreg_powerup = MCI_PWR_ON,
.signal_direction = true,
.pwrreg_clkgate = true,
+ .pwrreg_nopower = true,
};
static struct variant_data variant_nomadik = {
@@ -121,6 +124,7 @@ static struct variant_data variant_nomadik = {
.pwrreg_powerup = MCI_PWR_ON,
.signal_direction = true,
.pwrreg_clkgate = true,
+ .pwrreg_nopower = true,
};
static struct variant_data variant_ux500 = {
@@ -135,6 +139,7 @@ static struct variant_data variant_ux500 = {
.signal_direction = true,
.pwrreg_clkgate = true,
.busy_detect = true,
+ .pwrreg_nopower = true,
};
static struct variant_data variant_ux500v2 = {
@@ -150,6 +155,7 @@ static struct variant_data variant_ux500v2 = {
.signal_direction = true,
.pwrreg_clkgate = true,
.busy_detect = true,
+ .pwrreg_nopower = true,
};
static int mmci_card_busy(struct mmc_host *mmc)
@@ -189,6 +195,21 @@ static int mmci_validate_data(struct mmci_host *host,
return 0;
}
+static void mmci_reg_delay(struct mmci_host *host)
+{
+ /*
+ * According to the spec, at least three feedback clock cycles
+ * of max 52 MHz must pass between two writes to the MMCICLOCK reg.
+ * Three MCLK clock cycles must pass between two MMCIPOWER reg writes.
+ * Worst delay time during card init is at 100 kHz => 30 us.
+ * Worst delay time when up and running is at 25 MHz => 120 ns.
+ */
+ if (host->cclk < 25000000)
+ udelay(30);
+ else
+ ndelay(120);
+}
+
/*
* This must be called with host->lock held
*/
@@ -1264,6 +1285,7 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
mmci_set_clkreg(host, ios->clock);
mmci_write_pwrreg(host, pwr);
+ mmci_reg_delay(host);
spin_unlock_irqrestore(&host->lock, flags);
@@ -1510,23 +1532,6 @@ static int mmci_probe(struct amba_device *dev,
mmc->f_max = min(host->mclk, fmax);
dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max);
- host->pinctrl = devm_pinctrl_get(&dev->dev);
- if (IS_ERR(host->pinctrl)) {
- ret = PTR_ERR(host->pinctrl);
- goto clk_disable;
- }
-
- host->pins_default = pinctrl_lookup_state(host->pinctrl,
- PINCTRL_STATE_DEFAULT);
-
- /* enable pins to be muxed in and configured */
- if (!IS_ERR(host->pins_default)) {
- ret = pinctrl_select_state(host->pinctrl, host->pins_default);
- if (ret)
- dev_warn(&dev->dev, "could not set default pins\n");
- } else
- dev_warn(&dev->dev, "could not get default pinstate\n");
-
/* Get regulators and the supported OCR mask */
mmc_regulator_get_supply(mmc);
if (!mmc->ocr_avail)
@@ -1760,6 +1765,41 @@ static int mmci_resume(struct device *dev)
#endif
#ifdef CONFIG_PM_RUNTIME
+static void mmci_save(struct mmci_host *host)
+{
+ unsigned long flags;
+
+ if (host->variant->pwrreg_nopower) {
+ spin_lock_irqsave(&host->lock, flags);
+
+ writel(0, host->base + MMCIMASK0);
+ writel(0, host->base + MMCIDATACTRL);
+ writel(0, host->base + MMCIPOWER);
+ writel(0, host->base + MMCICLOCK);
+ mmci_reg_delay(host);
+
+ spin_unlock_irqrestore(&host->lock, flags);
+ }
+
+}
+
+static void mmci_restore(struct mmci_host *host)
+{
+ unsigned long flags;
+
+ if (host->variant->pwrreg_nopower) {
+ spin_lock_irqsave(&host->lock, flags);
+
+ writel(host->clk_reg, host->base + MMCICLOCK);
+ writel(host->datactrl_reg, host->base + MMCIDATACTRL);
+ writel(host->pwr_reg, host->base + MMCIPOWER);
+ writel(MCI_IRQENABLE, host->base + MMCIMASK0);
+ mmci_reg_delay(host);
+
+ spin_unlock_irqrestore(&host->lock, flags);
+ }
+}
+
static int mmci_runtime_suspend(struct device *dev)
{
struct amba_device *adev = to_amba_device(dev);
@@ -1767,6 +1807,8 @@ static int mmci_runtime_suspend(struct device *dev)
if (mmc) {
struct mmci_host *host = mmc_priv(mmc);
+ pinctrl_pm_select_sleep_state(dev);
+ mmci_save(host);
clk_disable_unprepare(host->clk);
}
@@ -1781,6 +1823,8 @@ static int mmci_runtime_resume(struct device *dev)
if (mmc) {
struct mmci_host *host = mmc_priv(mmc);
clk_prepare_enable(host->clk);
+ mmci_restore(host);
+ pinctrl_pm_select_default_state(dev);
}
return 0;
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 69080fab6375..168bc72f7a94 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -200,10 +200,6 @@ struct mmci_host {
struct sg_mapping_iter sg_miter;
unsigned int size;
- /* pinctrl handles */
- struct pinctrl *pinctrl;
- struct pinctrl_state *pins_default;
-
#ifdef CONFIG_DMA_ENGINE
/* DMA stuff */
struct dma_chan *dma_current;
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index 06c5b0b28ebc..8ad79864022f 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -655,7 +655,7 @@ static const struct mmc_host_ops mvsd_ops = {
.enable_sdio_irq = mvsd_enable_sdio_irq,
};
-static void __init
+static void
mv_conf_mbus_windows(struct mvsd_host *host,
const struct mbus_dram_target_info *dram)
{
@@ -677,7 +677,7 @@ mv_conf_mbus_windows(struct mvsd_host *host,
}
}
-static int __init mvsd_probe(struct platform_device *pdev)
+static int mvsd_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct mmc_host *mmc = NULL;
@@ -775,9 +775,9 @@ static int __init mvsd_probe(struct platform_device *pdev)
spin_lock_init(&host->lock);
- host->base = devm_request_and_ioremap(&pdev->dev, r);
- if (!host->base) {
- ret = -ENOMEM;
+ host->base = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(host->base)) {
+ ret = PTR_ERR(host->base);
goto out;
}
@@ -819,7 +819,7 @@ out:
return ret;
}
-static int __exit mvsd_remove(struct platform_device *pdev)
+static int mvsd_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
@@ -872,7 +872,8 @@ static const struct of_device_id mvsdio_dt_ids[] = {
MODULE_DEVICE_TABLE(of, mvsdio_dt_ids);
static struct platform_driver mvsd_driver = {
- .remove = __exit_p(mvsd_remove),
+ .probe = mvsd_probe,
+ .remove = mvsd_remove,
.suspend = mvsd_suspend,
.resume = mvsd_resume,
.driver = {
@@ -881,7 +882,7 @@ static struct platform_driver mvsd_driver = {
},
};
-module_platform_driver_probe(mvsd_driver, mvsd_probe);
+module_platform_driver(mvsd_driver);
/* maximum card clock frequency (default 50MHz) */
module_param(maxfreq, int, 0);
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c
index 375a880e0c5f..e2ab12473f97 100644
--- a/drivers/mmc/host/rtsx_pci_sdmmc.c
+++ b/drivers/mmc/host/rtsx_pci_sdmmc.c
@@ -364,7 +364,7 @@ static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq)
struct mmc_host *mmc = host->mmc;
struct mmc_card *card = mmc->card;
struct mmc_data *data = mrq->data;
- int uhs = mmc_sd_card_uhs(card);
+ int uhs = mmc_card_uhs(card);
int read = (data->flags & MMC_DATA_READ) ? 1 : 0;
u8 cfg2, trans_mode;
int err;
diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c
index 85472d3fd37f..7a190fe4dff1 100644
--- a/drivers/mmc/host/sdhci-bcm-kona.c
+++ b/drivers/mmc/host/sdhci-bcm-kona.c
@@ -316,19 +316,7 @@ err_pltfm_free:
static int __exit sdhci_bcm_kona_remove(struct platform_device *pdev)
{
- struct sdhci_host *host = platform_get_drvdata(pdev);
- int dead;
- u32 scratch;
-
- dead = 0;
- scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
- if (scratch == (u32)-1)
- dead = 1;
- sdhci_remove_host(host, dead);
-
- sdhci_free_host(host);
-
- return 0;
+ return sdhci_pltfm_unregister(pdev);
}
static struct platform_driver sdhci_bcm_kona_driver = {
diff --git a/drivers/mmc/host/sdhci-bcm2835.c b/drivers/mmc/host/sdhci-bcm2835.c
index 36fa2df04660..f6d8d67c545f 100644
--- a/drivers/mmc/host/sdhci-bcm2835.c
+++ b/drivers/mmc/host/sdhci-bcm2835.c
@@ -178,13 +178,7 @@ err:
static int bcm2835_sdhci_remove(struct platform_device *pdev)
{
- struct sdhci_host *host = platform_get_drvdata(pdev);
- int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
-
- sdhci_remove_host(host, dead);
- sdhci_pltfm_free(pdev);
-
- return 0;
+ return sdhci_pltfm_unregister(pdev);
}
static const struct of_device_id bcm2835_sdhci_of_match[] = {
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index abc8cf01e6e3..b9899e9c684a 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -34,12 +34,29 @@
/* VENDOR SPEC register */
#define ESDHC_VENDOR_SPEC 0xc0
#define ESDHC_VENDOR_SPEC_SDIO_QUIRK (1 << 1)
+#define ESDHC_VENDOR_SPEC_VSELECT (1 << 1)
+#define ESDHC_VENDOR_SPEC_FRC_SDCLK_ON (1 << 8)
#define ESDHC_WTMK_LVL 0x44
#define ESDHC_MIX_CTRL 0x48
#define ESDHC_MIX_CTRL_AC23EN (1 << 7)
+#define ESDHC_MIX_CTRL_EXE_TUNE (1 << 22)
+#define ESDHC_MIX_CTRL_SMPCLK_SEL (1 << 23)
+#define ESDHC_MIX_CTRL_FBCLK_SEL (1 << 25)
/* Bits 3 and 6 are not SDHCI standard definitions */
#define ESDHC_MIX_CTRL_SDHCI_MASK 0xb7
+/* tune control register */
+#define ESDHC_TUNE_CTRL_STATUS 0x68
+#define ESDHC_TUNE_CTRL_STEP 1
+#define ESDHC_TUNE_CTRL_MIN 0
+#define ESDHC_TUNE_CTRL_MAX ((1 << 7) - 1)
+
+#define ESDHC_TUNING_BLOCK_PATTERN_LEN 64
+
+/* pinctrl state */
+#define ESDHC_PINCTRL_STATE_100MHZ "state_100mhz"
+#define ESDHC_PINCTRL_STATE_200MHZ "state_200mhz"
+
/*
* Our interpretation of the SDHCI_HOST_CONTROL register
*/
@@ -81,6 +98,9 @@ struct pltfm_imx_data {
u32 scratchpad;
enum imx_esdhc_type devtype;
struct pinctrl *pinctrl;
+ struct pinctrl_state *pins_default;
+ struct pinctrl_state *pins_100mhz;
+ struct pinctrl_state *pins_200mhz;
struct esdhc_platform_data boarddata;
struct clk *clk_ipg;
struct clk *clk_ahb;
@@ -90,7 +110,7 @@ struct pltfm_imx_data {
MULTIBLK_IN_PROCESS, /* exact multiblock cmd in process */
WAIT_FOR_INT, /* sent CMD12, waiting for response INT */
} multiblock_status;
-
+ u32 uhs_mode;
};
static struct platform_device_id imx_esdhc_devtype[] = {
@@ -164,6 +184,16 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
struct pltfm_imx_data *imx_data = pltfm_host->priv;
u32 val = readl(host->ioaddr + reg);
+ if (unlikely(reg == SDHCI_PRESENT_STATE)) {
+ u32 fsl_prss = val;
+ /* save the least 20 bits */
+ val = fsl_prss & 0x000FFFFF;
+ /* move dat[0-3] bits */
+ val |= (fsl_prss & 0x0F000000) >> 4;
+ /* move cmd line bit */
+ val |= (fsl_prss & 0x00800000) << 1;
+ }
+
if (unlikely(reg == SDHCI_CAPABILITIES)) {
/* In FSL esdhc IC module, only bit20 is used to indicate the
* ADMA2 capability of esdhc, but this bit is messed up on
@@ -178,6 +208,17 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
}
}
+ if (unlikely(reg == SDHCI_CAPABILITIES_1) && is_imx6q_usdhc(imx_data))
+ val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104
+ | SDHCI_SUPPORT_SDR50;
+
+ if (unlikely(reg == SDHCI_MAX_CURRENT) && is_imx6q_usdhc(imx_data)) {
+ val = 0;
+ val |= 0xFF << SDHCI_MAX_CURRENT_330_SHIFT;
+ val |= 0xFF << SDHCI_MAX_CURRENT_300_SHIFT;
+ val |= 0xFF << SDHCI_MAX_CURRENT_180_SHIFT;
+ }
+
if (unlikely(reg == SDHCI_INT_STATUS)) {
if (val & ESDHC_INT_VENDOR_SPEC_DMA_ERR) {
val &= ~ESDHC_INT_VENDOR_SPEC_DMA_ERR;
@@ -256,6 +297,8 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct pltfm_imx_data *imx_data = pltfm_host->priv;
+ u16 ret = 0;
+ u32 val;
if (unlikely(reg == SDHCI_HOST_VERSION)) {
reg ^= 2;
@@ -268,6 +311,25 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
}
}
+ if (unlikely(reg == SDHCI_HOST_CONTROL2)) {
+ val = readl(host->ioaddr + ESDHC_VENDOR_SPEC);
+ if (val & ESDHC_VENDOR_SPEC_VSELECT)
+ ret |= SDHCI_CTRL_VDD_180;
+
+ if (is_imx6q_usdhc(imx_data)) {
+ val = readl(host->ioaddr + ESDHC_MIX_CTRL);
+ if (val & ESDHC_MIX_CTRL_EXE_TUNE)
+ ret |= SDHCI_CTRL_EXEC_TUNING;
+ if (val & ESDHC_MIX_CTRL_SMPCLK_SEL)
+ ret |= SDHCI_CTRL_TUNED_CLK;
+ }
+
+ ret |= (imx_data->uhs_mode & SDHCI_CTRL_UHS_MASK);
+ ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
+
+ return ret;
+ }
+
return readw(host->ioaddr + reg);
}
@@ -275,8 +337,32 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct pltfm_imx_data *imx_data = pltfm_host->priv;
+ u32 new_val = 0;
switch (reg) {
+ case SDHCI_CLOCK_CONTROL:
+ new_val = readl(host->ioaddr + ESDHC_VENDOR_SPEC);
+ if (val & SDHCI_CLOCK_CARD_EN)
+ new_val |= ESDHC_VENDOR_SPEC_FRC_SDCLK_ON;
+ else
+ new_val &= ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON;
+ writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
+ return;
+ case SDHCI_HOST_CONTROL2:
+ new_val = readl(host->ioaddr + ESDHC_VENDOR_SPEC);
+ if (val & SDHCI_CTRL_VDD_180)
+ new_val |= ESDHC_VENDOR_SPEC_VSELECT;
+ else
+ new_val &= ~ESDHC_VENDOR_SPEC_VSELECT;
+ writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC);
+ imx_data->uhs_mode = val & SDHCI_CTRL_UHS_MASK;
+ new_val = readl(host->ioaddr + ESDHC_MIX_CTRL);
+ if (val & SDHCI_CTRL_TUNED_CLK)
+ new_val |= ESDHC_MIX_CTRL_SMPCLK_SEL;
+ else
+ new_val &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
+ writel(new_val , host->ioaddr + ESDHC_MIX_CTRL);
+ return;
case SDHCI_TRANSFER_MODE:
if ((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)
&& (host->cmd->opcode == SD_IO_RW_EXTENDED)
@@ -409,8 +495,57 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
unsigned int clock)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct pltfm_imx_data *imx_data = pltfm_host->priv;
+ unsigned int host_clock = clk_get_rate(pltfm_host->clk);
+ int pre_div = 2;
+ int div = 1;
+ u32 temp, val;
+
+ if (clock == 0) {
+ if (is_imx6q_usdhc(imx_data)) {
+ val = readl(host->ioaddr + ESDHC_VENDOR_SPEC);
+ writel(val & ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
+ host->ioaddr + ESDHC_VENDOR_SPEC);
+ }
+ goto out;
+ }
- esdhc_set_clock(host, clock, clk_get_rate(pltfm_host->clk));
+ if (is_imx6q_usdhc(imx_data))
+ pre_div = 1;
+
+ temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
+ temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
+ | ESDHC_CLOCK_MASK);
+ sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
+
+ while (host_clock / pre_div / 16 > clock && pre_div < 256)
+ pre_div *= 2;
+
+ while (host_clock / pre_div / div > clock && div < 16)
+ div++;
+
+ host->mmc->actual_clock = host_clock / pre_div / div;
+ dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
+ clock, host->mmc->actual_clock);
+
+ pre_div >>= 1;
+ div--;
+
+ temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
+ temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
+ | (div << ESDHC_DIVIDER_SHIFT)
+ | (pre_div << ESDHC_PREDIV_SHIFT));
+ sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
+
+ if (is_imx6q_usdhc(imx_data)) {
+ val = readl(host->ioaddr + ESDHC_VENDOR_SPEC);
+ writel(val | ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
+ host->ioaddr + ESDHC_VENDOR_SPEC);
+ }
+
+ mdelay(1);
+out:
+ host->clock = clock;
}
static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
@@ -454,6 +589,177 @@ static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
return 0;
}
+static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
+{
+ u32 reg;
+
+ /* FIXME: delay a bit for card to be ready for next tuning due to errors */
+ mdelay(1);
+
+ reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
+ reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL |
+ ESDHC_MIX_CTRL_FBCLK_SEL;
+ writel(reg, host->ioaddr + ESDHC_MIX_CTRL);
+ writel(val << 8, host->ioaddr + ESDHC_TUNE_CTRL_STATUS);
+ dev_dbg(mmc_dev(host->mmc),
+ "tunning with delay 0x%x ESDHC_TUNE_CTRL_STATUS 0x%x\n",
+ val, readl(host->ioaddr + ESDHC_TUNE_CTRL_STATUS));
+}
+
+static void esdhc_request_done(struct mmc_request *mrq)
+{
+ complete(&mrq->completion);
+}
+
+static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode)
+{
+ struct mmc_command cmd = {0};
+ struct mmc_request mrq = {0};
+ struct mmc_data data = {0};
+ struct scatterlist sg;
+ char tuning_pattern[ESDHC_TUNING_BLOCK_PATTERN_LEN];
+
+ cmd.opcode = opcode;
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+ data.blksz = ESDHC_TUNING_BLOCK_PATTERN_LEN;
+ data.blocks = 1;
+ data.flags = MMC_DATA_READ;
+ data.sg = &sg;
+ data.sg_len = 1;
+
+ sg_init_one(&sg, tuning_pattern, sizeof(tuning_pattern));
+
+ mrq.cmd = &cmd;
+ mrq.cmd->mrq = &mrq;
+ mrq.data = &data;
+ mrq.data->mrq = &mrq;
+ mrq.cmd->data = mrq.data;
+
+ mrq.done = esdhc_request_done;
+ init_completion(&(mrq.completion));
+
+ disable_irq(host->irq);
+ spin_lock(&host->lock);
+ host->mrq = &mrq;
+
+ sdhci_send_command(host, mrq.cmd);
+
+ spin_unlock(&host->lock);
+ enable_irq(host->irq);
+
+ wait_for_completion(&mrq.completion);
+
+ if (cmd.error)
+ return cmd.error;
+ if (data.error)
+ return data.error;
+
+ return 0;
+}
+
+static void esdhc_post_tuning(struct sdhci_host *host)
+{
+ u32 reg;
+
+ reg = readl(host->ioaddr + ESDHC_MIX_CTRL);
+ reg &= ~ESDHC_MIX_CTRL_EXE_TUNE;
+ writel(reg, host->ioaddr + ESDHC_MIX_CTRL);
+}
+
+static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
+{
+ int min, max, avg, ret;
+
+ /* find the mininum delay first which can pass tuning */
+ min = ESDHC_TUNE_CTRL_MIN;
+ while (min < ESDHC_TUNE_CTRL_MAX) {
+ esdhc_prepare_tuning(host, min);
+ if (!esdhc_send_tuning_cmd(host, opcode))
+ break;
+ min += ESDHC_TUNE_CTRL_STEP;
+ }
+
+ /* find the maxinum delay which can not pass tuning */
+ max = min + ESDHC_TUNE_CTRL_STEP;
+ while (max < ESDHC_TUNE_CTRL_MAX) {
+ esdhc_prepare_tuning(host, max);
+ if (esdhc_send_tuning_cmd(host, opcode)) {
+ max -= ESDHC_TUNE_CTRL_STEP;
+ break;
+ }
+ max += ESDHC_TUNE_CTRL_STEP;
+ }
+
+ /* use average delay to get the best timing */
+ avg = (min + max) / 2;
+ esdhc_prepare_tuning(host, avg);
+ ret = esdhc_send_tuning_cmd(host, opcode);
+ esdhc_post_tuning(host);
+
+ dev_dbg(mmc_dev(host->mmc), "tunning %s at 0x%x ret %d\n",
+ ret ? "failed" : "passed", avg, ret);
+
+ return ret;
+}
+
+static int esdhc_change_pinstate(struct sdhci_host *host,
+ unsigned int uhs)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct pltfm_imx_data *imx_data = pltfm_host->priv;
+ struct pinctrl_state *pinctrl;
+
+ dev_dbg(mmc_dev(host->mmc), "change pinctrl state for uhs %d\n", uhs);
+
+ if (IS_ERR(imx_data->pinctrl) ||
+ IS_ERR(imx_data->pins_default) ||
+ IS_ERR(imx_data->pins_100mhz) ||
+ IS_ERR(imx_data->pins_200mhz))
+ return -EINVAL;
+
+ switch (uhs) {
+ case MMC_TIMING_UHS_SDR50:
+ pinctrl = imx_data->pins_100mhz;
+ break;
+ case MMC_TIMING_UHS_SDR104:
+ pinctrl = imx_data->pins_200mhz;
+ break;
+ default:
+ /* back to default state for other legacy timing */
+ pinctrl = imx_data->pins_default;
+ }
+
+ return pinctrl_select_state(imx_data->pinctrl, pinctrl);
+}
+
+static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct pltfm_imx_data *imx_data = pltfm_host->priv;
+
+ switch (uhs) {
+ case MMC_TIMING_UHS_SDR12:
+ imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR12;
+ break;
+ case MMC_TIMING_UHS_SDR25:
+ imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR25;
+ break;
+ case MMC_TIMING_UHS_SDR50:
+ imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR50;
+ break;
+ case MMC_TIMING_UHS_SDR104:
+ imx_data->uhs_mode = SDHCI_CTRL_UHS_SDR104;
+ break;
+ case MMC_TIMING_UHS_DDR50:
+ imx_data->uhs_mode = SDHCI_CTRL_UHS_DDR50;
+ break;
+ }
+
+ return esdhc_change_pinstate(host, uhs);
+}
+
static const struct sdhci_ops sdhci_esdhc_ops = {
.read_l = esdhc_readl_le,
.read_w = esdhc_readw_le,
@@ -465,6 +771,8 @@ static const struct sdhci_ops sdhci_esdhc_ops = {
.get_min_clock = esdhc_pltfm_get_min_clock,
.get_ro = esdhc_pltfm_get_ro,
.platform_bus_width = esdhc_pltfm_bus_width,
+ .set_uhs_signaling = esdhc_set_uhs_signaling,
+ .platform_execute_tuning = esdhc_executing_tuning,
};
static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
@@ -506,6 +814,11 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
of_property_read_u32(np, "max-frequency", &boarddata->f_max);
+ if (of_find_property(np, "no-1-8-v", NULL))
+ boarddata->support_vsel = false;
+ else
+ boarddata->support_vsel = true;
+
return 0;
}
#else
@@ -568,12 +881,20 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
clk_prepare_enable(imx_data->clk_ipg);
clk_prepare_enable(imx_data->clk_ahb);
- imx_data->pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ imx_data->pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(imx_data->pinctrl)) {
err = PTR_ERR(imx_data->pinctrl);
goto disable_clk;
}
+ imx_data->pins_default = pinctrl_lookup_state(imx_data->pinctrl,
+ PINCTRL_STATE_DEFAULT);
+ if (IS_ERR(imx_data->pins_default)) {
+ err = PTR_ERR(imx_data->pins_default);
+ dev_err(mmc_dev(host->mmc), "could not get default state\n");
+ goto disable_clk;
+ }
+
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data))
@@ -650,6 +971,23 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
break;
}
+ /* sdr50 and sdr104 needs work on 1.8v signal voltage */
+ if ((boarddata->support_vsel) && is_imx6q_usdhc(imx_data)) {
+ imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl,
+ ESDHC_PINCTRL_STATE_100MHZ);
+ imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl,
+ ESDHC_PINCTRL_STATE_200MHZ);
+ if (IS_ERR(imx_data->pins_100mhz) ||
+ IS_ERR(imx_data->pins_200mhz)) {
+ dev_warn(mmc_dev(host->mmc),
+ "could not get ultra high speed state, work on normal mode\n");
+ /* fall back to not support uhs by specify no 1.8v quirk */
+ host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
+ }
+ } else {
+ host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
+ }
+
err = sdhci_add_host(host);
if (err)
goto disable_clk;
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
index a2a06420e463..a7d9f95a7b03 100644
--- a/drivers/mmc/host/sdhci-esdhc.h
+++ b/drivers/mmc/host/sdhci-esdhc.h
@@ -49,41 +49,4 @@
#define ESDHC_HOST_CONTROL_RES 0x05
-static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock,
- unsigned int host_clock)
-{
- int pre_div = 2;
- int div = 1;
- u32 temp;
-
- if (clock == 0)
- goto out;
-
- temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
- temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
- | ESDHC_CLOCK_MASK);
- sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
-
- while (host_clock / pre_div / 16 > clock && pre_div < 256)
- pre_div *= 2;
-
- while (host_clock / pre_div / div > clock && div < 16)
- div++;
-
- dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
- clock, host_clock / pre_div / div);
-
- pre_div >>= 1;
- div--;
-
- temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
- temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
- | (div << ESDHC_DIVIDER_SHIFT)
- | (pre_div << ESDHC_PREDIV_SHIFT));
- sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
- mdelay(1);
-out:
- host->clock = clock;
-}
-
#endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index e328252ebf2a..b1605a1747c4 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -199,6 +199,14 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
{
+
+ int pre_div = 2;
+ int div = 1;
+ u32 temp;
+
+ if (clock == 0)
+ goto out;
+
/* Workaround to reduce the clock frequency for p1010 esdhc */
if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) {
if (clock > 20000000)
@@ -207,8 +215,31 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)
clock -= 5000000;
}
- /* Set the clock */
- esdhc_set_clock(host, clock, host->max_clk);
+ temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
+ temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
+ | ESDHC_CLOCK_MASK);
+ sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
+
+ while (host->max_clk / pre_div / 16 > clock && pre_div < 256)
+ pre_div *= 2;
+
+ while (host->max_clk / pre_div / div > clock && div < 16)
+ div++;
+
+ dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
+ clock, host_clock / pre_div / div);
+
+ pre_div >>= 1;
+ div--;
+
+ temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
+ temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
+ | (div << ESDHC_DIVIDER_SHIFT)
+ | (pre_div << ESDHC_PREDIV_SHIFT));
+ sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
+ mdelay(1);
+out:
+ host->clock = clock;
}
#ifdef CONFIG_PM
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 7a7fb4f0d5a4..66bce7a8e996 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -49,7 +49,6 @@ static unsigned int debug_quirks2;
static void sdhci_finish_data(struct sdhci_host *);
-static void sdhci_send_command(struct sdhci_host *, struct mmc_command *);
static void sdhci_finish_command(struct sdhci_host *);
static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
static void sdhci_tuning_timer(unsigned long data);
@@ -981,7 +980,7 @@ static void sdhci_finish_data(struct sdhci_host *host)
tasklet_schedule(&host->finish_tasklet);
}
-static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
+void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
{
int flags;
u32 mask;
@@ -1053,6 +1052,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
}
+EXPORT_SYMBOL_GPL(sdhci_send_command);
static void sdhci_finish_command(struct sdhci_host *host)
{
@@ -1875,6 +1875,14 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
return 0;
}
+ if (host->ops->platform_execute_tuning) {
+ spin_unlock(&host->lock);
+ enable_irq(host->irq);
+ err = host->ops->platform_execute_tuning(host, opcode);
+ sdhci_runtime_pm_put(host);
+ return err;
+ }
+
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
/*
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index b037f188fe44..0a3ed01887db 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -288,6 +288,7 @@ struct sdhci_ops {
unsigned int (*get_ro)(struct sdhci_host *host);
void (*platform_reset_enter)(struct sdhci_host *host, u8 mask);
void (*platform_reset_exit)(struct sdhci_host *host, u8 mask);
+ int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
void (*hw_reset)(struct sdhci_host *host);
void (*platform_suspend)(struct sdhci_host *host);
@@ -393,6 +394,8 @@ static inline void *sdhci_priv(struct sdhci_host *host)
extern void sdhci_card_detect(struct sdhci_host *host);
extern int sdhci_add_host(struct sdhci_host *host);
extern void sdhci_remove_host(struct sdhci_host *host, int dead);
+extern void sdhci_send_command(struct sdhci_host *host,
+ struct mmc_command *cmd);
#ifdef CONFIG_PM
extern int sdhci_suspend_host(struct sdhci_host *host);
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index 87ed3fb5149a..f344659dceac 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -113,14 +113,14 @@ static const struct sh_mobile_sdhi_ops sdhi_ops = {
};
static const struct of_device_id sh_mobile_sdhi_of_match[] = {
- { .compatible = "renesas,shmobile-sdhi" },
- { .compatible = "renesas,sh7372-sdhi" },
- { .compatible = "renesas,sh73a0-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
- { .compatible = "renesas,r8a73a4-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
- { .compatible = "renesas,r8a7740-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
- { .compatible = "renesas,r8a7778-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
- { .compatible = "renesas,r8a7779-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
- { .compatible = "renesas,r8a7790-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
+ { .compatible = "renesas,sdhi-shmobile" },
+ { .compatible = "renesas,sdhi-sh7372" },
+ { .compatible = "renesas,sdhi-sh73a0", .data = &sh_mobile_sdhi_of_cfg[0], },
+ { .compatible = "renesas,sdhi-r8a73a4", .data = &sh_mobile_sdhi_of_cfg[0], },
+ { .compatible = "renesas,sdhi-r8a7740", .data = &sh_mobile_sdhi_of_cfg[0], },
+ { .compatible = "renesas,sdhi-r8a7778", .data = &sh_mobile_sdhi_of_cfg[0], },
+ { .compatible = "renesas,sdhi-r8a7779", .data = &sh_mobile_sdhi_of_cfg[0], },
+ { .compatible = "renesas,sdhi-r8a7790", .data = &sh_mobile_sdhi_of_cfg[0], },
{},
};
MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match);
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 26b14f9fcac6..6bc9618af094 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -168,12 +168,25 @@ static inline int write_disable(struct m25p *flash)
*/
static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable)
{
+ int status;
+ bool need_wren = false;
+
switch (JEDEC_MFR(jedec_id)) {
- case CFI_MFR_MACRONIX:
case CFI_MFR_ST: /* Micron, actually */
+ /* Some Micron need WREN command; all will accept it */
+ need_wren = true;
+ case CFI_MFR_MACRONIX:
case 0xEF /* winbond */:
+ if (need_wren)
+ write_enable(flash);
+
flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B;
- return spi_write(flash->spi, flash->command, 1);
+ status = spi_write(flash->spi, flash->command, 1);
+
+ if (need_wren)
+ write_disable(flash);
+
+ return status;
default:
/* Spansion style */
flash->command[0] = OPCODE_BRWR;
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 0e8cbfeba11e..1cfbfcfb6e19 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -88,8 +88,6 @@ struct dataflash {
uint8_t command[4];
char name[24];
- unsigned partitioned:1;
-
unsigned short page_offset; /* offset in flash address */
unsigned int page_size; /* of bytes per page */
diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c
index d3cfe26beeaa..2ef19aa0086b 100644
--- a/drivers/mtd/lpddr/lpddr_cmds.c
+++ b/drivers/mtd/lpddr/lpddr_cmds.c
@@ -703,7 +703,7 @@ static int lpddr_erase(struct mtd_info *mtd, struct erase_info *instr)
#define DO_XXLOCK_LOCK 1
#define DO_XXLOCK_UNLOCK 2
-int do_xxlock(struct mtd_info *mtd, loff_t adr, uint32_t len, int thunk)
+static int do_xxlock(struct mtd_info *mtd, loff_t adr, uint32_t len, int thunk)
{
int ret = 0;
struct map_info *map = mtd->priv;
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 060feeaf6b3e..2dbd9133c395 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -1062,56 +1062,28 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd)
}
/*
- * Get ECC requirement in ONFI parameters, returns -1 if ONFI
- * parameters is not supported.
- * return 0 if success to get the ECC requirement.
- */
-static int get_onfi_ecc_param(struct nand_chip *chip,
- int *ecc_bits, int *sector_size)
-{
- *ecc_bits = *sector_size = 0;
-
- if (chip->onfi_params.ecc_bits == 0xff)
- /* TODO: the sector_size and ecc_bits need to be find in
- * extended ecc parameter, currently we don't support it.
- */
- return -1;
-
- *ecc_bits = chip->onfi_params.ecc_bits;
-
- /* The default sector size (ecc codeword size) is 512 */
- *sector_size = 512;
-
- return 0;
-}
-
-/*
- * Get ecc requirement from ONFI parameters ecc requirement.
+ * Get minimum ecc requirements from NAND.
* If pmecc-cap, pmecc-sector-size in DTS are not specified, this function
- * will set them according to ONFI ecc requirement. Otherwise, use the
+ * will set them according to minimum ecc requirement. Otherwise, use the
* value in DTS file.
* return 0 if success. otherwise return error code.
*/
static int pmecc_choose_ecc(struct atmel_nand_host *host,
int *cap, int *sector_size)
{
- /* Get ECC requirement from ONFI parameters */
- *cap = *sector_size = 0;
- if (host->nand_chip.onfi_version) {
- if (!get_onfi_ecc_param(&host->nand_chip, cap, sector_size))
- dev_info(host->dev, "ONFI params, minimum required ECC: %d bits in %d bytes\n",
+ /* Get minimum ECC requirements */
+ if (host->nand_chip.ecc_strength_ds) {
+ *cap = host->nand_chip.ecc_strength_ds;
+ *sector_size = host->nand_chip.ecc_step_ds;
+ dev_info(host->dev, "minimum ECC: %d bits in %d bytes\n",
*cap, *sector_size);
- else
- dev_info(host->dev, "NAND chip ECC reqirement is in Extended ONFI parameter, we don't support yet.\n");
} else {
- dev_info(host->dev, "NAND chip is not ONFI compliant, assume ecc_bits is 2 in 512 bytes");
- }
- if (*cap == 0 && *sector_size == 0) {
*cap = 2;
*sector_size = 512;
+ dev_info(host->dev, "can't detect min. ECC, assume 2 bits in 512 bytes\n");
}
- /* If dts file doesn't specify then use the one in ONFI parameters */
+ /* If device tree doesn't specify, use NAND's minimum ECC parameters */
if (host->pmecc_corr_cap == 0) {
/* use the most fitable ecc bits (the near bigger one ) */
if (*cap <= 2)
@@ -1139,7 +1111,7 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host,
return 0;
}
-static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev,
+static int atmel_pmecc_nand_init_params(struct platform_device *pdev,
struct atmel_nand_host *host)
{
struct mtd_info *mtd = &host->mtd;
@@ -1449,7 +1421,6 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
}
-#if defined(CONFIG_OF)
static int atmel_of_init_port(struct atmel_nand_host *host,
struct device_node *np)
{
@@ -1457,7 +1428,7 @@ static int atmel_of_init_port(struct atmel_nand_host *host,
u32 offset[2];
int ecc_mode;
struct atmel_nand_data *board = &host->board;
- enum of_gpio_flags flags;
+ enum of_gpio_flags flags = 0;
if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) {
if (val >= 32) {
@@ -1540,15 +1511,8 @@ static int atmel_of_init_port(struct atmel_nand_host *host,
return 0;
}
-#else
-static int atmel_of_init_port(struct atmel_nand_host *host,
- struct device_node *np)
-{
- return -EINVAL;
-}
-#endif
-static int __init atmel_hw_nand_init_params(struct platform_device *pdev,
+static int atmel_hw_nand_init_params(struct platform_device *pdev,
struct atmel_nand_host *host)
{
struct mtd_info *mtd = &host->mtd;
@@ -1987,7 +1951,7 @@ static struct platform_driver atmel_nand_nfc_driver;
/*
* Probe for the NAND device.
*/
-static int __init atmel_nand_probe(struct platform_device *pdev)
+static int atmel_nand_probe(struct platform_device *pdev)
{
struct atmel_nand_host *host;
struct mtd_info *mtd;
@@ -2019,7 +1983,8 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
mtd = &host->mtd;
nand_chip = &host->nand_chip;
host->dev = &pdev->dev;
- if (pdev->dev.of_node) {
+ if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
+ /* Only when CONFIG_OF is enabled of_node can be parsed */
res = atmel_of_init_port(host, pdev->dev.of_node);
if (res)
goto err_nand_ioremap;
@@ -2184,7 +2149,7 @@ err_nand_ioremap:
/*
* Remove a NAND device.
*/
-static int __exit atmel_nand_remove(struct platform_device *pdev)
+static int atmel_nand_remove(struct platform_device *pdev)
{
struct atmel_nand_host *host = platform_get_drvdata(pdev);
struct mtd_info *mtd = &host->mtd;
@@ -2207,14 +2172,12 @@ static int __exit atmel_nand_remove(struct platform_device *pdev)
return 0;
}
-#if defined(CONFIG_OF)
static const struct of_device_id atmel_nand_dt_ids[] = {
{ .compatible = "atmel,at91rm9200-nand" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, atmel_nand_dt_ids);
-#endif
static int atmel_nand_nfc_probe(struct platform_device *pdev)
{
@@ -2253,12 +2216,11 @@ static int atmel_nand_nfc_probe(struct platform_device *pdev)
return 0;
}
-#if defined(CONFIG_OF)
-static struct of_device_id atmel_nand_nfc_match[] = {
+static const struct of_device_id atmel_nand_nfc_match[] = {
{ .compatible = "atmel,sama5d3-nfc" },
{ /* sentinel */ }
};
-#endif
+MODULE_DEVICE_TABLE(of, atmel_nand_nfc_match);
static struct platform_driver atmel_nand_nfc_driver = {
.driver = {
@@ -2270,7 +2232,8 @@ static struct platform_driver atmel_nand_nfc_driver = {
};
static struct platform_driver atmel_nand_driver = {
- .remove = __exit_p(atmel_nand_remove),
+ .probe = atmel_nand_probe,
+ .remove = atmel_nand_remove,
.driver = {
.name = "atmel_nand",
.owner = THIS_MODULE,
@@ -2278,7 +2241,7 @@ static struct platform_driver atmel_nand_driver = {
},
};
-module_platform_driver_probe(atmel_nand_driver, atmel_nand_probe);
+module_platform_driver(atmel_nand_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rick Bronson");
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 2ed2bb33a6e7..154b033b4e8e 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -1394,7 +1394,7 @@ static struct nand_bbt_descr bbt_mirror_descr = {
};
/* initialize driver data structures */
-void denali_drv_init(struct denali_nand_info *denali)
+static void denali_drv_init(struct denali_nand_info *denali)
{
denali->idx = 0;
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c
index 548db2389fab..7c38b8ad4404 100644
--- a/drivers/mtd/nand/docg4.c
+++ b/drivers/mtd/nand/docg4.c
@@ -1239,7 +1239,6 @@ static void __init init_mtd_structs(struct mtd_info *mtd)
nand->block_markbad = docg4_block_markbad;
nand->read_buf = docg4_read_buf;
nand->write_buf = docg4_write_buf16;
- nand->scan_bbt = nand_default_bbt;
nand->erase_cmd = docg4_erase_block;
nand->ecc.read_page = docg4_read_page;
nand->ecc.write_page = docg4_write_page;
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 20657209a472..c6ef9f1c7a82 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -650,8 +650,6 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
chip->page_shift);
dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
chip->phys_erase_shift);
- dev_dbg(priv->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
- chip->ecclayout);
dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
chip->ecc.mode);
dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index 317a771f1587..47acda6c4e92 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -718,8 +718,6 @@ static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
chip->page_shift);
dev_dbg(priv->dev, "%s: nand->phys_erase_shift = %d\n", __func__,
chip->phys_erase_shift);
- dev_dbg(priv->dev, "%s: nand->ecclayout = %p\n", __func__,
- chip->ecclayout);
dev_dbg(priv->dev, "%s: nand->ecc.mode = %d\n", __func__,
chip->ecc.mode);
dev_dbg(priv->dev, "%s: nand->ecc.steps = %d\n", __func__,
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index 59ab0692f0b9..9c89e80bfbc3 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -1691,19 +1691,19 @@ static const struct platform_device_id gpmi_ids[] = {
{ .name = "imx23-gpmi-nand", .driver_data = IS_MX23, },
{ .name = "imx28-gpmi-nand", .driver_data = IS_MX28, },
{ .name = "imx6q-gpmi-nand", .driver_data = IS_MX6Q, },
- {},
+ {}
};
static const struct of_device_id gpmi_nand_id_table[] = {
{
.compatible = "fsl,imx23-gpmi-nand",
- .data = (void *)&gpmi_ids[IS_MX23]
+ .data = (void *)&gpmi_ids[IS_MX23],
}, {
.compatible = "fsl,imx28-gpmi-nand",
- .data = (void *)&gpmi_ids[IS_MX28]
+ .data = (void *)&gpmi_ids[IS_MX28],
}, {
.compatible = "fsl,imx6q-gpmi-nand",
- .data = (void *)&gpmi_ids[IS_MX6Q]
+ .data = (void *)&gpmi_ids[IS_MX6Q],
}, {}
};
MODULE_DEVICE_TABLE(of, gpmi_nand_id_table);
diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c
index add75709d415..6d5f8c515436 100644
--- a/drivers/mtd/nand/lpc32xx_slc.c
+++ b/drivers/mtd/nand/lpc32xx_slc.c
@@ -893,7 +893,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
/* Avoid extra scan if using BBT, setup BBT support */
if (host->ncfg->use_bbt) {
- chip->options |= NAND_SKIP_BBTSCAN;
chip->bbt_options |= NAND_BBT_USE_FLASH;
/*
@@ -915,13 +914,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
goto err_exit3;
}
- /* Standard layout in FLASH for bad block tables */
- if (host->ncfg->use_bbt) {
- if (nand_default_bbt(mtd) < 0)
- dev_err(&pdev->dev,
- "Error initializing default bad block tables\n");
- }
-
mtd->name = "nxp_lpc3220_slc";
ppdata.of_node = pdev->dev.of_node;
res = mtd_device_parse_register(mtd, NULL, &ppdata, host->ncfg->parts,
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 7ed4841327f2..0b39d0c03f1e 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2869,10 +2869,8 @@ static int nand_flash_detect_ext_param_page(struct mtd_info *mtd,
len = le16_to_cpu(p->ext_param_page_length) * 16;
ep = kmalloc(len, GFP_KERNEL);
- if (!ep) {
- ret = -ENOMEM;
- goto ext_out;
- }
+ if (!ep)
+ return -ENOMEM;
/* Send our own NAND_CMD_PARAM. */
chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
@@ -2914,13 +2912,14 @@ static int nand_flash_detect_ext_param_page(struct mtd_info *mtd,
/* get the info we want. */
ecc = (struct onfi_ext_ecc_info *)cursor;
- if (ecc->codeword_size) {
- chip->ecc_strength_ds = ecc->ecc_bits;
- chip->ecc_step_ds = 1 << ecc->codeword_size;
+ if (!ecc->codeword_size) {
+ pr_debug("Invalid codeword size\n");
+ goto ext_out;
}
- pr_info("ONFI extended param page detected.\n");
- return 0;
+ chip->ecc_strength_ds = ecc->ecc_bits;
+ chip->ecc_step_ds = 1 << ecc->codeword_size;
+ ret = 0;
ext_out:
kfree(ep);
@@ -2937,29 +2936,34 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
int i;
int val;
- /* ONFI need to be probed in 8 bits mode, and 16 bits should be selected with NAND_BUSWIDTH_AUTO */
- if (chip->options & NAND_BUSWIDTH_16) {
- pr_err("Trying ONFI probe in 16 bits mode, aborting !\n");
- return 0;
- }
/* Try ONFI for unknown chip or LP */
chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
return 0;
+ /*
+ * ONFI must be probed in 8-bit mode or with NAND_BUSWIDTH_AUTO, not
+ * with NAND_BUSWIDTH_16
+ */
+ if (chip->options & NAND_BUSWIDTH_16) {
+ pr_err("ONFI cannot be probed in 16-bit mode; aborting\n");
+ return 0;
+ }
+
chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
for (i = 0; i < 3; i++) {
chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
le16_to_cpu(p->crc)) {
- pr_info("ONFI param page %d valid\n", i);
break;
}
}
- if (i == 3)
+ if (i == 3) {
+ pr_err("Could not find valid ONFI parameter page; aborting\n");
return 0;
+ }
/* Check version */
val = le16_to_cpu(p->revision);
@@ -3011,10 +3015,11 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
/* The Extended Parameter Page is supported since ONFI 2.1. */
if (nand_flash_detect_ext_param_page(mtd, chip, p))
- pr_info("Failed to detect the extended param page.\n");
+ pr_warn("Failed to detect ONFI extended param page\n");
+ } else {
+ pr_warn("Could not retrieve ONFI ECC requirements\n");
}
- pr_info("ONFI flash detected\n");
return 1;
}
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index bc06196d5739..c75b6a7c6ea4 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -1392,4 +1392,3 @@ int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs)
}
EXPORT_SYMBOL(nand_scan_bbt);
-EXPORT_SYMBOL(nand_default_bbt);
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index bdc1d15369f8..3c6d5c601ade 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -575,12 +575,12 @@ static int alloc_device(struct nandsim *ns)
cfile = filp_open(cache_file, O_CREAT | O_RDWR | O_LARGEFILE, 0600);
if (IS_ERR(cfile))
return PTR_ERR(cfile);
- if (!cfile->f_op || (!cfile->f_op->read && !cfile->f_op->aio_read)) {
+ if (!file_readable(cfile)) {
NS_ERR("alloc_device: cache file not readable\n");
err = -EINVAL;
goto err_close;
}
- if (!cfile->f_op->write && !cfile->f_op->aio_write) {
+ if (!file_writable(cfile)) {
NS_ERR("alloc_device: cache file not writeable\n");
err = -EINVAL;
goto err_close;
@@ -2372,7 +2372,7 @@ static int __init ns_init_module(void)
if ((retval = init_nandsim(nsmtd)) != 0)
goto err_exit;
- if ((retval = nand_default_bbt(nsmtd)) != 0)
+ if ((retval = chip->scan_bbt(nsmtd)) != 0)
goto err_exit;
if ((retval = parse_badblocks(nand, nsmtd)) != 0)
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 558071bf92de..2362909d20c0 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -573,28 +573,6 @@ static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
static struct platform_driver omap2_onenand_driver;
-static int __adjust_timing(struct device *dev, void *data)
-{
- int ret = 0;
- struct omap2_onenand *c;
-
- c = dev_get_drvdata(dev);
-
- BUG_ON(c->setup == NULL);
-
- /* DMA is not in use so this is all that is needed */
- /* Revisit for OMAP3! */
- ret = c->setup(c->onenand.base, &c->freq);
-
- return ret;
-}
-
-int omap2_onenand_rephase(void)
-{
- return driver_for_each_device(&omap2_onenand_driver.driver, NULL,
- NULL, __adjust_timing);
-}
-
static void omap2_onenand_shutdown(struct platform_device *pdev)
{
struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index b3f41f200622..1de33b5d3903 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -2556,10 +2556,6 @@ static int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs)
{
int ret;
- /* Check for invalid offset */
- if (ofs > mtd->size)
- return -EINVAL;
-
onenand_get_device(mtd, FL_READING);
ret = onenand_block_isbad_nolock(mtd, ofs, 0);
onenand_release_device(mtd);
@@ -3529,7 +3525,7 @@ static int flexonenand_get_boundary(struct mtd_info *mtd)
{
struct onenand_chip *this = mtd->priv;
unsigned die, bdry;
- int ret, syscfg, locked;
+ int syscfg, locked;
/* Disable ECC */
syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
@@ -3540,7 +3536,7 @@ static int flexonenand_get_boundary(struct mtd_info *mtd)
this->wait(mtd, FL_SYNCING);
this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0);
- ret = this->wait(mtd, FL_READING);
+ this->wait(mtd, FL_READING);
bdry = this->read_word(this->base + ONENAND_DATARAM);
if ((bdry >> FLEXONENAND_PI_UNLOCK_SHIFT) == 3)
@@ -3550,7 +3546,7 @@ static int flexonenand_get_boundary(struct mtd_info *mtd)
this->boundary[die] = bdry & FLEXONENAND_PI_MASK;
this->command(mtd, ONENAND_CMD_RESET, 0, 0);
- ret = this->wait(mtd, FL_RESETING);
+ this->wait(mtd, FL_RESETING);
printk(KERN_INFO "Die %d boundary: %d%s\n", die,
this->boundary[die], locked ? "(Locked)" : "(Unlocked)");
@@ -3734,7 +3730,7 @@ static int flexonenand_set_boundary(struct mtd_info *mtd, int die,
/* Check is boundary is locked */
this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0);
- ret = this->wait(mtd, FL_READING);
+ this->wait(mtd, FL_READING);
thisboundary = this->read_word(this->base + ONENAND_DATARAM);
if ((thisboundary >> FLEXONENAND_PI_UNLOCK_SHIFT) != 3) {
@@ -3835,7 +3831,7 @@ static int onenand_chip_probe(struct mtd_info *mtd)
static int onenand_probe(struct mtd_info *mtd)
{
struct onenand_chip *this = mtd->priv;
- int maf_id, dev_id, ver_id;
+ int dev_id, ver_id;
int density;
int ret;
@@ -3843,8 +3839,7 @@ static int onenand_probe(struct mtd_info *mtd)
if (ret)
return ret;
- /* Read manufacturer and device IDs from Register */
- maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
+ /* Device and version IDs from Register */
dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY);
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index 3a8c7532ee0d..a7271e093845 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -102,8 +102,7 @@ static struct devprobe2 isa_probes[] __initdata = {
#ifdef CONFIG_WD80x3
{wd_probe, 0},
#endif
-#if defined(CONFIG_NE2000) || \
- defined(CONFIG_NE_H8300) /* ISA (use ne2k-pci for PCI cards) */
+#if defined(CONFIG_NE2000) /* ISA (use ne2k-pci for PCI cards) */
{ne_probe, 0},
#endif
#ifdef CONFIG_LANCE /* ISA/VLB (use pcnet32 for PCI cards) */
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 0d8f427ade93..1337eafe4311 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2117,7 +2117,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
read_lock(&bond->lock);
//check if there are any slaves
- if (list_empty(&bond->slave_list))
+ if (!bond_has_slaves(bond))
goto re_arm;
// check if agg_select_timer timer after initialize is timed out
@@ -2417,14 +2417,15 @@ int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info)
int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
{
- struct slave *slave, *start_at;
struct bonding *bond = netdev_priv(dev);
- int slave_agg_no;
- int slaves_in_agg;
- int agg_id;
- int i;
+ struct slave *slave, *first_ok_slave;
+ struct aggregator *agg;
struct ad_info ad_info;
+ struct list_head *iter;
+ int slaves_in_agg;
+ int slave_agg_no;
int res = 1;
+ int agg_id;
read_lock(&bond->lock);
if (__bond_3ad_get_active_agg_info(bond, &ad_info)) {
@@ -2437,20 +2438,28 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
agg_id = ad_info.aggregator_id;
if (slaves_in_agg == 0) {
- /*the aggregator is empty*/
pr_debug("%s: Error: active aggregator is empty\n", dev->name);
goto out;
}
slave_agg_no = bond->xmit_hash_policy(skb, slaves_in_agg);
+ first_ok_slave = NULL;
- bond_for_each_slave(bond, slave) {
- struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
+ bond_for_each_slave(bond, slave, iter) {
+ agg = SLAVE_AD_INFO(slave).port.aggregator;
+ if (!agg || agg->aggregator_identifier != agg_id)
+ continue;
- if (agg && (agg->aggregator_identifier == agg_id)) {
+ if (slave_agg_no >= 0) {
+ if (!first_ok_slave && SLAVE_IS_OK(slave))
+ first_ok_slave = slave;
slave_agg_no--;
- if (slave_agg_no < 0)
- break;
+ continue;
+ }
+
+ if (SLAVE_IS_OK(slave)) {
+ res = bond_dev_queue_xmit(bond, skb, slave->dev);
+ goto out;
}
}
@@ -2460,20 +2469,10 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
goto out;
}
- start_at = slave;
-
- bond_for_each_slave_from(bond, slave, i, start_at) {
- int slave_agg_id = 0;
- struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
-
- if (agg)
- slave_agg_id = agg->aggregator_identifier;
-
- if (SLAVE_IS_OK(slave) && agg && (slave_agg_id == agg_id)) {
- res = bond_dev_queue_xmit(bond, skb, slave->dev);
- break;
- }
- }
+ /* we couldn't find any suitable slave after the agg_no, so use the
+ * first suitable found, if found. */
+ if (first_ok_slave)
+ res = bond_dev_queue_xmit(bond, skb, first_ok_slave->dev);
out:
read_unlock(&bond->lock);
@@ -2515,11 +2514,12 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
void bond_3ad_update_lacp_rate(struct bonding *bond)
{
struct port *port = NULL;
+ struct list_head *iter;
struct slave *slave;
int lacp_fast;
lacp_fast = bond->params.lacp_fast;
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
port = &(SLAVE_AD_INFO(slave).port);
__get_state_machine_lock(port);
if (lacp_fast)
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index f428ef574372..1e9a984491bf 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -223,13 +223,14 @@ static long long compute_gap(struct slave *slave)
static struct slave *tlb_get_least_loaded_slave(struct bonding *bond)
{
struct slave *slave, *least_loaded;
+ struct list_head *iter;
long long max_gap;
least_loaded = NULL;
max_gap = LLONG_MIN;
/* Find the slave with the largest gap */
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
if (SLAVE_IS_OK(slave)) {
long long gap = compute_gap(slave);
@@ -382,30 +383,31 @@ out:
static struct slave *rlb_next_rx_slave(struct bonding *bond)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
- struct slave *rx_slave, *slave, *start_at;
- int i = 0;
-
- if (bond_info->next_rx_slave)
- start_at = bond_info->next_rx_slave;
- else
- start_at = bond_first_slave(bond);
-
- rx_slave = NULL;
+ struct slave *before = NULL, *rx_slave = NULL, *slave;
+ struct list_head *iter;
+ bool found = false;
- bond_for_each_slave_from(bond, slave, i, start_at) {
- if (SLAVE_IS_OK(slave)) {
- if (!rx_slave) {
- rx_slave = slave;
- } else if (slave->speed > rx_slave->speed) {
+ bond_for_each_slave(bond, slave, iter) {
+ if (!SLAVE_IS_OK(slave))
+ continue;
+ if (!found) {
+ if (!before || before->speed < slave->speed)
+ before = slave;
+ } else {
+ if (!rx_slave || rx_slave->speed < slave->speed)
rx_slave = slave;
- }
}
+ if (slave == bond_info->rx_slave)
+ found = true;
}
+ /* we didn't find anything after the current or we have something
+ * better before and up to the current slave
+ */
+ if (!rx_slave || (before && rx_slave->speed < before->speed))
+ rx_slave = before;
- if (rx_slave) {
- slave = bond_next_slave(bond, rx_slave);
- bond_info->next_rx_slave = slave;
- }
+ if (rx_slave)
+ bond_info->rx_slave = rx_slave;
return rx_slave;
}
@@ -1019,7 +1021,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
/* loop through vlans and send one packet for each */
rcu_read_lock();
- netdev_for_each_upper_dev_rcu(bond->dev, upper, iter) {
+ 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));
@@ -1172,10 +1174,11 @@ static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *sla
*/
static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave)
{
- struct slave *tmp_slave1, *free_mac_slave = NULL;
struct slave *has_bond_addr = bond->curr_active_slave;
+ struct slave *tmp_slave1, *free_mac_slave = NULL;
+ struct list_head *iter;
- if (list_empty(&bond->slave_list)) {
+ if (!bond_has_slaves(bond)) {
/* this is the first slave */
return 0;
}
@@ -1196,7 +1199,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
/* The slave's address is equal to the address of the bond.
* Search for a spare address in the bond for this slave.
*/
- bond_for_each_slave(bond, tmp_slave1) {
+ bond_for_each_slave(bond, tmp_slave1, iter) {
if (!bond_slave_has_mac(bond, tmp_slave1->perm_hwaddr)) {
/* no slave has tmp_slave1's perm addr
* as its curr addr
@@ -1246,15 +1249,16 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
*/
static int alb_set_mac_address(struct bonding *bond, void *addr)
{
- char tmp_addr[ETH_ALEN];
- struct slave *slave;
+ struct slave *slave, *rollback_slave;
+ struct list_head *iter;
struct sockaddr sa;
+ char tmp_addr[ETH_ALEN];
int res;
if (bond->alb_info.rlb_enabled)
return 0;
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
/* save net_device's current hw address */
memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
@@ -1274,10 +1278,12 @@ unwind:
sa.sa_family = bond->dev->type;
/* unwind from head to the slave that failed */
- bond_for_each_slave_continue_reverse(bond, slave) {
- memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
- dev_set_mac_address(slave->dev, &sa);
- memcpy(slave->dev->dev_addr, tmp_addr, ETH_ALEN);
+ bond_for_each_slave(bond, rollback_slave, iter) {
+ if (rollback_slave == slave)
+ break;
+ memcpy(tmp_addr, rollback_slave->dev->dev_addr, ETH_ALEN);
+ dev_set_mac_address(rollback_slave->dev, &sa);
+ memcpy(rollback_slave->dev->dev_addr, tmp_addr, ETH_ALEN);
}
return res;
@@ -1458,11 +1464,12 @@ void bond_alb_monitor(struct work_struct *work)
struct bonding *bond = container_of(work, struct bonding,
alb_work.work);
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+ struct list_head *iter;
struct slave *slave;
read_lock(&bond->lock);
- if (list_empty(&bond->slave_list)) {
+ if (!bond_has_slaves(bond)) {
bond_info->tx_rebalance_counter = 0;
bond_info->lp_counter = 0;
goto re_arm;
@@ -1480,7 +1487,7 @@ void bond_alb_monitor(struct work_struct *work)
*/
read_lock(&bond->curr_slave_lock);
- bond_for_each_slave(bond, slave)
+ bond_for_each_slave(bond, slave, iter)
alb_send_learning_packets(slave, slave->dev->dev_addr);
read_unlock(&bond->curr_slave_lock);
@@ -1493,7 +1500,7 @@ void bond_alb_monitor(struct work_struct *work)
read_lock(&bond->curr_slave_lock);
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
tlb_clear_slave(bond, slave, 1);
if (slave == bond->curr_active_slave) {
SLAVE_TLB_INFO(slave).load =
@@ -1599,13 +1606,13 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave)
*/
void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave)
{
- if (!list_empty(&bond->slave_list))
+ if (bond_has_slaves(bond))
alb_change_hw_addr_on_detach(bond, slave);
tlb_clear_slave(bond, slave, 0);
if (bond->alb_info.rlb_enabled) {
- bond->alb_info.next_rx_slave = NULL;
+ bond->alb_info.rx_slave = NULL;
rlb_clear_slave(bond, slave);
}
}
@@ -1667,9 +1674,10 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
}
swap_slave = bond->curr_active_slave;
- rcu_assign_pointer(bond->curr_active_slave, new_slave);
+ rcu_assign_pointer(bond->curr_active_slave,
+ rcu_access_pointer(new_slave));
- if (!new_slave || list_empty(&bond->slave_list))
+ if (!new_slave || !bond_has_slaves(bond))
return;
/* set the new curr_active_slave to the bonds mac address
diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
index c5eff5dafdfe..4226044efd08 100644
--- a/drivers/net/bonding/bond_alb.h
+++ b/drivers/net/bonding/bond_alb.h
@@ -154,9 +154,7 @@ struct alb_bond_info {
u8 rx_ntt; /* flag - need to transmit
* to all rx clients
*/
- struct slave *next_rx_slave;/* next slave to be assigned
- * to a new rx client for
- */
+ struct slave *rx_slave;/* last slave to xmit from */
u8 primary_is_promisc; /* boolean */
u32 rlb_promisc_timeout_counter;/* counts primary
* promiscuity time
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 55bbb8b8200c..a327997fec6a 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -332,10 +332,11 @@ static int bond_vlan_rx_add_vid(struct net_device *bond_dev,
__be16 proto, u16 vid)
{
struct bonding *bond = netdev_priv(bond_dev);
- struct slave *slave;
+ struct slave *slave, *rollback_slave;
+ struct list_head *iter;
int res;
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
res = vlan_vid_add(slave->dev, proto, vid);
if (res)
goto unwind;
@@ -344,9 +345,13 @@ static int bond_vlan_rx_add_vid(struct net_device *bond_dev,
return 0;
unwind:
- /* unwind from the slave that failed */
- bond_for_each_slave_continue_reverse(bond, slave)
- vlan_vid_del(slave->dev, proto, vid);
+ /* unwind to the slave that failed */
+ bond_for_each_slave(bond, rollback_slave, iter) {
+ if (rollback_slave == slave)
+ break;
+
+ vlan_vid_del(rollback_slave->dev, proto, vid);
+ }
return res;
}
@@ -360,9 +365,10 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev,
__be16 proto, u16 vid)
{
struct bonding *bond = netdev_priv(bond_dev);
+ struct list_head *iter;
struct slave *slave;
- bond_for_each_slave(bond, slave)
+ bond_for_each_slave(bond, slave, iter)
vlan_vid_del(slave->dev, proto, vid);
if (bond_is_lb(bond))
@@ -382,15 +388,16 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev,
*/
static int bond_set_carrier(struct bonding *bond)
{
+ struct list_head *iter;
struct slave *slave;
- if (list_empty(&bond->slave_list))
+ if (!bond_has_slaves(bond))
goto down;
if (bond->params.mode == BOND_MODE_8023AD)
return bond_3ad_set_carrier(bond);
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
if (slave->link == BOND_LINK_UP) {
if (!netif_carrier_ok(bond->dev)) {
netif_carrier_on(bond->dev);
@@ -522,7 +529,9 @@ static int bond_check_dev_link(struct bonding *bond,
*/
static int bond_set_promiscuity(struct bonding *bond, int inc)
{
+ struct list_head *iter;
int err = 0;
+
if (USES_PRIMARY(bond->params.mode)) {
/* write lock already acquired */
if (bond->curr_active_slave) {
@@ -532,7 +541,7 @@ static int bond_set_promiscuity(struct bonding *bond, int inc)
} else {
struct slave *slave;
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
err = dev_set_promiscuity(slave->dev, inc);
if (err)
return err;
@@ -546,7 +555,9 @@ static int bond_set_promiscuity(struct bonding *bond, int inc)
*/
static int bond_set_allmulti(struct bonding *bond, int inc)
{
+ struct list_head *iter;
int err = 0;
+
if (USES_PRIMARY(bond->params.mode)) {
/* write lock already acquired */
if (bond->curr_active_slave) {
@@ -556,7 +567,7 @@ static int bond_set_allmulti(struct bonding *bond, int inc)
} else {
struct slave *slave;
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
err = dev_set_allmulti(slave->dev, inc);
if (err)
return err;
@@ -774,43 +785,24 @@ static bool bond_should_change_active(struct bonding *bond)
/**
* find_best_interface - select the best available slave to be the active one
* @bond: our bonding struct
- *
- * Warning: Caller must hold curr_slave_lock for writing.
*/
static struct slave *bond_find_best_slave(struct bonding *bond)
{
- struct slave *new_active, *old_active;
- struct slave *bestslave = NULL;
+ struct slave *slave, *bestslave = NULL;
+ struct list_head *iter;
int mintime = bond->params.updelay;
- int i;
- new_active = bond->curr_active_slave;
-
- if (!new_active) { /* there were no active slaves left */
- new_active = bond_first_slave(bond);
- if (!new_active)
- return NULL; /* still no slave, return NULL */
- }
-
- if ((bond->primary_slave) &&
- bond->primary_slave->link == BOND_LINK_UP &&
- bond_should_change_active(bond)) {
- new_active = bond->primary_slave;
- }
-
- /* remember where to stop iterating over the slaves */
- old_active = new_active;
-
- bond_for_each_slave_from(bond, new_active, i, old_active) {
- if (new_active->link == BOND_LINK_UP) {
- return new_active;
- } else if (new_active->link == BOND_LINK_BACK &&
- IS_UP(new_active->dev)) {
- /* link up, but waiting for stabilization */
- if (new_active->delay < mintime) {
- mintime = new_active->delay;
- bestslave = new_active;
- }
+ if (bond->primary_slave && bond->primary_slave->link == BOND_LINK_UP &&
+ bond_should_change_active(bond))
+ return bond->primary_slave;
+
+ bond_for_each_slave(bond, slave, iter) {
+ if (slave->link == BOND_LINK_UP)
+ return slave;
+ if (slave->link == BOND_LINK_BACK && IS_UP(slave->dev) &&
+ slave->delay < mintime) {
+ mintime = slave->delay;
+ bestslave = slave;
}
}
@@ -890,7 +882,8 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
if (new_active)
bond_set_slave_active_flags(new_active);
} else {
- rcu_assign_pointer(bond->curr_active_slave, new_active);
+ rcu_assign_pointer(bond->curr_active_slave,
+ rcu_access_pointer(new_active));
}
if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
@@ -980,7 +973,6 @@ void bond_select_active_slave(struct bonding *bond)
*/
static void bond_attach_slave(struct bonding *bond, struct slave *new_slave)
{
- list_add_tail_rcu(&new_slave->list, &bond->slave_list);
bond->slave_cnt++;
}
@@ -996,7 +988,6 @@ static void bond_attach_slave(struct bonding *bond, struct slave *new_slave)
*/
static void bond_detach_slave(struct bonding *bond, struct slave *slave)
{
- list_del_rcu(&slave->list);
bond->slave_cnt--;
}
@@ -1046,9 +1037,10 @@ static void bond_poll_controller(struct net_device *bond_dev)
static void bond_netpoll_cleanup(struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
+ struct list_head *iter;
struct slave *slave;
- bond_for_each_slave(bond, slave)
+ bond_for_each_slave(bond, slave, iter)
if (IS_UP(slave->dev))
slave_disable_netpoll(slave);
}
@@ -1056,10 +1048,11 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev)
static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, gfp_t gfp)
{
struct bonding *bond = netdev_priv(dev);
+ struct list_head *iter;
struct slave *slave;
int err = 0;
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
err = slave_enable_netpoll(slave);
if (err) {
bond_netpoll_cleanup(dev);
@@ -1087,10 +1080,11 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
netdev_features_t features)
{
struct bonding *bond = netdev_priv(dev);
+ struct list_head *iter;
netdev_features_t mask;
struct slave *slave;
- if (list_empty(&bond->slave_list)) {
+ if (!bond_has_slaves(bond)) {
/* Disable adding VLANs to empty bond. But why? --mq */
features |= NETIF_F_VLAN_CHALLENGED;
return features;
@@ -1100,7 +1094,7 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
features &= ~NETIF_F_ONE_FOR_ALL;
features |= NETIF_F_ALL_FOR_ALL;
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
features = netdev_increment_features(features,
slave->dev->features,
mask);
@@ -1118,16 +1112,17 @@ static void bond_compute_features(struct bonding *bond)
{
unsigned int flags, dst_release_flag = IFF_XMIT_DST_RELEASE;
netdev_features_t vlan_features = BOND_VLAN_FEATURES;
+ struct net_device *bond_dev = bond->dev;
+ struct list_head *iter;
+ struct slave *slave;
unsigned short max_hard_header_len = ETH_HLEN;
unsigned int gso_max_size = GSO_MAX_SIZE;
- struct net_device *bond_dev = bond->dev;
u16 gso_max_segs = GSO_MAX_SEGS;
- struct slave *slave;
- if (list_empty(&bond->slave_list))
+ if (!bond_has_slaves(bond))
goto done;
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
vlan_features = netdev_increment_features(vlan_features,
slave->dev->vlan_features, BOND_VLAN_FEATURES);
@@ -1233,11 +1228,12 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
}
static int bond_master_upper_dev_link(struct net_device *bond_dev,
- struct net_device *slave_dev)
+ struct net_device *slave_dev,
+ struct slave *slave)
{
int err;
- err = netdev_master_upper_dev_link(slave_dev, bond_dev);
+ err = netdev_master_upper_dev_link_private(slave_dev, bond_dev, slave);
if (err)
return err;
slave_dev->flags |= IFF_SLAVE;
@@ -1258,7 +1254,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
- struct slave *new_slave = NULL;
+ struct slave *new_slave = NULL, *prev_slave;
struct sockaddr addr;
int link_reporting;
int res = 0, i;
@@ -1313,7 +1309,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
* bond ether type mutual exclusion - don't allow slaves of dissimilar
* ether type (eg ARPHRD_ETHER and ARPHRD_INFINIBAND) share the same bond
*/
- if (list_empty(&bond->slave_list)) {
+ if (!bond_has_slaves(bond)) {
if (bond_dev->type != slave_dev->type) {
pr_debug("%s: change device type from %d to %d\n",
bond_dev->name,
@@ -1352,7 +1348,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
}
if (slave_ops->ndo_set_mac_address == NULL) {
- if (list_empty(&bond->slave_list)) {
+ if (!bond_has_slaves(bond)) {
pr_warning("%s: Warning: The first slave device specified does not support setting the MAC address. Setting fail_over_mac to active.",
bond_dev->name);
bond->params.fail_over_mac = BOND_FOM_ACTIVE;
@@ -1368,7 +1364,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
/* If this is the first slave, then we need to set the master's hardware
* address to be the same as the slave's. */
- if (list_empty(&bond->slave_list) &&
+ if (!bond_has_slaves(bond) &&
bond->dev->addr_assign_type == NET_ADDR_RANDOM)
bond_set_dev_addr(bond->dev, slave_dev);
@@ -1377,7 +1373,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
res = -ENOMEM;
goto err_undo_flags;
}
- INIT_LIST_HEAD(&new_slave->list);
/*
* Set the new_slave's queue_id to be zero. Queue ID mapping
* is set via sysfs or module option if desired.
@@ -1413,17 +1408,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
}
}
- res = bond_master_upper_dev_link(bond_dev, slave_dev);
- if (res) {
- pr_debug("Error %d calling bond_master_upper_dev_link\n", res);
- goto err_restore_mac;
- }
-
/* open the slave since the application closed it */
res = dev_open(slave_dev);
if (res) {
pr_debug("Opening slave %s failed\n", slave_dev->name);
- goto err_unset_master;
+ goto err_restore_mac;
}
new_slave->bond = bond;
@@ -1481,6 +1470,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
write_lock_bh(&bond->lock);
+ prev_slave = bond_last_slave(bond);
bond_attach_slave(bond, new_slave);
new_slave->delay = 0;
@@ -1575,9 +1565,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
*/
bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL);
} else {
- struct slave *prev_slave;
-
- prev_slave = bond_prev_slave(bond, new_slave);
SLAVE_AD_INFO(new_slave).id =
SLAVE_AD_INFO(prev_slave).id + 1;
}
@@ -1601,7 +1588,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
* so we can change it without calling change_active_interface()
*/
if (!bond->curr_active_slave && new_slave->link == BOND_LINK_UP)
- rcu_assign_pointer(bond->curr_active_slave, new_slave);
+ rcu_assign_pointer(bond->curr_active_slave,
+ rcu_access_pointer(new_slave));
break;
} /* switch(bond_mode) */
@@ -1626,17 +1614,20 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
read_unlock(&bond->lock);
- res = bond_create_slave_symlinks(bond_dev, slave_dev);
- if (res)
- goto err_detach;
-
res = netdev_rx_handler_register(slave_dev, bond_handle_frame,
new_slave);
if (res) {
pr_debug("Error %d calling netdev_rx_handler_register\n", res);
- goto err_dest_symlinks;
+ goto err_detach;
+ }
+
+ res = bond_master_upper_dev_link(bond_dev, slave_dev, new_slave);
+ if (res) {
+ pr_debug("Error %d calling bond_master_upper_dev_link\n", res);
+ goto err_unregister;
}
+
pr_info("%s: enslaving %s as a%s interface with a%s link.\n",
bond_dev->name, slave_dev->name,
bond_is_active_slave(new_slave) ? "n active" : " backup",
@@ -1646,8 +1637,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
return 0;
/* Undo stages on error */
-err_dest_symlinks:
- bond_destroy_slave_symlinks(bond_dev, slave_dev);
+err_unregister:
+ netdev_rx_handler_unregister(slave_dev);
err_detach:
if (!USES_PRIMARY(bond->params.mode))
@@ -1675,9 +1666,6 @@ err_close:
slave_dev->priv_flags &= ~IFF_BONDING;
dev_close(slave_dev);
-err_unset_master:
- bond_upper_dev_unlink(bond_dev, slave_dev);
-
err_restore_mac:
if (!bond->params.fail_over_mac) {
/* XXX TODO - fom follow mode needs to change master's
@@ -1698,7 +1686,7 @@ err_free:
err_undo_flags:
bond_compute_features(bond);
/* Enslave of first slave has failed and we need to fix master's mac */
- if (list_empty(&bond->slave_list) &&
+ if (!bond_has_slaves(bond) &&
ether_addr_equal(bond_dev->dev_addr, slave_dev->dev_addr))
eth_hw_addr_random(bond_dev);
@@ -1748,6 +1736,8 @@ static int __bond_release_one(struct net_device *bond_dev,
}
write_unlock_bh(&bond->lock);
+
+ bond_upper_dev_unlink(bond_dev, slave_dev);
/* unregister rx_handler early so bond_handle_frame wouldn't be called
* for this slave anymore.
*/
@@ -1776,7 +1766,7 @@ static int __bond_release_one(struct net_device *bond_dev,
if (!all && !bond->params.fail_over_mac) {
if (ether_addr_equal(bond_dev->dev_addr, slave->perm_hwaddr) &&
- !list_empty(&bond->slave_list))
+ bond_has_slaves(bond))
pr_warn("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s. Set the HWaddr of %s to a different address to avoid conflicts.\n",
bond_dev->name, slave_dev->name,
slave->perm_hwaddr,
@@ -1801,7 +1791,7 @@ static int __bond_release_one(struct net_device *bond_dev,
}
if (all) {
- rcu_assign_pointer(bond->curr_active_slave, NULL);
+ RCU_INIT_POINTER(bond->curr_active_slave, NULL);
} else if (oldcurrent == slave) {
/*
* Note that we hold RTNL over this sequence, so there
@@ -1819,7 +1809,7 @@ static int __bond_release_one(struct net_device *bond_dev,
write_lock_bh(&bond->lock);
}
- if (list_empty(&bond->slave_list)) {
+ if (!bond_has_slaves(bond)) {
bond_set_carrier(bond);
eth_hw_addr_random(bond_dev);
@@ -1835,7 +1825,7 @@ static int __bond_release_one(struct net_device *bond_dev,
unblock_netpoll_tx();
synchronize_rcu();
- if (list_empty(&bond->slave_list)) {
+ if (!bond_has_slaves(bond)) {
call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev);
call_netdevice_notifiers(NETDEV_RELEASE, bond->dev);
}
@@ -1847,8 +1837,6 @@ static int __bond_release_one(struct net_device *bond_dev,
bond_dev->name, slave_dev->name, bond_dev->name);
/* must do this from outside any spinlocks */
- bond_destroy_slave_symlinks(bond_dev, slave_dev);
-
vlan_vids_del_by_dev(slave_dev, bond_dev);
/* If the mode USES_PRIMARY, then this cases was handled above by
@@ -1866,8 +1854,6 @@ static int __bond_release_one(struct net_device *bond_dev,
bond_hw_addr_flush(bond_dev, slave_dev);
}
- bond_upper_dev_unlink(bond_dev, slave_dev);
-
slave_disable_netpoll(slave);
/* close slave before restoring its mac address */
@@ -1906,7 +1892,7 @@ static int bond_release_and_destroy(struct net_device *bond_dev,
int ret;
ret = bond_release(bond_dev, slave_dev);
- if (ret == 0 && list_empty(&bond->slave_list)) {
+ if (ret == 0 && !bond_has_slaves(bond)) {
bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
pr_info("%s: destroying bond %s.\n",
bond_dev->name, bond_dev->name);
@@ -1987,11 +1973,12 @@ static int bond_info_query(struct net_device *bond_dev, struct ifbond *info)
static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *info)
{
struct bonding *bond = netdev_priv(bond_dev);
+ struct list_head *iter;
int i = 0, res = -ENODEV;
struct slave *slave;
read_lock(&bond->lock);
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
if (i++ == (int)info->slave_id) {
res = 0;
strcpy(info->slave_name, slave->dev->name);
@@ -2012,12 +1999,13 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
static int bond_miimon_inspect(struct bonding *bond)
{
int link_state, commit = 0;
+ struct list_head *iter;
struct slave *slave;
bool ignore_updelay;
ignore_updelay = !bond->curr_active_slave ? true : false;
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
slave->new_link = BOND_LINK_NOCHANGE;
link_state = bond_check_dev_link(bond, slave->dev, 0);
@@ -2111,9 +2099,10 @@ static int bond_miimon_inspect(struct bonding *bond)
static void bond_miimon_commit(struct bonding *bond)
{
+ struct list_head *iter;
struct slave *slave;
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
switch (slave->new_link) {
case BOND_LINK_NOCHANGE:
continue;
@@ -2218,7 +2207,7 @@ void bond_mii_monitor(struct work_struct *work)
delay = msecs_to_jiffies(bond->params.miimon);
- if (list_empty(&bond->slave_list))
+ if (!bond_has_slaves(bond))
goto re_arm;
should_notify_peers = bond_should_notify_peers(bond);
@@ -2267,7 +2256,7 @@ static bool bond_has_this_ip(struct bonding *bond, __be32 ip)
return true;
rcu_read_lock();
- netdev_for_each_upper_dev_rcu(bond->dev, upper, iter) {
+ netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
if (ip == bond_confirm_addr(upper, 0, ip)) {
ret = true;
break;
@@ -2342,10 +2331,12 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
*
* TODO: QinQ?
*/
- netdev_for_each_upper_dev_rcu(bond->dev, vlan_upper, vlan_iter) {
+ netdev_for_each_all_upper_dev_rcu(bond->dev, vlan_upper,
+ vlan_iter) {
if (!is_vlan_dev(vlan_upper))
continue;
- netdev_for_each_upper_dev_rcu(vlan_upper, upper, iter) {
+ netdev_for_each_all_upper_dev_rcu(vlan_upper, upper,
+ iter) {
if (upper == rt->dst.dev) {
vlan_id = vlan_dev_vlan_id(vlan_upper);
rcu_read_unlock();
@@ -2358,7 +2349,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
* our upper vlans, then just search for any dev that
* matches, and in case it's a vlan - save the id
*/
- netdev_for_each_upper_dev_rcu(bond->dev, upper, iter) {
+ netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
if (upper == rt->dst.dev) {
/* if it's a vlan - get its VID */
if (is_vlan_dev(upper))
@@ -2505,11 +2496,12 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
struct bonding *bond = container_of(work, struct bonding,
arp_work.work);
struct slave *slave, *oldcurrent;
+ struct list_head *iter;
int do_failover = 0;
read_lock(&bond->lock);
- if (list_empty(&bond->slave_list))
+ if (!bond_has_slaves(bond))
goto re_arm;
oldcurrent = bond->curr_active_slave;
@@ -2521,7 +2513,7 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
* TODO: what about up/down delay in arp mode? it wasn't here before
* so it can wait
*/
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
unsigned long trans_start = dev_trans_start(slave->dev);
if (slave->link != BOND_LINK_UP) {
@@ -2612,10 +2604,11 @@ re_arm:
static int bond_ab_arp_inspect(struct bonding *bond)
{
unsigned long trans_start, last_rx;
+ struct list_head *iter;
struct slave *slave;
int commit = 0;
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
slave->new_link = BOND_LINK_NOCHANGE;
last_rx = slave_last_rx(bond, slave);
@@ -2682,9 +2675,10 @@ static int bond_ab_arp_inspect(struct bonding *bond)
static void bond_ab_arp_commit(struct bonding *bond)
{
unsigned long trans_start;
+ struct list_head *iter;
struct slave *slave;
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
switch (slave->new_link) {
case BOND_LINK_NOCHANGE:
continue;
@@ -2755,8 +2749,9 @@ do_failover:
*/
static void bond_ab_arp_probe(struct bonding *bond)
{
- struct slave *slave, *next_slave;
- int i;
+ struct slave *slave, *before = NULL, *new_slave = NULL;
+ struct list_head *iter;
+ bool found = false;
read_lock(&bond->curr_slave_lock);
@@ -2786,18 +2781,12 @@ static void bond_ab_arp_probe(struct bonding *bond)
bond_set_slave_inactive_flags(bond->current_arp_slave);
- /* search for next candidate */
- next_slave = bond_next_slave(bond, bond->current_arp_slave);
- bond_for_each_slave_from(bond, slave, i, next_slave) {
- if (IS_UP(slave->dev)) {
- slave->link = BOND_LINK_BACK;
- bond_set_slave_active_flags(slave);
- bond_arp_send_all(bond, slave);
- slave->jiffies = jiffies;
- bond->current_arp_slave = slave;
- break;
- }
+ bond_for_each_slave(bond, slave, iter) {
+ if (!found && !before && IS_UP(slave->dev))
+ before = slave;
+ if (found && !new_slave && IS_UP(slave->dev))
+ new_slave = slave;
/* if the link state is up at this point, we
* mark it down - this can happen if we have
* simultaneous link failures and
@@ -2805,7 +2794,7 @@ static void bond_ab_arp_probe(struct bonding *bond)
* one the current slave so it is still marked
* up when it is actually down
*/
- if (slave->link == BOND_LINK_UP) {
+ if (!IS_UP(slave->dev) && slave->link == BOND_LINK_UP) {
slave->link = BOND_LINK_DOWN;
if (slave->link_failure_count < UINT_MAX)
slave->link_failure_count++;
@@ -2815,7 +2804,22 @@ static void bond_ab_arp_probe(struct bonding *bond)
pr_info("%s: backup interface %s is now down.\n",
bond->dev->name, slave->dev->name);
}
+ if (slave == bond->current_arp_slave)
+ found = true;
}
+
+ if (!new_slave && before)
+ new_slave = before;
+
+ if (!new_slave)
+ return;
+
+ new_slave->link = BOND_LINK_BACK;
+ bond_set_slave_active_flags(new_slave);
+ bond_arp_send_all(bond, new_slave);
+ new_slave->jiffies = jiffies;
+ bond->current_arp_slave = new_slave;
+
}
void bond_activebackup_arp_mon(struct work_struct *work)
@@ -2829,7 +2833,7 @@ void bond_activebackup_arp_mon(struct work_struct *work)
delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval);
- if (list_empty(&bond->slave_list))
+ if (!bond_has_slaves(bond))
goto re_arm;
should_notify_peers = bond_should_notify_peers(bond);
@@ -3148,13 +3152,14 @@ static void bond_work_cancel_all(struct bonding *bond)
static int bond_open(struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
+ struct list_head *iter;
struct slave *slave;
/* reset slave->backup and slave->inactive */
read_lock(&bond->lock);
- if (!list_empty(&bond->slave_list)) {
+ if (bond_has_slaves(bond)) {
read_lock(&bond->curr_slave_lock);
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP)
&& (slave != bond->curr_active_slave)) {
bond_set_slave_inactive_flags(slave);
@@ -3214,12 +3219,13 @@ static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev,
{
struct bonding *bond = netdev_priv(bond_dev);
struct rtnl_link_stats64 temp;
+ struct list_head *iter;
struct slave *slave;
memset(stats, 0, sizeof(*stats));
read_lock_bh(&bond->lock);
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
const struct rtnl_link_stats64 *sstats =
dev_get_stats(slave->dev, &temp);
@@ -3386,6 +3392,7 @@ static void bond_change_rx_flags(struct net_device *bond_dev, int change)
static void bond_set_rx_mode(struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
+ struct list_head *iter;
struct slave *slave;
ASSERT_RTNL();
@@ -3397,7 +3404,7 @@ static void bond_set_rx_mode(struct net_device *bond_dev)
dev_mc_sync(slave->dev, bond_dev);
}
} else {
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
dev_uc_sync_multiple(slave->dev, bond_dev);
dev_mc_sync_multiple(slave->dev, bond_dev);
}
@@ -3464,7 +3471,8 @@ static int bond_neigh_setup(struct net_device *dev,
static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
{
struct bonding *bond = netdev_priv(bond_dev);
- struct slave *slave;
+ struct slave *slave, *rollback_slave;
+ struct list_head *iter;
int res = 0;
pr_debug("bond=%p, name=%s, new_mtu=%d\n", bond,
@@ -3485,10 +3493,9 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
* call to the base driver.
*/
- bond_for_each_slave(bond, slave) {
- pr_debug("s %p s->p %p c_m %p\n",
+ bond_for_each_slave(bond, slave, iter) {
+ pr_debug("s %p c_m %p\n",
slave,
- bond_prev_slave(bond, slave),
slave->dev->netdev_ops->ndo_change_mtu);
res = dev_set_mtu(slave->dev, new_mtu);
@@ -3513,13 +3520,16 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
unwind:
/* unwind from head to the slave that failed */
- bond_for_each_slave_continue_reverse(bond, slave) {
+ bond_for_each_slave(bond, rollback_slave, iter) {
int tmp_res;
- tmp_res = dev_set_mtu(slave->dev, bond_dev->mtu);
+ if (rollback_slave == slave)
+ break;
+
+ tmp_res = dev_set_mtu(rollback_slave->dev, bond_dev->mtu);
if (tmp_res) {
pr_debug("unwind err %d dev %s\n",
- tmp_res, slave->dev->name);
+ tmp_res, rollback_slave->dev->name);
}
}
@@ -3536,8 +3546,9 @@ unwind:
static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
{
struct bonding *bond = netdev_priv(bond_dev);
+ struct slave *slave, *rollback_slave;
struct sockaddr *sa = addr, tmp_sa;
- struct slave *slave;
+ struct list_head *iter;
int res = 0;
if (bond->params.mode == BOND_MODE_ALB)
@@ -3571,7 +3582,7 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
* call to the base driver.
*/
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
const struct net_device_ops *slave_ops = slave->dev->netdev_ops;
pr_debug("slave %p %s\n", slave, slave->dev->name);
@@ -3603,13 +3614,16 @@ unwind:
tmp_sa.sa_family = bond_dev->type;
/* unwind from head to the slave that failed */
- bond_for_each_slave_continue_reverse(bond, slave) {
+ bond_for_each_slave(bond, rollback_slave, iter) {
int tmp_res;
- tmp_res = dev_set_mac_address(slave->dev, &tmp_sa);
+ if (rollback_slave == slave)
+ break;
+
+ tmp_res = dev_set_mac_address(rollback_slave->dev, &tmp_sa);
if (tmp_res) {
pr_debug("unwind err %d dev %s\n",
- tmp_res, slave->dev->name);
+ tmp_res, rollback_slave->dev->name);
}
}
@@ -3628,11 +3642,12 @@ unwind:
*/
void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int slave_id)
{
+ struct list_head *iter;
struct slave *slave;
int i = slave_id;
/* Here we start from the slave with slave_id */
- bond_for_each_slave_rcu(bond, slave) {
+ bond_for_each_slave_rcu(bond, slave, iter) {
if (--i < 0) {
if (slave_can_tx(slave)) {
bond_dev_queue_xmit(bond, skb, slave->dev);
@@ -3643,7 +3658,7 @@ void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int slave_id)
/* Here we start from the first slave up to slave_id */
i = slave_id;
- bond_for_each_slave_rcu(bond, slave) {
+ bond_for_each_slave_rcu(bond, slave, iter) {
if (--i < 0)
break;
if (slave_can_tx(slave)) {
@@ -3720,8 +3735,9 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave = NULL;
+ struct list_head *iter;
- bond_for_each_slave_rcu(bond, slave) {
+ bond_for_each_slave_rcu(bond, slave, iter) {
if (bond_is_last_slave(bond, slave))
break;
if (IS_UP(slave->dev) && slave->link == BOND_LINK_UP) {
@@ -3770,13 +3786,14 @@ static inline int bond_slave_override(struct bonding *bond,
{
struct slave *slave = NULL;
struct slave *check_slave;
+ struct list_head *iter;
int res = 1;
if (!skb->queue_mapping)
return 1;
/* Find out if any slaves have the same mapping as this skb. */
- bond_for_each_slave_rcu(bond, check_slave) {
+ bond_for_each_slave_rcu(bond, check_slave, iter) {
if (check_slave->queue_id == skb->queue_mapping) {
slave = check_slave;
break;
@@ -3862,7 +3879,7 @@ static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_BUSY;
rcu_read_lock();
- if (!list_empty(&bond->slave_list))
+ if (bond_has_slaves(bond))
ret = __bond_start_xmit(skb, dev);
else
kfree_skb(skb);
@@ -3908,6 +3925,7 @@ static int bond_ethtool_get_settings(struct net_device *bond_dev,
{
struct bonding *bond = netdev_priv(bond_dev);
unsigned long speed = 0;
+ struct list_head *iter;
struct slave *slave;
ecmd->duplex = DUPLEX_UNKNOWN;
@@ -3919,7 +3937,7 @@ static int bond_ethtool_get_settings(struct net_device *bond_dev,
* this is an accurate maximum.
*/
read_lock(&bond->lock);
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
if (SLAVE_IS_OK(slave)) {
if (slave->speed != SPEED_UNKNOWN)
speed += slave->speed;
@@ -3994,7 +4012,6 @@ static void bond_setup(struct net_device *bond_dev)
/* initialize rwlocks */
rwlock_init(&bond->lock);
rwlock_init(&bond->curr_slave_lock);
- INIT_LIST_HEAD(&bond->slave_list);
bond->params = bonding_defaults;
/* Initialize pointers */
@@ -4050,12 +4067,13 @@ static void bond_setup(struct net_device *bond_dev)
static void bond_uninit(struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
- struct slave *slave, *tmp_slave;
+ struct list_head *iter;
+ struct slave *slave;
bond_netpoll_cleanup(bond_dev);
/* Release the bonded slaves */
- list_for_each_entry_safe(slave, tmp_slave, &bond->slave_list, list)
+ bond_for_each_slave(bond, slave, iter)
__bond_release_one(bond_dev, slave->dev, true);
pr_info("%s: released all slaves\n", bond_dev->name);
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
index 20a6ee25bb63..7af5646e4410 100644
--- a/drivers/net/bonding/bond_procfs.c
+++ b/drivers/net/bonding/bond_procfs.c
@@ -10,8 +10,9 @@ static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(&bond->lock)
{
struct bonding *bond = seq->private;
- loff_t off = 0;
+ struct list_head *iter;
struct slave *slave;
+ loff_t off = 0;
/* make sure the bond won't be taken away */
rcu_read_lock();
@@ -20,7 +21,7 @@ static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
if (*pos == 0)
return SEQ_START_TOKEN;
- bond_for_each_slave(bond, slave)
+ bond_for_each_slave(bond, slave, iter)
if (++off == *pos)
return slave;
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index c29b836749b6..6f5f41387615 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -149,14 +149,6 @@ err_no_cmd:
return -EPERM;
}
-static const void *bonding_namespace(struct class *cls,
- const struct class_attribute *attr)
-{
- const struct bond_net *bn =
- container_of(attr, struct bond_net, class_attr_bonding_masters);
- return bn->net;
-}
-
/* class attribute for bond_masters file. This ends up in /sys/class/net */
static const struct class_attribute class_attr_bonding_masters = {
.attr = {
@@ -165,44 +157,8 @@ static const struct class_attribute class_attr_bonding_masters = {
},
.show = bonding_show_bonds,
.store = bonding_store_bonds,
- .namespace = bonding_namespace,
};
-int bond_create_slave_symlinks(struct net_device *master,
- struct net_device *slave)
-{
- char linkname[IFNAMSIZ+7];
- int ret = 0;
-
- /* first, create a link from the slave back to the master */
- ret = sysfs_create_link(&(slave->dev.kobj), &(master->dev.kobj),
- "master");
- if (ret)
- return ret;
- /* next, create a link from the master to the slave */
- sprintf(linkname, "slave_%s", slave->name);
- ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj),
- linkname);
-
- /* free the master link created earlier in case of error */
- if (ret)
- sysfs_remove_link(&(slave->dev.kobj), "master");
-
- return ret;
-
-}
-
-void bond_destroy_slave_symlinks(struct net_device *master,
- struct net_device *slave)
-{
- char linkname[IFNAMSIZ+7];
-
- sysfs_remove_link(&(slave->dev.kobj), "master");
- sprintf(linkname, "slave_%s", slave->name);
- sysfs_remove_link(&(master->dev.kobj), linkname);
-}
-
-
/*
* Show the slaves in the current bond.
*/
@@ -210,11 +166,12 @@ static ssize_t bonding_show_slaves(struct device *d,
struct device_attribute *attr, char *buf)
{
struct bonding *bond = to_bond(d);
+ struct list_head *iter;
struct slave *slave;
int res = 0;
read_lock(&bond->lock);
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
if (res > (PAGE_SIZE - IFNAMSIZ)) {
/* not enough space for another interface name */
if ((PAGE_SIZE - res) > 10)
@@ -326,7 +283,7 @@ static ssize_t bonding_store_mode(struct device *d,
goto out;
}
- if (!list_empty(&bond->slave_list)) {
+ if (bond_has_slaves(bond)) {
pr_err("unable to update mode of %s because it has slaves.\n",
bond->dev->name);
ret = -EPERM;
@@ -522,7 +479,7 @@ static ssize_t bonding_store_fail_over_mac(struct device *d,
if (!rtnl_trylock())
return restart_syscall();
- if (!list_empty(&bond->slave_list)) {
+ if (bond_has_slaves(bond)) {
pr_err("%s: Can't alter fail_over_mac with slaves in bond.\n",
bond->dev->name);
ret = -EPERM;
@@ -656,6 +613,7 @@ static ssize_t bonding_store_arp_targets(struct device *d,
const char *buf, size_t count)
{
struct bonding *bond = to_bond(d);
+ struct list_head *iter;
struct slave *slave;
__be32 newtarget, *targets;
unsigned long *targets_rx;
@@ -688,7 +646,7 @@ static ssize_t bonding_store_arp_targets(struct device *d,
&newtarget);
/* not to race with bond_arp_rcv */
write_lock_bh(&bond->lock);
- bond_for_each_slave(bond, slave)
+ bond_for_each_slave(bond, slave, iter)
slave->target_last_arp_rx[ind] = jiffies;
targets[ind] = newtarget;
write_unlock_bh(&bond->lock);
@@ -714,7 +672,7 @@ static ssize_t bonding_store_arp_targets(struct device *d,
&newtarget);
write_lock_bh(&bond->lock);
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
targets_rx = slave->target_last_arp_rx;
j = ind;
for (; (j < BOND_MAX_ARP_TARGETS-1) && targets[j+1]; j++)
@@ -1111,6 +1069,7 @@ static ssize_t bonding_store_primary(struct device *d,
const char *buf, size_t count)
{
struct bonding *bond = to_bond(d);
+ struct list_head *iter;
char ifname[IFNAMSIZ];
struct slave *slave;
@@ -1138,7 +1097,7 @@ static ssize_t bonding_store_primary(struct device *d,
goto out;
}
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
if (strncmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
pr_info("%s: Setting %s as primary slave.\n",
bond->dev->name, slave->dev->name);
@@ -1286,6 +1245,7 @@ static ssize_t bonding_store_active_slave(struct device *d,
{
struct slave *slave, *old_active, *new_active;
struct bonding *bond = to_bond(d);
+ struct list_head *iter;
char ifname[IFNAMSIZ];
if (!rtnl_trylock())
@@ -1313,7 +1273,7 @@ static ssize_t bonding_store_active_slave(struct device *d,
goto out;
}
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
if (strncmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
old_active = bond->curr_active_slave;
new_active = slave;
@@ -1493,6 +1453,7 @@ static ssize_t bonding_show_queue_id(struct device *d,
char *buf)
{
struct bonding *bond = to_bond(d);
+ struct list_head *iter;
struct slave *slave;
int res = 0;
@@ -1500,7 +1461,7 @@ static ssize_t bonding_show_queue_id(struct device *d,
return restart_syscall();
read_lock(&bond->lock);
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
if (res > (PAGE_SIZE - IFNAMSIZ - 6)) {
/* not enough space for another interface_name:queue_id pair */
if ((PAGE_SIZE - res) > 10)
@@ -1529,6 +1490,7 @@ static ssize_t bonding_store_queue_id(struct device *d,
{
struct slave *slave, *update_slave;
struct bonding *bond = to_bond(d);
+ struct list_head *iter;
u16 qid;
int ret = count;
char *delim;
@@ -1565,7 +1527,7 @@ static ssize_t bonding_store_queue_id(struct device *d,
/* Search for thes slave and check for duplicate qids */
update_slave = NULL;
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
if (sdev == slave->dev)
/*
* We don't need to check the matching
@@ -1619,6 +1581,7 @@ static ssize_t bonding_store_slaves_active(struct device *d,
{
struct bonding *bond = to_bond(d);
int new_value, ret = count;
+ struct list_head *iter;
struct slave *slave;
if (sscanf(buf, "%d", &new_value) != 1) {
@@ -1641,7 +1604,7 @@ static ssize_t bonding_store_slaves_active(struct device *d,
}
read_lock(&bond->lock);
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
if (!bond_is_active_slave(slave)) {
if (new_value)
slave->inactive = 0;
@@ -1787,7 +1750,8 @@ int bond_create_sysfs(struct bond_net *bn)
bn->class_attr_bonding_masters = class_attr_bonding_masters;
sysfs_attr_init(&bn->class_attr_bonding_masters.attr);
- ret = netdev_class_create_file(&bn->class_attr_bonding_masters);
+ ret = netdev_class_create_file_ns(&bn->class_attr_bonding_masters,
+ bn->net);
/*
* Permit multiple loads of the module by ignoring failures to
* create the bonding_masters sysfs file. Bonding devices
@@ -1817,7 +1781,7 @@ int bond_create_sysfs(struct bond_net *bn)
*/
void bond_destroy_sysfs(struct bond_net *bn)
{
- netdev_class_remove_file(&bn->class_attr_bonding_masters);
+ netdev_class_remove_file_ns(&bn->class_attr_bonding_masters, bn->net);
}
/*
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 03cf3fd14490..5b71601666cd 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -72,63 +72,40 @@
res; })
/* slave list primitives */
-#define bond_to_slave(ptr) list_entry(ptr, struct slave, list)
+#define bond_slave_list(bond) (&(bond)->dev->adj_list.lower)
+
+#define bond_has_slaves(bond) !list_empty(bond_slave_list(bond))
/* IMPORTANT: bond_first/last_slave can return NULL in case of an empty list */
#define bond_first_slave(bond) \
- list_first_entry_or_null(&(bond)->slave_list, struct slave, list)
+ (bond_has_slaves(bond) ? \
+ netdev_adjacent_get_private(bond_slave_list(bond)->next) : \
+ NULL)
#define bond_last_slave(bond) \
- (list_empty(&(bond)->slave_list) ? NULL : \
- bond_to_slave((bond)->slave_list.prev))
+ (bond_has_slaves(bond) ? \
+ netdev_adjacent_get_private(bond_slave_list(bond)->prev) : \
+ NULL)
-#define bond_is_first_slave(bond, pos) ((pos)->list.prev == &(bond)->slave_list)
-#define bond_is_last_slave(bond, pos) ((pos)->list.next == &(bond)->slave_list)
+#define bond_is_first_slave(bond, pos) (pos == bond_first_slave(bond))
+#define bond_is_last_slave(bond, pos) (pos == bond_last_slave(bond))
/* Since bond_first/last_slave can return NULL, these can return NULL too */
-#define bond_next_slave(bond, pos) \
- (bond_is_last_slave(bond, pos) ? bond_first_slave(bond) : \
- bond_to_slave((pos)->list.next))
-
-#define bond_prev_slave(bond, pos) \
- (bond_is_first_slave(bond, pos) ? bond_last_slave(bond) : \
- bond_to_slave((pos)->list.prev))
-
-/**
- * bond_for_each_slave_from - iterate the slaves list from a starting point
- * @bond: the bond holding this list.
- * @pos: current slave.
- * @cnt: counter for max number of moves
- * @start: starting point.
- *
- * Caller must hold bond->lock
- */
-#define bond_for_each_slave_from(bond, pos, cnt, start) \
- for (cnt = 0, pos = start; pos && cnt < (bond)->slave_cnt; \
- cnt++, pos = bond_next_slave(bond, pos))
+#define bond_next_slave(bond, pos) __bond_next_slave(bond, pos)
/**
* bond_for_each_slave - iterate over all slaves
* @bond: the bond holding this list
* @pos: current slave
+ * @iter: list_head * iterator
*
* Caller must hold bond->lock
*/
-#define bond_for_each_slave(bond, pos) \
- list_for_each_entry(pos, &(bond)->slave_list, list)
+#define bond_for_each_slave(bond, pos, iter) \
+ netdev_for_each_lower_private((bond)->dev, pos, iter)
/* Caller must have rcu_read_lock */
-#define bond_for_each_slave_rcu(bond, pos) \
- list_for_each_entry_rcu(pos, &(bond)->slave_list, list)
-
-/**
- * bond_for_each_slave_reverse - iterate in reverse from a given position
- * @bond: the bond holding this list
- * @pos: slave to continue from
- *
- * Caller must hold bond->lock
- */
-#define bond_for_each_slave_continue_reverse(bond, pos) \
- list_for_each_entry_continue_reverse(pos, &(bond)->slave_list, list)
+#define bond_for_each_slave_rcu(bond, pos, iter) \
+ netdev_for_each_lower_private_rcu((bond)->dev, pos, iter)
#ifdef CONFIG_NET_POLL_CONTROLLER
extern atomic_t netpoll_block_tx;
@@ -188,7 +165,6 @@ struct bond_parm_tbl {
struct slave {
struct net_device *dev; /* first - useful for panic debug */
- struct list_head list;
struct bonding *bond; /* our master */
int delay;
unsigned long jiffies;
@@ -228,7 +204,6 @@ struct slave {
*/
struct bonding {
struct net_device *dev; /* first - useful for panic debug */
- struct list_head slave_list;
struct slave *curr_active_slave;
struct slave *current_arp_slave;
struct slave *primary_slave;
@@ -269,6 +244,34 @@ struct bonding {
((struct slave *) rtnl_dereference(dev->rx_handler_data))
/**
+ * __bond_next_slave - get the next slave after the one provided
+ * @bond - bonding struct
+ * @slave - the slave provided
+ *
+ * Returns the next slave after the slave provided, first slave if the
+ * slave provided is the last slave and NULL if slave is not found
+ */
+static inline struct slave *__bond_next_slave(struct bonding *bond,
+ struct slave *slave)
+{
+ struct slave *slave_iter;
+ struct list_head *iter;
+ bool found = false;
+
+ netdev_for_each_lower_private(bond->dev, slave_iter, iter) {
+ if (found)
+ return slave_iter;
+ if (slave_iter == slave)
+ found = true;
+ }
+
+ if (found)
+ return bond_first_slave(bond);
+
+ return NULL;
+}
+
+/**
* Returns NULL if the net_device does not belong to any of the bond's slaves
*
* Caller must hold bond lock for read
@@ -276,13 +279,7 @@ struct bonding {
static inline struct slave *bond_get_slave_by_dev(struct bonding *bond,
struct net_device *slave_dev)
{
- struct slave *slave = NULL;
-
- bond_for_each_slave(bond, slave)
- if (slave->dev == slave_dev)
- return slave;
-
- return NULL;
+ return netdev_lower_dev_get_private(bond->dev, slave_dev);
}
static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
@@ -439,8 +436,6 @@ int bond_create(struct net *net, const char *name);
int bond_create_sysfs(struct bond_net *net);
void bond_destroy_sysfs(struct bond_net *net);
void bond_prepare_sysfs_group(struct bonding *bond);
-int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave);
-void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev);
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
void bond_mii_monitor(struct work_struct *);
@@ -492,9 +487,10 @@ static inline void bond_destroy_proc_dir(struct bond_net *bn)
static inline struct slave *bond_slave_has_mac(struct bonding *bond,
const u8 *mac)
{
+ struct list_head *iter;
struct slave *tmp;
- bond_for_each_slave(bond, tmp)
+ bond_for_each_slave(bond, tmp, iter)
if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr))
return tmp;
diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h
index 9c24d60a23b1..e98abb97a050 100644
--- a/drivers/net/can/mscan/mscan.h
+++ b/drivers/net/can/mscan/mscan.h
@@ -297,8 +297,8 @@ struct mscan_priv {
struct napi_struct napi;
};
-extern struct net_device *alloc_mscandev(void);
-extern int register_mscandev(struct net_device *dev, int mscan_clksrc);
-extern void unregister_mscandev(struct net_device *dev);
+struct net_device *alloc_mscandev(void);
+int register_mscandev(struct net_device *dev, int mscan_clksrc);
+void unregister_mscandev(struct net_device *dev);
#endif /* __MSCAN_H__ */
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index 874188ba06f7..25377e547f9b 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -76,6 +76,10 @@ MODULE_PARM_DESC(maxdev, "Maximum number of slcan interfaces");
/* maximum rx buffer len: extended CAN frame with timestamp */
#define SLC_MTU (sizeof("T1111222281122334455667788EA5F\r")+1)
+#define SLC_CMD_LEN 1
+#define SLC_SFF_ID_LEN 3
+#define SLC_EFF_ID_LEN 8
+
struct slcan {
int magic;
@@ -142,47 +146,63 @@ static void slc_bump(struct slcan *sl)
{
struct sk_buff *skb;
struct can_frame cf;
- int i, dlc_pos, tmp;
- unsigned long ultmp;
- char cmd = sl->rbuff[0];
-
- if ((cmd != 't') && (cmd != 'T') && (cmd != 'r') && (cmd != 'R'))
+ int i, tmp;
+ u32 tmpid;
+ char *cmd = sl->rbuff;
+
+ cf.can_id = 0;
+
+ switch (*cmd) {
+ case 'r':
+ cf.can_id = CAN_RTR_FLAG;
+ /* fallthrough */
+ case 't':
+ /* store dlc ASCII value and terminate SFF CAN ID string */
+ cf.can_dlc = sl->rbuff[SLC_CMD_LEN + SLC_SFF_ID_LEN];
+ sl->rbuff[SLC_CMD_LEN + SLC_SFF_ID_LEN] = 0;
+ /* point to payload data behind the dlc */
+ cmd += SLC_CMD_LEN + SLC_SFF_ID_LEN + 1;
+ break;
+ case 'R':
+ cf.can_id = CAN_RTR_FLAG;
+ /* fallthrough */
+ case 'T':
+ cf.can_id |= CAN_EFF_FLAG;
+ /* store dlc ASCII value and terminate EFF CAN ID string */
+ cf.can_dlc = sl->rbuff[SLC_CMD_LEN + SLC_EFF_ID_LEN];
+ sl->rbuff[SLC_CMD_LEN + SLC_EFF_ID_LEN] = 0;
+ /* point to payload data behind the dlc */
+ cmd += SLC_CMD_LEN + SLC_EFF_ID_LEN + 1;
+ break;
+ default:
return;
+ }
- if (cmd & 0x20) /* tiny chars 'r' 't' => standard frame format */
- dlc_pos = 4; /* dlc position tiiid */
- else
- dlc_pos = 9; /* dlc position Tiiiiiiiid */
-
- if (!((sl->rbuff[dlc_pos] >= '0') && (sl->rbuff[dlc_pos] < '9')))
+ if (kstrtou32(sl->rbuff + SLC_CMD_LEN, 16, &tmpid))
return;
- cf.can_dlc = sl->rbuff[dlc_pos] - '0'; /* get can_dlc from ASCII val */
+ cf.can_id |= tmpid;
- sl->rbuff[dlc_pos] = 0; /* terminate can_id string */
-
- if (kstrtoul(sl->rbuff+1, 16, &ultmp))
+ /* get can_dlc from sanitized ASCII value */
+ if (cf.can_dlc >= '0' && cf.can_dlc < '9')
+ cf.can_dlc -= '0';
+ else
return;
- cf.can_id = ultmp;
-
- if (!(cmd & 0x20)) /* NO tiny chars => extended frame format */
- cf.can_id |= CAN_EFF_FLAG;
-
- if ((cmd | 0x20) == 'r') /* RTR frame */
- cf.can_id |= CAN_RTR_FLAG;
-
*(u64 *) (&cf.data) = 0; /* clear payload */
- for (i = 0, dlc_pos++; i < cf.can_dlc; i++) {
- tmp = hex_to_bin(sl->rbuff[dlc_pos++]);
- if (tmp < 0)
- return;
- cf.data[i] = (tmp << 4);
- tmp = hex_to_bin(sl->rbuff[dlc_pos++]);
- if (tmp < 0)
- return;
- cf.data[i] |= tmp;
+ /* RTR frames may have a dlc > 0 but they never have any data bytes */
+ if (!(cf.can_id & CAN_RTR_FLAG)) {
+ for (i = 0; i < cf.can_dlc; i++) {
+ tmp = hex_to_bin(*cmd++);
+ if (tmp < 0)
+ return;
+ cf.data[i] = (tmp << 4);
+ tmp = hex_to_bin(*cmd++);
+ if (tmp < 0)
+ return;
+ cf.data[i] |= tmp;
+ }
}
skb = dev_alloc_skb(sizeof(struct can_frame) +
@@ -209,7 +229,6 @@ static void slc_bump(struct slcan *sl)
/* parse tty input stream */
static void slcan_unesc(struct slcan *sl, unsigned char s)
{
-
if ((s == '\r') || (s == '\a')) { /* CR or BEL ends the pdu */
if (!test_and_clear_bit(SLF_ERROR, &sl->flags) &&
(sl->rcount > 4)) {
@@ -236,27 +255,46 @@ static void slcan_unesc(struct slcan *sl, unsigned char s)
/* Encapsulate one can_frame and stuff into a TTY queue. */
static void slc_encaps(struct slcan *sl, struct can_frame *cf)
{
- int actual, idx, i;
- char cmd;
+ int actual, i;
+ unsigned char *pos;
+ unsigned char *endpos;
+ canid_t id = cf->can_id;
+
+ pos = sl->xbuff;
if (cf->can_id & CAN_RTR_FLAG)
- cmd = 'R'; /* becomes 'r' in standard frame format */
+ *pos = 'R'; /* becomes 'r' in standard frame format (SFF) */
else
- cmd = 'T'; /* becomes 't' in standard frame format */
+ *pos = 'T'; /* becomes 't' in standard frame format (SSF) */
- if (cf->can_id & CAN_EFF_FLAG)
- sprintf(sl->xbuff, "%c%08X%d", cmd,
- cf->can_id & CAN_EFF_MASK, cf->can_dlc);
- else
- sprintf(sl->xbuff, "%c%03X%d", cmd | 0x20,
- cf->can_id & CAN_SFF_MASK, cf->can_dlc);
+ /* determine number of chars for the CAN-identifier */
+ if (cf->can_id & CAN_EFF_FLAG) {
+ id &= CAN_EFF_MASK;
+ endpos = pos + SLC_EFF_ID_LEN;
+ } else {
+ *pos |= 0x20; /* convert R/T to lower case for SFF */
+ id &= CAN_SFF_MASK;
+ endpos = pos + SLC_SFF_ID_LEN;
+ }
- idx = strlen(sl->xbuff);
+ /* build 3 (SFF) or 8 (EFF) digit CAN identifier */
+ pos++;
+ while (endpos >= pos) {
+ *endpos-- = hex_asc_upper[id & 0xf];
+ id >>= 4;
+ }
+
+ pos += (cf->can_id & CAN_EFF_FLAG) ? SLC_EFF_ID_LEN : SLC_SFF_ID_LEN;
- for (i = 0; i < cf->can_dlc; i++)
- sprintf(&sl->xbuff[idx + 2*i], "%02X", cf->data[i]);
+ *pos++ = cf->can_dlc + '0';
+
+ /* RTR frames may have a dlc > 0 but they never have any data bytes */
+ if (!(cf->can_id & CAN_RTR_FLAG)) {
+ for (i = 0; i < cf->can_dlc; i++)
+ pos = hex_byte_pack_upper(pos, cf->data[i]);
+ }
- strcat(sl->xbuff, "\r"); /* add terminating character */
+ *pos++ = '\r';
/* Order of next two lines is *very* important.
* When we are sending a little amount of data,
@@ -267,8 +305,8 @@ static void slc_encaps(struct slcan *sl, struct can_frame *cf)
* 14 Oct 1994 Dmitry Gorodchanin.
*/
set_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
- actual = sl->tty->ops->write(sl->tty, sl->xbuff, strlen(sl->xbuff));
- sl->xleft = strlen(sl->xbuff) - actual;
+ actual = sl->tty->ops->write(sl->tty, sl->xbuff, pos - sl->xbuff);
+ sl->xleft = (pos - sl->xbuff) - actual;
sl->xhead = sl->xbuff + actual;
sl->dev->stats.tx_bytes += cf->can_dlc;
}
@@ -286,11 +324,13 @@ static void slcan_write_wakeup(struct tty_struct *tty)
if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev))
return;
+ spin_lock(&sl->lock);
if (sl->xleft <= 0) {
/* Now serial buffer is almost free & we can start
* transmission of another packet */
sl->dev->stats.tx_packets++;
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+ spin_unlock(&sl->lock);
netif_wake_queue(sl->dev);
return;
}
@@ -298,6 +338,7 @@ static void slcan_write_wakeup(struct tty_struct *tty)
actual = tty->ops->write(tty, sl->xhead, sl->xleft);
sl->xleft -= actual;
sl->xhead += actual;
+ spin_unlock(&sl->lock);
}
/* Send a can_frame to a TTY queue. */
diff --git a/drivers/net/can/softing/softing.h b/drivers/net/can/softing/softing.h
index afd7d85b6915..35f062282dbd 100644
--- a/drivers/net/can/softing/softing.h
+++ b/drivers/net/can/softing/softing.h
@@ -71,34 +71,34 @@ struct softing {
} id;
};
-extern int softing_default_output(struct net_device *netdev);
+int softing_default_output(struct net_device *netdev);
-extern ktime_t softing_raw2ktime(struct softing *card, u32 raw);
+ktime_t softing_raw2ktime(struct softing *card, u32 raw);
-extern int softing_chip_poweron(struct softing *card);
+int softing_chip_poweron(struct softing *card);
-extern int softing_bootloader_command(struct softing *card, int16_t cmd,
- const char *msg);
+int softing_bootloader_command(struct softing *card, int16_t cmd,
+ const char *msg);
/* Load firmware after reset */
-extern int softing_load_fw(const char *file, struct softing *card,
- __iomem uint8_t *virt, unsigned int size, int offset);
+int softing_load_fw(const char *file, struct softing *card,
+ __iomem uint8_t *virt, unsigned int size, int offset);
/* Load final application firmware after bootloader */
-extern int softing_load_app_fw(const char *file, struct softing *card);
+int softing_load_app_fw(const char *file, struct softing *card);
/*
* enable or disable irq
* only called with fw.lock locked
*/
-extern int softing_enable_irq(struct softing *card, int enable);
+int softing_enable_irq(struct softing *card, int enable);
/* start/stop 1 bus on card */
-extern int softing_startstop(struct net_device *netdev, int up);
+int softing_startstop(struct net_device *netdev, int up);
/* netif_rx() */
-extern int softing_netdev_rx(struct net_device *netdev,
- const struct can_frame *msg, ktime_t ktime);
+int softing_netdev_rx(struct net_device *netdev, const struct can_frame *msg,
+ ktime_t ktime);
/* SOFTING DPRAM mappings */
#define DPRAM_RX 0x0000
diff --git a/drivers/net/ethernet/8390/8390.h b/drivers/net/ethernet/8390/8390.h
index ef325ffa1b5a..2923c51bb351 100644
--- a/drivers/net/ethernet/8390/8390.h
+++ b/drivers/net/ethernet/8390/8390.h
@@ -28,42 +28,42 @@ extern int ei_debug;
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
-extern void ei_poll(struct net_device *dev);
-extern void eip_poll(struct net_device *dev);
+void ei_poll(struct net_device *dev);
+void eip_poll(struct net_device *dev);
#endif
/* Without I/O delay - non ISA or later chips */
-extern void NS8390_init(struct net_device *dev, int startp);
-extern int ei_open(struct net_device *dev);
-extern int ei_close(struct net_device *dev);
-extern irqreturn_t ei_interrupt(int irq, void *dev_id);
-extern void ei_tx_timeout(struct net_device *dev);
-extern netdev_tx_t ei_start_xmit(struct sk_buff *skb, struct net_device *dev);
-extern void ei_set_multicast_list(struct net_device *dev);
-extern struct net_device_stats *ei_get_stats(struct net_device *dev);
+void NS8390_init(struct net_device *dev, int startp);
+int ei_open(struct net_device *dev);
+int ei_close(struct net_device *dev);
+irqreturn_t ei_interrupt(int irq, void *dev_id);
+void ei_tx_timeout(struct net_device *dev);
+netdev_tx_t ei_start_xmit(struct sk_buff *skb, struct net_device *dev);
+void ei_set_multicast_list(struct net_device *dev);
+struct net_device_stats *ei_get_stats(struct net_device *dev);
extern const struct net_device_ops ei_netdev_ops;
-extern struct net_device *__alloc_ei_netdev(int size);
+struct net_device *__alloc_ei_netdev(int size);
static inline struct net_device *alloc_ei_netdev(void)
{
return __alloc_ei_netdev(0);
}
/* With I/O delay form */
-extern void NS8390p_init(struct net_device *dev, int startp);
-extern int eip_open(struct net_device *dev);
-extern int eip_close(struct net_device *dev);
-extern irqreturn_t eip_interrupt(int irq, void *dev_id);
-extern void eip_tx_timeout(struct net_device *dev);
-extern netdev_tx_t eip_start_xmit(struct sk_buff *skb, struct net_device *dev);
-extern void eip_set_multicast_list(struct net_device *dev);
-extern struct net_device_stats *eip_get_stats(struct net_device *dev);
+void NS8390p_init(struct net_device *dev, int startp);
+int eip_open(struct net_device *dev);
+int eip_close(struct net_device *dev);
+irqreturn_t eip_interrupt(int irq, void *dev_id);
+void eip_tx_timeout(struct net_device *dev);
+netdev_tx_t eip_start_xmit(struct sk_buff *skb, struct net_device *dev);
+void eip_set_multicast_list(struct net_device *dev);
+struct net_device_stats *eip_get_stats(struct net_device *dev);
extern const struct net_device_ops eip_netdev_ops;
-extern struct net_device *__alloc_eip_netdev(int size);
+struct net_device *__alloc_eip_netdev(int size);
static inline struct net_device *alloc_eip_netdev(void)
{
return __alloc_eip_netdev(0);
diff --git a/drivers/net/ethernet/8390/Kconfig b/drivers/net/ethernet/8390/Kconfig
index becef25fa194..0988811f4e40 100644
--- a/drivers/net/ethernet/8390/Kconfig
+++ b/drivers/net/ethernet/8390/Kconfig
@@ -146,13 +146,6 @@ config PCMCIA_PCNET
To compile this driver as a module, choose M here: the module will be
called pcnet_cs. If unsure, say N.
-config NE_H8300
- tristate "NE2000 compatible support for H8/300"
- depends on H8300H_AKI3068NET || H8300H_H8MAX
- ---help---
- Say Y here if you want to use the NE2000 compatible
- controller on the Renesas H8/300 processor.
-
config STNIC
tristate "National DP83902AV support"
depends on SUPERH
diff --git a/drivers/net/ethernet/8390/Makefile b/drivers/net/ethernet/8390/Makefile
index 588954a79b2a..ff3b31894188 100644
--- a/drivers/net/ethernet/8390/Makefile
+++ b/drivers/net/ethernet/8390/Makefile
@@ -10,7 +10,6 @@ obj-$(CONFIG_HYDRA) += hydra.o 8390.o
obj-$(CONFIG_MCF8390) += mcf8390.o 8390.o
obj-$(CONFIG_NE2000) += ne.o 8390p.o
obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
-obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
obj-$(CONFIG_PCMCIA_AXNET) += axnet_cs.o 8390.o
obj-$(CONFIG_PCMCIA_PCNET) += pcnet_cs.o 8390.o
obj-$(CONFIG_STNIC) += stnic.o 8390.o
diff --git a/drivers/net/ethernet/8390/ne-h8300.c b/drivers/net/ethernet/8390/ne-h8300.c
deleted file mode 100644
index 7fc28f2d28a6..000000000000
--- a/drivers/net/ethernet/8390/ne-h8300.c
+++ /dev/null
@@ -1,684 +0,0 @@
-/* ne-h8300.c: A NE2000 clone on H8/300 driver for linux. */
-/*
- original ne.c
- Written 1992-94 by Donald Becker.
-
- Copyright 1993 United States Government as represented by the
- Director, National Security Agency.
-
- This software may be used and distributed according to the terms
- of the GNU General Public License, incorporated herein by reference.
-
- The author may be reached as becker@scyld.com, or C/O
- Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
-
- H8/300 modified
- Yoshinori Sato <ysato@users.sourceforge.jp>
-*/
-
-static const char version1[] =
-"ne-h8300.c:v1.00 2004/04/11 ysato\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/jiffies.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#define EI_SHIFT(x) (ei_local->reg_offset[x])
-
-#include "8390.h"
-
-#define DRV_NAME "ne-h8300"
-
-/* Some defines that people can play with if so inclined. */
-
-/* Do we perform extra sanity checks on stuff ? */
-/* #define NE_SANITY_CHECK */
-
-/* Do we implement the read before write bugfix ? */
-/* #define NE_RW_BUGFIX */
-
-/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
-/* #define PACKETBUF_MEMSIZE 0x40 */
-
-/* A zero-terminated list of I/O addresses to be probed at boot. */
-
-/* ---- No user-serviceable parts below ---- */
-
-static const char version[] =
- "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#include "lib8390.c"
-
-#define NE_BASE (dev->base_addr)
-#define NE_CMD 0x00
-#define NE_DATAPORT (ei_status.word16?0x20:0x10) /* NatSemi-defined port window offset. */
-#define NE_RESET (ei_status.word16?0x3f:0x1f) /* Issue a read to reset, a write to clear. */
-#define NE_IO_EXTENT (ei_status.word16?0x40:0x20)
-
-#define NESM_START_PG 0x40 /* First page of TX buffer */
-#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
-
-static int ne_probe1(struct net_device *dev, int ioaddr);
-
-static int ne_open(struct net_device *dev);
-static int ne_close(struct net_device *dev);
-
-static void ne_reset_8390(struct net_device *dev);
-static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
- int ring_page);
-static void ne_block_input(struct net_device *dev, int count,
- struct sk_buff *skb, int ring_offset);
-static void ne_block_output(struct net_device *dev, const int count,
- const unsigned char *buf, const int start_page);
-
-
-static u32 reg_offset[16];
-
-static int __init init_reg_offset(struct net_device *dev,unsigned long base_addr)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- int i;
- unsigned char bus_width;
-
- bus_width = *(volatile unsigned char *)ABWCR;
- bus_width &= 1 << ((base_addr >> 21) & 7);
-
- for (i = 0; i < ARRAY_SIZE(reg_offset); i++)
- if (bus_width == 0)
- reg_offset[i] = i * 2 + 1;
- else
- reg_offset[i] = i;
-
- ei_local->reg_offset = reg_offset;
- return 0;
-}
-
-static int __initdata h8300_ne_count = 0;
-#ifdef CONFIG_H8300H_H8MAX
-static unsigned long __initdata h8300_ne_base[] = { 0x800600 };
-static int h8300_ne_irq[] = {EXT_IRQ4};
-#endif
-#ifdef CONFIG_H8300H_AKI3068NET
-static unsigned long __initdata h8300_ne_base[] = { 0x200000 };
-static int h8300_ne_irq[] = {EXT_IRQ5};
-#endif
-
-static inline int init_dev(struct net_device *dev)
-{
- if (h8300_ne_count < ARRAY_SIZE(h8300_ne_base)) {
- dev->base_addr = h8300_ne_base[h8300_ne_count];
- dev->irq = h8300_ne_irq[h8300_ne_count];
- h8300_ne_count++;
- return 0;
- } else
- return -ENODEV;
-}
-
-/* Probe for various non-shared-memory ethercards.
-
- NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
- buffer memory space. NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of
- the SAPROM, while other supposed NE2000 clones must be detected by their
- SA prefix.
-
- Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
- mode results in doubled values, which can be detected and compensated for.
-
- The probe is also responsible for initializing the card and filling
- in the 'dev' and 'ei_status' structures.
-
- We use the minimum memory size for some ethercard product lines, iff we can't
- distinguish models. You can increase the packet buffer size by setting
- PACKETBUF_MEMSIZE. Reported Cabletron packet buffer locations are:
- E1010 starts at 0x100 and ends at 0x2000.
- E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory")
- E2010 starts at 0x100 and ends at 0x4000.
- E2010-x starts at 0x100 and ends at 0xffff. */
-
-static int __init do_ne_probe(struct net_device *dev)
-{
- unsigned int base_addr = dev->base_addr;
-
- /* First check any supplied i/o locations. User knows best. <cough> */
- if (base_addr > 0x1ff) /* Check a single specified location. */
- return ne_probe1(dev, base_addr);
- else if (base_addr != 0) /* Don't probe at all. */
- return -ENXIO;
-
- return -ENODEV;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, NE_IO_EXTENT);
-}
-
-#ifndef MODULE
-struct net_device * __init ne_probe(int unit)
-{
- struct net_device *dev = ____alloc_ei_netdev(0);
- int err;
-
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- if (init_dev(dev))
- return ERR_PTR(-ENODEV);
-
- sprintf(dev->name, "eth%d", unit);
- netdev_boot_setup_check(dev);
-
- err = init_reg_offset(dev, dev->base_addr);
- if (err)
- goto out;
-
- err = do_ne_probe(dev);
- if (err)
- goto out;
- return dev;
-out:
- free_netdev(dev);
- return ERR_PTR(err);
-}
-#endif
-
-static const struct net_device_ops ne_netdev_ops = {
- .ndo_open = ne_open,
- .ndo_stop = ne_close,
-
- .ndo_start_xmit = __ei_start_xmit,
- .ndo_tx_timeout = __ei_tx_timeout,
- .ndo_get_stats = __ei_get_stats,
- .ndo_set_rx_mode = __ei_set_multicast_list,
- .ndo_validate_addr = eth_validate_addr,
- .ndo_set_mac_address = eth_mac_addr,
- .ndo_change_mtu = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = __ei_poll,
-#endif
-};
-
-static int __init ne_probe1(struct net_device *dev, int ioaddr)
-{
- int i;
- unsigned char SA_prom[16];
- int wordlength = 2;
- const char *name = NULL;
- int start_page, stop_page;
- int reg0, ret;
- static unsigned version_printed;
- struct ei_device *ei_local = netdev_priv(dev);
- unsigned char bus_width;
-
- if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
- return -EBUSY;
-
- reg0 = inb_p(ioaddr);
- if (reg0 == 0xFF) {
- ret = -ENODEV;
- goto err_out;
- }
-
- /* Do a preliminary verification that we have a 8390. */
- {
- int regd;
- outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
- regd = inb_p(ioaddr + EI_SHIFT(0x0d));
- outb_p(0xff, ioaddr + EI_SHIFT(0x0d));
- outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
- inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
- if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
- outb_p(reg0, ioaddr + EI_SHIFT(0));
- outb_p(regd, ioaddr + EI_SHIFT(0x0d)); /* Restore the old values. */
- ret = -ENODEV;
- goto err_out;
- }
- }
-
- if (ei_debug && version_printed++ == 0)
- printk(KERN_INFO "%s", version1);
-
- printk(KERN_INFO "NE*000 ethercard probe at %08x:", ioaddr);
-
- /* Read the 16 bytes of station address PROM.
- We must first initialize registers, similar to NS8390_init(eifdev, 0).
- We can't reliably read the SAPROM address without this.
- (I learned the hard way!). */
- {
- struct {unsigned char value, offset; } program_seq[] =
- {
- {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
- {0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */
- {0x00, EN0_RCNTLO}, /* Clear the count regs. */
- {0x00, EN0_RCNTHI},
- {0x00, EN0_IMR}, /* Mask completion irq. */
- {0xFF, EN0_ISR},
- {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */
- {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */
- {32, EN0_RCNTLO},
- {0x00, EN0_RCNTHI},
- {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */
- {0x00, EN0_RSARHI},
- {E8390_RREAD+E8390_START, E8390_CMD},
- };
-
- for (i = 0; i < ARRAY_SIZE(program_seq); i++)
- outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
-
- }
- bus_width = *(volatile unsigned char *)ABWCR;
- bus_width &= 1 << ((ioaddr >> 21) & 7);
- ei_status.word16 = (bus_width == 0); /* temporary setting */
- for(i = 0; i < 16 /*sizeof(SA_prom)*/; i++) {
- SA_prom[i] = inb_p(ioaddr + NE_DATAPORT);
- inb_p(ioaddr + NE_DATAPORT); /* dummy read */
- }
-
- start_page = NESM_START_PG;
- stop_page = NESM_STOP_PG;
-
- if (bus_width)
- wordlength = 1;
- else
- outb_p(0x49, ioaddr + EN0_DCFG);
-
- /* Set up the rest of the parameters. */
- name = (wordlength == 2) ? "NE2000" : "NE1000";
-
- if (! dev->irq) {
- printk(" failed to detect IRQ line.\n");
- ret = -EAGAIN;
- goto err_out;
- }
-
- /* Snarf the interrupt now. There's no point in waiting since we cannot
- share and the board will usually be enabled. */
- ret = request_irq(dev->irq, __ei_interrupt, 0, name, dev);
- if (ret) {
- printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
- goto err_out;
- }
-
- dev->base_addr = ioaddr;
-
- for (i = 0; i < ETH_ALEN; i++)
- dev->dev_addr[i] = SA_prom[i];
- printk(" %pM\n", dev->dev_addr);
-
- printk("%s: %s found at %#x, using IRQ %d.\n",
- dev->name, name, ioaddr, dev->irq);
-
- ei_status.name = name;
- ei_status.tx_start_page = start_page;
- ei_status.stop_page = stop_page;
- ei_status.word16 = (wordlength == 2);
-
- ei_status.rx_start_page = start_page + TX_PAGES;
-#ifdef PACKETBUF_MEMSIZE
- /* Allow the packet buffer size to be overridden by know-it-alls. */
- ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
-#endif
-
- ei_status.reset_8390 = &ne_reset_8390;
- ei_status.block_input = &ne_block_input;
- ei_status.block_output = &ne_block_output;
- ei_status.get_8390_hdr = &ne_get_8390_hdr;
- ei_status.priv = 0;
-
- dev->netdev_ops = &ne_netdev_ops;
-
- __NS8390_init(dev, 0);
-
- ret = register_netdev(dev);
- if (ret)
- goto out_irq;
- return 0;
-out_irq:
- free_irq(dev->irq, dev);
-err_out:
- release_region(ioaddr, NE_IO_EXTENT);
- return ret;
-}
-
-static int ne_open(struct net_device *dev)
-{
- __ei_open(dev);
- return 0;
-}
-
-static int ne_close(struct net_device *dev)
-{
- if (ei_debug > 1)
- printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
- __ei_close(dev);
- return 0;
-}
-
-/* Hard reset the card. This used to pause for the same period that a
- 8390 reset command required, but that shouldn't be necessary. */
-
-static void ne_reset_8390(struct net_device *dev)
-{
- unsigned long reset_start_time = jiffies;
- struct ei_device *ei_local = netdev_priv(dev);
-
- if (ei_debug > 1)
- printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
-
- /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
- outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
-
- ei_status.txing = 0;
- ei_status.dmaing = 0;
-
- /* This check _should_not_ be necessary, omit eventually. */
- while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
- if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
- printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
- break;
- }
- outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
- we don't need to be concerned with ring wrap as the header will be at
- the start of a page, so we optimize accordingly. */
-
-static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-
- if (ei_status.dmaing)
- {
- printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
- "[DMAstat:%d][irqlock:%d].\n",
- dev->name, ei_status.dmaing, ei_status.irqlock);
- return;
- }
-
- ei_status.dmaing |= 0x01;
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, NE_BASE + NE_CMD);
- outb_p(sizeof(struct e8390_pkt_hdr), NE_BASE + EN0_RCNTLO);
- outb_p(0, NE_BASE + EN0_RCNTHI);
- outb_p(0, NE_BASE + EN0_RSARLO); /* On page boundary */
- outb_p(ring_page, NE_BASE + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, NE_BASE + NE_CMD);
-
- if (ei_status.word16) {
- int len;
- unsigned short *p = (unsigned short *)hdr;
- for (len = sizeof(struct e8390_pkt_hdr)>>1; len > 0; len--)
- *p++ = inw(NE_BASE + NE_DATAPORT);
- } else
- insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
-
- outb_p(ENISR_RDC, NE_BASE + EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
-
- le16_to_cpus(&hdr->count);
-}
-
-/* Block input and output, similar to the Crynwr packet driver. If you
- are porting to a new ethercard, look at the packet driver source for hints.
- The NEx000 doesn't share the on-board packet memory -- you have to put
- the packet out through the "remote DMA" dataport using outb. */
-
-static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
- struct ei_device *ei_local = netdev_priv(dev);
-#ifdef NE_SANITY_CHECK
- int xfer_count = count;
-#endif
- char *buf = skb->data;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing)
- {
- printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
- "[DMAstat:%d][irqlock:%d].\n",
- dev->name, ei_status.dmaing, ei_status.irqlock);
- return;
- }
- ei_status.dmaing |= 0x01;
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, NE_BASE + NE_CMD);
- outb_p(count & 0xff, NE_BASE + EN0_RCNTLO);
- outb_p(count >> 8, NE_BASE + EN0_RCNTHI);
- outb_p(ring_offset & 0xff, NE_BASE + EN0_RSARLO);
- outb_p(ring_offset >> 8, NE_BASE + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, NE_BASE + NE_CMD);
- if (ei_status.word16)
- {
- int len;
- unsigned short *p = (unsigned short *)buf;
- for (len = count>>1; len > 0; len--)
- *p++ = inw(NE_BASE + NE_DATAPORT);
- if (count & 0x01)
- {
- buf[count-1] = inb(NE_BASE + NE_DATAPORT);
-#ifdef NE_SANITY_CHECK
- xfer_count++;
-#endif
- }
- } else {
- insb(NE_BASE + NE_DATAPORT, buf, count);
- }
-
-#ifdef NE_SANITY_CHECK
- /* This was for the ALPHA version only, but enough people have
- been encountering problems so it is still here. If you see
- this message you either 1) have a slightly incompatible clone
- or 2) have noise/speed problems with your bus. */
-
- if (ei_debug > 1)
- {
- /* DMA termination address check... */
- int addr, tries = 20;
- do {
- /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
- -- it's broken for Rx on some cards! */
- int high = inb_p(NE_BASE + EN0_RSARHI);
- int low = inb_p(NE_BASE + EN0_RSARLO);
- addr = (high << 8) + low;
- if (((ring_offset + xfer_count) & 0xff) == low)
- break;
- } while (--tries > 0);
- if (tries <= 0)
- printk(KERN_WARNING "%s: RX transfer address mismatch,"
- "%#4.4x (expected) vs. %#4.4x (actual).\n",
- dev->name, ring_offset + xfer_count, addr);
- }
-#endif
- outb_p(ENISR_RDC, NE_BASE + EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
-}
-
-static void ne_block_output(struct net_device *dev, int count,
- const unsigned char *buf, const int start_page)
-{
- struct ei_device *ei_local = netdev_priv(dev);
- unsigned long dma_start;
-#ifdef NE_SANITY_CHECK
- int retries = 0;
-#endif
-
- /* Round the count up for word writes. Do we need to do this?
- What effect will an odd byte count have on the 8390?
- I should check someday. */
-
- if (ei_status.word16 && (count & 0x01))
- count++;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing)
- {
- printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
- "[DMAstat:%d][irqlock:%d]\n",
- dev->name, ei_status.dmaing, ei_status.irqlock);
- return;
- }
- ei_status.dmaing |= 0x01;
- /* We should already be in page 0, but to be safe... */
- outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, NE_BASE + NE_CMD);
-
-#ifdef NE_SANITY_CHECK
-retry:
-#endif
-
-#ifdef NE8390_RW_BUGFIX
- /* Handle the read-before-write bug the same way as the
- Crynwr packet driver -- the NatSemi method doesn't work.
- Actually this doesn't always work either, but if you have
- problems with your NEx000 this is better than nothing! */
-
- outb_p(0x42, NE_BASE + EN0_RCNTLO);
- outb_p(0x00, NE_BASE + EN0_RCNTHI);
- outb_p(0x42, NE_BASE + EN0_RSARLO);
- outb_p(0x00, NE_BASE + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, NE_BASE + NE_CMD);
- /* Make certain that the dummy read has occurred. */
- udelay(6);
-#endif
-
- outb_p(ENISR_RDC, NE_BASE + EN0_ISR);
-
- /* Now the normal output. */
- outb_p(count & 0xff, NE_BASE + EN0_RCNTLO);
- outb_p(count >> 8, NE_BASE + EN0_RCNTHI);
- outb_p(0x00, NE_BASE + EN0_RSARLO);
- outb_p(start_page, NE_BASE + EN0_RSARHI);
-
- outb_p(E8390_RWRITE+E8390_START, NE_BASE + NE_CMD);
- if (ei_status.word16) {
- int len;
- unsigned short *p = (unsigned short *)buf;
- for (len = count>>1; len > 0; len--)
- outw(*p++, NE_BASE + NE_DATAPORT);
- } else {
- outsb(NE_BASE + NE_DATAPORT, buf, count);
- }
-
- dma_start = jiffies;
-
-#ifdef NE_SANITY_CHECK
- /* This was for the ALPHA version only, but enough people have
- been encountering problems so it is still here. */
-
- if (ei_debug > 1)
- {
- /* DMA termination address check... */
- int addr, tries = 20;
- do {
- int high = inb_p(NE_BASE + EN0_RSARHI);
- int low = inb_p(NE_BASE + EN0_RSARLO);
- addr = (high << 8) + low;
- if ((start_page << 8) + count == addr)
- break;
- } while (--tries > 0);
-
- if (tries <= 0)
- {
- printk(KERN_WARNING "%s: Tx packet transfer address mismatch,"
- "%#4.4x (expected) vs. %#4.4x (actual).\n",
- dev->name, (start_page << 8) + count, addr);
- if (retries++ == 0)
- goto retry;
- }
- }
-#endif
-
- while ((inb_p(NE_BASE + EN0_ISR) & ENISR_RDC) == 0)
- if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */
- printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
- ne_reset_8390(dev);
- __NS8390_init(dev,1);
- break;
- }
-
- outb_p(ENISR_RDC, NE_BASE + EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
-}
-
-
-#ifdef MODULE
-#define MAX_NE_CARDS 1 /* Max number of NE cards per module */
-static struct net_device *dev_ne[MAX_NE_CARDS];
-static int io[MAX_NE_CARDS];
-static int irq[MAX_NE_CARDS];
-static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */
-
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(bad, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es)");
-MODULE_PARM_DESC(irq, "IRQ number(s)");
-MODULE_DESCRIPTION("H8/300 NE2000 Ethernet driver");
-MODULE_LICENSE("GPL");
-
-/* This is set up so that no ISA autoprobe takes place. We can't guarantee
-that the ne2k probe is the last 8390 based probe to take place (as it
-is at boot) and so the probe will get confused by any other 8390 cards.
-ISA device autoprobes on a running machine are not recommended anyway. */
-
-int init_module(void)
-{
- int this_dev, found = 0;
- int err;
-
- for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
- struct net_device *dev = ____alloc_ei_netdev(0);
- if (!dev)
- break;
- if (io[this_dev]) {
- dev->irq = irq[this_dev];
- dev->mem_end = bad[this_dev];
- dev->base_addr = io[this_dev];
- } else {
- dev->base_addr = h8300_ne_base[this_dev];
- dev->irq = h8300_ne_irq[this_dev];
- }
- err = init_reg_offset(dev, dev->base_addr);
- if (!err) {
- if (do_ne_probe(dev) == 0) {
- dev_ne[found++] = dev;
- continue;
- }
- }
- free_netdev(dev);
- if (found)
- break;
- if (io[this_dev] != 0)
- printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", dev->base_addr);
- else
- printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
- return -ENXIO;
- }
- if (found)
- return 0;
- return -ENODEV;
-}
-
-void cleanup_module(void)
-{
- int this_dev;
-
- for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
- struct net_device *dev = dev_ne[this_dev];
- if (dev) {
- unregister_netdev(dev);
- cleanup_card(dev);
- free_netdev(dev);
- }
- }
-}
-#endif /* MODULE */
diff --git a/drivers/net/ethernet/adi/bfin_mac.h b/drivers/net/ethernet/adi/bfin_mac.h
index 7a07ee07906b..6dec86ac97cd 100644
--- a/drivers/net/ethernet/adi/bfin_mac.h
+++ b/drivers/net/ethernet/adi/bfin_mac.h
@@ -104,6 +104,6 @@ struct bfin_mac_local {
#endif
};
-extern int bfin_get_ether_addr(char *addr);
+int bfin_get_ether_addr(char *addr);
#endif
diff --git a/drivers/net/ethernet/amd/7990.h b/drivers/net/ethernet/amd/7990.h
index 0a5837b96421..ae33a99bf476 100644
--- a/drivers/net/ethernet/amd/7990.h
+++ b/drivers/net/ethernet/amd/7990.h
@@ -242,13 +242,13 @@ struct lance_private
#define LANCE_ADDR(x) ((int)(x) & ~0xff000000)
/* Now the prototypes we export */
-extern int lance_open(struct net_device *dev);
-extern int lance_close (struct net_device *dev);
-extern int lance_start_xmit (struct sk_buff *skb, struct net_device *dev);
-extern void lance_set_multicast (struct net_device *dev);
-extern void lance_tx_timeout(struct net_device *dev);
+int lance_open(struct net_device *dev);
+int lance_close (struct net_device *dev);
+int lance_start_xmit (struct sk_buff *skb, struct net_device *dev);
+void lance_set_multicast (struct net_device *dev);
+void lance_tx_timeout(struct net_device *dev);
#ifdef CONFIG_NET_POLL_CONTROLLER
-extern void lance_poll(struct net_device *dev);
+void lance_poll(struct net_device *dev);
#endif
#endif /* ndef _7990_H */
diff --git a/drivers/net/ethernet/amd/declance.c b/drivers/net/ethernet/amd/declance.c
index 94edc9c6fbbf..57397295887c 100644
--- a/drivers/net/ethernet/amd/declance.c
+++ b/drivers/net/ethernet/amd/declance.c
@@ -344,8 +344,8 @@ static void cp_to_buf(const int type, void *to, const void *from, int len)
}
clen = len & 1;
- rtp = tp;
- rfp = fp;
+ rtp = (unsigned char *)tp;
+ rfp = (const unsigned char *)fp;
while (clen--) {
*rtp++ = *rfp++;
}
@@ -372,8 +372,8 @@ static void cp_to_buf(const int type, void *to, const void *from, int len)
* do the rest, if any.
*/
clen = len & 15;
- rtp = (unsigned char *) tp;
- rfp = (unsigned char *) fp;
+ rtp = (unsigned char *)tp;
+ rfp = (const unsigned char *)fp;
while (clen--) {
*rtp++ = *rfp++;
}
@@ -403,8 +403,8 @@ static void cp_from_buf(const int type, void *to, const void *from, int len)
clen = len & 1;
- rtp = tp;
- rfp = fp;
+ rtp = (unsigned char *)tp;
+ rfp = (const unsigned char *)fp;
while (clen--) {
*rtp++ = *rfp++;
@@ -433,8 +433,8 @@ static void cp_from_buf(const int type, void *to, const void *from, int len)
* do the rest, if any.
*/
clen = len & 15;
- rtp = (unsigned char *) tp;
- rfp = (unsigned char *) fp;
+ rtp = (unsigned char *)tp;
+ rfp = (const unsigned char *)fp;
while (clen--) {
*rtp++ = *rfp++;
}
@@ -725,7 +725,6 @@ static irqreturn_t lance_dma_merr_int(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
- clear_ioasic_dma_irq(irq);
printk(KERN_ERR "%s: DMA error\n", dev->name);
return IRQ_HANDLED;
}
@@ -812,7 +811,7 @@ static int lance_open(struct net_device *dev)
if (lp->dma_irq >= 0) {
unsigned long flags;
- if (request_irq(lp->dma_irq, lance_dma_merr_int, 0,
+ if (request_irq(lp->dma_irq, lance_dma_merr_int, IRQF_ONESHOT,
"lance error", dev)) {
free_irq(dev->irq, dev);
printk("%s: Can't get DMA IRQ %d\n", dev->name,
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c.h b/drivers/net/ethernet/atheros/atl1c/atl1c.h
index 0f0556526ba9..7f9369a3b378 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c.h
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c.h
@@ -600,7 +600,7 @@ struct atl1c_adapter {
extern char atl1c_driver_name[];
extern char atl1c_driver_version[];
-extern void atl1c_reinit_locked(struct atl1c_adapter *adapter);
-extern s32 atl1c_reset_hw(struct atl1c_hw *hw);
-extern void atl1c_set_ethtool_ops(struct net_device *netdev);
+void atl1c_reinit_locked(struct atl1c_adapter *adapter);
+s32 atl1c_reset_hw(struct atl1c_hw *hw);
+void atl1c_set_ethtool_ops(struct net_device *netdev);
#endif /* _ATL1C_H_ */
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e.h b/drivers/net/ethernet/atheros/atl1e/atl1e.h
index b5fd934585e9..1b0fe2d04a0e 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e.h
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e.h
@@ -499,10 +499,10 @@ struct atl1e_adapter {
extern char atl1e_driver_name[];
extern char atl1e_driver_version[];
-extern void atl1e_check_options(struct atl1e_adapter *adapter);
-extern int atl1e_up(struct atl1e_adapter *adapter);
-extern void atl1e_down(struct atl1e_adapter *adapter);
-extern void atl1e_reinit_locked(struct atl1e_adapter *adapter);
-extern s32 atl1e_reset_hw(struct atl1e_hw *hw);
-extern void atl1e_set_ethtool_ops(struct net_device *netdev);
+void atl1e_check_options(struct atl1e_adapter *adapter);
+int atl1e_up(struct atl1e_adapter *adapter);
+void atl1e_down(struct atl1e_adapter *adapter);
+void atl1e_reinit_locked(struct atl1e_adapter *adapter);
+s32 atl1e_reset_hw(struct atl1e_hw *hw);
+void atl1e_set_ethtool_ops(struct net_device *netdev);
#endif /* _ATL1_E_H_ */
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.h b/drivers/net/ethernet/atheros/atlx/atl2.h
index 3ebe19f7242b..2f27d4c4c3ad 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.h
+++ b/drivers/net/ethernet/atheros/atlx/atl2.h
@@ -42,7 +42,7 @@
#include "atlx.h"
#ifdef ETHTOOL_OPS_COMPAT
-extern int ethtool_ioctl(struct ifreq *ifr);
+int ethtool_ioctl(struct ifreq *ifr);
#endif
#define PCI_COMMAND_REGISTER PCI_COMMAND
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 61726af1de6e..e66beff2704d 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -2481,8 +2481,7 @@ load_error_cnic2:
load_error_cnic1:
bnx2x_napi_disable_cnic(bp);
/* Update the number of queues without the cnic queues */
- rc = bnx2x_set_real_num_queues(bp, 0);
- if (rc)
+ if (bnx2x_set_real_num_queues(bp, 0))
BNX2X_ERR("Unable to set real_num_queues not including cnic\n");
load_error_cnic0:
BNX2X_ERR("CNIC-related load failed\n");
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index d60a2ea3da19..51468227bf3b 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -175,6 +175,7 @@ typedef int (*read_sfp_module_eeprom_func_p)(struct bnx2x_phy *phy,
#define EDC_MODE_LINEAR 0x0022
#define EDC_MODE_LIMITING 0x0044
#define EDC_MODE_PASSIVE_DAC 0x0055
+#define EDC_MODE_ACTIVE_DAC 0x0066
/* ETS defines*/
#define DCBX_INVALID_COS (0xFF)
@@ -3684,6 +3685,41 @@ static void bnx2x_warpcore_enable_AN_KR2(struct bnx2x_phy *phy,
bnx2x_update_link_attr(params, vars->link_attr_sync);
}
+static void bnx2x_disable_kr2(struct link_params *params,
+ struct link_vars *vars,
+ struct bnx2x_phy *phy)
+{
+ struct bnx2x *bp = params->bp;
+ int i;
+ static struct bnx2x_reg_set reg_set[] = {
+ /* Step 1 - Program the TX/RX alignment markers */
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0x7690},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xe647},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0xc4f0},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0x7690},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xe647},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0xc4f0},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000c},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6000},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0000},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0002},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x0000},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x0af7},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x0af7},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0002},
+ {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0000}
+ };
+ DP(NETIF_MSG_LINK, "Disabling 20G-KR2\n");
+
+ for (i = 0; i < ARRAY_SIZE(reg_set); i++)
+ bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
+ reg_set[i].val);
+ vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
+ bnx2x_update_link_attr(params, vars->link_attr_sync);
+
+ vars->check_kr2_recovery_cnt = CHECK_KR2_RECOVERY_CNT;
+}
+
static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,
struct link_params *params)
{
@@ -3715,7 +3751,6 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
struct link_params *params,
struct link_vars *vars) {
u16 lane, i, cl72_ctrl, an_adv = 0;
- u16 ucode_ver;
struct bnx2x *bp = params->bp;
static struct bnx2x_reg_set reg_set[] = {
{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
@@ -3806,15 +3841,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
/* Advertise pause */
bnx2x_ext_phy_set_pause(params, phy, vars);
- /* Set KR Autoneg Work-Around flag for Warpcore version older than D108
- */
- bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
- MDIO_WC_REG_UC_INFO_B1_VERSION, &ucode_ver);
- if (ucode_ver < 0xd108) {
- DP(NETIF_MSG_LINK, "Enable AN KR work-around. WC ver:0x%x\n",
- ucode_ver);
- vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
- }
+ vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_DIGITAL5_MISC7, 0x100);
@@ -3838,6 +3865,8 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
bnx2x_set_aer_mmd(params, phy);
bnx2x_warpcore_enable_AN_KR2(phy, params, vars);
+ } else {
+ bnx2x_disable_kr2(params, vars, phy);
}
/* Enable Autoneg: only on the main lane */
@@ -4347,20 +4376,14 @@ static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
struct bnx2x *bp = params->bp;
u32 serdes_net_if;
u16 gp_status1 = 0, lnkup = 0, lnkup_kr = 0;
- u16 lane = bnx2x_get_warpcore_lane(phy, params);
vars->turn_to_run_wc_rt = vars->turn_to_run_wc_rt ? 0 : 1;
if (!vars->turn_to_run_wc_rt)
return;
- /* Return if there is no link partner */
- if (!(bnx2x_warpcore_get_sigdet(phy, params))) {
- DP(NETIF_MSG_LINK, "bnx2x_warpcore_get_sigdet false\n");
- return;
- }
-
if (vars->rx_tx_asic_rst) {
+ u16 lane = bnx2x_get_warpcore_lane(phy, params);
serdes_net_if = (REG_RD(bp, params->shmem_base +
offsetof(struct shmem_region, dev_info.
port_hw_config[params->port].default_cfg)) &
@@ -4375,14 +4398,8 @@ static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
/*10G KR*/
lnkup_kr = (gp_status1 >> (12+lane)) & 0x1;
- DP(NETIF_MSG_LINK,
- "gp_status1 0x%x\n", gp_status1);
-
if (lnkup_kr || lnkup) {
- vars->rx_tx_asic_rst = 0;
- DP(NETIF_MSG_LINK,
- "link up, rx_tx_asic_rst 0x%x\n",
- vars->rx_tx_asic_rst);
+ vars->rx_tx_asic_rst = 0;
} else {
/* Reset the lane to see if link comes up.*/
bnx2x_warpcore_reset_lane(bp, phy, 1);
@@ -4507,10 +4524,14 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
* enabled transmitter to avoid current leakage in case
* no module is connected
*/
- if (bnx2x_is_sfp_module_plugged(phy, params))
- bnx2x_sfp_module_detection(phy, params);
- else
- bnx2x_sfp_e3_set_transmitter(params, phy, 1);
+ if ((params->loopback_mode == LOOPBACK_NONE) ||
+ (params->loopback_mode == LOOPBACK_EXT)) {
+ if (bnx2x_is_sfp_module_plugged(phy, params))
+ bnx2x_sfp_module_detection(phy, params);
+ else
+ bnx2x_sfp_e3_set_transmitter(params,
+ phy, 1);
+ }
bnx2x_warpcore_config_sfi(phy, params);
break;
@@ -5757,6 +5778,11 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, gp_speed,
duplex);
+ /* In case of KR link down, start up the recovering procedure */
+ if ((!link_up) && (phy->media_type == ETH_PHY_KR) &&
+ (!(phy->flags & FLAGS_WC_DUAL_MODE)))
+ vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
+
DP(NETIF_MSG_LINK, "duplex %x flow_ctrl 0x%x link_status 0x%x\n",
vars->duplex, vars->flow_ctrl, vars->link_status);
return rc;
@@ -6507,6 +6533,11 @@ static int bnx2x_link_initialize(struct link_params *params,
params->phy[INT_PHY].config_init(phy, params, vars);
}
+ /* Re-read this value in case it was changed inside config_init due to
+ * limitations of optic module
+ */
+ vars->line_speed = params->phy[INT_PHY].req_line_speed;
+
/* Init external phy*/
if (non_ext_phy) {
if (params->phy[INT_PHY].supported &
@@ -8080,7 +8111,10 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
if (copper_module_type &
SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE) {
DP(NETIF_MSG_LINK, "Active Copper cable detected\n");
- check_limiting_mode = 1;
+ if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
+ *edc_mode = EDC_MODE_ACTIVE_DAC;
+ else
+ check_limiting_mode = 1;
} else if (copper_module_type &
SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
DP(NETIF_MSG_LINK,
@@ -8555,6 +8589,7 @@ static void bnx2x_warpcore_set_limiting_mode(struct link_params *params,
mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT;
break;
case EDC_MODE_PASSIVE_DAC:
+ case EDC_MODE_ACTIVE_DAC:
mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_DAC;
break;
default:
@@ -9730,32 +9765,41 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
an_1000_val);
- /* set 100 speed advertisement */
- if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
- (phy->speed_cap_mask &
- (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
- PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF))) {
- an_10_100_val |= (1<<7);
- /* Enable autoneg and restart autoneg for legacy speeds */
- autoneg_val |= (1<<9 | 1<<12);
-
- if (phy->req_duplex == DUPLEX_FULL)
+ /* Set 10/100 speed advertisement */
+ if (phy->req_line_speed == SPEED_AUTO_NEG) {
+ if (phy->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL) {
+ /* Enable autoneg and restart autoneg for legacy speeds
+ */
+ autoneg_val |= (1<<9 | 1<<12);
an_10_100_val |= (1<<8);
- DP(NETIF_MSG_LINK, "Advertising 100M\n");
- }
- /* set 10 speed advertisement */
- if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
- (phy->speed_cap_mask &
- (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
- PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)) &&
- (phy->supported &
- (SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full)))) {
- an_10_100_val |= (1<<5);
- autoneg_val |= (1<<9 | 1<<12);
- if (phy->req_duplex == DUPLEX_FULL)
+ DP(NETIF_MSG_LINK, "Advertising 100M-FD\n");
+ }
+
+ if (phy->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF) {
+ /* Enable autoneg and restart autoneg for legacy speeds
+ */
+ autoneg_val |= (1<<9 | 1<<12);
+ an_10_100_val |= (1<<7);
+ DP(NETIF_MSG_LINK, "Advertising 100M-HD\n");
+ }
+
+ if ((phy->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
+ (phy->supported & SUPPORTED_10baseT_Full)) {
an_10_100_val |= (1<<6);
- DP(NETIF_MSG_LINK, "Advertising 10M\n");
+ autoneg_val |= (1<<9 | 1<<12);
+ DP(NETIF_MSG_LINK, "Advertising 10M-FD\n");
+ }
+
+ if ((phy->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF) &&
+ (phy->supported & SUPPORTED_10baseT_Half)) {
+ an_10_100_val |= (1<<5);
+ autoneg_val |= (1<<9 | 1<<12);
+ DP(NETIF_MSG_LINK, "Advertising 10M-HD\n");
+ }
}
/* Only 10/100 are allowed to work in FORCE mode */
@@ -13432,43 +13476,6 @@ static void bnx2x_sfp_tx_fault_detection(struct bnx2x_phy *phy,
}
}
}
-static void bnx2x_disable_kr2(struct link_params *params,
- struct link_vars *vars,
- struct bnx2x_phy *phy)
-{
- struct bnx2x *bp = params->bp;
- int i;
- static struct bnx2x_reg_set reg_set[] = {
- /* Step 1 - Program the TX/RX alignment markers */
- {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0x7690},
- {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xe647},
- {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0xc4f0},
- {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0x7690},
- {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xe647},
- {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0xc4f0},
- {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000c},
- {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6000},
- {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0000},
- {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0002},
- {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x0000},
- {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x0af7},
- {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x0af7},
- {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0002},
- {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0000}
- };
- DP(NETIF_MSG_LINK, "Disabling 20G-KR2\n");
-
- for (i = 0; i < ARRAY_SIZE(reg_set); i++)
- bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
- reg_set[i].val);
- vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
- bnx2x_update_link_attr(params, vars->link_attr_sync);
-
- vars->check_kr2_recovery_cnt = CHECK_KR2_RECOVERY_CNT;
- /* Restart AN on leading lane */
- bnx2x_warpcore_restart_AN_KR(phy, params);
-}
-
static void bnx2x_kr2_recovery(struct link_params *params,
struct link_vars *vars,
struct bnx2x_phy *phy)
@@ -13546,6 +13553,8 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
/* Disable KR2 on both lanes */
DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page, next_page);
bnx2x_disable_kr2(params, vars, phy);
+ /* Restart AN on leading lane */
+ bnx2x_warpcore_restart_AN_KR(phy, params);
return;
}
}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index a6704b555042..82b658d8c04c 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -4703,6 +4703,14 @@ bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print)
attn.sig[3] = REG_RD(bp,
MISC_REG_AEU_AFTER_INVERT_4_FUNC_0 +
port*4);
+ /* Since MCP attentions can't be disabled inside the block, we need to
+ * read AEU registers to see whether they're currently disabled
+ */
+ attn.sig[3] &= ((REG_RD(bp,
+ !port ? MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0
+ : MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0) &
+ MISC_AEU_ENABLE_MCP_PRTY_BITS) |
+ ~MISC_AEU_ENABLE_MCP_PRTY_BITS);
if (!CHIP_IS_E1x(bp))
attn.sig[4] = REG_RD(bp,
@@ -5447,26 +5455,24 @@ static void bnx2x_timer(unsigned long data)
if (IS_PF(bp) &&
!BP_NOMCP(bp)) {
int mb_idx = BP_FW_MB_IDX(bp);
- u32 drv_pulse;
- u32 mcp_pulse;
+ u16 drv_pulse;
+ u16 mcp_pulse;
++bp->fw_drv_pulse_wr_seq;
bp->fw_drv_pulse_wr_seq &= DRV_PULSE_SEQ_MASK;
- /* TBD - add SYSTEM_TIME */
drv_pulse = bp->fw_drv_pulse_wr_seq;
bnx2x_drv_pulse(bp);
mcp_pulse = (SHMEM_RD(bp, func_mb[mb_idx].mcp_pulse_mb) &
MCP_PULSE_SEQ_MASK);
/* The delta between driver pulse and mcp response
- * should be 1 (before mcp response) or 0 (after mcp response)
+ * should not get too big. If the MFW is more than 5 pulses
+ * behind, we should worry about it enough to generate an error
+ * log.
*/
- if ((drv_pulse != mcp_pulse) &&
- (drv_pulse != ((mcp_pulse + 1) & MCP_PULSE_SEQ_MASK))) {
- /* someone lost a heartbeat... */
- BNX2X_ERR("drv_pulse (0x%x) != mcp_pulse (0x%x)\n",
+ if (((drv_pulse - mcp_pulse) & MCP_PULSE_SEQ_MASK) > 5)
+ BNX2X_ERR("MFW seems hanged: drv_pulse (0x%x) != mcp_pulse (0x%x)\n",
drv_pulse, mcp_pulse);
- }
}
if (bp->state == BNX2X_STATE_OPEN)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index 2604b6204abe..49c61ed6d673 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -1819,7 +1819,7 @@ bnx2x_get_vf_igu_cam_info(struct bnx2x *bp)
fid = GET_FIELD((val), IGU_REG_MAPPING_MEMORY_FID);
if (fid & IGU_FID_ENCODE_IS_PF)
current_pf = fid & IGU_FID_PF_NUM_MASK;
- else if (current_pf == BP_ABS_FUNC(bp))
+ else if (current_pf == BP_FUNC(bp))
bnx2x_vf_set_igu_info(bp, sb_id,
(fid & IGU_FID_VF_NUM_MASK));
DP(BNX2X_MSG_IOV, "%s[%d], igu_sb_id=%d, msix=%d\n",
@@ -2802,7 +2802,7 @@ struct set_vf_state_cookie {
u8 state;
};
-void bnx2x_set_vf_state(void *cookie)
+static void bnx2x_set_vf_state(void *cookie)
{
struct set_vf_state_cookie *p = (struct set_vf_state_cookie *)cookie;
@@ -3180,6 +3180,7 @@ int bnx2x_enable_sriov(struct bnx2x *bp)
/* set local queue arrays */
vf->vfqs = &bp->vfdb->vfqs[qcount];
qcount += vf_sb_count(vf);
+ bnx2x_iov_static_resc(bp, vf);
}
/* prepare msix vectors in VF configuration space */
@@ -3187,6 +3188,8 @@ int bnx2x_enable_sriov(struct bnx2x *bp)
bnx2x_pretend_func(bp, HW_VF_HANDLE(bp, vf_idx));
REG_WR(bp, PCICFG_OFFSET + GRC_CONFIG_REG_VF_MSIX_CONTROL,
num_vf_queues);
+ DP(BNX2X_MSG_IOV, "set msix vec num in VF %d cfg space to %d\n",
+ vf_idx, num_vf_queues);
}
bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
@@ -3222,8 +3225,9 @@ void bnx2x_disable_sriov(struct bnx2x *bp)
pci_disable_sriov(bp->pdev);
}
-int bnx2x_vf_ndo_prep(struct bnx2x *bp, int vfidx, struct bnx2x_virtf **vf,
- struct pf_vf_bulletin_content **bulletin)
+static int bnx2x_vf_ndo_prep(struct bnx2x *bp, int vfidx,
+ struct bnx2x_virtf **vf,
+ struct pf_vf_bulletin_content **bulletin)
{
if (bp->state != BNX2X_STATE_OPEN) {
BNX2X_ERR("vf ndo called though PF is down\n");
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index 6cfb88732452..da16953eb2ec 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -1765,28 +1765,28 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
switch (mbx->first_tlv.tl.type) {
case CHANNEL_TLV_ACQUIRE:
bnx2x_vf_mbx_acquire(bp, vf, mbx);
- break;
+ return;
case CHANNEL_TLV_INIT:
bnx2x_vf_mbx_init_vf(bp, vf, mbx);
- break;
+ return;
case CHANNEL_TLV_SETUP_Q:
bnx2x_vf_mbx_setup_q(bp, vf, mbx);
- break;
+ return;
case CHANNEL_TLV_SET_Q_FILTERS:
bnx2x_vf_mbx_set_q_filters(bp, vf, mbx);
- break;
+ return;
case CHANNEL_TLV_TEARDOWN_Q:
bnx2x_vf_mbx_teardown_q(bp, vf, mbx);
- break;
+ return;
case CHANNEL_TLV_CLOSE:
bnx2x_vf_mbx_close_vf(bp, vf, mbx);
- break;
+ return;
case CHANNEL_TLV_RELEASE:
bnx2x_vf_mbx_release_vf(bp, vf, mbx);
- break;
+ return;
case CHANNEL_TLV_UPDATE_RSS:
bnx2x_vf_mbx_update_rss(bp, vf, mbx);
- break;
+ return;
}
} else {
@@ -1802,26 +1802,24 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
for (i = 0; i < 20; i++)
DP_CONT(BNX2X_MSG_IOV, "%x ",
mbx->msg->req.tlv_buf_size.tlv_buffer[i]);
+ }
- /* test whether we can respond to the VF (do we have an address
- * for it?)
- */
- if (vf->state == VF_ACQUIRED || vf->state == VF_ENABLED) {
- /* mbx_resp uses the op_rc of the VF */
- vf->op_rc = PFVF_STATUS_NOT_SUPPORTED;
+ /* can we respond to VF (do we have an address for it?) */
+ if (vf->state == VF_ACQUIRED || vf->state == VF_ENABLED) {
+ /* mbx_resp uses the op_rc of the VF */
+ vf->op_rc = PFVF_STATUS_NOT_SUPPORTED;
- /* notify the VF that we do not support this request */
- bnx2x_vf_mbx_resp(bp, vf);
- } else {
- /* can't send a response since this VF is unknown to us
- * just ack the FW to release the mailbox and unlock
- * the channel.
- */
- storm_memset_vf_mbx_ack(bp, vf->abs_vfid);
- mmiowb();
- bnx2x_unlock_vf_pf_channel(bp, vf,
- mbx->first_tlv.tl.type);
- }
+ /* notify the VF that we do not support this request */
+ bnx2x_vf_mbx_resp(bp, vf);
+ } else {
+ /* can't send a response since this VF is unknown to us
+ * just ack the FW to release the mailbox and unlock
+ * the channel.
+ */
+ storm_memset_vf_mbx_ack(bp, vf->abs_vfid);
+ /* Firmware ack should be written before unlocking channel */
+ mmiowb();
+ bnx2x_unlock_vf_pf_channel(bp, vf, mbx->first_tlv.tl.type);
}
}
diff --git a/drivers/net/ethernet/broadcom/cnic_if.h b/drivers/net/ethernet/broadcom/cnic_if.h
index 0658b43e148c..ebbfe25acaa6 100644
--- a/drivers/net/ethernet/broadcom/cnic_if.h
+++ b/drivers/net/ethernet/broadcom/cnic_if.h
@@ -353,8 +353,8 @@ struct cnic_ulp_ops {
atomic_t ref_count;
};
-extern int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops);
+int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops);
-extern int cnic_unregister_driver(int ulp_type);
+int cnic_unregister_driver(int ulp_type);
#endif
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 12d961c4ebca..221a1815fd36 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -94,10 +94,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
#define DRV_MODULE_NAME "tg3"
#define TG3_MAJ_NUM 3
-#define TG3_MIN_NUM 133
+#define TG3_MIN_NUM 134
#define DRV_MODULE_VERSION \
__stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE "Jul 29, 2013"
+#define DRV_MODULE_RELDATE "Sep 16, 2013"
#define RESET_KIND_SHUTDOWN 0
#define RESET_KIND_INIT 1
@@ -337,6 +337,11 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5762)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5725)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5727)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57764)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57767)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57787)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57782)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57786)},
{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)},
{PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)},
@@ -1326,6 +1331,12 @@ static int tg3_phy_toggle_auxctl_smdsp(struct tg3 *tp, bool enable)
return err;
}
+static int tg3_phy_shdw_write(struct tg3 *tp, int reg, u32 val)
+{
+ return tg3_writephy(tp, MII_TG3_MISC_SHDW,
+ reg | val | MII_TG3_MISC_SHDW_WREN);
+}
+
static int tg3_bmcr_reset(struct tg3 *tp)
{
u32 phy_control;
@@ -2218,25 +2229,21 @@ static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable)
return;
}
- reg = MII_TG3_MISC_SHDW_WREN |
- MII_TG3_MISC_SHDW_SCR5_SEL |
- MII_TG3_MISC_SHDW_SCR5_LPED |
+ reg = MII_TG3_MISC_SHDW_SCR5_LPED |
MII_TG3_MISC_SHDW_SCR5_DLPTLM |
MII_TG3_MISC_SHDW_SCR5_SDTL |
MII_TG3_MISC_SHDW_SCR5_C125OE;
if (tg3_asic_rev(tp) != ASIC_REV_5784 || !enable)
reg |= MII_TG3_MISC_SHDW_SCR5_DLLAPD;
- tg3_writephy(tp, MII_TG3_MISC_SHDW, reg);
+ tg3_phy_shdw_write(tp, MII_TG3_MISC_SHDW_SCR5_SEL, reg);
- reg = MII_TG3_MISC_SHDW_WREN |
- MII_TG3_MISC_SHDW_APD_SEL |
- MII_TG3_MISC_SHDW_APD_WKTM_84MS;
+ reg = MII_TG3_MISC_SHDW_APD_WKTM_84MS;
if (enable)
reg |= MII_TG3_MISC_SHDW_APD_ENABLE;
- tg3_writephy(tp, MII_TG3_MISC_SHDW, reg);
+ tg3_phy_shdw_write(tp, MII_TG3_MISC_SHDW_APD_SEL, reg);
}
static void tg3_phy_toggle_automdix(struct tg3 *tp, bool enable)
@@ -9196,10 +9203,7 @@ static int tg3_halt(struct tg3 *tp, int kind, bool silent)
memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
}
- if (err)
- return err;
-
- return 0;
+ return err;
}
static int tg3_set_mac_addr(struct net_device *dev, void *p)
@@ -11035,7 +11039,18 @@ static int tg3_request_irq(struct tg3 *tp, int irq_num)
name = tp->dev->name;
else {
name = &tnapi->irq_lbl[0];
- snprintf(name, IFNAMSIZ, "%s-%d", tp->dev->name, irq_num);
+ if (tnapi->tx_buffers && tnapi->rx_rcb)
+ snprintf(name, IFNAMSIZ,
+ "%s-txrx-%d", tp->dev->name, irq_num);
+ else if (tnapi->tx_buffers)
+ snprintf(name, IFNAMSIZ,
+ "%s-tx-%d", tp->dev->name, irq_num);
+ else if (tnapi->rx_rcb)
+ snprintf(name, IFNAMSIZ,
+ "%s-rx-%d", tp->dev->name, irq_num);
+ else
+ snprintf(name, IFNAMSIZ,
+ "%s-%d", tp->dev->name, irq_num);
name[IFNAMSIZ-1] = 0;
}
@@ -12093,12 +12108,10 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
device_set_wakeup_enable(dp, wol->wolopts & WAKE_MAGIC);
- spin_lock_bh(&tp->lock);
if (device_may_wakeup(dp))
tg3_flag_set(tp, WOL_ENABLE);
else
tg3_flag_clear(tp, WOL_ENABLE);
- spin_unlock_bh(&tp->lock);
return 0;
}
@@ -14921,6 +14934,12 @@ static void tg3_get_eeprom_hw_cfg(struct tg3 *tp)
tg3_chip_rev_id(tp) != CHIPREV_ID_5750_A1)
tp->led_ctrl |= (LED_CTRL_MODE_PHY_1 |
LED_CTRL_MODE_PHY_2);
+
+ if (tg3_flag(tp, 5717_PLUS) ||
+ tg3_asic_rev(tp) == ASIC_REV_5762)
+ tp->led_ctrl |= LED_CTRL_BLINK_RATE_OVERRIDE |
+ LED_CTRL_BLINK_RATE_MASK;
+
break;
case SHASTA_EXT_LED_MAC:
@@ -15759,9 +15778,12 @@ static void tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57767 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57764 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5762 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5725 ||
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_5727)
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5727 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57787)
reg = TG3PCI_GEN2_PRODID_ASICREV;
else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785 ||
@@ -17052,10 +17074,6 @@ static int tg3_test_dma(struct tg3 *tp)
tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
-#if 0
- /* Unneeded, already done by tg3_get_invariants. */
- tg3_switch_clocks(tp);
-#endif
if (tg3_asic_rev(tp) != ASIC_REV_5700 &&
tg3_asic_rev(tp) != ASIC_REV_5701)
@@ -17083,20 +17101,6 @@ static int tg3_test_dma(struct tg3 *tp)
break;
}
-#if 0
- /* validate data reached card RAM correctly. */
- for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) {
- u32 val;
- tg3_read_mem(tp, 0x2100 + (i*4), &val);
- if (le32_to_cpu(val) != p[i]) {
- dev_err(&tp->pdev->dev,
- "%s: Buffer corrupted on device! "
- "(%d != %d)\n", __func__, val, i);
- /* ret = -ENODEV here? */
- }
- p[i] = 0;
- }
-#endif
/* Now read it back. */
ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, false);
if (ret) {
@@ -17409,9 +17413,12 @@ static int tg3_init_one(struct pci_dev *pdev,
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57767 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57764 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5762 ||
tp->pdev->device == TG3PCI_DEVICE_TIGON3_5725 ||
- tp->pdev->device == TG3PCI_DEVICE_TIGON3_5727) {
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_5727 ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57787) {
tg3_flag_set(tp, ENABLE_APE);
tp->aperegs = pci_ioremap_bar(pdev, BAR_2);
if (!tp->aperegs) {
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index 70257808aa37..5c3835aa1e1b 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -68,6 +68,9 @@
#define TG3PCI_DEVICE_TIGON3_5762 0x1687
#define TG3PCI_DEVICE_TIGON3_5725 0x1643
#define TG3PCI_DEVICE_TIGON3_5727 0x16f3
+#define TG3PCI_DEVICE_TIGON3_57764 0x1642
+#define TG3PCI_DEVICE_TIGON3_57767 0x1683
+#define TG3PCI_DEVICE_TIGON3_57787 0x1641
/* 0x04 --> 0x2c unused */
#define TG3PCI_SUBVENDOR_ID_BROADCOM PCI_VENDOR_ID_BROADCOM
#define TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6 0x1644
diff --git a/drivers/net/ethernet/brocade/bna/bnad.h b/drivers/net/ethernet/brocade/bna/bnad.h
index aefee77523f2..f7e033f8a00e 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.h
+++ b/drivers/net/ethernet/brocade/bna/bnad.h
@@ -372,38 +372,37 @@ extern u32 bnad_rxqs_per_cq;
/*
* EXTERN PROTOTYPES
*/
-extern u32 *cna_get_firmware_buf(struct pci_dev *pdev);
+u32 *cna_get_firmware_buf(struct pci_dev *pdev);
/* Netdev entry point prototypes */
-extern void bnad_set_rx_mode(struct net_device *netdev);
-extern struct net_device_stats *bnad_get_netdev_stats(
- struct net_device *netdev);
-extern int bnad_mac_addr_set_locked(struct bnad *bnad, u8 *mac_addr);
-extern int bnad_enable_default_bcast(struct bnad *bnad);
-extern void bnad_restore_vlans(struct bnad *bnad, u32 rx_id);
-extern void bnad_set_ethtool_ops(struct net_device *netdev);
-extern void bnad_cb_completion(void *arg, enum bfa_status status);
+void bnad_set_rx_mode(struct net_device *netdev);
+struct net_device_stats *bnad_get_netdev_stats(struct net_device *netdev);
+int bnad_mac_addr_set_locked(struct bnad *bnad, u8 *mac_addr);
+int bnad_enable_default_bcast(struct bnad *bnad);
+void bnad_restore_vlans(struct bnad *bnad, u32 rx_id);
+void bnad_set_ethtool_ops(struct net_device *netdev);
+void bnad_cb_completion(void *arg, enum bfa_status status);
/* Configuration & setup */
-extern void bnad_tx_coalescing_timeo_set(struct bnad *bnad);
-extern void bnad_rx_coalescing_timeo_set(struct bnad *bnad);
+void bnad_tx_coalescing_timeo_set(struct bnad *bnad);
+void bnad_rx_coalescing_timeo_set(struct bnad *bnad);
-extern int bnad_setup_rx(struct bnad *bnad, u32 rx_id);
-extern int bnad_setup_tx(struct bnad *bnad, u32 tx_id);
-extern void bnad_destroy_tx(struct bnad *bnad, u32 tx_id);
-extern void bnad_destroy_rx(struct bnad *bnad, u32 rx_id);
+int bnad_setup_rx(struct bnad *bnad, u32 rx_id);
+int bnad_setup_tx(struct bnad *bnad, u32 tx_id);
+void bnad_destroy_tx(struct bnad *bnad, u32 tx_id);
+void bnad_destroy_rx(struct bnad *bnad, u32 rx_id);
/* Timer start/stop protos */
-extern void bnad_dim_timer_start(struct bnad *bnad);
+void bnad_dim_timer_start(struct bnad *bnad);
/* Statistics */
-extern void bnad_netdev_qstats_fill(struct bnad *bnad,
- struct rtnl_link_stats64 *stats);
-extern void bnad_netdev_hwstats_fill(struct bnad *bnad,
- struct rtnl_link_stats64 *stats);
+void bnad_netdev_qstats_fill(struct bnad *bnad,
+ struct rtnl_link_stats64 *stats);
+void bnad_netdev_hwstats_fill(struct bnad *bnad,
+ struct rtnl_link_stats64 *stats);
/* Debugfs */
-void bnad_debugfs_init(struct bnad *bnad);
-void bnad_debugfs_uninit(struct bnad *bnad);
+void bnad_debugfs_init(struct bnad *bnad);
+void bnad_debugfs_uninit(struct bnad *bnad);
/* MACROS */
/* To set & get the stats counters */
diff --git a/drivers/net/ethernet/chelsio/cxgb/common.h b/drivers/net/ethernet/chelsio/cxgb/common.h
index 5ccbed1784d2..8abb46b39032 100644
--- a/drivers/net/ethernet/chelsio/cxgb/common.h
+++ b/drivers/net/ethernet/chelsio/cxgb/common.h
@@ -324,30 +324,30 @@ static inline unsigned int core_ticks_per_usec(const adapter_t *adap)
return board_info(adap)->clock_core / 1000000;
}
-extern int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp);
-extern int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value);
-extern int t1_tpi_write(adapter_t *adapter, u32 addr, u32 value);
-extern int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *value);
-
-extern void t1_interrupts_enable(adapter_t *adapter);
-extern void t1_interrupts_disable(adapter_t *adapter);
-extern void t1_interrupts_clear(adapter_t *adapter);
-extern int t1_elmer0_ext_intr_handler(adapter_t *adapter);
-extern void t1_elmer0_ext_intr(adapter_t *adapter);
-extern int t1_slow_intr_handler(adapter_t *adapter);
-
-extern int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc);
-extern const struct board_info *t1_get_board_info(unsigned int board_id);
-extern const struct board_info *t1_get_board_info_from_ids(unsigned int devid,
+int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp);
+int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value);
+int t1_tpi_write(adapter_t *adapter, u32 addr, u32 value);
+int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *value);
+
+void t1_interrupts_enable(adapter_t *adapter);
+void t1_interrupts_disable(adapter_t *adapter);
+void t1_interrupts_clear(adapter_t *adapter);
+int t1_elmer0_ext_intr_handler(adapter_t *adapter);
+void t1_elmer0_ext_intr(adapter_t *adapter);
+int t1_slow_intr_handler(adapter_t *adapter);
+
+int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc);
+const struct board_info *t1_get_board_info(unsigned int board_id);
+const struct board_info *t1_get_board_info_from_ids(unsigned int devid,
unsigned short ssid);
-extern int t1_seeprom_read(adapter_t *adapter, u32 addr, __le32 *data);
-extern int t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
+int t1_seeprom_read(adapter_t *adapter, u32 addr, __le32 *data);
+int t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
struct adapter_params *p);
-extern int t1_init_hw_modules(adapter_t *adapter);
-extern int t1_init_sw_modules(adapter_t *adapter, const struct board_info *bi);
-extern void t1_free_sw_modules(adapter_t *adapter);
-extern void t1_fatal_err(adapter_t *adapter);
-extern void t1_link_changed(adapter_t *adapter, int port_id);
-extern void t1_link_negotiated(adapter_t *adapter, int port_id, int link_stat,
+int t1_init_hw_modules(adapter_t *adapter);
+int t1_init_sw_modules(adapter_t *adapter, const struct board_info *bi);
+void t1_free_sw_modules(adapter_t *adapter);
+void t1_fatal_err(adapter_t *adapter);
+void t1_link_changed(adapter_t *adapter, int port_id);
+void t1_link_negotiated(adapter_t *adapter, int port_id, int link_stat,
int speed, int duplex, int pause);
#endif /* _CXGB_COMMON_H_ */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index c73cabdbd4c0..85d0cda5fbfa 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3983,6 +3983,7 @@ static int cxgb4_inet6addr_handler(struct notifier_block *this,
struct net_device *event_dev;
int ret = NOTIFY_DONE;
struct bonding *bond = netdev_priv(ifa->idev->dev);
+ struct list_head *iter;
struct slave *slave;
struct pci_dev *first_pdev = NULL;
@@ -3995,7 +3996,7 @@ static int cxgb4_inet6addr_handler(struct notifier_block *this,
* in all of them only once.
*/
read_lock(&bond->lock);
- bond_for_each_slave(bond, slave) {
+ bond_for_each_slave(bond, slave, iter) {
if (!first_pdev) {
ret = clip_add(slave->dev, ifa, event);
/* If clip_add is success then only initialize
diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
index df296af20bd5..8475c4cda9e4 100644
--- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c
@@ -1396,8 +1396,9 @@ static inline void copy_frags(struct sk_buff *skb,
* Builds an sk_buff from the given packet gather list. Returns the
* sk_buff or %NULL if sk_buff allocation failed.
*/
-struct sk_buff *t4vf_pktgl_to_skb(const struct pkt_gl *gl,
- unsigned int skb_len, unsigned int pull_len)
+static struct sk_buff *t4vf_pktgl_to_skb(const struct pkt_gl *gl,
+ unsigned int skb_len,
+ unsigned int pull_len)
{
struct sk_buff *skb;
@@ -1443,7 +1444,7 @@ out:
* Releases the pages of a packet gather list. We do not own the last
* page on the list and do not free it.
*/
-void t4vf_pktgl_free(const struct pkt_gl *gl)
+static void t4vf_pktgl_free(const struct pkt_gl *gl)
{
int frag;
@@ -1640,7 +1641,7 @@ static inline void rspq_next(struct sge_rspq *rspq)
* on this queue. If the system is under memory shortage use a fairly
* long delay to help recovery.
*/
-int process_responses(struct sge_rspq *rspq, int budget)
+static int process_responses(struct sge_rspq *rspq, int budget)
{
struct sge_eth_rxq *rxq = container_of(rspq, struct sge_eth_rxq, rspq);
int budget_left = budget;
@@ -1893,7 +1894,7 @@ static unsigned int process_intrq(struct adapter *adapter)
* The MSI interrupt handler handles data events from SGE response queues as
* well as error and other async events as they all use the same MSI vector.
*/
-irqreturn_t t4vf_intr_msi(int irq, void *cookie)
+static irqreturn_t t4vf_intr_msi(int irq, void *cookie)
{
struct adapter *adapter = cookie;
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index ace5050dba38..4a0d3b786288 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -694,27 +694,27 @@ static inline int qnq_async_evt_rcvd(struct be_adapter *adapter)
return adapter->flags & BE_FLAGS_QNQ_ASYNC_EVT_RCVD;
}
-extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
- u16 num_popped);
-extern void be_link_status_update(struct be_adapter *adapter, u8 link_status);
-extern void be_parse_stats(struct be_adapter *adapter);
-extern int be_load_fw(struct be_adapter *adapter, u8 *func);
-extern bool be_is_wol_supported(struct be_adapter *adapter);
-extern bool be_pause_supported(struct be_adapter *adapter);
-extern u32 be_get_fw_log_level(struct be_adapter *adapter);
+void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
+ u16 num_popped);
+void be_link_status_update(struct be_adapter *adapter, u8 link_status);
+void be_parse_stats(struct be_adapter *adapter);
+int be_load_fw(struct be_adapter *adapter, u8 *func);
+bool be_is_wol_supported(struct be_adapter *adapter);
+bool be_pause_supported(struct be_adapter *adapter);
+u32 be_get_fw_log_level(struct be_adapter *adapter);
int be_update_queues(struct be_adapter *adapter);
int be_poll(struct napi_struct *napi, int budget);
/*
* internal function to initialize-cleanup roce device.
*/
-extern void be_roce_dev_add(struct be_adapter *);
-extern void be_roce_dev_remove(struct be_adapter *);
+void be_roce_dev_add(struct be_adapter *);
+void be_roce_dev_remove(struct be_adapter *);
/*
* internal function to open-close roce device during ifup-ifdown.
*/
-extern void be_roce_dev_open(struct be_adapter *);
-extern void be_roce_dev_close(struct be_adapter *);
+void be_roce_dev_open(struct be_adapter *);
+void be_roce_dev_close(struct be_adapter *);
#endif /* BE_H */
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index d026226db88c..84f8c5243655 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -1863,137 +1863,121 @@ struct be_cmd_resp_get_iface_list {
struct be_if_desc if_desc;
};
-extern int be_pci_fnum_get(struct be_adapter *adapter);
-extern int be_fw_wait_ready(struct be_adapter *adapter);
-extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
- bool permanent, u32 if_handle, u32 pmac_id);
-extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
- u32 if_id, u32 *pmac_id, u32 domain);
-extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id,
- int pmac_id, u32 domain);
-extern int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags,
- u32 en_flags, u32 *if_handle, u32 domain);
-extern int be_cmd_if_destroy(struct be_adapter *adapter, int if_handle,
- u32 domain);
-extern int be_cmd_eq_create(struct be_adapter *adapter, struct be_eq_obj *eqo);
-extern int be_cmd_cq_create(struct be_adapter *adapter,
- struct be_queue_info *cq, struct be_queue_info *eq,
- bool no_delay, int num_cqe_dma_coalesce);
-extern int be_cmd_mccq_create(struct be_adapter *adapter,
- struct be_queue_info *mccq,
- struct be_queue_info *cq);
-extern int be_cmd_txq_create(struct be_adapter *adapter,
- struct be_tx_obj *txo);
-extern int be_cmd_rxq_create(struct be_adapter *adapter,
- struct be_queue_info *rxq, u16 cq_id,
- u16 frag_size, u32 if_id, u32 rss, u8 *rss_id);
-extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
- int type);
-extern int be_cmd_rxq_destroy(struct be_adapter *adapter,
- struct be_queue_info *q);
-extern int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed,
- u8 *link_status, u32 dom);
-extern int be_cmd_reset(struct be_adapter *adapter);
-extern int be_cmd_get_stats(struct be_adapter *adapter,
- struct be_dma_mem *nonemb_cmd);
-extern int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
- struct be_dma_mem *nonemb_cmd);
-extern int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver,
- char *fw_on_flash);
-
-extern int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd);
-extern int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id,
- u16 *vtag_array, u32 num, bool untagged,
- bool promiscuous);
-extern int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 status);
-extern int be_cmd_set_flow_control(struct be_adapter *adapter,
- u32 tx_fc, u32 rx_fc);
-extern int be_cmd_get_flow_control(struct be_adapter *adapter,
- u32 *tx_fc, u32 *rx_fc);
-extern int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
+int be_pci_fnum_get(struct be_adapter *adapter);
+int be_fw_wait_ready(struct be_adapter *adapter);
+int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
+ bool permanent, u32 if_handle, u32 pmac_id);
+int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, u32 if_id,
+ u32 *pmac_id, u32 domain);
+int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id,
+ u32 domain);
+int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
+ u32 *if_handle, u32 domain);
+int be_cmd_if_destroy(struct be_adapter *adapter, int if_handle, u32 domain);
+int be_cmd_eq_create(struct be_adapter *adapter, struct be_eq_obj *eqo);
+int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq,
+ struct be_queue_info *eq, bool no_delay,
+ int num_cqe_dma_coalesce);
+int be_cmd_mccq_create(struct be_adapter *adapter, struct be_queue_info *mccq,
+ struct be_queue_info *cq);
+int be_cmd_txq_create(struct be_adapter *adapter, struct be_tx_obj *txo);
+int be_cmd_rxq_create(struct be_adapter *adapter, struct be_queue_info *rxq,
+ u16 cq_id, u16 frag_size, u32 if_id, u32 rss, u8 *rss_id);
+int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
+ int type);
+int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q);
+int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed,
+ u8 *link_status, u32 dom);
+int be_cmd_reset(struct be_adapter *adapter);
+int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd);
+int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
+ struct be_dma_mem *nonemb_cmd);
+int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver,
+ char *fw_on_flash);
+
+int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd);
+int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array,
+ u32 num, bool untagged, bool promiscuous);
+int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 status);
+int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc);
+int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc);
+int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
u32 *function_mode, u32 *function_caps, u16 *asic_rev);
-extern int be_cmd_reset_function(struct be_adapter *adapter);
-extern int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
- u32 rss_hash_opts, u16 table_size);
-extern int be_process_mcc(struct be_adapter *adapter);
-extern int be_cmd_set_beacon_state(struct be_adapter *adapter,
- u8 port_num, u8 beacon, u8 status, u8 state);
-extern int be_cmd_get_beacon_state(struct be_adapter *adapter,
- u8 port_num, u32 *state);
-extern int be_cmd_write_flashrom(struct be_adapter *adapter,
- struct be_dma_mem *cmd, u32 flash_oper,
- u32 flash_opcode, u32 buf_size);
-extern int lancer_cmd_write_object(struct be_adapter *adapter,
- struct be_dma_mem *cmd,
- u32 data_size, u32 data_offset,
- const char *obj_name,
- u32 *data_written, u8 *change_status,
- u8 *addn_status);
+int be_cmd_reset_function(struct be_adapter *adapter);
+int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
+ u32 rss_hash_opts, u16 table_size);
+int be_process_mcc(struct be_adapter *adapter);
+int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, u8 beacon,
+ u8 status, u8 state);
+int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num,
+ u32 *state);
+int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
+ u32 flash_oper, u32 flash_opcode, u32 buf_size);
+int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
+ u32 data_size, u32 data_offset,
+ const char *obj_name, u32 *data_written,
+ u8 *change_status, u8 *addn_status);
int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
- u32 data_size, u32 data_offset, const char *obj_name,
- u32 *data_read, u32 *eof, u8 *addn_status);
+ u32 data_size, u32 data_offset, const char *obj_name,
+ u32 *data_read, u32 *eof, u8 *addn_status);
int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
- int offset);
-extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
- struct be_dma_mem *nonemb_cmd);
-extern int be_cmd_fw_init(struct be_adapter *adapter);
-extern int be_cmd_fw_clean(struct be_adapter *adapter);
-extern void be_async_mcc_enable(struct be_adapter *adapter);
-extern void be_async_mcc_disable(struct be_adapter *adapter);
-extern int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
- u32 loopback_type, u32 pkt_size,
- u32 num_pkts, u64 pattern);
-extern int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern,
- u32 byte_cnt, struct be_dma_mem *cmd);
-extern int be_cmd_get_seeprom_data(struct be_adapter *adapter,
- struct be_dma_mem *nonemb_cmd);
-extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
- u8 loopback_type, u8 enable);
-extern int be_cmd_get_phy_info(struct be_adapter *adapter);
-extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain);
-extern void be_detect_error(struct be_adapter *adapter);
-extern int be_cmd_get_die_temperature(struct be_adapter *adapter);
-extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter);
-extern int be_cmd_req_native_mode(struct be_adapter *adapter);
-extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size);
-extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf);
-extern int be_cmd_get_fn_privileges(struct be_adapter *adapter,
- u32 *privilege, u32 domain);
-extern int be_cmd_set_fn_privileges(struct be_adapter *adapter,
- u32 privileges, u32 vf_num);
-extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
- bool *pmac_id_active, u32 *pmac_id,
- u8 domain);
-extern int be_cmd_get_active_mac(struct be_adapter *adapter, u32 pmac_id,
- u8 *mac);
-extern int be_cmd_get_perm_mac(struct be_adapter *adapter, u8 *mac);
-extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
- u8 mac_count, u32 domain);
-extern int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id,
- u32 dom);
-extern int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
- u32 domain, u16 intf_id, u16 hsw_mode);
-extern int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
- u32 domain, u16 intf_id, u8 *mode);
-extern int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter);
-extern int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter,
- struct be_dma_mem *cmd);
-extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
- struct be_dma_mem *cmd,
- struct be_fat_conf_params *cfgs);
-extern int lancer_wait_ready(struct be_adapter *adapter);
-extern int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask);
-extern int lancer_initiate_dump(struct be_adapter *adapter);
-extern bool dump_present(struct be_adapter *adapter);
-extern int lancer_test_and_set_rdy_state(struct be_adapter *adapter);
-extern int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name);
+ int offset);
+int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
+ struct be_dma_mem *nonemb_cmd);
+int be_cmd_fw_init(struct be_adapter *adapter);
+int be_cmd_fw_clean(struct be_adapter *adapter);
+void be_async_mcc_enable(struct be_adapter *adapter);
+void be_async_mcc_disable(struct be_adapter *adapter);
+int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
+ u32 loopback_type, u32 pkt_size, u32 num_pkts,
+ u64 pattern);
+int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, u32 byte_cnt,
+ struct be_dma_mem *cmd);
+int be_cmd_get_seeprom_data(struct be_adapter *adapter,
+ struct be_dma_mem *nonemb_cmd);
+int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
+ u8 loopback_type, u8 enable);
+int be_cmd_get_phy_info(struct be_adapter *adapter);
+int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain);
+void be_detect_error(struct be_adapter *adapter);
+int be_cmd_get_die_temperature(struct be_adapter *adapter);
+int be_cmd_get_cntl_attributes(struct be_adapter *adapter);
+int be_cmd_req_native_mode(struct be_adapter *adapter);
+int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size);
+void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf);
+int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege,
+ u32 domain);
+int be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges,
+ u32 vf_num);
+int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
+ bool *pmac_id_active, u32 *pmac_id, u8 domain);
+int be_cmd_get_active_mac(struct be_adapter *adapter, u32 pmac_id, u8 *mac);
+int be_cmd_get_perm_mac(struct be_adapter *adapter, u8 *mac);
+int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, u8 mac_count,
+ u32 domain);
+int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom);
+int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, u32 domain,
+ u16 intf_id, u16 hsw_mode);
+int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, u32 domain,
+ u16 intf_id, u8 *mode);
+int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter);
+int be_cmd_get_ext_fat_capabilites(struct be_adapter *adapter,
+ struct be_dma_mem *cmd);
+int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
+ struct be_dma_mem *cmd,
+ struct be_fat_conf_params *cfgs);
+int lancer_wait_ready(struct be_adapter *adapter);
+int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask);
+int lancer_initiate_dump(struct be_adapter *adapter);
+bool dump_present(struct be_adapter *adapter);
+int lancer_test_and_set_rdy_state(struct be_adapter *adapter);
+int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name);
int be_cmd_get_func_config(struct be_adapter *adapter,
struct be_resources *res);
int be_cmd_get_profile_config(struct be_adapter *adapter,
struct be_resources *res, u8 domain);
-extern int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps,
- u8 domain);
-extern int be_cmd_get_if_id(struct be_adapter *adapter,
- struct be_vf_cfg *vf_cfg, int vf_num);
-extern int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain);
-extern int be_cmd_intr_set(struct be_adapter *adapter, bool intr_enable);
+int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps, u8 domain);
+int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg,
+ int vf_num);
+int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain);
+int be_cmd_intr_set(struct be_adapter *adapter, bool intr_enable);
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 04112b98ff5d..114c58f9d8d2 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -1177,21 +1177,21 @@ static inline void gfar_read_filer(struct gfar_private *priv,
*fpr = gfar_read(&regs->rqfpr);
}
-extern void lock_rx_qs(struct gfar_private *priv);
-extern void lock_tx_qs(struct gfar_private *priv);
-extern void unlock_rx_qs(struct gfar_private *priv);
-extern void unlock_tx_qs(struct gfar_private *priv);
-extern irqreturn_t gfar_receive(int irq, void *dev_id);
-extern int startup_gfar(struct net_device *dev);
-extern void stop_gfar(struct net_device *dev);
-extern void gfar_halt(struct net_device *dev);
-extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev,
- int enable, u32 regnum, u32 read);
-extern void gfar_configure_coalescing_all(struct gfar_private *priv);
+void lock_rx_qs(struct gfar_private *priv);
+void lock_tx_qs(struct gfar_private *priv);
+void unlock_rx_qs(struct gfar_private *priv);
+void unlock_tx_qs(struct gfar_private *priv);
+irqreturn_t gfar_receive(int irq, void *dev_id);
+int startup_gfar(struct net_device *dev);
+void stop_gfar(struct net_device *dev);
+void gfar_halt(struct net_device *dev);
+void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, int enable,
+ u32 regnum, u32 read);
+void gfar_configure_coalescing_all(struct gfar_private *priv);
void gfar_init_sysfs(struct net_device *dev);
int gfar_set_features(struct net_device *dev, netdev_features_t features);
-extern void gfar_check_rx_parser_mode(struct gfar_private *priv);
-extern void gfar_vlan_mode(struct net_device *dev, netdev_features_t features);
+void gfar_check_rx_parser_mode(struct gfar_private *priv);
+void gfar_vlan_mode(struct net_device *dev, netdev_features_t features);
extern const struct ethtool_ops gfar_ethtool_ops;
diff --git a/drivers/net/ethernet/ibm/emac/debug.h b/drivers/net/ethernet/ibm/emac/debug.h
index 59a92d5870b5..9c45efe4c8fe 100644
--- a/drivers/net/ethernet/ibm/emac/debug.h
+++ b/drivers/net/ethernet/ibm/emac/debug.h
@@ -29,13 +29,13 @@
struct emac_instance;
struct mal_instance;
-extern void emac_dbg_register(struct emac_instance *dev);
-extern void emac_dbg_unregister(struct emac_instance *dev);
-extern void mal_dbg_register(struct mal_instance *mal);
-extern void mal_dbg_unregister(struct mal_instance *mal);
-extern int emac_init_debug(void) __init;
-extern void emac_fini_debug(void) __exit;
-extern void emac_dbg_dump_all(void);
+void emac_dbg_register(struct emac_instance *dev);
+void emac_dbg_unregister(struct emac_instance *dev);
+void mal_dbg_register(struct mal_instance *mal);
+void mal_dbg_unregister(struct mal_instance *mal);
+int emac_init_debug(void) __init;
+void emac_fini_debug(void) __exit;
+void emac_dbg_dump_all(void);
# define DBG_LEVEL 1
diff --git a/drivers/net/ethernet/ibm/emac/rgmii.h b/drivers/net/ethernet/ibm/emac/rgmii.h
index 668bceeff4a2..d4f1374d1900 100644
--- a/drivers/net/ethernet/ibm/emac/rgmii.h
+++ b/drivers/net/ethernet/ibm/emac/rgmii.h
@@ -56,15 +56,15 @@ struct rgmii_instance {
#ifdef CONFIG_IBM_EMAC_RGMII
-extern int rgmii_init(void);
-extern void rgmii_exit(void);
-extern int rgmii_attach(struct platform_device *ofdev, int input, int mode);
-extern void rgmii_detach(struct platform_device *ofdev, int input);
-extern void rgmii_get_mdio(struct platform_device *ofdev, int input);
-extern void rgmii_put_mdio(struct platform_device *ofdev, int input);
-extern void rgmii_set_speed(struct platform_device *ofdev, int input, int speed);
-extern int rgmii_get_regs_len(struct platform_device *ofdev);
-extern void *rgmii_dump_regs(struct platform_device *ofdev, void *buf);
+int rgmii_init(void);
+void rgmii_exit(void);
+int rgmii_attach(struct platform_device *ofdev, int input, int mode);
+void rgmii_detach(struct platform_device *ofdev, int input);
+void rgmii_get_mdio(struct platform_device *ofdev, int input);
+void rgmii_put_mdio(struct platform_device *ofdev, int input);
+void rgmii_set_speed(struct platform_device *ofdev, int input, int speed);
+int rgmii_get_regs_len(struct platform_device *ofdev);
+void *rgmii_dump_regs(struct platform_device *ofdev, void *buf);
#else
diff --git a/drivers/net/ethernet/ibm/emac/tah.h b/drivers/net/ethernet/ibm/emac/tah.h
index 350b7096a041..4d5f336f07b3 100644
--- a/drivers/net/ethernet/ibm/emac/tah.h
+++ b/drivers/net/ethernet/ibm/emac/tah.h
@@ -72,13 +72,13 @@ struct tah_instance {
#ifdef CONFIG_IBM_EMAC_TAH
-extern int tah_init(void);
-extern void tah_exit(void);
-extern int tah_attach(struct platform_device *ofdev, int channel);
-extern void tah_detach(struct platform_device *ofdev, int channel);
-extern void tah_reset(struct platform_device *ofdev);
-extern int tah_get_regs_len(struct platform_device *ofdev);
-extern void *tah_dump_regs(struct platform_device *ofdev, void *buf);
+int tah_init(void);
+void tah_exit(void);
+int tah_attach(struct platform_device *ofdev, int channel);
+void tah_detach(struct platform_device *ofdev, int channel);
+void tah_reset(struct platform_device *ofdev);
+int tah_get_regs_len(struct platform_device *ofdev);
+void *tah_dump_regs(struct platform_device *ofdev, void *buf);
#else
diff --git a/drivers/net/ethernet/ibm/emac/zmii.h b/drivers/net/ethernet/ibm/emac/zmii.h
index 455bfb085493..0959c55b1459 100644
--- a/drivers/net/ethernet/ibm/emac/zmii.h
+++ b/drivers/net/ethernet/ibm/emac/zmii.h
@@ -53,15 +53,15 @@ struct zmii_instance {
#ifdef CONFIG_IBM_EMAC_ZMII
-extern int zmii_init(void);
-extern void zmii_exit(void);
-extern int zmii_attach(struct platform_device *ofdev, int input, int *mode);
-extern void zmii_detach(struct platform_device *ofdev, int input);
-extern void zmii_get_mdio(struct platform_device *ofdev, int input);
-extern void zmii_put_mdio(struct platform_device *ofdev, int input);
-extern void zmii_set_speed(struct platform_device *ofdev, int input, int speed);
-extern int zmii_get_regs_len(struct platform_device *ocpdev);
-extern void *zmii_dump_regs(struct platform_device *ofdev, void *buf);
+int zmii_init(void);
+void zmii_exit(void);
+int zmii_attach(struct platform_device *ofdev, int input, int *mode);
+void zmii_detach(struct platform_device *ofdev, int input);
+void zmii_get_mdio(struct platform_device *ofdev, int input);
+void zmii_put_mdio(struct platform_device *ofdev, int input);
+void zmii_set_speed(struct platform_device *ofdev, int input, int speed);
+int zmii_get_regs_len(struct platform_device *ocpdev);
+void *zmii_dump_regs(struct platform_device *ofdev, void *buf);
#else
# define zmii_init() 0
diff --git a/drivers/net/ethernet/intel/e1000/e1000.h b/drivers/net/ethernet/intel/e1000/e1000.h
index 26d9cd59ec75..58c147271a36 100644
--- a/drivers/net/ethernet/intel/e1000/e1000.h
+++ b/drivers/net/ethernet/intel/e1000/e1000.h
@@ -325,7 +325,7 @@ enum e1000_state_t {
#undef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-extern struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
+struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
#define e_dbg(format, arg...) \
netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
#define e_err(msglvl, format, arg...) \
@@ -346,20 +346,20 @@ extern struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
extern char e1000_driver_name[];
extern const char e1000_driver_version[];
-extern int e1000_up(struct e1000_adapter *adapter);
-extern void e1000_down(struct e1000_adapter *adapter);
-extern void e1000_reinit_locked(struct e1000_adapter *adapter);
-extern void e1000_reset(struct e1000_adapter *adapter);
-extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
-extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
-extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
-extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
-extern void e1000_update_stats(struct e1000_adapter *adapter);
-extern bool e1000_has_link(struct e1000_adapter *adapter);
-extern void e1000_power_up_phy(struct e1000_adapter *);
-extern void e1000_set_ethtool_ops(struct net_device *netdev);
-extern void e1000_check_options(struct e1000_adapter *adapter);
-extern char *e1000_get_hw_dev_name(struct e1000_hw *hw);
+int e1000_up(struct e1000_adapter *adapter);
+void e1000_down(struct e1000_adapter *adapter);
+void e1000_reinit_locked(struct e1000_adapter *adapter);
+void e1000_reset(struct e1000_adapter *adapter);
+int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
+int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
+int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
+void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
+void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
+void e1000_update_stats(struct e1000_adapter *adapter);
+bool e1000_has_link(struct e1000_adapter *adapter);
+void e1000_power_up_phy(struct e1000_adapter *);
+void e1000_set_ethtool_ops(struct net_device *netdev);
+void e1000_check_options(struct e1000_adapter *adapter);
+char *e1000_get_hw_dev_name(struct e1000_hw *hw);
#endif /* _E1000_H_ */
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index ad0edd11015d..0150f7fc893d 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -472,26 +472,25 @@ enum latency_range {
extern char e1000e_driver_name[];
extern const char e1000e_driver_version[];
-extern void e1000e_check_options(struct e1000_adapter *adapter);
-extern void e1000e_set_ethtool_ops(struct net_device *netdev);
-
-extern int e1000e_up(struct e1000_adapter *adapter);
-extern void e1000e_down(struct e1000_adapter *adapter);
-extern void e1000e_reinit_locked(struct e1000_adapter *adapter);
-extern void e1000e_reset(struct e1000_adapter *adapter);
-extern void e1000e_power_up_phy(struct e1000_adapter *adapter);
-extern int e1000e_setup_rx_resources(struct e1000_ring *ring);
-extern int e1000e_setup_tx_resources(struct e1000_ring *ring);
-extern void e1000e_free_rx_resources(struct e1000_ring *ring);
-extern void e1000e_free_tx_resources(struct e1000_ring *ring);
-extern struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev,
- struct rtnl_link_stats64
- *stats);
-extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter);
-extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter);
-extern void e1000e_get_hw_control(struct e1000_adapter *adapter);
-extern void e1000e_release_hw_control(struct e1000_adapter *adapter);
-extern void e1000e_write_itr(struct e1000_adapter *adapter, u32 itr);
+void e1000e_check_options(struct e1000_adapter *adapter);
+void e1000e_set_ethtool_ops(struct net_device *netdev);
+
+int e1000e_up(struct e1000_adapter *adapter);
+void e1000e_down(struct e1000_adapter *adapter);
+void e1000e_reinit_locked(struct e1000_adapter *adapter);
+void e1000e_reset(struct e1000_adapter *adapter);
+void e1000e_power_up_phy(struct e1000_adapter *adapter);
+int e1000e_setup_rx_resources(struct e1000_ring *ring);
+int e1000e_setup_tx_resources(struct e1000_ring *ring);
+void e1000e_free_rx_resources(struct e1000_ring *ring);
+void e1000e_free_tx_resources(struct e1000_ring *ring);
+struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev,
+ struct rtnl_link_stats64 *stats);
+void e1000e_set_interrupt_capability(struct e1000_adapter *adapter);
+void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter);
+void e1000e_get_hw_control(struct e1000_adapter *adapter);
+void e1000e_release_hw_control(struct e1000_adapter *adapter);
+void e1000e_write_itr(struct e1000_adapter *adapter, u32 itr);
extern unsigned int copybreak;
@@ -508,8 +507,8 @@ extern const struct e1000_info e1000_pch2_info;
extern const struct e1000_info e1000_pch_lpt_info;
extern const struct e1000_info e1000_es2_info;
-extern void e1000e_ptp_init(struct e1000_adapter *adapter);
-extern void e1000e_ptp_remove(struct e1000_adapter *adapter);
+void e1000e_ptp_init(struct e1000_adapter *adapter);
+void e1000e_ptp_remove(struct e1000_adapter *adapter);
static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw)
{
@@ -536,7 +535,7 @@ static inline s32 e1e_wphy_locked(struct e1000_hw *hw, u32 offset, u16 data)
return hw->phy.ops.write_reg_locked(hw, offset, data);
}
-extern void e1000e_reload_nvm_generic(struct e1000_hw *hw);
+void e1000e_reload_nvm_generic(struct e1000_hw *hw);
static inline s32 e1000e_read_mac_addr(struct e1000_hw *hw)
{
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.h b/drivers/net/ethernet/intel/igb/e1000_82575.h
index 74a1506b4235..8c2437722aad 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.h
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.h
@@ -28,14 +28,14 @@
#ifndef _E1000_82575_H_
#define _E1000_82575_H_
-extern void igb_shutdown_serdes_link_82575(struct e1000_hw *hw);
-extern void igb_power_up_serdes_link_82575(struct e1000_hw *hw);
-extern void igb_power_down_phy_copper_82575(struct e1000_hw *hw);
-extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw);
-extern s32 igb_read_i2c_byte(struct e1000_hw *hw, u8 byte_offset,
- u8 dev_addr, u8 *data);
-extern s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset,
- u8 dev_addr, u8 data);
+void igb_shutdown_serdes_link_82575(struct e1000_hw *hw);
+void igb_power_up_serdes_link_82575(struct e1000_hw *hw);
+void igb_power_down_phy_copper_82575(struct e1000_hw *hw);
+void igb_rx_fifo_flush_82575(struct e1000_hw *hw);
+s32 igb_read_i2c_byte(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr,
+ u8 *data);
+s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr,
+ u8 data);
#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \
(ID_LED_DEF1_DEF2 << 8) | \
diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h
index 37a9c06a6c68..2e166b22d52b 100644
--- a/drivers/net/ethernet/intel/igb/e1000_hw.h
+++ b/drivers/net/ethernet/intel/igb/e1000_hw.h
@@ -562,11 +562,11 @@ struct e1000_hw {
u8 revision_id;
};
-extern struct net_device *igb_get_hw_dev(struct e1000_hw *hw);
+struct net_device *igb_get_hw_dev(struct e1000_hw *hw);
#define hw_dbg(format, arg...) \
netdev_dbg(igb_get_hw_dev(hw), format, ##arg)
/* These functions must be implemented by drivers */
-s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
-s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
+s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
+s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
#endif /* _E1000_HW_H_ */
diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.h b/drivers/net/ethernet/intel/igb/e1000_i210.h
index dde3c4b7ea99..2d913716573a 100644
--- a/drivers/net/ethernet/intel/igb/e1000_i210.h
+++ b/drivers/net/ethernet/intel/igb/e1000_i210.h
@@ -28,26 +28,24 @@
#ifndef _E1000_I210_H_
#define _E1000_I210_H_
-extern s32 igb_update_flash_i210(struct e1000_hw *hw);
-extern s32 igb_update_nvm_checksum_i210(struct e1000_hw *hw);
-extern s32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw);
-extern s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset,
- u16 words, u16 *data);
-extern s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset,
- u16 words, u16 *data);
-extern s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
-extern void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
-extern s32 igb_acquire_nvm_i210(struct e1000_hw *hw);
-extern void igb_release_nvm_i210(struct e1000_hw *hw);
-extern s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data);
-extern s32 igb_read_invm_version(struct e1000_hw *hw,
- struct e1000_fw_version *invm_ver);
-extern s32 igb_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr,
- u16 *data);
-extern s32 igb_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr,
- u16 data);
-extern s32 igb_init_nvm_params_i210(struct e1000_hw *hw);
-extern bool igb_get_flash_presence_i210(struct e1000_hw *hw);
+s32 igb_update_flash_i210(struct e1000_hw *hw);
+s32 igb_update_nvm_checksum_i210(struct e1000_hw *hw);
+s32 igb_validate_nvm_checksum_i210(struct e1000_hw *hw);
+s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
+s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
+s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
+void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
+s32 igb_acquire_nvm_i210(struct e1000_hw *hw);
+void igb_release_nvm_i210(struct e1000_hw *hw);
+s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data);
+s32 igb_read_invm_version(struct e1000_hw *hw,
+ struct e1000_fw_version *invm_ver);
+s32 igb_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data);
+s32 igb_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data);
+s32 igb_init_nvm_params_i210(struct e1000_hw *hw);
+bool igb_get_flash_presence_i210(struct e1000_hw *hw);
#define E1000_STM_OPCODE 0xDB00
#define E1000_EEPROM_FLASH_SIZE_WORD 0x11
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.h b/drivers/net/ethernet/intel/igb/e1000_mac.h
index 5e13e83cc608..e4cbe8ef67b3 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mac.h
+++ b/drivers/net/ethernet/intel/igb/e1000_mac.h
@@ -86,6 +86,6 @@ enum e1000_mng_mode {
#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2
-extern void e1000_init_function_pointers_82575(struct e1000_hw *hw);
+void e1000_init_function_pointers_82575(struct e1000_hw *hw);
#endif
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 6807b098edae..cdaa2bcefc4c 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -483,40 +483,37 @@ enum igb_boards {
extern char igb_driver_name[];
extern char igb_driver_version[];
-extern int igb_up(struct igb_adapter *);
-extern void igb_down(struct igb_adapter *);
-extern void igb_reinit_locked(struct igb_adapter *);
-extern void igb_reset(struct igb_adapter *);
-extern void igb_write_rss_indir_tbl(struct igb_adapter *);
-extern int igb_set_spd_dplx(struct igb_adapter *, u32, u8);
-extern int igb_setup_tx_resources(struct igb_ring *);
-extern int igb_setup_rx_resources(struct igb_ring *);
-extern void igb_free_tx_resources(struct igb_ring *);
-extern void igb_free_rx_resources(struct igb_ring *);
-extern void igb_configure_tx_ring(struct igb_adapter *, struct igb_ring *);
-extern void igb_configure_rx_ring(struct igb_adapter *, struct igb_ring *);
-extern void igb_setup_tctl(struct igb_adapter *);
-extern void igb_setup_rctl(struct igb_adapter *);
-extern netdev_tx_t igb_xmit_frame_ring(struct sk_buff *, struct igb_ring *);
-extern void igb_unmap_and_free_tx_resource(struct igb_ring *,
- struct igb_tx_buffer *);
-extern void igb_alloc_rx_buffers(struct igb_ring *, u16);
-extern void igb_update_stats(struct igb_adapter *, struct rtnl_link_stats64 *);
-extern bool igb_has_link(struct igb_adapter *adapter);
-extern void igb_set_ethtool_ops(struct net_device *);
-extern void igb_power_up_link(struct igb_adapter *);
-extern void igb_set_fw_version(struct igb_adapter *);
-extern void igb_ptp_init(struct igb_adapter *adapter);
-extern void igb_ptp_stop(struct igb_adapter *adapter);
-extern void igb_ptp_reset(struct igb_adapter *adapter);
-extern void igb_ptp_tx_work(struct work_struct *work);
-extern void igb_ptp_rx_hang(struct igb_adapter *adapter);
-extern void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter);
-extern void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
- struct sk_buff *skb);
-extern void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector,
- unsigned char *va,
- struct sk_buff *skb);
+int igb_up(struct igb_adapter *);
+void igb_down(struct igb_adapter *);
+void igb_reinit_locked(struct igb_adapter *);
+void igb_reset(struct igb_adapter *);
+void igb_write_rss_indir_tbl(struct igb_adapter *);
+int igb_set_spd_dplx(struct igb_adapter *, u32, u8);
+int igb_setup_tx_resources(struct igb_ring *);
+int igb_setup_rx_resources(struct igb_ring *);
+void igb_free_tx_resources(struct igb_ring *);
+void igb_free_rx_resources(struct igb_ring *);
+void igb_configure_tx_ring(struct igb_adapter *, struct igb_ring *);
+void igb_configure_rx_ring(struct igb_adapter *, struct igb_ring *);
+void igb_setup_tctl(struct igb_adapter *);
+void igb_setup_rctl(struct igb_adapter *);
+netdev_tx_t igb_xmit_frame_ring(struct sk_buff *, struct igb_ring *);
+void igb_unmap_and_free_tx_resource(struct igb_ring *, struct igb_tx_buffer *);
+void igb_alloc_rx_buffers(struct igb_ring *, u16);
+void igb_update_stats(struct igb_adapter *, struct rtnl_link_stats64 *);
+bool igb_has_link(struct igb_adapter *adapter);
+void igb_set_ethtool_ops(struct net_device *);
+void igb_power_up_link(struct igb_adapter *);
+void igb_set_fw_version(struct igb_adapter *);
+void igb_ptp_init(struct igb_adapter *adapter);
+void igb_ptp_stop(struct igb_adapter *adapter);
+void igb_ptp_reset(struct igb_adapter *adapter);
+void igb_ptp_tx_work(struct work_struct *work);
+void igb_ptp_rx_hang(struct igb_adapter *adapter);
+void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter);
+void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb);
+void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, unsigned char *va,
+ struct sk_buff *skb);
static inline void igb_ptp_rx_hwtstamp(struct igb_ring *rx_ring,
union e1000_adv_rx_desc *rx_desc,
struct sk_buff *skb)
@@ -531,11 +528,11 @@ static inline void igb_ptp_rx_hwtstamp(struct igb_ring *rx_ring,
rx_ring->last_rx_timestamp = jiffies;
}
-extern int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
- struct ifreq *ifr, int cmd);
+int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr,
+ int cmd);
#ifdef CONFIG_IGB_HWMON
-extern void igb_sysfs_exit(struct igb_adapter *adapter);
-extern int igb_sysfs_init(struct igb_adapter *adapter);
+void igb_sysfs_exit(struct igb_adapter *adapter);
+int igb_sysfs_init(struct igb_adapter *adapter);
#endif
static inline s32 igb_reset_phy(struct e1000_hw *hw)
{
diff --git a/drivers/net/ethernet/intel/igbvf/igbvf.h b/drivers/net/ethernet/intel/igbvf/igbvf.h
index a1463e3d14c0..7d6a25c8f889 100644
--- a/drivers/net/ethernet/intel/igbvf/igbvf.h
+++ b/drivers/net/ethernet/intel/igbvf/igbvf.h
@@ -312,17 +312,17 @@ enum igbvf_state_t {
extern char igbvf_driver_name[];
extern const char igbvf_driver_version[];
-extern void igbvf_check_options(struct igbvf_adapter *);
-extern void igbvf_set_ethtool_ops(struct net_device *);
-
-extern int igbvf_up(struct igbvf_adapter *);
-extern void igbvf_down(struct igbvf_adapter *);
-extern void igbvf_reinit_locked(struct igbvf_adapter *);
-extern int igbvf_setup_rx_resources(struct igbvf_adapter *, struct igbvf_ring *);
-extern int igbvf_setup_tx_resources(struct igbvf_adapter *, struct igbvf_ring *);
-extern void igbvf_free_rx_resources(struct igbvf_ring *);
-extern void igbvf_free_tx_resources(struct igbvf_ring *);
-extern void igbvf_update_stats(struct igbvf_adapter *);
+void igbvf_check_options(struct igbvf_adapter *);
+void igbvf_set_ethtool_ops(struct net_device *);
+
+int igbvf_up(struct igbvf_adapter *);
+void igbvf_down(struct igbvf_adapter *);
+void igbvf_reinit_locked(struct igbvf_adapter *);
+int igbvf_setup_rx_resources(struct igbvf_adapter *, struct igbvf_ring *);
+int igbvf_setup_tx_resources(struct igbvf_adapter *, struct igbvf_ring *);
+void igbvf_free_rx_resources(struct igbvf_ring *);
+void igbvf_free_tx_resources(struct igbvf_ring *);
+void igbvf_update_stats(struct igbvf_adapter *);
extern unsigned int copybreak;
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb.h b/drivers/net/ethernet/intel/ixgb/ixgb.h
index 4d2ae97ff1b3..2224cc2edf13 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb.h
+++ b/drivers/net/ethernet/intel/ixgb/ixgb.h
@@ -187,21 +187,21 @@ enum ixgb_state_t {
};
/* Exported from other modules */
-extern void ixgb_check_options(struct ixgb_adapter *adapter);
-extern void ixgb_set_ethtool_ops(struct net_device *netdev);
+void ixgb_check_options(struct ixgb_adapter *adapter);
+void ixgb_set_ethtool_ops(struct net_device *netdev);
extern char ixgb_driver_name[];
extern const char ixgb_driver_version[];
-extern void ixgb_set_speed_duplex(struct net_device *netdev);
+void ixgb_set_speed_duplex(struct net_device *netdev);
-extern int ixgb_up(struct ixgb_adapter *adapter);
-extern void ixgb_down(struct ixgb_adapter *adapter, bool kill_watchdog);
-extern void ixgb_reset(struct ixgb_adapter *adapter);
-extern int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
-extern int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
-extern void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
-extern void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
-extern void ixgb_update_stats(struct ixgb_adapter *adapter);
+int ixgb_up(struct ixgb_adapter *adapter);
+void ixgb_down(struct ixgb_adapter *adapter, bool kill_watchdog);
+void ixgb_reset(struct ixgb_adapter *adapter);
+int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
+int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
+void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
+void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
+void ixgb_update_stats(struct ixgb_adapter *adapter);
#endif /* _IXGB_H_ */
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_hw.h b/drivers/net/ethernet/intel/ixgb/ixgb_hw.h
index 2a99a35c33aa..0bd5d72e1af5 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_hw.h
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_hw.h
@@ -759,27 +759,20 @@ struct ixgb_hw_stats {
};
/* Function Prototypes */
-extern bool ixgb_adapter_stop(struct ixgb_hw *hw);
-extern bool ixgb_init_hw(struct ixgb_hw *hw);
-extern bool ixgb_adapter_start(struct ixgb_hw *hw);
-extern void ixgb_check_for_link(struct ixgb_hw *hw);
-extern bool ixgb_check_for_bad_link(struct ixgb_hw *hw);
-
-extern void ixgb_rar_set(struct ixgb_hw *hw,
- u8 *addr,
- u32 index);
+bool ixgb_adapter_stop(struct ixgb_hw *hw);
+bool ixgb_init_hw(struct ixgb_hw *hw);
+bool ixgb_adapter_start(struct ixgb_hw *hw);
+void ixgb_check_for_link(struct ixgb_hw *hw);
+bool ixgb_check_for_bad_link(struct ixgb_hw *hw);
+void ixgb_rar_set(struct ixgb_hw *hw, u8 *addr, u32 index);
/* Filters (multicast, vlan, receive) */
-extern void ixgb_mc_addr_list_update(struct ixgb_hw *hw,
- u8 *mc_addr_list,
- u32 mc_addr_count,
- u32 pad);
+void ixgb_mc_addr_list_update(struct ixgb_hw *hw, u8 *mc_addr_list,
+ u32 mc_addr_count, u32 pad);
/* Vfta functions */
-extern void ixgb_write_vfta(struct ixgb_hw *hw,
- u32 offset,
- u32 value);
+void ixgb_write_vfta(struct ixgb_hw *hw, u32 offset, u32 value);
/* Access functions to eeprom data */
void ixgb_get_ee_mac_addr(struct ixgb_hw *hw, u8 *mac_addr);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 0ac6b11c6e4e..3637841daea4 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -786,93 +786,89 @@ extern const char ixgbe_driver_version[];
extern char ixgbe_default_device_descr[];
#endif /* IXGBE_FCOE */
-extern void ixgbe_up(struct ixgbe_adapter *adapter);
-extern void ixgbe_down(struct ixgbe_adapter *adapter);
-extern void ixgbe_reinit_locked(struct ixgbe_adapter *adapter);
-extern void ixgbe_reset(struct ixgbe_adapter *adapter);
-extern void ixgbe_set_ethtool_ops(struct net_device *netdev);
-extern int ixgbe_setup_rx_resources(struct ixgbe_ring *);
-extern int ixgbe_setup_tx_resources(struct ixgbe_ring *);
-extern void ixgbe_free_rx_resources(struct ixgbe_ring *);
-extern void ixgbe_free_tx_resources(struct ixgbe_ring *);
-extern void ixgbe_configure_rx_ring(struct ixgbe_adapter *,struct ixgbe_ring *);
-extern void ixgbe_configure_tx_ring(struct ixgbe_adapter *,struct ixgbe_ring *);
-extern void ixgbe_disable_rx_queue(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *);
-extern void ixgbe_update_stats(struct ixgbe_adapter *adapter);
-extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
-extern int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
+void ixgbe_up(struct ixgbe_adapter *adapter);
+void ixgbe_down(struct ixgbe_adapter *adapter);
+void ixgbe_reinit_locked(struct ixgbe_adapter *adapter);
+void ixgbe_reset(struct ixgbe_adapter *adapter);
+void ixgbe_set_ethtool_ops(struct net_device *netdev);
+int ixgbe_setup_rx_resources(struct ixgbe_ring *);
+int ixgbe_setup_tx_resources(struct ixgbe_ring *);
+void ixgbe_free_rx_resources(struct ixgbe_ring *);
+void ixgbe_free_tx_resources(struct ixgbe_ring *);
+void ixgbe_configure_rx_ring(struct ixgbe_adapter *, struct ixgbe_ring *);
+void ixgbe_configure_tx_ring(struct ixgbe_adapter *, struct ixgbe_ring *);
+void ixgbe_disable_rx_queue(struct ixgbe_adapter *adapter, struct ixgbe_ring *);
+void ixgbe_update_stats(struct ixgbe_adapter *adapter);
+int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
+int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
u16 subdevice_id);
-extern void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter);
-extern netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *,
- struct ixgbe_adapter *,
- struct ixgbe_ring *);
-extern void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *,
- struct ixgbe_tx_buffer *);
-extern void ixgbe_alloc_rx_buffers(struct ixgbe_ring *, u16);
-extern void ixgbe_write_eitr(struct ixgbe_q_vector *);
-extern int ixgbe_poll(struct napi_struct *napi, int budget);
-extern int ethtool_ioctl(struct ifreq *ifr);
-extern s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw);
-extern s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl);
-extern s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl);
-extern s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
- union ixgbe_atr_hash_dword input,
- union ixgbe_atr_hash_dword common,
- u8 queue);
-extern s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
- union ixgbe_atr_input *input_mask);
-extern s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
- union ixgbe_atr_input *input,
- u16 soft_id, u8 queue);
-extern s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
- union ixgbe_atr_input *input,
- u16 soft_id);
-extern void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
- union ixgbe_atr_input *mask);
-extern bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
-extern void ixgbe_set_rx_mode(struct net_device *netdev);
+void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter);
+netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *, struct ixgbe_adapter *,
+ struct ixgbe_ring *);
+void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *,
+ struct ixgbe_tx_buffer *);
+void ixgbe_alloc_rx_buffers(struct ixgbe_ring *, u16);
+void ixgbe_write_eitr(struct ixgbe_q_vector *);
+int ixgbe_poll(struct napi_struct *napi, int budget);
+int ethtool_ioctl(struct ifreq *ifr);
+s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw);
+s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 fdirctrl);
+s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 fdirctrl);
+s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_hash_dword input,
+ union ixgbe_atr_hash_dword common,
+ u8 queue);
+s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input_mask);
+s32 ixgbe_fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input,
+ u16 soft_id, u8 queue);
+s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
+ union ixgbe_atr_input *input,
+ u16 soft_id);
+void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
+ union ixgbe_atr_input *mask);
+bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
+void ixgbe_set_rx_mode(struct net_device *netdev);
#ifdef CONFIG_IXGBE_DCB
-extern void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter);
+void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter);
#endif
-extern int ixgbe_setup_tc(struct net_device *dev, u8 tc);
-extern void ixgbe_tx_ctxtdesc(struct ixgbe_ring *, u32, u32, u32, u32);
-extern void ixgbe_do_reset(struct net_device *netdev);
+int ixgbe_setup_tc(struct net_device *dev, u8 tc);
+void ixgbe_tx_ctxtdesc(struct ixgbe_ring *, u32, u32, u32, u32);
+void ixgbe_do_reset(struct net_device *netdev);
#ifdef CONFIG_IXGBE_HWMON
-extern void ixgbe_sysfs_exit(struct ixgbe_adapter *adapter);
-extern int ixgbe_sysfs_init(struct ixgbe_adapter *adapter);
+void ixgbe_sysfs_exit(struct ixgbe_adapter *adapter);
+int ixgbe_sysfs_init(struct ixgbe_adapter *adapter);
#endif /* CONFIG_IXGBE_HWMON */
#ifdef IXGBE_FCOE
-extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter);
-extern int ixgbe_fso(struct ixgbe_ring *tx_ring,
- struct ixgbe_tx_buffer *first,
- u8 *hdr_len);
-extern int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
- union ixgbe_adv_rx_desc *rx_desc,
- struct sk_buff *skb);
-extern int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
- struct scatterlist *sgl, unsigned int sgc);
-extern int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid,
- struct scatterlist *sgl, unsigned int sgc);
-extern int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid);
-extern int ixgbe_setup_fcoe_ddp_resources(struct ixgbe_adapter *adapter);
-extern void ixgbe_free_fcoe_ddp_resources(struct ixgbe_adapter *adapter);
-extern int ixgbe_fcoe_enable(struct net_device *netdev);
-extern int ixgbe_fcoe_disable(struct net_device *netdev);
+void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter);
+int ixgbe_fso(struct ixgbe_ring *tx_ring, struct ixgbe_tx_buffer *first,
+ u8 *hdr_len);
+int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
+ union ixgbe_adv_rx_desc *rx_desc, struct sk_buff *skb);
+int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
+ struct scatterlist *sgl, unsigned int sgc);
+int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid,
+ struct scatterlist *sgl, unsigned int sgc);
+int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid);
+int ixgbe_setup_fcoe_ddp_resources(struct ixgbe_adapter *adapter);
+void ixgbe_free_fcoe_ddp_resources(struct ixgbe_adapter *adapter);
+int ixgbe_fcoe_enable(struct net_device *netdev);
+int ixgbe_fcoe_disable(struct net_device *netdev);
#ifdef CONFIG_IXGBE_DCB
-extern u8 ixgbe_fcoe_getapp(struct ixgbe_adapter *adapter);
-extern u8 ixgbe_fcoe_setapp(struct ixgbe_adapter *adapter, u8 up);
+u8 ixgbe_fcoe_getapp(struct ixgbe_adapter *adapter);
+u8 ixgbe_fcoe_setapp(struct ixgbe_adapter *adapter, u8 up);
#endif /* CONFIG_IXGBE_DCB */
-extern int ixgbe_fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type);
-extern int ixgbe_fcoe_get_hbainfo(struct net_device *netdev,
- struct netdev_fcoe_hbainfo *info);
-extern u8 ixgbe_fcoe_get_tc(struct ixgbe_adapter *adapter);
+int ixgbe_fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type);
+int ixgbe_fcoe_get_hbainfo(struct net_device *netdev,
+ struct netdev_fcoe_hbainfo *info);
+u8 ixgbe_fcoe_get_tc(struct ixgbe_adapter *adapter);
#endif /* IXGBE_FCOE */
#ifdef CONFIG_DEBUG_FS
-extern void ixgbe_dbg_adapter_init(struct ixgbe_adapter *adapter);
-extern void ixgbe_dbg_adapter_exit(struct ixgbe_adapter *adapter);
-extern void ixgbe_dbg_init(void);
-extern void ixgbe_dbg_exit(void);
+void ixgbe_dbg_adapter_init(struct ixgbe_adapter *adapter);
+void ixgbe_dbg_adapter_exit(struct ixgbe_adapter *adapter);
+void ixgbe_dbg_init(void);
+void ixgbe_dbg_exit(void);
#else
static inline void ixgbe_dbg_adapter_init(struct ixgbe_adapter *adapter) {}
static inline void ixgbe_dbg_adapter_exit(struct ixgbe_adapter *adapter) {}
@@ -884,12 +880,12 @@ static inline struct netdev_queue *txring_txq(const struct ixgbe_ring *ring)
return netdev_get_tx_queue(ring->netdev, ring->queue_index);
}
-extern void ixgbe_ptp_init(struct ixgbe_adapter *adapter);
-extern void ixgbe_ptp_stop(struct ixgbe_adapter *adapter);
-extern void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter);
-extern void ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter);
-extern void __ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector,
- struct sk_buff *skb);
+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)
@@ -906,11 +902,11 @@ static inline void ixgbe_ptp_rx_hwtstamp(struct ixgbe_ring *rx_ring,
rx_ring->last_rx_timestamp = jiffies;
}
-extern int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
- struct ifreq *ifr, int cmd);
-extern void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter);
-extern void ixgbe_ptp_reset(struct ixgbe_adapter *adapter);
-extern void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr);
+int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter, struct ifreq *ifr,
+ int cmd);
+void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter);
+void ixgbe_ptp_reset(struct ixgbe_adapter *adapter);
+void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr);
#ifdef CONFIG_PCI_IOV
void ixgbe_sriov_reinit(struct ixgbe_adapter *adapter);
#endif
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index fff0d9867529..64a2b912e73c 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -281,27 +281,23 @@ extern const struct ixgbe_mbx_operations ixgbevf_mbx_ops;
extern const char ixgbevf_driver_name[];
extern const char ixgbevf_driver_version[];
-extern void ixgbevf_up(struct ixgbevf_adapter *adapter);
-extern void ixgbevf_down(struct ixgbevf_adapter *adapter);
-extern void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter);
-extern void ixgbevf_reset(struct ixgbevf_adapter *adapter);
-extern void ixgbevf_set_ethtool_ops(struct net_device *netdev);
-extern int ixgbevf_setup_rx_resources(struct ixgbevf_adapter *,
- struct ixgbevf_ring *);
-extern int ixgbevf_setup_tx_resources(struct ixgbevf_adapter *,
- struct ixgbevf_ring *);
-extern void ixgbevf_free_rx_resources(struct ixgbevf_adapter *,
- struct ixgbevf_ring *);
-extern void ixgbevf_free_tx_resources(struct ixgbevf_adapter *,
- struct ixgbevf_ring *);
-extern void ixgbevf_update_stats(struct ixgbevf_adapter *adapter);
-extern int ethtool_ioctl(struct ifreq *ifr);
-
-extern void ixgbe_napi_add_all(struct ixgbevf_adapter *adapter);
-extern void ixgbe_napi_del_all(struct ixgbevf_adapter *adapter);
+void ixgbevf_up(struct ixgbevf_adapter *adapter);
+void ixgbevf_down(struct ixgbevf_adapter *adapter);
+void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter);
+void ixgbevf_reset(struct ixgbevf_adapter *adapter);
+void ixgbevf_set_ethtool_ops(struct net_device *netdev);
+int ixgbevf_setup_rx_resources(struct ixgbevf_adapter *, struct ixgbevf_ring *);
+int ixgbevf_setup_tx_resources(struct ixgbevf_adapter *, struct ixgbevf_ring *);
+void ixgbevf_free_rx_resources(struct ixgbevf_adapter *, struct ixgbevf_ring *);
+void ixgbevf_free_tx_resources(struct ixgbevf_adapter *, struct ixgbevf_ring *);
+void ixgbevf_update_stats(struct ixgbevf_adapter *adapter);
+int ethtool_ioctl(struct ifreq *ifr);
+
+void ixgbe_napi_add_all(struct ixgbevf_adapter *adapter);
+void ixgbe_napi_del_all(struct ixgbevf_adapter *adapter);
#ifdef DEBUG
-extern char *ixgbevf_get_hw_dev_name(struct ixgbe_hw *hw);
+char *ixgbevf_get_hw_dev_name(struct ixgbe_hw *hw);
#define hw_dbg(hw, format, arg...) \
printk(KERN_DEBUG "%s: " format, ixgbevf_get_hw_dev_name(hw), ##arg)
#else
diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c
index 1a9c4f6269ea..ecc7f7b696b8 100644
--- a/drivers/net/ethernet/marvell/skge.c
+++ b/drivers/net/ethernet/marvell/skge.c
@@ -3086,13 +3086,16 @@ static struct sk_buff *skge_rx_get(struct net_device *dev,
PCI_DMA_FROMDEVICE);
skge_rx_reuse(e, skge->rx_buf_size);
} else {
+ struct skge_element ee;
struct sk_buff *nskb;
nskb = netdev_alloc_skb_ip_align(dev, skge->rx_buf_size);
if (!nskb)
goto resubmit;
- skb = e->skb;
+ ee = *e;
+
+ skb = ee.skb;
prefetch(skb->data);
if (skge_rx_setup(skge, e, nskb, skge->rx_buf_size) < 0) {
@@ -3101,8 +3104,8 @@ static struct sk_buff *skge_rx_get(struct net_device *dev,
}
pci_unmap_single(skge->hw->pdev,
- dma_unmap_addr(e, mapaddr),
- dma_unmap_len(e, maplen),
+ dma_unmap_addr(&ee, mapaddr),
+ dma_unmap_len(&ee, maplen),
PCI_DMA_FROMDEVICE);
}
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
index 6797b1075874..2a9003071d51 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
@@ -653,38 +653,38 @@ struct pch_gbe_adapter {
extern const char pch_driver_version[];
/* pch_gbe_main.c */
-extern int pch_gbe_up(struct pch_gbe_adapter *adapter);
-extern void pch_gbe_down(struct pch_gbe_adapter *adapter);
-extern void pch_gbe_reinit_locked(struct pch_gbe_adapter *adapter);
-extern void pch_gbe_reset(struct pch_gbe_adapter *adapter);
-extern int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter,
- struct pch_gbe_tx_ring *txdr);
-extern int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter,
- struct pch_gbe_rx_ring *rxdr);
-extern void pch_gbe_free_tx_resources(struct pch_gbe_adapter *adapter,
- struct pch_gbe_tx_ring *tx_ring);
-extern void pch_gbe_free_rx_resources(struct pch_gbe_adapter *adapter,
- struct pch_gbe_rx_ring *rx_ring);
-extern void pch_gbe_update_stats(struct pch_gbe_adapter *adapter);
-extern u32 pch_ch_control_read(struct pci_dev *pdev);
-extern void pch_ch_control_write(struct pci_dev *pdev, u32 val);
-extern u32 pch_ch_event_read(struct pci_dev *pdev);
-extern void pch_ch_event_write(struct pci_dev *pdev, u32 val);
-extern u32 pch_src_uuid_lo_read(struct pci_dev *pdev);
-extern u32 pch_src_uuid_hi_read(struct pci_dev *pdev);
-extern u64 pch_rx_snap_read(struct pci_dev *pdev);
-extern u64 pch_tx_snap_read(struct pci_dev *pdev);
-extern int pch_set_station_address(u8 *addr, struct pci_dev *pdev);
+int pch_gbe_up(struct pch_gbe_adapter *adapter);
+void pch_gbe_down(struct pch_gbe_adapter *adapter);
+void pch_gbe_reinit_locked(struct pch_gbe_adapter *adapter);
+void pch_gbe_reset(struct pch_gbe_adapter *adapter);
+int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_tx_ring *txdr);
+int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_rx_ring *rxdr);
+void pch_gbe_free_tx_resources(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_tx_ring *tx_ring);
+void pch_gbe_free_rx_resources(struct pch_gbe_adapter *adapter,
+ struct pch_gbe_rx_ring *rx_ring);
+void pch_gbe_update_stats(struct pch_gbe_adapter *adapter);
+u32 pch_ch_control_read(struct pci_dev *pdev);
+void pch_ch_control_write(struct pci_dev *pdev, u32 val);
+u32 pch_ch_event_read(struct pci_dev *pdev);
+void pch_ch_event_write(struct pci_dev *pdev, u32 val);
+u32 pch_src_uuid_lo_read(struct pci_dev *pdev);
+u32 pch_src_uuid_hi_read(struct pci_dev *pdev);
+u64 pch_rx_snap_read(struct pci_dev *pdev);
+u64 pch_tx_snap_read(struct pci_dev *pdev);
+int pch_set_station_address(u8 *addr, struct pci_dev *pdev);
/* pch_gbe_param.c */
-extern void pch_gbe_check_options(struct pch_gbe_adapter *adapter);
+void pch_gbe_check_options(struct pch_gbe_adapter *adapter);
/* pch_gbe_ethtool.c */
-extern void pch_gbe_set_ethtool_ops(struct net_device *netdev);
+void pch_gbe_set_ethtool_ops(struct net_device *netdev);
/* pch_gbe_mac.c */
-extern s32 pch_gbe_mac_force_mac_fc(struct pch_gbe_hw *hw);
-extern s32 pch_gbe_mac_read_mac_addr(struct pch_gbe_hw *hw);
-extern u16 pch_gbe_mac_ctrl_miim(struct pch_gbe_hw *hw,
- u32 addr, u32 dir, u32 reg, u16 data);
+s32 pch_gbe_mac_force_mac_fc(struct pch_gbe_hw *hw);
+s32 pch_gbe_mac_read_mac_addr(struct pch_gbe_hw *hw);
+u16 pch_gbe_mac_ctrl_miim(struct pch_gbe_hw *hw, u32 addr, u32 dir, u32 reg,
+ u16 data);
#endif /* _PCH_GBE_H_ */
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h
index 32675e16021e..e8eff3e269e4 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h
@@ -1883,9 +1883,8 @@ static inline u32 netxen_tx_avail(struct nx_host_tx_ring *tx_ring)
int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 *mac);
int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, u64 *mac);
-extern void netxen_change_ringparam(struct netxen_adapter *adapter);
-extern int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr,
- int *valp);
+void netxen_change_ringparam(struct netxen_adapter *adapter);
+int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp);
extern const struct ethtool_ops netxen_nic_ethtool_ops;
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge.h b/drivers/net/ethernet/qlogic/qlge/qlge.h
index 899433778466..cc62272d485b 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge.h
+++ b/drivers/net/ethernet/qlogic/qlge/qlge.h
@@ -2206,14 +2206,14 @@ extern char qlge_driver_name[];
extern const char qlge_driver_version[];
extern const struct ethtool_ops qlge_ethtool_ops;
-extern int ql_sem_spinlock(struct ql_adapter *qdev, u32 sem_mask);
-extern void ql_sem_unlock(struct ql_adapter *qdev, u32 sem_mask);
-extern int ql_read_xgmac_reg(struct ql_adapter *qdev, u32 reg, u32 *data);
-extern int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index,
- u32 *value);
-extern int ql_get_routing_reg(struct ql_adapter *qdev, u32 index, u32 *value);
-extern int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit,
- u16 q_id);
+int ql_sem_spinlock(struct ql_adapter *qdev, u32 sem_mask);
+void ql_sem_unlock(struct ql_adapter *qdev, u32 sem_mask);
+int ql_read_xgmac_reg(struct ql_adapter *qdev, u32 reg, u32 *data);
+int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index,
+ u32 *value);
+int ql_get_routing_reg(struct ql_adapter *qdev, u32 index, u32 *value);
+int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit,
+ u16 q_id);
void ql_queue_fw_error(struct ql_adapter *qdev);
void ql_mpi_work(struct work_struct *work);
void ql_mpi_reset_work(struct work_struct *work);
@@ -2233,10 +2233,9 @@ int ql_unpause_mpi_risc(struct ql_adapter *qdev);
int ql_pause_mpi_risc(struct ql_adapter *qdev);
int ql_hard_reset_mpi_risc(struct ql_adapter *qdev);
int ql_soft_reset_mpi_risc(struct ql_adapter *qdev);
-int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf,
- u32 ram_addr, int word_count);
-int ql_core_dump(struct ql_adapter *qdev,
- struct ql_mpi_coredump *mpi_coredump);
+int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf, u32 ram_addr,
+ int word_count);
+int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump);
int ql_mb_about_fw(struct ql_adapter *qdev);
int ql_mb_wol_set_magic(struct ql_adapter *qdev, u32 enable_wol);
int ql_mb_wol_mode(struct ql_adapter *qdev, u32 wol);
@@ -2249,8 +2248,7 @@ int ql_mb_get_port_cfg(struct ql_adapter *qdev);
int ql_mb_set_port_cfg(struct ql_adapter *qdev);
int ql_wait_fifo_empty(struct ql_adapter *qdev);
void ql_get_dump(struct ql_adapter *qdev, void *buff);
-void ql_gen_reg_dump(struct ql_adapter *qdev,
- struct ql_reg_dump *mpi_coredump);
+void ql_gen_reg_dump(struct ql_adapter *qdev, struct ql_reg_dump *mpi_coredump);
netdev_tx_t ql_lb_send(struct sk_buff *skb, struct net_device *ndev);
void ql_check_lb_frame(struct ql_adapter *, struct sk_buff *);
int ql_own_firmware(struct ql_adapter *qdev);
@@ -2264,9 +2262,9 @@ int ql_clean_lb_rx_ring(struct rx_ring *rx_ring, int budget);
/* #define QL_OB_DUMP */
#ifdef QL_REG_DUMP
-extern void ql_dump_xgmac_control_regs(struct ql_adapter *qdev);
-extern void ql_dump_routing_entries(struct ql_adapter *qdev);
-extern void ql_dump_regs(struct ql_adapter *qdev);
+void ql_dump_xgmac_control_regs(struct ql_adapter *qdev);
+void ql_dump_routing_entries(struct ql_adapter *qdev);
+void ql_dump_regs(struct ql_adapter *qdev);
#define QL_DUMP_REGS(qdev) ql_dump_regs(qdev)
#define QL_DUMP_ROUTE(qdev) ql_dump_routing_entries(qdev)
#define QL_DUMP_XGMAC_CONTROL_REGS(qdev) ql_dump_xgmac_control_regs(qdev)
@@ -2277,26 +2275,26 @@ extern void ql_dump_regs(struct ql_adapter *qdev);
#endif
#ifdef QL_STAT_DUMP
-extern void ql_dump_stat(struct ql_adapter *qdev);
+void ql_dump_stat(struct ql_adapter *qdev);
#define QL_DUMP_STAT(qdev) ql_dump_stat(qdev)
#else
#define QL_DUMP_STAT(qdev)
#endif
#ifdef QL_DEV_DUMP
-extern void ql_dump_qdev(struct ql_adapter *qdev);
+void ql_dump_qdev(struct ql_adapter *qdev);
#define QL_DUMP_QDEV(qdev) ql_dump_qdev(qdev)
#else
#define QL_DUMP_QDEV(qdev)
#endif
#ifdef QL_CB_DUMP
-extern void ql_dump_wqicb(struct wqicb *wqicb);
-extern void ql_dump_tx_ring(struct tx_ring *tx_ring);
-extern void ql_dump_ricb(struct ricb *ricb);
-extern void ql_dump_cqicb(struct cqicb *cqicb);
-extern void ql_dump_rx_ring(struct rx_ring *rx_ring);
-extern void ql_dump_hw_cb(struct ql_adapter *qdev, int size, u32 bit, u16 q_id);
+void ql_dump_wqicb(struct wqicb *wqicb);
+void ql_dump_tx_ring(struct tx_ring *tx_ring);
+void ql_dump_ricb(struct ricb *ricb);
+void ql_dump_cqicb(struct cqicb *cqicb);
+void ql_dump_rx_ring(struct rx_ring *rx_ring);
+void ql_dump_hw_cb(struct ql_adapter *qdev, int size, u32 bit, u16 q_id);
#define QL_DUMP_RICB(ricb) ql_dump_ricb(ricb)
#define QL_DUMP_WQICB(wqicb) ql_dump_wqicb(wqicb)
#define QL_DUMP_TX_RING(tx_ring) ql_dump_tx_ring(tx_ring)
@@ -2314,9 +2312,9 @@ extern void ql_dump_hw_cb(struct ql_adapter *qdev, int size, u32 bit, u16 q_id);
#endif
#ifdef QL_OB_DUMP
-extern void ql_dump_tx_desc(struct tx_buf_desc *tbd);
-extern void ql_dump_ob_mac_iocb(struct ob_mac_iocb_req *ob_mac_iocb);
-extern void ql_dump_ob_mac_rsp(struct ob_mac_iocb_rsp *ob_mac_rsp);
+void ql_dump_tx_desc(struct tx_buf_desc *tbd);
+void ql_dump_ob_mac_iocb(struct ob_mac_iocb_req *ob_mac_iocb);
+void ql_dump_ob_mac_rsp(struct ob_mac_iocb_rsp *ob_mac_rsp);
#define QL_DUMP_OB_MAC_IOCB(ob_mac_iocb) ql_dump_ob_mac_iocb(ob_mac_iocb)
#define QL_DUMP_OB_MAC_RSP(ob_mac_rsp) ql_dump_ob_mac_rsp(ob_mac_rsp)
#else
@@ -2325,14 +2323,14 @@ extern void ql_dump_ob_mac_rsp(struct ob_mac_iocb_rsp *ob_mac_rsp);
#endif
#ifdef QL_IB_DUMP
-extern void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp);
+void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp);
#define QL_DUMP_IB_MAC_RSP(ib_mac_rsp) ql_dump_ib_mac_rsp(ib_mac_rsp)
#else
#define QL_DUMP_IB_MAC_RSP(ib_mac_rsp)
#endif
#ifdef QL_ALL_DUMP
-extern void ql_dump_all(struct ql_adapter *qdev);
+void ql_dump_all(struct ql_adapter *qdev);
#define QL_DUMP_ALL(qdev) ql_dump_all(qdev)
#else
#define QL_DUMP_ALL(qdev)
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
index 10093f0c4c0f..6bc5db703920 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
@@ -740,8 +740,8 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
int i;
if (!mpi_coredump) {
- netif_err(qdev, drv, qdev->ndev, "No memory available\n");
- return -ENOMEM;
+ netif_err(qdev, drv, qdev->ndev, "No memory allocated\n");
+ return -EINVAL;
}
/* Try to get the spinlock, but dont worry if
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_mpi.c b/drivers/net/ethernet/qlogic/qlge/qlge_mpi.c
index ff2bf8a4e247..7ad146080c36 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_mpi.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_mpi.c
@@ -1274,7 +1274,7 @@ void ql_mpi_reset_work(struct work_struct *work)
return;
}
- if (!ql_core_dump(qdev, qdev->mpi_coredump)) {
+ if (qdev->mpi_coredump && !ql_core_dump(qdev, qdev->mpi_coredump)) {
netif_err(qdev, drv, qdev->ndev, "Core is dumped!\n");
qdev->core_is_dumped = 1;
queue_delayed_work(qdev->workqueue,
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 9f18ae984f9e..844ee7539d33 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -285,6 +285,181 @@ static int efx_ef10_free_vis(struct efx_nic *efx)
return rc;
}
+#ifdef EFX_USE_PIO
+
+static void efx_ef10_free_piobufs(struct efx_nic *efx)
+{
+ struct efx_ef10_nic_data *nic_data = efx->nic_data;
+ MCDI_DECLARE_BUF(inbuf, MC_CMD_FREE_PIOBUF_IN_LEN);
+ unsigned int i;
+ int rc;
+
+ BUILD_BUG_ON(MC_CMD_FREE_PIOBUF_OUT_LEN != 0);
+
+ for (i = 0; i < nic_data->n_piobufs; i++) {
+ MCDI_SET_DWORD(inbuf, FREE_PIOBUF_IN_PIOBUF_HANDLE,
+ nic_data->piobuf_handle[i]);
+ rc = efx_mcdi_rpc(efx, MC_CMD_FREE_PIOBUF, inbuf, sizeof(inbuf),
+ NULL, 0, NULL);
+ WARN_ON(rc);
+ }
+
+ nic_data->n_piobufs = 0;
+}
+
+static int efx_ef10_alloc_piobufs(struct efx_nic *efx, unsigned int n)
+{
+ struct efx_ef10_nic_data *nic_data = efx->nic_data;
+ MCDI_DECLARE_BUF(outbuf, MC_CMD_ALLOC_PIOBUF_OUT_LEN);
+ unsigned int i;
+ size_t outlen;
+ int rc = 0;
+
+ BUILD_BUG_ON(MC_CMD_ALLOC_PIOBUF_IN_LEN != 0);
+
+ for (i = 0; i < n; i++) {
+ rc = efx_mcdi_rpc(efx, MC_CMD_ALLOC_PIOBUF, NULL, 0,
+ outbuf, sizeof(outbuf), &outlen);
+ if (rc)
+ break;
+ if (outlen < MC_CMD_ALLOC_PIOBUF_OUT_LEN) {
+ rc = -EIO;
+ break;
+ }
+ nic_data->piobuf_handle[i] =
+ MCDI_DWORD(outbuf, ALLOC_PIOBUF_OUT_PIOBUF_HANDLE);
+ netif_dbg(efx, probe, efx->net_dev,
+ "allocated PIO buffer %u handle %x\n", i,
+ nic_data->piobuf_handle[i]);
+ }
+
+ nic_data->n_piobufs = i;
+ if (rc)
+ efx_ef10_free_piobufs(efx);
+ return rc;
+}
+
+static int efx_ef10_link_piobufs(struct efx_nic *efx)
+{
+ struct efx_ef10_nic_data *nic_data = efx->nic_data;
+ MCDI_DECLARE_BUF(inbuf,
+ max(MC_CMD_LINK_PIOBUF_IN_LEN,
+ MC_CMD_UNLINK_PIOBUF_IN_LEN));
+ struct efx_channel *channel;
+ struct efx_tx_queue *tx_queue;
+ unsigned int offset, index;
+ int rc;
+
+ BUILD_BUG_ON(MC_CMD_LINK_PIOBUF_OUT_LEN != 0);
+ BUILD_BUG_ON(MC_CMD_UNLINK_PIOBUF_OUT_LEN != 0);
+
+ /* Link a buffer to each VI in the write-combining mapping */
+ for (index = 0; index < nic_data->n_piobufs; ++index) {
+ MCDI_SET_DWORD(inbuf, LINK_PIOBUF_IN_PIOBUF_HANDLE,
+ nic_data->piobuf_handle[index]);
+ MCDI_SET_DWORD(inbuf, LINK_PIOBUF_IN_TXQ_INSTANCE,
+ nic_data->pio_write_vi_base + index);
+ rc = efx_mcdi_rpc(efx, MC_CMD_LINK_PIOBUF,
+ inbuf, MC_CMD_LINK_PIOBUF_IN_LEN,
+ NULL, 0, NULL);
+ if (rc) {
+ netif_err(efx, drv, efx->net_dev,
+ "failed to link VI %u to PIO buffer %u (%d)\n",
+ nic_data->pio_write_vi_base + index, index,
+ rc);
+ goto fail;
+ }
+ netif_dbg(efx, probe, efx->net_dev,
+ "linked VI %u to PIO buffer %u\n",
+ nic_data->pio_write_vi_base + index, index);
+ }
+
+ /* Link a buffer to each TX queue */
+ efx_for_each_channel(channel, efx) {
+ efx_for_each_channel_tx_queue(tx_queue, channel) {
+ /* We assign the PIO buffers to queues in
+ * reverse order to allow for the following
+ * special case.
+ */
+ offset = ((efx->tx_channel_offset + efx->n_tx_channels -
+ tx_queue->channel->channel - 1) *
+ efx_piobuf_size);
+ index = offset / ER_DZ_TX_PIOBUF_SIZE;
+ offset = offset % ER_DZ_TX_PIOBUF_SIZE;
+
+ /* When the host page size is 4K, the first
+ * host page in the WC mapping may be within
+ * the same VI page as the last TX queue. We
+ * can only link one buffer to each VI.
+ */
+ if (tx_queue->queue == nic_data->pio_write_vi_base) {
+ BUG_ON(index != 0);
+ rc = 0;
+ } else {
+ MCDI_SET_DWORD(inbuf,
+ LINK_PIOBUF_IN_PIOBUF_HANDLE,
+ nic_data->piobuf_handle[index]);
+ MCDI_SET_DWORD(inbuf,
+ LINK_PIOBUF_IN_TXQ_INSTANCE,
+ tx_queue->queue);
+ rc = efx_mcdi_rpc(efx, MC_CMD_LINK_PIOBUF,
+ inbuf, MC_CMD_LINK_PIOBUF_IN_LEN,
+ NULL, 0, NULL);
+ }
+
+ if (rc) {
+ /* This is non-fatal; the TX path just
+ * won't use PIO for this queue
+ */
+ netif_err(efx, drv, efx->net_dev,
+ "failed to link VI %u to PIO buffer %u (%d)\n",
+ tx_queue->queue, index, rc);
+ tx_queue->piobuf = NULL;
+ } else {
+ tx_queue->piobuf =
+ nic_data->pio_write_base +
+ index * EFX_VI_PAGE_SIZE + offset;
+ tx_queue->piobuf_offset = offset;
+ netif_dbg(efx, probe, efx->net_dev,
+ "linked VI %u to PIO buffer %u offset %x addr %p\n",
+ tx_queue->queue, index,
+ tx_queue->piobuf_offset,
+ tx_queue->piobuf);
+ }
+ }
+ }
+
+ return 0;
+
+fail:
+ while (index--) {
+ MCDI_SET_DWORD(inbuf, UNLINK_PIOBUF_IN_TXQ_INSTANCE,
+ nic_data->pio_write_vi_base + index);
+ efx_mcdi_rpc(efx, MC_CMD_UNLINK_PIOBUF,
+ inbuf, MC_CMD_UNLINK_PIOBUF_IN_LEN,
+ NULL, 0, NULL);
+ }
+ return rc;
+}
+
+#else /* !EFX_USE_PIO */
+
+static int efx_ef10_alloc_piobufs(struct efx_nic *efx, unsigned int n)
+{
+ return n == 0 ? 0 : -ENOBUFS;
+}
+
+static int efx_ef10_link_piobufs(struct efx_nic *efx)
+{
+ return 0;
+}
+
+static void efx_ef10_free_piobufs(struct efx_nic *efx)
+{
+}
+
+#endif /* EFX_USE_PIO */
+
static void efx_ef10_remove(struct efx_nic *efx)
{
struct efx_ef10_nic_data *nic_data = efx->nic_data;
@@ -295,9 +470,15 @@ static void efx_ef10_remove(struct efx_nic *efx)
/* This needs to be after efx_ptp_remove_channel() with no filters */
efx_ef10_rx_free_indir_table(efx);
+ if (nic_data->wc_membase)
+ iounmap(nic_data->wc_membase);
+
rc = efx_ef10_free_vis(efx);
WARN_ON(rc != 0);
+ if (!nic_data->must_restore_piobufs)
+ efx_ef10_free_piobufs(efx);
+
efx_mcdi_fini(efx);
efx_nic_free_buffer(efx, &nic_data->mcdi_buf);
kfree(nic_data);
@@ -330,12 +511,126 @@ static int efx_ef10_alloc_vis(struct efx_nic *efx,
return 0;
}
+/* Note that the failure path of this function does not free
+ * resources, as this will be done by efx_ef10_remove().
+ */
static int efx_ef10_dimension_resources(struct efx_nic *efx)
{
- unsigned int n_vis =
- max(efx->n_channels, efx->n_tx_channels * EFX_TXQ_TYPES);
+ struct efx_ef10_nic_data *nic_data = efx->nic_data;
+ unsigned int uc_mem_map_size, wc_mem_map_size;
+ unsigned int min_vis, pio_write_vi_base, max_vis;
+ void __iomem *membase;
+ int rc;
+
+ min_vis = max(efx->n_channels, efx->n_tx_channels * EFX_TXQ_TYPES);
+
+#ifdef EFX_USE_PIO
+ /* Try to allocate PIO buffers if wanted and if the full
+ * number of PIO buffers would be sufficient to allocate one
+ * copy-buffer per TX channel. Failure is non-fatal, as there
+ * are only a small number of PIO buffers shared between all
+ * functions of the controller.
+ */
+ if (efx_piobuf_size != 0 &&
+ ER_DZ_TX_PIOBUF_SIZE / efx_piobuf_size * EF10_TX_PIOBUF_COUNT >=
+ efx->n_tx_channels) {
+ unsigned int n_piobufs =
+ DIV_ROUND_UP(efx->n_tx_channels,
+ ER_DZ_TX_PIOBUF_SIZE / efx_piobuf_size);
+
+ rc = efx_ef10_alloc_piobufs(efx, n_piobufs);
+ if (rc)
+ netif_err(efx, probe, efx->net_dev,
+ "failed to allocate PIO buffers (%d)\n", rc);
+ else
+ netif_dbg(efx, probe, efx->net_dev,
+ "allocated %u PIO buffers\n", n_piobufs);
+ }
+#else
+ nic_data->n_piobufs = 0;
+#endif
- return efx_ef10_alloc_vis(efx, n_vis, n_vis);
+ /* PIO buffers should be mapped with write-combining enabled,
+ * and we want to make single UC and WC mappings rather than
+ * several of each (in fact that's the only option if host
+ * page size is >4K). So we may allocate some extra VIs just
+ * for writing PIO buffers through.
+ */
+ uc_mem_map_size = PAGE_ALIGN((min_vis - 1) * EFX_VI_PAGE_SIZE +
+ ER_DZ_TX_PIOBUF);
+ if (nic_data->n_piobufs) {
+ pio_write_vi_base = uc_mem_map_size / EFX_VI_PAGE_SIZE;
+ wc_mem_map_size = (PAGE_ALIGN((pio_write_vi_base +
+ nic_data->n_piobufs) *
+ EFX_VI_PAGE_SIZE) -
+ uc_mem_map_size);
+ max_vis = pio_write_vi_base + nic_data->n_piobufs;
+ } else {
+ pio_write_vi_base = 0;
+ wc_mem_map_size = 0;
+ max_vis = min_vis;
+ }
+
+ /* In case the last attached driver failed to free VIs, do it now */
+ rc = efx_ef10_free_vis(efx);
+ if (rc != 0)
+ return rc;
+
+ rc = efx_ef10_alloc_vis(efx, min_vis, max_vis);
+ if (rc != 0)
+ return rc;
+
+ /* If we didn't get enough VIs to map all the PIO buffers, free the
+ * PIO buffers
+ */
+ if (nic_data->n_piobufs &&
+ nic_data->n_allocated_vis <
+ pio_write_vi_base + nic_data->n_piobufs) {
+ netif_dbg(efx, probe, efx->net_dev,
+ "%u VIs are not sufficient to map %u PIO buffers\n",
+ nic_data->n_allocated_vis, nic_data->n_piobufs);
+ efx_ef10_free_piobufs(efx);
+ }
+
+ /* Shrink the original UC mapping of the memory BAR */
+ membase = ioremap_nocache(efx->membase_phys, uc_mem_map_size);
+ if (!membase) {
+ netif_err(efx, probe, efx->net_dev,
+ "could not shrink memory BAR to %x\n",
+ uc_mem_map_size);
+ return -ENOMEM;
+ }
+ iounmap(efx->membase);
+ efx->membase = membase;
+
+ /* Set up the WC mapping if needed */
+ if (wc_mem_map_size) {
+ nic_data->wc_membase = ioremap_wc(efx->membase_phys +
+ uc_mem_map_size,
+ wc_mem_map_size);
+ if (!nic_data->wc_membase) {
+ netif_err(efx, probe, efx->net_dev,
+ "could not allocate WC mapping of size %x\n",
+ wc_mem_map_size);
+ return -ENOMEM;
+ }
+ nic_data->pio_write_vi_base = pio_write_vi_base;
+ nic_data->pio_write_base =
+ nic_data->wc_membase +
+ (pio_write_vi_base * EFX_VI_PAGE_SIZE + ER_DZ_TX_PIOBUF -
+ uc_mem_map_size);
+
+ rc = efx_ef10_link_piobufs(efx);
+ if (rc)
+ efx_ef10_free_piobufs(efx);
+ }
+
+ netif_dbg(efx, probe, efx->net_dev,
+ "memory BAR at %pa (virtual %p+%x UC, %p+%x WC)\n",
+ &efx->membase_phys, efx->membase, uc_mem_map_size,
+ nic_data->wc_membase, wc_mem_map_size);
+
+ return 0;
}
static int efx_ef10_init_nic(struct efx_nic *efx)
@@ -359,6 +654,21 @@ static int efx_ef10_init_nic(struct efx_nic *efx)
nic_data->must_realloc_vis = false;
}
+ if (nic_data->must_restore_piobufs && nic_data->n_piobufs) {
+ rc = efx_ef10_alloc_piobufs(efx, nic_data->n_piobufs);
+ if (rc == 0) {
+ rc = efx_ef10_link_piobufs(efx);
+ if (rc)
+ efx_ef10_free_piobufs(efx);
+ }
+
+ /* Log an error on failure, but this is non-fatal */
+ if (rc)
+ netif_err(efx, drv, efx->net_dev,
+ "failed to restore PIO buffers (%d)\n", rc);
+ nic_data->must_restore_piobufs = false;
+ }
+
efx_ef10_rx_push_indir_table(efx);
return 0;
}
@@ -716,6 +1026,7 @@ static int efx_ef10_mcdi_poll_reboot(struct efx_nic *efx)
/* All our allocations have been reset */
nic_data->must_realloc_vis = true;
nic_data->must_restore_filters = true;
+ nic_data->must_restore_piobufs = true;
nic_data->rx_rss_context = EFX_EF10_RSS_CONTEXT_INVALID;
/* The datapath firmware might have been changed */
@@ -2137,7 +2448,7 @@ out_unlock:
return rc;
}
-void efx_ef10_filter_update_rx_scatter(struct efx_nic *efx)
+static void efx_ef10_filter_update_rx_scatter(struct efx_nic *efx)
{
/* no need to do anything here on EF10 */
}
diff --git a/drivers/net/ethernet/sfc/ef10_regs.h b/drivers/net/ethernet/sfc/ef10_regs.h
index b3f4e3755fd9..207ac9a1e3de 100644
--- a/drivers/net/ethernet/sfc/ef10_regs.h
+++ b/drivers/net/ethernet/sfc/ef10_regs.h
@@ -315,6 +315,7 @@
#define ESF_DZ_TX_PIO_TYPE_WIDTH 1
#define ESF_DZ_TX_PIO_OPT_LBN 60
#define ESF_DZ_TX_PIO_OPT_WIDTH 3
+#define ESE_DZ_TX_OPTION_DESC_PIO 1
#define ESF_DZ_TX_PIO_CONT_LBN 59
#define ESF_DZ_TX_PIO_CONT_WIDTH 1
#define ESF_DZ_TX_PIO_BYTE_CNT_LBN 32
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h
index 34d00f5771fe..b8235ee5d7d7 100644
--- a/drivers/net/ethernet/sfc/efx.h
+++ b/drivers/net/ethernet/sfc/efx.h
@@ -18,37 +18,36 @@
#define EFX_MEM_BAR 2
/* TX */
-extern int efx_probe_tx_queue(struct efx_tx_queue *tx_queue);
-extern void efx_remove_tx_queue(struct efx_tx_queue *tx_queue);
-extern void efx_init_tx_queue(struct efx_tx_queue *tx_queue);
-extern void efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue);
-extern void efx_fini_tx_queue(struct efx_tx_queue *tx_queue);
-extern netdev_tx_t
-efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev);
-extern netdev_tx_t
-efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
-extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
-extern int efx_setup_tc(struct net_device *net_dev, u8 num_tc);
-extern unsigned int efx_tx_max_skb_descs(struct efx_nic *efx);
+int efx_probe_tx_queue(struct efx_tx_queue *tx_queue);
+void efx_remove_tx_queue(struct efx_tx_queue *tx_queue);
+void efx_init_tx_queue(struct efx_tx_queue *tx_queue);
+void efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue);
+void efx_fini_tx_queue(struct efx_tx_queue *tx_queue);
+netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
+ struct net_device *net_dev);
+netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
+void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
+int efx_setup_tc(struct net_device *net_dev, u8 num_tc);
+unsigned int efx_tx_max_skb_descs(struct efx_nic *efx);
+extern unsigned int efx_piobuf_size;
/* RX */
-extern void efx_rx_config_page_split(struct efx_nic *efx);
-extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue);
-extern void efx_remove_rx_queue(struct efx_rx_queue *rx_queue);
-extern void efx_init_rx_queue(struct efx_rx_queue *rx_queue);
-extern void efx_fini_rx_queue(struct efx_rx_queue *rx_queue);
-extern void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue);
-extern void efx_rx_slow_fill(unsigned long context);
-extern void __efx_rx_packet(struct efx_channel *channel);
-extern void efx_rx_packet(struct efx_rx_queue *rx_queue,
- unsigned int index, unsigned int n_frags,
- unsigned int len, u16 flags);
+void efx_rx_config_page_split(struct efx_nic *efx);
+int efx_probe_rx_queue(struct efx_rx_queue *rx_queue);
+void efx_remove_rx_queue(struct efx_rx_queue *rx_queue);
+void efx_init_rx_queue(struct efx_rx_queue *rx_queue);
+void efx_fini_rx_queue(struct efx_rx_queue *rx_queue);
+void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue);
+void efx_rx_slow_fill(unsigned long context);
+void __efx_rx_packet(struct efx_channel *channel);
+void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
+ unsigned int n_frags, unsigned int len, u16 flags);
static inline void efx_rx_flush_packet(struct efx_channel *channel)
{
if (channel->rx_pkt_n_frags)
__efx_rx_packet(channel);
}
-extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);
+void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);
#define EFX_MAX_DMAQ_SIZE 4096UL
#define EFX_DEFAULT_DMAQ_SIZE 1024UL
@@ -162,9 +161,9 @@ static inline s32 efx_filter_get_rx_ids(struct efx_nic *efx,
return efx->type->filter_get_rx_ids(efx, priority, buf, size);
}
#ifdef CONFIG_RFS_ACCEL
-extern int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
- u16 rxq_index, u32 flow_id);
-extern bool __efx_filter_rfs_expire(struct efx_nic *efx, unsigned quota);
+int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
+ u16 rxq_index, u32 flow_id);
+bool __efx_filter_rfs_expire(struct efx_nic *efx, unsigned quota);
static inline void efx_filter_rfs_expire(struct efx_channel *channel)
{
if (channel->rfs_filters_added >= 60 &&
@@ -176,50 +175,48 @@ static inline void efx_filter_rfs_expire(struct efx_channel *channel)
static inline void efx_filter_rfs_expire(struct efx_channel *channel) {}
#define efx_filter_rfs_enabled() 0
#endif
-extern bool efx_filter_is_mc_recipient(const struct efx_filter_spec *spec);
+bool efx_filter_is_mc_recipient(const struct efx_filter_spec *spec);
/* Channels */
-extern int efx_channel_dummy_op_int(struct efx_channel *channel);
-extern void efx_channel_dummy_op_void(struct efx_channel *channel);
-extern int
-efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries);
+int efx_channel_dummy_op_int(struct efx_channel *channel);
+void efx_channel_dummy_op_void(struct efx_channel *channel);
+int efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries);
/* Ports */
-extern int efx_reconfigure_port(struct efx_nic *efx);
-extern int __efx_reconfigure_port(struct efx_nic *efx);
+int efx_reconfigure_port(struct efx_nic *efx);
+int __efx_reconfigure_port(struct efx_nic *efx);
/* Ethtool support */
extern const struct ethtool_ops efx_ethtool_ops;
/* Reset handling */
-extern int efx_reset(struct efx_nic *efx, enum reset_type method);
-extern void efx_reset_down(struct efx_nic *efx, enum reset_type method);
-extern int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok);
-extern int efx_try_recovery(struct efx_nic *efx);
+int efx_reset(struct efx_nic *efx, enum reset_type method);
+void efx_reset_down(struct efx_nic *efx, enum reset_type method);
+int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok);
+int efx_try_recovery(struct efx_nic *efx);
/* Global */
-extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
-extern int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
- unsigned int rx_usecs, bool rx_adaptive,
- bool rx_may_override_tx);
-extern void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs,
- unsigned int *rx_usecs, bool *rx_adaptive);
+void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
+int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs,
+ unsigned int rx_usecs, bool rx_adaptive,
+ bool rx_may_override_tx);
+void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs,
+ unsigned int *rx_usecs, bool *rx_adaptive);
/* Dummy PHY ops for PHY drivers */
-extern int efx_port_dummy_op_int(struct efx_nic *efx);
-extern void efx_port_dummy_op_void(struct efx_nic *efx);
-
+int efx_port_dummy_op_int(struct efx_nic *efx);
+void efx_port_dummy_op_void(struct efx_nic *efx);
/* MTD */
#ifdef CONFIG_SFC_MTD
-extern int efx_mtd_add(struct efx_nic *efx, struct efx_mtd_partition *parts,
- size_t n_parts, size_t sizeof_part);
+int efx_mtd_add(struct efx_nic *efx, struct efx_mtd_partition *parts,
+ size_t n_parts, size_t sizeof_part);
static inline int efx_mtd_probe(struct efx_nic *efx)
{
return efx->type->mtd_probe(efx);
}
-extern void efx_mtd_rename(struct efx_nic *efx);
-extern void efx_mtd_remove(struct efx_nic *efx);
+void efx_mtd_rename(struct efx_nic *efx);
+void efx_mtd_remove(struct efx_nic *efx);
#else
static inline int efx_mtd_probe(struct efx_nic *efx) { return 0; }
static inline void efx_mtd_rename(struct efx_nic *efx) {}
@@ -241,9 +238,9 @@ static inline void efx_schedule_channel_irq(struct efx_channel *channel)
efx_schedule_channel(channel);
}
-extern void efx_link_status_changed(struct efx_nic *efx);
-extern void efx_link_set_advertising(struct efx_nic *efx, u32);
-extern void efx_link_set_wanted_fc(struct efx_nic *efx, u8);
+void efx_link_status_changed(struct efx_nic *efx);
+void efx_link_set_advertising(struct efx_nic *efx, u32);
+void efx_link_set_wanted_fc(struct efx_nic *efx, u8);
static inline void efx_device_detach_sync(struct efx_nic *efx)
{
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c
index 5b471cf5c323..1f529fa2edb1 100644
--- a/drivers/net/ethernet/sfc/ethtool.c
+++ b/drivers/net/ethernet/sfc/ethtool.c
@@ -70,6 +70,7 @@ static const struct efx_sw_stat_desc efx_sw_stat_desc[] = {
EFX_ETHTOOL_UINT_TXQ_STAT(tso_long_headers),
EFX_ETHTOOL_UINT_TXQ_STAT(tso_packets),
EFX_ETHTOOL_UINT_TXQ_STAT(pushes),
+ EFX_ETHTOOL_UINT_TXQ_STAT(pio_packets),
EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc),
EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err),
@@ -1035,8 +1036,8 @@ static int efx_ethtool_set_rxfh_indir(struct net_device *net_dev,
return 0;
}
-int efx_ethtool_get_ts_info(struct net_device *net_dev,
- struct ethtool_ts_info *ts_info)
+static int efx_ethtool_get_ts_info(struct net_device *net_dev,
+ struct ethtool_ts_info *ts_info)
{
struct efx_nic *efx = netdev_priv(net_dev);
diff --git a/drivers/net/ethernet/sfc/io.h b/drivers/net/ethernet/sfc/io.h
index 96ce507d8602..4d3f119b67b3 100644
--- a/drivers/net/ethernet/sfc/io.h
+++ b/drivers/net/ethernet/sfc/io.h
@@ -66,6 +66,11 @@
#define EFX_USE_QWORD_IO 1
#endif
+/* PIO is a win only if write-combining is possible */
+#ifdef ARCH_HAS_IOREMAP_WC
+#define EFX_USE_PIO 1
+#endif
+
#ifdef EFX_USE_QWORD_IO
static inline void _efx_writeq(struct efx_nic *efx, __le64 value,
unsigned int reg)
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index 128d7cdf9eb2..c082562dbf4e 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -27,10 +27,10 @@
/* A reboot/assertion causes the MCDI status word to be set after the
* command word is set or a REBOOT event is sent. If we notice a reboot
- * via these mechanisms then wait 20ms for the status word to be set.
+ * via these mechanisms then wait 250ms for the status word to be set.
*/
#define MCDI_STATUS_DELAY_US 100
-#define MCDI_STATUS_DELAY_COUNT 200
+#define MCDI_STATUS_DELAY_COUNT 2500
#define MCDI_STATUS_SLEEP_MS \
(MCDI_STATUS_DELAY_US * MCDI_STATUS_DELAY_COUNT / 1000)
@@ -800,9 +800,6 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc)
} else {
int count;
- /* Nobody was waiting for an MCDI request, so trigger a reset */
- efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
-
/* Consume the status word since efx_mcdi_rpc_finish() won't */
for (count = 0; count < MCDI_STATUS_DELAY_COUNT; ++count) {
if (efx_mcdi_poll_reboot(efx))
@@ -810,6 +807,9 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc)
udelay(MCDI_STATUS_DELAY_US);
}
mcdi->new_epoch = true;
+
+ /* Nobody was waiting for an MCDI request, so trigger a reset */
+ efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
}
spin_unlock(&mcdi->iface_lock);
diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
index c34d0d4e10ee..656a3277c2b2 100644
--- a/drivers/net/ethernet/sfc/mcdi.h
+++ b/drivers/net/ethernet/sfc/mcdi.h
@@ -108,38 +108,35 @@ static inline struct efx_mcdi_mon *efx_mcdi_mon(struct efx_nic *efx)
}
#endif
-extern int efx_mcdi_init(struct efx_nic *efx);
-extern void efx_mcdi_fini(struct efx_nic *efx);
+int efx_mcdi_init(struct efx_nic *efx);
+void efx_mcdi_fini(struct efx_nic *efx);
-extern int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
- const efx_dword_t *inbuf, size_t inlen,
+int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, const efx_dword_t *inbuf,
+ size_t inlen, efx_dword_t *outbuf, size_t outlen,
+ size_t *outlen_actual);
+
+int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd,
+ const efx_dword_t *inbuf, size_t inlen);
+int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
efx_dword_t *outbuf, size_t outlen,
size_t *outlen_actual);
-extern int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd,
- const efx_dword_t *inbuf, size_t inlen);
-extern int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
- efx_dword_t *outbuf, size_t outlen,
- size_t *outlen_actual);
-
typedef void efx_mcdi_async_completer(struct efx_nic *efx,
unsigned long cookie, int rc,
efx_dword_t *outbuf,
size_t outlen_actual);
-extern int efx_mcdi_rpc_async(struct efx_nic *efx, unsigned int cmd,
- const efx_dword_t *inbuf, size_t inlen,
- size_t outlen,
- efx_mcdi_async_completer *complete,
- unsigned long cookie);
+int efx_mcdi_rpc_async(struct efx_nic *efx, unsigned int cmd,
+ const efx_dword_t *inbuf, size_t inlen, size_t outlen,
+ efx_mcdi_async_completer *complete,
+ unsigned long cookie);
-extern int efx_mcdi_poll_reboot(struct efx_nic *efx);
-extern void efx_mcdi_mode_poll(struct efx_nic *efx);
-extern void efx_mcdi_mode_event(struct efx_nic *efx);
-extern void efx_mcdi_flush_async(struct efx_nic *efx);
+int efx_mcdi_poll_reboot(struct efx_nic *efx);
+void efx_mcdi_mode_poll(struct efx_nic *efx);
+void efx_mcdi_mode_event(struct efx_nic *efx);
+void efx_mcdi_flush_async(struct efx_nic *efx);
-extern void efx_mcdi_process_event(struct efx_channel *channel,
- efx_qword_t *event);
-extern void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
+void efx_mcdi_process_event(struct efx_channel *channel, efx_qword_t *event);
+void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
/* We expect that 16- and 32-bit fields in MCDI requests and responses
* are appropriately aligned, but 64-bit fields are only
@@ -275,55 +272,54 @@ extern void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
#define MCDI_EVENT_FIELD(_ev, _field) \
EFX_QWORD_FIELD(_ev, MCDI_EVENT_ ## _field)
-extern void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len);
-extern int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
- u16 *fw_subtype_list, u32 *capabilities);
-extern int efx_mcdi_log_ctrl(struct efx_nic *efx, bool evq, bool uart,
- u32 dest_evq);
-extern int efx_mcdi_nvram_types(struct efx_nic *efx, u32 *nvram_types_out);
-extern int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type,
- size_t *size_out, size_t *erase_size_out,
- bool *protected_out);
-extern int efx_mcdi_nvram_test_all(struct efx_nic *efx);
-extern int efx_mcdi_handle_assertion(struct efx_nic *efx);
-extern void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
-extern int efx_mcdi_wol_filter_set_magic(struct efx_nic *efx,
- const u8 *mac, int *id_out);
-extern int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out);
-extern int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id);
-extern int efx_mcdi_wol_filter_reset(struct efx_nic *efx);
-extern int efx_mcdi_flush_rxqs(struct efx_nic *efx);
-extern int efx_mcdi_port_probe(struct efx_nic *efx);
-extern void efx_mcdi_port_remove(struct efx_nic *efx);
-extern int efx_mcdi_port_reconfigure(struct efx_nic *efx);
-extern int efx_mcdi_port_get_number(struct efx_nic *efx);
-extern u32 efx_mcdi_phy_get_caps(struct efx_nic *efx);
-extern void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev);
-extern int efx_mcdi_set_mac(struct efx_nic *efx);
+void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len);
+int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
+ u16 *fw_subtype_list, u32 *capabilities);
+int efx_mcdi_log_ctrl(struct efx_nic *efx, bool evq, bool uart, u32 dest_evq);
+int efx_mcdi_nvram_types(struct efx_nic *efx, u32 *nvram_types_out);
+int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type,
+ size_t *size_out, size_t *erase_size_out,
+ bool *protected_out);
+int efx_mcdi_nvram_test_all(struct efx_nic *efx);
+int efx_mcdi_handle_assertion(struct efx_nic *efx);
+void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
+int efx_mcdi_wol_filter_set_magic(struct efx_nic *efx, const u8 *mac,
+ int *id_out);
+int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out);
+int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id);
+int efx_mcdi_wol_filter_reset(struct efx_nic *efx);
+int efx_mcdi_flush_rxqs(struct efx_nic *efx);
+int efx_mcdi_port_probe(struct efx_nic *efx);
+void efx_mcdi_port_remove(struct efx_nic *efx);
+int efx_mcdi_port_reconfigure(struct efx_nic *efx);
+int efx_mcdi_port_get_number(struct efx_nic *efx);
+u32 efx_mcdi_phy_get_caps(struct efx_nic *efx);
+void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev);
+int efx_mcdi_set_mac(struct efx_nic *efx);
#define EFX_MC_STATS_GENERATION_INVALID ((__force __le64)(-1))
-extern void efx_mcdi_mac_start_stats(struct efx_nic *efx);
-extern void efx_mcdi_mac_stop_stats(struct efx_nic *efx);
-extern bool efx_mcdi_mac_check_fault(struct efx_nic *efx);
-extern enum reset_type efx_mcdi_map_reset_reason(enum reset_type reason);
-extern int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method);
-extern int efx_mcdi_set_workaround(struct efx_nic *efx, u32 type, bool enabled);
+void efx_mcdi_mac_start_stats(struct efx_nic *efx);
+void efx_mcdi_mac_stop_stats(struct efx_nic *efx);
+bool efx_mcdi_mac_check_fault(struct efx_nic *efx);
+enum reset_type efx_mcdi_map_reset_reason(enum reset_type reason);
+int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method);
+int efx_mcdi_set_workaround(struct efx_nic *efx, u32 type, bool enabled);
#ifdef CONFIG_SFC_MCDI_MON
-extern int efx_mcdi_mon_probe(struct efx_nic *efx);
-extern void efx_mcdi_mon_remove(struct efx_nic *efx);
+int efx_mcdi_mon_probe(struct efx_nic *efx);
+void efx_mcdi_mon_remove(struct efx_nic *efx);
#else
static inline int efx_mcdi_mon_probe(struct efx_nic *efx) { return 0; }
static inline void efx_mcdi_mon_remove(struct efx_nic *efx) {}
#endif
#ifdef CONFIG_SFC_MTD
-extern int efx_mcdi_mtd_read(struct mtd_info *mtd, loff_t start,
- size_t len, size_t *retlen, u8 *buffer);
-extern int efx_mcdi_mtd_erase(struct mtd_info *mtd, loff_t start, size_t len);
-extern int efx_mcdi_mtd_write(struct mtd_info *mtd, loff_t start,
- size_t len, size_t *retlen, const u8 *buffer);
-extern int efx_mcdi_mtd_sync(struct mtd_info *mtd);
-extern void efx_mcdi_mtd_rename(struct efx_mtd_partition *part);
+int efx_mcdi_mtd_read(struct mtd_info *mtd, loff_t start, size_t len,
+ size_t *retlen, u8 *buffer);
+int efx_mcdi_mtd_erase(struct mtd_info *mtd, loff_t start, size_t len);
+int efx_mcdi_mtd_write(struct mtd_info *mtd, loff_t start, size_t len,
+ size_t *retlen, const u8 *buffer);
+int efx_mcdi_mtd_sync(struct mtd_info *mtd);
+void efx_mcdi_mtd_rename(struct efx_mtd_partition *part);
#endif
#endif /* EFX_MCDI_H */
diff --git a/drivers/net/ethernet/sfc/mdio_10g.h b/drivers/net/ethernet/sfc/mdio_10g.h
index 16824fecc5ee..4a2dc4c281b7 100644
--- a/drivers/net/ethernet/sfc/mdio_10g.h
+++ b/drivers/net/ethernet/sfc/mdio_10g.h
@@ -20,7 +20,7 @@
static inline unsigned efx_mdio_id_rev(u32 id) { return id & 0xf; }
static inline unsigned efx_mdio_id_model(u32 id) { return (id >> 4) & 0x3f; }
-extern unsigned efx_mdio_id_oui(u32 id);
+unsigned efx_mdio_id_oui(u32 id);
static inline int efx_mdio_read(struct efx_nic *efx, int devad, int addr)
{
@@ -56,7 +56,7 @@ static inline bool efx_mdio_phyxgxs_lane_sync(struct efx_nic *efx)
return sync;
}
-extern const char *efx_mdio_mmd_name(int mmd);
+const char *efx_mdio_mmd_name(int mmd);
/*
* Reset a specific MMD and wait for reset to clear.
@@ -64,30 +64,29 @@ extern const char *efx_mdio_mmd_name(int mmd);
*
* This function will sleep
*/
-extern int efx_mdio_reset_mmd(struct efx_nic *efx, int mmd,
- int spins, int spintime);
+int efx_mdio_reset_mmd(struct efx_nic *efx, int mmd, int spins, int spintime);
/* As efx_mdio_check_mmd but for multiple MMDs */
int efx_mdio_check_mmds(struct efx_nic *efx, unsigned int mmd_mask);
/* Check the link status of specified mmds in bit mask */
-extern bool efx_mdio_links_ok(struct efx_nic *efx, unsigned int mmd_mask);
+bool efx_mdio_links_ok(struct efx_nic *efx, unsigned int mmd_mask);
/* Generic transmit disable support though PMAPMD */
-extern void efx_mdio_transmit_disable(struct efx_nic *efx);
+void efx_mdio_transmit_disable(struct efx_nic *efx);
/* Generic part of reconfigure: set/clear loopback bits */
-extern void efx_mdio_phy_reconfigure(struct efx_nic *efx);
+void efx_mdio_phy_reconfigure(struct efx_nic *efx);
/* Set the power state of the specified MMDs */
-extern void efx_mdio_set_mmds_lpower(struct efx_nic *efx,
- int low_power, unsigned int mmd_mask);
+void efx_mdio_set_mmds_lpower(struct efx_nic *efx, int low_power,
+ unsigned int mmd_mask);
/* Set (some of) the PHY settings over MDIO */
-extern int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd);
+int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd);
/* Push advertising flags and restart autonegotiation */
-extern void efx_mdio_an_reconfigure(struct efx_nic *efx);
+void efx_mdio_an_reconfigure(struct efx_nic *efx);
/* Get pause parameters from AN if available (otherwise return
* requested pause parameters)
@@ -95,8 +94,7 @@ extern void efx_mdio_an_reconfigure(struct efx_nic *efx);
u8 efx_mdio_get_pause(struct efx_nic *efx);
/* Wait for specified MMDs to exit reset within a timeout */
-extern int efx_mdio_wait_reset_mmds(struct efx_nic *efx,
- unsigned int mmd_mask);
+int efx_mdio_wait_reset_mmds(struct efx_nic *efx, unsigned int mmd_mask);
/* Set or clear flag, debouncing */
static inline void
@@ -107,6 +105,6 @@ efx_mdio_set_flag(struct efx_nic *efx, int devad, int addr,
}
/* Liveness self-test for MDIO PHYs */
-extern int efx_mdio_test_alive(struct efx_nic *efx);
+int efx_mdio_test_alive(struct efx_nic *efx);
#endif /* EFX_MDIO_10G_H */
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index b172ed133055..aac22a1e85b8 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -182,6 +182,9 @@ struct efx_tx_buffer {
* @tsoh_page: Array of pages of TSO header buffers
* @txd: The hardware descriptor ring
* @ptr_mask: The size of the ring minus 1.
+ * @piobuf: PIO buffer region for this TX queue (shared with its partner).
+ * Size of the region is efx_piobuf_size.
+ * @piobuf_offset: Buffer offset to be specified in PIO descriptors
* @initialised: Has hardware queue been initialised?
* @read_count: Current read pointer.
* This is the number of buffers that have been removed from both rings.
@@ -209,6 +212,7 @@ struct efx_tx_buffer {
* blocks
* @tso_packets: Number of packets via the TSO xmit path
* @pushes: Number of times the TX push feature has been used
+ * @pio_packets: Number of times the TX PIO feature has been used
* @empty_read_count: If the completion path has seen the queue as empty
* and the transmission path has not yet checked this, the value of
* @read_count bitwise-added to %EFX_EMPTY_COUNT_VALID; otherwise 0.
@@ -223,6 +227,8 @@ struct efx_tx_queue {
struct efx_buffer *tsoh_page;
struct efx_special_buffer txd;
unsigned int ptr_mask;
+ void __iomem *piobuf;
+ unsigned int piobuf_offset;
bool initialised;
/* Members used mainly on the completion path */
@@ -238,6 +244,7 @@ struct efx_tx_queue {
unsigned int tso_long_headers;
unsigned int tso_packets;
unsigned int pushes;
+ unsigned int pio_packets;
/* Members shared between paths and sometimes updated */
unsigned int empty_read_count ____cacheline_aligned_in_smp;
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index e7dbd2dd202e..c75009b8c0d9 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -19,6 +19,7 @@
#include "bitfield.h"
#include "efx.h"
#include "nic.h"
+#include "ef10_regs.h"
#include "farch_regs.h"
#include "io.h"
#include "workarounds.h"
@@ -166,26 +167,30 @@ void efx_nic_fini_interrupt(struct efx_nic *efx)
/* Register dump */
-#define REGISTER_REVISION_A 1
-#define REGISTER_REVISION_B 2
-#define REGISTER_REVISION_C 3
-#define REGISTER_REVISION_Z 3 /* latest revision */
+#define REGISTER_REVISION_FA 1
+#define REGISTER_REVISION_FB 2
+#define REGISTER_REVISION_FC 3
+#define REGISTER_REVISION_FZ 3 /* last Falcon arch revision */
+#define REGISTER_REVISION_ED 4
+#define REGISTER_REVISION_EZ 4 /* latest EF10 revision */
struct efx_nic_reg {
u32 offset:24;
- u32 min_revision:2, max_revision:2;
+ u32 min_revision:3, max_revision:3;
};
-#define REGISTER(name, min_rev, max_rev) { \
- FR_ ## min_rev ## max_rev ## _ ## name, \
- REGISTER_REVISION_ ## min_rev, REGISTER_REVISION_ ## max_rev \
+#define REGISTER(name, arch, min_rev, max_rev) { \
+ arch ## R_ ## min_rev ## max_rev ## _ ## name, \
+ REGISTER_REVISION_ ## arch ## min_rev, \
+ REGISTER_REVISION_ ## arch ## max_rev \
}
-#define REGISTER_AA(name) REGISTER(name, A, A)
-#define REGISTER_AB(name) REGISTER(name, A, B)
-#define REGISTER_AZ(name) REGISTER(name, A, Z)
-#define REGISTER_BB(name) REGISTER(name, B, B)
-#define REGISTER_BZ(name) REGISTER(name, B, Z)
-#define REGISTER_CZ(name) REGISTER(name, C, Z)
+#define REGISTER_AA(name) REGISTER(name, F, A, A)
+#define REGISTER_AB(name) REGISTER(name, F, A, B)
+#define REGISTER_AZ(name) REGISTER(name, F, A, Z)
+#define REGISTER_BB(name) REGISTER(name, F, B, B)
+#define REGISTER_BZ(name) REGISTER(name, F, B, Z)
+#define REGISTER_CZ(name) REGISTER(name, F, C, Z)
+#define REGISTER_DZ(name) REGISTER(name, E, D, Z)
static const struct efx_nic_reg efx_nic_regs[] = {
REGISTER_AZ(ADR_REGION),
@@ -292,37 +297,42 @@ static const struct efx_nic_reg efx_nic_regs[] = {
REGISTER_AB(XX_TXDRV_CTL),
/* XX_PRBS_CTL, XX_PRBS_CHK and XX_PRBS_ERR are not used */
/* XX_CORE_STAT is partly RC */
+ REGISTER_DZ(BIU_HW_REV_ID),
+ REGISTER_DZ(MC_DB_LWRD),
+ REGISTER_DZ(MC_DB_HWRD),
};
struct efx_nic_reg_table {
u32 offset:24;
- u32 min_revision:2, max_revision:2;
+ u32 min_revision:3, max_revision:3;
u32 step:6, rows:21;
};
-#define REGISTER_TABLE_DIMENSIONS(_, offset, min_rev, max_rev, step, rows) { \
+#define REGISTER_TABLE_DIMENSIONS(_, offset, arch, min_rev, max_rev, step, rows) { \
offset, \
- REGISTER_REVISION_ ## min_rev, REGISTER_REVISION_ ## max_rev, \
+ REGISTER_REVISION_ ## arch ## min_rev, \
+ REGISTER_REVISION_ ## arch ## max_rev, \
step, rows \
}
-#define REGISTER_TABLE(name, min_rev, max_rev) \
+#define REGISTER_TABLE(name, arch, min_rev, max_rev) \
REGISTER_TABLE_DIMENSIONS( \
- name, FR_ ## min_rev ## max_rev ## _ ## name, \
- min_rev, max_rev, \
- FR_ ## min_rev ## max_rev ## _ ## name ## _STEP, \
- FR_ ## min_rev ## max_rev ## _ ## name ## _ROWS)
-#define REGISTER_TABLE_AA(name) REGISTER_TABLE(name, A, A)
-#define REGISTER_TABLE_AZ(name) REGISTER_TABLE(name, A, Z)
-#define REGISTER_TABLE_BB(name) REGISTER_TABLE(name, B, B)
-#define REGISTER_TABLE_BZ(name) REGISTER_TABLE(name, B, Z)
+ name, arch ## R_ ## min_rev ## max_rev ## _ ## name, \
+ arch, min_rev, max_rev, \
+ arch ## R_ ## min_rev ## max_rev ## _ ## name ## _STEP, \
+ arch ## R_ ## min_rev ## max_rev ## _ ## name ## _ROWS)
+#define REGISTER_TABLE_AA(name) REGISTER_TABLE(name, F, A, A)
+#define REGISTER_TABLE_AZ(name) REGISTER_TABLE(name, F, A, Z)
+#define REGISTER_TABLE_BB(name) REGISTER_TABLE(name, F, B, B)
+#define REGISTER_TABLE_BZ(name) REGISTER_TABLE(name, F, B, Z)
#define REGISTER_TABLE_BB_CZ(name) \
- REGISTER_TABLE_DIMENSIONS(name, FR_BZ_ ## name, B, B, \
+ REGISTER_TABLE_DIMENSIONS(name, FR_BZ_ ## name, F, B, B, \
FR_BZ_ ## name ## _STEP, \
FR_BB_ ## name ## _ROWS), \
- REGISTER_TABLE_DIMENSIONS(name, FR_BZ_ ## name, C, Z, \
+ REGISTER_TABLE_DIMENSIONS(name, FR_BZ_ ## name, F, C, Z, \
FR_BZ_ ## name ## _STEP, \
FR_CZ_ ## name ## _ROWS)
-#define REGISTER_TABLE_CZ(name) REGISTER_TABLE(name, C, Z)
+#define REGISTER_TABLE_CZ(name) REGISTER_TABLE(name, F, C, Z)
+#define REGISTER_TABLE_DZ(name) REGISTER_TABLE(name, E, D, Z)
static const struct efx_nic_reg_table efx_nic_reg_tables[] = {
/* DRIVER is not used */
@@ -340,9 +350,9 @@ static const struct efx_nic_reg_table efx_nic_reg_tables[] = {
* 1K entries allows for some expansion of queue count and
* size before we need to change the version. */
REGISTER_TABLE_DIMENSIONS(BUF_FULL_TBL_KER, FR_AA_BUF_FULL_TBL_KER,
- A, A, 8, 1024),
+ F, A, A, 8, 1024),
REGISTER_TABLE_DIMENSIONS(BUF_FULL_TBL, FR_BZ_BUF_FULL_TBL,
- B, Z, 8, 1024),
+ F, B, Z, 8, 1024),
REGISTER_TABLE_CZ(RX_MAC_FILTER_TBL0),
REGISTER_TABLE_BB_CZ(TIMER_TBL),
REGISTER_TABLE_BB_CZ(TX_PACE_TBL),
@@ -353,6 +363,7 @@ static const struct efx_nic_reg_table efx_nic_reg_tables[] = {
/* MSIX_PBA_TABLE is not mapped */
/* SRM_DBG is not mapped (and is redundant with BUF_FLL_TBL) */
REGISTER_TABLE_BZ(RX_FILTER_TBL0),
+ REGISTER_TABLE_DZ(BIU_MC_SFT_STATUS),
};
size_t efx_nic_get_regs_len(struct efx_nic *efx)
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index fda29d39032f..08883c8edf0e 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -30,7 +30,7 @@ static inline int efx_nic_rev(struct efx_nic *efx)
return efx->type->revision;
}
-extern u32 efx_farch_fpga_ver(struct efx_nic *efx);
+u32 efx_farch_fpga_ver(struct efx_nic *efx);
/* NIC has two interlinked PCI functions for the same port. */
static inline bool efx_nic_is_dual_func(struct efx_nic *efx)
@@ -71,6 +71,26 @@ efx_tx_desc(struct efx_tx_queue *tx_queue, unsigned int index)
return ((efx_qword_t *) (tx_queue->txd.buf.addr)) + index;
}
+/* Report whether the NIC considers this TX queue empty, given the
+ * write_count used for the last doorbell push. May return false
+ * negative.
+ */
+static inline bool __efx_nic_tx_is_empty(struct efx_tx_queue *tx_queue,
+ unsigned int write_count)
+{
+ unsigned int empty_read_count = ACCESS_ONCE(tx_queue->empty_read_count);
+
+ if (empty_read_count == 0)
+ return false;
+
+ return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0;
+}
+
+static inline bool efx_nic_tx_is_empty(struct efx_tx_queue *tx_queue)
+{
+ return __efx_nic_tx_is_empty(tx_queue, tx_queue->write_count);
+}
+
/* Decide whether to push a TX descriptor to the NIC vs merely writing
* the doorbell. This can reduce latency when we are adding a single
* descriptor to an empty queue, but is otherwise pointless. Further,
@@ -80,14 +100,10 @@ efx_tx_desc(struct efx_tx_queue *tx_queue, unsigned int index)
static inline bool efx_nic_may_push_tx_desc(struct efx_tx_queue *tx_queue,
unsigned int write_count)
{
- unsigned empty_read_count = ACCESS_ONCE(tx_queue->empty_read_count);
-
- if (empty_read_count == 0)
- return false;
+ bool was_empty = __efx_nic_tx_is_empty(tx_queue, write_count);
tx_queue->empty_read_count = 0;
- return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0
- && tx_queue->write_count - write_count == 1;
+ return was_empty && tx_queue->write_count - write_count == 1;
}
/* Returns a pointer to the specified descriptor in the RX descriptor queue */
@@ -389,6 +405,12 @@ enum {
EF10_STAT_COUNT
};
+/* Maximum number of TX PIO buffers we may allocate to a function.
+ * This matches the total number of buffers on each SFC9100-family
+ * controller.
+ */
+#define EF10_TX_PIOBUF_COUNT 16
+
/**
* struct efx_ef10_nic_data - EF10 architecture NIC state
* @mcdi_buf: DMA buffer for MCDI
@@ -397,6 +419,13 @@ enum {
* @n_allocated_vis: Number of VIs allocated to this function
* @must_realloc_vis: Flag: VIs have yet to be reallocated after MC reboot
* @must_restore_filters: Flag: filters have yet to be restored after MC reboot
+ * @n_piobufs: Number of PIO buffers allocated to this function
+ * @wc_membase: Base address of write-combining mapping of the memory BAR
+ * @pio_write_base: Base address for writing PIO buffers
+ * @pio_write_vi_base: Relative VI number for @pio_write_base
+ * @piobuf_handle: Handle of each PIO buffer allocated
+ * @must_restore_piobufs: Flag: PIO buffers have yet to be restored after MC
+ * reboot
* @rx_rss_context: Firmware handle for our RSS context
* @stats: Hardware statistics
* @workaround_35388: Flag: firmware supports workaround for bug 35388
@@ -412,6 +441,11 @@ struct efx_ef10_nic_data {
unsigned int n_allocated_vis;
bool must_realloc_vis;
bool must_restore_filters;
+ unsigned int n_piobufs;
+ void __iomem *wc_membase, *pio_write_base;
+ unsigned int pio_write_vi_base;
+ unsigned int piobuf_handle[EF10_TX_PIOBUF_COUNT];
+ bool must_restore_piobufs;
u32 rx_rss_context;
u64 stats[EF10_STAT_COUNT];
bool workaround_35388;
@@ -463,18 +497,18 @@ static inline unsigned int efx_vf_size(struct efx_nic *efx)
return 1 << efx->vi_scale;
}
-extern int efx_init_sriov(void);
-extern void efx_sriov_probe(struct efx_nic *efx);
-extern int efx_sriov_init(struct efx_nic *efx);
-extern void efx_sriov_mac_address_changed(struct efx_nic *efx);
-extern void efx_sriov_tx_flush_done(struct efx_nic *efx, efx_qword_t *event);
-extern void efx_sriov_rx_flush_done(struct efx_nic *efx, efx_qword_t *event);
-extern void efx_sriov_event(struct efx_channel *channel, efx_qword_t *event);
-extern void efx_sriov_desc_fetch_err(struct efx_nic *efx, unsigned dmaq);
-extern void efx_sriov_flr(struct efx_nic *efx, unsigned flr);
-extern void efx_sriov_reset(struct efx_nic *efx);
-extern void efx_sriov_fini(struct efx_nic *efx);
-extern void efx_fini_sriov(void);
+int efx_init_sriov(void);
+void efx_sriov_probe(struct efx_nic *efx);
+int efx_sriov_init(struct efx_nic *efx);
+void efx_sriov_mac_address_changed(struct efx_nic *efx);
+void efx_sriov_tx_flush_done(struct efx_nic *efx, efx_qword_t *event);
+void efx_sriov_rx_flush_done(struct efx_nic *efx, efx_qword_t *event);
+void efx_sriov_event(struct efx_channel *channel, efx_qword_t *event);
+void efx_sriov_desc_fetch_err(struct efx_nic *efx, unsigned dmaq);
+void efx_sriov_flr(struct efx_nic *efx, unsigned flr);
+void efx_sriov_reset(struct efx_nic *efx);
+void efx_sriov_fini(struct efx_nic *efx);
+void efx_fini_sriov(void);
#else
@@ -500,22 +534,20 @@ static inline void efx_fini_sriov(void) {}
#endif
-extern int efx_sriov_set_vf_mac(struct net_device *dev, int vf, u8 *mac);
-extern int efx_sriov_set_vf_vlan(struct net_device *dev, int vf,
- u16 vlan, u8 qos);
-extern int efx_sriov_get_vf_config(struct net_device *dev, int vf,
- struct ifla_vf_info *ivf);
-extern int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf,
- bool spoofchk);
+int efx_sriov_set_vf_mac(struct net_device *dev, int vf, u8 *mac);
+int efx_sriov_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u8 qos);
+int efx_sriov_get_vf_config(struct net_device *dev, int vf,
+ struct ifla_vf_info *ivf);
+int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf,
+ bool spoofchk);
struct ethtool_ts_info;
-extern void efx_ptp_probe(struct efx_nic *efx);
-extern int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd);
-extern void efx_ptp_get_ts_info(struct efx_nic *efx,
- struct ethtool_ts_info *ts_info);
-extern bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
-extern int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
-extern void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev);
+void efx_ptp_probe(struct efx_nic *efx);
+int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd);
+void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info);
+bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
+int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
+void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev);
extern const struct efx_nic_type falcon_a1_nic_type;
extern const struct efx_nic_type falcon_b0_nic_type;
@@ -529,7 +561,7 @@ extern const struct efx_nic_type efx_hunt_a0_nic_type;
**************************************************************************
*/
-extern int falcon_probe_board(struct efx_nic *efx, u16 revision_info);
+int falcon_probe_board(struct efx_nic *efx, u16 revision_info);
/* TX data path */
static inline int efx_nic_probe_tx(struct efx_tx_queue *tx_queue)
@@ -597,58 +629,58 @@ static inline void efx_nic_eventq_read_ack(struct efx_channel *channel)
{
channel->efx->type->ev_read_ack(channel);
}
-extern void efx_nic_event_test_start(struct efx_channel *channel);
+void efx_nic_event_test_start(struct efx_channel *channel);
/* Falcon/Siena queue operations */
-extern int efx_farch_tx_probe(struct efx_tx_queue *tx_queue);
-extern void efx_farch_tx_init(struct efx_tx_queue *tx_queue);
-extern void efx_farch_tx_fini(struct efx_tx_queue *tx_queue);
-extern void efx_farch_tx_remove(struct efx_tx_queue *tx_queue);
-extern void efx_farch_tx_write(struct efx_tx_queue *tx_queue);
-extern int efx_farch_rx_probe(struct efx_rx_queue *rx_queue);
-extern void efx_farch_rx_init(struct efx_rx_queue *rx_queue);
-extern void efx_farch_rx_fini(struct efx_rx_queue *rx_queue);
-extern void efx_farch_rx_remove(struct efx_rx_queue *rx_queue);
-extern void efx_farch_rx_write(struct efx_rx_queue *rx_queue);
-extern void efx_farch_rx_defer_refill(struct efx_rx_queue *rx_queue);
-extern int efx_farch_ev_probe(struct efx_channel *channel);
-extern int efx_farch_ev_init(struct efx_channel *channel);
-extern void efx_farch_ev_fini(struct efx_channel *channel);
-extern void efx_farch_ev_remove(struct efx_channel *channel);
-extern int efx_farch_ev_process(struct efx_channel *channel, int quota);
-extern void efx_farch_ev_read_ack(struct efx_channel *channel);
-extern void efx_farch_ev_test_generate(struct efx_channel *channel);
+int efx_farch_tx_probe(struct efx_tx_queue *tx_queue);
+void efx_farch_tx_init(struct efx_tx_queue *tx_queue);
+void efx_farch_tx_fini(struct efx_tx_queue *tx_queue);
+void efx_farch_tx_remove(struct efx_tx_queue *tx_queue);
+void efx_farch_tx_write(struct efx_tx_queue *tx_queue);
+int efx_farch_rx_probe(struct efx_rx_queue *rx_queue);
+void efx_farch_rx_init(struct efx_rx_queue *rx_queue);
+void efx_farch_rx_fini(struct efx_rx_queue *rx_queue);
+void efx_farch_rx_remove(struct efx_rx_queue *rx_queue);
+void efx_farch_rx_write(struct efx_rx_queue *rx_queue);
+void efx_farch_rx_defer_refill(struct efx_rx_queue *rx_queue);
+int efx_farch_ev_probe(struct efx_channel *channel);
+int efx_farch_ev_init(struct efx_channel *channel);
+void efx_farch_ev_fini(struct efx_channel *channel);
+void efx_farch_ev_remove(struct efx_channel *channel);
+int efx_farch_ev_process(struct efx_channel *channel, int quota);
+void efx_farch_ev_read_ack(struct efx_channel *channel);
+void efx_farch_ev_test_generate(struct efx_channel *channel);
/* Falcon/Siena filter operations */
-extern int efx_farch_filter_table_probe(struct efx_nic *efx);
-extern void efx_farch_filter_table_restore(struct efx_nic *efx);
-extern void efx_farch_filter_table_remove(struct efx_nic *efx);
-extern void efx_farch_filter_update_rx_scatter(struct efx_nic *efx);
-extern s32 efx_farch_filter_insert(struct efx_nic *efx,
- struct efx_filter_spec *spec, bool replace);
-extern int efx_farch_filter_remove_safe(struct efx_nic *efx,
- enum efx_filter_priority priority,
- u32 filter_id);
-extern int efx_farch_filter_get_safe(struct efx_nic *efx,
- enum efx_filter_priority priority,
- u32 filter_id, struct efx_filter_spec *);
-extern void efx_farch_filter_clear_rx(struct efx_nic *efx,
- enum efx_filter_priority priority);
-extern u32 efx_farch_filter_count_rx_used(struct efx_nic *efx,
- enum efx_filter_priority priority);
-extern u32 efx_farch_filter_get_rx_id_limit(struct efx_nic *efx);
-extern s32 efx_farch_filter_get_rx_ids(struct efx_nic *efx,
- enum efx_filter_priority priority,
- u32 *buf, u32 size);
+int efx_farch_filter_table_probe(struct efx_nic *efx);
+void efx_farch_filter_table_restore(struct efx_nic *efx);
+void efx_farch_filter_table_remove(struct efx_nic *efx);
+void efx_farch_filter_update_rx_scatter(struct efx_nic *efx);
+s32 efx_farch_filter_insert(struct efx_nic *efx, struct efx_filter_spec *spec,
+ bool replace);
+int efx_farch_filter_remove_safe(struct efx_nic *efx,
+ enum efx_filter_priority priority,
+ u32 filter_id);
+int efx_farch_filter_get_safe(struct efx_nic *efx,
+ enum efx_filter_priority priority, u32 filter_id,
+ struct efx_filter_spec *);
+void efx_farch_filter_clear_rx(struct efx_nic *efx,
+ enum efx_filter_priority priority);
+u32 efx_farch_filter_count_rx_used(struct efx_nic *efx,
+ enum efx_filter_priority priority);
+u32 efx_farch_filter_get_rx_id_limit(struct efx_nic *efx);
+s32 efx_farch_filter_get_rx_ids(struct efx_nic *efx,
+ enum efx_filter_priority priority, u32 *buf,
+ u32 size);
#ifdef CONFIG_RFS_ACCEL
-extern s32 efx_farch_filter_rfs_insert(struct efx_nic *efx,
- struct efx_filter_spec *spec);
-extern bool efx_farch_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id,
- unsigned int index);
+s32 efx_farch_filter_rfs_insert(struct efx_nic *efx,
+ struct efx_filter_spec *spec);
+bool efx_farch_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id,
+ unsigned int index);
#endif
-extern void efx_farch_filter_sync_rx_mode(struct efx_nic *efx);
+void efx_farch_filter_sync_rx_mode(struct efx_nic *efx);
-extern bool efx_nic_event_present(struct efx_channel *channel);
+bool efx_nic_event_present(struct efx_channel *channel);
/* Some statistics are computed as A - B where A and B each increase
* linearly with some hardware counter(s) and the counters are read
@@ -669,17 +701,17 @@ static inline void efx_update_diff_stat(u64 *stat, u64 diff)
}
/* Interrupts */
-extern int efx_nic_init_interrupt(struct efx_nic *efx);
-extern void efx_nic_irq_test_start(struct efx_nic *efx);
-extern void efx_nic_fini_interrupt(struct efx_nic *efx);
+int efx_nic_init_interrupt(struct efx_nic *efx);
+void efx_nic_irq_test_start(struct efx_nic *efx);
+void efx_nic_fini_interrupt(struct efx_nic *efx);
/* Falcon/Siena interrupts */
-extern void efx_farch_irq_enable_master(struct efx_nic *efx);
-extern void efx_farch_irq_test_generate(struct efx_nic *efx);
-extern void efx_farch_irq_disable_master(struct efx_nic *efx);
-extern irqreturn_t efx_farch_msi_interrupt(int irq, void *dev_id);
-extern irqreturn_t efx_farch_legacy_interrupt(int irq, void *dev_id);
-extern irqreturn_t efx_farch_fatal_interrupt(struct efx_nic *efx);
+void efx_farch_irq_enable_master(struct efx_nic *efx);
+void efx_farch_irq_test_generate(struct efx_nic *efx);
+void efx_farch_irq_disable_master(struct efx_nic *efx);
+irqreturn_t efx_farch_msi_interrupt(int irq, void *dev_id);
+irqreturn_t efx_farch_legacy_interrupt(int irq, void *dev_id);
+irqreturn_t efx_farch_fatal_interrupt(struct efx_nic *efx);
static inline int efx_nic_event_test_irq_cpu(struct efx_channel *channel)
{
@@ -691,21 +723,21 @@ static inline int efx_nic_irq_test_irq_cpu(struct efx_nic *efx)
}
/* Global Resources */
-extern int efx_nic_flush_queues(struct efx_nic *efx);
-extern void siena_prepare_flush(struct efx_nic *efx);
-extern int efx_farch_fini_dmaq(struct efx_nic *efx);
-extern void siena_finish_flush(struct efx_nic *efx);
-extern void falcon_start_nic_stats(struct efx_nic *efx);
-extern void falcon_stop_nic_stats(struct efx_nic *efx);
-extern int falcon_reset_xaui(struct efx_nic *efx);
-extern void efx_farch_dimension_resources(struct efx_nic *efx, unsigned sram_lim_qw);
-extern void efx_farch_init_common(struct efx_nic *efx);
-extern void efx_ef10_handle_drain_event(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 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);
+int falcon_reset_xaui(struct efx_nic *efx);
+void efx_farch_dimension_resources(struct efx_nic *efx, unsigned sram_lim_qw);
+void efx_farch_init_common(struct efx_nic *efx);
+void efx_ef10_handle_drain_event(struct efx_nic *efx);
static inline void efx_nic_push_rx_indir_table(struct efx_nic *efx)
{
efx->type->rx_push_indir_table(efx);
}
-extern void efx_farch_rx_push_indir_table(struct efx_nic *efx);
+void efx_farch_rx_push_indir_table(struct efx_nic *efx);
int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer,
unsigned int len, gfp_t gfp_flags);
@@ -716,24 +748,22 @@ struct efx_farch_register_test {
unsigned address;
efx_oword_t mask;
};
-extern int efx_farch_test_registers(struct efx_nic *efx,
- const struct efx_farch_register_test *regs,
- size_t n_regs);
+int efx_farch_test_registers(struct efx_nic *efx,
+ const struct efx_farch_register_test *regs,
+ size_t n_regs);
-extern size_t efx_nic_get_regs_len(struct efx_nic *efx);
-extern void efx_nic_get_regs(struct efx_nic *efx, void *buf);
+size_t efx_nic_get_regs_len(struct efx_nic *efx);
+void efx_nic_get_regs(struct efx_nic *efx, void *buf);
-extern size_t
-efx_nic_describe_stats(const struct efx_hw_stat_desc *desc, size_t count,
- const unsigned long *mask, u8 *names);
-extern void
-efx_nic_update_stats(const struct efx_hw_stat_desc *desc, size_t count,
- const unsigned long *mask,
- u64 *stats, const void *dma_buf, bool accumulate);
+size_t efx_nic_describe_stats(const struct efx_hw_stat_desc *desc, size_t count,
+ const unsigned long *mask, u8 *names);
+void efx_nic_update_stats(const struct efx_hw_stat_desc *desc, size_t count,
+ const unsigned long *mask, u64 *stats,
+ const void *dma_buf, bool accumulate);
#define EFX_MAX_FLUSH_TIME 5000
-extern void efx_farch_generate_event(struct efx_nic *efx, unsigned int evq,
- efx_qword_t *event);
+void efx_farch_generate_event(struct efx_nic *efx, unsigned int evq,
+ efx_qword_t *event);
#endif /* EFX_NIC_H */
diff --git a/drivers/net/ethernet/sfc/phy.h b/drivers/net/ethernet/sfc/phy.h
index 45eeb7075156..803bf445c08e 100644
--- a/drivers/net/ethernet/sfc/phy.h
+++ b/drivers/net/ethernet/sfc/phy.h
@@ -15,7 +15,7 @@
*/
extern const struct efx_phy_operations falcon_sfx7101_phy_ops;
-extern void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
+void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode);
/****************************************************************************
* AMCC/Quake QT202x PHYs
@@ -34,7 +34,7 @@ extern const struct efx_phy_operations falcon_qt202x_phy_ops;
#define QUAKE_LED_TXLINK (0)
#define QUAKE_LED_RXLINK (8)
-extern void falcon_qt202x_set_led(struct efx_nic *p, int led, int state);
+void falcon_qt202x_set_led(struct efx_nic *p, int led, int state);
/****************************************************************************
* Transwitch CX4 retimer
@@ -44,7 +44,7 @@ extern const struct efx_phy_operations falcon_txc_phy_ops;
#define TXC_GPIO_DIR_INPUT 0
#define TXC_GPIO_DIR_OUTPUT 1
-extern void falcon_txc_set_gpio_dir(struct efx_nic *efx, int pin, int dir);
-extern void falcon_txc_set_gpio_val(struct efx_nic *efx, int pin, int val);
+void falcon_txc_set_gpio_dir(struct efx_nic *efx, int pin, int dir);
+void falcon_txc_set_gpio_val(struct efx_nic *efx, int pin, int val);
#endif
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index 4a596725023f..8f09e686fc23 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -12,6 +12,7 @@
#include <linux/in.h>
#include <linux/slab.h>
#include <linux/ip.h>
+#include <linux/ipv6.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/prefetch.h>
@@ -818,44 +819,70 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
struct efx_nic *efx = netdev_priv(net_dev);
struct efx_channel *channel;
struct efx_filter_spec spec;
- const struct iphdr *ip;
const __be16 *ports;
+ __be16 ether_type;
int nhoff;
int rc;
- nhoff = skb_network_offset(skb);
+ /* The core RPS/RFS code has already parsed and validated
+ * VLAN, IP and transport headers. We assume they are in the
+ * header area.
+ */
if (skb->protocol == htons(ETH_P_8021Q)) {
- EFX_BUG_ON_PARANOID(skb_headlen(skb) <
- nhoff + sizeof(struct vlan_hdr));
- if (((const struct vlan_hdr *)skb->data + nhoff)->
- h_vlan_encapsulated_proto != htons(ETH_P_IP))
- return -EPROTONOSUPPORT;
+ const struct vlan_hdr *vh =
+ (const struct vlan_hdr *)skb->data;
- /* This is IP over 802.1q VLAN. We can't filter on the
- * IP 5-tuple and the vlan together, so just strip the
- * vlan header and filter on the IP part.
+ /* We can't filter on the IP 5-tuple and the vlan
+ * together, so just strip the vlan header and filter
+ * on the IP part.
*/
- nhoff += sizeof(struct vlan_hdr);
- } else if (skb->protocol != htons(ETH_P_IP)) {
- return -EPROTONOSUPPORT;
+ EFX_BUG_ON_PARANOID(skb_headlen(skb) < sizeof(*vh));
+ ether_type = vh->h_vlan_encapsulated_proto;
+ nhoff = sizeof(struct vlan_hdr);
+ } else {
+ ether_type = skb->protocol;
+ nhoff = 0;
}
- /* RFS must validate the IP header length before calling us */
- EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + sizeof(*ip));
- ip = (const struct iphdr *)(skb->data + nhoff);
- if (ip_is_fragment(ip))
+ if (ether_type != htons(ETH_P_IP) && ether_type != htons(ETH_P_IPV6))
return -EPROTONOSUPPORT;
- EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + 4 * ip->ihl + 4);
- ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
efx_filter_init_rx(&spec, EFX_FILTER_PRI_HINT,
efx->rx_scatter ? EFX_FILTER_FLAG_RX_SCATTER : 0,
rxq_index);
- rc = efx_filter_set_ipv4_full(&spec, ip->protocol,
- ip->daddr, ports[1], ip->saddr, ports[0]);
- if (rc)
- return rc;
+ spec.match_flags =
+ EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
+ EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
+ EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
+ spec.ether_type = ether_type;
+
+ if (ether_type == htons(ETH_P_IP)) {
+ const struct iphdr *ip =
+ (const struct iphdr *)(skb->data + nhoff);
+
+ EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + sizeof(*ip));
+ if (ip_is_fragment(ip))
+ return -EPROTONOSUPPORT;
+ spec.ip_proto = ip->protocol;
+ spec.rem_host[0] = ip->saddr;
+ spec.loc_host[0] = ip->daddr;
+ EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + 4 * ip->ihl + 4);
+ ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
+ } else {
+ const struct ipv6hdr *ip6 =
+ (const struct ipv6hdr *)(skb->data + nhoff);
+
+ EFX_BUG_ON_PARANOID(skb_headlen(skb) <
+ nhoff + sizeof(*ip6) + 4);
+ spec.ip_proto = ip6->nexthdr;
+ memcpy(spec.rem_host, &ip6->saddr, sizeof(ip6->saddr));
+ memcpy(spec.loc_host, &ip6->daddr, sizeof(ip6->daddr));
+ ports = (const __be16 *)(ip6 + 1);
+ }
+
+ spec.rem_port = ports[0];
+ spec.loc_port = ports[1];
rc = efx->type->filter_rfs_insert(efx, &spec);
if (rc < 0)
@@ -866,11 +893,18 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
channel = efx_get_channel(efx, skb_get_rx_queue(skb));
++channel->rfs_filters_added;
- netif_info(efx, rx_status, efx->net_dev,
- "steering %s %pI4:%u:%pI4:%u to queue %u [flow %u filter %d]\n",
- (ip->protocol == IPPROTO_TCP) ? "TCP" : "UDP",
- &ip->saddr, ntohs(ports[0]), &ip->daddr, ntohs(ports[1]),
- rxq_index, flow_id, rc);
+ if (ether_type == htons(ETH_P_IP))
+ netif_info(efx, rx_status, efx->net_dev,
+ "steering %s %pI4:%u:%pI4:%u to queue %u [flow %u filter %d]\n",
+ (spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP",
+ spec.rem_host, ntohs(ports[0]), spec.loc_host,
+ ntohs(ports[1]), rxq_index, flow_id, rc);
+ else
+ netif_info(efx, rx_status, efx->net_dev,
+ "steering %s [%pI6]:%u:[%pI6]:%u to queue %u [flow %u filter %d]\n",
+ (spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP",
+ spec.rem_host, ntohs(ports[0]), spec.loc_host,
+ ntohs(ports[1]), rxq_index, flow_id, rc);
return rc;
}
diff --git a/drivers/net/ethernet/sfc/selftest.h b/drivers/net/ethernet/sfc/selftest.h
index 87698ae0bf75..a2f4a06ffa4e 100644
--- a/drivers/net/ethernet/sfc/selftest.h
+++ b/drivers/net/ethernet/sfc/selftest.h
@@ -43,13 +43,12 @@ struct efx_self_tests {
struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1];
};
-extern void efx_loopback_rx_packet(struct efx_nic *efx,
- const char *buf_ptr, int pkt_len);
-extern int efx_selftest(struct efx_nic *efx,
- struct efx_self_tests *tests,
- unsigned flags);
-extern void efx_selftest_async_start(struct efx_nic *efx);
-extern void efx_selftest_async_cancel(struct efx_nic *efx);
-extern void efx_selftest_async_work(struct work_struct *data);
+void efx_loopback_rx_packet(struct efx_nic *efx, const char *buf_ptr,
+ int pkt_len);
+int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
+ unsigned flags);
+void efx_selftest_async_start(struct efx_nic *efx);
+void efx_selftest_async_cancel(struct efx_nic *efx);
+void efx_selftest_async_work(struct work_struct *data);
#endif /* EFX_SELFTEST_H */
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index 2ac91c5b5eea..282692c48e6b 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -17,10 +17,46 @@
#include <net/ipv6.h>
#include <linux/if_ether.h>
#include <linux/highmem.h>
+#include <linux/cache.h>
#include "net_driver.h"
#include "efx.h"
+#include "io.h"
#include "nic.h"
#include "workarounds.h"
+#include "ef10_regs.h"
+
+#ifdef EFX_USE_PIO
+
+#define EFX_PIOBUF_SIZE_MAX ER_DZ_TX_PIOBUF_SIZE
+#define EFX_PIOBUF_SIZE_DEF ALIGN(256, L1_CACHE_BYTES)
+unsigned int efx_piobuf_size __read_mostly = EFX_PIOBUF_SIZE_DEF;
+
+#endif /* EFX_USE_PIO */
+
+static inline unsigned int
+efx_tx_queue_get_insert_index(const struct efx_tx_queue *tx_queue)
+{
+ return tx_queue->insert_count & tx_queue->ptr_mask;
+}
+
+static inline struct efx_tx_buffer *
+__efx_tx_queue_get_insert_buffer(const struct efx_tx_queue *tx_queue)
+{
+ return &tx_queue->buffer[efx_tx_queue_get_insert_index(tx_queue)];
+}
+
+static inline struct efx_tx_buffer *
+efx_tx_queue_get_insert_buffer(const struct efx_tx_queue *tx_queue)
+{
+ struct efx_tx_buffer *buffer =
+ __efx_tx_queue_get_insert_buffer(tx_queue);
+
+ EFX_BUG_ON_PARANOID(buffer->len);
+ EFX_BUG_ON_PARANOID(buffer->flags);
+ EFX_BUG_ON_PARANOID(buffer->unmap_len);
+
+ return buffer;
+}
static void efx_dequeue_buffer(struct efx_tx_queue *tx_queue,
struct efx_tx_buffer *buffer,
@@ -83,8 +119,10 @@ unsigned int efx_tx_max_skb_descs(struct efx_nic *efx)
*/
unsigned int max_descs = EFX_TSO_MAX_SEGS * 2 + MAX_SKB_FRAGS;
- /* Possibly one more per segment for the alignment workaround */
- if (EFX_WORKAROUND_5391(efx))
+ /* Possibly one more per segment for the alignment workaround,
+ * or for option descriptors
+ */
+ if (EFX_WORKAROUND_5391(efx) || efx_nic_rev(efx) >= EFX_REV_HUNT_A0)
max_descs += EFX_TSO_MAX_SEGS;
/* Possibly more for PCIe page boundaries within input fragments */
@@ -145,6 +183,145 @@ static void efx_tx_maybe_stop_queue(struct efx_tx_queue *txq1)
}
}
+#ifdef EFX_USE_PIO
+
+struct efx_short_copy_buffer {
+ int used;
+ u8 buf[L1_CACHE_BYTES];
+};
+
+/* Copy to PIO, respecting that writes to PIO buffers must be dword aligned.
+ * Advances piobuf pointer. Leaves additional data in the copy buffer.
+ */
+static void efx_memcpy_toio_aligned(struct efx_nic *efx, u8 __iomem **piobuf,
+ u8 *data, int len,
+ struct efx_short_copy_buffer *copy_buf)
+{
+ int block_len = len & ~(sizeof(copy_buf->buf) - 1);
+
+ memcpy_toio(*piobuf, data, block_len);
+ *piobuf += block_len;
+ len -= block_len;
+
+ if (len) {
+ data += block_len;
+ BUG_ON(copy_buf->used);
+ BUG_ON(len > sizeof(copy_buf->buf));
+ memcpy(copy_buf->buf, data, len);
+ copy_buf->used = len;
+ }
+}
+
+/* Copy to PIO, respecting dword alignment, popping data from copy buffer first.
+ * Advances piobuf pointer. Leaves additional data in the copy buffer.
+ */
+static void efx_memcpy_toio_aligned_cb(struct efx_nic *efx, u8 __iomem **piobuf,
+ u8 *data, int len,
+ struct efx_short_copy_buffer *copy_buf)
+{
+ if (copy_buf->used) {
+ /* if the copy buffer is partially full, fill it up and write */
+ int copy_to_buf =
+ min_t(int, sizeof(copy_buf->buf) - copy_buf->used, len);
+
+ memcpy(copy_buf->buf + copy_buf->used, data, copy_to_buf);
+ copy_buf->used += copy_to_buf;
+
+ /* if we didn't fill it up then we're done for now */
+ if (copy_buf->used < sizeof(copy_buf->buf))
+ return;
+
+ memcpy_toio(*piobuf, copy_buf->buf, sizeof(copy_buf->buf));
+ *piobuf += sizeof(copy_buf->buf);
+ data += copy_to_buf;
+ len -= copy_to_buf;
+ copy_buf->used = 0;
+ }
+
+ efx_memcpy_toio_aligned(efx, piobuf, data, len, copy_buf);
+}
+
+static void efx_flush_copy_buffer(struct efx_nic *efx, u8 __iomem *piobuf,
+ struct efx_short_copy_buffer *copy_buf)
+{
+ /* if there's anything in it, write the whole buffer, including junk */
+ if (copy_buf->used)
+ memcpy_toio(piobuf, copy_buf->buf, sizeof(copy_buf->buf));
+}
+
+/* Traverse skb structure and copy fragments in to PIO buffer.
+ * Advances piobuf pointer.
+ */
+static void efx_skb_copy_bits_to_pio(struct efx_nic *efx, struct sk_buff *skb,
+ u8 __iomem **piobuf,
+ struct efx_short_copy_buffer *copy_buf)
+{
+ int i;
+
+ efx_memcpy_toio_aligned(efx, piobuf, skb->data, skb_headlen(skb),
+ copy_buf);
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i) {
+ skb_frag_t *f = &skb_shinfo(skb)->frags[i];
+ u8 *vaddr;
+
+ vaddr = kmap_atomic(skb_frag_page(f));
+
+ efx_memcpy_toio_aligned_cb(efx, piobuf, vaddr + f->page_offset,
+ skb_frag_size(f), copy_buf);
+ kunmap_atomic(vaddr);
+ }
+
+ EFX_BUG_ON_PARANOID(skb_shinfo(skb)->frag_list);
+}
+
+static struct efx_tx_buffer *
+efx_enqueue_skb_pio(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
+{
+ struct efx_tx_buffer *buffer =
+ efx_tx_queue_get_insert_buffer(tx_queue);
+ u8 __iomem *piobuf = tx_queue->piobuf;
+
+ /* Copy to PIO buffer. Ensure the writes are padded to the end
+ * of a cache line, as this is required for write-combining to be
+ * effective on at least x86.
+ */
+
+ if (skb_shinfo(skb)->nr_frags) {
+ /* The size of the copy buffer will ensure all writes
+ * are the size of a cache line.
+ */
+ struct efx_short_copy_buffer copy_buf;
+
+ copy_buf.used = 0;
+
+ efx_skb_copy_bits_to_pio(tx_queue->efx, skb,
+ &piobuf, &copy_buf);
+ efx_flush_copy_buffer(tx_queue->efx, piobuf, &copy_buf);
+ } else {
+ /* Pad the write to the size of a cache line.
+ * We can do this because we know the skb_shared_info sruct is
+ * after the source, and the destination buffer is big enough.
+ */
+ BUILD_BUG_ON(L1_CACHE_BYTES >
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)));
+ memcpy_toio(tx_queue->piobuf, skb->data,
+ ALIGN(skb->len, L1_CACHE_BYTES));
+ }
+
+ EFX_POPULATE_QWORD_5(buffer->option,
+ ESF_DZ_TX_DESC_IS_OPT, 1,
+ ESF_DZ_TX_OPTION_TYPE, ESE_DZ_TX_OPTION_DESC_PIO,
+ ESF_DZ_TX_PIO_CONT, 0,
+ ESF_DZ_TX_PIO_BYTE_CNT, skb->len,
+ ESF_DZ_TX_PIO_BUF_ADDR,
+ tx_queue->piobuf_offset);
+ ++tx_queue->pio_packets;
+ ++tx_queue->insert_count;
+ return buffer;
+}
+#endif /* EFX_USE_PIO */
+
/*
* Add a socket buffer to a TX queue
*
@@ -167,7 +344,7 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
struct device *dma_dev = &efx->pci_dev->dev;
struct efx_tx_buffer *buffer;
skb_frag_t *fragment;
- unsigned int len, unmap_len = 0, insert_ptr;
+ unsigned int len, unmap_len = 0;
dma_addr_t dma_addr, unmap_addr = 0;
unsigned int dma_len;
unsigned short dma_flags;
@@ -189,6 +366,17 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
return NETDEV_TX_OK;
}
+ /* Consider using PIO for short packets */
+#ifdef EFX_USE_PIO
+ if (skb->len <= efx_piobuf_size && tx_queue->piobuf &&
+ efx_nic_tx_is_empty(tx_queue) &&
+ efx_nic_tx_is_empty(efx_tx_queue_partner(tx_queue))) {
+ buffer = efx_enqueue_skb_pio(tx_queue, skb);
+ dma_flags = EFX_TX_BUF_OPTION;
+ goto finish_packet;
+ }
+#endif
+
/* Map for DMA. Use dma_map_single rather than dma_map_page
* since this is more efficient on machines with sparse
* memory.
@@ -208,11 +396,7 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
/* Add to TX queue, splitting across DMA boundaries */
do {
- insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask;
- buffer = &tx_queue->buffer[insert_ptr];
- EFX_BUG_ON_PARANOID(buffer->flags);
- EFX_BUG_ON_PARANOID(buffer->len);
- EFX_BUG_ON_PARANOID(buffer->unmap_len);
+ buffer = efx_tx_queue_get_insert_buffer(tx_queue);
dma_len = efx_max_tx_len(efx, dma_addr);
if (likely(dma_len >= len))
@@ -245,6 +429,7 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
}
/* Transfer ownership of the skb to the final buffer */
+finish_packet:
buffer->skb = skb;
buffer->flags = EFX_TX_BUF_SKB | dma_flags;
@@ -270,8 +455,7 @@ netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb)
while (tx_queue->insert_count != tx_queue->write_count) {
unsigned int pkts_compl = 0, bytes_compl = 0;
--tx_queue->insert_count;
- insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask;
- buffer = &tx_queue->buffer[insert_ptr];
+ buffer = __efx_tx_queue_get_insert_buffer(tx_queue);
efx_dequeue_buffer(tx_queue, buffer, &pkts_compl, &bytes_compl);
}
@@ -628,6 +812,9 @@ void efx_remove_tx_queue(struct efx_tx_queue *tx_queue)
* @tcp_off: Offset of TCP header
* @header_len: Number of bytes of header
* @ip_base_len: IPv4 tot_len or IPv6 payload_len, before TCP payload
+ * @header_dma_addr: Header DMA address, when using option descriptors
+ * @header_unmap_len: Header DMA mapped length, or 0 if not using option
+ * descriptors
*
* The state used during segmentation. It is put into this data structure
* just to make it easy to pass into inline functions.
@@ -636,7 +823,7 @@ struct tso_state {
/* Output position */
unsigned out_len;
unsigned seqnum;
- unsigned ipv4_id;
+ u16 ipv4_id;
unsigned packet_space;
/* Input position */
@@ -651,6 +838,8 @@ struct tso_state {
unsigned int tcp_off;
unsigned header_len;
unsigned int ip_base_len;
+ dma_addr_t header_dma_addr;
+ unsigned int header_unmap_len;
};
@@ -737,23 +926,18 @@ static void efx_tx_queue_insert(struct efx_tx_queue *tx_queue,
{
struct efx_tx_buffer *buffer;
struct efx_nic *efx = tx_queue->efx;
- unsigned dma_len, insert_ptr;
+ unsigned dma_len;
EFX_BUG_ON_PARANOID(len <= 0);
while (1) {
- insert_ptr = tx_queue->insert_count & tx_queue->ptr_mask;
- buffer = &tx_queue->buffer[insert_ptr];
+ buffer = efx_tx_queue_get_insert_buffer(tx_queue);
++tx_queue->insert_count;
EFX_BUG_ON_PARANOID(tx_queue->insert_count -
tx_queue->read_count >=
efx->txq_entries);
- EFX_BUG_ON_PARANOID(buffer->len);
- EFX_BUG_ON_PARANOID(buffer->unmap_len);
- EFX_BUG_ON_PARANOID(buffer->flags);
-
buffer->dma_addr = dma_addr;
dma_len = efx_max_tx_len(efx, dma_addr);
@@ -814,19 +998,27 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue)
/* Work backwards until we hit the original insert pointer value */
while (tx_queue->insert_count != tx_queue->write_count) {
--tx_queue->insert_count;
- buffer = &tx_queue->buffer[tx_queue->insert_count &
- tx_queue->ptr_mask];
+ buffer = __efx_tx_queue_get_insert_buffer(tx_queue);
efx_dequeue_buffer(tx_queue, buffer, NULL, NULL);
}
}
/* Parse the SKB header and initialise state. */
-static void tso_start(struct tso_state *st, const struct sk_buff *skb)
+static int tso_start(struct tso_state *st, struct efx_nic *efx,
+ const struct sk_buff *skb)
{
+ bool use_options = efx_nic_rev(efx) >= EFX_REV_HUNT_A0;
+ struct device *dma_dev = &efx->pci_dev->dev;
+ unsigned int header_len, in_len;
+ dma_addr_t dma_addr;
+
st->ip_off = skb_network_header(skb) - skb->data;
st->tcp_off = skb_transport_header(skb) - skb->data;
- st->header_len = st->tcp_off + (tcp_hdr(skb)->doff << 2u);
+ header_len = st->tcp_off + (tcp_hdr(skb)->doff << 2u);
+ in_len = skb_headlen(skb) - header_len;
+ st->header_len = header_len;
+ st->in_len = in_len;
if (st->protocol == htons(ETH_P_IP)) {
st->ip_base_len = st->header_len - st->ip_off;
st->ipv4_id = ntohs(ip_hdr(skb)->id);
@@ -840,9 +1032,34 @@ static void tso_start(struct tso_state *st, const struct sk_buff *skb)
EFX_BUG_ON_PARANOID(tcp_hdr(skb)->syn);
EFX_BUG_ON_PARANOID(tcp_hdr(skb)->rst);
- st->out_len = skb->len - st->header_len;
- st->unmap_len = 0;
- st->dma_flags = 0;
+ st->out_len = skb->len - header_len;
+
+ if (!use_options) {
+ st->header_unmap_len = 0;
+
+ if (likely(in_len == 0)) {
+ st->dma_flags = 0;
+ st->unmap_len = 0;
+ return 0;
+ }
+
+ dma_addr = dma_map_single(dma_dev, skb->data + header_len,
+ in_len, DMA_TO_DEVICE);
+ st->dma_flags = EFX_TX_BUF_MAP_SINGLE;
+ st->dma_addr = dma_addr;
+ st->unmap_addr = dma_addr;
+ st->unmap_len = in_len;
+ } else {
+ dma_addr = dma_map_single(dma_dev, skb->data,
+ skb_headlen(skb), DMA_TO_DEVICE);
+ st->header_dma_addr = dma_addr;
+ st->header_unmap_len = skb_headlen(skb);
+ st->dma_flags = 0;
+ st->dma_addr = dma_addr + header_len;
+ st->unmap_len = 0;
+ }
+
+ return unlikely(dma_mapping_error(dma_dev, dma_addr)) ? -ENOMEM : 0;
}
static int tso_get_fragment(struct tso_state *st, struct efx_nic *efx,
@@ -860,24 +1077,6 @@ static int tso_get_fragment(struct tso_state *st, struct efx_nic *efx,
return -ENOMEM;
}
-static int tso_get_head_fragment(struct tso_state *st, struct efx_nic *efx,
- const struct sk_buff *skb)
-{
- int hl = st->header_len;
- int len = skb_headlen(skb) - hl;
-
- st->unmap_addr = dma_map_single(&efx->pci_dev->dev, skb->data + hl,
- len, DMA_TO_DEVICE);
- if (likely(!dma_mapping_error(&efx->pci_dev->dev, st->unmap_addr))) {
- st->dma_flags = EFX_TX_BUF_MAP_SINGLE;
- st->unmap_len = len;
- st->in_len = len;
- st->dma_addr = st->unmap_addr;
- return 0;
- }
- return -ENOMEM;
-}
-
/**
* tso_fill_packet_with_fragment - form descriptors for the current fragment
@@ -944,55 +1143,97 @@ static int tso_start_new_packet(struct efx_tx_queue *tx_queue,
struct tso_state *st)
{
struct efx_tx_buffer *buffer =
- &tx_queue->buffer[tx_queue->insert_count & tx_queue->ptr_mask];
- struct tcphdr *tsoh_th;
- unsigned ip_length;
- u8 *header;
- int rc;
+ efx_tx_queue_get_insert_buffer(tx_queue);
+ bool is_last = st->out_len <= skb_shinfo(skb)->gso_size;
+ u8 tcp_flags_clear;
- /* Allocate and insert a DMA-mapped header buffer. */
- header = efx_tsoh_get_buffer(tx_queue, buffer, st->header_len);
- if (!header)
- return -ENOMEM;
-
- tsoh_th = (struct tcphdr *)(header + st->tcp_off);
-
- /* Copy and update the headers. */
- memcpy(header, skb->data, st->header_len);
-
- tsoh_th->seq = htonl(st->seqnum);
- st->seqnum += skb_shinfo(skb)->gso_size;
- if (st->out_len > skb_shinfo(skb)->gso_size) {
- /* This packet will not finish the TSO burst. */
+ if (!is_last) {
st->packet_space = skb_shinfo(skb)->gso_size;
- tsoh_th->fin = 0;
- tsoh_th->psh = 0;
+ tcp_flags_clear = 0x09; /* mask out FIN and PSH */
} else {
- /* This packet will be the last in the TSO burst. */
st->packet_space = st->out_len;
- tsoh_th->fin = tcp_hdr(skb)->fin;
- tsoh_th->psh = tcp_hdr(skb)->psh;
+ tcp_flags_clear = 0x00;
}
- ip_length = st->ip_base_len + st->packet_space;
- if (st->protocol == htons(ETH_P_IP)) {
- struct iphdr *tsoh_iph = (struct iphdr *)(header + st->ip_off);
+ if (!st->header_unmap_len) {
+ /* Allocate and insert a DMA-mapped header buffer. */
+ struct tcphdr *tsoh_th;
+ unsigned ip_length;
+ u8 *header;
+ int rc;
+
+ header = efx_tsoh_get_buffer(tx_queue, buffer, st->header_len);
+ if (!header)
+ return -ENOMEM;
- tsoh_iph->tot_len = htons(ip_length);
+ tsoh_th = (struct tcphdr *)(header + st->tcp_off);
+
+ /* Copy and update the headers. */
+ memcpy(header, skb->data, st->header_len);
+
+ tsoh_th->seq = htonl(st->seqnum);
+ ((u8 *)tsoh_th)[13] &= ~tcp_flags_clear;
+
+ ip_length = st->ip_base_len + st->packet_space;
+
+ if (st->protocol == htons(ETH_P_IP)) {
+ struct iphdr *tsoh_iph =
+ (struct iphdr *)(header + st->ip_off);
+
+ tsoh_iph->tot_len = htons(ip_length);
+ tsoh_iph->id = htons(st->ipv4_id);
+ } else {
+ struct ipv6hdr *tsoh_iph =
+ (struct ipv6hdr *)(header + st->ip_off);
+
+ tsoh_iph->payload_len = htons(ip_length);
+ }
- /* Linux leaves suitable gaps in the IP ID space for us to fill. */
- tsoh_iph->id = htons(st->ipv4_id);
- st->ipv4_id++;
+ rc = efx_tso_put_header(tx_queue, buffer, header);
+ if (unlikely(rc))
+ return rc;
} else {
- struct ipv6hdr *tsoh_iph =
- (struct ipv6hdr *)(header + st->ip_off);
+ /* Send the original headers with a TSO option descriptor
+ * in front
+ */
+ u8 tcp_flags = ((u8 *)tcp_hdr(skb))[13] & ~tcp_flags_clear;
- tsoh_iph->payload_len = htons(ip_length);
+ buffer->flags = EFX_TX_BUF_OPTION;
+ buffer->len = 0;
+ buffer->unmap_len = 0;
+ EFX_POPULATE_QWORD_5(buffer->option,
+ ESF_DZ_TX_DESC_IS_OPT, 1,
+ ESF_DZ_TX_OPTION_TYPE,
+ ESE_DZ_TX_OPTION_DESC_TSO,
+ ESF_DZ_TX_TSO_TCP_FLAGS, tcp_flags,
+ ESF_DZ_TX_TSO_IP_ID, st->ipv4_id,
+ ESF_DZ_TX_TSO_TCP_SEQNO, st->seqnum);
+ ++tx_queue->insert_count;
+
+ /* We mapped the headers in tso_start(). Unmap them
+ * when the last segment is completed.
+ */
+ buffer = efx_tx_queue_get_insert_buffer(tx_queue);
+ buffer->dma_addr = st->header_dma_addr;
+ buffer->len = st->header_len;
+ if (is_last) {
+ buffer->flags = EFX_TX_BUF_CONT | EFX_TX_BUF_MAP_SINGLE;
+ buffer->unmap_len = st->header_unmap_len;
+ /* Ensure we only unmap them once in case of a
+ * later DMA mapping error and rollback
+ */
+ st->header_unmap_len = 0;
+ } else {
+ buffer->flags = EFX_TX_BUF_CONT;
+ buffer->unmap_len = 0;
+ }
+ ++tx_queue->insert_count;
}
- rc = efx_tso_put_header(tx_queue, buffer, header);
- if (unlikely(rc))
- return rc;
+ st->seqnum += skb_shinfo(skb)->gso_size;
+
+ /* Linux leaves suitable gaps in the IP ID space for us to fill. */
+ ++st->ipv4_id;
++tx_queue->tso_packets;
@@ -1023,12 +1264,11 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
EFX_BUG_ON_PARANOID(tx_queue->write_count != tx_queue->insert_count);
- tso_start(&state, skb);
+ rc = tso_start(&state, efx, skb);
+ if (rc)
+ goto mem_err;
- /* Assume that skb header area contains exactly the headers, and
- * all payload is in the frag list.
- */
- if (skb_headlen(skb) == state.header_len) {
+ if (likely(state.in_len == 0)) {
/* Grab the first payload fragment. */
EFX_BUG_ON_PARANOID(skb_shinfo(skb)->nr_frags < 1);
frag_i = 0;
@@ -1037,9 +1277,7 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
if (rc)
goto mem_err;
} else {
- rc = tso_get_head_fragment(&state, efx, skb);
- if (rc)
- goto mem_err;
+ /* Payload starts in the header area. */
frag_i = -1;
}
@@ -1091,6 +1329,11 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue,
state.unmap_len, DMA_TO_DEVICE);
}
+ /* Free the header DMA mapping, if using option descriptors */
+ if (state.header_unmap_len)
+ dma_unmap_single(&efx->pci_dev->dev, state.header_dma_addr,
+ state.header_unmap_len, DMA_TO_DEVICE);
+
efx_enqueue_unwind(tx_queue);
return NETDEV_TX_OK;
}
diff --git a/drivers/net/ethernet/smsc/smc9194.c b/drivers/net/ethernet/smsc/smc9194.c
index e85c2e7e8246..afd9873e9bdb 100644
--- a/drivers/net/ethernet/smsc/smc9194.c
+++ b/drivers/net/ethernet/smsc/smc9194.c
@@ -95,14 +95,6 @@ static const char version[] =
#define USE_32_BIT 1
#endif
-#if defined(__H8300H__) || defined(__H8300S__)
-#define NO_AUTOPROBE
-#undef insl
-#undef outsl
-#define insl(a,b,l) io_insl_noswap(a,b,l)
-#define outsl(a,b,l) io_outsl_noswap(a,b,l)
-#endif
-
/*
.the SMC9194 can be at any of the following port addresses. To change,
.for a slightly different card, you can add it to the array. Keep in
@@ -114,12 +106,6 @@ struct devlist {
unsigned int irq;
};
-#if defined(CONFIG_H8S_EDOSK2674)
-static struct devlist smc_devlist[] __initdata = {
- {.port = 0xf80000, .irq = 16},
- {.port = 0, .irq = 0 },
-};
-#else
static struct devlist smc_devlist[] __initdata = {
{.port = 0x200, .irq = 0},
{.port = 0x220, .irq = 0},
@@ -139,7 +125,6 @@ static struct devlist smc_devlist[] __initdata = {
{.port = 0x3E0, .irq = 0},
{.port = 0, .irq = 0},
};
-#endif
/*
. Wait time for memory to be free. This probably shouldn't be
. tuned that much, as waiting for this means nothing else happens
@@ -651,11 +636,7 @@ static void smc_hardware_send_packet( struct net_device * dev )
#ifdef USE_32_BIT
if ( length & 0x2 ) {
outsl(ioaddr + DATA_1, buf, length >> 2 );
-#if !defined(__H8300H__) && !defined(__H8300S__)
outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1);
-#else
- ctrl_outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1);
-#endif
}
else
outsl(ioaddr + DATA_1, buf, length >> 2 );
@@ -899,7 +880,6 @@ static int __init smc_probe(struct net_device *dev, int ioaddr)
retval = -ENODEV;
goto err_out;
}
-#if !defined(CONFIG_H8S_EDOSK2674)
/* well, we've already written once, so hopefully another time won't
hurt. This time, I need to switch the bank register to bank 1,
so I can access the base address register */
@@ -914,10 +894,6 @@ static int __init smc_probe(struct net_device *dev, int ioaddr)
retval = -ENODEV;
goto err_out;
}
-#else
- (void)base_address_register; /* Warning suppression */
-#endif
-
/* check if the revision register is something that I recognize.
These might need to be added to later, as future revisions
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 7eb8babed2cb..fc94f202a43e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -451,14 +451,14 @@ struct mac_device_info {
struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr);
struct mac_device_info *dwmac100_setup(void __iomem *ioaddr);
-extern void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
- unsigned int high, unsigned int low);
-extern void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
- unsigned int high, unsigned int low);
+void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
+ unsigned int high, unsigned int low);
+void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
+ unsigned int high, unsigned int low);
-extern void stmmac_set_mac(void __iomem *ioaddr, bool enable);
+void stmmac_set_mac(void __iomem *ioaddr, bool enable);
-extern void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr);
+void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr);
extern const struct stmmac_ring_mode_ops ring_mode_ops;
extern const struct stmmac_chain_mode_ops chain_mode_ops;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
index 8e5662ce488b..def266da55db 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -104,14 +104,13 @@
#define DMA_STATUS_TI 0x00000001 /* Transmit Interrupt */
#define DMA_CONTROL_FTF 0x00100000 /* Flush transmit FIFO */
-extern void dwmac_enable_dma_transmission(void __iomem *ioaddr);
-extern void dwmac_enable_dma_irq(void __iomem *ioaddr);
-extern void dwmac_disable_dma_irq(void __iomem *ioaddr);
-extern void dwmac_dma_start_tx(void __iomem *ioaddr);
-extern void dwmac_dma_stop_tx(void __iomem *ioaddr);
-extern void dwmac_dma_start_rx(void __iomem *ioaddr);
-extern void dwmac_dma_stop_rx(void __iomem *ioaddr);
-extern int dwmac_dma_interrupt(void __iomem *ioaddr,
- struct stmmac_extra_stats *x);
+void dwmac_enable_dma_transmission(void __iomem *ioaddr);
+void dwmac_enable_dma_irq(void __iomem *ioaddr);
+void dwmac_disable_dma_irq(void __iomem *ioaddr);
+void dwmac_dma_start_tx(void __iomem *ioaddr);
+void dwmac_dma_stop_tx(void __iomem *ioaddr);
+void dwmac_dma_start_rx(void __iomem *ioaddr);
+void dwmac_dma_stop_rx(void __iomem *ioaddr);
+int dwmac_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x);
#endif /* __DWMAC_DMA_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc.h b/drivers/net/ethernet/stmicro/stmmac/mmc.h
index 48ec001566b5..8607488cbcfc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/mmc.h
+++ b/drivers/net/ethernet/stmicro/stmmac/mmc.h
@@ -128,8 +128,8 @@ struct stmmac_counters {
unsigned int mmc_rx_icmp_err_octets;
};
-extern void dwmac_mmc_ctrl(void __iomem *ioaddr, unsigned int mode);
-extern void dwmac_mmc_intr_all_mask(void __iomem *ioaddr);
-extern void dwmac_mmc_read(void __iomem *ioaddr, struct stmmac_counters *mmc);
+void dwmac_mmc_ctrl(void __iomem *ioaddr, unsigned int mode);
+void dwmac_mmc_intr_all_mask(void __iomem *ioaddr);
+void dwmac_mmc_read(void __iomem *ioaddr, struct stmmac_counters *mmc);
#endif /* __MMC_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index f16a9bdf45bb..22f89ffdfd95 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -110,14 +110,14 @@ struct stmmac_priv {
extern int phyaddr;
-extern int stmmac_mdio_unregister(struct net_device *ndev);
-extern int stmmac_mdio_register(struct net_device *ndev);
-extern void stmmac_set_ethtool_ops(struct net_device *netdev);
+int stmmac_mdio_unregister(struct net_device *ndev);
+int stmmac_mdio_register(struct net_device *ndev);
+void stmmac_set_ethtool_ops(struct net_device *netdev);
extern const struct stmmac_desc_ops enh_desc_ops;
extern const struct stmmac_desc_ops ndesc_ops;
extern const struct stmmac_hwtimestamp stmmac_ptp;
-extern int stmmac_ptp_register(struct stmmac_priv *priv);
-extern void stmmac_ptp_unregister(struct stmmac_priv *priv);
+int stmmac_ptp_register(struct stmmac_priv *priv);
+void stmmac_ptp_unregister(struct stmmac_priv *priv);
int stmmac_freeze(struct net_device *ndev);
int stmmac_restore(struct net_device *ndev);
int stmmac_resume(struct net_device *ndev);
diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
index de71b1ec4625..53150c25a96b 100644
--- a/drivers/net/ethernet/ti/Kconfig
+++ b/drivers/net/ethernet/ti/Kconfig
@@ -49,11 +49,19 @@ config TI_DAVINCI_CPDMA
To compile this driver as a module, choose M here: the module
will be called davinci_cpdma. This is recommended.
+config TI_CPSW_PHY_SEL
+ boolean "TI CPSW Switch Phy sel Support"
+ depends on TI_CPSW
+ ---help---
+ This driver supports configuring of the phy mode connected to
+ the CPSW.
+
config TI_CPSW
tristate "TI CPSW Switch Support"
depends on ARM && (ARCH_DAVINCI || SOC_AM33XX)
select TI_DAVINCI_CPDMA
select TI_DAVINCI_MDIO
+ select TI_CPSW_PHY_SEL
---help---
This driver supports TI's CPSW Ethernet Switch.
diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile
index c65148e8aa1d..9cfaab8152be 100644
--- a/drivers/net/ethernet/ti/Makefile
+++ b/drivers/net/ethernet/ti/Makefile
@@ -7,5 +7,6 @@ obj-$(CONFIG_CPMAC) += cpmac.o
obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o
obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o
+obj-$(CONFIG_TI_CPSW_PHY_SEL) += cpsw-phy-sel.o
obj-$(CONFIG_TI_CPSW) += ti_cpsw.o
ti_cpsw-y := cpsw_ale.o cpsw.o cpts.o
diff --git a/drivers/net/ethernet/ti/cpsw-phy-sel.c b/drivers/net/ethernet/ti/cpsw-phy-sel.c
new file mode 100644
index 000000000000..e092edeab650
--- /dev/null
+++ b/drivers/net/ethernet/ti/cpsw-phy-sel.c
@@ -0,0 +1,161 @@
+/* Texas Instruments Ethernet Switch Driver
+ *
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * 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 "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/platform_device.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#include "cpsw.h"
+
+/* AM33xx SoC specific definitions for the CONTROL port */
+#define AM33XX_GMII_SEL_MODE_MII 0
+#define AM33XX_GMII_SEL_MODE_RMII 1
+#define AM33XX_GMII_SEL_MODE_RGMII 2
+
+#define AM33XX_GMII_SEL_RMII2_IO_CLK_EN BIT(7)
+#define AM33XX_GMII_SEL_RMII1_IO_CLK_EN BIT(6)
+
+struct cpsw_phy_sel_priv {
+ struct device *dev;
+ u32 __iomem *gmii_sel;
+ bool rmii_clock_external;
+ void (*cpsw_phy_sel)(struct cpsw_phy_sel_priv *priv,
+ phy_interface_t phy_mode, int slave);
+};
+
+
+static void cpsw_gmii_sel_am3352(struct cpsw_phy_sel_priv *priv,
+ phy_interface_t phy_mode, int slave)
+{
+ u32 reg;
+ u32 mask;
+ u32 mode = 0;
+
+ reg = readl(priv->gmii_sel);
+
+ switch (phy_mode) {
+ case PHY_INTERFACE_MODE_RMII:
+ mode = AM33XX_GMII_SEL_MODE_RMII;
+ break;
+
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ mode = AM33XX_GMII_SEL_MODE_RGMII;
+ break;
+
+ case PHY_INTERFACE_MODE_MII:
+ default:
+ mode = AM33XX_GMII_SEL_MODE_MII;
+ break;
+ };
+
+ mask = 0x3 << (slave * 2) | BIT(slave + 6);
+ mode <<= slave * 2;
+
+ if (priv->rmii_clock_external) {
+ if (slave == 0)
+ mode |= AM33XX_GMII_SEL_RMII1_IO_CLK_EN;
+ else
+ mode |= AM33XX_GMII_SEL_RMII2_IO_CLK_EN;
+ }
+
+ reg &= ~mask;
+ reg |= mode;
+
+ writel(reg, priv->gmii_sel);
+}
+
+static struct platform_driver cpsw_phy_sel_driver;
+static int match(struct device *dev, void *data)
+{
+ struct device_node *node = (struct device_node *)data;
+ return dev->of_node == node &&
+ dev->driver == &cpsw_phy_sel_driver.driver;
+}
+
+void cpsw_phy_sel(struct device *dev, phy_interface_t phy_mode, int slave)
+{
+ struct device_node *node;
+ struct cpsw_phy_sel_priv *priv;
+
+ node = of_get_child_by_name(dev->of_node, "cpsw-phy-sel");
+ if (!node) {
+ dev_err(dev, "Phy mode driver DT not found\n");
+ return;
+ }
+
+ dev = bus_find_device(&platform_bus_type, NULL, node, match);
+ priv = dev_get_drvdata(dev);
+
+ priv->cpsw_phy_sel(priv, phy_mode, slave);
+}
+EXPORT_SYMBOL_GPL(cpsw_phy_sel);
+
+static const struct of_device_id cpsw_phy_sel_id_table[] = {
+ {
+ .compatible = "ti,am3352-cpsw-phy-sel",
+ .data = &cpsw_gmii_sel_am3352,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, cpsw_phy_sel_id_table);
+
+static int cpsw_phy_sel_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ const struct of_device_id *of_id;
+ struct cpsw_phy_sel_priv *priv;
+
+ of_id = of_match_node(cpsw_phy_sel_id_table, pdev->dev.of_node);
+ if (!of_id)
+ return -EINVAL;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(&pdev->dev, "unable to alloc memory for cpsw phy sel\n");
+ return -ENOMEM;
+ }
+
+ priv->cpsw_phy_sel = of_id->data;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gmii-sel");
+ priv->gmii_sel = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->gmii_sel))
+ return PTR_ERR(priv->gmii_sel);
+
+ if (of_find_property(pdev->dev.of_node, "rmii-clock-ext", NULL))
+ priv->rmii_clock_external = true;
+
+ dev_set_drvdata(&pdev->dev, priv);
+
+ return 0;
+}
+
+static struct platform_driver cpsw_phy_sel_driver = {
+ .probe = cpsw_phy_sel_probe,
+ .driver = {
+ .name = "cpsw-phy-sel",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(cpsw_phy_sel_id_table),
+ },
+};
+
+module_platform_driver(cpsw_phy_sel_driver);
+MODULE_AUTHOR("Mugunthan V N <mugunthanvnm@ti.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 79974e31187a..5efb37bf0681 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -367,8 +367,6 @@ struct cpsw_priv {
spinlock_t lock;
struct platform_device *pdev;
struct net_device *ndev;
- struct resource *cpsw_res;
- struct resource *cpsw_wr_res;
struct napi_struct napi;
struct device *dev;
struct cpsw_platform_data data;
@@ -1023,6 +1021,10 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
dev_info(priv->dev, "phy found : id is : 0x%x\n",
slave->phy->phy_id);
phy_start(slave->phy);
+
+ /* Configure GMII_SEL register */
+ cpsw_phy_sel(&priv->pdev->dev, slave->phy->interface,
+ slave->slave_num);
}
}
@@ -1712,62 +1714,55 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
if (of_property_read_u32(node, "active_slave", &prop)) {
pr_err("Missing active_slave property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->active_slave = prop;
if (of_property_read_u32(node, "cpts_clock_mult", &prop)) {
pr_err("Missing cpts_clock_mult property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->cpts_clock_mult = prop;
if (of_property_read_u32(node, "cpts_clock_shift", &prop)) {
pr_err("Missing cpts_clock_shift property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->cpts_clock_shift = prop;
- data->slave_data = kcalloc(data->slaves, sizeof(struct cpsw_slave_data),
- GFP_KERNEL);
+ data->slave_data = devm_kzalloc(&pdev->dev, data->slaves
+ * sizeof(struct cpsw_slave_data),
+ GFP_KERNEL);
if (!data->slave_data)
- return -EINVAL;
+ return -ENOMEM;
if (of_property_read_u32(node, "cpdma_channels", &prop)) {
pr_err("Missing cpdma_channels property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->channels = prop;
if (of_property_read_u32(node, "ale_entries", &prop)) {
pr_err("Missing ale_entries property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->ale_entries = prop;
if (of_property_read_u32(node, "bd_ram_size", &prop)) {
pr_err("Missing bd_ram_size property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->bd_ram_size = prop;
if (of_property_read_u32(node, "rx_descs", &prop)) {
pr_err("Missing rx_descs property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->rx_descs = prop;
if (of_property_read_u32(node, "mac_control", &prop)) {
pr_err("Missing mac_control property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->mac_control = prop;
@@ -1794,8 +1789,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
parp = of_get_property(slave_node, "phy_id", &lenp);
if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) {
pr_err("Missing slave[%d] phy_id property\n", i);
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
mdio_node = of_find_node_by_phandle(be32_to_cpup(parp));
phyid = be32_to_cpup(parp+1);
@@ -1825,10 +1819,6 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
return 0;
-
-error_ret:
- kfree(data->slave_data);
- return ret;
}
static int cpsw_probe_dual_emac(struct platform_device *pdev,
@@ -1870,7 +1860,6 @@ static int cpsw_probe_dual_emac(struct platform_device *pdev,
priv_sl2->coal_intvl = 0;
priv_sl2->bus_freq_mhz = priv->bus_freq_mhz;
- priv_sl2->cpsw_res = priv->cpsw_res;
priv_sl2->regs = priv->regs;
priv_sl2->host_port = priv->host_port;
priv_sl2->host_port_regs = priv->host_port_regs;
@@ -1914,8 +1903,8 @@ static int cpsw_probe(struct platform_device *pdev)
struct cpsw_priv *priv;
struct cpdma_params dma_params;
struct cpsw_ale_params ale_params;
- void __iomem *ss_regs, *wr_regs;
- struct resource *res;
+ void __iomem *ss_regs;
+ struct resource *res, *ss_res;
u32 slave_offset, sliver_offset, slave_size;
int ret = 0, i, k = 0;
@@ -1951,7 +1940,7 @@ static int cpsw_probe(struct platform_device *pdev)
if (cpsw_probe_dt(&priv->data, pdev)) {
pr_err("cpsw: platform data missing\n");
ret = -ENODEV;
- goto clean_ndev_ret;
+ goto clean_runtime_disable_ret;
}
data = &priv->data;
@@ -1965,11 +1954,12 @@ static int cpsw_probe(struct platform_device *pdev)
memcpy(ndev->dev_addr, priv->mac_addr, ETH_ALEN);
- priv->slaves = kzalloc(sizeof(struct cpsw_slave) * data->slaves,
- GFP_KERNEL);
+ priv->slaves = devm_kzalloc(&pdev->dev,
+ sizeof(struct cpsw_slave) * data->slaves,
+ GFP_KERNEL);
if (!priv->slaves) {
- ret = -EBUSY;
- goto clean_ndev_ret;
+ ret = -ENOMEM;
+ goto clean_runtime_disable_ret;
}
for (i = 0; i < data->slaves; i++)
priv->slaves[i].slave_num = i;
@@ -1977,55 +1967,31 @@ static int cpsw_probe(struct platform_device *pdev)
priv->slaves[0].ndev = ndev;
priv->emac_port = 0;
- priv->clk = clk_get(&pdev->dev, "fck");
+ priv->clk = devm_clk_get(&pdev->dev, "fck");
if (IS_ERR(priv->clk)) {
- dev_err(&pdev->dev, "fck is not found\n");
+ dev_err(priv->dev, "fck is not found\n");
ret = -ENODEV;
- goto clean_slave_ret;
+ goto clean_runtime_disable_ret;
}
priv->coal_intvl = 0;
priv->bus_freq_mhz = clk_get_rate(priv->clk) / 1000000;
- priv->cpsw_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!priv->cpsw_res) {
- dev_err(priv->dev, "error getting i/o resource\n");
- ret = -ENOENT;
- goto clean_clk_ret;
- }
- if (!request_mem_region(priv->cpsw_res->start,
- resource_size(priv->cpsw_res), ndev->name)) {
- dev_err(priv->dev, "failed request i/o region\n");
- ret = -ENXIO;
- goto clean_clk_ret;
- }
- ss_regs = ioremap(priv->cpsw_res->start, resource_size(priv->cpsw_res));
- if (!ss_regs) {
- dev_err(priv->dev, "unable to map i/o region\n");
- goto clean_cpsw_iores_ret;
+ ss_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ss_regs = devm_ioremap_resource(&pdev->dev, ss_res);
+ if (IS_ERR(ss_regs)) {
+ ret = PTR_ERR(ss_regs);
+ goto clean_runtime_disable_ret;
}
priv->regs = ss_regs;
priv->version = __raw_readl(&priv->regs->id_ver);
priv->host_port = HOST_PORT_NUM;
- priv->cpsw_wr_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!priv->cpsw_wr_res) {
- dev_err(priv->dev, "error getting i/o resource\n");
- ret = -ENOENT;
- goto clean_iomap_ret;
- }
- if (!request_mem_region(priv->cpsw_wr_res->start,
- resource_size(priv->cpsw_wr_res), ndev->name)) {
- dev_err(priv->dev, "failed request i/o region\n");
- ret = -ENXIO;
- goto clean_iomap_ret;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ priv->wr_regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->wr_regs)) {
+ ret = PTR_ERR(priv->wr_regs);
+ goto clean_runtime_disable_ret;
}
- wr_regs = ioremap(priv->cpsw_wr_res->start,
- resource_size(priv->cpsw_wr_res));
- if (!wr_regs) {
- dev_err(priv->dev, "unable to map i/o region\n");
- goto clean_cpsw_wr_iores_ret;
- }
- priv->wr_regs = wr_regs;
memset(&dma_params, 0, sizeof(dma_params));
memset(&ale_params, 0, sizeof(ale_params));
@@ -2056,12 +2022,12 @@ static int cpsw_probe(struct platform_device *pdev)
slave_size = CPSW2_SLAVE_SIZE;
sliver_offset = CPSW2_SLIVER_OFFSET;
dma_params.desc_mem_phys =
- (u32 __force) priv->cpsw_res->start + CPSW2_BD_OFFSET;
+ (u32 __force) ss_res->start + CPSW2_BD_OFFSET;
break;
default:
dev_err(priv->dev, "unknown version 0x%08x\n", priv->version);
ret = -ENODEV;
- goto clean_cpsw_wr_iores_ret;
+ goto clean_runtime_disable_ret;
}
for (i = 0; i < priv->data.slaves; i++) {
struct cpsw_slave *slave = &priv->slaves[i];
@@ -2089,7 +2055,7 @@ static int cpsw_probe(struct platform_device *pdev)
if (!priv->dma) {
dev_err(priv->dev, "error initializing dma\n");
ret = -ENOMEM;
- goto clean_wr_iomap_ret;
+ goto clean_runtime_disable_ret;
}
priv->txch = cpdma_chan_create(priv->dma, tx_chan_num(0),
@@ -2124,8 +2090,8 @@ static int cpsw_probe(struct platform_device *pdev)
while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) {
for (i = res->start; i <= res->end; i++) {
- if (request_irq(i, cpsw_interrupt, 0,
- dev_name(&pdev->dev), priv)) {
+ if (devm_request_irq(&pdev->dev, i, cpsw_interrupt, 0,
+ dev_name(priv->dev), priv)) {
dev_err(priv->dev, "error attaching irq\n");
goto clean_ale_ret;
}
@@ -2147,7 +2113,7 @@ static int cpsw_probe(struct platform_device *pdev)
if (ret) {
dev_err(priv->dev, "error registering net device\n");
ret = -ENODEV;
- goto clean_irq_ret;
+ goto clean_ale_ret;
}
if (cpts_register(&pdev->dev, priv->cpts,
@@ -2155,44 +2121,27 @@ static int cpsw_probe(struct platform_device *pdev)
dev_err(priv->dev, "error registering cpts device\n");
cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n",
- priv->cpsw_res->start, ndev->irq);
+ ss_res->start, ndev->irq);
if (priv->data.dual_emac) {
ret = cpsw_probe_dual_emac(pdev, priv);
if (ret) {
cpsw_err(priv, probe, "error probe slave 2 emac interface\n");
- goto clean_irq_ret;
+ goto clean_ale_ret;
}
}
return 0;
-clean_irq_ret:
- for (i = 0; i < priv->num_irqs; i++)
- free_irq(priv->irqs_table[i], priv);
clean_ale_ret:
cpsw_ale_destroy(priv->ale);
clean_dma_ret:
cpdma_chan_destroy(priv->txch);
cpdma_chan_destroy(priv->rxch);
cpdma_ctlr_destroy(priv->dma);
-clean_wr_iomap_ret:
- iounmap(priv->wr_regs);
-clean_cpsw_wr_iores_ret:
- release_mem_region(priv->cpsw_wr_res->start,
- resource_size(priv->cpsw_wr_res));
-clean_iomap_ret:
- iounmap(priv->regs);
-clean_cpsw_iores_ret:
- release_mem_region(priv->cpsw_res->start,
- resource_size(priv->cpsw_res));
-clean_clk_ret:
- clk_put(priv->clk);
-clean_slave_ret:
+clean_runtime_disable_ret:
pm_runtime_disable(&pdev->dev);
- kfree(priv->slaves);
clean_ndev_ret:
- kfree(priv->data.slave_data);
free_netdev(priv->ndev);
return ret;
}
@@ -2201,30 +2150,18 @@ static int cpsw_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct cpsw_priv *priv = netdev_priv(ndev);
- int i;
if (priv->data.dual_emac)
unregister_netdev(cpsw_get_slave_ndev(priv, 1));
unregister_netdev(ndev);
cpts_unregister(priv->cpts);
- for (i = 0; i < priv->num_irqs; i++)
- free_irq(priv->irqs_table[i], priv);
cpsw_ale_destroy(priv->ale);
cpdma_chan_destroy(priv->txch);
cpdma_chan_destroy(priv->rxch);
cpdma_ctlr_destroy(priv->dma);
- iounmap(priv->regs);
- release_mem_region(priv->cpsw_res->start,
- resource_size(priv->cpsw_res));
- iounmap(priv->wr_regs);
- release_mem_region(priv->cpsw_wr_res->start,
- resource_size(priv->cpsw_wr_res));
pm_runtime_disable(&pdev->dev);
- clk_put(priv->clk);
- kfree(priv->slaves);
- kfree(priv->data.slave_data);
if (priv->data.dual_emac)
free_netdev(cpsw_get_slave_ndev(priv, 1));
free_netdev(ndev);
diff --git a/drivers/net/ethernet/ti/cpsw.h b/drivers/net/ethernet/ti/cpsw.h
index eb3e101ec048..574f49da693f 100644
--- a/drivers/net/ethernet/ti/cpsw.h
+++ b/drivers/net/ethernet/ti/cpsw.h
@@ -39,4 +39,6 @@ struct cpsw_platform_data {
bool dual_emac; /* Enable Dual EMAC mode */
};
+void cpsw_phy_sel(struct device *dev, phy_interface_t phy_mode, int slave);
+
#endif /* __CPSW_H__ */
diff --git a/drivers/net/ethernet/ti/cpts.h b/drivers/net/ethernet/ti/cpts.h
index fe993cdd7e23..1a581ef7eee8 100644
--- a/drivers/net/ethernet/ti/cpts.h
+++ b/drivers/net/ethernet/ti/cpts.h
@@ -127,8 +127,8 @@ struct cpts {
};
#ifdef CONFIG_TI_CPTS
-extern void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb);
-extern void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb);
+void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb);
+void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb);
#else
static inline void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb)
{
@@ -138,8 +138,7 @@ static inline void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb)
}
#endif
-extern int cpts_register(struct device *dev, struct cpts *cpts,
- u32 mult, u32 shift);
-extern void cpts_unregister(struct cpts *cpts);
+int cpts_register(struct device *dev, struct cpts *cpts, u32 mult, u32 shift);
+void cpts_unregister(struct cpts *cpts);
#endif
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.h b/drivers/net/ethernet/toshiba/ps3_gelic_net.h
index 309abb472aa2..8505196be9f5 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_net.h
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.h
@@ -359,27 +359,26 @@ static inline void *port_priv(struct gelic_port *port)
}
#ifdef CONFIG_PPC_EARLY_DEBUG_PS3GELIC
-extern void udbg_shutdown_ps3gelic(void);
+void udbg_shutdown_ps3gelic(void);
#else
static inline void udbg_shutdown_ps3gelic(void) {}
#endif
-extern int gelic_card_set_irq_mask(struct gelic_card *card, u64 mask);
+int gelic_card_set_irq_mask(struct gelic_card *card, u64 mask);
/* shared netdev ops */
-extern void gelic_card_up(struct gelic_card *card);
-extern void gelic_card_down(struct gelic_card *card);
-extern int gelic_net_open(struct net_device *netdev);
-extern int gelic_net_stop(struct net_device *netdev);
-extern int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev);
-extern void gelic_net_set_multi(struct net_device *netdev);
-extern void gelic_net_tx_timeout(struct net_device *netdev);
-extern int gelic_net_change_mtu(struct net_device *netdev, int new_mtu);
-extern int gelic_net_setup_netdev(struct net_device *netdev,
- struct gelic_card *card);
+void gelic_card_up(struct gelic_card *card);
+void gelic_card_down(struct gelic_card *card);
+int gelic_net_open(struct net_device *netdev);
+int gelic_net_stop(struct net_device *netdev);
+int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev);
+void gelic_net_set_multi(struct net_device *netdev);
+void gelic_net_tx_timeout(struct net_device *netdev);
+int gelic_net_change_mtu(struct net_device *netdev, int new_mtu);
+int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card);
/* shared ethtool ops */
-extern void gelic_net_get_drvinfo(struct net_device *netdev,
- struct ethtool_drvinfo *info);
-extern void gelic_net_poll_controller(struct net_device *netdev);
+void gelic_net_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *info);
+void gelic_net_poll_controller(struct net_device *netdev);
#endif /* _GELIC_NET_H */
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.h b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.h
index f7e51b7d7049..11f443d8e4ea 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.h
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.h
@@ -320,7 +320,7 @@ struct gelic_eurus_cmd {
#define GELIC_WL_PRIV_SET_PSK (SIOCIWFIRSTPRIV + 0)
#define GELIC_WL_PRIV_GET_PSK (SIOCIWFIRSTPRIV + 1)
-extern int gelic_wl_driver_probe(struct gelic_card *card);
-extern int gelic_wl_driver_remove(struct gelic_card *card);
-extern void gelic_wl_interrupt(struct net_device *netdev, u64 status);
+int gelic_wl_driver_probe(struct gelic_card *card);
+int gelic_wl_driver_remove(struct gelic_card *card);
+void gelic_wl_interrupt(struct net_device *netdev, u64 status);
#endif /* _GELIC_WIRELESS_H */
diff --git a/drivers/net/ethernet/toshiba/spider_net.h b/drivers/net/ethernet/toshiba/spider_net.h
index 4ba2135474d1..9b6af0845a11 100644
--- a/drivers/net/ethernet/toshiba/spider_net.h
+++ b/drivers/net/ethernet/toshiba/spider_net.h
@@ -29,8 +29,8 @@
#include <linux/sungem_phy.h>
-extern int spider_net_stop(struct net_device *netdev);
-extern int spider_net_open(struct net_device *netdev);
+int spider_net_stop(struct net_device *netdev);
+int spider_net_open(struct net_device *netdev);
extern const struct ethtool_ops spider_net_ethtool_ops;
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index c8f088ab5fdf..bdf697b184ae 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -32,7 +32,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define DRV_NAME "via-rhine"
-#define DRV_VERSION "1.5.0"
+#define DRV_VERSION "1.5.1"
#define DRV_RELDATE "2010-10-09"
#include <linux/types.h>
@@ -1704,7 +1704,12 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
if (unlikely(vlan_tx_tag_present(skb))) {
- rp->tx_ring[entry].tx_status = cpu_to_le32((vlan_tx_tag_get(skb)) << 16);
+ u16 vid_pcp = vlan_tx_tag_get(skb);
+
+ /* drop CFI/DEI bit, register needs VID and PCP */
+ vid_pcp = (vid_pcp & VLAN_VID_MASK) |
+ ((vid_pcp & VLAN_PRIO_MASK) >> 1);
+ rp->tx_ring[entry].tx_status = cpu_to_le32((vid_pcp) << 16);
/* request tagging */
rp->tx_ring[entry].desc_length |= cpu_to_le32(0x020000);
}
diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
index 4c619ea5189f..80dd40417850 100644
--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
@@ -31,7 +31,7 @@
#define DRIVER_NAME "xilinx_emaclite"
/* Register offsets for the EmacLite Core */
-#define XEL_TXBUFF_OFFSET 0x0 /* Transmit Buffer */
+#define XEL_TXBUFF_OFFSET 0x0 /* Transmit Buffer */
#define XEL_MDIOADDR_OFFSET 0x07E4 /* MDIO Address Register */
#define XEL_MDIOWR_OFFSET 0x07E8 /* MDIO Write Data Register */
#define XEL_MDIORD_OFFSET 0x07EC /* MDIO Read Data Register */
@@ -63,13 +63,13 @@
#define XEL_MDIOCTRL_MDIOEN_MASK 0x00000008 /* MDIO Enable */
/* Global Interrupt Enable Register (GIER) Bit Masks */
-#define XEL_GIER_GIE_MASK 0x80000000 /* Global Enable */
+#define XEL_GIER_GIE_MASK 0x80000000 /* Global Enable */
/* Transmit Status Register (TSR) Bit Masks */
-#define XEL_TSR_XMIT_BUSY_MASK 0x00000001 /* Tx complete */
-#define XEL_TSR_PROGRAM_MASK 0x00000002 /* Program the MAC address */
-#define XEL_TSR_XMIT_IE_MASK 0x00000008 /* Tx interrupt enable bit */
-#define XEL_TSR_XMIT_ACTIVE_MASK 0x80000000 /* Buffer is active, SW bit
+#define XEL_TSR_XMIT_BUSY_MASK 0x00000001 /* Tx complete */
+#define XEL_TSR_PROGRAM_MASK 0x00000002 /* Program the MAC address */
+#define XEL_TSR_XMIT_IE_MASK 0x00000008 /* Tx interrupt enable bit */
+#define XEL_TSR_XMIT_ACTIVE_MASK 0x80000000 /* Buffer is active, SW bit
* only. This is not documented
* in the HW spec */
@@ -77,21 +77,21 @@
#define XEL_TSR_PROG_MAC_ADDR (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_PROGRAM_MASK)
/* Receive Status Register (RSR) */
-#define XEL_RSR_RECV_DONE_MASK 0x00000001 /* Rx complete */
-#define XEL_RSR_RECV_IE_MASK 0x00000008 /* Rx interrupt enable bit */
+#define XEL_RSR_RECV_DONE_MASK 0x00000001 /* Rx complete */
+#define XEL_RSR_RECV_IE_MASK 0x00000008 /* Rx interrupt enable bit */
/* Transmit Packet Length Register (TPLR) */
-#define XEL_TPLR_LENGTH_MASK 0x0000FFFF /* Tx packet length */
+#define XEL_TPLR_LENGTH_MASK 0x0000FFFF /* Tx packet length */
/* Receive Packet Length Register (RPLR) */
-#define XEL_RPLR_LENGTH_MASK 0x0000FFFF /* Rx packet length */
+#define XEL_RPLR_LENGTH_MASK 0x0000FFFF /* Rx packet length */
-#define XEL_HEADER_OFFSET 12 /* Offset to length field */
-#define XEL_HEADER_SHIFT 16 /* Shift value for length */
+#define XEL_HEADER_OFFSET 12 /* Offset to length field */
+#define XEL_HEADER_SHIFT 16 /* Shift value for length */
/* General Ethernet Definitions */
-#define XEL_ARP_PACKET_SIZE 28 /* Max ARP packet size */
-#define XEL_HEADER_IP_LENGTH_OFFSET 16 /* IP Length Offset */
+#define XEL_ARP_PACKET_SIZE 28 /* Max ARP packet size */
+#define XEL_HEADER_IP_LENGTH_OFFSET 16 /* IP Length Offset */
@@ -1075,14 +1075,9 @@ static int xemaclite_send(struct sk_buff *orig_skb, struct net_device *dev)
* This function un maps the IO region of the Emaclite device and frees the net
* device.
*/
-static void xemaclite_remove_ndev(struct net_device *ndev,
- struct platform_device *pdev)
+static void xemaclite_remove_ndev(struct net_device *ndev)
{
if (ndev) {
- struct net_local *lp = netdev_priv(ndev);
-
- if (lp->base_addr)
- devm_iounmap(&pdev->dev, lp->base_addr);
free_netdev(ndev);
}
}
@@ -1214,7 +1209,7 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
return 0;
error:
- xemaclite_remove_ndev(ndev, ofdev);
+ xemaclite_remove_ndev(ndev);
return rc;
}
@@ -1248,7 +1243,7 @@ static int xemaclite_of_remove(struct platform_device *of_dev)
of_node_put(lp->phy_node);
lp->phy_node = NULL;
- xemaclite_remove_ndev(ndev, of_dev);
+ xemaclite_remove_ndev(ndev);
return 0;
}
diff --git a/drivers/net/fddi/skfp/h/smc.h b/drivers/net/fddi/skfp/h/smc.h
index 3ca308b28214..bd1166bf8f61 100644
--- a/drivers/net/fddi/skfp/h/smc.h
+++ b/drivers/net/fddi/skfp/h/smc.h
@@ -469,20 +469,20 @@ struct s_smc {
extern const struct fddi_addr fddi_broadcast;
-extern void all_selection_criteria(struct s_smc *smc);
-extern void card_stop(struct s_smc *smc);
-extern void init_board(struct s_smc *smc, u_char *mac_addr);
-extern int init_fplus(struct s_smc *smc);
-extern void init_plc(struct s_smc *smc);
-extern int init_smt(struct s_smc *smc, u_char * mac_addr);
-extern void mac1_irq(struct s_smc *smc, u_short stu, u_short stl);
-extern void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l);
-extern void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l);
-extern int pcm_status_twisted(struct s_smc *smc);
-extern void plc1_irq(struct s_smc *smc);
-extern void plc2_irq(struct s_smc *smc);
-extern void read_address(struct s_smc *smc, u_char * mac_addr);
-extern void timer_irq(struct s_smc *smc);
+void all_selection_criteria(struct s_smc *smc);
+void card_stop(struct s_smc *smc);
+void init_board(struct s_smc *smc, u_char *mac_addr);
+int init_fplus(struct s_smc *smc);
+void init_plc(struct s_smc *smc);
+int init_smt(struct s_smc *smc, u_char *mac_addr);
+void mac1_irq(struct s_smc *smc, u_short stu, u_short stl);
+void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l);
+void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l);
+int pcm_status_twisted(struct s_smc *smc);
+void plc1_irq(struct s_smc *smc);
+void plc2_irq(struct s_smc *smc);
+void read_address(struct s_smc *smc, u_char *mac_addr);
+void timer_irq(struct s_smc *smc);
#endif /* _SCMECM_ */
diff --git a/drivers/net/irda/sir-dev.h b/drivers/net/irda/sir-dev.h
index 6d5b1e2b1289..f50b9c1c0639 100644
--- a/drivers/net/irda/sir-dev.h
+++ b/drivers/net/irda/sir-dev.h
@@ -102,28 +102,29 @@ struct sir_driver {
/* exported */
-extern int irda_register_dongle(struct dongle_driver *new);
-extern int irda_unregister_dongle(struct dongle_driver *drv);
+int irda_register_dongle(struct dongle_driver *new);
+int irda_unregister_dongle(struct dongle_driver *drv);
-extern struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *name);
-extern int sirdev_put_instance(struct sir_dev *self);
+struct sir_dev *sirdev_get_instance(const struct sir_driver *drv,
+ const char *name);
+int sirdev_put_instance(struct sir_dev *self);
-extern int sirdev_set_dongle(struct sir_dev *dev, IRDA_DONGLE type);
-extern void sirdev_write_complete(struct sir_dev *dev);
-extern int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count);
+int sirdev_set_dongle(struct sir_dev *dev, IRDA_DONGLE type);
+void sirdev_write_complete(struct sir_dev *dev);
+int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count);
/* low level helpers for SIR device/dongle setup */
-extern int sirdev_raw_write(struct sir_dev *dev, const char *buf, int len);
-extern int sirdev_raw_read(struct sir_dev *dev, char *buf, int len);
-extern int sirdev_set_dtr_rts(struct sir_dev *dev, int dtr, int rts);
+int sirdev_raw_write(struct sir_dev *dev, const char *buf, int len);
+int sirdev_raw_read(struct sir_dev *dev, char *buf, int len);
+int sirdev_set_dtr_rts(struct sir_dev *dev, int dtr, int rts);
/* not exported */
-extern int sirdev_get_dongle(struct sir_dev *self, IRDA_DONGLE type);
-extern int sirdev_put_dongle(struct sir_dev *self);
+int sirdev_get_dongle(struct sir_dev *self, IRDA_DONGLE type);
+int sirdev_put_dongle(struct sir_dev *self);
-extern void sirdev_enable_rx(struct sir_dev *dev);
-extern int sirdev_schedule_request(struct sir_dev *dev, int state, unsigned param);
+void sirdev_enable_rx(struct sir_dev *dev);
+int sirdev_schedule_request(struct sir_dev *dev, int state, unsigned param);
/* inline helpers */
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index adeee615dd19..0e785499ce23 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -765,7 +765,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
static struct console netconsole = {
.name = "netcon",
- .flags = CON_ENABLED,
+ .flags = CON_ENABLED | CON_ALLDATA,
.write = write_msg,
};
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index c31aad0004cb..3ae28f420868 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -287,6 +287,8 @@ static struct phy_driver ksphy_driver[] = {
.read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = ks8737_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
.driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_KSZ8021,
@@ -300,6 +302,8 @@ static struct phy_driver ksphy_driver[] = {
.read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = kszphy_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
.driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_KSZ8031,
@@ -313,6 +317,8 @@ static struct phy_driver ksphy_driver[] = {
.read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = kszphy_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
.driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_KSZ8041,
@@ -326,6 +332,8 @@ static struct phy_driver ksphy_driver[] = {
.read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = kszphy_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
.driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_KSZ8051,
@@ -339,6 +347,8 @@ static struct phy_driver ksphy_driver[] = {
.read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = kszphy_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
.driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_KSZ8001,
@@ -351,6 +361,8 @@ static struct phy_driver ksphy_driver[] = {
.read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = kszphy_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
.driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_KSZ8081,
@@ -363,6 +375,8 @@ static struct phy_driver ksphy_driver[] = {
.read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = kszphy_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
.driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_KSZ8061,
@@ -375,6 +389,8 @@ static struct phy_driver ksphy_driver[] = {
.read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = kszphy_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
.driver = { .owner = THIS_MODULE,},
}, {
.phy_id = PHY_ID_KSZ9021,
@@ -387,6 +403,8 @@ static struct phy_driver ksphy_driver[] = {
.read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = ksz9021_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
.driver = { .owner = THIS_MODULE, },
}, {
.phy_id = PHY_ID_KSZ9031,
@@ -400,6 +418,8 @@ static struct phy_driver ksphy_driver[] = {
.read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = ksz9021_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
.driver = { .owner = THIS_MODULE, },
}, {
.phy_id = PHY_ID_KSZ8873MLL,
@@ -410,6 +430,8 @@ static struct phy_driver ksphy_driver[] = {
.config_init = kszphy_config_init,
.config_aneg = ksz8873mll_config_aneg,
.read_status = ksz8873mll_read_status,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
.driver = { .owner = THIS_MODULE, },
}, {
.phy_id = PHY_ID_KSZ886X,
@@ -420,6 +442,8 @@ static struct phy_driver ksphy_driver[] = {
.config_init = kszphy_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
.driver = { .owner = THIS_MODULE, },
} };
diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
index a34d6bf5e43b..cc70ecfc7062 100644
--- a/drivers/net/slip/slip.c
+++ b/drivers/net/slip/slip.c
@@ -429,11 +429,13 @@ static void slip_write_wakeup(struct tty_struct *tty)
if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev))
return;
+ spin_lock(&sl->lock);
if (sl->xleft <= 0) {
/* Now serial buffer is almost free & we can start
* transmission of another packet */
sl->dev->stats.tx_packets++;
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+ spin_unlock(&sl->lock);
sl_unlock(sl);
return;
}
@@ -441,6 +443,7 @@ static void slip_write_wakeup(struct tty_struct *tty)
actual = tty->ops->write(tty, sl->xhead, sl->xleft);
sl->xleft -= actual;
sl->xhead += actual;
+ spin_unlock(&sl->lock);
}
static void sl_tx_timeout(struct net_device *dev)
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
index 7d78669000d7..6358d420e185 100644
--- a/drivers/net/usb/cdc-phonet.c
+++ b/drivers/net/usb/cdc-phonet.c
@@ -328,7 +328,7 @@ MODULE_DEVICE_TABLE(usb, usbpn_ids);
static struct usb_driver usbpn_driver;
-int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
+static int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
static const char ifname[] = "usbpn%d";
const struct usb_cdc_union_desc *union_header = NULL;
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index a03f358fd58b..12040a35d95d 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -410,9 +410,9 @@ int
vmxnet3_create_queues(struct vmxnet3_adapter *adapter,
u32 tx_ring_size, u32 rx_ring_size, u32 rx_ring2_size);
-extern void vmxnet3_set_ethtool_ops(struct net_device *netdev);
+void vmxnet3_set_ethtool_ops(struct net_device *netdev);
-extern struct rtnl_link_stats64 *
+struct rtnl_link_stats64 *
vmxnet3_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats);
extern char vmxnet3_driver_name[];
diff --git a/drivers/net/wan/x25_asy.h b/drivers/net/wan/x25_asy.h
index 8f0fc2e57e2b..f57ee67836ae 100644
--- a/drivers/net/wan/x25_asy.h
+++ b/drivers/net/wan/x25_asy.h
@@ -41,6 +41,6 @@ struct x25_asy {
#define X25_ASY_MAGIC 0x5303
-extern int x25_asy_init(struct net_device *dev);
+int x25_asy_init(struct net_device *dev);
#endif /* _LINUX_X25_ASY.H */
diff --git a/drivers/net/wan/z85230.h b/drivers/net/wan/z85230.h
index f29d554fc07d..2416a9d60bd6 100644
--- a/drivers/net/wan/z85230.h
+++ b/drivers/net/wan/z85230.h
@@ -395,20 +395,19 @@ struct z8530_dev
extern u8 z8530_dead_port[];
extern u8 z8530_hdlc_kilostream_85230[];
extern u8 z8530_hdlc_kilostream[];
-extern irqreturn_t z8530_interrupt(int, void *);
-extern void z8530_describe(struct z8530_dev *, char *mapping, unsigned long io);
-extern int z8530_init(struct z8530_dev *);
-extern int z8530_shutdown(struct z8530_dev *);
-extern int z8530_sync_open(struct net_device *, struct z8530_channel *);
-extern int z8530_sync_close(struct net_device *, struct z8530_channel *);
-extern int z8530_sync_dma_open(struct net_device *, struct z8530_channel *);
-extern int z8530_sync_dma_close(struct net_device *, struct z8530_channel *);
-extern int z8530_sync_txdma_open(struct net_device *, struct z8530_channel *);
-extern int z8530_sync_txdma_close(struct net_device *, struct z8530_channel *);
-extern int z8530_channel_load(struct z8530_channel *, u8 *);
-extern netdev_tx_t z8530_queue_xmit(struct z8530_channel *c,
- struct sk_buff *skb);
-extern void z8530_null_rx(struct z8530_channel *c, struct sk_buff *skb);
+irqreturn_t z8530_interrupt(int, void *);
+void z8530_describe(struct z8530_dev *, char *mapping, unsigned long io);
+int z8530_init(struct z8530_dev *);
+int z8530_shutdown(struct z8530_dev *);
+int z8530_sync_open(struct net_device *, struct z8530_channel *);
+int z8530_sync_close(struct net_device *, struct z8530_channel *);
+int z8530_sync_dma_open(struct net_device *, struct z8530_channel *);
+int z8530_sync_dma_close(struct net_device *, struct z8530_channel *);
+int z8530_sync_txdma_open(struct net_device *, struct z8530_channel *);
+int z8530_sync_txdma_close(struct net_device *, struct z8530_channel *);
+int z8530_channel_load(struct z8530_channel *, u8 *);
+netdev_tx_t z8530_queue_xmit(struct z8530_channel *c, struct sk_buff *skb);
+void z8530_null_rx(struct z8530_channel *c, struct sk_buff *skb);
/*
diff --git a/drivers/net/wimax/i2400m/i2400m-usb.h b/drivers/net/wimax/i2400m/i2400m-usb.h
index 9f1e947f3557..649ecad6844c 100644
--- a/drivers/net/wimax/i2400m/i2400m-usb.h
+++ b/drivers/net/wimax/i2400m/i2400m-usb.h
@@ -256,21 +256,20 @@ void i2400mu_init(struct i2400mu *i2400mu)
i2400mu->rx_size_auto_shrink = 1;
}
-extern int i2400mu_notification_setup(struct i2400mu *);
-extern void i2400mu_notification_release(struct i2400mu *);
+int i2400mu_notification_setup(struct i2400mu *);
+void i2400mu_notification_release(struct i2400mu *);
-extern int i2400mu_rx_setup(struct i2400mu *);
-extern void i2400mu_rx_release(struct i2400mu *);
-extern void i2400mu_rx_kick(struct i2400mu *);
+int i2400mu_rx_setup(struct i2400mu *);
+void i2400mu_rx_release(struct i2400mu *);
+void i2400mu_rx_kick(struct i2400mu *);
-extern int i2400mu_tx_setup(struct i2400mu *);
-extern void i2400mu_tx_release(struct i2400mu *);
-extern void i2400mu_bus_tx_kick(struct i2400m *);
+int i2400mu_tx_setup(struct i2400mu *);
+void i2400mu_tx_release(struct i2400mu *);
+void i2400mu_bus_tx_kick(struct i2400m *);
-extern ssize_t i2400mu_bus_bm_cmd_send(struct i2400m *,
- const struct i2400m_bootrom_header *,
- size_t, int);
-extern ssize_t i2400mu_bus_bm_wait_for_ack(struct i2400m *,
- struct i2400m_bootrom_header *,
- size_t);
+ssize_t i2400mu_bus_bm_cmd_send(struct i2400m *,
+ const struct i2400m_bootrom_header *, size_t,
+ int);
+ssize_t i2400mu_bus_bm_wait_for_ack(struct i2400m *,
+ struct i2400m_bootrom_header *, size_t);
#endif /* #ifndef __I2400M_USB_H__ */
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h
index 79c6505b5c20..5a34e72bab9a 100644
--- a/drivers/net/wimax/i2400m/i2400m.h
+++ b/drivers/net/wimax/i2400m/i2400m.h
@@ -710,18 +710,18 @@ enum i2400m_bri {
I2400M_BRI_MAC_REINIT = 1 << 3,
};
-extern void i2400m_bm_cmd_prepare(struct i2400m_bootrom_header *);
-extern int i2400m_dev_bootstrap(struct i2400m *, enum i2400m_bri);
-extern int i2400m_read_mac_addr(struct i2400m *);
-extern int i2400m_bootrom_init(struct i2400m *, enum i2400m_bri);
-extern int i2400m_is_boot_barker(struct i2400m *, const void *, size_t);
+void i2400m_bm_cmd_prepare(struct i2400m_bootrom_header *);
+int i2400m_dev_bootstrap(struct i2400m *, enum i2400m_bri);
+int i2400m_read_mac_addr(struct i2400m *);
+int i2400m_bootrom_init(struct i2400m *, enum i2400m_bri);
+int i2400m_is_boot_barker(struct i2400m *, const void *, size_t);
static inline
int i2400m_is_d2h_barker(const void *buf)
{
const __le32 *barker = buf;
return le32_to_cpu(*barker) == I2400M_D2H_MSG_BARKER;
}
-extern void i2400m_unknown_barker(struct i2400m *, const void *, size_t);
+void i2400m_unknown_barker(struct i2400m *, const void *, size_t);
/* Make/grok boot-rom header commands */
@@ -789,32 +789,31 @@ unsigned i2400m_brh_get_signature(const struct i2400m_bootrom_header *hdr)
/*
* Driver / device setup and internal functions
*/
-extern void i2400m_init(struct i2400m *);
-extern int i2400m_reset(struct i2400m *, enum i2400m_reset_type);
-extern void i2400m_netdev_setup(struct net_device *net_dev);
-extern int i2400m_sysfs_setup(struct device_driver *);
-extern void i2400m_sysfs_release(struct device_driver *);
-extern int i2400m_tx_setup(struct i2400m *);
-extern void i2400m_wake_tx_work(struct work_struct *);
-extern void i2400m_tx_release(struct i2400m *);
-
-extern int i2400m_rx_setup(struct i2400m *);
-extern void i2400m_rx_release(struct i2400m *);
-
-extern void i2400m_fw_cache(struct i2400m *);
-extern void i2400m_fw_uncache(struct i2400m *);
-
-extern void i2400m_net_rx(struct i2400m *, struct sk_buff *, unsigned,
- const void *, int);
-extern void i2400m_net_erx(struct i2400m *, struct sk_buff *,
- enum i2400m_cs);
-extern void i2400m_net_wake_stop(struct i2400m *);
+void i2400m_init(struct i2400m *);
+int i2400m_reset(struct i2400m *, enum i2400m_reset_type);
+void i2400m_netdev_setup(struct net_device *net_dev);
+int i2400m_sysfs_setup(struct device_driver *);
+void i2400m_sysfs_release(struct device_driver *);
+int i2400m_tx_setup(struct i2400m *);
+void i2400m_wake_tx_work(struct work_struct *);
+void i2400m_tx_release(struct i2400m *);
+
+int i2400m_rx_setup(struct i2400m *);
+void i2400m_rx_release(struct i2400m *);
+
+void i2400m_fw_cache(struct i2400m *);
+void i2400m_fw_uncache(struct i2400m *);
+
+void i2400m_net_rx(struct i2400m *, struct sk_buff *, unsigned, const void *,
+ int);
+void i2400m_net_erx(struct i2400m *, struct sk_buff *, enum i2400m_cs);
+void i2400m_net_wake_stop(struct i2400m *);
enum i2400m_pt;
-extern int i2400m_tx(struct i2400m *, const void *, size_t, enum i2400m_pt);
+int i2400m_tx(struct i2400m *, const void *, size_t, enum i2400m_pt);
#ifdef CONFIG_DEBUG_FS
-extern int i2400m_debugfs_add(struct i2400m *);
-extern void i2400m_debugfs_rm(struct i2400m *);
+int i2400m_debugfs_add(struct i2400m *);
+void i2400m_debugfs_rm(struct i2400m *);
#else
static inline int i2400m_debugfs_add(struct i2400m *i2400m)
{
@@ -824,8 +823,8 @@ static inline void i2400m_debugfs_rm(struct i2400m *i2400m) {}
#endif
/* Initialize/shutdown the device */
-extern int i2400m_dev_initialize(struct i2400m *);
-extern void i2400m_dev_shutdown(struct i2400m *);
+int i2400m_dev_initialize(struct i2400m *);
+void i2400m_dev_shutdown(struct i2400m *);
extern struct attribute_group i2400m_dev_attr_group;
@@ -873,21 +872,21 @@ void i2400m_put(struct i2400m *i2400m)
dev_put(i2400m->wimax_dev.net_dev);
}
-extern int i2400m_dev_reset_handle(struct i2400m *, const char *);
-extern int i2400m_pre_reset(struct i2400m *);
-extern int i2400m_post_reset(struct i2400m *);
-extern void i2400m_error_recovery(struct i2400m *);
+int i2400m_dev_reset_handle(struct i2400m *, const char *);
+int i2400m_pre_reset(struct i2400m *);
+int i2400m_post_reset(struct i2400m *);
+void i2400m_error_recovery(struct i2400m *);
/*
* _setup()/_release() are called by the probe/disconnect functions of
* the bus-specific drivers.
*/
-extern int i2400m_setup(struct i2400m *, enum i2400m_bri bm_flags);
-extern void i2400m_release(struct i2400m *);
+int i2400m_setup(struct i2400m *, enum i2400m_bri bm_flags);
+void i2400m_release(struct i2400m *);
-extern int i2400m_rx(struct i2400m *, struct sk_buff *);
-extern struct i2400m_msg_hdr *i2400m_tx_msg_get(struct i2400m *, size_t *);
-extern void i2400m_tx_msg_sent(struct i2400m *);
+int i2400m_rx(struct i2400m *, struct sk_buff *);
+struct i2400m_msg_hdr *i2400m_tx_msg_get(struct i2400m *, size_t *);
+void i2400m_tx_msg_sent(struct i2400m *);
/*
@@ -900,20 +899,19 @@ struct device *i2400m_dev(struct i2400m *i2400m)
return i2400m->wimax_dev.net_dev->dev.parent;
}
-extern int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *,
- char *, size_t);
-extern int i2400m_msg_size_check(struct i2400m *,
- const struct i2400m_l3l4_hdr *, size_t);
-extern struct sk_buff *i2400m_msg_to_dev(struct i2400m *, const void *, size_t);
-extern void i2400m_msg_to_dev_cancel_wait(struct i2400m *, int);
-extern void i2400m_report_hook(struct i2400m *,
- const struct i2400m_l3l4_hdr *, size_t);
-extern void i2400m_report_hook_work(struct work_struct *);
-extern int i2400m_cmd_enter_powersave(struct i2400m *);
-extern int i2400m_cmd_exit_idle(struct i2400m *);
-extern struct sk_buff *i2400m_get_device_info(struct i2400m *);
-extern int i2400m_firmware_check(struct i2400m *);
-extern int i2400m_set_idle_timeout(struct i2400m *, unsigned);
+int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *, char *, size_t);
+int i2400m_msg_size_check(struct i2400m *, const struct i2400m_l3l4_hdr *,
+ size_t);
+struct sk_buff *i2400m_msg_to_dev(struct i2400m *, const void *, size_t);
+void i2400m_msg_to_dev_cancel_wait(struct i2400m *, int);
+void i2400m_report_hook(struct i2400m *, const struct i2400m_l3l4_hdr *,
+ size_t);
+void i2400m_report_hook_work(struct work_struct *);
+int i2400m_cmd_enter_powersave(struct i2400m *);
+int i2400m_cmd_exit_idle(struct i2400m *);
+struct sk_buff *i2400m_get_device_info(struct i2400m *);
+int i2400m_firmware_check(struct i2400m *);
+int i2400m_set_idle_timeout(struct i2400m *, unsigned);
static inline
struct usb_endpoint_descriptor *usb_get_epd(struct usb_interface *iface, int ep)
@@ -921,10 +919,9 @@ struct usb_endpoint_descriptor *usb_get_epd(struct usb_interface *iface, int ep)
return &iface->cur_altsetting->endpoint[ep].desc;
}
-extern int i2400m_op_rfkill_sw_toggle(struct wimax_dev *,
- enum wimax_rf_state);
-extern void i2400m_report_tlv_rf_switches_status(
- struct i2400m *, const struct i2400m_tlv_rf_switches_status *);
+int i2400m_op_rfkill_sw_toggle(struct wimax_dev *, enum wimax_rf_state);
+void i2400m_report_tlv_rf_switches_status(struct i2400m *,
+ const struct i2400m_tlv_rf_switches_status *);
/*
* Helpers for firmware backwards compatibility
@@ -968,8 +965,8 @@ void __i2400m_msleep(unsigned ms)
/* module initialization helpers */
-extern int i2400m_barker_db_init(const char *);
-extern void i2400m_barker_db_exit(void);
+int i2400m_barker_db_init(const char *);
+void i2400m_barker_db_exit(void);
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index f9a24e599dee..cfce83e1f273 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -1924,7 +1924,6 @@ static int adm8211_probe(struct pci_dev *pdev,
pci_iounmap(pdev, priv->map);
err_free_dev:
- pci_set_drvdata(pdev, NULL);
ieee80211_free_hw(dev);
err_free_reg:
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 7fe19648f10e..edf4b57c4aaa 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -5570,7 +5570,6 @@ static void airo_pci_remove(struct pci_dev *pdev)
airo_print_info(dev->name, "Unregistering...");
stop_airo_card(dev, 1);
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
}
static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c
index 17d7fece35d2..280fc3d53a36 100644
--- a/drivers/net/wireless/ath/ar5523/ar5523.c
+++ b/drivers/net/wireless/ath/ar5523/ar5523.c
@@ -1762,6 +1762,7 @@ static struct usb_device_id ar5523_id_table[] = {
AR5523_DEVICE_UX(0x2001, 0x3a00), /* Dlink / DWLAG132 */
AR5523_DEVICE_UG(0x2001, 0x3a02), /* Dlink / DWLG132 */
AR5523_DEVICE_UX(0x2001, 0x3a04), /* Dlink / DWLAG122 */
+ AR5523_DEVICE_UG(0x07d1, 0x3a07), /* D-Link / WUA-2340 rev A1 */
AR5523_DEVICE_UG(0x1690, 0x0712), /* Gigaset / AR5523 */
AR5523_DEVICE_UG(0x1690, 0x0710), /* Gigaset / SMCWUSBTG */
AR5523_DEVICE_UG(0x129b, 0x160c), /* Gigaset / USB stick 108
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index f8b969f518f8..afe5df404ce6 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -76,36 +76,7 @@ static inline void ath10k_ce_src_ring_write_index_set(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int n)
{
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- void __iomem *indicator_addr;
-
- if (!test_bit(ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND, ar_pci->features)) {
- ath10k_pci_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n);
- return;
- }
-
- /* workaround for QCA988x_1.0 HW CE */
- indicator_addr = ar_pci->mem + ce_ctrl_addr + DST_WATERMARK_ADDRESS;
-
- if (ce_ctrl_addr == ath10k_ce_base_address(CDC_WAR_DATA_CE)) {
- iowrite32((CDC_WAR_MAGIC_STR | n), indicator_addr);
- } else {
- unsigned long irq_flags;
- local_irq_save(irq_flags);
- iowrite32(1, indicator_addr);
-
- /*
- * PCIE write waits for ACK in IPQ8K, there is no
- * need to read back value.
- */
- (void)ioread32(indicator_addr);
- (void)ioread32(indicator_addr); /* conservative */
-
- ath10k_pci_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n);
-
- iowrite32(0, indicator_addr);
- local_irq_restore(irq_flags);
- }
+ ath10k_pci_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n);
}
static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar,
@@ -285,7 +256,7 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
* ath10k_ce_sendlist_send.
* The caller takes responsibility for any needed locking.
*/
-static int ath10k_ce_send_nolock(struct ce_state *ce_state,
+static int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
void *per_transfer_context,
u32 buffer,
unsigned int nbytes,
@@ -293,7 +264,7 @@ static int ath10k_ce_send_nolock(struct ce_state *ce_state,
unsigned int flags)
{
struct ath10k *ar = ce_state->ar;
- struct ce_ring_state *src_ring = ce_state->src_ring;
+ struct ath10k_ce_ring *src_ring = ce_state->src_ring;
struct ce_desc *desc, *sdesc;
unsigned int nentries_mask = src_ring->nentries_mask;
unsigned int sw_index = src_ring->sw_index;
@@ -306,7 +277,9 @@ static int ath10k_ce_send_nolock(struct ce_state *ce_state,
ath10k_warn("%s: send more we can (nbytes: %d, max: %d)\n",
__func__, nbytes, ce_state->src_sz_max);
- ath10k_pci_wake(ar);
+ ret = ath10k_pci_wake(ar);
+ if (ret)
+ return ret;
if (unlikely(CE_RING_DELTA(nentries_mask,
write_index, sw_index - 1) <= 0)) {
@@ -346,7 +319,7 @@ exit:
return ret;
}
-int ath10k_ce_send(struct ce_state *ce_state,
+int ath10k_ce_send(struct ath10k_ce_pipe *ce_state,
void *per_transfer_context,
u32 buffer,
unsigned int nbytes,
@@ -378,12 +351,12 @@ void ath10k_ce_sendlist_buf_add(struct ce_sendlist *sendlist, u32 buffer,
sendlist->num_items++;
}
-int ath10k_ce_sendlist_send(struct ce_state *ce_state,
+int ath10k_ce_sendlist_send(struct ath10k_ce_pipe *ce_state,
void *per_transfer_context,
struct ce_sendlist *sendlist,
unsigned int transfer_id)
{
- struct ce_ring_state *src_ring = ce_state->src_ring;
+ struct ath10k_ce_ring *src_ring = ce_state->src_ring;
struct ce_sendlist_item *item;
struct ath10k *ar = ce_state->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
@@ -431,11 +404,11 @@ int ath10k_ce_sendlist_send(struct ce_state *ce_state,
return ret;
}
-int ath10k_ce_recv_buf_enqueue(struct ce_state *ce_state,
+int ath10k_ce_recv_buf_enqueue(struct ath10k_ce_pipe *ce_state,
void *per_recv_context,
u32 buffer)
{
- struct ce_ring_state *dest_ring = ce_state->dest_ring;
+ struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
u32 ctrl_addr = ce_state->ctrl_addr;
struct ath10k *ar = ce_state->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
@@ -448,7 +421,9 @@ int ath10k_ce_recv_buf_enqueue(struct ce_state *ce_state,
write_index = dest_ring->write_index;
sw_index = dest_ring->sw_index;
- ath10k_pci_wake(ar);
+ ret = ath10k_pci_wake(ar);
+ if (ret)
+ goto out;
if (CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) > 0) {
struct ce_desc *base = dest_ring->base_addr_owner_space;
@@ -470,6 +445,8 @@ int ath10k_ce_recv_buf_enqueue(struct ce_state *ce_state,
ret = -EIO;
}
ath10k_pci_sleep(ar);
+
+out:
spin_unlock_bh(&ar_pci->ce_lock);
return ret;
@@ -479,14 +456,14 @@ int ath10k_ce_recv_buf_enqueue(struct ce_state *ce_state,
* Guts of ath10k_ce_completed_recv_next.
* The caller takes responsibility for any necessary locking.
*/
-static int ath10k_ce_completed_recv_next_nolock(struct ce_state *ce_state,
+static int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
void **per_transfer_contextp,
u32 *bufferp,
unsigned int *nbytesp,
unsigned int *transfer_idp,
unsigned int *flagsp)
{
- struct ce_ring_state *dest_ring = ce_state->dest_ring;
+ struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
unsigned int nentries_mask = dest_ring->nentries_mask;
unsigned int sw_index = dest_ring->sw_index;
@@ -535,7 +512,7 @@ static int ath10k_ce_completed_recv_next_nolock(struct ce_state *ce_state,
return 0;
}
-int ath10k_ce_completed_recv_next(struct ce_state *ce_state,
+int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
void **per_transfer_contextp,
u32 *bufferp,
unsigned int *nbytesp,
@@ -556,11 +533,11 @@ int ath10k_ce_completed_recv_next(struct ce_state *ce_state,
return ret;
}
-int ath10k_ce_revoke_recv_next(struct ce_state *ce_state,
+int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
void **per_transfer_contextp,
u32 *bufferp)
{
- struct ce_ring_state *dest_ring;
+ struct ath10k_ce_ring *dest_ring;
unsigned int nentries_mask;
unsigned int sw_index;
unsigned int write_index;
@@ -612,19 +589,20 @@ int ath10k_ce_revoke_recv_next(struct ce_state *ce_state,
* Guts of ath10k_ce_completed_send_next.
* The caller takes responsibility for any necessary locking.
*/
-static int ath10k_ce_completed_send_next_nolock(struct ce_state *ce_state,
+static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
void **per_transfer_contextp,
u32 *bufferp,
unsigned int *nbytesp,
unsigned int *transfer_idp)
{
- struct ce_ring_state *src_ring = ce_state->src_ring;
+ struct ath10k_ce_ring *src_ring = ce_state->src_ring;
u32 ctrl_addr = ce_state->ctrl_addr;
struct ath10k *ar = ce_state->ar;
unsigned int nentries_mask = src_ring->nentries_mask;
unsigned int sw_index = src_ring->sw_index;
+ struct ce_desc *sdesc, *sbase;
unsigned int read_index;
- int ret = -EIO;
+ int ret;
if (src_ring->hw_index == sw_index) {
/*
@@ -634,48 +612,54 @@ static int ath10k_ce_completed_send_next_nolock(struct ce_state *ce_state,
* the SW has really caught up to the HW, or if the cached
* value of the HW index has become stale.
*/
- ath10k_pci_wake(ar);
+
+ ret = ath10k_pci_wake(ar);
+ if (ret)
+ return ret;
+
src_ring->hw_index =
ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
src_ring->hw_index &= nentries_mask;
+
ath10k_pci_sleep(ar);
}
+
read_index = src_ring->hw_index;
- if ((read_index != sw_index) && (read_index != 0xffffffff)) {
- struct ce_desc *sbase = src_ring->shadow_base;
- struct ce_desc *sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index);
+ if ((read_index == sw_index) || (read_index == 0xffffffff))
+ return -EIO;
- /* Return data from completed source descriptor */
- *bufferp = __le32_to_cpu(sdesc->addr);
- *nbytesp = __le16_to_cpu(sdesc->nbytes);
- *transfer_idp = MS(__le16_to_cpu(sdesc->flags),
- CE_DESC_FLAGS_META_DATA);
+ sbase = src_ring->shadow_base;
+ sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index);
- if (per_transfer_contextp)
- *per_transfer_contextp =
- src_ring->per_transfer_context[sw_index];
+ /* Return data from completed source descriptor */
+ *bufferp = __le32_to_cpu(sdesc->addr);
+ *nbytesp = __le16_to_cpu(sdesc->nbytes);
+ *transfer_idp = MS(__le16_to_cpu(sdesc->flags),
+ CE_DESC_FLAGS_META_DATA);
- /* sanity */
- src_ring->per_transfer_context[sw_index] = NULL;
+ if (per_transfer_contextp)
+ *per_transfer_contextp =
+ src_ring->per_transfer_context[sw_index];
- /* Update sw_index */
- sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
- src_ring->sw_index = sw_index;
- ret = 0;
- }
+ /* sanity */
+ src_ring->per_transfer_context[sw_index] = NULL;
- return ret;
+ /* Update sw_index */
+ sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
+ src_ring->sw_index = sw_index;
+
+ return 0;
}
/* NB: Modeled after ath10k_ce_completed_send_next */
-int ath10k_ce_cancel_send_next(struct ce_state *ce_state,
+int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state,
void **per_transfer_contextp,
u32 *bufferp,
unsigned int *nbytesp,
unsigned int *transfer_idp)
{
- struct ce_ring_state *src_ring;
+ struct ath10k_ce_ring *src_ring;
unsigned int nentries_mask;
unsigned int sw_index;
unsigned int write_index;
@@ -727,7 +711,7 @@ int ath10k_ce_cancel_send_next(struct ce_state *ce_state,
return ret;
}
-int ath10k_ce_completed_send_next(struct ce_state *ce_state,
+int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
void **per_transfer_contextp,
u32 *bufferp,
unsigned int *nbytesp,
@@ -756,15 +740,19 @@ int ath10k_ce_completed_send_next(struct ce_state *ce_state,
void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct ce_state *ce_state = ar_pci->ce_id_to_state[ce_id];
+ struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
u32 ctrl_addr = ce_state->ctrl_addr;
void *transfer_context;
u32 buf;
unsigned int nbytes;
unsigned int id;
unsigned int flags;
+ int ret;
+
+ ret = ath10k_pci_wake(ar);
+ if (ret)
+ return;
- ath10k_pci_wake(ar);
spin_lock_bh(&ar_pci->ce_lock);
/* Clear the copy-complete interrupts that will be handled here. */
@@ -823,10 +811,13 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
void ath10k_ce_per_engine_service_any(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- int ce_id;
+ int ce_id, ret;
u32 intr_summary;
- ath10k_pci_wake(ar);
+ ret = ath10k_pci_wake(ar);
+ if (ret)
+ return;
+
intr_summary = CE_INTERRUPT_SUMMARY(ar);
for (ce_id = 0; intr_summary && (ce_id < ar_pci->ce_count); ce_id++) {
@@ -849,13 +840,16 @@ void ath10k_ce_per_engine_service_any(struct ath10k *ar)
*
* Called with ce_lock held.
*/
-static void ath10k_ce_per_engine_handler_adjust(struct ce_state *ce_state,
+static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state,
int disable_copy_compl_intr)
{
u32 ctrl_addr = ce_state->ctrl_addr;
struct ath10k *ar = ce_state->ar;
+ int ret;
- ath10k_pci_wake(ar);
+ ret = ath10k_pci_wake(ar);
+ if (ret)
+ return;
if ((!disable_copy_compl_intr) &&
(ce_state->send_cb || ce_state->recv_cb))
@@ -871,11 +865,14 @@ static void ath10k_ce_per_engine_handler_adjust(struct ce_state *ce_state,
void ath10k_ce_disable_interrupts(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- int ce_id;
+ int ce_id, ret;
+
+ ret = ath10k_pci_wake(ar);
+ if (ret)
+ return;
- ath10k_pci_wake(ar);
for (ce_id = 0; ce_id < ar_pci->ce_count; ce_id++) {
- struct ce_state *ce_state = ar_pci->ce_id_to_state[ce_id];
+ struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
u32 ctrl_addr = ce_state->ctrl_addr;
ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr);
@@ -883,12 +880,12 @@ void ath10k_ce_disable_interrupts(struct ath10k *ar)
ath10k_pci_sleep(ar);
}
-void ath10k_ce_send_cb_register(struct ce_state *ce_state,
- void (*send_cb) (struct ce_state *ce_state,
- void *transfer_context,
- u32 buffer,
- unsigned int nbytes,
- unsigned int transfer_id),
+void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state,
+ void (*send_cb)(struct ath10k_ce_pipe *ce_state,
+ void *transfer_context,
+ u32 buffer,
+ unsigned int nbytes,
+ unsigned int transfer_id),
int disable_interrupts)
{
struct ath10k *ar = ce_state->ar;
@@ -900,13 +897,13 @@ void ath10k_ce_send_cb_register(struct ce_state *ce_state,
spin_unlock_bh(&ar_pci->ce_lock);
}
-void ath10k_ce_recv_cb_register(struct ce_state *ce_state,
- void (*recv_cb) (struct ce_state *ce_state,
- void *transfer_context,
- u32 buffer,
- unsigned int nbytes,
- unsigned int transfer_id,
- unsigned int flags))
+void ath10k_ce_recv_cb_register(struct ath10k_ce_pipe *ce_state,
+ void (*recv_cb)(struct ath10k_ce_pipe *ce_state,
+ void *transfer_context,
+ u32 buffer,
+ unsigned int nbytes,
+ unsigned int transfer_id,
+ unsigned int flags))
{
struct ath10k *ar = ce_state->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
@@ -919,11 +916,11 @@ void ath10k_ce_recv_cb_register(struct ce_state *ce_state,
static int ath10k_ce_init_src_ring(struct ath10k *ar,
unsigned int ce_id,
- struct ce_state *ce_state,
+ struct ath10k_ce_pipe *ce_state,
const struct ce_attr *attr)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct ce_ring_state *src_ring;
+ struct ath10k_ce_ring *src_ring;
unsigned int nentries = attr->src_nentries;
unsigned int ce_nbytes;
u32 ctrl_addr = ath10k_ce_base_address(ce_id);
@@ -937,19 +934,18 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar,
return 0;
}
- ce_nbytes = sizeof(struct ce_ring_state) + (nentries * sizeof(void *));
+ ce_nbytes = sizeof(struct ath10k_ce_ring) + (nentries * sizeof(void *));
ptr = kzalloc(ce_nbytes, GFP_KERNEL);
if (ptr == NULL)
return -ENOMEM;
- ce_state->src_ring = (struct ce_ring_state *)ptr;
+ ce_state->src_ring = (struct ath10k_ce_ring *)ptr;
src_ring = ce_state->src_ring;
- ptr += sizeof(struct ce_ring_state);
+ ptr += sizeof(struct ath10k_ce_ring);
src_ring->nentries = nentries;
src_ring->nentries_mask = nentries - 1;
- ath10k_pci_wake(ar);
src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
src_ring->sw_index &= src_ring->nentries_mask;
src_ring->hw_index = src_ring->sw_index;
@@ -957,7 +953,6 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar,
src_ring->write_index =
ath10k_ce_src_ring_write_index_get(ar, ctrl_addr);
src_ring->write_index &= src_ring->nentries_mask;
- ath10k_pci_sleep(ar);
src_ring->per_transfer_context = (void **)ptr;
@@ -970,6 +965,12 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar,
(nentries * sizeof(struct ce_desc) +
CE_DESC_RING_ALIGN),
&base_addr);
+ if (!src_ring->base_addr_owner_space_unaligned) {
+ kfree(ce_state->src_ring);
+ ce_state->src_ring = NULL;
+ return -ENOMEM;
+ }
+
src_ring->base_addr_ce_space_unaligned = base_addr;
src_ring->base_addr_owner_space = PTR_ALIGN(
@@ -986,12 +987,21 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar,
src_ring->shadow_base_unaligned =
kmalloc((nentries * sizeof(struct ce_desc) +
CE_DESC_RING_ALIGN), GFP_KERNEL);
+ if (!src_ring->shadow_base_unaligned) {
+ pci_free_consistent(ar_pci->pdev,
+ (nentries * sizeof(struct ce_desc) +
+ CE_DESC_RING_ALIGN),
+ src_ring->base_addr_owner_space,
+ src_ring->base_addr_ce_space);
+ kfree(ce_state->src_ring);
+ ce_state->src_ring = NULL;
+ return -ENOMEM;
+ }
src_ring->shadow_base = PTR_ALIGN(
src_ring->shadow_base_unaligned,
CE_DESC_RING_ALIGN);
- ath10k_pci_wake(ar);
ath10k_ce_src_ring_base_addr_set(ar, ctrl_addr,
src_ring->base_addr_ce_space);
ath10k_ce_src_ring_size_set(ar, ctrl_addr, nentries);
@@ -999,18 +1009,17 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar,
ath10k_ce_src_ring_byte_swap_set(ar, ctrl_addr, 0);
ath10k_ce_src_ring_lowmark_set(ar, ctrl_addr, 0);
ath10k_ce_src_ring_highmark_set(ar, ctrl_addr, nentries);
- ath10k_pci_sleep(ar);
return 0;
}
static int ath10k_ce_init_dest_ring(struct ath10k *ar,
unsigned int ce_id,
- struct ce_state *ce_state,
+ struct ath10k_ce_pipe *ce_state,
const struct ce_attr *attr)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct ce_ring_state *dest_ring;
+ struct ath10k_ce_ring *dest_ring;
unsigned int nentries = attr->dest_nentries;
unsigned int ce_nbytes;
u32 ctrl_addr = ath10k_ce_base_address(ce_id);
@@ -1024,25 +1033,23 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar,
return 0;
}
- ce_nbytes = sizeof(struct ce_ring_state) + (nentries * sizeof(void *));
+ ce_nbytes = sizeof(struct ath10k_ce_ring) + (nentries * sizeof(void *));
ptr = kzalloc(ce_nbytes, GFP_KERNEL);
if (ptr == NULL)
return -ENOMEM;
- ce_state->dest_ring = (struct ce_ring_state *)ptr;
+ ce_state->dest_ring = (struct ath10k_ce_ring *)ptr;
dest_ring = ce_state->dest_ring;
- ptr += sizeof(struct ce_ring_state);
+ ptr += sizeof(struct ath10k_ce_ring);
dest_ring->nentries = nentries;
dest_ring->nentries_mask = nentries - 1;
- ath10k_pci_wake(ar);
dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr);
dest_ring->sw_index &= dest_ring->nentries_mask;
dest_ring->write_index =
ath10k_ce_dest_ring_write_index_get(ar, ctrl_addr);
dest_ring->write_index &= dest_ring->nentries_mask;
- ath10k_pci_sleep(ar);
dest_ring->per_transfer_context = (void **)ptr;
@@ -1055,6 +1062,12 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar,
(nentries * sizeof(struct ce_desc) +
CE_DESC_RING_ALIGN),
&base_addr);
+ if (!dest_ring->base_addr_owner_space_unaligned) {
+ kfree(ce_state->dest_ring);
+ ce_state->dest_ring = NULL;
+ return -ENOMEM;
+ }
+
dest_ring->base_addr_ce_space_unaligned = base_addr;
/*
@@ -1071,44 +1084,31 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar,
dest_ring->base_addr_ce_space_unaligned,
CE_DESC_RING_ALIGN);
- ath10k_pci_wake(ar);
ath10k_ce_dest_ring_base_addr_set(ar, ctrl_addr,
dest_ring->base_addr_ce_space);
ath10k_ce_dest_ring_size_set(ar, ctrl_addr, nentries);
ath10k_ce_dest_ring_byte_swap_set(ar, ctrl_addr, 0);
ath10k_ce_dest_ring_lowmark_set(ar, ctrl_addr, 0);
ath10k_ce_dest_ring_highmark_set(ar, ctrl_addr, nentries);
- ath10k_pci_sleep(ar);
return 0;
}
-static struct ce_state *ath10k_ce_init_state(struct ath10k *ar,
+static struct ath10k_ce_pipe *ath10k_ce_init_state(struct ath10k *ar,
unsigned int ce_id,
const struct ce_attr *attr)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct ce_state *ce_state = NULL;
+ struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
u32 ctrl_addr = ath10k_ce_base_address(ce_id);
spin_lock_bh(&ar_pci->ce_lock);
- if (!ar_pci->ce_id_to_state[ce_id]) {
- ce_state = kzalloc(sizeof(*ce_state), GFP_ATOMIC);
- if (ce_state == NULL) {
- spin_unlock_bh(&ar_pci->ce_lock);
- return NULL;
- }
-
- ar_pci->ce_id_to_state[ce_id] = ce_state;
- ce_state->ar = ar;
- ce_state->id = ce_id;
- ce_state->ctrl_addr = ctrl_addr;
- ce_state->state = CE_RUNNING;
- /* Save attribute flags */
- ce_state->attr_flags = attr->flags;
- ce_state->src_sz_max = attr->src_sz_max;
- }
+ ce_state->ar = ar;
+ ce_state->id = ce_id;
+ ce_state->ctrl_addr = ctrl_addr;
+ ce_state->attr_flags = attr->flags;
+ ce_state->src_sz_max = attr->src_sz_max;
spin_unlock_bh(&ar_pci->ce_lock);
@@ -1122,12 +1122,17 @@ static struct ce_state *ath10k_ce_init_state(struct ath10k *ar,
* initialization. It may be that only one side or the other is
* initialized by software/firmware.
*/
-struct ce_state *ath10k_ce_init(struct ath10k *ar,
+struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar,
unsigned int ce_id,
const struct ce_attr *attr)
{
- struct ce_state *ce_state;
+ struct ath10k_ce_pipe *ce_state;
u32 ctrl_addr = ath10k_ce_base_address(ce_id);
+ int ret;
+
+ ret = ath10k_pci_wake(ar);
+ if (ret)
+ return NULL;
ce_state = ath10k_ce_init_state(ar, ce_id, attr);
if (!ce_state) {
@@ -1136,40 +1141,38 @@ struct ce_state *ath10k_ce_init(struct ath10k *ar,
}
if (attr->src_nentries) {
- if (ath10k_ce_init_src_ring(ar, ce_id, ce_state, attr)) {
- ath10k_err("Failed to initialize CE src ring for ID: %d\n",
- ce_id);
+ ret = ath10k_ce_init_src_ring(ar, ce_id, ce_state, attr);
+ if (ret) {
+ ath10k_err("Failed to initialize CE src ring for ID: %d (%d)\n",
+ ce_id, ret);
ath10k_ce_deinit(ce_state);
return NULL;
}
}
if (attr->dest_nentries) {
- if (ath10k_ce_init_dest_ring(ar, ce_id, ce_state, attr)) {
- ath10k_err("Failed to initialize CE dest ring for ID: %d\n",
- ce_id);
+ ret = ath10k_ce_init_dest_ring(ar, ce_id, ce_state, attr);
+ if (ret) {
+ ath10k_err("Failed to initialize CE dest ring for ID: %d (%d)\n",
+ ce_id, ret);
ath10k_ce_deinit(ce_state);
return NULL;
}
}
/* Enable CE error interrupts */
- ath10k_pci_wake(ar);
ath10k_ce_error_intr_enable(ar, ctrl_addr);
+
ath10k_pci_sleep(ar);
return ce_state;
}
-void ath10k_ce_deinit(struct ce_state *ce_state)
+void ath10k_ce_deinit(struct ath10k_ce_pipe *ce_state)
{
- unsigned int ce_id = ce_state->id;
struct ath10k *ar = ce_state->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- ce_state->state = CE_UNUSED;
- ar_pci->ce_id_to_state[ce_id] = NULL;
-
if (ce_state->src_ring) {
kfree(ce_state->src_ring->shadow_base_unaligned);
pci_free_consistent(ar_pci->pdev,
@@ -1190,5 +1193,7 @@ void ath10k_ce_deinit(struct ce_state *ce_state)
ce_state->dest_ring->base_addr_ce_space);
kfree(ce_state->dest_ring);
}
- kfree(ce_state);
+
+ ce_state->src_ring = NULL;
+ ce_state->dest_ring = NULL;
}
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index c17f07c026f4..cfef7d0fc5c4 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -36,16 +36,9 @@
* how to use copy engines.
*/
-struct ce_state;
+struct ath10k_ce_pipe;
-/* Copy Engine operational state */
-enum ce_op_state {
- CE_UNUSED,
- CE_PAUSED,
- CE_RUNNING,
-};
-
#define CE_DESC_FLAGS_GATHER (1 << 0)
#define CE_DESC_FLAGS_BYTE_SWAP (1 << 1)
#define CE_DESC_FLAGS_META_DATA_MASK 0xFFFC
@@ -57,8 +50,7 @@ struct ce_desc {
__le16 flags; /* %CE_DESC_FLAGS_ */
};
-/* Copy Engine Ring internal state */
-struct ce_ring_state {
+struct ath10k_ce_ring {
/* Number of entries in this ring; must be power of 2 */
unsigned int nentries;
unsigned int nentries_mask;
@@ -116,22 +108,20 @@ struct ce_ring_state {
void **per_transfer_context;
};
-/* Copy Engine internal state */
-struct ce_state {
+struct ath10k_ce_pipe {
struct ath10k *ar;
unsigned int id;
unsigned int attr_flags;
u32 ctrl_addr;
- enum ce_op_state state;
- void (*send_cb) (struct ce_state *ce_state,
+ void (*send_cb) (struct ath10k_ce_pipe *ce_state,
void *per_transfer_send_context,
u32 buffer,
unsigned int nbytes,
unsigned int transfer_id);
- void (*recv_cb) (struct ce_state *ce_state,
+ void (*recv_cb) (struct ath10k_ce_pipe *ce_state,
void *per_transfer_recv_context,
u32 buffer,
unsigned int nbytes,
@@ -139,8 +129,8 @@ struct ce_state {
unsigned int flags);
unsigned int src_sz_max;
- struct ce_ring_state *src_ring;
- struct ce_ring_state *dest_ring;
+ struct ath10k_ce_ring *src_ring;
+ struct ath10k_ce_ring *dest_ring;
};
struct ce_sendlist_item {
@@ -182,7 +172,7 @@ struct ce_attr;
*
* Implementation note: pushes 1 buffer to Source ring
*/
-int ath10k_ce_send(struct ce_state *ce_state,
+int ath10k_ce_send(struct ath10k_ce_pipe *ce_state,
void *per_transfer_send_context,
u32 buffer,
unsigned int nbytes,
@@ -190,12 +180,12 @@ int ath10k_ce_send(struct ce_state *ce_state,
unsigned int transfer_id,
unsigned int flags);
-void ath10k_ce_send_cb_register(struct ce_state *ce_state,
- void (*send_cb) (struct ce_state *ce_state,
- void *transfer_context,
- u32 buffer,
- unsigned int nbytes,
- unsigned int transfer_id),
+void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state,
+ void (*send_cb)(struct ath10k_ce_pipe *ce_state,
+ void *transfer_context,
+ u32 buffer,
+ unsigned int nbytes,
+ unsigned int transfer_id),
int disable_interrupts);
/* Append a simple buffer (address/length) to a sendlist. */
@@ -215,7 +205,7 @@ void ath10k_ce_sendlist_buf_add(struct ce_sendlist *sendlist,
*
* Implemenation note: Pushes multiple buffers with Gather to Source ring.
*/
-int ath10k_ce_sendlist_send(struct ce_state *ce_state,
+int ath10k_ce_sendlist_send(struct ath10k_ce_pipe *ce_state,
void *per_transfer_send_context,
struct ce_sendlist *sendlist,
/* 14 bits */
@@ -233,17 +223,17 @@ int ath10k_ce_sendlist_send(struct ce_state *ce_state,
*
* Implemenation note: Pushes a buffer to Dest ring.
*/
-int ath10k_ce_recv_buf_enqueue(struct ce_state *ce_state,
+int ath10k_ce_recv_buf_enqueue(struct ath10k_ce_pipe *ce_state,
void *per_transfer_recv_context,
u32 buffer);
-void ath10k_ce_recv_cb_register(struct ce_state *ce_state,
- void (*recv_cb) (struct ce_state *ce_state,
- void *transfer_context,
- u32 buffer,
- unsigned int nbytes,
- unsigned int transfer_id,
- unsigned int flags));
+void ath10k_ce_recv_cb_register(struct ath10k_ce_pipe *ce_state,
+ void (*recv_cb)(struct ath10k_ce_pipe *ce_state,
+ void *transfer_context,
+ u32 buffer,
+ unsigned int nbytes,
+ unsigned int transfer_id,
+ unsigned int flags));
/* recv flags */
/* Data is byte-swapped */
@@ -253,7 +243,7 @@ void ath10k_ce_recv_cb_register(struct ce_state *ce_state,
* Supply data for the next completed unprocessed receive descriptor.
* Pops buffer from Dest ring.
*/
-int ath10k_ce_completed_recv_next(struct ce_state *ce_state,
+int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
void **per_transfer_contextp,
u32 *bufferp,
unsigned int *nbytesp,
@@ -263,7 +253,7 @@ int ath10k_ce_completed_recv_next(struct ce_state *ce_state,
* Supply data for the next completed unprocessed send descriptor.
* Pops 1 completed send buffer from Source ring.
*/
-int ath10k_ce_completed_send_next(struct ce_state *ce_state,
+int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
void **per_transfer_contextp,
u32 *bufferp,
unsigned int *nbytesp,
@@ -272,7 +262,7 @@ int ath10k_ce_completed_send_next(struct ce_state *ce_state,
/*==================CE Engine Initialization=======================*/
/* Initialize an instance of a CE */
-struct ce_state *ath10k_ce_init(struct ath10k *ar,
+struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar,
unsigned int ce_id,
const struct ce_attr *attr);
@@ -282,7 +272,7 @@ struct ce_state *ath10k_ce_init(struct ath10k *ar,
* receive buffers. Target DMA must be stopped before using
* this API.
*/
-int ath10k_ce_revoke_recv_next(struct ce_state *ce_state,
+int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
void **per_transfer_contextp,
u32 *bufferp);
@@ -291,13 +281,13 @@ int ath10k_ce_revoke_recv_next(struct ce_state *ce_state,
* pending sends. Target DMA must be stopped before using
* this API.
*/
-int ath10k_ce_cancel_send_next(struct ce_state *ce_state,
+int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state,
void **per_transfer_contextp,
u32 *bufferp,
unsigned int *nbytesp,
unsigned int *transfer_idp);
-void ath10k_ce_deinit(struct ce_state *ce_state);
+void ath10k_ce_deinit(struct ath10k_ce_pipe *ce_state);
/*==================CE Interrupt Handlers====================*/
void ath10k_ce_per_engine_service_any(struct ath10k *ar);
@@ -322,9 +312,6 @@ struct ce_attr {
/* CE_ATTR_* values */
unsigned int flags;
- /* currently not in use */
- unsigned int priority;
-
/* #entries in source ring - Must be a power of 2 */
unsigned int src_nentries;
@@ -336,9 +323,6 @@ struct ce_attr {
/* #entries in destination ring - Must be a power of 2 */
unsigned int dest_nentries;
-
- /* Future use */
- void *reserved;
};
/*
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 7226c23b9569..2dd39a82ae99 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -39,17 +39,6 @@ MODULE_PARM_DESC(p2p, "Enable ath10k P2P support");
static const struct ath10k_hw_params ath10k_hw_params_list[] = {
{
- .id = QCA988X_HW_1_0_VERSION,
- .name = "qca988x hw1.0",
- .patch_load_addr = QCA988X_HW_1_0_PATCH_LOAD_ADDR,
- .fw = {
- .dir = QCA988X_HW_1_0_FW_DIR,
- .fw = QCA988X_HW_1_0_FW_FILE,
- .otp = QCA988X_HW_1_0_OTP_FILE,
- .board = QCA988X_HW_1_0_BOARD_DATA_FILE,
- },
- },
- {
.id = QCA988X_HW_2_0_VERSION,
.name = "qca988x hw2.0",
.patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
@@ -717,10 +706,43 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
return 0;
}
-int ath10k_core_register(struct ath10k *ar)
+static int ath10k_core_check_chip_id(struct ath10k *ar)
+{
+ u32 hw_revision = MS(ar->chip_id, SOC_CHIP_ID_REV);
+
+ /* Check that we are not using hw1.0 (some of them have same pci id
+ * as hw2.0) before doing anything else as ath10k crashes horribly
+ * due to missing hw1.0 workarounds. */
+ switch (hw_revision) {
+ case QCA988X_HW_1_0_CHIP_ID_REV:
+ ath10k_err("ERROR: qca988x hw1.0 is not supported\n");
+ return -EOPNOTSUPP;
+
+ case QCA988X_HW_2_0_CHIP_ID_REV:
+ /* known hardware revision, continue normally */
+ return 0;
+
+ default:
+ ath10k_warn("Warning: hardware revision unknown (0x%x), expect problems\n",
+ ar->chip_id);
+ return 0;
+ }
+
+ return 0;
+}
+
+int ath10k_core_register(struct ath10k *ar, u32 chip_id)
{
int status;
+ ar->chip_id = chip_id;
+
+ status = ath10k_core_check_chip_id(ar);
+ if (status) {
+ ath10k_err("Unsupported chip id 0x%08x\n", ar->chip_id);
+ return status;
+ }
+
status = ath10k_core_probe_fw(ar);
if (status) {
ath10k_err("could not probe fw (%d)\n", status);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index e4bba563ed42..174c4b404223 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -270,12 +270,21 @@ enum ath10k_state {
ATH10K_STATE_WEDGED,
};
+enum ath10k_fw_features {
+ /* wmi_mgmt_rx_hdr contains extra RSSI information */
+ ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX = 0,
+
+ /* keep last */
+ ATH10K_FW_FEATURE_COUNT,
+};
+
struct ath10k {
struct ath_common ath_common;
struct ieee80211_hw *hw;
struct device *dev;
u8 mac_addr[ETH_ALEN];
+ u32 chip_id;
u32 target_version;
u8 fw_version_major;
u32 fw_version_minor;
@@ -288,6 +297,8 @@ struct ath10k {
u32 vht_cap_info;
u32 num_rf_chains;
+ DECLARE_BITMAP(fw_features, ATH10K_FW_FEATURE_COUNT);
+
struct targetdef *targetdef;
struct hostdef *hostdef;
@@ -393,7 +404,7 @@ void ath10k_core_destroy(struct ath10k *ar);
int ath10k_core_start(struct ath10k *ar);
void ath10k_core_stop(struct ath10k *ar);
-int ath10k_core_register(struct ath10k *ar);
+int ath10k_core_register(struct ath10k *ar, u32 chip_id);
void ath10k_core_unregister(struct ath10k *ar);
#endif /* _CORE_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 3d65594fa098..09f535a1c767 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -260,7 +260,6 @@ void ath10k_debug_read_target_stats(struct ath10k *ar,
}
spin_unlock_bh(&ar->data_lock);
- mutex_unlock(&ar->conf_mutex);
complete(&ar->debug.event_stats_compl);
}
@@ -499,6 +498,25 @@ static const struct file_operations fops_simulate_fw_crash = {
.llseek = default_llseek,
};
+static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath10k *ar = file->private_data;
+ unsigned int len;
+ char buf[50];
+
+ len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->chip_id);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_chip_id = {
+ .read = ath10k_read_chip_id,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
int ath10k_debug_create(struct ath10k *ar)
{
ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
@@ -518,6 +536,9 @@ int ath10k_debug_create(struct ath10k *ar)
debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_simulate_fw_crash);
+ debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
+ ar, &fops_chip_id);
+
return 0;
}
#endif /* CONFIG_ATH10K_DEBUGFS */
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index 168140c54028..bb0063320397 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -37,9 +37,9 @@ enum ath10k_debug_mask {
extern unsigned int ath10k_debug_mask;
-extern __printf(1, 2) int ath10k_info(const char *fmt, ...);
-extern __printf(1, 2) int ath10k_err(const char *fmt, ...);
-extern __printf(1, 2) int ath10k_warn(const char *fmt, ...);
+__printf(1, 2) int ath10k_info(const char *fmt, ...);
+__printf(1, 2) int ath10k_err(const char *fmt, ...);
+__printf(1, 2) int ath10k_warn(const char *fmt, ...);
#ifdef CONFIG_ATH10K_DEBUGFS
int ath10k_debug_create(struct ath10k *ar);
@@ -68,7 +68,7 @@ static inline void ath10k_debug_read_target_stats(struct ath10k *ar,
#endif /* CONFIG_ATH10K_DEBUGFS */
#ifdef CONFIG_ATH10K_DEBUG
-extern __printf(2, 3) void ath10k_dbg(enum ath10k_debug_mask mask,
+__printf(2, 3) void ath10k_dbg(enum ath10k_debug_mask mask,
const char *fmt, ...);
void ath10k_dbg_dump(enum ath10k_debug_mask mask,
const char *msg, const char *prefix,
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index ef3329ef52f3..7d445d3b849d 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -772,16 +772,16 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
flags |= SM(tx_alloc, ATH10K_HTC_CONN_FLAGS_RECV_ALLOC);
- req_msg = &msg->connect_service;
- req_msg->flags = __cpu_to_le16(flags);
- req_msg->service_id = __cpu_to_le16(conn_req->service_id);
-
/* Only enable credit flow control for WMI ctrl service */
if (conn_req->service_id != ATH10K_HTC_SVC_ID_WMI_CONTROL) {
flags |= ATH10K_HTC_CONN_FLAGS_DISABLE_CREDIT_FLOW_CTRL;
disable_credit_flow_ctrl = true;
}
+ req_msg = &msg->connect_service;
+ req_msg->flags = __cpu_to_le16(flags);
+ req_msg->service_id = __cpu_to_le16(conn_req->service_id);
+
INIT_COMPLETION(htc->ctl_resp);
status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb);
diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c
index 39342c5cfcb2..5f7eeebc5432 100644
--- a/drivers/net/wireless/ath/ath10k/htt.c
+++ b/drivers/net/wireless/ath/ath10k/htt.c
@@ -104,21 +104,16 @@ err_htc_attach:
static int ath10k_htt_verify_version(struct ath10k_htt *htt)
{
- ath10k_dbg(ATH10K_DBG_HTT,
- "htt target version %d.%d; host version %d.%d\n",
- htt->target_version_major,
- htt->target_version_minor,
- HTT_CURRENT_VERSION_MAJOR,
- HTT_CURRENT_VERSION_MINOR);
-
- if (htt->target_version_major != HTT_CURRENT_VERSION_MAJOR) {
- ath10k_err("htt major versions are incompatible!\n");
+ ath10k_info("htt target version %d.%d\n",
+ htt->target_version_major, htt->target_version_minor);
+
+ if (htt->target_version_major != 2 &&
+ htt->target_version_major != 3) {
+ ath10k_err("unsupported htt major version %d. supported versions are 2 and 3\n",
+ htt->target_version_major);
return -ENOTSUPP;
}
- if (htt->target_version_minor != HTT_CURRENT_VERSION_MINOR)
- ath10k_warn("htt minor version differ but still compatible\n");
-
return 0;
}
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 318be4629cde..26c78a907f97 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -23,9 +23,6 @@
#include "htc.h"
#include "rx_desc.h"
-#define HTT_CURRENT_VERSION_MAJOR 2
-#define HTT_CURRENT_VERSION_MINOR 1
-
enum htt_dbg_stats_type {
HTT_DBG_STATS_WAL_PDEV_TXRX = 1 << 0,
HTT_DBG_STATS_RX_REORDER = 1 << 1,
@@ -45,6 +42,9 @@ enum htt_h2t_msg_type { /* host-to-target */
HTT_H2T_MSG_TYPE_SYNC = 4,
HTT_H2T_MSG_TYPE_AGGR_CFG = 5,
HTT_H2T_MSG_TYPE_FRAG_DESC_BANK_CFG = 6,
+
+ /* This command is used for sending management frames in HTT < 3.0.
+ * HTT >= 3.0 uses TX_FRM for everything. */
HTT_H2T_MSG_TYPE_MGMT_TX = 7,
HTT_H2T_NUM_MSGS /* keep this last */
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index e784c40b904b..9bb0ae89fdba 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -610,8 +610,7 @@ static int ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
RX_MPDU_START_INFO0_ENCRYPT_TYPE);
/* FIXME: No idea what assumptions are safe here. Need logs */
- if ((fmt == RX_MSDU_DECAP_RAW && skb->next) ||
- (fmt == RX_MSDU_DECAP_8023_SNAP_LLC)) {
+ if ((fmt == RX_MSDU_DECAP_RAW && skb->next)) {
ath10k_htt_rx_free_msdu_chain(skb->next);
skb->next = NULL;
return -ENOTSUPP;
@@ -659,6 +658,15 @@ static int ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
decap_hdr += roundup(crypto_len, 4);
}
+ /* When fmt == RX_MSDU_DECAP_8023_SNAP_LLC:
+ *
+ * SNAP 802.3 consists of:
+ * [dst:6][src:6][len:2][dsap:1][ssap:1][ctl:1][snap:5]
+ * [data][fcs:4].
+ *
+ * Since this overlaps with A-MSDU header (da, sa, len)
+ * there's nothing extra to do. */
+
if (fmt == RX_MSDU_DECAP_ETHERNET2_DIX) {
/* Ethernet2 decap inserts ethernet header in place of
* A-MSDU subframe header. */
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 656c2546b294..d4fb3875c918 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -401,10 +401,16 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
goto err;
}
- txfrag = dev_alloc_skb(frag_len);
- if (!txfrag) {
- res = -ENOMEM;
- goto err;
+ /* Since HTT 3.0 there is no separate mgmt tx command. However in case
+ * of mgmt tx using TX_FRM there is not tx fragment list. Instead of tx
+ * fragment list host driver specifies directly frame pointer. */
+ if (htt->target_version_major < 3 ||
+ !ieee80211_is_mgmt(hdr->frame_control)) {
+ txfrag = dev_alloc_skb(frag_len);
+ if (!txfrag) {
+ res = -ENOMEM;
+ goto err;
+ }
}
if (!IS_ALIGNED((unsigned long)txdesc->data, 4)) {
@@ -427,23 +433,31 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
if (res)
goto err;
- /* tx fragment list must be terminated with zero-entry */
- skb_put(txfrag, frag_len);
- tx_frags = (struct htt_data_tx_desc_frag *)txfrag->data;
- tx_frags[0].paddr = __cpu_to_le32(ATH10K_SKB_CB(msdu)->paddr);
- tx_frags[0].len = __cpu_to_le32(msdu->len);
- tx_frags[1].paddr = __cpu_to_le32(0);
- tx_frags[1].len = __cpu_to_le32(0);
-
- res = ath10k_skb_map(dev, txfrag);
- if (res)
- goto err;
+ /* Since HTT 3.0 there is no separate mgmt tx command. However in case
+ * of mgmt tx using TX_FRM there is not tx fragment list. Instead of tx
+ * fragment list host driver specifies directly frame pointer. */
+ if (htt->target_version_major < 3 ||
+ !ieee80211_is_mgmt(hdr->frame_control)) {
+ /* tx fragment list must be terminated with zero-entry */
+ skb_put(txfrag, frag_len);
+ tx_frags = (struct htt_data_tx_desc_frag *)txfrag->data;
+ tx_frags[0].paddr = __cpu_to_le32(ATH10K_SKB_CB(msdu)->paddr);
+ tx_frags[0].len = __cpu_to_le32(msdu->len);
+ tx_frags[1].paddr = __cpu_to_le32(0);
+ tx_frags[1].len = __cpu_to_le32(0);
+
+ res = ath10k_skb_map(dev, txfrag);
+ if (res)
+ goto err;
+
+ ath10k_dbg(ATH10K_DBG_HTT, "txfrag 0x%llx\n",
+ (unsigned long long) ATH10K_SKB_CB(txfrag)->paddr);
+ ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "txfrag: ",
+ txfrag->data, frag_len);
+ }
- ath10k_dbg(ATH10K_DBG_HTT, "txfrag 0x%llx msdu 0x%llx\n",
- (unsigned long long) ATH10K_SKB_CB(txfrag)->paddr,
+ ath10k_dbg(ATH10K_DBG_HTT, "msdu 0x%llx\n",
(unsigned long long) ATH10K_SKB_CB(msdu)->paddr);
- ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "txfrag: ",
- txfrag->data, frag_len);
ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "msdu: ",
msdu->data, msdu->len);
@@ -459,8 +473,17 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
if (!ieee80211_has_protected(hdr->frame_control))
flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
- flags0 |= SM(ATH10K_HW_TXRX_NATIVE_WIFI,
- HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
+
+ /* Since HTT 3.0 there is no separate mgmt tx command. However in case
+ * of mgmt tx using TX_FRM there is not tx fragment list. Instead of tx
+ * fragment list host driver specifies directly frame pointer. */
+ if (htt->target_version_major >= 3 &&
+ ieee80211_is_mgmt(hdr->frame_control))
+ flags0 |= SM(ATH10K_HW_TXRX_MGMT,
+ HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
+ else
+ flags0 |= SM(ATH10K_HW_TXRX_NATIVE_WIFI,
+ HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
flags1 = 0;
flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID);
@@ -468,7 +491,14 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD;
flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD;
- frags_paddr = ATH10K_SKB_CB(txfrag)->paddr;
+ /* Since HTT 3.0 there is no separate mgmt tx command. However in case
+ * of mgmt tx using TX_FRM there is not tx fragment list. Instead of tx
+ * fragment list host driver specifies directly frame pointer. */
+ if (htt->target_version_major >= 3 &&
+ ieee80211_is_mgmt(hdr->frame_control))
+ frags_paddr = ATH10K_SKB_CB(msdu)->paddr;
+ else
+ frags_paddr = ATH10K_SKB_CB(txfrag)->paddr;
cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM;
cmd->data_tx.flags0 = flags0;
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 44ed5af0a204..643f0c9f052b 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -24,18 +24,14 @@
#define SUPPORTED_FW_MAJOR 1
#define SUPPORTED_FW_MINOR 0
#define SUPPORTED_FW_RELEASE 0
-#define SUPPORTED_FW_BUILD 629
+#define SUPPORTED_FW_BUILD 636
-/* QCA988X 1.0 definitions */
-#define QCA988X_HW_1_0_VERSION 0x4000002c
-#define QCA988X_HW_1_0_FW_DIR "ath10k/QCA988X/hw1.0"
-#define QCA988X_HW_1_0_FW_FILE "firmware.bin"
-#define QCA988X_HW_1_0_OTP_FILE "otp.bin"
-#define QCA988X_HW_1_0_BOARD_DATA_FILE "board.bin"
-#define QCA988X_HW_1_0_PATCH_LOAD_ADDR 0x1234
+/* QCA988X 1.0 definitions (unsupported) */
+#define QCA988X_HW_1_0_CHIP_ID_REV 0x0
/* QCA988X 2.0 definitions */
#define QCA988X_HW_2_0_VERSION 0x4100016c
+#define QCA988X_HW_2_0_CHIP_ID_REV 0x2
#define QCA988X_HW_2_0_FW_DIR "ath10k/QCA988X/hw2.0"
#define QCA988X_HW_2_0_FW_FILE "firmware.bin"
#define QCA988X_HW_2_0_OTP_FILE "otp.bin"
@@ -53,6 +49,9 @@ enum ath10k_hw_txrx_mode {
ATH10K_HW_TXRX_RAW = 0,
ATH10K_HW_TXRX_NATIVE_WIFI = 1,
ATH10K_HW_TXRX_ETHERNET = 2,
+
+ /* Valid for HTT >= 3.0. Used for management frames in TX_FRM. */
+ ATH10K_HW_TXRX_MGMT = 3,
};
enum ath10k_mcast2ucast_mode {
@@ -169,6 +168,10 @@ enum ath10k_mcast2ucast_mode {
#define SOC_LPO_CAL_ENABLE_LSB 20
#define SOC_LPO_CAL_ENABLE_MASK 0x00100000
+#define SOC_CHIP_ID_ADDRESS 0x000000ec
+#define SOC_CHIP_ID_REV_LSB 8
+#define SOC_CHIP_ID_REV_MASK 0x00000f00
+
#define WLAN_RESET_CONTROL_COLD_RST_MASK 0x00000008
#define WLAN_RESET_CONTROL_WARM_RST_MASK 0x00000004
#define WLAN_SYSTEM_SLEEP_DISABLE_LSB 0
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index cf2ba4d850c9..248248b5c196 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -503,13 +503,10 @@ static int ath10k_monitor_start(struct ath10k *ar, int vdev_id)
{
struct ieee80211_channel *channel = ar->hw->conf.chandef.chan;
struct wmi_vdev_start_request_arg arg = {};
- enum nl80211_channel_type type;
int ret = 0;
lockdep_assert_held(&ar->conf_mutex);
- type = cfg80211_get_chandef_type(&ar->hw->conf.chandef);
-
arg.vdev_id = vdev_id;
arg.channel.freq = channel->center_freq;
arg.channel.band_center_freq1 = ar->hw->conf.chandef.center_freq1;
@@ -973,7 +970,7 @@ static void ath10k_peer_assoc_h_qos_ap(struct ath10k *ar,
sta->uapsd_queues, sta->max_sp);
arg->peer_flags |= WMI_PEER_APSD;
- arg->peer_flags |= WMI_RC_UAPSD_FLAG;
+ arg->peer_rate_caps |= WMI_RC_UAPSD_FLAG;
if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
uapsd |= WMI_AP_PS_UAPSD_AC3_DELIVERY_EN |
@@ -1421,10 +1418,6 @@ static void ath10k_tx_h_update_wep_key(struct sk_buff *skb)
struct ieee80211_key_conf *key = info->control.hw_key;
int ret;
- /* TODO AP mode should be implemented */
- if (vif->type != NL80211_IFTYPE_STATION)
- return;
-
if (!ieee80211_has_protected(hdr->frame_control))
return;
@@ -1480,6 +1473,12 @@ static void ath10k_tx_htt(struct ath10k *ar, struct sk_buff *skb)
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
int ret;
+ if (ar->htt.target_version_major >= 3) {
+ /* Since HTT 3.0 there is no separate mgmt tx command */
+ ret = ath10k_htt_tx(&ar->htt, skb);
+ goto exit;
+ }
+
if (ieee80211_is_mgmt(hdr->frame_control))
ret = ath10k_htt_mgmt_tx(&ar->htt, skb);
else if (ieee80211_is_nullfunc(hdr->frame_control))
@@ -1491,6 +1490,7 @@ static void ath10k_tx_htt(struct ath10k *ar, struct sk_buff *skb)
else
ret = ath10k_htt_tx(&ar->htt, skb);
+exit:
if (ret) {
ath10k_warn("tx failed (%d). dropping packet.\n", ret);
ieee80211_free_txskb(ar->hw, skb);
@@ -1727,8 +1727,10 @@ static void ath10k_tx(struct ieee80211_hw *hw,
/* we must calculate tid before we apply qos workaround
* as we'd lose the qos control field */
tid = HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
- if (ieee80211_is_data_qos(hdr->frame_control) &&
- is_unicast_ether_addr(ieee80211_get_DA(hdr))) {
+ if (ieee80211_is_mgmt(hdr->frame_control)) {
+ tid = HTT_DATA_TX_EXT_TID_MGMT;
+ } else if (ieee80211_is_data_qos(hdr->frame_control) &&
+ is_unicast_ether_addr(ieee80211_get_DA(hdr))) {
u8 *qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
}
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index e2f9ef50b1bd..56501f47ab9c 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -36,11 +36,9 @@ static unsigned int ath10k_target_ps;
module_param(ath10k_target_ps, uint, 0644);
MODULE_PARM_DESC(ath10k_target_ps, "Enable ath10k Target (SoC) PS option");
-#define QCA988X_1_0_DEVICE_ID (0xabcd)
#define QCA988X_2_0_DEVICE_ID (0x003c)
static DEFINE_PCI_DEVICE_TABLE(ath10k_pci_id_table) = {
- { PCI_VDEVICE(ATHEROS, QCA988X_1_0_DEVICE_ID) }, /* PCI-E QCA988X V1 */
{ PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */
{0}
};
@@ -50,9 +48,9 @@ static int ath10k_pci_diag_read_access(struct ath10k *ar, u32 address,
static void ath10k_pci_process_ce(struct ath10k *ar);
static int ath10k_pci_post_rx(struct ath10k *ar);
-static int ath10k_pci_post_rx_pipe(struct hif_ce_pipe_info *pipe_info,
+static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info,
int num);
-static void ath10k_pci_rx_pipe_cleanup(struct hif_ce_pipe_info *pipe_info);
+static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info);
static void ath10k_pci_stop_ce(struct ath10k *ar);
static void ath10k_pci_device_reset(struct ath10k *ar);
static int ath10k_pci_reset_target(struct ath10k *ar);
@@ -60,43 +58,145 @@ static int ath10k_pci_start_intr(struct ath10k *ar);
static void ath10k_pci_stop_intr(struct ath10k *ar);
static const struct ce_attr host_ce_config_wlan[] = {
- /* host->target HTC control and raw streams */
- { /* CE0 */ CE_ATTR_FLAGS, 0, 16, 256, 0, NULL,},
- /* could be moved to share CE3 */
- /* target->host HTT + HTC control */
- { /* CE1 */ CE_ATTR_FLAGS, 0, 0, 512, 512, NULL,},
- /* target->host WMI */
- { /* CE2 */ CE_ATTR_FLAGS, 0, 0, 2048, 32, NULL,},
- /* host->target WMI */
- { /* CE3 */ CE_ATTR_FLAGS, 0, 32, 2048, 0, NULL,},
- /* host->target HTT */
- { /* CE4 */ CE_ATTR_FLAGS | CE_ATTR_DIS_INTR, 0,
- CE_HTT_H2T_MSG_SRC_NENTRIES, 256, 0, NULL,},
- /* unused */
- { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,},
- /* Target autonomous hif_memcpy */
- { /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL,},
- /* ce_diag, the Diagnostic Window */
- { /* CE7 */ CE_ATTR_FLAGS, 0, 2, DIAG_TRANSFER_LIMIT, 2, NULL,},
+ /* CE0: host->target HTC control and raw streams */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 16,
+ .src_sz_max = 256,
+ .dest_nentries = 0,
+ },
+
+ /* CE1: target->host HTT + HTC control */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 512,
+ .dest_nentries = 512,
+ },
+
+ /* CE2: target->host WMI */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+ .dest_nentries = 32,
+ },
+
+ /* CE3: host->target WMI */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 32,
+ .src_sz_max = 2048,
+ .dest_nentries = 0,
+ },
+
+ /* CE4: host->target HTT */
+ {
+ .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+ .src_nentries = CE_HTT_H2T_MSG_SRC_NENTRIES,
+ .src_sz_max = 256,
+ .dest_nentries = 0,
+ },
+
+ /* CE5: unused */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+
+ /* CE6: target autonomous hif_memcpy */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 0,
+ .dest_nentries = 0,
+ },
+
+ /* CE7: ce_diag, the Diagnostic Window */
+ {
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 2,
+ .src_sz_max = DIAG_TRANSFER_LIMIT,
+ .dest_nentries = 2,
+ },
};
/* Target firmware's Copy Engine configuration. */
static const struct ce_pipe_config target_ce_config_wlan[] = {
- /* host->target HTC control and raw streams */
- { /* CE0 */ 0, PIPEDIR_OUT, 32, 256, CE_ATTR_FLAGS, 0,},
- /* target->host HTT + HTC control */
- { /* CE1 */ 1, PIPEDIR_IN, 32, 512, CE_ATTR_FLAGS, 0,},
- /* target->host WMI */
- { /* CE2 */ 2, PIPEDIR_IN, 32, 2048, CE_ATTR_FLAGS, 0,},
- /* host->target WMI */
- { /* CE3 */ 3, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,},
- /* host->target HTT */
- { /* CE4 */ 4, PIPEDIR_OUT, 256, 256, CE_ATTR_FLAGS, 0,},
+ /* CE0: host->target HTC control and raw streams */
+ {
+ .pipenum = 0,
+ .pipedir = PIPEDIR_OUT,
+ .nentries = 32,
+ .nbytes_max = 256,
+ .flags = CE_ATTR_FLAGS,
+ .reserved = 0,
+ },
+
+ /* CE1: target->host HTT + HTC control */
+ {
+ .pipenum = 1,
+ .pipedir = PIPEDIR_IN,
+ .nentries = 32,
+ .nbytes_max = 512,
+ .flags = CE_ATTR_FLAGS,
+ .reserved = 0,
+ },
+
+ /* CE2: target->host WMI */
+ {
+ .pipenum = 2,
+ .pipedir = PIPEDIR_IN,
+ .nentries = 32,
+ .nbytes_max = 2048,
+ .flags = CE_ATTR_FLAGS,
+ .reserved = 0,
+ },
+
+ /* CE3: host->target WMI */
+ {
+ .pipenum = 3,
+ .pipedir = PIPEDIR_OUT,
+ .nentries = 32,
+ .nbytes_max = 2048,
+ .flags = CE_ATTR_FLAGS,
+ .reserved = 0,
+ },
+
+ /* CE4: host->target HTT */
+ {
+ .pipenum = 4,
+ .pipedir = PIPEDIR_OUT,
+ .nentries = 256,
+ .nbytes_max = 256,
+ .flags = CE_ATTR_FLAGS,
+ .reserved = 0,
+ },
+
/* NB: 50% of src nentries, since tx has 2 frags */
- /* unused */
- { /* CE5 */ 5, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0,},
- /* Reserved for target autonomous hif_memcpy */
- { /* CE6 */ 6, PIPEDIR_INOUT, 32, 4096, CE_ATTR_FLAGS, 0,},
+
+ /* CE5: unused */
+ {
+ .pipenum = 5,
+ .pipedir = PIPEDIR_OUT,
+ .nentries = 32,
+ .nbytes_max = 2048,
+ .flags = CE_ATTR_FLAGS,
+ .reserved = 0,
+ },
+
+ /* CE6: Reserved for target autonomous hif_memcpy */
+ {
+ .pipenum = 6,
+ .pipedir = PIPEDIR_INOUT,
+ .nentries = 32,
+ .nbytes_max = 4096,
+ .flags = CE_ATTR_FLAGS,
+ .reserved = 0,
+ },
+
/* CE7 used only by Host */
};
@@ -114,7 +214,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
unsigned int completed_nbytes, orig_nbytes, remaining_bytes;
unsigned int id;
unsigned int flags;
- struct ce_state *ce_diag;
+ struct ath10k_ce_pipe *ce_diag;
/* Host buffer address in CE space */
u32 ce_data;
dma_addr_t ce_data_base = 0;
@@ -278,7 +378,7 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
unsigned int completed_nbytes, orig_nbytes, remaining_bytes;
unsigned int id;
unsigned int flags;
- struct ce_state *ce_diag;
+ struct ath10k_ce_pipe *ce_diag;
void *data_buf = NULL;
u32 ce_data; /* Host buffer address in CE space */
dma_addr_t ce_data_base = 0;
@@ -437,7 +537,7 @@ static void ath10k_pci_wait(struct ath10k *ar)
ath10k_warn("Unable to wakeup target\n");
}
-void ath10k_do_pci_wake(struct ath10k *ar)
+int ath10k_do_pci_wake(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
void __iomem *pci_addr = ar_pci->mem;
@@ -453,18 +553,19 @@ void ath10k_do_pci_wake(struct ath10k *ar)
atomic_inc(&ar_pci->keep_awake_count);
if (ar_pci->verified_awake)
- return;
+ return 0;
for (;;) {
if (ath10k_pci_target_is_awake(ar)) {
ar_pci->verified_awake = true;
- break;
+ return 0;
}
if (tot_delay > PCIE_WAKE_TIMEOUT) {
- ath10k_warn("target takes too long to wake up (awake count %d)\n",
+ ath10k_warn("target took longer %d us to wake up (awake count %d)\n",
+ PCIE_WAKE_TIMEOUT,
atomic_read(&ar_pci->keep_awake_count));
- break;
+ return -ETIMEDOUT;
}
udelay(curr_delay);
@@ -493,7 +594,7 @@ void ath10k_do_pci_sleep(struct ath10k *ar)
* FIXME: Handle OOM properly.
*/
static inline
-struct ath10k_pci_compl *get_free_compl(struct hif_ce_pipe_info *pipe_info)
+struct ath10k_pci_compl *get_free_compl(struct ath10k_pci_pipe *pipe_info)
{
struct ath10k_pci_compl *compl = NULL;
@@ -511,7 +612,7 @@ exit:
}
/* Called by lower (CE) layer when a send to Target completes. */
-static void ath10k_pci_ce_send_done(struct ce_state *ce_state,
+static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state,
void *transfer_context,
u32 ce_data,
unsigned int nbytes,
@@ -519,7 +620,7 @@ static void ath10k_pci_ce_send_done(struct ce_state *ce_state,
{
struct ath10k *ar = ce_state->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct hif_ce_pipe_info *pipe_info = &ar_pci->pipe_info[ce_state->id];
+ struct ath10k_pci_pipe *pipe_info = &ar_pci->pipe_info[ce_state->id];
struct ath10k_pci_compl *compl;
bool process = false;
@@ -540,10 +641,10 @@ static void ath10k_pci_ce_send_done(struct ce_state *ce_state,
if (!compl)
break;
- compl->send_or_recv = HIF_CE_COMPLETE_SEND;
+ compl->state = ATH10K_PCI_COMPL_SEND;
compl->ce_state = ce_state;
compl->pipe_info = pipe_info;
- compl->transfer_context = transfer_context;
+ compl->skb = transfer_context;
compl->nbytes = nbytes;
compl->transfer_id = transfer_id;
compl->flags = 0;
@@ -573,7 +674,7 @@ static void ath10k_pci_ce_send_done(struct ce_state *ce_state,
}
/* Called by lower (CE) layer when data is received from the Target. */
-static void ath10k_pci_ce_recv_data(struct ce_state *ce_state,
+static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state,
void *transfer_context, u32 ce_data,
unsigned int nbytes,
unsigned int transfer_id,
@@ -581,7 +682,7 @@ static void ath10k_pci_ce_recv_data(struct ce_state *ce_state,
{
struct ath10k *ar = ce_state->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct hif_ce_pipe_info *pipe_info = &ar_pci->pipe_info[ce_state->id];
+ struct ath10k_pci_pipe *pipe_info = &ar_pci->pipe_info[ce_state->id];
struct ath10k_pci_compl *compl;
struct sk_buff *skb;
@@ -590,10 +691,10 @@ static void ath10k_pci_ce_recv_data(struct ce_state *ce_state,
if (!compl)
break;
- compl->send_or_recv = HIF_CE_COMPLETE_RECV;
+ compl->state = ATH10K_PCI_COMPL_RECV;
compl->ce_state = ce_state;
compl->pipe_info = pipe_info;
- compl->transfer_context = transfer_context;
+ compl->skb = transfer_context;
compl->nbytes = nbytes;
compl->transfer_id = transfer_id;
compl->flags = flags;
@@ -625,8 +726,8 @@ static int ath10k_pci_hif_send_head(struct ath10k *ar, u8 pipe_id,
{
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(nbuf);
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct hif_ce_pipe_info *pipe_info = &(ar_pci->pipe_info[pipe_id]);
- struct ce_state *ce_hdl = pipe_info->ce_hdl;
+ struct ath10k_pci_pipe *pipe_info = &(ar_pci->pipe_info[pipe_id]);
+ struct ath10k_ce_pipe *ce_hdl = pipe_info->ce_hdl;
struct ce_sendlist sendlist;
unsigned int len;
u32 flags = 0;
@@ -670,7 +771,7 @@ static int ath10k_pci_hif_send_head(struct ath10k *ar, u8 pipe_id,
static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct hif_ce_pipe_info *pipe_info = &(ar_pci->pipe_info[pipe]);
+ struct ath10k_pci_pipe *pipe_info = &(ar_pci->pipe_info[pipe]);
int ret;
spin_lock_bh(&pipe_info->pipe_lock);
@@ -764,9 +865,9 @@ static void ath10k_pci_hif_set_callbacks(struct ath10k *ar,
static int ath10k_pci_start_ce(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct ce_state *ce_diag = ar_pci->ce_diag;
+ struct ath10k_ce_pipe *ce_diag = ar_pci->ce_diag;
const struct ce_attr *attr;
- struct hif_ce_pipe_info *pipe_info;
+ struct ath10k_pci_pipe *pipe_info;
struct ath10k_pci_compl *compl;
int i, pipe_num, completions, disable_interrupts;
@@ -805,15 +906,14 @@ static int ath10k_pci_start_ce(struct ath10k *ar)
continue;
for (i = 0; i < completions; i++) {
- compl = kmalloc(sizeof(struct ath10k_pci_compl),
- GFP_KERNEL);
+ compl = kmalloc(sizeof(*compl), GFP_KERNEL);
if (!compl) {
ath10k_warn("No memory for completion state\n");
ath10k_pci_stop_ce(ar);
return -ENOMEM;
}
- compl->send_or_recv = HIF_CE_COMPLETE_FREE;
+ compl->state = ATH10K_PCI_COMPL_FREE;
list_add_tail(&compl->list, &pipe_info->compl_free);
}
}
@@ -840,7 +940,7 @@ static void ath10k_pci_stop_ce(struct ath10k *ar)
* their associated resources */
spin_lock_bh(&ar_pci->compl_lock);
list_for_each_entry(compl, &ar_pci->compl_process, list) {
- skb = (struct sk_buff *)compl->transfer_context;
+ skb = compl->skb;
ATH10K_SKB_CB(skb)->is_aborted = true;
}
spin_unlock_bh(&ar_pci->compl_lock);
@@ -850,7 +950,7 @@ static void ath10k_pci_cleanup_ce(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_pci_compl *compl, *tmp;
- struct hif_ce_pipe_info *pipe_info;
+ struct ath10k_pci_pipe *pipe_info;
struct sk_buff *netbuf;
int pipe_num;
@@ -861,7 +961,7 @@ static void ath10k_pci_cleanup_ce(struct ath10k *ar)
list_for_each_entry_safe(compl, tmp, &ar_pci->compl_process, list) {
list_del(&compl->list);
- netbuf = (struct sk_buff *)compl->transfer_context;
+ netbuf = compl->skb;
dev_kfree_skb_any(netbuf);
kfree(compl);
}
@@ -912,12 +1012,14 @@ static void ath10k_pci_process_ce(struct ath10k *ar)
list_del(&compl->list);
spin_unlock_bh(&ar_pci->compl_lock);
- if (compl->send_or_recv == HIF_CE_COMPLETE_SEND) {
+ switch (compl->state) {
+ case ATH10K_PCI_COMPL_SEND:
cb->tx_completion(ar,
- compl->transfer_context,
+ compl->skb,
compl->transfer_id);
send_done = 1;
- } else {
+ break;
+ case ATH10K_PCI_COMPL_RECV:
ret = ath10k_pci_post_rx_pipe(compl->pipe_info, 1);
if (ret) {
ath10k_warn("Unable to post recv buffer for pipe: %d\n",
@@ -925,7 +1027,7 @@ static void ath10k_pci_process_ce(struct ath10k *ar)
break;
}
- skb = (struct sk_buff *)compl->transfer_context;
+ skb = compl->skb;
nbytes = compl->nbytes;
ath10k_dbg(ATH10K_DBG_PCI,
@@ -944,9 +1046,17 @@ static void ath10k_pci_process_ce(struct ath10k *ar)
nbytes,
skb->len + skb_tailroom(skb));
}
+ break;
+ case ATH10K_PCI_COMPL_FREE:
+ ath10k_warn("free completion cannot be processed\n");
+ break;
+ default:
+ ath10k_warn("invalid completion state (%d)\n",
+ compl->state);
+ break;
}
- compl->send_or_recv = HIF_CE_COMPLETE_FREE;
+ compl->state = ATH10K_PCI_COMPL_FREE;
/*
* Add completion back to the pipe's free list.
@@ -1037,12 +1147,12 @@ static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar,
&dl_is_polled);
}
-static int ath10k_pci_post_rx_pipe(struct hif_ce_pipe_info *pipe_info,
+static int ath10k_pci_post_rx_pipe(struct ath10k_pci_pipe *pipe_info,
int num)
{
struct ath10k *ar = pipe_info->hif_ce_state;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct ce_state *ce_state = pipe_info->ce_hdl;
+ struct ath10k_ce_pipe *ce_state = pipe_info->ce_hdl;
struct sk_buff *skb;
dma_addr_t ce_data;
int i, ret = 0;
@@ -1097,7 +1207,7 @@ err:
static int ath10k_pci_post_rx(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct hif_ce_pipe_info *pipe_info;
+ struct ath10k_pci_pipe *pipe_info;
const struct ce_attr *attr;
int pipe_num, ret = 0;
@@ -1147,11 +1257,11 @@ static int ath10k_pci_hif_start(struct ath10k *ar)
return 0;
}
-static void ath10k_pci_rx_pipe_cleanup(struct hif_ce_pipe_info *pipe_info)
+static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info)
{
struct ath10k *ar;
struct ath10k_pci *ar_pci;
- struct ce_state *ce_hdl;
+ struct ath10k_ce_pipe *ce_hdl;
u32 buf_sz;
struct sk_buff *netbuf;
u32 ce_data;
@@ -1179,11 +1289,11 @@ static void ath10k_pci_rx_pipe_cleanup(struct hif_ce_pipe_info *pipe_info)
}
}
-static void ath10k_pci_tx_pipe_cleanup(struct hif_ce_pipe_info *pipe_info)
+static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info)
{
struct ath10k *ar;
struct ath10k_pci *ar_pci;
- struct ce_state *ce_hdl;
+ struct ath10k_ce_pipe *ce_hdl;
struct sk_buff *netbuf;
u32 ce_data;
unsigned int nbytes;
@@ -1232,7 +1342,7 @@ static void ath10k_pci_buffer_cleanup(struct ath10k *ar)
int pipe_num;
for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) {
- struct hif_ce_pipe_info *pipe_info;
+ struct ath10k_pci_pipe *pipe_info;
pipe_info = &ar_pci->pipe_info[pipe_num];
ath10k_pci_rx_pipe_cleanup(pipe_info);
@@ -1243,7 +1353,7 @@ static void ath10k_pci_buffer_cleanup(struct ath10k *ar)
static void ath10k_pci_ce_deinit(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct hif_ce_pipe_info *pipe_info;
+ struct ath10k_pci_pipe *pipe_info;
int pipe_num;
for (pipe_num = 0; pipe_num < ar_pci->ce_count; pipe_num++) {
@@ -1293,8 +1403,10 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
void *resp, u32 *resp_len)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct ce_state *ce_tx = ar_pci->pipe_info[BMI_CE_NUM_TO_TARG].ce_hdl;
- struct ce_state *ce_rx = ar_pci->pipe_info[BMI_CE_NUM_TO_HOST].ce_hdl;
+ struct ath10k_pci_pipe *pci_tx = &ar_pci->pipe_info[BMI_CE_NUM_TO_TARG];
+ struct ath10k_pci_pipe *pci_rx = &ar_pci->pipe_info[BMI_CE_NUM_TO_HOST];
+ struct ath10k_ce_pipe *ce_tx = pci_tx->ce_hdl;
+ struct ath10k_ce_pipe *ce_rx = pci_rx->ce_hdl;
dma_addr_t req_paddr = 0;
dma_addr_t resp_paddr = 0;
struct bmi_xfer xfer = {};
@@ -1378,7 +1490,7 @@ err_dma:
return ret;
}
-static void ath10k_pci_bmi_send_done(struct ce_state *ce_state,
+static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state,
void *transfer_context,
u32 data,
unsigned int nbytes,
@@ -1392,7 +1504,7 @@ static void ath10k_pci_bmi_send_done(struct ce_state *ce_state,
complete(&xfer->done);
}
-static void ath10k_pci_bmi_recv_data(struct ce_state *ce_state,
+static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state,
void *transfer_context,
u32 data,
unsigned int nbytes,
@@ -1679,7 +1791,7 @@ static int ath10k_pci_init_config(struct ath10k *ar)
static int ath10k_pci_ce_init(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct hif_ce_pipe_info *pipe_info;
+ struct ath10k_pci_pipe *pipe_info;
const struct ce_attr *attr;
int pipe_num;
@@ -1895,7 +2007,7 @@ static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
static void ath10k_pci_ce_tasklet(unsigned long ptr)
{
- struct hif_ce_pipe_info *pipe = (struct hif_ce_pipe_info *)ptr;
+ struct ath10k_pci_pipe *pipe = (struct ath10k_pci_pipe *)ptr;
struct ath10k_pci *ar_pci = pipe->ar_pci;
ath10k_ce_per_engine_service(ar_pci->ar, pipe->pipe_num);
@@ -2212,18 +2324,13 @@ static int ath10k_pci_reset_target(struct ath10k *ar)
static void ath10k_pci_device_reset(struct ath10k *ar)
{
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- void __iomem *mem = ar_pci->mem;
int i;
u32 val;
if (!SOC_GLOBAL_RESET_ADDRESS)
return;
- if (!mem)
- return;
-
- ath10k_pci_reg_write32(mem, PCIE_SOC_WAKE_ADDRESS,
+ ath10k_pci_reg_write32(ar, PCIE_SOC_WAKE_ADDRESS,
PCIE_SOC_WAKE_V_MASK);
for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) {
if (ath10k_pci_target_is_awake(ar))
@@ -2232,12 +2339,12 @@ static void ath10k_pci_device_reset(struct ath10k *ar)
}
/* Put Target, including PCIe, into RESET. */
- val = ath10k_pci_reg_read32(mem, SOC_GLOBAL_RESET_ADDRESS);
+ val = ath10k_pci_reg_read32(ar, SOC_GLOBAL_RESET_ADDRESS);
val |= 1;
- ath10k_pci_reg_write32(mem, SOC_GLOBAL_RESET_ADDRESS, val);
+ ath10k_pci_reg_write32(ar, SOC_GLOBAL_RESET_ADDRESS, val);
for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) {
- if (ath10k_pci_reg_read32(mem, RTC_STATE_ADDRESS) &
+ if (ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS) &
RTC_STATE_COLD_RESET_MASK)
break;
msleep(1);
@@ -2245,16 +2352,16 @@ static void ath10k_pci_device_reset(struct ath10k *ar)
/* Pull Target, including PCIe, out of RESET. */
val &= ~1;
- ath10k_pci_reg_write32(mem, SOC_GLOBAL_RESET_ADDRESS, val);
+ ath10k_pci_reg_write32(ar, SOC_GLOBAL_RESET_ADDRESS, val);
for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) {
- if (!(ath10k_pci_reg_read32(mem, RTC_STATE_ADDRESS) &
+ if (!(ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS) &
RTC_STATE_COLD_RESET_MASK))
break;
msleep(1);
}
- ath10k_pci_reg_write32(mem, PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET);
+ ath10k_pci_reg_write32(ar, PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET);
}
static void ath10k_pci_dump_features(struct ath10k_pci *ar_pci)
@@ -2269,9 +2376,6 @@ static void ath10k_pci_dump_features(struct ath10k_pci *ar_pci)
case ATH10K_PCI_FEATURE_MSI_X:
ath10k_dbg(ATH10K_DBG_PCI, "device supports MSI-X\n");
break;
- case ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND:
- ath10k_dbg(ATH10K_DBG_PCI, "QCA988X_1.0 workaround enabled\n");
- break;
case ATH10K_PCI_FEATURE_SOC_POWER_SAVE:
ath10k_dbg(ATH10K_DBG_PCI, "QCA98XX SoC power save enabled\n");
break;
@@ -2286,7 +2390,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
int ret = 0;
struct ath10k *ar;
struct ath10k_pci *ar_pci;
- u32 lcr_val;
+ u32 lcr_val, chip_id;
ath10k_dbg(ATH10K_DBG_PCI, "%s\n", __func__);
@@ -2298,9 +2402,6 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
ar_pci->dev = &pdev->dev;
switch (pci_dev->device) {
- case QCA988X_1_0_DEVICE_ID:
- set_bit(ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND, ar_pci->features);
- break;
case QCA988X_2_0_DEVICE_ID:
set_bit(ATH10K_PCI_FEATURE_MSI_X, ar_pci->features);
break;
@@ -2322,10 +2423,6 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
goto err_ar_pci;
}
- /* Enable QCA988X_1.0 HW workarounds */
- if (test_bit(ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND, ar_pci->features))
- spin_lock_init(&ar_pci->hw_v1_workaround_lock);
-
ar_pci->ar = ar;
ar_pci->fw_indicator_address = FW_INDICATOR_ADDRESS;
atomic_set(&ar_pci->keep_awake_count, 0);
@@ -2395,9 +2492,18 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
spin_lock_init(&ar_pci->ce_lock);
- ar_pci->cacheline_sz = dma_get_cache_alignment();
+ ret = ath10k_do_pci_wake(ar);
+ if (ret) {
+ ath10k_err("Failed to get chip id: %d\n", ret);
+ return ret;
+ }
+
+ chip_id = ath10k_pci_read32(ar,
+ RTC_SOC_BASE_ADDRESS + SOC_CHIP_ID_ADDRESS);
+
+ ath10k_do_pci_sleep(ar);
- ret = ath10k_core_register(ar);
+ ret = ath10k_core_register(ar, chip_id);
if (ret) {
ath10k_err("could not register driver core (%d)\n", ret);
goto err_iomap;
@@ -2414,7 +2520,6 @@ err_region:
err_device:
pci_disable_device(pdev);
err_ar:
- pci_set_drvdata(pdev, NULL);
ath10k_core_destroy(ar);
err_ar_pci:
/* call HIF PCI free here */
@@ -2442,7 +2547,6 @@ static void ath10k_pci_remove(struct pci_dev *pdev)
ath10k_core_unregister(ar);
- pci_set_drvdata(pdev, NULL);
pci_iounmap(pdev, ar_pci->mem);
pci_release_region(pdev, BAR_NUM);
pci_clear_master(pdev);
@@ -2483,9 +2587,6 @@ module_exit(ath10k_pci_exit);
MODULE_AUTHOR("Qualcomm Atheros");
MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_FIRMWARE(QCA988X_HW_1_0_FW_DIR "/" QCA988X_HW_1_0_FW_FILE);
-MODULE_FIRMWARE(QCA988X_HW_1_0_FW_DIR "/" QCA988X_HW_1_0_OTP_FILE);
-MODULE_FIRMWARE(QCA988X_HW_1_0_FW_DIR "/" QCA988X_HW_1_0_BOARD_DATA_FILE);
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_FILE);
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_OTP_FILE);
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE);
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
index 871bb339d56d..7c49f6f96f70 100644
--- a/drivers/net/wireless/ath/ath10k/pci.h
+++ b/drivers/net/wireless/ath/ath10k/pci.h
@@ -43,22 +43,23 @@ struct bmi_xfer {
u32 resp_len;
};
+enum ath10k_pci_compl_state {
+ ATH10K_PCI_COMPL_FREE = 0,
+ ATH10K_PCI_COMPL_SEND,
+ ATH10K_PCI_COMPL_RECV,
+};
+
struct ath10k_pci_compl {
struct list_head list;
- int send_or_recv;
- struct ce_state *ce_state;
- struct hif_ce_pipe_info *pipe_info;
- void *transfer_context;
+ enum ath10k_pci_compl_state state;
+ struct ath10k_ce_pipe *ce_state;
+ struct ath10k_pci_pipe *pipe_info;
+ struct sk_buff *skb;
unsigned int nbytes;
unsigned int transfer_id;
unsigned int flags;
};
-/* compl_state.send_or_recv */
-#define HIF_CE_COMPLETE_FREE 0
-#define HIF_CE_COMPLETE_SEND 1
-#define HIF_CE_COMPLETE_RECV 2
-
/*
* PCI-specific Target state
*
@@ -152,17 +153,16 @@ struct service_to_pipe {
enum ath10k_pci_features {
ATH10K_PCI_FEATURE_MSI_X = 0,
- ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND = 1,
- ATH10K_PCI_FEATURE_SOC_POWER_SAVE = 2,
+ ATH10K_PCI_FEATURE_SOC_POWER_SAVE = 1,
/* keep last */
ATH10K_PCI_FEATURE_COUNT
};
/* Per-pipe state. */
-struct hif_ce_pipe_info {
+struct ath10k_pci_pipe {
/* Handle of underlying Copy Engine */
- struct ce_state *ce_hdl;
+ struct ath10k_ce_pipe *ce_hdl;
/* Our pipe number; facilitiates use of pipe_info ptrs. */
u8 pipe_num;
@@ -190,7 +190,6 @@ struct ath10k_pci {
struct device *dev;
struct ath10k *ar;
void __iomem *mem;
- int cacheline_sz;
DECLARE_BITMAP(features, ATH10K_PCI_FEATURE_COUNT);
@@ -219,7 +218,7 @@ struct ath10k_pci {
bool compl_processing;
- struct hif_ce_pipe_info pipe_info[CE_COUNT_MAX];
+ struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX];
struct ath10k_hif_cb msg_callbacks_current;
@@ -227,16 +226,13 @@ struct ath10k_pci {
u32 fw_indicator_address;
/* Copy Engine used for Diagnostic Accesses */
- struct ce_state *ce_diag;
+ struct ath10k_ce_pipe *ce_diag;
/* FIXME: document what this really protects */
spinlock_t ce_lock;
/* Map CE id to ce_state */
- struct ce_state *ce_id_to_state[CE_COUNT_MAX];
-
- /* makes sure that dummy reads are atomic */
- spinlock_t hw_v1_workaround_lock;
+ struct ath10k_ce_pipe ce_states[CE_COUNT_MAX];
};
static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar)
@@ -244,14 +240,18 @@ static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar)
return ar->hif.priv;
}
-static inline u32 ath10k_pci_reg_read32(void __iomem *mem, u32 addr)
+static inline u32 ath10k_pci_reg_read32(struct ath10k *ar, u32 addr)
{
- return ioread32(mem + PCIE_LOCAL_BASE_ADDRESS + addr);
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
+ return ioread32(ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + addr);
}
-static inline void ath10k_pci_reg_write32(void __iomem *mem, u32 addr, u32 val)
+static inline void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val)
{
- iowrite32(val, mem + PCIE_LOCAL_BASE_ADDRESS + addr);
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
+ iowrite32(val, ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + addr);
}
#define ATH_PCI_RESET_WAIT_MAX 10 /* ms */
@@ -310,23 +310,8 @@ static inline void ath10k_pci_write32(struct ath10k *ar, u32 offset,
u32 value)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- void __iomem *addr = ar_pci->mem;
-
- if (test_bit(ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND, ar_pci->features)) {
- unsigned long irq_flags;
- spin_lock_irqsave(&ar_pci->hw_v1_workaround_lock, irq_flags);
-
- ioread32(addr+offset+4); /* 3rd read prior to write */
- ioread32(addr+offset+4); /* 2nd read prior to write */
- ioread32(addr+offset+4); /* 1st read prior to write */
- iowrite32(value, addr+offset);
-
- spin_unlock_irqrestore(&ar_pci->hw_v1_workaround_lock,
- irq_flags);
- } else {
- iowrite32(value, addr+offset);
- }
+ iowrite32(value, ar_pci->mem + offset);
}
static inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset)
@@ -336,15 +321,17 @@ static inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset)
return ioread32(ar_pci->mem + offset);
}
-void ath10k_do_pci_wake(struct ath10k *ar);
+int ath10k_do_pci_wake(struct ath10k *ar);
void ath10k_do_pci_sleep(struct ath10k *ar);
-static inline void ath10k_pci_wake(struct ath10k *ar)
+static inline int ath10k_pci_wake(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
if (test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features))
- ath10k_do_pci_wake(ar);
+ return ath10k_do_pci_wake(ar);
+
+ return 0;
}
static inline void ath10k_pci_sleep(struct ath10k *ar)
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 55f90c761868..32fd5e735beb 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -110,6 +110,7 @@ static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb,
if (atomic_add_return(1, &ar->wmi.pending_tx_count) >
WMI_MAX_PENDING_TX_COUNT) {
/* avoid using up memory when FW hangs */
+ dev_kfree_skb(skb);
atomic_dec(&ar->wmi.pending_tx_count);
return -EBUSY;
}
@@ -315,7 +316,9 @@ static inline u8 get_rate_idx(u32 rate, enum ieee80211_band band)
static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
{
- struct wmi_mgmt_rx_event *event = (struct wmi_mgmt_rx_event *)skb->data;
+ struct wmi_mgmt_rx_event_v1 *ev_v1;
+ struct wmi_mgmt_rx_event_v2 *ev_v2;
+ struct wmi_mgmt_rx_hdr_v1 *ev_hdr;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_hdr *hdr;
u32 rx_status;
@@ -325,13 +328,24 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
u32 rate;
u32 buf_len;
u16 fc;
+ int pull_len;
+
+ if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features)) {
+ ev_v2 = (struct wmi_mgmt_rx_event_v2 *)skb->data;
+ ev_hdr = &ev_v2->hdr.v1;
+ pull_len = sizeof(*ev_v2);
+ } else {
+ ev_v1 = (struct wmi_mgmt_rx_event_v1 *)skb->data;
+ ev_hdr = &ev_v1->hdr;
+ pull_len = sizeof(*ev_v1);
+ }
- channel = __le32_to_cpu(event->hdr.channel);
- buf_len = __le32_to_cpu(event->hdr.buf_len);
- rx_status = __le32_to_cpu(event->hdr.status);
- snr = __le32_to_cpu(event->hdr.snr);
- phy_mode = __le32_to_cpu(event->hdr.phy_mode);
- rate = __le32_to_cpu(event->hdr.rate);
+ channel = __le32_to_cpu(ev_hdr->channel);
+ buf_len = __le32_to_cpu(ev_hdr->buf_len);
+ rx_status = __le32_to_cpu(ev_hdr->status);
+ snr = __le32_to_cpu(ev_hdr->snr);
+ phy_mode = __le32_to_cpu(ev_hdr->phy_mode);
+ rate = __le32_to_cpu(ev_hdr->rate);
memset(status, 0, sizeof(*status));
@@ -358,7 +372,7 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR;
status->rate_idx = get_rate_idx(rate, status->band);
- skb_pull(skb, sizeof(event->hdr));
+ skb_pull(skb, pull_len);
hdr = (struct ieee80211_hdr *)skb->data;
fc = le16_to_cpu(hdr->frame_control);
@@ -943,6 +957,9 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
ar->phy_capability = __le32_to_cpu(ev->phy_capability);
ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains);
+ if (ar->fw_version_build > 636)
+ set_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features);
+
if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) {
ath10k_warn("hardware advertises support for more spatial streams than it should (%d > %d)\n",
ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 2c5a4f8daf2e..08860c475721 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -1268,7 +1268,7 @@ struct wmi_scan_event {
* good idea to pass all the fields in the RX status
* descriptor up to the host.
*/
-struct wmi_mgmt_rx_hdr {
+struct wmi_mgmt_rx_hdr_v1 {
__le32 channel;
__le32 snr;
__le32 rate;
@@ -1277,8 +1277,18 @@ struct wmi_mgmt_rx_hdr {
__le32 status; /* %WMI_RX_STATUS_ */
} __packed;
-struct wmi_mgmt_rx_event {
- struct wmi_mgmt_rx_hdr hdr;
+struct wmi_mgmt_rx_hdr_v2 {
+ struct wmi_mgmt_rx_hdr_v1 v1;
+ __le32 rssi_ctl[4];
+} __packed;
+
+struct wmi_mgmt_rx_event_v1 {
+ struct wmi_mgmt_rx_hdr_v1 hdr;
+ u8 buf[0];
+} __packed;
+
+struct wmi_mgmt_rx_event_v2 {
+ struct wmi_mgmt_rx_hdr_v2 hdr;
u8 buf[0];
} __packed;
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
index e9bc9e616b69..79bffe165cab 100644
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -37,12 +37,9 @@ ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
{
struct ath5k_hw *ah = common->priv;
struct platform_device *pdev = to_platform_device(ah->dev);
- struct ar231x_board_config *bcfg = pdev->dev.platform_data;
+ struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
u16 *eeprom, *eeprom_end;
-
-
- bcfg = pdev->dev.platform_data;
eeprom = (u16 *) bcfg->radio;
eeprom_end = ((void *) bcfg->config) + BOARD_CONFIG_BUFSZ;
@@ -57,7 +54,7 @@ ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
int ath5k_hw_read_srev(struct ath5k_hw *ah)
{
struct platform_device *pdev = to_platform_device(ah->dev);
- struct ar231x_board_config *bcfg = pdev->dev.platform_data;
+ struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
ah->ah_mac_srev = bcfg->devid;
return 0;
}
@@ -65,7 +62,7 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah)
static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
{
struct platform_device *pdev = to_platform_device(ah->dev);
- struct ar231x_board_config *bcfg = pdev->dev.platform_data;
+ struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
u8 *cfg_mac;
if (to_platform_device(ah->dev)->id == 0)
@@ -87,7 +84,7 @@ static const struct ath_bus_ops ath_ahb_bus_ops = {
/*Initialization*/
static int ath_ahb_probe(struct platform_device *pdev)
{
- struct ar231x_board_config *bcfg = pdev->dev.platform_data;
+ struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
struct ath5k_hw *ah;
struct ieee80211_hw *hw;
struct resource *res;
@@ -96,7 +93,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
int ret = 0;
u32 reg;
- if (!pdev->dev.platform_data) {
+ if (!dev_get_platdata(&pdev->dev)) {
dev_err(&pdev->dev, "no platform data specified\n");
ret = -EINVAL;
goto err_out;
@@ -193,7 +190,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
static int ath_ahb_remove(struct platform_device *pdev)
{
- struct ar231x_board_config *bcfg = pdev->dev.platform_data;
+ struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
struct ieee80211_hw *hw = platform_get_drvdata(pdev);
struct ath5k_hw *ah;
u32 reg;
diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h
index 98a886154d9c..05debf700a84 100644
--- a/drivers/net/wireless/ath/ath6kl/common.h
+++ b/drivers/net/wireless/ath/ath6kl/common.h
@@ -22,8 +22,7 @@
#define ATH6KL_MAX_IE 256
-extern __printf(2, 3)
-int ath6kl_printk(const char *level, const char *fmt, ...);
+__printf(2, 3) int ath6kl_printk(const char *level, const char *fmt, ...);
/*
* Reflects the version of binary interface exposed by ATH6KL target
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
index 74369de00fb5..ca9ba005f287 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.h
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -50,11 +50,10 @@ enum ATH6K_DEBUG_MASK {
};
extern unsigned int debug_mask;
-extern __printf(2, 3)
-int ath6kl_printk(const char *level, const char *fmt, ...);
-extern __printf(1, 2) int ath6kl_info(const char *fmt, ...);
-extern __printf(1, 2) int ath6kl_err(const char *fmt, ...);
-extern __printf(1, 2) int ath6kl_warn(const char *fmt, ...);
+__printf(2, 3) int ath6kl_printk(const char *level, const char *fmt, ...);
+__printf(1, 2) int ath6kl_info(const char *fmt, ...);
+__printf(1, 2) int ath6kl_err(const char *fmt, ...);
+__printf(1, 2) int ath6kl_warn(const char *fmt, ...);
enum ath6kl_war {
ATH6KL_WAR_INVALID_RATE,
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 072e4b531067..2dff2765769b 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -54,7 +54,7 @@ static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
struct platform_device *pdev = to_platform_device(sc->dev);
struct ath9k_platform_data *pdata;
- pdata = (struct ath9k_platform_data *) pdev->dev.platform_data;
+ pdata = dev_get_platdata(&pdev->dev);
if (off >= (ARRAY_SIZE(pdata->eeprom_data))) {
ath_err(common,
"%s: flash read failed, offset %08x is out of range\n",
@@ -84,7 +84,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
struct ath_hw *ah;
char hw_name[64];
- if (!pdev->dev.platform_data) {
+ if (!dev_get_platdata(&pdev->dev)) {
dev_err(&pdev->dev, "no platform data specified\n");
return -EINVAL;
}
diff --git a/drivers/net/wireless/ath/ath9k/antenna.c b/drivers/net/wireless/ath/ath9k/antenna.c
index dd1cc73d7946..bd048cc69a33 100644
--- a/drivers/net/wireless/ath/ath9k/antenna.c
+++ b/drivers/net/wireless/ath/ath9k/antenna.c
@@ -332,7 +332,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
}
if (antcomb->rssi_lna2 > antcomb->rssi_lna1 +
- ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)
+ div_ant_conf->lna1_lna2_switch_delta)
div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2;
else
div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
@@ -554,42 +554,22 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
ant_conf->fast_div_bias = 0x1;
break;
case 0x10: /* LNA2 A-B */
- if ((antcomb->scan == 0) &&
- (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) {
- ant_conf->fast_div_bias = 0x3f;
- } else {
- ant_conf->fast_div_bias = 0x1;
- }
+ ant_conf->fast_div_bias = 0x2;
break;
case 0x12: /* LNA2 LNA1 */
- ant_conf->fast_div_bias = 0x39;
+ ant_conf->fast_div_bias = 0x3f;
break;
case 0x13: /* LNA2 A+B */
- if ((antcomb->scan == 0) &&
- (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) {
- ant_conf->fast_div_bias = 0x3f;
- } else {
- ant_conf->fast_div_bias = 0x1;
- }
+ ant_conf->fast_div_bias = 0x2;
break;
case 0x20: /* LNA1 A-B */
- if ((antcomb->scan == 0) &&
- (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) {
- ant_conf->fast_div_bias = 0x3f;
- } else {
- ant_conf->fast_div_bias = 0x4;
- }
+ ant_conf->fast_div_bias = 0x3;
break;
case 0x21: /* LNA1 LNA2 */
- ant_conf->fast_div_bias = 0x6;
+ ant_conf->fast_div_bias = 0x3;
break;
case 0x23: /* LNA1 A+B */
- if ((antcomb->scan == 0) &&
- (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) {
- ant_conf->fast_div_bias = 0x3f;
- } else {
- ant_conf->fast_div_bias = 0x6;
- }
+ ant_conf->fast_div_bias = 0x3;
break;
case 0x30: /* A+B A-B */
ant_conf->fast_div_bias = 0x1;
@@ -638,7 +618,7 @@ static void ath_ant_try_scan(struct ath_ant_comb *antcomb,
antcomb->rssi_sub = alt_rssi_avg;
antcomb->scan = false;
if (antcomb->rssi_lna2 >
- (antcomb->rssi_lna1 + ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) {
+ (antcomb->rssi_lna1 + conf->lna1_lna2_switch_delta)) {
/* use LNA2 as main LNA */
if ((antcomb->rssi_add > antcomb->rssi_lna1) &&
(antcomb->rssi_add > antcomb->rssi_sub)) {
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 08656473c63e..cb6435e7c6f5 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -626,12 +626,11 @@ static void ar5008_hw_override_ini(struct ath_hw *ah,
if (AR_SREV_9287_11_OR_LATER(ah))
val = val & (~AR_PCU_MISC_MODE2_HWWAR2);
+ val |= AR_PCU_MISC_MODE2_CFP_IGNORE;
+
REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
}
- REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
- AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
-
if (AR_SREV_9280_20_OR_LATER(ah))
return;
/*
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index 9f589744a9f9..32376ad74011 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -671,7 +671,7 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah,
nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF);
if (ah->caldata)
- nfcal_pending = ah->caldata->nfcal_pending;
+ nfcal_pending = test_bit(NFCAL_PENDING, &ah->caldata->cal_flags);
if (currCal && !nfcal &&
(currCal->calState == CAL_RUNNING ||
@@ -861,7 +861,7 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
ar9002_hw_pa_cal(ah, true);
if (ah->caldata)
- ah->caldata->nfcal_pending = true;
+ set_bit(NFCAL_PENDING, &ah->caldata->cal_flags);
ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
index 1fc1fa955d44..17970d49d858 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
@@ -485,7 +485,7 @@ static void ar9002_hw_do_getnf(struct ath_hw *ah,
if (IS_CHAN_HT40(ah->curchan))
nfarray[3] = sign_extend32(nf, 8);
- if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
+ if (!(ah->rxchainmask & BIT(1)))
return;
nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR);
@@ -532,6 +532,7 @@ static void ar9002_hw_antdiv_comb_conf_get(struct ath_hw *ah,
AR_PHY_9285_ANT_DIV_ALT_LNACONF_S;
antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >>
AR_PHY_9285_FAST_DIV_BIAS_S;
+ antconf->lna1_lna2_switch_delta = -1;
antconf->lna1_lna2_delta = -3;
antconf->div_group = 0;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 6988e1d081f2..22934d3ca544 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -727,8 +727,12 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
- if (caldata)
- caldata->done_txiqcal_once = is_reusable;
+ if (caldata) {
+ if (is_reusable)
+ set_bit(TXIQCAL_DONE, &caldata->cal_flags);
+ else
+ clear_bit(TXIQCAL_DONE, &caldata->cal_flags);
+ }
return;
}
@@ -961,18 +965,44 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
}
static void ar9003_hw_do_manual_peak_cal(struct ath_hw *ah,
- struct ath9k_channel *chan)
+ struct ath9k_channel *chan,
+ bool run_rtt_cal)
{
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
int i;
if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah) && !AR_SREV_9485(ah))
return;
+ if ((ah->caps.hw_caps & ATH9K_HW_CAP_RTT) && !run_rtt_cal)
+ return;
+
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
if (!(ah->rxchainmask & (1 << i)))
continue;
ar9003_hw_manual_peak_cal(ah, i, IS_CHAN_2GHZ(chan));
}
+
+ if (caldata)
+ set_bit(SW_PKDET_DONE, &caldata->cal_flags);
+
+ if ((ah->caps.hw_caps & ATH9K_HW_CAP_RTT) && caldata) {
+ if (IS_CHAN_2GHZ(chan)){
+ caldata->caldac[0] = REG_READ_FIELD(ah,
+ AR_PHY_65NM_RXRF_AGC(0),
+ AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR);
+ caldata->caldac[1] = REG_READ_FIELD(ah,
+ AR_PHY_65NM_RXRF_AGC(1),
+ AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR);
+ } else {
+ caldata->caldac[0] = REG_READ_FIELD(ah,
+ AR_PHY_65NM_RXRF_AGC(0),
+ AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR);
+ caldata->caldac[1] = REG_READ_FIELD(ah,
+ AR_PHY_65NM_RXRF_AGC(1),
+ AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR);
+ }
+ }
}
static void ar9003_hw_cl_cal_post_proc(struct ath_hw *ah, bool is_reusable)
@@ -990,7 +1020,7 @@ static void ar9003_hw_cl_cal_post_proc(struct ath_hw *ah, bool is_reusable)
txclcal_done = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) &
AR_PHY_AGC_CONTROL_CLC_SUCCESS);
- if (caldata->done_txclcal_once) {
+ if (test_bit(TXCLCAL_DONE, &caldata->cal_flags)) {
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
if (!(ah->txchainmask & (1 << i)))
continue;
@@ -1006,7 +1036,7 @@ static void ar9003_hw_cl_cal_post_proc(struct ath_hw *ah, bool is_reusable)
caldata->tx_clcal[i][j] =
REG_READ(ah, CL_TAB_ENTRY(cl_idx[i]));
}
- caldata->done_txclcal_once = true;
+ set_bit(TXCLCAL_DONE, &caldata->cal_flags);
}
}
@@ -1019,6 +1049,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
bool is_reusable = true, status = true;
bool run_rtt_cal = false, run_agc_cal, sep_iq_cal = false;
bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT);
+ u32 rx_delay = 0;
u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL |
AR_PHY_AGC_CONTROL_FLTR_CAL |
AR_PHY_AGC_CONTROL_PKDET_CAL;
@@ -1042,17 +1073,22 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
ar9003_hw_rtt_clear_hist(ah);
}
- if (rtt && !run_rtt_cal) {
- agc_ctrl = REG_READ(ah, AR_PHY_AGC_CONTROL);
- agc_supp_cals &= agc_ctrl;
- agc_ctrl &= ~(AR_PHY_AGC_CONTROL_OFFSET_CAL |
- AR_PHY_AGC_CONTROL_FLTR_CAL |
- AR_PHY_AGC_CONTROL_PKDET_CAL);
- REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl);
+ if (rtt) {
+ if (!run_rtt_cal) {
+ agc_ctrl = REG_READ(ah, AR_PHY_AGC_CONTROL);
+ agc_supp_cals &= agc_ctrl;
+ agc_ctrl &= ~(AR_PHY_AGC_CONTROL_OFFSET_CAL |
+ AR_PHY_AGC_CONTROL_FLTR_CAL |
+ AR_PHY_AGC_CONTROL_PKDET_CAL);
+ REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl);
+ } else {
+ if (ah->ah_flags & AH_FASTCC)
+ run_agc_cal = true;
+ }
}
if (ah->enabled_cals & TX_CL_CAL) {
- if (caldata && caldata->done_txclcal_once)
+ if (caldata && test_bit(TXCLCAL_DONE, &caldata->cal_flags))
REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL,
AR_PHY_CL_CAL_ENABLE);
else {
@@ -1076,14 +1112,14 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
* AGC calibration
*/
if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) {
- if (caldata && !caldata->done_txiqcal_once)
+ if (caldata && !test_bit(TXIQCAL_DONE, &caldata->cal_flags))
REG_SET_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
else
REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
txiqcal_done = run_agc_cal = true;
- } else if (caldata && !caldata->done_txiqcal_once) {
+ } else if (caldata && !test_bit(TXIQCAL_DONE, &caldata->cal_flags)) {
run_agc_cal = true;
sep_iq_cal = true;
}
@@ -1099,6 +1135,15 @@ skip_tx_iqcal:
REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
}
+ if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) {
+ rx_delay = REG_READ(ah, AR_PHY_RX_DELAY);
+ /* Disable BB_active */
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
+ udelay(5);
+ REG_WRITE(ah, AR_PHY_RX_DELAY, AR_PHY_RX_DELAY_DELAY);
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+ }
+
if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
/* Calibrate the AGC */
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
@@ -1110,7 +1155,12 @@ skip_tx_iqcal:
AR_PHY_AGC_CONTROL_CAL,
0, AH_WAIT_TIMEOUT);
- ar9003_hw_do_manual_peak_cal(ah, chan);
+ ar9003_hw_do_manual_peak_cal(ah, chan, run_rtt_cal);
+ }
+
+ if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) {
+ REG_WRITE(ah, AR_PHY_RX_DELAY, rx_delay);
+ udelay(5);
}
if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal)
@@ -1133,19 +1183,23 @@ skip_tx_iqcal:
if (txiqcal_done)
ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
- else if (caldata && caldata->done_txiqcal_once)
+ else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags))
ar9003_hw_tx_iq_cal_reload(ah);
ar9003_hw_cl_cal_post_proc(ah, is_reusable);
if (run_rtt_cal && caldata) {
if (is_reusable) {
- if (!ath9k_hw_rfbus_req(ah))
+ if (!ath9k_hw_rfbus_req(ah)) {
ath_err(ath9k_hw_common(ah),
"Could not stop baseband\n");
- else
+ } else {
ar9003_hw_rtt_fill_hist(ah);
+ if (test_bit(SW_PKDET_DONE, &caldata->cal_flags))
+ ar9003_hw_rtt_load_hist(ah);
+ }
+
ath9k_hw_rfbus_done(ah);
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index f4864807e15b..1ec52356b5a1 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -2991,7 +2991,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
case EEP_CHAIN_MASK_REDUCE:
return (pBase->miscConfiguration >> 0x3) & 0x1;
case EEP_ANT_DIV_CTL1:
- return eep->base_ext1.ant_div_control;
+ if (AR_SREV_9565(ah))
+ return AR9300_EEP_ANTDIV_CONTROL_DEFAULT_VALUE;
+ else
+ return eep->base_ext1.ant_div_control;
case EEP_ANTENNA_GAIN_5G:
return eep->modalHeader5G.antennaGain;
case EEP_ANTENNA_GAIN_2G:
@@ -3424,12 +3427,12 @@ static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
struct ar9300_base_eep_hdr *pBase;
if (!dump_base_hdr) {
- len += snprintf(buf + len, size - len,
- "%20s :\n", "2GHz modal Header");
+ len += scnprintf(buf + len, size - len,
+ "%20s :\n", "2GHz modal Header");
len = ar9003_dump_modal_eeprom(buf, len, size,
&eep->modalHeader2G);
- len += snprintf(buf + len, size - len,
- "%20s :\n", "5GHz modal Header");
+ len += scnprintf(buf + len, size - len,
+ "%20s :\n", "5GHz modal Header");
len = ar9003_dump_modal_eeprom(buf, len, size,
&eep->modalHeader5G);
goto out;
@@ -3479,8 +3482,8 @@ static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
PR_EEP("Rx Gain", pBase->txrxgain & 0xf);
PR_EEP("SW Reg", le32_to_cpu(pBase->swreg));
- len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
- ah->eeprom.ar9300_eep.macAddr);
+ len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+ ah->eeprom.ar9300_eep.macAddr);
out:
if (len > size)
len = size;
@@ -3656,9 +3659,23 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
if (AR_SREV_9565(ah)) {
if (common->bt_ant_diversity) {
regval |= (1 << AR_PHY_ANT_SW_RX_PROT_S);
+
+ REG_SET_BIT(ah, AR_PHY_RESTART,
+ AR_PHY_RESTART_ENABLE_DIV_M2FLAG);
+
+ /* Force WLAN LNA diversity ON */
+ REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV,
+ AR_BTCOEX_WL_LNADIV_FORCE_ON);
} else {
regval &= ~(1 << AR_PHY_ANT_DIV_LNADIV_S);
regval &= ~(1 << AR_PHY_ANT_SW_RX_PROT_S);
+
+ REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL,
+ (1 << AR_PHY_ANT_SW_RX_PROT_S));
+
+ /* Force WLAN LNA diversity OFF */
+ REG_CLR_BIT(ah, AR_BTCOEX_WL_LNADIV,
+ AR_BTCOEX_WL_LNADIV_FORCE_ON);
}
}
@@ -3669,7 +3686,8 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
regval &= (~AR_FAST_DIV_ENABLE);
regval |= ((value >> 7) & 0x1) << AR_FAST_DIV_ENABLE_S;
- if (AR_SREV_9485(ah) && common->bt_ant_diversity)
+ if ((AR_SREV_9485(ah) || AR_SREV_9565(ah))
+ && common->bt_ant_diversity)
regval |= AR_FAST_DIV_ENABLE;
REG_WRITE(ah, AR_PHY_CCK_DETECT, regval);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
index 75d4fb41962f..0e5daa58a4fc 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
@@ -52,6 +52,8 @@
#define AR9300_PAPRD_SCALE_2 0x70000000
#define AR9300_PAPRD_SCALE_2_S 28
+#define AR9300_EEP_ANTDIV_CONTROL_DEFAULT_VALUE 0xc9
+
/* Delta from which to start power to pdadc table */
/* This offset is used in both open loop and closed loop power control
* schemes. In open loop power control, it is not really needed, but for
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 608bb4824e2a..b07f164d65cf 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -364,6 +364,8 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9565_1p0_modes_fast_clock);
+ INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
+ ar9565_1p0_baseband_core_txfir_coeff_japan_2484);
} else {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
@@ -628,6 +630,9 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah)
else if (AR_SREV_9462_20(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9462_common_rx_gain_table_2p0);
+ else if (AR_SREV_9565(ah))
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ ar9565_1p0_Common_rx_gain_table);
else
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_rx_gain_table_2p2);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
index 8dd069259e7b..7b94a6c7db3d 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
@@ -753,9 +753,9 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT);
if (caldata) {
- caldata->done_txiqcal_once = false;
- caldata->done_txclcal_once = false;
- caldata->rtt_done = false;
+ clear_bit(TXIQCAL_DONE, &caldata->cal_flags);
+ clear_bit(TXCLCAL_DONE, &caldata->cal_flags);
+ clear_bit(RTT_DONE, &caldata->cal_flags);
}
if (!ath9k_hw_init_cal(ah, chan))
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index e897648d3233..0131ba2f5d51 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -627,11 +627,10 @@ static void ar9003_hw_override_ini(struct ath_hw *ah)
* MAC addr only will fail.
*/
val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE);
- REG_WRITE(ah, AR_PCU_MISC_MODE2,
- val | AR_AGG_WEP_ENABLE_FIX | AR_AGG_WEP_ENABLE);
-
- REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
- AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+ val |= AR_AGG_WEP_ENABLE_FIX |
+ AR_AGG_WEP_ENABLE |
+ AR_PCU_MISC_MODE2_CFP_IGNORE;
+ REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE,
@@ -1375,15 +1374,19 @@ static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah,
AR_PHY_ANT_FAST_DIV_BIAS_S;
if (AR_SREV_9330_11(ah)) {
+ antconf->lna1_lna2_switch_delta = -1;
antconf->lna1_lna2_delta = -9;
antconf->div_group = 1;
} else if (AR_SREV_9485(ah)) {
+ antconf->lna1_lna2_switch_delta = -1;
antconf->lna1_lna2_delta = -9;
antconf->div_group = 2;
} else if (AR_SREV_9565(ah)) {
- antconf->lna1_lna2_delta = -3;
+ antconf->lna1_lna2_switch_delta = 3;
+ antconf->lna1_lna2_delta = -9;
antconf->div_group = 3;
} else {
+ antconf->lna1_lna2_switch_delta = -1;
antconf->lna1_lna2_delta = -3;
antconf->div_group = 0;
}
@@ -1489,17 +1492,24 @@ static void ar9003_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable)
} else if (AR_SREV_9565(ah)) {
if (enable) {
REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL,
+ AR_ANT_DIV_ENABLE);
+ REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL,
(1 << AR_PHY_ANT_SW_RX_PROT_S));
- if (ah->curchan && IS_CHAN_2GHZ(ah->curchan))
- REG_SET_BIT(ah, AR_PHY_RESTART,
- AR_PHY_RESTART_ENABLE_DIV_M2FLAG);
+ REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
+ AR_FAST_DIV_ENABLE);
+ REG_SET_BIT(ah, AR_PHY_RESTART,
+ AR_PHY_RESTART_ENABLE_DIV_M2FLAG);
REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV,
AR_BTCOEX_WL_LNADIV_FORCE_ON);
} else {
- REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_ENABLE);
+ REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL,
+ AR_ANT_DIV_ENABLE);
REG_CLR_BIT(ah, AR_PHY_MC_GAIN_CTRL,
(1 << AR_PHY_ANT_SW_RX_PROT_S));
- REG_CLR_BIT(ah, AR_PHY_CCK_DETECT, AR_FAST_DIV_ENABLE);
+ REG_CLR_BIT(ah, AR_PHY_CCK_DETECT,
+ AR_FAST_DIV_ENABLE);
+ REG_CLR_BIT(ah, AR_PHY_RESTART,
+ AR_PHY_RESTART_ENABLE_DIV_M2FLAG);
REG_CLR_BIT(ah, AR_BTCOEX_WL_LNADIV,
AR_BTCOEX_WL_LNADIV_FORCE_ON);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index 6fd752321e36..fca624322dc8 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -343,8 +343,12 @@
#define AR_PHY_CCA_NOM_VAL_9462_2GHZ -127
#define AR_PHY_CCA_MIN_GOOD_VAL_9462_2GHZ -127
+#define AR_PHY_CCA_MAX_GOOD_VAL_9462_2GHZ -60
+#define AR_PHY_CCA_MAX_GOOD_VAL_9462_FCC_2GHZ -95
#define AR_PHY_CCA_NOM_VAL_9462_5GHZ -127
#define AR_PHY_CCA_MIN_GOOD_VAL_9462_5GHZ -127
+#define AR_PHY_CCA_MAX_GOOD_VAL_9462_5GHZ -60
+#define AR_PHY_CCA_MAX_GOOD_VAL_9462_FCC_5GHZ -100
#define AR_PHY_CCA_NOM_VAL_9330_2GHZ -118
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_rtt.c b/drivers/net/wireless/ath/ath9k/ar9003_rtt.c
index 74de3539c2c8..934418872e8e 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_rtt.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_rtt.c
@@ -118,6 +118,27 @@ void ar9003_hw_rtt_load_hist(struct ath_hw *ah)
}
}
+static void ar9003_hw_patch_rtt(struct ath_hw *ah, int index, int chain)
+{
+ int agc, caldac;
+
+ if (!test_bit(SW_PKDET_DONE, &ah->caldata->cal_flags))
+ return;
+
+ if ((index != 5) || (chain >= 2))
+ return;
+
+ agc = REG_READ_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+ AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE);
+ if (!agc)
+ return;
+
+ caldac = ah->caldata->caldac[chain];
+ ah->caldata->rtt_table[chain][index] &= 0xFFFF05FF;
+ caldac = (caldac & 0x20) | ((caldac & 0x1F) << 7);
+ ah->caldata->rtt_table[chain][index] |= (caldac << 4);
+}
+
static int ar9003_hw_rtt_fill_hist_entry(struct ath_hw *ah, u8 chain, u32 index)
{
u32 val;
@@ -155,13 +176,16 @@ void ar9003_hw_rtt_fill_hist(struct ath_hw *ah)
for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) {
ah->caldata->rtt_table[chain][i] =
ar9003_hw_rtt_fill_hist_entry(ah, chain, i);
+
+ ar9003_hw_patch_rtt(ah, i, chain);
+
ath_dbg(ath9k_hw_common(ah), CALIBRATE,
"RTT value at idx %d, chain %d is: 0x%x\n",
i, chain, ah->caldata->rtt_table[chain][i]);
}
}
- ah->caldata->rtt_done = true;
+ set_bit(RTT_DONE, &ah->caldata->cal_flags);
}
void ar9003_hw_rtt_clear_hist(struct ath_hw *ah)
@@ -176,7 +200,7 @@ void ar9003_hw_rtt_clear_hist(struct ath_hw *ah)
}
if (ah->caldata)
- ah->caldata->rtt_done = false;
+ clear_bit(RTT_DONE, &ah->caldata->cal_flags);
}
bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan)
@@ -186,11 +210,37 @@ bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan)
if (!ah->caldata)
return false;
- if (!ah->caldata->rtt_done)
+ if (test_bit(SW_PKDET_DONE, &ah->caldata->cal_flags)) {
+ if (IS_CHAN_2GHZ(chan)){
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(0),
+ AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR,
+ ah->caldata->caldac[0]);
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(1),
+ AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR,
+ ah->caldata->caldac[1]);
+ } else {
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(0),
+ AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR,
+ ah->caldata->caldac[0]);
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(1),
+ AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR,
+ ah->caldata->caldac[1]);
+ }
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(1),
+ AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1);
+ REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(0),
+ AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1);
+ }
+
+ if (!test_bit(RTT_DONE, &ah->caldata->cal_flags))
return false;
ar9003_hw_rtt_enable(ah);
- ar9003_hw_rtt_set_mask(ah, 0x10);
+
+ if (test_bit(SW_PKDET_DONE, &ah->caldata->cal_flags))
+ ar9003_hw_rtt_set_mask(ah, 0x30);
+ else
+ ar9003_hw_rtt_set_mask(ah, 0x10);
if (!ath9k_hw_rfbus_req(ah)) {
ath_err(ath9k_hw_common(ah), "Could not stop baseband\n");
diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
index 88ff1d7b53ab..6f899c692647 100644
--- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
@@ -20,7 +20,17 @@
/* AR9485 1.1 */
-#define ar9485_1_1_mac_postamble ar9300_2p2_mac_postamble
+static const u32 ar9485_1_1_mac_postamble[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+ {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+ {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+ {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+ {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+ {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+ {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+ {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = {
/* Addr allmodes */
@@ -34,6 +44,7 @@ static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = {
{0x00009e00, 0x037216a0},
{0x00009e04, 0x00182020},
{0x00009e18, 0x00000000},
+ {0x00009e20, 0x000003a8},
{0x00009e2c, 0x00004121},
{0x00009e44, 0x02282324},
{0x0000a000, 0x00060005},
@@ -174,7 +185,7 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
{0x0000a2e0, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
{0x0000a2e4, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
{0x0000a2e8, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050da, 0x000050da},
{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
@@ -200,14 +211,14 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
- {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
- {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
- {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x62001eee, 0x62001eee},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001ff6, 0x66001ff6},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6},
{0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
@@ -263,6 +274,11 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
static const u32 ar9485Modes_green_ob_db_tx_gain_1_1[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003},
+ {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a},
+ {0x0000a2dc, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+ {0x0000a2e0, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+ {0x0000a2e4, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
{0x0000a458, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
{0x0000a500, 0x00022200, 0x00022200, 0x00000006, 0x00000006},
@@ -297,6 +313,22 @@ static const u32 ar9485Modes_green_ob_db_tx_gain_1_1[][5] = {
{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a58c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a590, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a594, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a598, 0x00000000, 0x00000000, 0x01404501, 0x01404501},
+ {0x0000a59c, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
+ {0x0000a5a0, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
+ {0x0000a5a4, 0x00000000, 0x00000000, 0x02808803, 0x02808803},
+ {0x0000a5a8, 0x00000000, 0x00000000, 0x04c14b04, 0x04c14b04},
+ {0x0000a5ac, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+ {0x0000a5b0, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+ {0x0000a5b4, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+ {0x0000a5b8, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+ {0x0000a5bc, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
{0x0000b500, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
{0x0000b504, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
{0x0000b508, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
@@ -341,6 +373,100 @@ static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = {
{0x0000a2e0, 0x00000000, 0x00000000, 0xffc63a84, 0xffc63a84},
{0x0000a2e4, 0x00000000, 0x00000000, 0xfe0fc000, 0xfe0fc000},
{0x0000a2e8, 0x00000000, 0x00000000, 0xfff00000, 0xfff00000},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050da, 0x000050da},
+ {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+ {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+ {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+ {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+ {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+ {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+ {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+ {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+ {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+ {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+ {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+ {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+ {0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
+ {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
+ {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x62001eee, 0x62001eee},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001ff6, 0x66001ff6},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001ff6, 0x66001ff6},
+ {0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a58c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a590, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a594, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a598, 0x00000000, 0x00000000, 0x01404501, 0x01404501},
+ {0x0000a59c, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
+ {0x0000a5a0, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
+ {0x0000a5a4, 0x00000000, 0x00000000, 0x02808803, 0x02808803},
+ {0x0000a5a8, 0x00000000, 0x00000000, 0x04c14b04, 0x04c14b04},
+ {0x0000a5ac, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+ {0x0000a5b0, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+ {0x0000a5b4, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+ {0x0000a5b8, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+ {0x0000a5bc, 0x00000000, 0x00000000, 0x04c15305, 0x04c15305},
+ {0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+ {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
+
+static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+ {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a},
+ {0x0000a2dc, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+ {0x0000a2e0, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+ {0x0000a2e4, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0xfe2d3552, 0xfe2d3552},
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
@@ -427,7 +553,7 @@ static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = {
{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
};
-static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = {
+static const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a},
@@ -521,12 +647,15 @@ static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = {
{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
};
-#define ar9485_modes_lowest_ob_db_tx_gain_1_1 ar9485Modes_low_ob_db_tx_gain_1_1
-
static const u32 ar9485Modes_green_spur_ob_db_tx_gain_1_1[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003},
- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+ {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0x7999a83a, 0x7999a83a},
+ {0x0000a2dc, 0x00000000, 0x00000000, 0xffad452a, 0xffad452a},
+ {0x0000a2e0, 0x00000000, 0x00000000, 0xffc98634, 0xffc98634},
+ {0x0000a2e4, 0x00000000, 0x00000000, 0xfff60780, 0xfff60780},
+ {0x0000a2e8, 0x00000000, 0x00000000, 0xfffff800, 0xfffff800},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
{0x0000a458, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
{0x0000a500, 0x00022200, 0x00022200, 0x00000006, 0x00000006},
{0x0000a504, 0x05062002, 0x05062002, 0x03000201, 0x03000201},
@@ -543,23 +672,39 @@ static const u32 ar9485Modes_green_spur_ob_db_tx_gain_1_1[][5] = {
{0x0000a530, 0x48023ec6, 0x48023ec6, 0x310006e0, 0x310006e0},
{0x0000a534, 0x4d023f01, 0x4d023f01, 0x330006e0, 0x330006e0},
{0x0000a538, 0x53023f4b, 0x53023f4b, 0x3e0008e3, 0x3e0008e3},
- {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x410008e5, 0x410008e5},
- {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x430008e6, 0x430008e6},
- {0x0000a544, 0x6502feca, 0x6502feca, 0x4a0008ec, 0x4a0008ec},
- {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4e0008f1, 0x4e0008f1},
- {0x0000a54c, 0x7203feca, 0x7203feca, 0x520008f3, 0x520008f3},
- {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x54000eed, 0x54000eed},
- {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x58000ef1, 0x58000ef1},
- {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5c000ef3, 0x5c000ef3},
- {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x60000ef5, 0x60000ef5},
- {0x0000a560, 0x900fff0b, 0x900fff0b, 0x62000ef6, 0x62000ef6},
- {0x0000a564, 0x960fffcb, 0x960fffcb, 0x62000ef6, 0x62000ef6},
- {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6},
- {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6},
- {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6},
- {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6},
- {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6},
- {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6},
+ {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x430008e6, 0x430008e6},
+ {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4a0008ec, 0x4a0008ec},
+ {0x0000a544, 0x6502feca, 0x6502feca, 0x4e0008f1, 0x4e0008f1},
+ {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x520008f3, 0x520008f3},
+ {0x0000a54c, 0x7203feca, 0x7203feca, 0x54000eed, 0x54000eed},
+ {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x58000ef1, 0x58000ef1},
+ {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5c000ef3, 0x5c000ef3},
+ {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x62000ef6, 0x62000ef6},
+ {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001ff0, 0x66001ff0},
+ {0x0000a560, 0x900fff0b, 0x900fff0b, 0x68001ff6, 0x68001ff6},
+ {0x0000a564, 0x960fffcb, 0x960fffcb, 0x68001ff6, 0x68001ff6},
+ {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x68001ff6, 0x68001ff6},
+ {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x68001ff6, 0x68001ff6},
+ {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x68001ff6, 0x68001ff6},
+ {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x68001ff6, 0x68001ff6},
+ {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x68001ff6, 0x68001ff6},
+ {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x68001ff6, 0x68001ff6},
+ {0x0000a580, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a584, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a588, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000a58c, 0x00000000, 0x00000000, 0x01804000, 0x01804000},
+ {0x0000a590, 0x00000000, 0x00000000, 0x02808a02, 0x02808a02},
+ {0x0000a594, 0x00000000, 0x00000000, 0x0340ca02, 0x0340ca02},
+ {0x0000a598, 0x00000000, 0x00000000, 0x0340cd03, 0x0340cd03},
+ {0x0000a59c, 0x00000000, 0x00000000, 0x0340cd03, 0x0340cd03},
+ {0x0000a5a0, 0x00000000, 0x00000000, 0x06415304, 0x06415304},
+ {0x0000a5a4, 0x00000000, 0x00000000, 0x04c11905, 0x04c11905},
+ {0x0000a5a8, 0x00000000, 0x00000000, 0x06415905, 0x06415905},
+ {0x0000a5ac, 0x00000000, 0x00000000, 0x06415905, 0x06415905},
+ {0x0000a5b0, 0x00000000, 0x00000000, 0x06415905, 0x06415905},
+ {0x0000a5b4, 0x00000000, 0x00000000, 0x06415905, 0x06415905},
+ {0x0000a5b8, 0x00000000, 0x00000000, 0x06415905, 0x06415905},
+ {0x0000a5bc, 0x00000000, 0x00000000, 0x06415905, 0x06415905},
{0x0000b500, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
{0x0000b504, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
{0x0000b508, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
@@ -823,6 +968,7 @@ static const u32 ar9485_common_rx_gain_1_1[][2] = {
{0x00009e00, 0x03721b20},
{0x00009e04, 0x00082020},
{0x00009e18, 0x0300501e},
+ {0x00009e20, 0x000003ba},
{0x00009e2c, 0x00002e21},
{0x00009e44, 0x02182324},
{0x0000a000, 0x00060005},
@@ -1001,7 +1147,6 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = {
{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e},
{0x00009e14, 0x31395d53, 0x31396053, 0x312e6053, 0x312e5d53},
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
- {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
{0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
@@ -1020,7 +1165,7 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = {
{0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0},
{0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18},
+ {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
{0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982},
{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
@@ -1206,6 +1351,11 @@ static const u32 ar9485_1_1_mac_core[][2] = {
{0x000083d0, 0x000301ff},
};
-#define ar9485_1_1_baseband_core_txfir_coeff_japan_2484 ar9462_2p0_baseband_core_txfir_coeff_japan_2484
+static const u32 ar9485_1_1_baseband_core_txfir_coeff_japan_2484[][2] = {
+ /* Addr allmodes */
+ {0x0000a398, 0x00000000},
+ {0x0000a39c, 0x6f7f0301},
+ {0x0000a3a0, 0xca9228ee},
+};
#endif /* INITVALS_9485_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
index e85a8b076c22..a8c757b6124f 100644
--- a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
@@ -272,9 +272,9 @@ static const u32 ar9565_1p0_baseband_core[][2] = {
{0x0000a398, 0x001f0e0f},
{0x0000a39c, 0x0075393f},
{0x0000a3a0, 0xb79f6427},
- {0x0000a3a4, 0x00000000},
- {0x0000a3a8, 0xaaaaaaaa},
- {0x0000a3ac, 0x3c466478},
+ {0x0000a3a4, 0x00000011},
+ {0x0000a3a8, 0xaaaaaa6e},
+ {0x0000a3ac, 0x3c466455},
{0x0000a3c0, 0x20202020},
{0x0000a3c4, 0x22222220},
{0x0000a3c8, 0x20200020},
@@ -295,11 +295,11 @@ static const u32 ar9565_1p0_baseband_core[][2] = {
{0x0000a404, 0x00000000},
{0x0000a408, 0x0e79e5c6},
{0x0000a40c, 0x00820820},
- {0x0000a414, 0x1ce739ce},
+ {0x0000a414, 0x1ce739c5},
{0x0000a418, 0x2d001dce},
- {0x0000a41c, 0x1ce739ce},
+ {0x0000a41c, 0x1ce739c5},
{0x0000a420, 0x000001ce},
- {0x0000a424, 0x1ce739ce},
+ {0x0000a424, 0x1ce739c5},
{0x0000a428, 0x000001ce},
{0x0000a42c, 0x1ce739ce},
{0x0000a430, 0x1ce739ce},
@@ -351,9 +351,9 @@ static const u32 ar9565_1p0_baseband_postamble[][5] = {
{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
- {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+ {0x00009e20, 0x000003b5, 0x000003b5, 0x000003a4, 0x000003a4},
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
- {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222},
+ {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946220, 0xcf946220},
{0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
@@ -452,6 +452,7 @@ static const u32 ar9565_1p0_Common_rx_gain_table[][2] = {
/* Addr allmodes */
{0x00004050, 0x00300300},
{0x0000406c, 0x00100000},
+ {0x00009e20, 0x000003b6},
{0x0000a000, 0x00010000},
{0x0000a004, 0x00030002},
{0x0000a008, 0x00050004},
@@ -1230,4 +1231,11 @@ static const u32 ar9565_1p0_modes_high_power_tx_gain_table[][5] = {
{0x00016054, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
};
+static const u32 ar9565_1p0_baseband_core_txfir_coeff_japan_2484[][2] = {
+ /* Addr allmodes */
+ {0x0000a398, 0x00000000},
+ {0x0000a39c, 0x6f7f0301},
+ {0x0000a3a0, 0xca9228ee},
+};
+
#endif /* INITVALS_9565_1P0_H */
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 2ee35f677c0e..15afde3c348b 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -459,8 +459,8 @@ void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
#define ATH_DUMP_BTCOEX(_s, _val) \
do { \
- len += snprintf(buf + len, size - len, \
- "%20s : %10d\n", _s, (_val)); \
+ len += scnprintf(buf + len, size - len, \
+ "%20s : %10d\n", _s, (_val)); \
} while (0)
enum bt_op_flags {
@@ -581,7 +581,6 @@ static inline void ath_fill_led_pin(struct ath_softc *sc)
#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO_LOW_RSSI 50
#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2_LOW_RSSI 50
-#define ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA -1
#define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4
#define ATH_ANT_DIV_COMB_LNA1_DELTA_MID -2
#define ATH_ANT_DIV_COMB_LNA1_DELTA_LOW 2
@@ -626,12 +625,15 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs);
/* Main driver core */
/********************/
-#define ATH9K_PCI_CUS198 0x0001
-#define ATH9K_PCI_CUS230 0x0002
-#define ATH9K_PCI_CUS217 0x0004
-#define ATH9K_PCI_WOW 0x0008
-#define ATH9K_PCI_BT_ANT_DIV 0x0010
-#define ATH9K_PCI_D3_L1_WAR 0x0020
+#define ATH9K_PCI_CUS198 0x0001
+#define ATH9K_PCI_CUS230 0x0002
+#define ATH9K_PCI_CUS217 0x0004
+#define ATH9K_PCI_CUS252 0x0008
+#define ATH9K_PCI_WOW 0x0010
+#define ATH9K_PCI_BT_ANT_DIV 0x0020
+#define ATH9K_PCI_D3_L1_WAR 0x0040
+#define ATH9K_PCI_AR9565_1ANT 0x0080
+#define ATH9K_PCI_AR9565_2ANT 0x0100
/*
* Default cache line size, in bytes.
@@ -952,7 +954,7 @@ void ath9k_ps_restore(struct ath_softc *sc);
u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate);
void ath_start_rfkill_poll(struct ath_softc *sc);
-extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw);
+void ath9k_rfkill_poll_state(struct ieee80211_hw *hw);
void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ath9k_vif_iter_data *iter_data);
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index b5c16b3a37b9..17be35392bb4 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -334,6 +334,8 @@ void ath9k_beacon_tasklet(unsigned long data)
if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
sc->beacon.bmisscnt++;
+ ath9k_hw_check_nav(ah);
+
if (!ath9k_hw_check_alive(ah))
ieee80211_queue_work(sc->hw, &sc->hw_check_work);
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 5e8219a91e25..d438a0341e68 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -119,7 +119,7 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
ath_dbg(common, CALIBRATE,
"NFmid[%d] (%d) > MAX (%d), %s\n",
i, h[i].privNF, limit->max,
- (cal->nfcal_interference ?
+ (test_bit(NFCAL_INTF, &cal->cal_flags) ?
"not corrected (due to interference)" :
"correcting to MAX"));
@@ -130,7 +130,7 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
* we bypass this limit here in order to better deal
* with our environment.
*/
- if (!cal->nfcal_interference)
+ if (!test_bit(NFCAL_INTF, &cal->cal_flags))
h[i].privNF = limit->max;
}
}
@@ -141,7 +141,7 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
* Re-enable the enforcement of the NF maximum again.
*/
if (!high_nf_mid)
- cal->nfcal_interference = false;
+ clear_bit(NFCAL_INTF, &cal->cal_flags);
}
static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah,
@@ -220,7 +220,7 @@ EXPORT_SYMBOL(ath9k_hw_reset_calvalid);
void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update)
{
if (ah->caldata)
- ah->caldata->nfcal_pending = true;
+ set_bit(NFCAL_PENDING, &ah->caldata->cal_flags);
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
AR_PHY_AGC_CONTROL_ENABLE_NF);
@@ -391,7 +391,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
}
h = caldata->nfCalHist;
- caldata->nfcal_pending = false;
+ clear_bit(NFCAL_PENDING, &caldata->cal_flags);
ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray);
chan->noisefloor = h[0].privNF;
ah->noise = ath9k_hw_getchan_noise(ah, chan);
@@ -437,12 +437,12 @@ void ath9k_hw_bstuck_nfcal(struct ath_hw *ah)
* the baseband update the internal NF value itself, similar to
* what is being done after a full reset.
*/
- if (!caldata->nfcal_pending)
+ if (!test_bit(NFCAL_PENDING, &caldata->cal_flags))
ath9k_hw_start_nfcal(ah, true);
else if (!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF))
ath9k_hw_getnf(ah, ah->curchan);
- caldata->nfcal_interference = true;
+ set_bit(NFCAL_INTF, &caldata->cal_flags);
}
EXPORT_SYMBOL(ath9k_hw_bstuck_nfcal);
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index c088744a6bfb..1be2c787aac9 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -104,37 +104,37 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf,
return -ENOMEM;
if (common->disable_ani) {
- len += snprintf(buf + len, size - len, "%s: %s\n",
- "ANI", "DISABLED");
+ len += scnprintf(buf + len, size - len, "%s: %s\n",
+ "ANI", "DISABLED");
goto exit;
}
- len += snprintf(buf + len, size - len, "%15s: %s\n",
- "ANI", "ENABLED");
- len += snprintf(buf + len, size - len, "%15s: %u\n",
- "ANI RESET", ah->stats.ast_ani_reset);
- len += snprintf(buf + len, size - len, "%15s: %u\n",
- "SPUR UP", ah->stats.ast_ani_spurup);
- len += snprintf(buf + len, size - len, "%15s: %u\n",
- "SPUR DOWN", ah->stats.ast_ani_spurup);
- len += snprintf(buf + len, size - len, "%15s: %u\n",
- "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon);
- len += snprintf(buf + len, size - len, "%15s: %u\n",
- "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff);
- len += snprintf(buf + len, size - len, "%15s: %u\n",
- "MRC-CCK ON", ah->stats.ast_ani_ccklow);
- len += snprintf(buf + len, size - len, "%15s: %u\n",
- "MRC-CCK OFF", ah->stats.ast_ani_cckhigh);
- len += snprintf(buf + len, size - len, "%15s: %u\n",
- "FIR-STEP UP", ah->stats.ast_ani_stepup);
- len += snprintf(buf + len, size - len, "%15s: %u\n",
- "FIR-STEP DOWN", ah->stats.ast_ani_stepdown);
- len += snprintf(buf + len, size - len, "%15s: %u\n",
- "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero);
- len += snprintf(buf + len, size - len, "%15s: %u\n",
- "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs);
- len += snprintf(buf + len, size - len, "%15s: %u\n",
- "CCK ERRORS", ah->stats.ast_ani_cckerrs);
+ len += scnprintf(buf + len, size - len, "%15s: %s\n",
+ "ANI", "ENABLED");
+ len += scnprintf(buf + len, size - len, "%15s: %u\n",
+ "ANI RESET", ah->stats.ast_ani_reset);
+ len += scnprintf(buf + len, size - len, "%15s: %u\n",
+ "SPUR UP", ah->stats.ast_ani_spurup);
+ len += scnprintf(buf + len, size - len, "%15s: %u\n",
+ "SPUR DOWN", ah->stats.ast_ani_spurup);
+ len += scnprintf(buf + len, size - len, "%15s: %u\n",
+ "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon);
+ len += scnprintf(buf + len, size - len, "%15s: %u\n",
+ "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff);
+ len += scnprintf(buf + len, size - len, "%15s: %u\n",
+ "MRC-CCK ON", ah->stats.ast_ani_ccklow);
+ len += scnprintf(buf + len, size - len, "%15s: %u\n",
+ "MRC-CCK OFF", ah->stats.ast_ani_cckhigh);
+ len += scnprintf(buf + len, size - len, "%15s: %u\n",
+ "FIR-STEP UP", ah->stats.ast_ani_stepup);
+ len += scnprintf(buf + len, size - len, "%15s: %u\n",
+ "FIR-STEP DOWN", ah->stats.ast_ani_stepdown);
+ len += scnprintf(buf + len, size - len, "%15s: %u\n",
+ "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero);
+ len += scnprintf(buf + len, size - len, "%15s: %u\n",
+ "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs);
+ len += scnprintf(buf + len, size - len, "%15s: %u\n",
+ "CCK ERRORS", ah->stats.ast_ani_cckerrs);
exit:
if (len > size)
len = size;
@@ -280,70 +280,70 @@ static ssize_t read_file_antenna_diversity(struct file *file,
return -ENOMEM;
if (!(pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)) {
- len += snprintf(buf + len, size - len, "%s\n",
- "Antenna Diversity Combining is disabled");
+ len += scnprintf(buf + len, size - len, "%s\n",
+ "Antenna Diversity Combining is disabled");
goto exit;
}
ath9k_ps_wakeup(sc);
ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf);
- len += snprintf(buf + len, size - len, "Current MAIN config : %s\n",
- lna_conf_str[div_ant_conf.main_lna_conf]);
- len += snprintf(buf + len, size - len, "Current ALT config : %s\n",
- lna_conf_str[div_ant_conf.alt_lna_conf]);
- len += snprintf(buf + len, size - len, "Average MAIN RSSI : %d\n",
- as_main->rssi_avg);
- len += snprintf(buf + len, size - len, "Average ALT RSSI : %d\n\n",
- as_alt->rssi_avg);
+ len += scnprintf(buf + len, size - len, "Current MAIN config : %s\n",
+ lna_conf_str[div_ant_conf.main_lna_conf]);
+ len += scnprintf(buf + len, size - len, "Current ALT config : %s\n",
+ lna_conf_str[div_ant_conf.alt_lna_conf]);
+ len += scnprintf(buf + len, size - len, "Average MAIN RSSI : %d\n",
+ as_main->rssi_avg);
+ len += scnprintf(buf + len, size - len, "Average ALT RSSI : %d\n\n",
+ as_alt->rssi_avg);
ath9k_ps_restore(sc);
- len += snprintf(buf + len, size - len, "Packet Receive Cnt:\n");
- len += snprintf(buf + len, size - len, "-------------------\n");
-
- len += snprintf(buf + len, size - len, "%30s%15s\n",
- "MAIN", "ALT");
- len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
- "TOTAL COUNT",
- as_main->recv_cnt,
- as_alt->recv_cnt);
- len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
- "LNA1",
- as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1],
- as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1]);
- len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
- "LNA2",
- as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2],
- as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2]);
- len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
- "LNA1 + LNA2",
- as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2],
- as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]);
- len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
- "LNA1 - LNA2",
- as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2],
- as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]);
-
- len += snprintf(buf + len, size - len, "\nLNA Config Attempts:\n");
- len += snprintf(buf + len, size - len, "--------------------\n");
-
- len += snprintf(buf + len, size - len, "%30s%15s\n",
- "MAIN", "ALT");
- len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
- "LNA1",
- as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1],
- as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1]);
- len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
- "LNA2",
- as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2],
- as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2]);
- len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
- "LNA1 + LNA2",
- as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2],
- as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]);
- len += snprintf(buf + len, size - len, "%-14s:%15d%15d\n",
- "LNA1 - LNA2",
- as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2],
- as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]);
+ len += scnprintf(buf + len, size - len, "Packet Receive Cnt:\n");
+ len += scnprintf(buf + len, size - len, "-------------------\n");
+
+ len += scnprintf(buf + len, size - len, "%30s%15s\n",
+ "MAIN", "ALT");
+ len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+ "TOTAL COUNT",
+ as_main->recv_cnt,
+ as_alt->recv_cnt);
+ len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+ "LNA1",
+ as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1],
+ as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1]);
+ len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+ "LNA2",
+ as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2],
+ as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA2]);
+ len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+ "LNA1 + LNA2",
+ as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2],
+ as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]);
+ len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+ "LNA1 - LNA2",
+ as_main->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2],
+ as_alt->lna_recv_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]);
+
+ len += scnprintf(buf + len, size - len, "\nLNA Config Attempts:\n");
+ len += scnprintf(buf + len, size - len, "--------------------\n");
+
+ len += scnprintf(buf + len, size - len, "%30s%15s\n",
+ "MAIN", "ALT");
+ len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+ "LNA1",
+ as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1],
+ as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1]);
+ len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+ "LNA2",
+ as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2],
+ as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA2]);
+ len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+ "LNA1 + LNA2",
+ as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2],
+ as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2]);
+ len += scnprintf(buf + len, size - len, "%-14s:%15d%15d\n",
+ "LNA1 - LNA2",
+ as_main->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2],
+ as_alt->lna_attempt_cnt[ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2]);
exit:
if (len > size)
@@ -385,21 +385,21 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
(AR_MACMISC_MISC_OBS_BUS_1 <<
AR_MACMISC_MISC_OBS_BUS_MSB_S)));
- len += snprintf(buf + len, DMA_BUF_LEN - len,
- "Raw DMA Debug values:\n");
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
+ "Raw DMA Debug values:\n");
for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
if (i % 4 == 0)
- len += snprintf(buf + len, DMA_BUF_LEN - len, "\n");
+ len += scnprintf(buf + len, DMA_BUF_LEN - len, "\n");
val[i] = REG_READ_D(ah, AR_DMADBG_0 + (i * sizeof(u32)));
- len += snprintf(buf + len, DMA_BUF_LEN - len, "%d: %08x ",
- i, val[i]);
+ len += scnprintf(buf + len, DMA_BUF_LEN - len, "%d: %08x ",
+ i, val[i]);
}
- len += snprintf(buf + len, DMA_BUF_LEN - len, "\n\n");
- len += snprintf(buf + len, DMA_BUF_LEN - len,
- "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
+ len += scnprintf(buf + len, DMA_BUF_LEN - len, "\n\n");
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
+ "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) {
if (i == 8) {
@@ -412,39 +412,39 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf,
dcuBase++;
}
- len += snprintf(buf + len, DMA_BUF_LEN - len,
- "%2d %2x %1x %2x %2x\n",
- i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
- (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
- val[2] & (0x7 << (i * 3)) >> (i * 3),
- (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
+ "%2d %2x %1x %2x %2x\n",
+ i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
+ (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
+ val[2] & (0x7 << (i * 3)) >> (i * 3),
+ (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
}
- len += snprintf(buf + len, DMA_BUF_LEN - len, "\n");
+ len += scnprintf(buf + len, DMA_BUF_LEN - len, "\n");
- len += snprintf(buf + len, DMA_BUF_LEN - len,
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
"qcu_stitch state: %2x qcu_fetch state: %2x\n",
(val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
- len += snprintf(buf + len, DMA_BUF_LEN - len,
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
"qcu_complete state: %2x dcu_complete state: %2x\n",
(val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
- len += snprintf(buf + len, DMA_BUF_LEN - len,
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
"dcu_arb state: %2x dcu_fp state: %2x\n",
(val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
- len += snprintf(buf + len, DMA_BUF_LEN - len,
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
"chan_idle_dur: %3d chan_idle_dur_valid: %1d\n",
(val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
- len += snprintf(buf + len, DMA_BUF_LEN - len,
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
"txfifo_valid_0: %1d txfifo_valid_1: %1d\n",
(val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
- len += snprintf(buf + len, DMA_BUF_LEN - len,
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
"txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n",
(val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
- len += snprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x\n",
- REG_READ_D(ah, AR_OBS_BUS_1));
- len += snprintf(buf + len, DMA_BUF_LEN - len,
- "AR_CR: 0x%x\n", REG_READ_D(ah, AR_CR));
+ len += scnprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x\n",
+ REG_READ_D(ah, AR_OBS_BUS_1));
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
+ "AR_CR: 0x%x\n", REG_READ_D(ah, AR_CR));
ath9k_ps_restore(sc);
@@ -530,9 +530,9 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
#define PR_IS(a, s) \
do { \
- len += snprintf(buf + len, mxlen - len, \
- "%21s: %10u\n", a, \
- sc->debug.stats.istats.s); \
+ len += scnprintf(buf + len, mxlen - len, \
+ "%21s: %10u\n", a, \
+ sc->debug.stats.istats.s); \
} while (0)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
@@ -563,8 +563,8 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
PR_IS("GENTIMER", gen_timer);
PR_IS("TOTAL", total);
- len += snprintf(buf + len, mxlen - len,
- "SYNC_CAUSE stats:\n");
+ len += scnprintf(buf + len, mxlen - len,
+ "SYNC_CAUSE stats:\n");
PR_IS("Sync-All", sync_cause_all);
PR_IS("RTC-IRQ", sync_rtc_irq);
@@ -655,16 +655,16 @@ static ssize_t print_queue(struct ath_softc *sc, struct ath_txq *txq,
ath_txq_lock(sc, txq);
- len += snprintf(buf + len, size - len, "%s: %d ",
- "qnum", txq->axq_qnum);
- len += snprintf(buf + len, size - len, "%s: %2d ",
- "qdepth", txq->axq_depth);
- len += snprintf(buf + len, size - len, "%s: %2d ",
- "ampdu-depth", txq->axq_ampdu_depth);
- len += snprintf(buf + len, size - len, "%s: %3d ",
- "pending", txq->pending_frames);
- len += snprintf(buf + len, size - len, "%s: %d\n",
- "stopped", txq->stopped);
+ len += scnprintf(buf + len, size - len, "%s: %d ",
+ "qnum", txq->axq_qnum);
+ len += scnprintf(buf + len, size - len, "%s: %2d ",
+ "qdepth", txq->axq_depth);
+ len += scnprintf(buf + len, size - len, "%s: %2d ",
+ "ampdu-depth", txq->axq_ampdu_depth);
+ len += scnprintf(buf + len, size - len, "%s: %3d ",
+ "pending", txq->pending_frames);
+ len += scnprintf(buf + len, size - len, "%s: %d\n",
+ "stopped", txq->stopped);
ath_txq_unlock(sc, txq);
return len;
@@ -687,11 +687,11 @@ static ssize_t read_file_queues(struct file *file, char __user *user_buf,
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
txq = sc->tx.txq_map[i];
- len += snprintf(buf + len, size - len, "(%s): ", qname[i]);
+ len += scnprintf(buf + len, size - len, "(%s): ", qname[i]);
len += print_queue(sc, txq, buf + len, size - len);
}
- len += snprintf(buf + len, size - len, "(CAB): ");
+ len += scnprintf(buf + len, size - len, "(CAB): ");
len += print_queue(sc, sc->beacon.cabq, buf + len, size - len);
if (len > size)
@@ -716,80 +716,82 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
unsigned int reg;
u32 rxfilter;
- len += snprintf(buf + len, sizeof(buf) - len,
- "BSSID: %pM\n", common->curbssid);
- len += snprintf(buf + len, sizeof(buf) - len,
- "BSSID-MASK: %pM\n", common->bssidmask);
- len += snprintf(buf + len, sizeof(buf) - len,
- "OPMODE: %s\n", ath_opmode_to_string(sc->sc_ah->opmode));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "BSSID: %pM\n", common->curbssid);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "BSSID-MASK: %pM\n", common->bssidmask);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "OPMODE: %s\n",
+ ath_opmode_to_string(sc->sc_ah->opmode));
ath9k_ps_wakeup(sc);
rxfilter = ath9k_hw_getrxfilter(sc->sc_ah);
ath9k_ps_restore(sc);
- len += snprintf(buf + len, sizeof(buf) - len,
- "RXFILTER: 0x%x", rxfilter);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "RXFILTER: 0x%x", rxfilter);
if (rxfilter & ATH9K_RX_FILTER_UCAST)
- len += snprintf(buf + len, sizeof(buf) - len, " UCAST");
+ len += scnprintf(buf + len, sizeof(buf) - len, " UCAST");
if (rxfilter & ATH9K_RX_FILTER_MCAST)
- len += snprintf(buf + len, sizeof(buf) - len, " MCAST");
+ len += scnprintf(buf + len, sizeof(buf) - len, " MCAST");
if (rxfilter & ATH9K_RX_FILTER_BCAST)
- len += snprintf(buf + len, sizeof(buf) - len, " BCAST");
+ len += scnprintf(buf + len, sizeof(buf) - len, " BCAST");
if (rxfilter & ATH9K_RX_FILTER_CONTROL)
- len += snprintf(buf + len, sizeof(buf) - len, " CONTROL");
+ len += scnprintf(buf + len, sizeof(buf) - len, " CONTROL");
if (rxfilter & ATH9K_RX_FILTER_BEACON)
- len += snprintf(buf + len, sizeof(buf) - len, " BEACON");
+ len += scnprintf(buf + len, sizeof(buf) - len, " BEACON");
if (rxfilter & ATH9K_RX_FILTER_PROM)
- len += snprintf(buf + len, sizeof(buf) - len, " PROM");
+ len += scnprintf(buf + len, sizeof(buf) - len, " PROM");
if (rxfilter & ATH9K_RX_FILTER_PROBEREQ)
- len += snprintf(buf + len, sizeof(buf) - len, " PROBEREQ");
+ len += scnprintf(buf + len, sizeof(buf) - len, " PROBEREQ");
if (rxfilter & ATH9K_RX_FILTER_PHYERR)
- len += snprintf(buf + len, sizeof(buf) - len, " PHYERR");
+ len += scnprintf(buf + len, sizeof(buf) - len, " PHYERR");
if (rxfilter & ATH9K_RX_FILTER_MYBEACON)
- len += snprintf(buf + len, sizeof(buf) - len, " MYBEACON");
+ len += scnprintf(buf + len, sizeof(buf) - len, " MYBEACON");
if (rxfilter & ATH9K_RX_FILTER_COMP_BAR)
- len += snprintf(buf + len, sizeof(buf) - len, " COMP_BAR");
+ len += scnprintf(buf + len, sizeof(buf) - len, " COMP_BAR");
if (rxfilter & ATH9K_RX_FILTER_PSPOLL)
- len += snprintf(buf + len, sizeof(buf) - len, " PSPOLL");
+ len += scnprintf(buf + len, sizeof(buf) - len, " PSPOLL");
if (rxfilter & ATH9K_RX_FILTER_PHYRADAR)
- len += snprintf(buf + len, sizeof(buf) - len, " PHYRADAR");
+ len += scnprintf(buf + len, sizeof(buf) - len, " PHYRADAR");
if (rxfilter & ATH9K_RX_FILTER_MCAST_BCAST_ALL)
- len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL");
+ len += scnprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL");
if (rxfilter & ATH9K_RX_FILTER_CONTROL_WRAPPER)
- len += snprintf(buf + len, sizeof(buf) - len, " CONTROL_WRAPPER");
+ len += scnprintf(buf + len, sizeof(buf) - len, " CONTROL_WRAPPER");
- len += snprintf(buf + len, sizeof(buf) - len, "\n");
+ len += scnprintf(buf + len, sizeof(buf) - len, "\n");
reg = sc->sc_ah->imask;
- len += snprintf(buf + len, sizeof(buf) - len, "INTERRUPT-MASK: 0x%x", reg);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "INTERRUPT-MASK: 0x%x", reg);
if (reg & ATH9K_INT_SWBA)
- len += snprintf(buf + len, sizeof(buf) - len, " SWBA");
+ len += scnprintf(buf + len, sizeof(buf) - len, " SWBA");
if (reg & ATH9K_INT_BMISS)
- len += snprintf(buf + len, sizeof(buf) - len, " BMISS");
+ len += scnprintf(buf + len, sizeof(buf) - len, " BMISS");
if (reg & ATH9K_INT_CST)
- len += snprintf(buf + len, sizeof(buf) - len, " CST");
+ len += scnprintf(buf + len, sizeof(buf) - len, " CST");
if (reg & ATH9K_INT_RX)
- len += snprintf(buf + len, sizeof(buf) - len, " RX");
+ len += scnprintf(buf + len, sizeof(buf) - len, " RX");
if (reg & ATH9K_INT_RXHP)
- len += snprintf(buf + len, sizeof(buf) - len, " RXHP");
+ len += scnprintf(buf + len, sizeof(buf) - len, " RXHP");
if (reg & ATH9K_INT_RXLP)
- len += snprintf(buf + len, sizeof(buf) - len, " RXLP");
+ len += scnprintf(buf + len, sizeof(buf) - len, " RXLP");
if (reg & ATH9K_INT_BB_WATCHDOG)
- len += snprintf(buf + len, sizeof(buf) - len, " BB_WATCHDOG");
+ len += scnprintf(buf + len, sizeof(buf) - len, " BB_WATCHDOG");
- len += snprintf(buf + len, sizeof(buf) - len, "\n");
+ len += scnprintf(buf + len, sizeof(buf) - len, "\n");
ath9k_calculate_iter_data(hw, NULL, &iter_data);
- len += snprintf(buf + len, sizeof(buf) - len,
- "VIF-COUNTS: AP: %i STA: %i MESH: %i WDS: %i"
- " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n",
- iter_data.naps, iter_data.nstations, iter_data.nmeshes,
- iter_data.nwds, iter_data.nadhocs,
- sc->nvifs, sc->nbcnvifs);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "VIF-COUNTS: AP: %i STA: %i MESH: %i WDS: %i"
+ " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n",
+ iter_data.naps, iter_data.nstations, iter_data.nmeshes,
+ iter_data.nwds, iter_data.nadhocs,
+ sc->nvifs, sc->nbcnvifs);
if (len > sizeof(buf))
len = sizeof(buf);
@@ -805,27 +807,27 @@ static ssize_t read_file_reset(struct file *file, char __user *user_buf,
char buf[512];
unsigned int len = 0;
- len += snprintf(buf + len, sizeof(buf) - len,
- "%17s: %2d\n", "Baseband Hang",
- sc->debug.stats.reset[RESET_TYPE_BB_HANG]);
- len += snprintf(buf + len, sizeof(buf) - len,
- "%17s: %2d\n", "Baseband Watchdog",
- sc->debug.stats.reset[RESET_TYPE_BB_WATCHDOG]);
- len += snprintf(buf + len, sizeof(buf) - len,
- "%17s: %2d\n", "Fatal HW Error",
- sc->debug.stats.reset[RESET_TYPE_FATAL_INT]);
- len += snprintf(buf + len, sizeof(buf) - len,
- "%17s: %2d\n", "TX HW error",
- sc->debug.stats.reset[RESET_TYPE_TX_ERROR]);
- len += snprintf(buf + len, sizeof(buf) - len,
- "%17s: %2d\n", "TX Path Hang",
- sc->debug.stats.reset[RESET_TYPE_TX_HANG]);
- len += snprintf(buf + len, sizeof(buf) - len,
- "%17s: %2d\n", "PLL RX Hang",
- sc->debug.stats.reset[RESET_TYPE_PLL_HANG]);
- len += snprintf(buf + len, sizeof(buf) - len,
- "%17s: %2d\n", "MCI Reset",
- sc->debug.stats.reset[RESET_TYPE_MCI]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%17s: %2d\n", "Baseband Hang",
+ sc->debug.stats.reset[RESET_TYPE_BB_HANG]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%17s: %2d\n", "Baseband Watchdog",
+ sc->debug.stats.reset[RESET_TYPE_BB_WATCHDOG]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%17s: %2d\n", "Fatal HW Error",
+ sc->debug.stats.reset[RESET_TYPE_FATAL_INT]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%17s: %2d\n", "TX HW error",
+ sc->debug.stats.reset[RESET_TYPE_TX_ERROR]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%17s: %2d\n", "TX Path Hang",
+ sc->debug.stats.reset[RESET_TYPE_TX_HANG]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%17s: %2d\n", "PLL RX Hang",
+ sc->debug.stats.reset[RESET_TYPE_PLL_HANG]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%17s: %2d\n", "MCI Reset",
+ sc->debug.stats.reset[RESET_TYPE_MCI]);
if (len > sizeof(buf))
len = sizeof(buf);
@@ -902,14 +904,14 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
#define PHY_ERR(s, p) \
- len += snprintf(buf + len, size - len, "%22s : %10u\n", s, \
- sc->debug.stats.rxstats.phy_err_stats[p]);
+ len += scnprintf(buf + len, size - len, "%22s : %10u\n", s, \
+ sc->debug.stats.rxstats.phy_err_stats[p]);
#define RXS_ERR(s, e) \
do { \
- len += snprintf(buf + len, size - len, \
- "%22s : %10u\n", s, \
- sc->debug.stats.rxstats.e); \
+ len += scnprintf(buf + len, size - len, \
+ "%22s : %10u\n", s, \
+ sc->debug.stats.rxstats.e);\
} while (0)
struct ath_softc *sc = file->private_data;
@@ -1439,22 +1441,22 @@ static ssize_t read_file_dump_nfcal(struct file *file, char __user *user_buf,
if (!buf)
return -ENOMEM;
- len += snprintf(buf + len, size - len,
- "Channel Noise Floor : %d\n", ah->noise);
- len += snprintf(buf + len, size - len,
- "Chain | privNF | # Readings | NF Readings\n");
+ len += scnprintf(buf + len, size - len,
+ "Channel Noise Floor : %d\n", ah->noise);
+ len += scnprintf(buf + len, size - len,
+ "Chain | privNF | # Readings | NF Readings\n");
for (i = 0; i < NUM_NF_READINGS; i++) {
if (!(chainmask & (1 << i)) ||
((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
continue;
nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - h[i].invalidNFcount;
- len += snprintf(buf + len, size - len, " %d\t %d\t %d\t\t",
- i, h[i].privNF, nread);
+ len += scnprintf(buf + len, size - len, " %d\t %d\t %d\t\t",
+ i, h[i].privNF, nread);
for (j = 0; j < nread; j++)
- len += snprintf(buf + len, size - len,
- " %d", h[i].nfCalBuffer[j]);
- len += snprintf(buf + len, size - len, "\n");
+ len += scnprintf(buf + len, size - len,
+ " %d", h[i].nfCalBuffer[j]);
+ len += scnprintf(buf + len, size - len, "\n");
}
if (len > size)
@@ -1543,8 +1545,8 @@ static ssize_t read_file_btcoex(struct file *file, char __user *user_buf,
return -ENOMEM;
if (!sc->sc_ah->common.btcoex_enabled) {
- len = snprintf(buf, size, "%s\n",
- "BTCOEX is disabled");
+ len = scnprintf(buf, size, "%s\n",
+ "BTCOEX is disabled");
goto exit;
}
@@ -1582,43 +1584,43 @@ static ssize_t read_file_node_stat(struct file *file, char __user *user_buf,
return -ENOMEM;
if (!an->sta->ht_cap.ht_supported) {
- len = snprintf(buf, size, "%s\n",
- "HT not supported");
+ len = scnprintf(buf, size, "%s\n",
+ "HT not supported");
goto exit;
}
- len = snprintf(buf, size, "Max-AMPDU: %d\n",
- an->maxampdu);
- len += snprintf(buf + len, size - len, "MPDU Density: %d\n\n",
- an->mpdudensity);
+ len = scnprintf(buf, size, "Max-AMPDU: %d\n",
+ an->maxampdu);
+ len += scnprintf(buf + len, size - len, "MPDU Density: %d\n\n",
+ an->mpdudensity);
- len += snprintf(buf + len, size - len,
- "%2s%7s\n", "AC", "SCHED");
+ len += scnprintf(buf + len, size - len,
+ "%2s%7s\n", "AC", "SCHED");
for (acno = 0, ac = &an->ac[acno];
acno < IEEE80211_NUM_ACS; acno++, ac++) {
txq = ac->txq;
ath_txq_lock(sc, txq);
- len += snprintf(buf + len, size - len,
- "%2d%7d\n",
- acno, ac->sched);
+ len += scnprintf(buf + len, size - len,
+ "%2d%7d\n",
+ acno, ac->sched);
ath_txq_unlock(sc, txq);
}
- len += snprintf(buf + len, size - len,
- "\n%3s%11s%10s%10s%10s%10s%9s%6s%8s\n",
- "TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE",
- "BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED");
+ len += scnprintf(buf + len, size - len,
+ "\n%3s%11s%10s%10s%10s%10s%9s%6s%8s\n",
+ "TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE",
+ "BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED");
for (tidno = 0, tid = &an->tid[tidno];
tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
txq = tid->ac->txq;
ath_txq_lock(sc, txq);
- len += snprintf(buf + len, size - len,
- "%3d%11d%10d%10d%10d%10d%9d%6d%8d\n",
- tid->tidno, tid->seq_start, tid->seq_next,
- tid->baw_size, tid->baw_head, tid->baw_tail,
- tid->bar_index, tid->sched, tid->paused);
+ len += scnprintf(buf + len, size - len,
+ "%3d%11d%10d%10d%10d%10d%9d%6d%8d\n",
+ tid->tidno, tid->seq_start, tid->seq_next,
+ tid->baw_size, tid->baw_head, tid->baw_tail,
+ tid->bar_index, tid->sched, tid->paused);
ath_txq_unlock(sc, txq);
}
exit:
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 6e1556fa2f3e..d6e3fa4299a4 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -193,12 +193,12 @@ struct ath_tx_stats {
#define TXSTATS sc->debug.stats.txstats
#define PR(str, elem) \
do { \
- len += snprintf(buf + len, size - len, \
- "%s%13u%11u%10u%10u\n", str, \
- TXSTATS[PR_QNUM(IEEE80211_AC_BE)].elem, \
- TXSTATS[PR_QNUM(IEEE80211_AC_BK)].elem, \
- TXSTATS[PR_QNUM(IEEE80211_AC_VI)].elem, \
- TXSTATS[PR_QNUM(IEEE80211_AC_VO)].elem); \
+ len += scnprintf(buf + len, size - len, \
+ "%s%13u%11u%10u%10u\n", str, \
+ TXSTATS[PR_QNUM(IEEE80211_AC_BE)].elem,\
+ TXSTATS[PR_QNUM(IEEE80211_AC_BK)].elem,\
+ TXSTATS[PR_QNUM(IEEE80211_AC_VI)].elem,\
+ TXSTATS[PR_QNUM(IEEE80211_AC_VO)].elem); \
} while(0)
#define RX_STAT_INC(c) (sc->debug.stats.rxstats.c++)
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.c b/drivers/net/wireless/ath/ath9k/dfs_debug.c
index 3c6e4138a95d..821599135d8a 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_debug.c
+++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c
@@ -25,11 +25,11 @@
struct ath_dfs_pool_stats global_dfs_pool_stats = { 0 };
#define ATH9K_DFS_STAT(s, p) \
- len += snprintf(buf + len, size - len, "%28s : %10u\n", s, \
- sc->debug.stats.dfs_stats.p);
+ len += scnprintf(buf + len, size - len, "%28s : %10u\n", s, \
+ sc->debug.stats.dfs_stats.p);
#define ATH9K_DFS_POOL_STAT(s, p) \
- len += snprintf(buf + len, size - len, "%28s : %10u\n", s, \
- global_dfs_pool_stats.p);
+ len += scnprintf(buf + len, size - len, "%28s : %10u\n", s, \
+ global_dfs_pool_stats.p);
static ssize_t read_file_dfs(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -44,12 +44,12 @@ static ssize_t read_file_dfs(struct file *file, char __user *user_buf,
if (buf == NULL)
return -ENOMEM;
- len += snprintf(buf + len, size - len, "DFS support for "
- "macVersion = 0x%x, macRev = 0x%x: %s\n",
- hw_ver->macVersion, hw_ver->macRev,
- (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_DFS) ?
+ len += scnprintf(buf + len, size - len, "DFS support for "
+ "macVersion = 0x%x, macRev = 0x%x: %s\n",
+ hw_ver->macVersion, hw_ver->macRev,
+ (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_DFS) ?
"enabled" : "disabled");
- len += snprintf(buf + len, size - len, "Pulse detector statistics:\n");
+ len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n");
ATH9K_DFS_STAT("pulse events reported ", pulses_total);
ATH9K_DFS_STAT("invalid pulse events ", pulses_no_dfs);
ATH9K_DFS_STAT("DFS pulses detected ", pulses_detected);
@@ -59,11 +59,12 @@ static ssize_t read_file_dfs(struct file *file, char __user *user_buf,
ATH9K_DFS_STAT("Primary channel pulses ", pri_phy_errors);
ATH9K_DFS_STAT("Secondary channel pulses", ext_phy_errors);
ATH9K_DFS_STAT("Dual channel pulses ", dc_phy_errors);
- len += snprintf(buf + len, size - len, "Radar detector statistics "
- "(current DFS region: %d)\n", sc->dfs_detector->region);
+ len += scnprintf(buf + len, size - len, "Radar detector statistics "
+ "(current DFS region: %d)\n",
+ sc->dfs_detector->region);
ATH9K_DFS_STAT("Pulse events processed ", pulses_processed);
ATH9K_DFS_STAT("Radars detected ", radar_detected);
- len += snprintf(buf + len, size - len, "Global Pool statistics:\n");
+ len += scnprintf(buf + len, size - len, "Global Pool statistics:\n");
ATH9K_DFS_POOL_STAT("Pool references ", pool_reference);
ATH9K_DFS_POOL_STAT("Pulses allocated ", pulse_allocated);
ATH9K_DFS_POOL_STAT("Pulses alloc error ", pulse_alloc_error);
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
index 5ba4b6fe37c0..c718fc379a10 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
+++ b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
@@ -392,7 +392,7 @@ static struct pri_sequence *pri_detector_add_pulse(struct pri_detector *de,
if (!pseq_handler_create_sequences(de, ts, max_updated_seq)) {
pri_detector_reset(de, ts);
- return false;
+ return NULL;
}
ps = pseq_handler_check_detection(de);
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index 9ea8e4b779c9..b4091716e9b3 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -129,10 +129,10 @@ static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
struct base_eep_header_4k *pBase = &eep->baseEepHeader;
if (!dump_base_hdr) {
- len += snprintf(buf + len, size - len,
- "%20s :\n", "2GHz modal Header");
+ len += scnprintf(buf + len, size - len,
+ "%20s :\n", "2GHz modal Header");
len = ath9k_dump_4k_modal_eeprom(buf, len, size,
- &eep->modalHeader);
+ &eep->modalHeader);
goto out;
}
@@ -160,8 +160,8 @@ static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF);
PR_EEP("TX Gain type", pBase->txGainType);
- len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
- pBase->macAddr);
+ len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+ pBase->macAddr);
out:
if (len > size)
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index 3ae1f3df0637..e1d0c217c104 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -125,8 +125,8 @@ static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
if (!dump_base_hdr) {
- len += snprintf(buf + len, size - len,
- "%20s :\n", "2GHz modal Header");
+ len += scnprintf(buf + len, size - len,
+ "%20s :\n", "2GHz modal Header");
len = ar9287_dump_modal_eeprom(buf, len, size,
&eep->modalHeader);
goto out;
@@ -157,8 +157,8 @@ static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
PR_EEP("Power Table Offset", pBase->pwrTableOffset);
PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl);
- len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
- pBase->macAddr);
+ len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+ pBase->macAddr);
out:
if (len > size)
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index 1c25368b3836..39107e31e79a 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -205,12 +205,12 @@ static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
struct base_eep_header *pBase = &eep->baseEepHeader;
if (!dump_base_hdr) {
- len += snprintf(buf + len, size - len,
- "%20s :\n", "2GHz modal Header");
+ len += scnprintf(buf + len, size - len,
+ "%20s :\n", "2GHz modal Header");
len = ath9k_def_dump_modal_eeprom(buf, len, size,
&eep->modalHeader[0]);
- len += snprintf(buf + len, size - len,
- "%20s :\n", "5GHz modal Header");
+ len += scnprintf(buf + len, size - len,
+ "%20s :\n", "5GHz modal Header");
len = ath9k_def_dump_modal_eeprom(buf, len, size,
&eep->modalHeader[1]);
goto out;
@@ -240,8 +240,8 @@ static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF);
PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl);
- len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
- pBase->macAddr);
+ len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+ pBase->macAddr);
out:
if (len > size)
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index 4b412aaf4f36..c34f21241da9 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -522,22 +522,22 @@ static int ath9k_dump_mci_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
ATH_DUMP_BTCOEX("Concurrent Tx", btcoex_hw->mci.concur_tx);
ATH_DUMP_BTCOEX("Concurrent RSSI cnt", btcoex->rssi_count);
- len += snprintf(buf + len, size - len, "BT Weights: ");
+ len += scnprintf(buf + len, size - len, "BT Weights: ");
for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
- len += snprintf(buf + len, size - len, "%08x ",
- btcoex_hw->bt_weight[i]);
- len += snprintf(buf + len, size - len, "\n");
- len += snprintf(buf + len, size - len, "WLAN Weights: ");
+ len += scnprintf(buf + len, size - len, "%08x ",
+ btcoex_hw->bt_weight[i]);
+ len += scnprintf(buf + len, size - len, "\n");
+ len += scnprintf(buf + len, size - len, "WLAN Weights: ");
for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
- len += snprintf(buf + len, size - len, "%08x ",
- btcoex_hw->wlan_weight[i]);
- len += snprintf(buf + len, size - len, "\n");
- len += snprintf(buf + len, size - len, "Tx Priorities: ");
+ len += scnprintf(buf + len, size - len, "%08x ",
+ btcoex_hw->wlan_weight[i]);
+ len += scnprintf(buf + len, size - len, "\n");
+ len += scnprintf(buf + len, size - len, "Tx Priorities: ");
for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++)
- len += snprintf(buf + len, size - len, "%08x ",
+ len += scnprintf(buf + len, size - len, "%08x ",
btcoex_hw->tx_prio[i]);
- len += snprintf(buf + len, size - len, "\n");
+ len += scnprintf(buf + len, size - len, "\n");
return len;
}
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
index c1b45e2f8481..fb071ee4fcfb 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -37,29 +37,29 @@ static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf,
ath9k_htc_ps_restore(priv);
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "RX",
- be32_to_cpu(cmd_rsp.rx));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "RX",
+ be32_to_cpu(cmd_rsp.rx));
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "RXORN",
- be32_to_cpu(cmd_rsp.rxorn));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "RXORN",
+ be32_to_cpu(cmd_rsp.rxorn));
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "RXEOL",
- be32_to_cpu(cmd_rsp.rxeol));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "RXEOL",
+ be32_to_cpu(cmd_rsp.rxeol));
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "TXURN",
- be32_to_cpu(cmd_rsp.txurn));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "TXURN",
+ be32_to_cpu(cmd_rsp.txurn));
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "TXTO",
- be32_to_cpu(cmd_rsp.txto));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "TXTO",
+ be32_to_cpu(cmd_rsp.txto));
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "CST",
- be32_to_cpu(cmd_rsp.cst));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "CST",
+ be32_to_cpu(cmd_rsp.cst));
if (len > sizeof(buf))
len = sizeof(buf);
@@ -95,41 +95,41 @@ static ssize_t read_file_tgt_tx_stats(struct file *file, char __user *user_buf,
ath9k_htc_ps_restore(priv);
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "Xretries",
- be32_to_cpu(cmd_rsp.xretries));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "Xretries",
+ be32_to_cpu(cmd_rsp.xretries));
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "FifoErr",
- be32_to_cpu(cmd_rsp.fifoerr));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "FifoErr",
+ be32_to_cpu(cmd_rsp.fifoerr));
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "Filtered",
- be32_to_cpu(cmd_rsp.filtered));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "Filtered",
+ be32_to_cpu(cmd_rsp.filtered));
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "TimerExp",
- be32_to_cpu(cmd_rsp.timer_exp));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "TimerExp",
+ be32_to_cpu(cmd_rsp.timer_exp));
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "ShortRetries",
- be32_to_cpu(cmd_rsp.shortretries));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "ShortRetries",
+ be32_to_cpu(cmd_rsp.shortretries));
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "LongRetries",
- be32_to_cpu(cmd_rsp.longretries));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "LongRetries",
+ be32_to_cpu(cmd_rsp.longretries));
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "QueueNull",
- be32_to_cpu(cmd_rsp.qnull));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "QueueNull",
+ be32_to_cpu(cmd_rsp.qnull));
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "EncapFail",
- be32_to_cpu(cmd_rsp.encap_fail));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "EncapFail",
+ be32_to_cpu(cmd_rsp.encap_fail));
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "NoBuf",
- be32_to_cpu(cmd_rsp.nobuf));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "NoBuf",
+ be32_to_cpu(cmd_rsp.nobuf));
if (len > sizeof(buf))
len = sizeof(buf);
@@ -165,17 +165,17 @@ static ssize_t read_file_tgt_rx_stats(struct file *file, char __user *user_buf,
ath9k_htc_ps_restore(priv);
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "NoBuf",
- be32_to_cpu(cmd_rsp.nobuf));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "NoBuf",
+ be32_to_cpu(cmd_rsp.nobuf));
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "HostSend",
- be32_to_cpu(cmd_rsp.host_send));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "HostSend",
+ be32_to_cpu(cmd_rsp.host_send));
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "HostDone",
- be32_to_cpu(cmd_rsp.host_done));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "HostDone",
+ be32_to_cpu(cmd_rsp.host_done));
if (len > sizeof(buf))
len = sizeof(buf);
@@ -197,37 +197,37 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
char buf[512];
unsigned int len = 0;
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "Buffers queued",
- priv->debug.tx_stats.buf_queued);
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "Buffers completed",
- priv->debug.tx_stats.buf_completed);
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "SKBs queued",
- priv->debug.tx_stats.skb_queued);
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "SKBs success",
- priv->debug.tx_stats.skb_success);
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "SKBs failed",
- priv->debug.tx_stats.skb_failed);
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "CAB queued",
- priv->debug.tx_stats.cab_queued);
-
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "BE queued",
- priv->debug.tx_stats.queue_stats[IEEE80211_AC_BE]);
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "BK queued",
- priv->debug.tx_stats.queue_stats[IEEE80211_AC_BK]);
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "VI queued",
- priv->debug.tx_stats.queue_stats[IEEE80211_AC_VI]);
- len += snprintf(buf + len, sizeof(buf) - len,
- "%20s : %10u\n", "VO queued",
- priv->debug.tx_stats.queue_stats[IEEE80211_AC_VO]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "Buffers queued",
+ priv->debug.tx_stats.buf_queued);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "Buffers completed",
+ priv->debug.tx_stats.buf_completed);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "SKBs queued",
+ priv->debug.tx_stats.skb_queued);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "SKBs success",
+ priv->debug.tx_stats.skb_success);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "SKBs failed",
+ priv->debug.tx_stats.skb_failed);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "CAB queued",
+ priv->debug.tx_stats.cab_queued);
+
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "BE queued",
+ priv->debug.tx_stats.queue_stats[IEEE80211_AC_BE]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "BK queued",
+ priv->debug.tx_stats.queue_stats[IEEE80211_AC_BK]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "VI queued",
+ priv->debug.tx_stats.queue_stats[IEEE80211_AC_VI]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "VO queued",
+ priv->debug.tx_stats.queue_stats[IEEE80211_AC_VO]);
if (len > sizeof(buf))
len = sizeof(buf);
@@ -273,8 +273,8 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
#define PHY_ERR(s, p) \
- len += snprintf(buf + len, size - len, "%20s : %10u\n", s, \
- priv->debug.rx_stats.err_phy_stats[p]);
+ len += scnprintf(buf + len, size - len, "%20s : %10u\n", s, \
+ priv->debug.rx_stats.err_phy_stats[p]);
struct ath9k_htc_priv *priv = file->private_data;
char *buf;
@@ -285,37 +285,37 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
if (buf == NULL)
return -ENOMEM;
- len += snprintf(buf + len, size - len,
- "%20s : %10u\n", "SKBs allocated",
- priv->debug.rx_stats.skb_allocated);
- len += snprintf(buf + len, size - len,
- "%20s : %10u\n", "SKBs completed",
- priv->debug.rx_stats.skb_completed);
- len += snprintf(buf + len, size - len,
- "%20s : %10u\n", "SKBs Dropped",
- priv->debug.rx_stats.skb_dropped);
-
- len += snprintf(buf + len, size - len,
- "%20s : %10u\n", "CRC ERR",
- priv->debug.rx_stats.err_crc);
- len += snprintf(buf + len, size - len,
- "%20s : %10u\n", "DECRYPT CRC ERR",
- priv->debug.rx_stats.err_decrypt_crc);
- len += snprintf(buf + len, size - len,
- "%20s : %10u\n", "MIC ERR",
- priv->debug.rx_stats.err_mic);
- len += snprintf(buf + len, size - len,
- "%20s : %10u\n", "PRE-DELIM CRC ERR",
- priv->debug.rx_stats.err_pre_delim);
- len += snprintf(buf + len, size - len,
- "%20s : %10u\n", "POST-DELIM CRC ERR",
- priv->debug.rx_stats.err_post_delim);
- len += snprintf(buf + len, size - len,
- "%20s : %10u\n", "DECRYPT BUSY ERR",
- priv->debug.rx_stats.err_decrypt_busy);
- len += snprintf(buf + len, size - len,
- "%20s : %10u\n", "TOTAL PHY ERR",
- priv->debug.rx_stats.err_phy);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10u\n", "SKBs allocated",
+ priv->debug.rx_stats.skb_allocated);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10u\n", "SKBs completed",
+ priv->debug.rx_stats.skb_completed);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10u\n", "SKBs Dropped",
+ priv->debug.rx_stats.skb_dropped);
+
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10u\n", "CRC ERR",
+ priv->debug.rx_stats.err_crc);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10u\n", "DECRYPT CRC ERR",
+ priv->debug.rx_stats.err_decrypt_crc);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10u\n", "MIC ERR",
+ priv->debug.rx_stats.err_mic);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10u\n", "PRE-DELIM CRC ERR",
+ priv->debug.rx_stats.err_pre_delim);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10u\n", "POST-DELIM CRC ERR",
+ priv->debug.rx_stats.err_post_delim);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10u\n", "DECRYPT BUSY ERR",
+ priv->debug.rx_stats.err_decrypt_busy);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10u\n", "TOTAL PHY ERR",
+ priv->debug.rx_stats.err_phy);
PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN);
@@ -372,16 +372,16 @@ static ssize_t read_file_slot(struct file *file, char __user *user_buf,
spin_lock_bh(&priv->tx.tx_lock);
- len += snprintf(buf + len, sizeof(buf) - len, "TX slot bitmap : ");
+ len += scnprintf(buf + len, sizeof(buf) - len, "TX slot bitmap : ");
len += bitmap_scnprintf(buf + len, sizeof(buf) - len,
priv->tx.tx_slot, MAX_TX_BUF_NUM);
- len += snprintf(buf + len, sizeof(buf) - len, "\n");
+ len += scnprintf(buf + len, sizeof(buf) - len, "\n");
- len += snprintf(buf + len, sizeof(buf) - len,
- "Used slots : %d\n",
- bitmap_weight(priv->tx.tx_slot, MAX_TX_BUF_NUM));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "Used slots : %d\n",
+ bitmap_weight(priv->tx.tx_slot, MAX_TX_BUF_NUM));
spin_unlock_bh(&priv->tx.tx_lock);
@@ -405,30 +405,30 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf,
char buf[512];
unsigned int len = 0;
- len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
- "Mgmt endpoint", skb_queue_len(&priv->tx.mgmt_ep_queue));
+ len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
+ "Mgmt endpoint", skb_queue_len(&priv->tx.mgmt_ep_queue));
- len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
- "Cab endpoint", skb_queue_len(&priv->tx.cab_ep_queue));
+ len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
+ "Cab endpoint", skb_queue_len(&priv->tx.cab_ep_queue));
- len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
- "Data BE endpoint", skb_queue_len(&priv->tx.data_be_queue));
+ len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
+ "Data BE endpoint", skb_queue_len(&priv->tx.data_be_queue));
- len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
- "Data BK endpoint", skb_queue_len(&priv->tx.data_bk_queue));
+ len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
+ "Data BK endpoint", skb_queue_len(&priv->tx.data_bk_queue));
- len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
- "Data VI endpoint", skb_queue_len(&priv->tx.data_vi_queue));
+ len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
+ "Data VI endpoint", skb_queue_len(&priv->tx.data_vi_queue));
- len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
- "Data VO endpoint", skb_queue_len(&priv->tx.data_vo_queue));
+ len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
+ "Data VO endpoint", skb_queue_len(&priv->tx.data_vo_queue));
- len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
- "Failed queue", skb_queue_len(&priv->tx.tx_failed));
+ len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
+ "Failed queue", skb_queue_len(&priv->tx.tx_failed));
spin_lock_bh(&priv->tx.tx_lock);
- len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
- "Queued count", priv->tx.queued_cnt);
+ len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
+ "Queued count", priv->tx.queued_cnt);
spin_unlock_bh(&priv->tx.tx_lock);
if (len > sizeof(buf))
@@ -507,70 +507,70 @@ static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
if (buf == NULL)
return -ENOMEM;
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n", "Major Version",
- pBase->version >> 12);
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n", "Minor Version",
- pBase->version & 0xFFF);
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n", "Checksum",
- pBase->checksum);
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n", "Length",
- pBase->length);
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n", "RegDomain1",
- pBase->regDmn[0]);
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n", "RegDomain2",
- pBase->regDmn[1]);
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n",
- "TX Mask", pBase->txMask);
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n",
- "RX Mask", pBase->rxMask);
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Allow 5GHz",
- !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Allow 2GHz",
- !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Disable 2GHz HT20",
- !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT20));
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Disable 2GHz HT40",
- !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT40));
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Disable 5Ghz HT20",
- !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT20));
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Disable 5Ghz HT40",
- !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT40));
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Big Endian",
- !!(pBase->eepMisc & 0x01));
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Cal Bin Major Ver",
- (pBase->binBuildNumber >> 24) & 0xFF);
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Cal Bin Minor Ver",
- (pBase->binBuildNumber >> 16) & 0xFF);
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Cal Bin Build",
- (pBase->binBuildNumber >> 8) & 0xFF);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n", "Major Version",
+ pBase->version >> 12);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n", "Minor Version",
+ pBase->version & 0xFFF);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n", "Checksum",
+ pBase->checksum);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n", "Length",
+ pBase->length);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n", "RegDomain1",
+ pBase->regDmn[0]);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n", "RegDomain2",
+ pBase->regDmn[1]);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n",
+ "TX Mask", pBase->txMask);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n",
+ "RX Mask", pBase->rxMask);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n",
+ "Allow 5GHz",
+ !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n",
+ "Allow 2GHz",
+ !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n",
+ "Disable 2GHz HT20",
+ !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT20));
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n",
+ "Disable 2GHz HT40",
+ !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT40));
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n",
+ "Disable 5Ghz HT20",
+ !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT20));
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n",
+ "Disable 5Ghz HT40",
+ !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT40));
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n",
+ "Big Endian",
+ !!(pBase->eepMisc & 0x01));
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n",
+ "Cal Bin Major Ver",
+ (pBase->binBuildNumber >> 24) & 0xFF);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n",
+ "Cal Bin Minor Ver",
+ (pBase->binBuildNumber >> 16) & 0xFF);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n",
+ "Cal Bin Build",
+ (pBase->binBuildNumber >> 8) & 0xFF);
/*
* UB91 specific data.
@@ -579,10 +579,10 @@ static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
struct base_eep_header_4k *pBase4k =
&priv->ah->eeprom.map4k.baseEepHeader;
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n",
- "TX Gain type",
- pBase4k->txGainType);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n",
+ "TX Gain type",
+ pBase4k->txGainType);
}
/*
@@ -592,19 +592,19 @@ static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
struct base_eep_ar9287_header *pBase9287 =
&priv->ah->eeprom.map9287.baseEepHeader;
- len += snprintf(buf + len, size - len,
- "%20s : %10ddB\n",
- "Power Table Offset",
- pBase9287->pwrTableOffset);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10ddB\n",
+ "Power Table Offset",
+ pBase9287->pwrTableOffset);
- len += snprintf(buf + len, size - len,
- "%20s : %10d\n",
- "OpenLoop Power Ctrl",
- pBase9287->openLoopPwrCntl);
+ len += scnprintf(buf + len, size - len,
+ "%20s : %10d\n",
+ "OpenLoop Power Ctrl",
+ pBase9287->openLoopPwrCntl);
}
- len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
- pBase->macAddr);
+ len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
+ pBase->macAddr);
if (len > size)
len = size;
@@ -627,8 +627,8 @@ static ssize_t read_4k_modal_eeprom(struct file *file,
{
#define PR_EEP(_s, _val) \
do { \
- len += snprintf(buf + len, size - len, "%20s : %10d\n", \
- _s, (_val)); \
+ len += scnprintf(buf + len, size - len, "%20s : %10d\n",\
+ _s, (_val)); \
} while (0)
struct ath9k_htc_priv *priv = file->private_data;
@@ -708,12 +708,12 @@ static ssize_t read_def_modal_eeprom(struct file *file,
do { \
if (pBase->opCapFlags & AR5416_OPFLAGS_11G) { \
pModal = &priv->ah->eeprom.def.modalHeader[1]; \
- len += snprintf(buf + len, size - len, "%20s : %8d%7s", \
- _s, (_val), "|"); \
+ len += scnprintf(buf + len, size - len, "%20s : %8d%7s", \
+ _s, (_val), "|"); \
} \
if (pBase->opCapFlags & AR5416_OPFLAGS_11A) { \
pModal = &priv->ah->eeprom.def.modalHeader[0]; \
- len += snprintf(buf + len, size - len, "%9d\n", \
+ len += scnprintf(buf + len, size - len, "%9d\n",\
(_val)); \
} \
} while (0)
@@ -729,10 +729,10 @@ static ssize_t read_def_modal_eeprom(struct file *file,
if (buf == NULL)
return -ENOMEM;
- len += snprintf(buf + len, size - len,
- "%31s %15s\n", "2G", "5G");
- len += snprintf(buf + len, size - len,
- "%32s %16s\n", "====", "====\n");
+ len += scnprintf(buf + len, size - len,
+ "%31s %15s\n", "2G", "5G");
+ len += scnprintf(buf + len, size - len,
+ "%32s %16s\n", "====", "====\n");
PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]);
PR_EEP("Chain1 Ant. Control", pModal->antCtrlChain[1]);
@@ -814,8 +814,8 @@ static ssize_t read_9287_modal_eeprom(struct file *file,
{
#define PR_EEP(_s, _val) \
do { \
- len += snprintf(buf + len, size - len, "%20s : %10d\n", \
- _s, (_val)); \
+ len += scnprintf(buf + len, size - len, "%20s : %10d\n",\
+ _s, (_val)); \
} while (0)
struct ath9k_htc_priv *priv = file->private_data;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index ecc6ec4a1edb..f11e8389a9be 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -549,6 +549,18 @@ static int ath9k_hw_post_init(struct ath_hw *ah)
ath9k_hw_ani_init(ah);
+ /*
+ * EEPROM needs to be initialized before we do this.
+ * This is required for regulatory compliance.
+ */
+ if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
+ u16 regdmn = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
+ if ((regdmn & 0xF0) == CTL_FCC) {
+ ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9462_FCC_2GHZ;
+ ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9462_FCC_5GHZ;
+ }
+ }
+
return 0;
}
@@ -1644,6 +1656,19 @@ hang_check_iter:
return true;
}
+void ath9k_hw_check_nav(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ u32 val;
+
+ val = REG_READ(ah, AR_NAV);
+ if (val != 0xdeadbeef && val > 0x7fff) {
+ ath_dbg(common, BSTUCK, "Abnormal NAV: 0x%x\n", val);
+ REG_WRITE(ah, AR_NAV, 0);
+ }
+}
+EXPORT_SYMBOL(ath9k_hw_check_nav);
+
bool ath9k_hw_check_alive(struct ath_hw *ah)
{
int count = 50;
@@ -1822,9 +1847,9 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan)
* re-using are present.
*/
if (AR_SREV_9462(ah) && (ah->caldata &&
- (!ah->caldata->done_txiqcal_once ||
- !ah->caldata->done_txclcal_once ||
- !ah->caldata->rtt_done)))
+ (!test_bit(TXIQCAL_DONE, &ah->caldata->cal_flags) ||
+ !test_bit(TXCLCAL_DONE, &ah->caldata->cal_flags) ||
+ !test_bit(RTT_DONE, &ah->caldata->cal_flags))))
goto fail;
ath_dbg(common, RESET, "FastChannelChange for %d -> %d\n",
@@ -1880,7 +1905,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
memset(caldata, 0, sizeof(*caldata));
ath9k_init_nfcal_hist_buffer(ah, chan);
} else if (caldata) {
- caldata->paprd_packet_sent = false;
+ clear_bit(PAPRD_PACKET_SENT, &caldata->cal_flags);
}
ah->noise = ath9k_hw_getchan_noise(ah, chan);
@@ -2017,8 +2042,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_init_bb(ah, chan);
if (caldata) {
- caldata->done_txiqcal_once = false;
- caldata->done_txclcal_once = false;
+ clear_bit(TXIQCAL_DONE, &caldata->cal_flags);
+ clear_bit(TXCLCAL_DONE, &caldata->cal_flags);
}
if (!ath9k_hw_init_cal(ah, chan))
return -EIO;
@@ -3240,19 +3265,19 @@ void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len)
/* chipsets >= AR9280 are single-chip */
if (AR_SREV_9280_20_OR_LATER(ah)) {
- used = snprintf(hw_name, len,
- "Atheros AR%s Rev:%x",
- ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
- ah->hw_version.macRev);
+ used = scnprintf(hw_name, len,
+ "Atheros AR%s Rev:%x",
+ ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
+ ah->hw_version.macRev);
}
else {
- used = snprintf(hw_name, len,
- "Atheros AR%s MAC/BB Rev:%x AR%s RF Rev:%x",
- ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
- ah->hw_version.macRev,
- ath9k_hw_rf_name((ah->hw_version.analog5GhzRev &
- AR_RADIO_SREV_MAJOR)),
- ah->hw_version.phyRev);
+ used = scnprintf(hw_name, len,
+ "Atheros AR%s MAC/BB Rev:%x AR%s RF Rev:%x",
+ ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
+ ah->hw_version.macRev,
+ ath9k_hw_rf_name((ah->hw_version.analog5GhzRev
+ & AR_RADIO_SREV_MAJOR)),
+ ah->hw_version.phyRev);
}
hw_name[used] = '\0';
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 69a907b55a73..2babf931b459 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -98,8 +98,8 @@
#define PR_EEP(_s, _val) \
do { \
- len += snprintf(buf + len, size - len, "%20s : %10d\n", \
- _s, (_val)); \
+ len += scnprintf(buf + len, size - len, "%20s : %10d\n",\
+ _s, (_val)); \
} while (0)
#define SM(_v, _f) (((_v) << _f##_S) & _f)
@@ -404,20 +404,26 @@ enum ath9k_int {
#define MAX_CL_TAB_ENTRY 16
#define CL_TAB_ENTRY(reg_base) (reg_base + (4 * j))
+enum ath9k_cal_flags {
+ RTT_DONE,
+ PAPRD_PACKET_SENT,
+ PAPRD_DONE,
+ NFCAL_PENDING,
+ NFCAL_INTF,
+ TXIQCAL_DONE,
+ TXCLCAL_DONE,
+ SW_PKDET_DONE,
+};
+
struct ath9k_hw_cal_data {
u16 channel;
u32 channelFlags;
u32 chanmode;
+ unsigned long cal_flags;
int32_t CalValid;
int8_t iCoff;
int8_t qCoff;
- bool rtt_done;
- bool paprd_packet_sent;
- bool paprd_done;
- bool nfcal_pending;
- bool nfcal_interference;
- bool done_txiqcal_once;
- bool done_txclcal_once;
+ u8 caldac[2];
u16 small_signal_gain[AR9300_MAX_CHAINS];
u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ];
u32 num_measures[AR9300_MAX_CHAINS];
@@ -558,6 +564,7 @@ struct ath_hw_antcomb_conf {
u8 main_gaintb;
u8 alt_gaintb;
int lna1_lna2_delta;
+ int lna1_lna2_switch_delta;
u8 div_group;
};
@@ -1030,6 +1037,7 @@ void ath9k_hw_set11nmac2040(struct ath_hw *ah);
void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
const struct ath9k_beacon_state *bs);
+void ath9k_hw_check_nav(struct ath_hw *ah);
bool ath9k_hw_check_alive(struct ath_hw *ah);
bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 9a1f349f9260..e3d11c41a145 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -547,6 +547,26 @@ static void ath9k_init_platform(struct ath_softc *sc)
if (sc->driver_data & ATH9K_PCI_CUS217)
ath_info(common, "CUS217 card detected\n");
+ if (sc->driver_data & ATH9K_PCI_CUS252)
+ ath_info(common, "CUS252 card detected\n");
+
+ if (sc->driver_data & ATH9K_PCI_AR9565_1ANT)
+ ath_info(common, "WB335 1-ANT card detected\n");
+
+ if (sc->driver_data & ATH9K_PCI_AR9565_2ANT)
+ ath_info(common, "WB335 2-ANT card detected\n");
+
+ /*
+ * Some WB335 cards do not support antenna diversity. Since
+ * we use a hardcoded value for AR9565 instead of using the
+ * EEPROM/OTP data, remove the combining feature from
+ * the HW capabilities bitmap.
+ */
+ if (sc->driver_data & (ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_AR9565_2ANT)) {
+ if (!(sc->driver_data & ATH9K_PCI_BT_ANT_DIV))
+ pCap->hw_caps &= ~ATH9K_HW_CAP_ANT_DIV_COMB;
+ }
+
if (sc->driver_data & ATH9K_PCI_BT_ANT_DIV) {
pCap->hw_caps |= ATH9K_HW_CAP_BT_ANT_DIV;
ath_info(common, "Set BT/WLAN RX diversity capability\n");
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index 2f831db396ac..84a60644f93a 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -184,7 +184,7 @@ static void ath_paprd_activate(struct ath_softc *sc)
struct ath9k_hw_cal_data *caldata = ah->caldata;
int chain;
- if (!caldata || !caldata->paprd_done) {
+ if (!caldata || !test_bit(PAPRD_DONE, &caldata->cal_flags)) {
ath_dbg(common, CALIBRATE, "Failed to activate PAPRD\n");
return;
}
@@ -256,7 +256,9 @@ void ath_paprd_calibrate(struct work_struct *work)
int len = 1800;
int ret;
- if (!caldata || !caldata->paprd_packet_sent || caldata->paprd_done) {
+ if (!caldata ||
+ !test_bit(PAPRD_PACKET_SENT, &caldata->cal_flags) ||
+ test_bit(PAPRD_DONE, &caldata->cal_flags)) {
ath_dbg(common, CALIBRATE, "Skipping PAPRD calibration\n");
return;
}
@@ -316,7 +318,7 @@ void ath_paprd_calibrate(struct work_struct *work)
kfree_skb(skb);
if (chain_ok) {
- caldata->paprd_done = true;
+ set_bit(PAPRD_DONE, &caldata->cal_flags);
ath_paprd_activate(sc);
}
@@ -343,7 +345,7 @@ void ath_ani_calibrate(unsigned long data)
u32 cal_interval, short_cal_interval, long_cal_interval;
unsigned long flags;
- if (ah->caldata && ah->caldata->nfcal_interference)
+ if (ah->caldata && test_bit(NFCAL_INTF, &ah->caldata->cal_flags))
long_cal_interval = ATH_LONG_CALINTERVAL_INT;
else
long_cal_interval = ATH_LONG_CALINTERVAL;
@@ -432,7 +434,7 @@ set_timer:
mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
if (ar9003_is_paprd_enabled(ah) && ah->caldata) {
- if (!ah->caldata->paprd_done) {
+ if (!test_bit(PAPRD_DONE, &ah->caldata->cal_flags)) {
ieee80211_queue_work(sc->hw, &sc->paprd_work);
} else if (!ah->paprd_table_write_done) {
ath9k_ps_wakeup(sc);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index e4f65900132d..cdb3b1e10b95 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -362,6 +362,13 @@ void ath9k_tasklet(unsigned long data)
type = RESET_TYPE_BB_WATCHDOG;
ath9k_queue_reset(sc, type);
+
+ /*
+ * Increment the ref. counter here so that
+ * interrupts are enabled in the reset routine.
+ */
+ atomic_inc(&ah->intr_ref_cnt);
+ ath_dbg(common, ANY, "FATAL: Skipping interrupts\n");
goto out;
}
@@ -400,10 +407,9 @@ void ath9k_tasklet(unsigned long data)
ath9k_btcoex_handle_interrupt(sc, status);
-out:
/* re-enable hardware interrupt */
ath9k_hw_enable_interrupts(ah);
-
+out:
spin_unlock(&sc->sc_pcu_lock);
ath9k_ps_restore(sc);
}
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index d089a7cf01c4..7e4c2524b630 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -269,7 +269,200 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
{ PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */
{ PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */
- { PCI_VDEVICE(ATHEROS, 0x0036) }, /* PCI-E AR9565 */
+
+ /* CUS252 */
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_ATHEROS,
+ 0x3028),
+ .driver_data = ATH9K_PCI_CUS252 |
+ ATH9K_PCI_AR9565_2ANT |
+ ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_AZWAVE,
+ 0x2176),
+ .driver_data = ATH9K_PCI_CUS252 |
+ ATH9K_PCI_AR9565_2ANT |
+ ATH9K_PCI_BT_ANT_DIV },
+
+ /* WB335 1-ANT */
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_FOXCONN,
+ 0xE068),
+ .driver_data = ATH9K_PCI_AR9565_1ANT },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ 0x185F, /* WNC */
+ 0xA119),
+ .driver_data = ATH9K_PCI_AR9565_1ANT },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ 0x11AD, /* LITEON */
+ 0x0632),
+ .driver_data = ATH9K_PCI_AR9565_1ANT },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ 0x11AD, /* LITEON */
+ 0x6671),
+ .driver_data = ATH9K_PCI_AR9565_1ANT },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ 0x1B9A, /* XAVI */
+ 0x2811),
+ .driver_data = ATH9K_PCI_AR9565_1ANT },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ 0x1B9A, /* XAVI */
+ 0x2812),
+ .driver_data = ATH9K_PCI_AR9565_1ANT },
+
+ /* WB335 1-ANT / Antenna Diversity */
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_ATHEROS,
+ 0x3025),
+ .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_ATHEROS,
+ 0x3026),
+ .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_ATHEROS,
+ 0x302B),
+ .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_FOXCONN,
+ 0xE069),
+ .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ 0x185F, /* WNC */
+ 0x3028),
+ .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ 0x11AD, /* LITEON */
+ 0x0622),
+ .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ 0x11AD, /* LITEON */
+ 0x0672),
+ .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ 0x11AD, /* LITEON */
+ 0x0662),
+ .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_AZWAVE,
+ 0x213A),
+ .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_LENOVO,
+ 0x3026),
+ .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_HP,
+ 0x18E3),
+ .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_HP,
+ 0x217F),
+ .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_DELL,
+ 0x020E),
+ .driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
+
+ /* WB335 2-ANT */
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_SAMSUNG,
+ 0x411A),
+ .driver_data = ATH9K_PCI_AR9565_2ANT },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_SAMSUNG,
+ 0x411B),
+ .driver_data = ATH9K_PCI_AR9565_2ANT },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_SAMSUNG,
+ 0x411C),
+ .driver_data = ATH9K_PCI_AR9565_2ANT },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_SAMSUNG,
+ 0x411D),
+ .driver_data = ATH9K_PCI_AR9565_2ANT },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_SAMSUNG,
+ 0x411E),
+ .driver_data = ATH9K_PCI_AR9565_2ANT },
+
+ /* WB335 2-ANT / Antenna-Diversity */
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_ATHEROS,
+ 0x3027),
+ .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_ATHEROS,
+ 0x302C),
+ .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ 0x11AD, /* LITEON */
+ 0x0642),
+ .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ 0x11AD, /* LITEON */
+ 0x0652),
+ .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ 0x11AD, /* LITEON */
+ 0x0612),
+ .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ PCI_VENDOR_ID_AZWAVE,
+ 0x2130),
+ .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ 0x144F, /* ASKEY */
+ 0x7202),
+ .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ 0x1B9A, /* XAVI */
+ 0x2810),
+ .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0036,
+ 0x185F, /* WNC */
+ 0x3027),
+ .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
+
+ /* PCI-E AR9565 (WB335) */
+ { PCI_VDEVICE(ATHEROS, 0x0036),
+ .driver_data = ATH9K_PCI_BT_ANT_DIV },
+
{ 0 }
};
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index d3d7c51fa6c8..d829bb62a3fc 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -1387,31 +1387,31 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
int used_mcs = 0, used_htmode = 0;
if (WLAN_RC_PHY_HT(rc->rate_table->info[i].phy)) {
- used_mcs = snprintf(mcs, 5, "%d",
- rc->rate_table->info[i].ratecode);
+ used_mcs = scnprintf(mcs, 5, "%d",
+ rc->rate_table->info[i].ratecode);
if (WLAN_RC_PHY_40(rc->rate_table->info[i].phy))
- used_htmode = snprintf(htmode, 5, "HT40");
+ used_htmode = scnprintf(htmode, 5, "HT40");
else if (WLAN_RC_PHY_20(rc->rate_table->info[i].phy))
- used_htmode = snprintf(htmode, 5, "HT20");
+ used_htmode = scnprintf(htmode, 5, "HT20");
else
- used_htmode = snprintf(htmode, 5, "????");
+ used_htmode = scnprintf(htmode, 5, "????");
}
mcs[used_mcs] = '\0';
htmode[used_htmode] = '\0';
- len += snprintf(buf + len, max - len,
- "%6s %6s %3u.%d: "
- "%10u %10u %10u %10u\n",
- htmode,
- mcs,
- ratekbps / 1000,
- (ratekbps % 1000) / 100,
- stats->success,
- stats->retries,
- stats->xretries,
- stats->per);
+ len += scnprintf(buf + len, max - len,
+ "%6s %6s %3u.%d: "
+ "%10u %10u %10u %10u\n",
+ htmode,
+ mcs,
+ ratekbps / 1000,
+ (ratekbps % 1000) / 100,
+ stats->success,
+ stats->retries,
+ stats->xretries,
+ stats->per);
}
if (len > max)
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 4ee472a5a4e4..ab9e3a8410bc 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1270,13 +1270,6 @@ static void ath9k_antenna_check(struct ath_softc *sc,
return;
/*
- * All MPDUs in an aggregate will use the same LNA
- * as the first MPDU.
- */
- if (rs->rs_isaggr && !rs->rs_firstaggr)
- return;
-
- /*
* Change the default rx antenna if rx diversity
* chooses the other antenna 3 times in a row.
*/
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h
index fde6da619f30..0db37f230018 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.h
+++ b/drivers/net/wireless/ath/ath9k/wmi.h
@@ -39,7 +39,7 @@ struct wmi_fw_version {
struct wmi_event_swba {
__be64 tsf;
u8 beacon_pending;
-};
+} __packed;
/*
* 64 - HTC header - WMI header - 1 / txstatus
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 35b515fe3ffa..13f5434e7f6c 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -399,6 +399,7 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
tbf->bf_buf_addr = bf->bf_buf_addr;
memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len);
tbf->bf_state = bf->bf_state;
+ tbf->bf_state.stale = false;
return tbf;
}
@@ -1389,11 +1390,15 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
u16 tid, u16 *ssn)
{
struct ath_atx_tid *txtid;
+ struct ath_txq *txq;
struct ath_node *an;
u8 density;
an = (struct ath_node *)sta->drv_priv;
txtid = ATH_AN_2_TID(an, tid);
+ txq = txtid->ac->txq;
+
+ ath_txq_lock(sc, txq);
/* update ampdu factor/density, they may have changed. This may happen
* in HT IBSS when a beacon with HT-info is received after the station
@@ -1417,6 +1422,8 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf));
txtid->baw_head = txtid->baw_tail = 0;
+ ath_txq_unlock_complete(sc, txq);
+
return 0;
}
@@ -1555,8 +1562,10 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
__skb_unlink(bf->bf_mpdu, tid_q);
list_add_tail(&bf->list, &bf_q);
ath_set_rates(tid->an->vif, tid->an->sta, bf);
- ath_tx_addto_baw(sc, tid, bf);
- bf->bf_state.bf_type &= ~BUF_AGGR;
+ if (bf_isampdu(bf)) {
+ ath_tx_addto_baw(sc, tid, bf);
+ bf->bf_state.bf_type &= ~BUF_AGGR;
+ }
if (bf_tail)
bf_tail->bf_next = bf;
@@ -1950,7 +1959,9 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
if (bf_is_ampdu_not_probing(bf))
txq->axq_ampdu_depth++;
- bf = bf->bf_lastbf->bf_next;
+ bf_last = bf->bf_lastbf;
+ bf = bf_last->bf_next;
+ bf_last->bf_next = NULL;
}
}
}
@@ -2315,7 +2326,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
if (sc->sc_ah->caldata)
- sc->sc_ah->caldata->paprd_packet_sent = true;
+ set_bit(PAPRD_PACKET_SENT, &sc->sc_ah->caldata->cal_flags);
if (!(tx_flags & ATH_TX_ERROR))
/* Frame was ACKed */
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index eb1dc7ad80fb..eeceab39cda2 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -197,7 +197,6 @@ static void wil_pcie_remove(struct pci_dev *pdev)
pci_iounmap(pdev, wil->csr);
pci_release_region(pdev, 0);
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
}
static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 64f4a2bc8dde..f28964a8bf50 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -464,20 +464,14 @@ static struct sdio_driver brcmf_sdmmc_driver = {
static int brcmf_sdio_pd_probe(struct platform_device *pdev)
{
- int ret;
-
brcmf_dbg(SDIO, "Enter\n");
- brcmfmac_sdio_pdata = pdev->dev.platform_data;
+ brcmfmac_sdio_pdata = dev_get_platdata(&pdev->dev);
if (brcmfmac_sdio_pdata->power_on)
brcmfmac_sdio_pdata->power_on();
- ret = sdio_register_driver(&brcmf_sdmmc_driver);
- if (ret)
- brcmf_err("sdio_register_driver failed: %d\n", ret);
-
- return ret;
+ return 0;
}
static int brcmf_sdio_pd_remove(struct platform_device *pdev)
@@ -500,6 +494,15 @@ static struct platform_driver brcmf_sdio_pd = {
}
};
+void brcmf_sdio_register(void)
+{
+ int ret;
+
+ ret = sdio_register_driver(&brcmf_sdmmc_driver);
+ if (ret)
+ brcmf_err("sdio_register_driver failed: %d\n", ret);
+}
+
void brcmf_sdio_exit(void)
{
brcmf_dbg(SDIO, "Enter\n");
@@ -510,18 +513,13 @@ void brcmf_sdio_exit(void)
sdio_unregister_driver(&brcmf_sdmmc_driver);
}
-void brcmf_sdio_init(void)
+void __init brcmf_sdio_init(void)
{
int ret;
brcmf_dbg(SDIO, "Enter\n");
ret = platform_driver_probe(&brcmf_sdio_pd, brcmf_sdio_pd_probe);
- if (ret == -ENODEV) {
- brcmf_dbg(SDIO, "No platform data available, registering without.\n");
- ret = sdio_register_driver(&brcmf_sdmmc_driver);
- }
-
- if (ret)
- brcmf_err("driver registration failed: %d\n", ret);
+ if (ret == -ENODEV)
+ brcmf_dbg(SDIO, "No platform data available.\n");
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index 2eb9e642c9bf..34af9d183107 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -632,29 +632,29 @@ struct brcmf_skb_reorder_data {
u8 *reorder;
};
-extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev);
+int brcmf_netdev_wait_pend8021x(struct net_device *ndev);
/* Return pointer to interface name */
-extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
+char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
/* Query dongle */
-extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx,
- uint cmd, void *buf, uint len);
-extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
- void *buf, uint len);
+int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
+ void *buf, uint len);
+int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
+ void *buf, uint len);
/* Remove any protocol-specific data header. */
-extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
- struct sk_buff *rxp);
+int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
+ struct sk_buff *rxp);
-extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
-extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx,
- s32 ifidx, char *name, u8 *mac_addr);
-extern void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
+int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
+struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
+ char *name, u8 *mac_addr);
+void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
void brcmf_txflowblock_if(struct brcmf_if *ifp,
enum brcmf_netif_stop_reason reason, bool state);
-extern u32 brcmf_get_chip_info(struct brcmf_if *ifp);
-extern void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
- bool success);
+u32 brcmf_get_chip_info(struct brcmf_if *ifp);
+void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
+ bool success);
#endif /* _BRCMF_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index f7c1985844e4..7f1340d03f18 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -132,34 +132,34 @@ struct pktq *brcmf_bus_gettxq(struct brcmf_bus *bus)
* interface functions from common layer
*/
-extern bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
- struct sk_buff *pkt, int prec);
+bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, struct sk_buff *pkt,
+ int prec);
/* Receive frame for delivery to OS. Callee disposes of rxp. */
-extern void brcmf_rx_frames(struct device *dev, struct sk_buff_head *rxlist);
+void brcmf_rx_frames(struct device *dev, struct sk_buff_head *rxlist);
/* Indication from bus module regarding presence/insertion of dongle. */
-extern int brcmf_attach(uint bus_hdrlen, struct device *dev);
+int brcmf_attach(uint bus_hdrlen, struct device *dev);
/* Indication from bus module regarding removal/absence of dongle */
-extern void brcmf_detach(struct device *dev);
+void brcmf_detach(struct device *dev);
/* Indication from bus module that dongle should be reset */
-extern void brcmf_dev_reset(struct device *dev);
+void brcmf_dev_reset(struct device *dev);
/* Indication from bus module to change flow-control state */
-extern void brcmf_txflowblock(struct device *dev, bool state);
+void brcmf_txflowblock(struct device *dev, bool state);
/* Notify the bus has transferred the tx packet to firmware */
-extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp,
- bool success);
+void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success);
-extern int brcmf_bus_start(struct device *dev);
+int brcmf_bus_start(struct device *dev);
#ifdef CONFIG_BRCMFMAC_SDIO
-extern void brcmf_sdio_exit(void);
-extern void brcmf_sdio_init(void);
+void brcmf_sdio_exit(void);
+void brcmf_sdio_init(void);
+void brcmf_sdio_register(void);
#endif
#ifdef CONFIG_BRCMFMAC_USB
-extern void brcmf_usb_exit(void);
-extern void brcmf_usb_init(void);
+void brcmf_usb_exit(void);
+void brcmf_usb_register(void);
#endif
#endif /* _BRCMF_BUS_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index e067aec1fbf1..40e7f854e10f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -1231,21 +1231,23 @@ u32 brcmf_get_chip_info(struct brcmf_if *ifp)
return bus->chip << 4 | bus->chiprev;
}
-static void brcmf_driver_init(struct work_struct *work)
+static void brcmf_driver_register(struct work_struct *work)
{
- brcmf_debugfs_init();
-
#ifdef CONFIG_BRCMFMAC_SDIO
- brcmf_sdio_init();
+ brcmf_sdio_register();
#endif
#ifdef CONFIG_BRCMFMAC_USB
- brcmf_usb_init();
+ brcmf_usb_register();
#endif
}
-static DECLARE_WORK(brcmf_driver_work, brcmf_driver_init);
+static DECLARE_WORK(brcmf_driver_work, brcmf_driver_register);
static int __init brcmfmac_module_init(void)
{
+ brcmf_debugfs_init();
+#ifdef CONFIG_BRCMFMAC_SDIO
+ brcmf_sdio_init();
+#endif
if (!schedule_work(&brcmf_driver_work))
return -EBUSY;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
index ef9179883748..53c6e710f2cb 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
@@ -22,21 +22,21 @@
*/
/* Linkage, sets prot link and updates hdrlen in pub */
-extern int brcmf_proto_attach(struct brcmf_pub *drvr);
+int brcmf_proto_attach(struct brcmf_pub *drvr);
/* Unlink, frees allocated protocol memory (including brcmf_proto) */
-extern void brcmf_proto_detach(struct brcmf_pub *drvr);
+void brcmf_proto_detach(struct brcmf_pub *drvr);
/* Stop protocol: sync w/dongle state. */
-extern void brcmf_proto_stop(struct brcmf_pub *drvr);
+void brcmf_proto_stop(struct brcmf_pub *drvr);
/* Add any protocol-specific data header.
* Caller must reserve prot_hdrlen prepend space.
*/
-extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, u8 offset,
- struct sk_buff *txp);
+void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, u8 offset,
+ struct sk_buff *txp);
/* Sets dongle media info (drv_version, mac address). */
-extern int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
+int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
#endif /* _BRCMF_PROTO_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
index 83c041f1bf4a..f0780ee05602 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.h
@@ -215,17 +215,16 @@ struct sdpcmd_regs {
u16 PAD[0x80];
};
-extern int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
- struct chip_info **ci_ptr, u32 regs);
-extern void brcmf_sdio_chip_detach(struct chip_info **ci_ptr);
-extern void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci,
- u32 drivestrength);
-extern u8 brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid);
-extern void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci);
-extern bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
- struct chip_info *ci, char *nvram_dat,
- uint nvram_sz);
+int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info **ci_ptr, u32 regs);
+void brcmf_sdio_chip_detach(struct chip_info **ci_ptr);
+void brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci, u32 drivestrength);
+u8 brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid);
+void brcmf_sdio_chip_enter_download(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci);
+bool brcmf_sdio_chip_exit_download(struct brcmf_sdio_dev *sdiodev,
+ struct chip_info *ci, char *nvram_dat,
+ uint nvram_sz);
#endif /* _BRCMFMAC_SDIO_CHIP_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 2b5407f002e5..c9b06b4e71f7 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -181,18 +181,18 @@ struct brcmf_sdio_dev {
};
/* Register/deregister interrupt handler. */
-extern int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev);
-extern int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev);
+int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev);
+int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev);
/* sdio device register access interface */
-extern u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
-extern u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
-extern void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
- u8 data, int *ret);
-extern void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
- u32 data, int *ret);
-extern int brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
- void *data, bool write);
+u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
+u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
+void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, u8 data,
+ int *ret);
+void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data,
+ int *ret);
+int brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
+ void *data, bool write);
/* Buffer transfer to/from device (client) core via cmd53.
* fn: function number
@@ -206,22 +206,17 @@ extern int brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
* Returns 0 or error code.
* NOTE: Async operation is not currently supported.
*/
-extern int
-brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
- uint flags, struct sk_buff_head *pktq);
-extern int
-brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
- uint flags, u8 *buf, uint nbytes);
-
-extern int
-brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
- uint flags, struct sk_buff *pkt);
-extern int
-brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
- uint flags, u8 *buf, uint nbytes);
-extern int
-brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
- uint flags, struct sk_buff_head *pktq);
+int brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
+ uint flags, struct sk_buff_head *pktq);
+int brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
+ uint flags, u8 *buf, uint nbytes);
+
+int brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
+ uint flags, struct sk_buff *pkt);
+int brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
+ uint flags, u8 *buf, uint nbytes);
+int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
+ uint flags, struct sk_buff_head *pktq);
/* Flags bits */
@@ -237,46 +232,43 @@ brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
* nbytes: number of bytes to transfer to/from buf
* Returns 0 or error code.
*/
-extern int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw,
- u32 addr, u8 *buf, uint nbytes);
-extern int brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write,
- u32 address, u8 *data, uint size);
+int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr,
+ u8 *buf, uint nbytes);
+int brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
+ u8 *data, uint size);
/* Issue an abort to the specified function */
-extern int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
+int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
/* platform specific/high level functions */
-extern int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
-extern int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev);
+int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
+int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev);
/* attach, return handler on success, NULL if failed.
* The handler shall be provided by all subsequent calls. No local cache
* cfghdl points to the starting address of pci device mapped memory
*/
-extern int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev);
-extern void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev);
+int brcmf_sdioh_attach(struct brcmf_sdio_dev *sdiodev);
+void brcmf_sdioh_detach(struct brcmf_sdio_dev *sdiodev);
/* read or write one byte using cmd52 */
-extern int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw,
- uint fnc, uint addr, u8 *byte);
+int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint fnc,
+ uint addr, u8 *byte);
/* read or write 2/4 bytes using cmd53 */
-extern int
-brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
- uint rw, uint fnc, uint addr,
- u32 *word, uint nbyte);
+int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, uint rw, uint fnc,
+ uint addr, u32 *word, uint nbyte);
/* Watchdog timer interface for pm ops */
-extern void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev,
- bool enable);
+void brcmf_sdio_wdtmr_enable(struct brcmf_sdio_dev *sdiodev, bool enable);
-extern void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev);
-extern void brcmf_sdbrcm_disconnect(void *ptr);
-extern void brcmf_sdbrcm_isr(void *arg);
+void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev);
+void brcmf_sdbrcm_disconnect(void *ptr);
+void brcmf_sdbrcm_isr(void *arg);
-extern void brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick);
+void brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick);
-extern void brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev,
- wait_queue_head_t *wq);
-extern bool brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev);
+void brcmf_pm_resume_wait(struct brcmf_sdio_dev *sdiodev,
+ wait_queue_head_t *wq);
+bool brcmf_pm_resume_error(struct brcmf_sdio_dev *sdiodev);
#endif /* _BRCM_SDH_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index 39e01a7c8556..f4aea47e0730 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -1539,7 +1539,7 @@ void brcmf_usb_exit(void)
brcmf_release_fw(&fw_image_list);
}
-void brcmf_usb_init(void)
+void brcmf_usb_register(void)
{
brcmf_dbg(USB, "Enter\n");
INIT_LIST_HEAD(&fw_image_list);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h
index a8a267b5b87a..2d08c155c23b 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h
@@ -172,19 +172,19 @@ struct si_info {
/* AMBA Interconnect exported externs */
-extern u32 ai_core_cflags(struct bcma_device *core, u32 mask, u32 val);
+u32 ai_core_cflags(struct bcma_device *core, u32 mask, u32 val);
/* === exported functions === */
-extern struct si_pub *ai_attach(struct bcma_bus *pbus);
-extern void ai_detach(struct si_pub *sih);
-extern uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val);
-extern void ai_clkctl_init(struct si_pub *sih);
-extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih);
-extern bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode);
-extern bool ai_deviceremoved(struct si_pub *sih);
+struct si_pub *ai_attach(struct bcma_bus *pbus);
+void ai_detach(struct si_pub *sih);
+uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val);
+void ai_clkctl_init(struct si_pub *sih);
+u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih);
+bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode);
+bool ai_deviceremoved(struct si_pub *sih);
/* Enable Ex-PA for 4313 */
-extern void ai_epa_4313war(struct si_pub *sih);
+void ai_epa_4313war(struct si_pub *sih);
static inline u32 ai_get_cccaps(struct si_pub *sih)
{
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h
index 73d01e586109..03bdcf29bd50 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.h
@@ -37,17 +37,17 @@ struct brcms_ampdu_session {
u16 dma_len;
};
-extern void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session,
- struct brcms_c_info *wlc);
-extern int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,
- struct sk_buff *p);
-extern void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session);
+void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session,
+ struct brcms_c_info *wlc);
+int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,
+ struct sk_buff *p);
+void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session);
-extern struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc);
-extern void brcms_c_ampdu_detach(struct ampdu_info *ampdu);
-extern void brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
- struct sk_buff *p, struct tx_status *txs);
-extern void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc);
-extern void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu);
+struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc);
+void brcms_c_ampdu_detach(struct ampdu_info *ampdu);
+void brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
+ struct sk_buff *p, struct tx_status *txs);
+void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc);
+void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu);
#endif /* _BRCM_AMPDU_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/antsel.h b/drivers/net/wireless/brcm80211/brcmsmac/antsel.h
index 97ea3881a8ec..a3d487ab1964 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/antsel.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/antsel.h
@@ -17,13 +17,11 @@
#ifndef _BRCM_ANTSEL_H_
#define _BRCM_ANTSEL_H_
-extern struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc);
-extern void brcms_c_antsel_detach(struct antsel_info *asi);
-extern void brcms_c_antsel_init(struct antsel_info *asi);
-extern void brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef,
- bool sel,
- u8 id, u8 fbid, u8 *antcfg,
- u8 *fbantcfg);
-extern u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel);
+struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc);
+void brcms_c_antsel_detach(struct antsel_info *asi);
+void brcms_c_antsel_init(struct antsel_info *asi);
+void brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef, bool sel,
+ u8 id, u8 fbid, u8 *antcfg, u8 *fbantcfg);
+u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel);
#endif /* _BRCM_ANTSEL_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.h b/drivers/net/wireless/brcm80211/brcmsmac/channel.h
index 006483a0abe6..39dd3a5b2979 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.h
@@ -32,20 +32,16 @@
#define BRCMS_DFS_EU (BRCMS_DFS_TPC | BRCMS_RADAR_TYPE_EU) /* Flag for DFS EU */
-extern struct brcms_cm_info *
-brcms_c_channel_mgr_attach(struct brcms_c_info *wlc);
+struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc);
-extern void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm);
+void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm);
-extern bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm,
- u16 chspec);
+bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec);
-extern void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm,
- u16 chanspec,
- struct txpwr_limits *txpwr);
-extern void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm,
- u16 chanspec,
- u8 local_constraint_qdbm);
-extern void brcms_c_regd_init(struct brcms_c_info *wlc);
+void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
+ struct txpwr_limits *txpwr);
+void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
+ u8 local_constraint_qdbm);
+void brcms_c_regd_init(struct brcms_c_info *wlc);
#endif /* _WLC_CHANNEL_H */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index 3a6544710c8a..edc5d105ff98 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -457,6 +457,8 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
if (err != 0)
brcms_err(wl->wlc->hw->d11core, "%s: brcms_up() returned %d\n",
__func__, err);
+
+ bcma_core_pci_power_save(wl->wlc->hw->d11core->bus, true);
return err;
}
@@ -479,6 +481,8 @@ static void brcms_ops_stop(struct ieee80211_hw *hw)
return;
}
+ bcma_core_pci_power_save(wl->wlc->hw->d11core->bus, false);
+
/* put driver in down state */
spin_lock_bh(&wl->lock);
brcms_down(wl);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
index 4090032e81a2..198053dfc310 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
@@ -88,26 +88,26 @@ struct brcms_info {
};
/* misc callbacks */
-extern void brcms_init(struct brcms_info *wl);
-extern uint brcms_reset(struct brcms_info *wl);
-extern void brcms_intrson(struct brcms_info *wl);
-extern u32 brcms_intrsoff(struct brcms_info *wl);
-extern void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask);
-extern int brcms_up(struct brcms_info *wl);
-extern void brcms_down(struct brcms_info *wl);
-extern void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
- bool state, int prio);
-extern bool brcms_rfkill_set_hw_state(struct brcms_info *wl);
+void brcms_init(struct brcms_info *wl);
+uint brcms_reset(struct brcms_info *wl);
+void brcms_intrson(struct brcms_info *wl);
+u32 brcms_intrsoff(struct brcms_info *wl);
+void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask);
+int brcms_up(struct brcms_info *wl);
+void brcms_down(struct brcms_info *wl);
+void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
+ bool state, int prio);
+bool brcms_rfkill_set_hw_state(struct brcms_info *wl);
/* timer functions */
-extern struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
- void (*fn) (void *arg), void *arg,
- const char *name);
-extern void brcms_free_timer(struct brcms_timer *timer);
-extern void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic);
-extern bool brcms_del_timer(struct brcms_timer *timer);
-extern void brcms_dpc(unsigned long data);
-extern void brcms_timer(struct brcms_timer *t);
-extern void brcms_fatal_error(struct brcms_info *wl);
+struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
+ void (*fn) (void *arg), void *arg,
+ const char *name);
+void brcms_free_timer(struct brcms_timer *timer);
+void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic);
+bool brcms_del_timer(struct brcms_timer *timer);
+void brcms_dpc(unsigned long data);
+void brcms_timer(struct brcms_timer *t);
+void brcms_fatal_error(struct brcms_info *wl);
#endif /* _BRCM_MAC80211_IF_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h
index b5d7a38b53fe..c4d135cff04a 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h
@@ -616,66 +616,54 @@ struct brcms_bss_cfg {
struct brcms_bss_info *current_bss;
};
-extern int brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo,
- struct sk_buff *p);
-extern int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
- uint *blocks);
-
-extern int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config);
-extern void brcms_c_mac_promisc(struct brcms_c_info *wlc, uint filter_flags);
-extern u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec,
- uint mac_len);
-extern u32 brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc,
- u32 rspec,
- bool use_rspec, u16 mimo_ctlchbw);
-extern u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
- u32 rts_rate,
- u32 frame_rate,
- u8 rts_preamble_type,
- u8 frame_preamble_type, uint frame_len,
- bool ba);
-extern void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
- struct ieee80211_sta *sta,
- void (*dma_callback_fn));
-extern void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend);
-extern int brcms_c_set_nmode(struct brcms_c_info *wlc);
-extern void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc,
- u32 bcn_rate);
-extern void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw,
- u8 antsel_type);
-extern void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw,
- u16 chanspec,
- bool mute, struct txpwr_limits *txpwr);
-extern void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset,
- u16 v);
-extern u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset);
-extern void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask,
- u16 val, int bands);
-extern void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags);
-extern void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val);
-extern void brcms_b_phy_reset(struct brcms_hardware *wlc_hw);
-extern void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw);
-extern void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw);
-extern void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw,
- u32 override_bit);
-extern void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw,
- u32 override_bit);
-extern void brcms_b_write_template_ram(struct brcms_hardware *wlc_hw,
- int offset, int len, void *buf);
-extern u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate);
-extern void brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw,
- uint offset, const void *buf, int len,
- u32 sel);
-extern void brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset,
- void *buf, int len, u32 sel);
-extern void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode);
-extern u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw);
-extern void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk);
-extern void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk);
-extern void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on);
-extern void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant);
-extern void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw,
- u8 stf_mode);
-extern void brcms_c_init_scb(struct scb *scb);
+int brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p);
+int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
+ uint *blocks);
+
+int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config);
+void brcms_c_mac_promisc(struct brcms_c_info *wlc, uint filter_flags);
+u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec, uint mac_len);
+u32 brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec,
+ bool use_rspec, u16 mimo_ctlchbw);
+u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
+ u32 rts_rate, u32 frame_rate,
+ u8 rts_preamble_type, u8 frame_preamble_type,
+ uint frame_len, bool ba);
+void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
+ struct ieee80211_sta *sta, void (*dma_callback_fn));
+void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend);
+int brcms_c_set_nmode(struct brcms_c_info *wlc);
+void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, u32 bcn_rate);
+void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type);
+void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec,
+ bool mute, struct txpwr_limits *txpwr);
+void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, u16 v);
+u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset);
+void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, u16 val,
+ int bands);
+void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags);
+void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val);
+void brcms_b_phy_reset(struct brcms_hardware *wlc_hw);
+void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw);
+void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw);
+void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw,
+ u32 override_bit);
+void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw,
+ u32 override_bit);
+void brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset,
+ int len, void *buf);
+u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate);
+void brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, uint offset,
+ const void *buf, int len, u32 sel);
+void brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset,
+ void *buf, int len, u32 sel);
+void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode);
+u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw);
+void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk);
+void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk);
+void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on);
+void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant);
+void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode);
+void brcms_c_init_scb(struct scb *scb);
#endif /* _BRCM_MAIN_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h
index e34a71e7d242..4d3734f48d9c 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_hal.h
@@ -179,121 +179,106 @@ struct shared_phy_params {
};
-extern struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp);
-extern struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh,
- struct bcma_device *d11core,
- int bandtype, struct wiphy *wiphy);
-extern void wlc_phy_detach(struct brcms_phy_pub *ppi);
-
-extern bool wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype,
- u16 *phyrev, u16 *radioid,
- u16 *radiover);
-extern bool wlc_phy_get_encore(struct brcms_phy_pub *pih);
-extern u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih);
-
-extern void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *ppi, bool newstate);
-extern void wlc_phy_hw_state_upd(struct brcms_phy_pub *ppi, bool newstate);
-extern void wlc_phy_init(struct brcms_phy_pub *ppi, u16 chanspec);
-extern void wlc_phy_watchdog(struct brcms_phy_pub *ppi);
-extern int wlc_phy_down(struct brcms_phy_pub *ppi);
-extern u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih);
-extern void wlc_phy_cal_init(struct brcms_phy_pub *ppi);
-extern void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init);
-
-extern void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi,
- u16 chanspec);
-extern u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi);
-extern void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi,
- u16 newch);
-extern u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi);
-extern void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw);
-
-extern int wlc_phy_rssi_compute(struct brcms_phy_pub *pih,
- struct d11rxhdr *rxh);
-extern void wlc_phy_por_inform(struct brcms_phy_pub *ppi);
-extern void wlc_phy_noise_sample_intr(struct brcms_phy_pub *ppi);
-extern bool wlc_phy_bist_check_phy(struct brcms_phy_pub *ppi);
-
-extern void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag);
-
-extern void wlc_phy_switch_radio(struct brcms_phy_pub *ppi, bool on);
-extern void wlc_phy_anacore(struct brcms_phy_pub *ppi, bool on);
-
-
-extern void wlc_phy_BSSinit(struct brcms_phy_pub *ppi, bool bonlyap, int rssi);
-
-extern void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi,
- bool wide_filter);
-extern void wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band,
- struct brcms_chanvec *channels);
-extern u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi,
- uint band);
-
-extern void wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint chan,
- u8 *_min_, u8 *_max_, int rate);
-extern void wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi,
- uint chan, u8 *_max_, u8 *_min_);
-extern void wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi,
- uint band, s32 *, s32 *, u32 *);
-extern void wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi,
- struct txpwr_limits *,
- u16 chanspec);
-extern int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm,
- bool *override);
-extern int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm,
- bool override);
-extern void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi,
- struct txpwr_limits *);
-extern bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi);
-extern void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi,
- bool hwpwrctrl);
-extern u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi);
-extern u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi);
-extern bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *pih);
-
-extern void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain,
- u8 rxchain);
-extern void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain,
- u8 rxchain);
-extern void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain,
- u8 *rxchain);
-extern u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih);
-extern s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih,
- u16 chanspec);
-extern void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool val);
-
-extern void wlc_phy_cal_perical(struct brcms_phy_pub *ppi, u8 reason);
-extern void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *ppi);
-extern void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock);
-extern void wlc_phy_cal_papd_recal(struct brcms_phy_pub *ppi);
-
-extern void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val);
-extern void wlc_phy_clear_tssi(struct brcms_phy_pub *ppi);
-extern void wlc_phy_hold_upd(struct brcms_phy_pub *ppi, u32 id, bool val);
-extern void wlc_phy_mute_upd(struct brcms_phy_pub *ppi, bool val, u32 flags);
-
-extern void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type);
-
-extern void wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi,
- struct tx_power *power, uint channel);
-
-extern void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal);
-extern bool wlc_phy_test_ison(struct brcms_phy_pub *ppi);
-extern void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi,
- u8 txpwr_percent);
-extern void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war);
-extern void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih,
- bool bf_preempt);
-extern void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap);
-
-extern void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end);
-
-extern void wlc_phy_freqtrack_start(struct brcms_phy_pub *ppi);
-extern void wlc_phy_freqtrack_end(struct brcms_phy_pub *ppi);
-
-extern const u8 *wlc_phy_get_ofdm_rate_lookup(void);
-
-extern s8 wlc_phy_get_tx_power_offset_by_mcs(struct brcms_phy_pub *ppi,
- u8 mcs_offset);
-extern s8 wlc_phy_get_tx_power_offset(struct brcms_phy_pub *ppi, u8 tbl_offset);
+struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp);
+struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh,
+ struct bcma_device *d11core, int bandtype,
+ struct wiphy *wiphy);
+void wlc_phy_detach(struct brcms_phy_pub *ppi);
+
+bool wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype,
+ u16 *phyrev, u16 *radioid, u16 *radiover);
+bool wlc_phy_get_encore(struct brcms_phy_pub *pih);
+u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih);
+
+void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *ppi, bool newstate);
+void wlc_phy_hw_state_upd(struct brcms_phy_pub *ppi, bool newstate);
+void wlc_phy_init(struct brcms_phy_pub *ppi, u16 chanspec);
+void wlc_phy_watchdog(struct brcms_phy_pub *ppi);
+int wlc_phy_down(struct brcms_phy_pub *ppi);
+u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih);
+void wlc_phy_cal_init(struct brcms_phy_pub *ppi);
+void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init);
+
+void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, u16 chanspec);
+u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi);
+void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, u16 newch);
+u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi);
+void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw);
+
+int wlc_phy_rssi_compute(struct brcms_phy_pub *pih, struct d11rxhdr *rxh);
+void wlc_phy_por_inform(struct brcms_phy_pub *ppi);
+void wlc_phy_noise_sample_intr(struct brcms_phy_pub *ppi);
+bool wlc_phy_bist_check_phy(struct brcms_phy_pub *ppi);
+
+void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag);
+
+void wlc_phy_switch_radio(struct brcms_phy_pub *ppi, bool on);
+void wlc_phy_anacore(struct brcms_phy_pub *ppi, bool on);
+
+
+void wlc_phy_BSSinit(struct brcms_phy_pub *ppi, bool bonlyap, int rssi);
+
+void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi,
+ bool wide_filter);
+void wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band,
+ struct brcms_chanvec *channels);
+u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band);
+
+void wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint chan, u8 *_min_,
+ u8 *_max_, int rate);
+void wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, uint chan,
+ u8 *_max_, u8 *_min_);
+void wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi, uint band,
+ s32 *, s32 *, u32 *);
+void wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *,
+ u16 chanspec);
+int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, bool *override);
+int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override);
+void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi,
+ struct txpwr_limits *);
+bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi);
+void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl);
+u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi);
+u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi);
+bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *pih);
+
+void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain);
+void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain);
+void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, u8 *rxchain);
+u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih);
+s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, u16 chanspec);
+void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool val);
+
+void wlc_phy_cal_perical(struct brcms_phy_pub *ppi, u8 reason);
+void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *ppi);
+void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock);
+void wlc_phy_cal_papd_recal(struct brcms_phy_pub *ppi);
+
+void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val);
+void wlc_phy_clear_tssi(struct brcms_phy_pub *ppi);
+void wlc_phy_hold_upd(struct brcms_phy_pub *ppi, u32 id, bool val);
+void wlc_phy_mute_upd(struct brcms_phy_pub *ppi, bool val, u32 flags);
+
+void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type);
+
+void wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi,
+ struct tx_power *power, uint channel);
+
+void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal);
+bool wlc_phy_test_ison(struct brcms_phy_pub *ppi);
+void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi, u8 txpwr_percent);
+void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war);
+void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, bool bf_preempt);
+void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap);
+
+void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end);
+
+void wlc_phy_freqtrack_start(struct brcms_phy_pub *ppi);
+void wlc_phy_freqtrack_end(struct brcms_phy_pub *ppi);
+
+const u8 *wlc_phy_get_ofdm_rate_lookup(void);
+
+s8 wlc_phy_get_tx_power_offset_by_mcs(struct brcms_phy_pub *ppi,
+ u8 mcs_offset);
+s8 wlc_phy_get_tx_power_offset(struct brcms_phy_pub *ppi, u8 tbl_offset);
#endif /* _BRCM_PHY_HAL_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h
index 1dc767c31653..4960f7d26804 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h
@@ -910,113 +910,103 @@ struct lcnphy_radio_regs {
u8 do_init_g;
};
-extern u16 read_phy_reg(struct brcms_phy *pi, u16 addr);
-extern void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val);
-extern void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val);
-extern void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val);
-extern void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val);
-
-extern u16 read_radio_reg(struct brcms_phy *pi, u16 addr);
-extern void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val);
-extern void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val);
-extern void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask,
- u16 val);
-extern void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask);
-
-extern void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val);
-
-extern void wlc_phyreg_enter(struct brcms_phy_pub *pih);
-extern void wlc_phyreg_exit(struct brcms_phy_pub *pih);
-extern void wlc_radioreg_enter(struct brcms_phy_pub *pih);
-extern void wlc_radioreg_exit(struct brcms_phy_pub *pih);
-
-extern void wlc_phy_read_table(struct brcms_phy *pi,
- const struct phytbl_info *ptbl_info,
- u16 tblAddr, u16 tblDataHi,
- u16 tblDatalo);
-extern void wlc_phy_write_table(struct brcms_phy *pi,
- const struct phytbl_info *ptbl_info,
- u16 tblAddr, u16 tblDataHi, u16 tblDatalo);
-extern void wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id,
- uint tbl_offset, u16 tblAddr, u16 tblDataHi,
- u16 tblDataLo);
-extern void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val);
-
-extern void write_phy_channel_reg(struct brcms_phy *pi, uint val);
-extern void wlc_phy_txpower_update_shm(struct brcms_phy *pi);
-
-extern u8 wlc_phy_nbits(s32 value);
-extern void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_dB, u8 core);
-
-extern uint wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi,
- struct radio_20xx_regs *radioregs);
-extern uint wlc_phy_init_radio_regs(struct brcms_phy *pi,
- const struct radio_regs *radioregs,
- u16 core_offset);
-
-extern void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi);
-
-extern void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on);
-extern void wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real,
- s32 *eps_imag);
-
-extern void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi);
-extern void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi);
-
-extern bool wlc_phy_attach_nphy(struct brcms_phy *pi);
-extern bool wlc_phy_attach_lcnphy(struct brcms_phy *pi);
-
-extern void wlc_phy_detach_lcnphy(struct brcms_phy *pi);
-
-extern void wlc_phy_init_nphy(struct brcms_phy *pi);
-extern void wlc_phy_init_lcnphy(struct brcms_phy *pi);
-
-extern void wlc_phy_cal_init_nphy(struct brcms_phy *pi);
-extern void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi);
-
-extern void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi,
- u16 chanspec);
-extern void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi,
- u16 chanspec);
-extern void wlc_phy_chanspec_set_fixup_lcnphy(struct brcms_phy *pi,
- u16 chanspec);
-extern int wlc_phy_channel2freq(uint channel);
-extern int wlc_phy_chanspec_freq2bandrange_lpssn(uint);
-extern int wlc_phy_chanspec_bandrange_get(struct brcms_phy *, u16 chanspec);
-
-extern void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode);
-extern s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi);
-
-extern void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi);
-extern void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi);
-extern void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi);
-
-extern void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index);
-extern void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable);
-extern void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi);
-extern void wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz,
- u16 max_val, bool iqcalmode);
-
-extern void wlc_phy_txpower_sromlimit_get_nphy(struct brcms_phy *pi, uint chan,
- u8 *max_pwr, u8 rate_id);
-extern void wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start,
- u8 rate_mcs_end,
- u8 rate_ofdm_start);
-extern void wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power,
- u8 rate_ofdm_start,
- u8 rate_ofdm_end,
- u8 rate_mcs_start);
-
-extern u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode);
-extern s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode);
-extern s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode);
-extern s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode);
-extern void wlc_phy_carrier_suppress_lcnphy(struct brcms_phy *pi);
-extern void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel);
-extern void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode);
-extern void wlc_2064_vco_cal(struct brcms_phy *pi);
-
-extern void wlc_phy_txpower_recalc_target(struct brcms_phy *pi);
+u16 read_phy_reg(struct brcms_phy *pi, u16 addr);
+void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val);
+void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val);
+void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val);
+void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val);
+
+u16 read_radio_reg(struct brcms_phy *pi, u16 addr);
+void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val);
+void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val);
+void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val);
+void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask);
+
+void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val);
+
+void wlc_phyreg_enter(struct brcms_phy_pub *pih);
+void wlc_phyreg_exit(struct brcms_phy_pub *pih);
+void wlc_radioreg_enter(struct brcms_phy_pub *pih);
+void wlc_radioreg_exit(struct brcms_phy_pub *pih);
+
+void wlc_phy_read_table(struct brcms_phy *pi,
+ const struct phytbl_info *ptbl_info,
+ u16 tblAddr, u16 tblDataHi, u16 tblDatalo);
+void wlc_phy_write_table(struct brcms_phy *pi,
+ const struct phytbl_info *ptbl_info,
+ u16 tblAddr, u16 tblDataHi, u16 tblDatalo);
+void wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset,
+ u16 tblAddr, u16 tblDataHi, u16 tblDataLo);
+void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val);
+
+void write_phy_channel_reg(struct brcms_phy *pi, uint val);
+void wlc_phy_txpower_update_shm(struct brcms_phy *pi);
+
+u8 wlc_phy_nbits(s32 value);
+void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_dB, u8 core);
+
+uint wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi,
+ struct radio_20xx_regs *radioregs);
+uint wlc_phy_init_radio_regs(struct brcms_phy *pi,
+ const struct radio_regs *radioregs,
+ u16 core_offset);
+
+void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi);
+
+void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on);
+void wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag);
+
+void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi);
+void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi);
+
+bool wlc_phy_attach_nphy(struct brcms_phy *pi);
+bool wlc_phy_attach_lcnphy(struct brcms_phy *pi);
+
+void wlc_phy_detach_lcnphy(struct brcms_phy *pi);
+
+void wlc_phy_init_nphy(struct brcms_phy *pi);
+void wlc_phy_init_lcnphy(struct brcms_phy *pi);
+
+void wlc_phy_cal_init_nphy(struct brcms_phy *pi);
+void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi);
+
+void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, u16 chanspec);
+void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec);
+void wlc_phy_chanspec_set_fixup_lcnphy(struct brcms_phy *pi, u16 chanspec);
+int wlc_phy_channel2freq(uint channel);
+int wlc_phy_chanspec_freq2bandrange_lpssn(uint);
+int wlc_phy_chanspec_bandrange_get(struct brcms_phy *, u16 chanspec);
+
+void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode);
+s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi);
+
+void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi);
+void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi);
+void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi);
+
+void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index);
+void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable);
+void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi);
+void wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, u16 max_val,
+ bool iqcalmode);
+
+void wlc_phy_txpower_sromlimit_get_nphy(struct brcms_phy *pi, uint chan,
+ u8 *max_pwr, u8 rate_id);
+void wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start,
+ u8 rate_mcs_end, u8 rate_ofdm_start);
+void wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power, u8 rate_ofdm_start,
+ u8 rate_ofdm_end, u8 rate_mcs_start);
+
+u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode);
+s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode);
+s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode);
+s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode);
+void wlc_phy_carrier_suppress_lcnphy(struct brcms_phy *pi);
+void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel);
+void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode);
+void wlc_2064_vco_cal(struct brcms_phy *pi);
+
+void wlc_phy_txpower_recalc_target(struct brcms_phy *pi);
#define LCNPHY_TBL_ID_PAPDCOMPDELTATBL 0x18
#define LCNPHY_TX_POWER_TABLE_SIZE 128
@@ -1030,26 +1020,24 @@ extern void wlc_phy_txpower_recalc_target(struct brcms_phy *pi);
#define LCNPHY_TX_PWR_CTRL_TEMPBASED 0xE001
-extern void wlc_lcnphy_write_table(struct brcms_phy *pi,
- const struct phytbl_info *pti);
-extern void wlc_lcnphy_read_table(struct brcms_phy *pi,
- struct phytbl_info *pti);
-extern void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b);
-extern void wlc_lcnphy_set_tx_locc(struct brcms_phy *pi, u16 didq);
-extern void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b);
-extern u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi);
-extern void wlc_lcnphy_get_radio_loft(struct brcms_phy *pi, u8 *ei0,
- u8 *eq0, u8 *fi0, u8 *fq0);
-extern void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode);
-extern void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode);
-extern bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi);
-extern void wlc_lcnphy_tx_pwr_update_npt(struct brcms_phy *pi);
-extern s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1);
-extern void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr,
- s8 *cck_pwr);
-extern void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi);
-
-extern s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index);
+void wlc_lcnphy_write_table(struct brcms_phy *pi,
+ const struct phytbl_info *pti);
+void wlc_lcnphy_read_table(struct brcms_phy *pi, struct phytbl_info *pti);
+void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b);
+void wlc_lcnphy_set_tx_locc(struct brcms_phy *pi, u16 didq);
+void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b);
+u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi);
+void wlc_lcnphy_get_radio_loft(struct brcms_phy *pi, u8 *ei0, u8 *eq0, u8 *fi0,
+ u8 *fq0);
+void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode);
+void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode);
+bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi);
+void wlc_lcnphy_tx_pwr_update_npt(struct brcms_phy *pi);
+s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1);
+void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, s8 *cck_pwr);
+void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi);
+
+s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index);
#define NPHY_MAX_HPVGA1_INDEX 10
#define NPHY_DEF_HPVGA1_INDEXLIMIT 7
@@ -1060,9 +1048,8 @@ struct phy_iq_est {
u32 q_pwr;
};
-extern void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi,
- bool enable);
-extern void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode);
+void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi, bool enable);
+void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode);
#define wlc_phy_write_table_nphy(pi, pti) \
wlc_phy_write_table(pi, pti, 0x72, 0x74, 0x73)
@@ -1076,10 +1063,10 @@ extern void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode);
#define wlc_nphy_table_data_write(pi, w, v) \
wlc_phy_table_data_write((pi), (w), (v))
-extern void wlc_phy_table_read_nphy(struct brcms_phy *pi, u32, u32 l, u32 o,
- u32 w, void *d);
-extern void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32, u32, u32,
- u32, const void *);
+void wlc_phy_table_read_nphy(struct brcms_phy *pi, u32, u32 l, u32 o, u32 w,
+ void *d);
+void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32, u32, u32, u32,
+ const void *);
#define PHY_IPA(pi) \
((pi->ipa2g_on && CHSPEC_IS2G(pi->radio_chanspec)) || \
@@ -1089,73 +1076,67 @@ extern void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32, u32, u32,
if (NREV_LT((pi)->pubpi.phy_rev, 3)) \
(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol))
-extern void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype);
-extern void wlc_phy_aci_reset_nphy(struct brcms_phy *pi);
-extern void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en);
-
-extern u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint chan);
-extern void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on);
-
-extern void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi);
-
-extern void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd);
-extern s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi);
-
-extern u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val);
-
-extern void wlc_phy_rx_iq_est_nphy(struct brcms_phy *pi, struct phy_iq_est *est,
- u16 num_samps, u8 wait_time,
- u8 wait_for_crs);
-
-extern void wlc_phy_rx_iq_coeffs_nphy(struct brcms_phy *pi, u8 write,
- struct nphy_iq_comp *comp);
-extern void wlc_phy_aci_and_noise_reduction_nphy(struct brcms_phy *pi);
-
-extern void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih,
- u8 rxcore_bitmask);
-extern u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih);
-
-extern void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type);
-extern void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi);
-extern void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi);
-extern void wlc_phy_txpwr_papd_cal_nphy(struct brcms_phy *pi);
-extern u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi);
-
-extern struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi);
-extern int wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi,
- struct nphy_txgains target_gain,
- bool full, bool m);
-extern int wlc_phy_cal_rxiq_nphy(struct brcms_phy *pi,
- struct nphy_txgains target_gain,
- u8 type, bool d);
-extern void wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask,
- s8 txpwrindex, bool res);
-extern void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core, u8 rssi_type);
-extern int wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type,
- s32 *rssi_buf, u8 nsamps);
-extern void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi);
-extern int wlc_phy_aci_scan_nphy(struct brcms_phy *pi);
-extern void wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi,
- s32 dBm_targetpower, bool debug);
-extern int wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val,
- u8 mode, u8, bool);
-extern void wlc_phy_stopplayback_nphy(struct brcms_phy *pi);
-extern void wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf,
- u8 num_samps);
-extern void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi);
-
-extern int wlc_phy_rssi_compute_nphy(struct brcms_phy *pi,
- struct d11rxhdr *rxh);
+void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype);
+void wlc_phy_aci_reset_nphy(struct brcms_phy *pi);
+void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en);
+
+u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint chan);
+void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on);
+
+void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi);
+
+void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd);
+s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi);
+
+u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val);
+
+void wlc_phy_rx_iq_est_nphy(struct brcms_phy *pi, struct phy_iq_est *est,
+ u16 num_samps, u8 wait_time, u8 wait_for_crs);
+
+void wlc_phy_rx_iq_coeffs_nphy(struct brcms_phy *pi, u8 write,
+ struct nphy_iq_comp *comp);
+void wlc_phy_aci_and_noise_reduction_nphy(struct brcms_phy *pi);
+
+void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, u8 rxcore_bitmask);
+u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih);
+
+void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type);
+void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi);
+void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi);
+void wlc_phy_txpwr_papd_cal_nphy(struct brcms_phy *pi);
+u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi);
+
+struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi);
+int wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi,
+ struct nphy_txgains target_gain, bool full, bool m);
+int wlc_phy_cal_rxiq_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
+ u8 type, bool d);
+void wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask,
+ s8 txpwrindex, bool res);
+void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core, u8 rssi_type);
+int wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type,
+ s32 *rssi_buf, u8 nsamps);
+void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi);
+int wlc_phy_aci_scan_nphy(struct brcms_phy *pi);
+void wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, s32 dBm_targetpower,
+ bool debug);
+int wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, u8 mode,
+ u8, bool);
+void wlc_phy_stopplayback_nphy(struct brcms_phy *pi);
+void wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf,
+ u8 num_samps);
+void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi);
+
+int wlc_phy_rssi_compute_nphy(struct brcms_phy *pi, struct d11rxhdr *rxh);
#define NPHY_TESTPATTERN_BPHY_EVM 0
#define NPHY_TESTPATTERN_BPHY_RFCS 1
-extern void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs);
+void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs);
void wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset,
s8 *ofdmoffset);
-extern s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi,
- u16 chanspec);
+s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, u16 chanspec);
-extern bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pih);
+bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pih);
#endif /* _BRCM_PHY_INT_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h b/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h
index 2c5b66b75970..dd8774717ade 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h
@@ -124,56 +124,49 @@
struct brcms_phy;
-extern struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw,
- struct brcms_info *wl,
- struct brcms_c_info *wlc);
-extern void wlc_phy_shim_detach(struct phy_shim_info *physhim);
+struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw,
+ struct brcms_info *wl,
+ struct brcms_c_info *wlc);
+void wlc_phy_shim_detach(struct phy_shim_info *physhim);
/* PHY to WL utility functions */
-extern struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
- void (*fn) (struct brcms_phy *pi),
- void *arg, const char *name);
-extern void wlapi_free_timer(struct wlapi_timer *t);
-extern void wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic);
-extern bool wlapi_del_timer(struct wlapi_timer *t);
-extern void wlapi_intrson(struct phy_shim_info *physhim);
-extern u32 wlapi_intrsoff(struct phy_shim_info *physhim);
-extern void wlapi_intrsrestore(struct phy_shim_info *physhim,
- u32 macintmask);
-
-extern void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset,
- u16 v);
-extern u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset);
-extern void wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx,
- u16 mask, u16 val, int bands);
-extern void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags);
-extern void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim);
-extern void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode);
-extern void wlapi_enable_mac(struct phy_shim_info *physhim);
-extern void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask,
- u32 val);
-extern void wlapi_bmac_phy_reset(struct phy_shim_info *physhim);
-extern void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw);
-extern void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk);
-extern void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk);
-extern void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on);
-extern void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim);
-extern void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info *
- physhim);
-extern void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info *
- physhim);
-extern void wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int o,
- int len, void *buf);
-extern u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim,
- u8 rate);
-extern void wlapi_ucode_sample_init(struct phy_shim_info *physhim);
-extern void wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint,
- void *buf, int, u32 sel);
-extern void wlapi_copyto_objmem(struct phy_shim_info *physhim, uint,
- const void *buf, int, u32);
-
-extern void wlapi_high_update_phy_mode(struct phy_shim_info *physhim,
- u32 phy_mode);
-extern u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim);
+struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
+ void (*fn)(struct brcms_phy *pi),
+ void *arg, const char *name);
+void wlapi_free_timer(struct wlapi_timer *t);
+void wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic);
+bool wlapi_del_timer(struct wlapi_timer *t);
+void wlapi_intrson(struct phy_shim_info *physhim);
+u32 wlapi_intrsoff(struct phy_shim_info *physhim);
+void wlapi_intrsrestore(struct phy_shim_info *physhim, u32 macintmask);
+
+void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset, u16 v);
+u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset);
+void wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx, u16 mask, u16 val,
+ int bands);
+void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags);
+void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim);
+void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode);
+void wlapi_enable_mac(struct phy_shim_info *physhim);
+void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask, u32 val);
+void wlapi_bmac_phy_reset(struct phy_shim_info *physhim);
+void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw);
+void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk);
+void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk);
+void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on);
+void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim);
+void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info *physhim);
+void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info *physhim);
+void wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int o,
+ int len, void *buf);
+u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim, u8 rate);
+void wlapi_ucode_sample_init(struct phy_shim_info *physhim);
+void wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint, void *buf,
+ int, u32 sel);
+void wlapi_copyto_objmem(struct phy_shim_info *physhim, uint, const void *buf,
+ int, u32);
+
+void wlapi_high_update_phy_mode(struct phy_shim_info *physhim, u32 phy_mode);
+u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim);
#endif /* _BRCM_PHY_SHIM_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h
index 20e2012d5a3a..a014bbc4f935 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/pmu.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pmu.h
@@ -20,7 +20,7 @@
#include "types.h"
-extern u16 si_pmu_fast_pwrup_delay(struct si_pub *sih);
-extern u32 si_pmu_measure_alpclk(struct si_pub *sih);
+u16 si_pmu_fast_pwrup_delay(struct si_pub *sih);
+u32 si_pmu_measure_alpclk(struct si_pub *sih);
#endif /* _BRCM_PMU_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
index d36ea5e1cc49..4da38cb4f318 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h
@@ -266,83 +266,76 @@ struct brcms_antselcfg {
};
/* common functions for every port */
-extern struct brcms_c_info *
-brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit,
- bool piomode, uint *perr);
-extern uint brcms_c_detach(struct brcms_c_info *wlc);
-extern int brcms_c_up(struct brcms_c_info *wlc);
-extern uint brcms_c_down(struct brcms_c_info *wlc);
-
-extern bool brcms_c_chipmatch(struct bcma_device *core);
-extern void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx);
-extern void brcms_c_reset(struct brcms_c_info *wlc);
-
-extern void brcms_c_intrson(struct brcms_c_info *wlc);
-extern u32 brcms_c_intrsoff(struct brcms_c_info *wlc);
-extern void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask);
-extern bool brcms_c_intrsupd(struct brcms_c_info *wlc);
-extern bool brcms_c_isr(struct brcms_c_info *wlc);
-extern bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded);
-extern bool brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc,
- struct sk_buff *sdu,
- struct ieee80211_hw *hw);
-extern bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid);
-extern void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx,
- int val);
-extern int brcms_c_get_header_len(void);
-extern void brcms_c_set_addrmatch(struct brcms_c_info *wlc,
- int match_reg_offset,
- const u8 *addr);
-extern void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
- const struct ieee80211_tx_queue_params *arg,
- bool suspend);
-extern struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc);
-extern void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
- struct ieee80211_sta *sta, u16 tid);
-extern void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
- u8 ba_wsize, uint max_rx_ampdu_bytes);
-extern int brcms_c_module_register(struct brcms_pub *pub,
- const char *name, struct brcms_info *hdl,
- int (*down_fn)(void *handle));
-extern int brcms_c_module_unregister(struct brcms_pub *pub, const char *name,
- struct brcms_info *hdl);
-extern void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc);
-extern void brcms_c_enable_mac(struct brcms_c_info *wlc);
-extern void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state);
-extern void brcms_c_scan_start(struct brcms_c_info *wlc);
-extern void brcms_c_scan_stop(struct brcms_c_info *wlc);
-extern int brcms_c_get_curband(struct brcms_c_info *wlc);
-extern int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel);
-extern int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl);
-extern void brcms_c_get_current_rateset(struct brcms_c_info *wlc,
+struct brcms_c_info *brcms_c_attach(struct brcms_info *wl,
+ struct bcma_device *core, uint unit,
+ bool piomode, uint *perr);
+uint brcms_c_detach(struct brcms_c_info *wlc);
+int brcms_c_up(struct brcms_c_info *wlc);
+uint brcms_c_down(struct brcms_c_info *wlc);
+
+bool brcms_c_chipmatch(struct bcma_device *core);
+void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx);
+void brcms_c_reset(struct brcms_c_info *wlc);
+
+void brcms_c_intrson(struct brcms_c_info *wlc);
+u32 brcms_c_intrsoff(struct brcms_c_info *wlc);
+void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask);
+bool brcms_c_intrsupd(struct brcms_c_info *wlc);
+bool brcms_c_isr(struct brcms_c_info *wlc);
+bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded);
+bool brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu,
+ struct ieee80211_hw *hw);
+bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid);
+void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val);
+int brcms_c_get_header_len(void);
+void brcms_c_set_addrmatch(struct brcms_c_info *wlc, int match_reg_offset,
+ const u8 *addr);
+void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
+ const struct ieee80211_tx_queue_params *arg,
+ bool suspend);
+struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc);
+void brcms_c_ampdu_flush(struct brcms_c_info *wlc, struct ieee80211_sta *sta,
+ u16 tid);
+void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
+ u8 ba_wsize, uint max_rx_ampdu_bytes);
+int brcms_c_module_register(struct brcms_pub *pub, const char *name,
+ struct brcms_info *hdl,
+ int (*down_fn)(void *handle));
+int brcms_c_module_unregister(struct brcms_pub *pub, const char *name,
+ struct brcms_info *hdl);
+void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc);
+void brcms_c_enable_mac(struct brcms_c_info *wlc);
+void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state);
+void brcms_c_scan_start(struct brcms_c_info *wlc);
+void brcms_c_scan_stop(struct brcms_c_info *wlc);
+int brcms_c_get_curband(struct brcms_c_info *wlc);
+int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel);
+int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl);
+void brcms_c_get_current_rateset(struct brcms_c_info *wlc,
struct brcm_rateset *currs);
-extern int brcms_c_set_rateset(struct brcms_c_info *wlc,
- struct brcm_rateset *rs);
-extern int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period);
-extern u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx);
-extern void brcms_c_set_shortslot_override(struct brcms_c_info *wlc,
+int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs);
+int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period);
+u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx);
+void brcms_c_set_shortslot_override(struct brcms_c_info *wlc,
s8 sslot_override);
-extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc,
- u8 interval);
-extern u64 brcms_c_tsf_get(struct brcms_c_info *wlc);
-extern void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf);
-extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);
-extern int brcms_c_get_tx_power(struct brcms_c_info *wlc);
-extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
-extern void brcms_c_mute(struct brcms_c_info *wlc, bool on);
-extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc);
-extern void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr);
-extern void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr,
- const u8 *bssid, u8 *ssid, size_t ssid_len);
-extern void brcms_c_start_adhoc(struct brcms_c_info *wlc, u8 *addr);
-extern void brcms_c_update_beacon(struct brcms_c_info *wlc);
-extern void brcms_c_set_new_beacon(struct brcms_c_info *wlc,
- struct sk_buff *beacon, u16 tim_offset,
- u16 dtim_period);
-extern void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc,
- struct sk_buff *probe_resp);
-extern void brcms_c_enable_probe_resp(struct brcms_c_info *wlc, bool enable);
-extern void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid,
- size_t ssid_len);
+void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval);
+u64 brcms_c_tsf_get(struct brcms_c_info *wlc);
+void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf);
+int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);
+int brcms_c_get_tx_power(struct brcms_c_info *wlc);
+bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
+void brcms_c_mute(struct brcms_c_info *wlc, bool on);
+bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc);
+void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr);
+void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr, const u8 *bssid,
+ u8 *ssid, size_t ssid_len);
+void brcms_c_start_adhoc(struct brcms_c_info *wlc, u8 *addr);
+void brcms_c_update_beacon(struct brcms_c_info *wlc);
+void brcms_c_set_new_beacon(struct brcms_c_info *wlc, struct sk_buff *beacon,
+ u16 tim_offset, u16 dtim_period);
+void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc,
+ struct sk_buff *probe_resp);
+void brcms_c_enable_probe_resp(struct brcms_c_info *wlc, bool enable);
+void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid, size_t ssid_len);
#endif /* _BRCM_PUB_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/rate.h b/drivers/net/wireless/brcm80211/brcmsmac/rate.h
index 980d578825cc..5bb88b78ed64 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/rate.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/rate.h
@@ -216,34 +216,30 @@ static inline u8 cck_phy2mac_rate(u8 signal)
/* sanitize, and sort a rateset with the basic bit(s) preserved, validate
* rateset */
-extern bool
-brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs,
- const struct brcms_c_rateset *hw_rs,
- bool check_brate, u8 txstreams);
+bool brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs,
+ const struct brcms_c_rateset *hw_rs,
+ bool check_brate, u8 txstreams);
/* copy rateset src to dst as-is (no masking or sorting) */
-extern void brcms_c_rateset_copy(const struct brcms_c_rateset *src,
- struct brcms_c_rateset *dst);
+void brcms_c_rateset_copy(const struct brcms_c_rateset *src,
+ struct brcms_c_rateset *dst);
/* would be nice to have these documented ... */
-extern u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp);
-
-extern void brcms_c_rateset_filter(struct brcms_c_rateset *src,
- struct brcms_c_rateset *dst, bool basic_only, u8 rates, uint xmask,
- bool mcsallow);
-
-extern void
-brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt,
- const struct brcms_c_rateset *rs_hw, uint phy_type,
- int bandtype, bool cck_only, uint rate_mask,
- bool mcsallow, u8 bw, u8 txstreams);
-
-extern s16 brcms_c_rate_legacy_phyctl(uint rate);
-
-extern void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams);
-extern void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset);
-extern void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset,
- u8 txstreams);
-extern void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset,
- u8 bw);
+u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp);
+
+void brcms_c_rateset_filter(struct brcms_c_rateset *src,
+ struct brcms_c_rateset *dst, bool basic_only,
+ u8 rates, uint xmask, bool mcsallow);
+
+void brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt,
+ const struct brcms_c_rateset *rs_hw, uint phy_type,
+ int bandtype, bool cck_only, uint rate_mask,
+ bool mcsallow, u8 bw, u8 txstreams);
+
+s16 brcms_c_rate_legacy_phyctl(uint rate);
+
+void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams);
+void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset);
+void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, u8 txstreams);
+void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, u8 bw);
#endif /* _BRCM_RATE_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/stf.h b/drivers/net/wireless/brcm80211/brcmsmac/stf.h
index 19f6580f69be..ba9493009a33 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/stf.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/stf.h
@@ -19,24 +19,19 @@
#include "types.h"
-extern int brcms_c_stf_attach(struct brcms_c_info *wlc);
-extern void brcms_c_stf_detach(struct brcms_c_info *wlc);
+int brcms_c_stf_attach(struct brcms_c_info *wlc);
+void brcms_c_stf_detach(struct brcms_c_info *wlc);
-extern void brcms_c_tempsense_upd(struct brcms_c_info *wlc);
-extern void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc,
- u16 *ss_algo_channel,
- u16 chanspec);
-extern int brcms_c_stf_ss_update(struct brcms_c_info *wlc,
- struct brcms_band *band);
-extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
-extern int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val,
- bool force);
-extern bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val);
-extern void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
-extern void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc);
-extern u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc,
- u32 rspec);
-extern u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc,
- u32 rspec);
+void brcms_c_tempsense_upd(struct brcms_c_info *wlc);
+void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc,
+ u16 *ss_algo_channel, u16 chanspec);
+int brcms_c_stf_ss_update(struct brcms_c_info *wlc, struct brcms_band *band);
+void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
+int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force);
+bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val);
+void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
+void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc);
+u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, u32 rspec);
+u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, u32 rspec);
#endif /* _BRCM_STF_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h b/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h
index 18750a814b4f..c87dd89bcb78 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ucode_loader.h
@@ -43,16 +43,14 @@ struct brcms_ucode {
u32 *bcm43xx_bomminor;
};
-extern int
-brcms_ucode_data_init(struct brcms_info *wl, struct brcms_ucode *ucode);
+int brcms_ucode_data_init(struct brcms_info *wl, struct brcms_ucode *ucode);
-extern void brcms_ucode_data_free(struct brcms_ucode *ucode);
+void brcms_ucode_data_free(struct brcms_ucode *ucode);
-extern int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf,
- unsigned int idx);
-extern int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes,
- unsigned int idx);
-extern void brcms_ucode_free_buf(void *);
-extern int brcms_check_firmwares(struct brcms_info *wl);
+int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, unsigned int idx);
+int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes,
+ unsigned int idx);
+void brcms_ucode_free_buf(void *);
+int brcms_check_firmwares(struct brcms_info *wl);
#endif /* _BRCM_UCODE_H_ */
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_d11.h b/drivers/net/wireless/brcm80211/include/brcmu_d11.h
index 92623f02b1c0..8660a2cba098 100644
--- a/drivers/net/wireless/brcm80211/include/brcmu_d11.h
+++ b/drivers/net/wireless/brcm80211/include/brcmu_d11.h
@@ -140,6 +140,6 @@ struct brcmu_d11inf {
void (*decchspec)(struct brcmu_chan *ch);
};
-extern void brcmu_d11_attach(struct brcmu_d11inf *d11inf);
+void brcmu_d11_attach(struct brcmu_d11inf *d11inf);
#endif /* _BRCMU_CHANNELS_H_ */
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
index 898cacb8d01d..8ba445b3fd72 100644
--- a/drivers/net/wireless/brcm80211/include/brcmu_utils.h
+++ b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
@@ -114,31 +114,29 @@ static inline struct sk_buff *pktq_ppeek_tail(struct pktq *pq, int prec)
return skb_peek_tail(&pq->q[prec].skblist);
}
-extern struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec,
- struct sk_buff *p);
-extern struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec,
- struct sk_buff *p);
-extern struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec);
-extern struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec);
-extern struct sk_buff *brcmu_pktq_pdeq_match(struct pktq *pq, int prec,
- bool (*match_fn)(struct sk_buff *p,
- void *arg),
- void *arg);
+struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec, struct sk_buff *p);
+struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec,
+ struct sk_buff *p);
+struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec);
+struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec);
+struct sk_buff *brcmu_pktq_pdeq_match(struct pktq *pq, int prec,
+ bool (*match_fn)(struct sk_buff *p,
+ void *arg),
+ void *arg);
/* packet primitives */
-extern struct sk_buff *brcmu_pkt_buf_get_skb(uint len);
-extern void brcmu_pkt_buf_free_skb(struct sk_buff *skb);
+struct sk_buff *brcmu_pkt_buf_get_skb(uint len);
+void brcmu_pkt_buf_free_skb(struct sk_buff *skb);
/* Empty the queue at particular precedence level */
/* callback function fn(pkt, arg) returns true if pkt belongs to if */
-extern void brcmu_pktq_pflush(struct pktq *pq, int prec,
- bool dir, bool (*fn)(struct sk_buff *, void *), void *arg);
+void brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir,
+ bool (*fn)(struct sk_buff *, void *), void *arg);
/* operations on a set of precedences in packet queue */
-extern int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp);
-extern struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp,
- int *prec_out);
+int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp);
+struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out);
/* operations on packet queue as a whole */
@@ -167,11 +165,11 @@ static inline bool pktq_empty(struct pktq *pq)
return pq->len == 0;
}
-extern void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len);
+void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len);
/* prec_out may be NULL if caller is not interested in return value */
-extern struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out);
-extern void brcmu_pktq_flush(struct pktq *pq, bool dir,
- bool (*fn)(struct sk_buff *, void *), void *arg);
+struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out);
+void brcmu_pktq_flush(struct pktq *pq, bool dir,
+ bool (*fn)(struct sk_buff *, void *), void *arg);
/* externs */
/* ip address */
@@ -204,13 +202,13 @@ static inline u16 brcmu_maskget16(u16 var, u16 mask, u8 shift)
/* externs */
/* format/print */
#ifdef DEBUG
-extern void brcmu_prpkt(const char *msg, struct sk_buff *p0);
+void brcmu_prpkt(const char *msg, struct sk_buff *p0);
#else
#define brcmu_prpkt(a, b)
#endif /* DEBUG */
#ifdef DEBUG
-extern __printf(3, 4)
+__printf(3, 4)
void brcmu_dbg_hex_dump(const void *data, size_t size, const char *fmt, ...);
#else
__printf(3, 4)
diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c
index f5e6b489ed32..8057143849ce 100644
--- a/drivers/net/wireless/cw1200/cw1200_spi.c
+++ b/drivers/net/wireless/cw1200/cw1200_spi.c
@@ -42,7 +42,6 @@ struct hwbus_priv {
spinlock_t lock; /* Serialize all bus operations */
wait_queue_head_t wq;
int claimed;
- int irq_disabled;
};
#define SDIO_TO_SPI_ADDR(addr) ((addr & 0x1f)>>2)
@@ -238,8 +237,6 @@ static irqreturn_t cw1200_spi_irq_handler(int irq, void *dev_id)
struct hwbus_priv *self = dev_id;
if (self->core) {
- disable_irq_nosync(self->func->irq);
- self->irq_disabled = 1;
cw1200_irq_handler(self->core);
return IRQ_HANDLED;
} else {
@@ -253,9 +250,10 @@ static int cw1200_spi_irq_subscribe(struct hwbus_priv *self)
pr_debug("SW IRQ subscribe\n");
- ret = request_any_context_irq(self->func->irq, cw1200_spi_irq_handler,
- IRQF_TRIGGER_HIGH,
- "cw1200_wlan_irq", self);
+ ret = request_threaded_irq(self->func->irq, NULL,
+ cw1200_spi_irq_handler,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "cw1200_wlan_irq", self);
if (WARN_ON(ret < 0))
goto exit;
@@ -273,22 +271,13 @@ exit:
static int cw1200_spi_irq_unsubscribe(struct hwbus_priv *self)
{
+ int ret = 0;
+
pr_debug("SW IRQ unsubscribe\n");
disable_irq_wake(self->func->irq);
free_irq(self->func->irq, self);
- return 0;
-}
-
-static int cw1200_spi_irq_enable(struct hwbus_priv *self, int enable)
-{
- /* Disables are handled by the interrupt handler */
- if (enable && self->irq_disabled) {
- enable_irq(self->func->irq);
- self->irq_disabled = 0;
- }
-
- return 0;
+ return ret;
}
static int cw1200_spi_off(const struct cw1200_platform_data_spi *pdata)
@@ -368,14 +357,13 @@ static struct hwbus_ops cw1200_spi_hwbus_ops = {
.unlock = cw1200_spi_unlock,
.align_size = cw1200_spi_align_size,
.power_mgmt = cw1200_spi_pm,
- .irq_enable = cw1200_spi_irq_enable,
};
/* Probe Function to be called by SPI stack when device is discovered */
static int cw1200_spi_probe(struct spi_device *func)
{
const struct cw1200_platform_data_spi *plat_data =
- func->dev.platform_data;
+ dev_get_platdata(&func->dev);
struct hwbus_priv *self;
int status;
@@ -453,7 +441,7 @@ static int cw1200_spi_disconnect(struct spi_device *func)
}
kfree(self);
}
- cw1200_spi_off(func->dev.platform_data);
+ cw1200_spi_off(dev_get_platdata(&func->dev));
return 0;
}
diff --git a/drivers/net/wireless/cw1200/fwio.c b/drivers/net/wireless/cw1200/fwio.c
index 0b2061bbc68b..acdff0f7f952 100644
--- a/drivers/net/wireless/cw1200/fwio.c
+++ b/drivers/net/wireless/cw1200/fwio.c
@@ -485,7 +485,7 @@ int cw1200_load_firmware(struct cw1200_common *priv)
/* Enable interrupt signalling */
priv->hwbus_ops->lock(priv->hwbus_priv);
- ret = __cw1200_irq_enable(priv, 2);
+ ret = __cw1200_irq_enable(priv, 1);
priv->hwbus_ops->unlock(priv->hwbus_priv);
if (ret < 0)
goto unsubscribe;
diff --git a/drivers/net/wireless/cw1200/hwbus.h b/drivers/net/wireless/cw1200/hwbus.h
index 51dfb3a90735..8b2fc831c3de 100644
--- a/drivers/net/wireless/cw1200/hwbus.h
+++ b/drivers/net/wireless/cw1200/hwbus.h
@@ -28,7 +28,6 @@ struct hwbus_ops {
void (*unlock)(struct hwbus_priv *self);
size_t (*align_size)(struct hwbus_priv *self, size_t size);
int (*power_mgmt)(struct hwbus_priv *self, bool suspend);
- int (*irq_enable)(struct hwbus_priv *self, int enable);
};
#endif /* CW1200_HWBUS_H */
diff --git a/drivers/net/wireless/cw1200/hwio.c b/drivers/net/wireless/cw1200/hwio.c
index 41bd7615ccaa..ff230b7aeedd 100644
--- a/drivers/net/wireless/cw1200/hwio.c
+++ b/drivers/net/wireless/cw1200/hwio.c
@@ -273,21 +273,6 @@ int __cw1200_irq_enable(struct cw1200_common *priv, int enable)
u16 val16;
int ret;
- /* We need to do this hack because the SPI layer can sleep on I/O
- and the general path involves I/O to the device in interrupt
- context.
-
- However, the initial enable call needs to go to the hardware.
-
- We don't worry about shutdown because we do a full reset which
- clears the interrupt enabled bits.
- */
- if (priv->hwbus_ops->irq_enable) {
- ret = priv->hwbus_ops->irq_enable(priv->hwbus_priv, enable);
- if (ret || enable < 2)
- return ret;
- }
-
if (HIF_8601_SILICON == priv->hw_type) {
ret = __cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, &val32);
if (ret < 0) {
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index 6b823a1ab789..f394af777cf5 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -11885,7 +11885,6 @@ static int ipw_pci_probe(struct pci_dev *pdev,
pci_release_regions(pdev);
out_pci_disable_device:
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
out_free_libipw:
free_libipw(priv->net_dev, 0);
out:
@@ -11966,7 +11965,6 @@ static void ipw_pci_remove(struct pci_dev *pdev)
iounmap(priv->hw_base);
pci_release_regions(pdev);
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
/* wiphy_unregister needs to be here, before free_libipw */
wiphy_unregister(priv->ieee->wdev.wiphy);
kfree(priv->ieee->a_band.channels);
diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h
index 6eede52ad8c0..5ce2f59d3378 100644
--- a/drivers/net/wireless/ipw2x00/libipw.h
+++ b/drivers/net/wireless/ipw2x00/libipw.h
@@ -950,66 +950,55 @@ static inline int libipw_is_cck_rate(u8 rate)
}
/* libipw.c */
-extern void free_libipw(struct net_device *dev, int monitor);
-extern struct net_device *alloc_libipw(int sizeof_priv, int monitor);
-extern int libipw_change_mtu(struct net_device *dev, int new_mtu);
+void free_libipw(struct net_device *dev, int monitor);
+struct net_device *alloc_libipw(int sizeof_priv, int monitor);
+int libipw_change_mtu(struct net_device *dev, int new_mtu);
-extern void libipw_networks_age(struct libipw_device *ieee,
- unsigned long age_secs);
+void libipw_networks_age(struct libipw_device *ieee, unsigned long age_secs);
-extern int libipw_set_encryption(struct libipw_device *ieee);
+int libipw_set_encryption(struct libipw_device *ieee);
/* libipw_tx.c */
-extern netdev_tx_t libipw_xmit(struct sk_buff *skb,
- struct net_device *dev);
-extern void libipw_txb_free(struct libipw_txb *);
+netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev);
+void libipw_txb_free(struct libipw_txb *);
/* libipw_rx.c */
-extern void libipw_rx_any(struct libipw_device *ieee,
- struct sk_buff *skb, struct libipw_rx_stats *stats);
-extern int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb,
- struct libipw_rx_stats *rx_stats);
+void libipw_rx_any(struct libipw_device *ieee, struct sk_buff *skb,
+ struct libipw_rx_stats *stats);
+int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb,
+ struct libipw_rx_stats *rx_stats);
/* make sure to set stats->len */
-extern void libipw_rx_mgt(struct libipw_device *ieee,
- struct libipw_hdr_4addr *header,
- struct libipw_rx_stats *stats);
-extern void libipw_network_reset(struct libipw_network *network);
+void libipw_rx_mgt(struct libipw_device *ieee, struct libipw_hdr_4addr *header,
+ struct libipw_rx_stats *stats);
+void libipw_network_reset(struct libipw_network *network);
/* libipw_geo.c */
-extern const struct libipw_geo *libipw_get_geo(struct libipw_device
- *ieee);
-extern void libipw_set_geo(struct libipw_device *ieee,
- const struct libipw_geo *geo);
-
-extern int libipw_is_valid_channel(struct libipw_device *ieee,
- u8 channel);
-extern int libipw_channel_to_index(struct libipw_device *ieee,
- u8 channel);
-extern u8 libipw_freq_to_channel(struct libipw_device *ieee, u32 freq);
-extern u8 libipw_get_channel_flags(struct libipw_device *ieee,
- u8 channel);
-extern const struct libipw_channel *libipw_get_channel(struct
- libipw_device
- *ieee, u8 channel);
-extern u32 libipw_channel_to_freq(struct libipw_device * ieee,
- u8 channel);
+const struct libipw_geo *libipw_get_geo(struct libipw_device *ieee);
+void libipw_set_geo(struct libipw_device *ieee, const struct libipw_geo *geo);
+
+int libipw_is_valid_channel(struct libipw_device *ieee, u8 channel);
+int libipw_channel_to_index(struct libipw_device *ieee, u8 channel);
+u8 libipw_freq_to_channel(struct libipw_device *ieee, u32 freq);
+u8 libipw_get_channel_flags(struct libipw_device *ieee, u8 channel);
+const struct libipw_channel *libipw_get_channel(struct libipw_device *ieee,
+ u8 channel);
+u32 libipw_channel_to_freq(struct libipw_device *ieee, u8 channel);
/* libipw_wx.c */
-extern int libipw_wx_get_scan(struct libipw_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *key);
-extern int libipw_wx_set_encode(struct libipw_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *key);
-extern int libipw_wx_get_encode(struct libipw_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *key);
-extern int libipw_wx_set_encodeext(struct libipw_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-extern int libipw_wx_get_encodeext(struct libipw_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
+int libipw_wx_get_scan(struct libipw_device *ieee, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key);
+int libipw_wx_set_encode(struct libipw_device *ieee,
+ struct iw_request_info *info, union iwreq_data *wrqu,
+ char *key);
+int libipw_wx_get_encode(struct libipw_device *ieee,
+ struct iw_request_info *info, union iwreq_data *wrqu,
+ char *key);
+int libipw_wx_set_encodeext(struct libipw_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+int libipw_wx_get_encodeext(struct libipw_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
static inline void libipw_increment_scans(struct libipw_device *ieee)
{
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c
index 9581d07a4242..dea3b50d68b9 100644
--- a/drivers/net/wireless/iwlegacy/3945-mac.c
+++ b/drivers/net/wireless/iwlegacy/3945-mac.c
@@ -3811,7 +3811,6 @@ out_iounmap:
out_pci_release_regions:
pci_release_regions(pdev);
out_pci_disable_device:
- pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
out_ieee80211_free_hw:
ieee80211_free_hw(il->hw);
@@ -3888,7 +3887,6 @@ il3945_pci_remove(struct pci_dev *pdev)
iounmap(il->hw_base);
pci_release_regions(pdev);
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
il_free_channel_map(il);
il_free_geos(il);
diff --git a/drivers/net/wireless/iwlegacy/3945.h b/drivers/net/wireless/iwlegacy/3945.h
index 9a8703def0ba..00030d43a194 100644
--- a/drivers/net/wireless/iwlegacy/3945.h
+++ b/drivers/net/wireless/iwlegacy/3945.h
@@ -189,15 +189,14 @@ struct il3945_ibss_seq {
* for use by iwl-*.c
*
*****************************************************************************/
-extern int il3945_calc_db_from_ratio(int sig_ratio);
-extern void il3945_rx_replenish(void *data);
-extern void il3945_rx_queue_reset(struct il_priv *il, struct il_rx_queue *rxq);
-extern unsigned int il3945_fill_beacon_frame(struct il_priv *il,
- struct ieee80211_hdr *hdr,
- int left);
-extern int il3945_dump_nic_event_log(struct il_priv *il, bool full_log,
- char **buf, bool display);
-extern void il3945_dump_nic_error_log(struct il_priv *il);
+int il3945_calc_db_from_ratio(int sig_ratio);
+void il3945_rx_replenish(void *data);
+void il3945_rx_queue_reset(struct il_priv *il, struct il_rx_queue *rxq);
+unsigned int il3945_fill_beacon_frame(struct il_priv *il,
+ struct ieee80211_hdr *hdr, int left);
+int il3945_dump_nic_event_log(struct il_priv *il, bool full_log, char **buf,
+ bool display);
+void il3945_dump_nic_error_log(struct il_priv *il);
/******************************************************************************
*
@@ -215,39 +214,36 @@ extern void il3945_dump_nic_error_log(struct il_priv *il);
* il3945_mac_ <-- mac80211 callback
*
****************************************************************************/
-extern void il3945_hw_handler_setup(struct il_priv *il);
-extern void il3945_hw_setup_deferred_work(struct il_priv *il);
-extern void il3945_hw_cancel_deferred_work(struct il_priv *il);
-extern int il3945_hw_rxq_stop(struct il_priv *il);
-extern int il3945_hw_set_hw_params(struct il_priv *il);
-extern int il3945_hw_nic_init(struct il_priv *il);
-extern int il3945_hw_nic_stop_master(struct il_priv *il);
-extern void il3945_hw_txq_ctx_free(struct il_priv *il);
-extern void il3945_hw_txq_ctx_stop(struct il_priv *il);
-extern int il3945_hw_nic_reset(struct il_priv *il);
-extern int il3945_hw_txq_attach_buf_to_tfd(struct il_priv *il,
- struct il_tx_queue *txq,
- dma_addr_t addr, u16 len, u8 reset,
- u8 pad);
-extern void il3945_hw_txq_free_tfd(struct il_priv *il, struct il_tx_queue *txq);
-extern int il3945_hw_get_temperature(struct il_priv *il);
-extern int il3945_hw_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq);
-extern unsigned int il3945_hw_get_beacon_cmd(struct il_priv *il,
- struct il3945_frame *frame,
- u8 rate);
+void il3945_hw_handler_setup(struct il_priv *il);
+void il3945_hw_setup_deferred_work(struct il_priv *il);
+void il3945_hw_cancel_deferred_work(struct il_priv *il);
+int il3945_hw_rxq_stop(struct il_priv *il);
+int il3945_hw_set_hw_params(struct il_priv *il);
+int il3945_hw_nic_init(struct il_priv *il);
+int il3945_hw_nic_stop_master(struct il_priv *il);
+void il3945_hw_txq_ctx_free(struct il_priv *il);
+void il3945_hw_txq_ctx_stop(struct il_priv *il);
+int il3945_hw_nic_reset(struct il_priv *il);
+int il3945_hw_txq_attach_buf_to_tfd(struct il_priv *il, struct il_tx_queue *txq,
+ dma_addr_t addr, u16 len, u8 reset, u8 pad);
+void il3945_hw_txq_free_tfd(struct il_priv *il, struct il_tx_queue *txq);
+int il3945_hw_get_temperature(struct il_priv *il);
+int il3945_hw_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq);
+unsigned int il3945_hw_get_beacon_cmd(struct il_priv *il,
+ struct il3945_frame *frame, u8 rate);
void il3945_hw_build_tx_cmd_rate(struct il_priv *il, struct il_device_cmd *cmd,
struct ieee80211_tx_info *info,
struct ieee80211_hdr *hdr, int sta_id);
-extern int il3945_hw_reg_send_txpower(struct il_priv *il);
-extern int il3945_hw_reg_set_txpower(struct il_priv *il, s8 power);
-extern void il3945_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb);
+int il3945_hw_reg_send_txpower(struct il_priv *il);
+int il3945_hw_reg_set_txpower(struct il_priv *il, s8 power);
+void il3945_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb);
void il3945_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb);
-extern void il3945_disable_events(struct il_priv *il);
-extern int il4965_get_temperature(const struct il_priv *il);
-extern void il3945_post_associate(struct il_priv *il);
-extern void il3945_config_ap(struct il_priv *il);
+void il3945_disable_events(struct il_priv *il);
+int il4965_get_temperature(const struct il_priv *il);
+void il3945_post_associate(struct il_priv *il);
+void il3945_config_ap(struct il_priv *il);
-extern int il3945_commit_rxon(struct il_priv *il);
+int il3945_commit_rxon(struct il_priv *il);
/**
* il3945_hw_find_station - Find station id for a given BSSID
@@ -257,14 +253,14 @@ extern int il3945_commit_rxon(struct il_priv *il);
* not yet been merged into a single common layer for managing the
* station tables.
*/
-extern u8 il3945_hw_find_station(struct il_priv *il, const u8 * bssid);
+u8 il3945_hw_find_station(struct il_priv *il, const u8 *bssid);
-extern __le32 il3945_get_antenna_flags(const struct il_priv *il);
-extern int il3945_init_hw_rate_table(struct il_priv *il);
-extern void il3945_reg_txpower_periodic(struct il_priv *il);
-extern int il3945_txpower_set_from_eeprom(struct il_priv *il);
+__le32 il3945_get_antenna_flags(const struct il_priv *il);
+int il3945_init_hw_rate_table(struct il_priv *il);
+void il3945_reg_txpower_periodic(struct il_priv *il);
+int il3945_txpower_set_from_eeprom(struct il_priv *il);
-extern int il3945_rs_next_rate(struct il_priv *il, int rate);
+int il3945_rs_next_rate(struct il_priv *il, int rate);
/* scanning */
int il3945_request_scan(struct il_priv *il, struct ieee80211_vif *vif);
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index 5ab50a5b48b1..3982ab76f375 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -6706,7 +6706,6 @@ out_free_eeprom:
out_iounmap:
iounmap(il->hw_base);
out_pci_release_regions:
- pci_set_drvdata(pdev, NULL);
pci_release_regions(pdev);
out_pci_disable_device:
pci_disable_device(pdev);
@@ -6787,7 +6786,6 @@ il4965_pci_remove(struct pci_dev *pdev)
iounmap(il->hw_base);
pci_release_regions(pdev);
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
il4965_uninit_drv(il);
diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h
index 1b15b0b2292b..337dfcf3bbde 100644
--- a/drivers/net/wireless/iwlegacy/4965.h
+++ b/drivers/net/wireless/iwlegacy/4965.h
@@ -272,7 +272,7 @@ il4965_hw_valid_rtc_data_addr(u32 addr)
((t) < IL_TX_POWER_TEMPERATURE_MIN || \
(t) > IL_TX_POWER_TEMPERATURE_MAX)
-extern void il4965_temperature_calib(struct il_priv *il);
+void il4965_temperature_calib(struct il_priv *il);
/********************* END TEMPERATURE ***************************************/
/********************* START TXPOWER *****************************************/
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h
index 83f8ed8a5528..ad123d66ab6c 100644
--- a/drivers/net/wireless/iwlegacy/common.h
+++ b/drivers/net/wireless/iwlegacy/common.h
@@ -858,9 +858,9 @@ struct il_hw_params {
* il4965_mac_ <-- mac80211 callback
*
****************************************************************************/
-extern void il4965_update_chain_flags(struct il_priv *il);
+void il4965_update_chain_flags(struct il_priv *il);
extern const u8 il_bcast_addr[ETH_ALEN];
-extern int il_queue_space(const struct il_queue *q);
+int il_queue_space(const struct il_queue *q);
static inline int
il_queue_used(const struct il_queue *q, int i)
{
@@ -1727,7 +1727,7 @@ int il_alloc_txq_mem(struct il_priv *il);
void il_free_txq_mem(struct il_priv *il);
#ifdef CONFIG_IWLEGACY_DEBUGFS
-extern void il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len);
+void il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len);
#else
static inline void
il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len)
@@ -1760,12 +1760,12 @@ void il_chswitch_done(struct il_priv *il, bool is_success);
/*****************************************************
* TX
******************************************************/
-extern void il_txq_update_write_ptr(struct il_priv *il, struct il_tx_queue *txq);
-extern int il_tx_queue_init(struct il_priv *il, u32 txq_id);
-extern void il_tx_queue_reset(struct il_priv *il, u32 txq_id);
-extern void il_tx_queue_unmap(struct il_priv *il, int txq_id);
-extern void il_tx_queue_free(struct il_priv *il, int txq_id);
-extern void il_setup_watchdog(struct il_priv *il);
+void il_txq_update_write_ptr(struct il_priv *il, struct il_tx_queue *txq);
+int il_tx_queue_init(struct il_priv *il, u32 txq_id);
+void il_tx_queue_reset(struct il_priv *il, u32 txq_id);
+void il_tx_queue_unmap(struct il_priv *il, int txq_id);
+void il_tx_queue_free(struct il_priv *il, int txq_id);
+void il_setup_watchdog(struct il_priv *il);
/*****************************************************
* TX power
****************************************************/
@@ -1931,10 +1931,10 @@ il_is_ready_rf(struct il_priv *il)
return il_is_ready(il);
}
-extern void il_send_bt_config(struct il_priv *il);
-extern int il_send_stats_request(struct il_priv *il, u8 flags, bool clear);
-extern void il_apm_stop(struct il_priv *il);
-extern void _il_apm_stop(struct il_priv *il);
+void il_send_bt_config(struct il_priv *il);
+int il_send_stats_request(struct il_priv *il, u8 flags, bool clear);
+void il_apm_stop(struct il_priv *il);
+void _il_apm_stop(struct il_priv *il);
int il_apm_init(struct il_priv *il);
@@ -1968,15 +1968,15 @@ void il_tx_cmd_protection(struct il_priv *il, struct ieee80211_tx_info *info,
irqreturn_t il_isr(int irq, void *data);
-extern void il_set_bit(struct il_priv *p, u32 r, u32 m);
-extern void il_clear_bit(struct il_priv *p, u32 r, u32 m);
-extern bool _il_grab_nic_access(struct il_priv *il);
-extern int _il_poll_bit(struct il_priv *il, u32 addr, u32 bits, u32 mask, int timeout);
-extern int il_poll_bit(struct il_priv *il, u32 addr, u32 mask, int timeout);
-extern u32 il_rd_prph(struct il_priv *il, u32 reg);
-extern void il_wr_prph(struct il_priv *il, u32 addr, u32 val);
-extern u32 il_read_targ_mem(struct il_priv *il, u32 addr);
-extern void il_write_targ_mem(struct il_priv *il, u32 addr, u32 val);
+void il_set_bit(struct il_priv *p, u32 r, u32 m);
+void il_clear_bit(struct il_priv *p, u32 r, u32 m);
+bool _il_grab_nic_access(struct il_priv *il);
+int _il_poll_bit(struct il_priv *il, u32 addr, u32 bits, u32 mask, int timeout);
+int il_poll_bit(struct il_priv *il, u32 addr, u32 mask, int timeout);
+u32 il_rd_prph(struct il_priv *il, u32 reg);
+void il_wr_prph(struct il_priv *il, u32 addr, u32 val);
+u32 il_read_targ_mem(struct il_priv *il, u32 addr);
+void il_write_targ_mem(struct il_priv *il, u32 addr, u32 val);
static inline void
_il_write8(struct il_priv *il, u32 ofs, u8 val)
@@ -2868,13 +2868,13 @@ il4965_first_antenna(u8 mask)
* The specific throughput table used is based on the type of network
* the associated with, including A, B, G, and G w/ TGG protection
*/
-extern void il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);
+void il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);
/* Initialize station's rate scaling information after adding station */
-extern void il4965_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta,
- u8 sta_id);
-extern void il3945_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta,
- u8 sta_id);
+void il4965_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta,
+ u8 sta_id);
+void il3945_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta,
+ u8 sta_id);
/**
* il_rate_control_register - Register the rate control algorithm callbacks
@@ -2886,8 +2886,8 @@ extern void il3945_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta,
* ieee80211_register_hw
*
*/
-extern int il4965_rate_control_register(void);
-extern int il3945_rate_control_register(void);
+int il4965_rate_control_register(void);
+int il3945_rate_control_register(void);
/**
* il_rate_control_unregister - Unregister the rate control callbacks
@@ -2895,11 +2895,11 @@ extern int il3945_rate_control_register(void);
* This should be called after calling ieee80211_unregister_hw, but before
* the driver is unloaded.
*/
-extern void il4965_rate_control_unregister(void);
-extern void il3945_rate_control_unregister(void);
+void il4965_rate_control_unregister(void);
+void il3945_rate_control_unregister(void);
-extern int il_power_update_mode(struct il_priv *il, bool force);
-extern void il_power_initialize(struct il_priv *il);
+int il_power_update_mode(struct il_priv *il, bool force);
+void il_power_initialize(struct il_priv *il);
extern u32 il_debug_level;
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h
index f2a86ffc3b4c..23d5f0275ce9 100644
--- a/drivers/net/wireless/iwlwifi/dvm/agn.h
+++ b/drivers/net/wireless/iwlwifi/dvm/agn.h
@@ -397,7 +397,7 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
return cpu_to_le32(flags|(u32)rate);
}
-extern int iwl_alive_start(struct iwl_priv *priv);
+int iwl_alive_start(struct iwl_priv *priv);
#ifdef CONFIG_IWLWIFI_DEBUG
void iwl_print_rx_config_cmd(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h
index a79fdd137f95..7434d9edf3b7 100644
--- a/drivers/net/wireless/iwlwifi/dvm/dev.h
+++ b/drivers/net/wireless/iwlwifi/dvm/dev.h
@@ -270,7 +270,7 @@ struct iwl_sensitivity_ranges {
* iwlXXXX_ <-- Hardware specific (implemented in iwl-XXXX.c for XXXX)
*
****************************************************************************/
-extern void iwl_update_chain_flags(struct iwl_priv *priv);
+void iwl_update_chain_flags(struct iwl_priv *priv);
extern const u8 iwl_bcast_addr[ETH_ALEN];
#define IWL_OPERATION_MODE_AUTO 0
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.h b/drivers/net/wireless/iwlwifi/dvm/rs.h
index 5d83cab22d62..26fc550cd68c 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rs.h
+++ b/drivers/net/wireless/iwlwifi/dvm/rs.h
@@ -407,8 +407,8 @@ static inline u8 first_antenna(u8 mask)
/* Initialize station's rate scaling information after adding station */
-extern void iwl_rs_rate_init(struct iwl_priv *priv,
- struct ieee80211_sta *sta, u8 sta_id);
+void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta,
+ u8 sta_id);
/**
* iwl_rate_control_register - Register the rate control algorithm callbacks
@@ -420,7 +420,7 @@ extern void iwl_rs_rate_init(struct iwl_priv *priv,
* ieee80211_register_hw
*
*/
-extern int iwlagn_rate_control_register(void);
+int iwlagn_rate_control_register(void);
/**
* iwl_rate_control_unregister - Unregister the rate control callbacks
@@ -428,6 +428,6 @@ extern int iwlagn_rate_control_register(void);
* This should be called after calling ieee80211_unregister_hw, but before
* the driver is unloaded.
*/
-extern void iwlagn_rate_control_unregister(void);
+void iwlagn_rate_control_unregister(void);
#endif /* __iwl_agn__rs__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h
index 335cf1682902..465d40ee176f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.h
@@ -314,9 +314,8 @@ static inline u8 num_of_ant(u8 mask)
}
/* Initialize station's rate scaling information after adding station */
-extern void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm,
- struct ieee80211_sta *sta,
- enum ieee80211_band band);
+void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+ enum ieee80211_band band);
/**
* iwl_rate_control_register - Register the rate control algorithm callbacks
@@ -328,7 +327,7 @@ extern void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm,
* ieee80211_register_hw
*
*/
-extern int iwl_mvm_rate_control_register(void);
+int iwl_mvm_rate_control_register(void);
/**
* iwl_rate_control_unregister - Unregister the rate control callbacks
@@ -336,7 +335,7 @@ extern int iwl_mvm_rate_control_register(void);
* This should be called after calling ieee80211_unregister_hw, but before
* the driver is unloaded.
*/
-extern void iwl_mvm_rate_control_unregister(void);
+void iwl_mvm_rate_control_unregister(void);
struct iwl_mvm_sta;
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index 4bb6574f4073..5d39ec880d84 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -1128,7 +1128,7 @@ static int if_spi_probe(struct spi_device *spi)
{
struct if_spi_card *card;
struct lbs_private *priv = NULL;
- struct libertas_spi_platform_data *pdata = spi->dev.platform_data;
+ struct libertas_spi_platform_data *pdata = dev_get_platdata(&spi->dev);
int err = 0;
lbs_deb_enter(LBS_DEB_SPI);
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index 21c688264708..1214c587fd08 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -150,7 +150,7 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv,
*/
int
mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
- struct mwifiex_ra_list_tbl *pra_list, int headroom,
+ struct mwifiex_ra_list_tbl *pra_list,
int ptrindex, unsigned long ra_list_flags)
__releases(&priv->wmm.ra_list_spinlock)
{
@@ -160,6 +160,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
int pad = 0, ret;
struct mwifiex_tx_param tx_param;
struct txpd *ptx_pd = NULL;
+ int headroom = adapter->iface_type == MWIFIEX_USB ? 0 : INTF_HEADER_LEN;
skb_src = skb_peek(&pra_list->skb_head);
if (!skb_src) {
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.h b/drivers/net/wireless/mwifiex/11n_aggr.h
index 900e1c62a0cc..892098d6a696 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.h
+++ b/drivers/net/wireless/mwifiex/11n_aggr.h
@@ -26,7 +26,7 @@
int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv,
struct sk_buff *skb);
int mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
- struct mwifiex_ra_list_tbl *ptr, int headroom,
+ struct mwifiex_ra_list_tbl *ptr,
int ptr_index, unsigned long flags)
__releases(&priv->wmm.ra_list_spinlock);
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index 2d761477d15e..a6c46f3b6e3a 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -1155,7 +1155,7 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
uint32_t conditions = le32_to_cpu(phs_cfg->params.hs_config.conditions);
if (phs_cfg->action == cpu_to_le16(HS_ACTIVATE) &&
- adapter->iface_type == MWIFIEX_SDIO) {
+ adapter->iface_type != MWIFIEX_USB) {
mwifiex_hs_activated_event(priv, true);
return 0;
} else {
@@ -1167,8 +1167,7 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
}
if (conditions != HS_CFG_CANCEL) {
adapter->is_hs_configured = true;
- if (adapter->iface_type == MWIFIEX_USB ||
- adapter->iface_type == MWIFIEX_PCIE)
+ if (adapter->iface_type == MWIFIEX_USB)
mwifiex_hs_activated_event(priv, true);
} else {
adapter->is_hs_configured = false;
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 52da8ee7599a..33fa9432b241 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -93,7 +93,7 @@ static int mwifiex_pcie_suspend(struct device *dev)
struct pci_dev *pdev = to_pci_dev(dev);
if (pdev) {
- card = (struct pcie_service_card *) pci_get_drvdata(pdev);
+ card = pci_get_drvdata(pdev);
if (!card || !card->adapter) {
pr_err("Card or adapter structure is not valid\n");
return 0;
@@ -128,7 +128,7 @@ static int mwifiex_pcie_resume(struct device *dev)
struct pci_dev *pdev = to_pci_dev(dev);
if (pdev) {
- card = (struct pcie_service_card *) pci_get_drvdata(pdev);
+ card = pci_get_drvdata(pdev);
if (!card || !card->adapter) {
pr_err("Card or adapter structure is not valid\n");
return 0;
@@ -2037,7 +2037,7 @@ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
goto exit;
}
- card = (struct pcie_service_card *) pci_get_drvdata(pdev);
+ card = pci_get_drvdata(pdev);
if (!card || !card->adapter) {
pr_debug("info: %s: card=%p adapter=%p\n", __func__, card,
card ? card->adapter : NULL);
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c
index 2472d4b7f00e..1c70b8d09227 100644
--- a/drivers/net/wireless/mwifiex/usb.c
+++ b/drivers/net/wireless/mwifiex/usb.c
@@ -447,9 +447,6 @@ static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message)
*/
adapter->is_suspended = true;
- for (i = 0; i < adapter->priv_num; i++)
- netif_carrier_off(adapter->priv[i]->netdev);
-
if (atomic_read(&card->rx_cmd_urb_pending) && card->rx_cmd.urb)
usb_kill_urb(card->rx_cmd.urb);
@@ -509,10 +506,6 @@ static int mwifiex_usb_resume(struct usb_interface *intf)
MWIFIEX_RX_CMD_BUF_SIZE);
}
- for (i = 0; i < adapter->priv_num; i++)
- if (adapter->priv[i]->media_connected)
- netif_carrier_on(adapter->priv[i]->netdev);
-
/* Disable Host Sleep */
if (adapter->hs_activated)
mwifiex_cancel_hs(mwifiex_get_priv(adapter,
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 2e8f9cdea54d..95fa3599b407 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -1239,8 +1239,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
if (enable_tx_amsdu && mwifiex_is_amsdu_allowed(priv, tid) &&
mwifiex_is_11n_aggragation_possible(priv, ptr,
adapter->tx_buf_size))
- mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN,
- ptr_index, flags);
+ mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags);
/* ra_list_spinlock has been freed in
mwifiex_11n_aggregate_pkt() */
else
diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h
index 644d6e0c51cc..0f129d498fb1 100644
--- a/drivers/net/wireless/mwifiex/wmm.h
+++ b/drivers/net/wireless/mwifiex/wmm.h
@@ -83,11 +83,10 @@ mwifiex_wmm_is_ra_list_empty(struct list_head *ra_list_hhead)
}
void mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
- struct sk_buff *skb);
+ struct sk_buff *skb);
void mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra);
void mwifiex_rotate_priolists(struct mwifiex_private *priv,
- struct mwifiex_ra_list_tbl *ra,
- int tid);
+ struct mwifiex_ra_list_tbl *ra, int tid);
int mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter);
void mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter);
@@ -95,21 +94,18 @@ int mwifiex_is_ralist_valid(struct mwifiex_private *priv,
struct mwifiex_ra_list_tbl *ra_list, int tid);
u8 mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv,
- const struct sk_buff *skb);
+ const struct sk_buff *skb);
void mwifiex_wmm_init(struct mwifiex_adapter *adapter);
-extern u32 mwifiex_wmm_process_association_req(struct mwifiex_private *priv,
- u8 **assoc_buf,
- struct ieee_types_wmm_parameter
- *wmmie,
- struct ieee80211_ht_cap
- *htcap);
+u32 mwifiex_wmm_process_association_req(struct mwifiex_private *priv,
+ u8 **assoc_buf,
+ struct ieee_types_wmm_parameter *wmmie,
+ struct ieee80211_ht_cap *htcap);
void mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv,
- struct ieee_types_wmm_parameter
- *wmm_ie);
+ struct ieee_types_wmm_parameter *wmm_ie);
void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv);
-extern int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
- const struct host_cmd_ds_command *resp);
+int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv,
+ const struct host_cmd_ds_command *resp);
#endif /* !_MWIFIEX_WMM_H_ */
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index a3707fd4ef62..b953ad621e0b 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -6093,7 +6093,6 @@ err_iounmap:
if (priv->sram != NULL)
pci_iounmap(pdev, priv->sram);
- pci_set_drvdata(pdev, NULL);
ieee80211_free_hw(hw);
err_free_reg:
@@ -6147,7 +6146,6 @@ static void mwl8k_remove(struct pci_dev *pdev)
unmap:
pci_iounmap(pdev, priv->regs);
pci_iounmap(pdev, priv->sram);
- pci_set_drvdata(pdev, NULL);
ieee80211_free_hw(hw);
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h
index 3bb936b9558c..eebd2be21ee9 100644
--- a/drivers/net/wireless/orinoco/orinoco.h
+++ b/drivers/net/wireless/orinoco/orinoco.h
@@ -182,23 +182,20 @@ extern int orinoco_debug;
/* Exported prototypes */
/********************************************************************/
-extern struct orinoco_private *alloc_orinocodev(
- int sizeof_card, struct device *device,
- int (*hard_reset)(struct orinoco_private *),
- int (*stop_fw)(struct orinoco_private *, int));
-extern void free_orinocodev(struct orinoco_private *priv);
-extern int orinoco_init(struct orinoco_private *priv);
-extern int orinoco_if_add(struct orinoco_private *priv,
- unsigned long base_addr,
- unsigned int irq,
- const struct net_device_ops *ops);
-extern void orinoco_if_del(struct orinoco_private *priv);
-extern int orinoco_up(struct orinoco_private *priv);
-extern void orinoco_down(struct orinoco_private *priv);
-extern irqreturn_t orinoco_interrupt(int irq, void *dev_id);
-
-extern void __orinoco_ev_info(struct net_device *dev, struct hermes *hw);
-extern void __orinoco_ev_rx(struct net_device *dev, struct hermes *hw);
+struct orinoco_private *alloc_orinocodev(int sizeof_card, struct device *device,
+ int (*hard_reset)(struct orinoco_private *),
+ int (*stop_fw)(struct orinoco_private *, int));
+void free_orinocodev(struct orinoco_private *priv);
+int orinoco_init(struct orinoco_private *priv);
+int orinoco_if_add(struct orinoco_private *priv, unsigned long base_addr,
+ unsigned int irq, const struct net_device_ops *ops);
+void orinoco_if_del(struct orinoco_private *priv);
+int orinoco_up(struct orinoco_private *priv);
+void orinoco_down(struct orinoco_private *priv);
+irqreturn_t orinoco_interrupt(int irq, void *dev_id);
+
+void __orinoco_ev_info(struct net_device *dev, struct hermes *hw);
+void __orinoco_ev_rx(struct net_device *dev, struct hermes *hw);
int orinoco_process_xmit_skb(struct sk_buff *skb,
struct net_device *dev,
diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c
index d73fdf6185a2..ffb2469eb679 100644
--- a/drivers/net/wireless/orinoco/orinoco_nortel.c
+++ b/drivers/net/wireless/orinoco/orinoco_nortel.c
@@ -234,7 +234,6 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,
free_irq(pdev->irq, priv);
fail_irq:
- pci_set_drvdata(pdev, NULL);
free_orinocodev(priv);
fail_alloc:
@@ -265,7 +264,6 @@ static void orinoco_nortel_remove_one(struct pci_dev *pdev)
orinoco_if_del(priv);
free_irq(pdev->irq, priv);
- pci_set_drvdata(pdev, NULL);
free_orinocodev(priv);
pci_iounmap(pdev, priv->hw.iobase);
pci_iounmap(pdev, card->attr_io);
diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c
index 677bf14eca84..5ae1191d2532 100644
--- a/drivers/net/wireless/orinoco/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco/orinoco_pci.c
@@ -184,7 +184,6 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
free_irq(pdev->irq, priv);
fail_irq:
- pci_set_drvdata(pdev, NULL);
free_orinocodev(priv);
fail_alloc:
@@ -205,7 +204,6 @@ static void orinoco_pci_remove_one(struct pci_dev *pdev)
orinoco_if_del(priv);
free_irq(pdev->irq, priv);
- pci_set_drvdata(pdev, NULL);
free_orinocodev(priv);
pci_iounmap(pdev, priv->hw.iobase);
pci_release_regions(pdev);
diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c
index 2559dbd6184b..bbd36d1676ff 100644
--- a/drivers/net/wireless/orinoco/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco/orinoco_plx.c
@@ -273,7 +273,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
free_irq(pdev->irq, priv);
fail_irq:
- pci_set_drvdata(pdev, NULL);
free_orinocodev(priv);
fail_alloc:
@@ -301,7 +300,6 @@ static void orinoco_plx_remove_one(struct pci_dev *pdev)
orinoco_if_del(priv);
free_irq(pdev->irq, priv);
- pci_set_drvdata(pdev, NULL);
free_orinocodev(priv);
pci_iounmap(pdev, priv->hw.iobase);
pci_iounmap(pdev, card->attr_io);
diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c
index 42afeeea2c40..04b08de5fd5d 100644
--- a/drivers/net/wireless/orinoco/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco/orinoco_tmd.c
@@ -170,7 +170,6 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
free_irq(pdev->irq, priv);
fail_irq:
- pci_set_drvdata(pdev, NULL);
free_orinocodev(priv);
fail_alloc:
@@ -195,7 +194,6 @@ static void orinoco_tmd_remove_one(struct pci_dev *pdev)
orinoco_if_del(priv);
free_irq(pdev->irq, priv);
- pci_set_drvdata(pdev, NULL);
free_orinocodev(priv);
pci_iounmap(pdev, priv->hw.iobase);
pci_iounmap(pdev, card->bridge_io);
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index 57e3af8ebb4b..f9a07b0d83ac 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -631,7 +631,6 @@ static int p54p_probe(struct pci_dev *pdev,
iounmap(priv->map);
err_free_dev:
- pci_set_drvdata(pdev, NULL);
p54_free_common(dev);
err_free_reg:
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index b9deef66cf4b..e328d3058c41 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -83,6 +83,7 @@ static struct usb_device_id p54u_table[] = {
{USB_DEVICE(0x06a9, 0x000e)}, /* Westell 802.11g USB (A90-211WG-01) */
{USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */
{USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
+ {USB_DEVICE(0x07aa, 0x0020)}, /* Corega WLUSB2GTST USB */
{USB_DEVICE(0x0803, 0x4310)}, /* Zoom 4410a */
{USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
{USB_DEVICE(0x083a, 0x4531)}, /* T-Com Sinus 154 data II */
@@ -979,6 +980,7 @@ static int p54u_load_firmware(struct ieee80211_hw *dev,
if (err) {
dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s "
"(%d)!\n", p54u_fwlist[i].fw, err);
+ usb_put_dev(udev);
}
return err;
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 88ce656f96cd..f4149782e501 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -3315,29 +3315,37 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 8, 0x80);
if (rt2x00_rt(rt2x00dev, RT3593)) {
- if (rt2x00_is_usb(rt2x00dev)) {
- rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
+ rt2800_register_read(rt2x00dev, GPIO_CTRL, &reg);
- /* Band selection. GPIO #8 controls all paths */
+ /* Band selection */
+ if (rt2x00_is_usb(rt2x00dev) ||
+ rt2x00_is_pcie(rt2x00dev)) {
+ /* GPIO #8 controls all paths */
rt2x00_set_field32(&reg, GPIO_CTRL_DIR8, 0);
if (rf->channel <= 14)
rt2x00_set_field32(&reg, GPIO_CTRL_VAL8, 1);
else
rt2x00_set_field32(&reg, GPIO_CTRL_VAL8, 0);
+ }
+ /* LNA PE control. */
+ if (rt2x00_is_usb(rt2x00dev)) {
+ /* GPIO #4 controls PE0 and PE1,
+ * GPIO #7 controls PE2
+ */
rt2x00_set_field32(&reg, GPIO_CTRL_DIR4, 0);
rt2x00_set_field32(&reg, GPIO_CTRL_DIR7, 0);
- /* LNA PE control.
- * GPIO #4 controls PE0 and PE1,
- * GPIO #7 controls PE2
- */
rt2x00_set_field32(&reg, GPIO_CTRL_VAL4, 1);
rt2x00_set_field32(&reg, GPIO_CTRL_VAL7, 1);
-
- rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
+ } else if (rt2x00_is_pcie(rt2x00dev)) {
+ /* GPIO #4 controls PE0, PE1 and PE2 */
+ rt2x00_set_field32(&reg, GPIO_CTRL_DIR4, 0);
+ rt2x00_set_field32(&reg, GPIO_CTRL_VAL4, 1);
}
+ rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
+
/* AGC init */
if (rf->channel <= 14)
reg = 0x1c + 2 * rt2x00dev->lna_gain;
@@ -5985,7 +5993,7 @@ static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 20, 0xba);
rt2800_rfcsr_write(rt2x00dev, 21, 0xdb);
rt2800_rfcsr_write(rt2x00dev, 24, 0x16);
- rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x03);
rt2800_rfcsr_write(rt2x00dev, 29, 0x1f);
if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
@@ -6653,17 +6661,20 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
u16 word;
/*
- * Initialize all registers.
+ * Initialize MAC registers.
*/
if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) ||
rt2800_init_registers(rt2x00dev)))
return -EIO;
+ /*
+ * Wait BBP/RF to wake up.
+ */
if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev)))
return -EIO;
/*
- * Send signal to firmware during boot time.
+ * Send signal during boot time to initialize firmware.
*/
rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
@@ -6672,9 +6683,15 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
msleep(1);
+ /*
+ * Make sure BBP is up and running.
+ */
if (unlikely(rt2800_wait_bbp_ready(rt2x00dev)))
return -EIO;
+ /*
+ * Initialize BBP/RF registers.
+ */
rt2800_init_bbp(rt2x00dev);
rt2800_init_rfcsr(rt2x00dev);
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index fc207b268e4f..a91506b12a62 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
@@ -1122,7 +1122,6 @@ static int rtl8180_probe(struct pci_dev *pdev,
iounmap(priv->map);
err_free_dev:
- pci_set_drvdata(pdev, NULL);
ieee80211_free_hw(dev);
err_free_reg:
diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h
index 0e5fe0902daf..c07f114e7d1b 100644
--- a/drivers/net/wireless/rtlwifi/base.h
+++ b/drivers/net/wireless/rtlwifi/base.h
@@ -114,7 +114,6 @@ void rtl_init_rfkill(struct ieee80211_hw *hw);
void rtl_deinit_rfkill(struct ieee80211_hw *hw);
void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb);
-void rtl_watch_dog_timer_callback(unsigned long data);
void rtl_deinit_deferred_work(struct ieee80211_hw *hw);
bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx);
diff --git a/drivers/net/wireless/rtlwifi/cam.h b/drivers/net/wireless/rtlwifi/cam.h
index 35e00086a520..0105e6c1901e 100644
--- a/drivers/net/wireless/rtlwifi/cam.h
+++ b/drivers/net/wireless/rtlwifi/cam.h
@@ -41,12 +41,12 @@
#define CAM_CONFIG_USEDK 1
#define CAM_CONFIG_NO_USEDK 0
-extern void rtl_cam_reset_all_entry(struct ieee80211_hw *hw);
-extern u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr,
- u32 ul_key_id, u32 ul_entry_idx, u32 ul_enc_alg,
- u32 ul_default_key, u8 *key_content);
+void rtl_cam_reset_all_entry(struct ieee80211_hw *hw);
+u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr,
+ u32 ul_key_id, u32 ul_entry_idx, u32 ul_enc_alg,
+ u32 ul_default_key, u8 *key_content);
int rtl_cam_delete_one_entry(struct ieee80211_hw *hw, u8 *mac_addr,
- u32 ul_key_id);
+ u32 ul_key_id);
void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index);
void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index);
void rtl_cam_reset_sec_info(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c
index 838a1ed3f194..ae13fb94b2e8 100644
--- a/drivers/net/wireless/rtlwifi/efuse.c
+++ b/drivers/net/wireless/rtlwifi/efuse.c
@@ -1203,20 +1203,18 @@ static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate)
static u16 efuse_get_current_size(struct ieee80211_hw *hw)
{
- int continual = true;
u16 efuse_addr = 0;
u8 hworden;
u8 efuse_data, word_cnts;
- while (continual && efuse_one_byte_read(hw, efuse_addr, &efuse_data)
- && (efuse_addr < EFUSE_MAX_SIZE)) {
- if (efuse_data != 0xFF) {
- hworden = efuse_data & 0x0F;
- word_cnts = efuse_calculate_word_cnts(hworden);
- efuse_addr = efuse_addr + (word_cnts * 2) + 1;
- } else {
- continual = false;
- }
+ while (efuse_one_byte_read(hw, efuse_addr, &efuse_data) &&
+ efuse_addr < EFUSE_MAX_SIZE) {
+ if (efuse_data == 0xFF)
+ break;
+
+ hworden = efuse_data & 0x0F;
+ word_cnts = efuse_calculate_word_cnts(hworden);
+ efuse_addr = efuse_addr + (word_cnts * 2) + 1;
}
return efuse_addr;
diff --git a/drivers/net/wireless/rtlwifi/efuse.h b/drivers/net/wireless/rtlwifi/efuse.h
index 395a326acfb4..1663b3afd41e 100644
--- a/drivers/net/wireless/rtlwifi/efuse.h
+++ b/drivers/net/wireless/rtlwifi/efuse.h
@@ -104,20 +104,19 @@ struct efuse_priv {
u8 tx_power_g[14];
};
-extern void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf);
-extern void efuse_initialize(struct ieee80211_hw *hw);
-extern u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address);
-extern void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value);
-extern void read_efuse(struct ieee80211_hw *hw, u16 _offset,
- u16 _size_byte, u8 *pbuf);
-extern void efuse_shadow_read(struct ieee80211_hw *hw, u8 type,
- u16 offset, u32 *value);
-extern void efuse_shadow_write(struct ieee80211_hw *hw, u8 type,
- u16 offset, u32 value);
-extern bool efuse_shadow_update(struct ieee80211_hw *hw);
-extern bool efuse_shadow_update_chk(struct ieee80211_hw *hw);
-extern void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw);
-extern void efuse_force_write_vendor_Id(struct ieee80211_hw *hw);
-extern void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx);
+void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf);
+void efuse_initialize(struct ieee80211_hw *hw);
+u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address);
+void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value);
+void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf);
+void efuse_shadow_read(struct ieee80211_hw *hw, u8 type, u16 offset,
+ u32 *value);
+void efuse_shadow_write(struct ieee80211_hw *hw, u8 type, u16 offset,
+ u32 value);
+bool efuse_shadow_update(struct ieee80211_hw *hw);
+bool efuse_shadow_update_chk(struct ieee80211_hw *hw);
+void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw);
+void efuse_force_write_vendor_Id(struct ieee80211_hw *hw);
+void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx);
#endif
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 703f839af6ca..2b6d3e0afef0 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -2009,7 +2009,6 @@ fail2:
fail1:
if (hw)
ieee80211_free_hw(hw);
- pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
return err;
@@ -2064,8 +2063,6 @@ void rtl_pci_disconnect(struct pci_dev *pdev)
rtl_pci_disable_aspm(hw);
- pci_set_drvdata(pdev, NULL);
-
ieee80211_free_hw(hw);
}
EXPORT_SYMBOL(rtl_pci_disconnect);
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h
index f1acd6d27e44..71ddf4f3f6cc 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h
@@ -200,37 +200,32 @@ enum _ANT_DIV_TYPE {
CGCS_RX_SW_ANTDIV = 0x05,
};
-extern u32 rtl88e_phy_query_bb_reg(struct ieee80211_hw *hw,
- u32 regaddr, u32 bitmask);
-extern void rtl88e_phy_set_bb_reg(struct ieee80211_hw *hw,
- u32 regaddr, u32 bitmask, u32 data);
-extern u32 rtl88e_phy_query_rf_reg(struct ieee80211_hw *hw,
- enum radio_path rfpath, u32 regaddr,
- u32 bitmask);
-extern void rtl88e_phy_set_rf_reg(struct ieee80211_hw *hw,
- enum radio_path rfpath, u32 regaddr,
- u32 bitmask, u32 data);
-extern bool rtl88e_phy_mac_config(struct ieee80211_hw *hw);
-extern bool rtl88e_phy_bb_config(struct ieee80211_hw *hw);
-extern bool rtl88e_phy_rf_config(struct ieee80211_hw *hw);
-extern void rtl88e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw);
-extern void rtl88e_phy_get_txpower_level(struct ieee80211_hw *hw,
- long *powerlevel);
-extern void rtl88e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel);
-extern void rtl88e_phy_scan_operation_backup(struct ieee80211_hw *hw,
- u8 operation);
-extern void rtl88e_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
-extern void rtl88e_phy_set_bw_mode(struct ieee80211_hw *hw,
- enum nl80211_channel_type ch_type);
-extern void rtl88e_phy_sw_chnl_callback(struct ieee80211_hw *hw);
-extern u8 rtl88e_phy_sw_chnl(struct ieee80211_hw *hw);
-extern void rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery);
+u32 rtl88e_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask);
+void rtl88e_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask,
+ u32 data);
+u32 rtl88e_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
+ u32 regaddr, u32 bitmask);
+void rtl88e_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
+ u32 regaddr, u32 bitmask, u32 data);
+bool rtl88e_phy_mac_config(struct ieee80211_hw *hw);
+bool rtl88e_phy_bb_config(struct ieee80211_hw *hw);
+bool rtl88e_phy_rf_config(struct ieee80211_hw *hw);
+void rtl88e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw);
+void rtl88e_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel);
+void rtl88e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel);
+void rtl88e_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation);
+void rtl88e_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
+void rtl88e_phy_set_bw_mode(struct ieee80211_hw *hw,
+ enum nl80211_channel_type ch_type);
+void rtl88e_phy_sw_chnl_callback(struct ieee80211_hw *hw);
+u8 rtl88e_phy_sw_chnl(struct ieee80211_hw *hw);
+void rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery);
void rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw);
void rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain);
bool rtl88e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
enum radio_path rfpath);
bool rtl88e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
-extern bool rtl88e_phy_set_rf_power_state(struct ieee80211_hw *hw,
- enum rf_pwrstate rfpwr_state);
+bool rtl88e_phy_set_rf_power_state(struct ieee80211_hw *hw,
+ enum rf_pwrstate rfpwr_state);
#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h
index cec10d696492..24957e2a8370 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h
@@ -39,9 +39,7 @@
#define RT_CANNOT_IO(hw) false
#define HIGHPOWER_RADIOA_ARRAYLEN 22
-#define IQK_ADDA_REG_NUM 16
#define MAX_TOLERANCE 5
-#define IQK_DELAY_TIME 1
#define APK_BB_REG_NUM 5
#define APK_AFE_REG_NUM 16
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
index 3cfa1bb0f476..fa24de43ce79 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
@@ -152,8 +152,6 @@ enum version_8192c {
#define IS_VENDOR_UMC_A_CUT(version) ((IS_CHIP_VENDOR_UMC(version)) ? \
((GET_CVID_CUT_VERSION(version)) ? false : true) : false)
#define IS_CHIP_VER_B(version) ((version & CHIP_VER_B) ? true : false)
-#define IS_VENDOR_UMC_A_CUT(version) ((IS_CHIP_VENDOR_UMC(version)) ? \
- ((GET_CVID_CUT_VERSION(version)) ? false : true) : false)
#define IS_92C_SERIAL(version) ((version & CHIP_92C_BITMASK) ? true : false)
#define IS_CHIP_VENDOR_UMC(version) \
((version & CHIP_VENDOR_UMC) ? true : false)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h
index d5e3b704f930..bb319b0e8931 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h
@@ -39,9 +39,7 @@
#define RT_CANNOT_IO(hw) false
#define HIGHPOWER_RADIOA_ARRAYLEN 22
-#define IQK_ADDA_REG_NUM 16
#define MAX_TOLERANCE 5
-#define IQK_DELAY_TIME 1
#define APK_BB_REG_NUM 5
#define APK_AFE_REG_NUM 16
@@ -188,65 +186,54 @@ struct tx_power_struct {
};
bool rtl92c_phy_bb_config(struct ieee80211_hw *hw);
-u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw,
- u32 regaddr, u32 bitmask);
-void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw,
- u32 regaddr, u32 bitmask, u32 data);
-u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,
- enum radio_path rfpath, u32 regaddr,
- u32 bitmask);
-extern void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw,
- enum radio_path rfpath, u32 regaddr,
- u32 bitmask, u32 data);
+u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask);
+void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask,
+ u32 data);
+u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
+ u32 regaddr, u32 bitmask);
+void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
+ u32 regaddr, u32 bitmask, u32 data);
bool rtl92c_phy_mac_config(struct ieee80211_hw *hw);
bool rtl92ce_phy_bb_config(struct ieee80211_hw *hw);
bool rtl92c_phy_rf_config(struct ieee80211_hw *hw);
bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw,
- enum radio_path rfpath);
+ enum radio_path rfpath);
void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw);
-void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw,
- long *powerlevel);
+void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel);
void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel);
-bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw,
- long power_indbm);
-void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw,
- u8 operation);
+bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm);
+void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation);
void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw,
- enum nl80211_channel_type ch_type);
+ enum nl80211_channel_type ch_type);
void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw);
u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw);
void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery);
-void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw,
- u16 beaconinterval);
+void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval);
void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta);
void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw);
void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t);
void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain);
bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
enum radio_path rfpath);
-bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw,
- u32 rfpath);
-bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
+bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath);
bool rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
- enum rf_pwrstate rfpwr_state);
+ enum rf_pwrstate rfpwr_state);
void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw);
bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
void rtl92c_phy_set_io(struct ieee80211_hw *hw);
void rtl92c_bb_block_on(struct ieee80211_hw *hw);
-u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw,
- enum radio_path rfpath, u32 offset);
+u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, enum radio_path rfpath,
+ u32 offset);
u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw,
- enum radio_path rfpath, u32 offset);
+ enum radio_path rfpath, u32 offset);
u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask);
void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw,
- enum radio_path rfpath, u32 offset,
- u32 data);
+ enum radio_path rfpath, u32 offset, u32 data);
void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw,
- enum radio_path rfpath, u32 offset,
- u32 data);
+ enum radio_path rfpath, u32 offset,
+ u32 data);
void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw,
- u32 regaddr, u32 bitmask,
- u32 data);
+ u32 regaddr, u32 bitmask, u32 data);
bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw);
bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
index bd4aef74c056..8922ecb47ad2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
@@ -560,7 +560,6 @@
#define EEPROM_DEFAULT_TXPOWERLEVEL 0x22
#define EEPROM_DEFAULT_HT40_2SDIFF 0x0
#define EEPROM_DEFAULT_HT20_DIFF 2
-#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3
#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0
#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0
@@ -639,17 +638,8 @@
#define EEPROM_TXPWR_GROUP 0x6F
-#define EEPROM_TSSI_A 0x76
-#define EEPROM_TSSI_B 0x77
-#define EEPROM_THERMAL_METER 0x78
-
#define EEPROM_CHANNELPLAN 0x75
-#define RF_OPTION1 0x79
-#define RF_OPTION2 0x7A
-#define RF_OPTION3 0x7B
-#define RF_OPTION4 0x7C
-
#define STOPBECON BIT(6)
#define STOPHIGHT BIT(5)
#define STOPMGT BIT(4)
@@ -689,13 +679,6 @@
#define RSV_CTRL 0x001C
#define RD_CTRL 0x0524
-#define REG_USB_INFO 0xFE17
-#define REG_USB_SPECIAL_OPTION 0xFE55
-
-#define REG_USB_DMA_AGG_TO 0xFE5B
-#define REG_USB_AGG_TO 0xFE5C
-#define REG_USB_AGG_TH 0xFE5D
-
#define REG_USB_VID 0xFE60
#define REG_USB_PID 0xFE62
#define REG_USB_OPTIONAL 0xFE64
@@ -1196,9 +1179,6 @@
#define POLLING_LLT_THRESHOLD 20
#define POLLING_READY_TIMEOUT_COUNT 1000
-#define MAX_MSS_DENSITY_2T 0x13
-#define MAX_MSS_DENSITY_1T 0x0A
-
#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6))
#define EPROM_CMD_CONFIG 0x3
#define EPROM_CMD_LOAD 1
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h
index 6c8d56efceae..d8fe68b389d2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h
@@ -34,11 +34,10 @@
#define RF6052_MAX_REG 0x3F
#define RF6052_MAX_PATH 2
-extern void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw,
- u8 bandwidth);
-extern void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
- u8 *ppowerlevel);
-extern void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
- u8 *ppowerlevel, u8 channel);
-extern bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw);
+void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth);
+void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel);
+void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel, u8 channel);
+bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw);
#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
index da4f587199ee..393685390f3e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
@@ -32,6 +32,7 @@
#include "../usb.h"
#include "../ps.h"
#include "../cam.h"
+#include "../stats.h"
#include "reg.h"
#include "def.h"
#include "phy.h"
@@ -738,16 +739,6 @@ static u8 _rtl92c_evm_db_to_percentage(char value)
return ret_val;
}
-static long _rtl92c_translate_todbm(struct ieee80211_hw *hw,
- u8 signal_strength_index)
-{
- long signal_power;
-
- signal_power = (long)((signal_strength_index + 1) >> 1);
- signal_power -= 95;
- return signal_power;
-}
-
static long _rtl92c_signal_scale_mapping(struct ieee80211_hw *hw,
long currsig)
{
@@ -913,180 +904,6 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
(hw, total_rssi /= rf_rx_num));
}
-static void _rtl92c_process_ui_rssi(struct ieee80211_hw *hw,
- struct rtl_stats *pstats)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_phy *rtlphy = &(rtlpriv->phy);
- u8 rfpath;
- u32 last_rssi, tmpval;
-
- if (pstats->packet_toself || pstats->packet_beacon) {
- rtlpriv->stats.rssi_calculate_cnt++;
- if (rtlpriv->stats.ui_rssi.total_num++ >=
- PHY_RSSI_SLID_WIN_MAX) {
- rtlpriv->stats.ui_rssi.total_num =
- PHY_RSSI_SLID_WIN_MAX;
- last_rssi =
- rtlpriv->stats.ui_rssi.elements[rtlpriv->
- stats.ui_rssi.index];
- rtlpriv->stats.ui_rssi.total_val -= last_rssi;
- }
- rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength;
- rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.
- index++] = pstats->signalstrength;
- if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
- rtlpriv->stats.ui_rssi.index = 0;
- tmpval = rtlpriv->stats.ui_rssi.total_val /
- rtlpriv->stats.ui_rssi.total_num;
- rtlpriv->stats.signal_strength =
- _rtl92c_translate_todbm(hw, (u8) tmpval);
- pstats->rssi = rtlpriv->stats.signal_strength;
- }
- if (!pstats->is_cck && pstats->packet_toself) {
- for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
- rfpath++) {
- if (!rtl8192_phy_check_is_legal_rfpath(hw, rfpath))
- continue;
- if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
- rtlpriv->stats.rx_rssi_percentage[rfpath] =
- pstats->rx_mimo_signalstrength[rfpath];
- }
- if (pstats->rx_mimo_signalstrength[rfpath] >
- rtlpriv->stats.rx_rssi_percentage[rfpath]) {
- rtlpriv->stats.rx_rssi_percentage[rfpath] =
- ((rtlpriv->stats.
- rx_rssi_percentage[rfpath] *
- (RX_SMOOTH_FACTOR - 1)) +
- (pstats->rx_mimo_signalstrength[rfpath])) /
- (RX_SMOOTH_FACTOR);
-
- rtlpriv->stats.rx_rssi_percentage[rfpath] =
- rtlpriv->stats.rx_rssi_percentage[rfpath] +
- 1;
- } else {
- rtlpriv->stats.rx_rssi_percentage[rfpath] =
- ((rtlpriv->stats.
- rx_rssi_percentage[rfpath] *
- (RX_SMOOTH_FACTOR - 1)) +
- (pstats->rx_mimo_signalstrength[rfpath])) /
- (RX_SMOOTH_FACTOR);
- }
- }
- }
-}
-
-static void _rtl92c_update_rxsignalstatistics(struct ieee80211_hw *hw,
- struct rtl_stats *pstats)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
- int weighting = 0;
-
- if (rtlpriv->stats.recv_signal_power == 0)
- rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
- if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power)
- weighting = 5;
- else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power)
- weighting = (-5);
- rtlpriv->stats.recv_signal_power =
- (rtlpriv->stats.recv_signal_power * 5 +
- pstats->recvsignalpower + weighting) / 6;
-}
-
-static void _rtl92c_process_pwdb(struct ieee80211_hw *hw,
- struct rtl_stats *pstats)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
- long undec_sm_pwdb = 0;
-
- if (mac->opmode == NL80211_IFTYPE_ADHOC) {
- return;
- } else {
- undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
- }
- if (pstats->packet_toself || pstats->packet_beacon) {
- if (undec_sm_pwdb < 0)
- undec_sm_pwdb = pstats->rx_pwdb_all;
- if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) {
- undec_sm_pwdb = (((undec_sm_pwdb) *
- (RX_SMOOTH_FACTOR - 1)) +
- (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
- undec_sm_pwdb += 1;
- } else {
- undec_sm_pwdb = (((undec_sm_pwdb) *
- (RX_SMOOTH_FACTOR - 1)) +
- (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
- }
- rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
- _rtl92c_update_rxsignalstatistics(hw, pstats);
- }
-}
-
-static void _rtl92c_process_LINK_Q(struct ieee80211_hw *hw,
- struct rtl_stats *pstats)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
- u32 last_evm = 0, n_stream, tmpval;
-
- if (pstats->signalquality != 0) {
- if (pstats->packet_toself || pstats->packet_beacon) {
- if (rtlpriv->stats.LINK_Q.total_num++ >=
- PHY_LINKQUALITY_SLID_WIN_MAX) {
- rtlpriv->stats.LINK_Q.total_num =
- PHY_LINKQUALITY_SLID_WIN_MAX;
- last_evm =
- rtlpriv->stats.LINK_Q.elements
- [rtlpriv->stats.LINK_Q.index];
- rtlpriv->stats.LINK_Q.total_val -=
- last_evm;
- }
- rtlpriv->stats.LINK_Q.total_val +=
- pstats->signalquality;
- rtlpriv->stats.LINK_Q.elements
- [rtlpriv->stats.LINK_Q.index++] =
- pstats->signalquality;
- if (rtlpriv->stats.LINK_Q.index >=
- PHY_LINKQUALITY_SLID_WIN_MAX)
- rtlpriv->stats.LINK_Q.index = 0;
- tmpval = rtlpriv->stats.LINK_Q.total_val /
- rtlpriv->stats.LINK_Q.total_num;
- rtlpriv->stats.signal_quality = tmpval;
- rtlpriv->stats.last_sigstrength_inpercent = tmpval;
- for (n_stream = 0; n_stream < 2;
- n_stream++) {
- if (pstats->RX_SIGQ[n_stream] != -1) {
- if (!rtlpriv->stats.RX_EVM[n_stream]) {
- rtlpriv->stats.RX_EVM[n_stream]
- = pstats->RX_SIGQ[n_stream];
- }
- rtlpriv->stats.RX_EVM[n_stream] =
- ((rtlpriv->stats.RX_EVM
- [n_stream] *
- (RX_SMOOTH_FACTOR - 1)) +
- (pstats->RX_SIGQ
- [n_stream] * 1)) /
- (RX_SMOOTH_FACTOR);
- }
- }
- }
- } else {
- ;
- }
-}
-
-static void _rtl92c_process_phyinfo(struct ieee80211_hw *hw,
- u8 *buffer,
- struct rtl_stats *pcurrent_stats)
-{
- if (!pcurrent_stats->packet_matchbssid &&
- !pcurrent_stats->packet_beacon)
- return;
- _rtl92c_process_ui_rssi(hw, pcurrent_stats);
- _rtl92c_process_pwdb(hw, pcurrent_stats);
- _rtl92c_process_LINK_Q(hw, pcurrent_stats);
-}
-
void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
struct sk_buff *skb,
struct rtl_stats *pstats,
@@ -1123,5 +940,5 @@ void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
_rtl92c_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
packet_matchbssid, packet_toself,
packet_beacon);
- _rtl92c_process_phyinfo(hw, tmp_buf, pstats);
+ rtl_process_phyinfo(hw, tmp_buf, pstats);
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h
index 090fd33a158d..11b439d6b671 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h
@@ -34,15 +34,14 @@
#define RF6052_MAX_REG 0x3F
#define RF6052_MAX_PATH 2
-extern void rtl92cu_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw,
- u8 bandwidth);
-extern void rtl92c_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
- u8 *ppowerlevel);
-extern void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
- u8 *ppowerlevel, u8 channel);
+void rtl92cu_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth);
+void rtl92c_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel);
+void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel, u8 channel);
bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw);
bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
- enum radio_path rfpath);
+ enum radio_path rfpath);
void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
u8 *ppowerlevel);
void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.h b/drivers/net/wireless/rtlwifi/rtl8192de/hw.h
index 7c9f7a2f1e42..1bc7b1a96d4a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.h
@@ -55,10 +55,9 @@ void rtl92de_set_key(struct ieee80211_hw *hw, u32 key_index,
u8 *p_macaddr, bool is_group, u8 enc_algo,
bool is_wepkey, bool clear_all);
-extern void rtl92de_write_dword_dbi(struct ieee80211_hw *hw, u16 offset,
- u32 value, u8 direct);
-extern u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset,
- u8 direct);
+void rtl92de_write_dword_dbi(struct ieee80211_hw *hw, u16 offset, u32 value,
+ u8 direct);
+u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset, u8 direct);
void rtl92de_suspend(struct ieee80211_hw *hw);
void rtl92de_resume(struct ieee80211_hw *hw);
void rtl92d_linked_set_reg(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.h b/drivers/net/wireless/rtlwifi/rtl8192de/phy.h
index f074952bf25c..8f07606ff0bc 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.h
@@ -39,9 +39,7 @@
#define RT_CANNOT_IO(hw) false
#define HIGHPOWER_RADIOA_ARRAYLEN 22
-#define IQK_ADDA_REG_NUM 16
#define MAX_TOLERANCE 5
-#define IQK_DELAY_TIME 1
#define APK_BB_REG_NUM 5
#define APK_AFE_REG_NUM 16
@@ -127,34 +125,30 @@ static inline void rtl92d_release_cckandrw_pagea_ctl(struct ieee80211_hw *hw,
*flag);
}
-extern u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw,
- u32 regaddr, u32 bitmask);
-extern void rtl92d_phy_set_bb_reg(struct ieee80211_hw *hw,
- u32 regaddr, u32 bitmask, u32 data);
-extern u32 rtl92d_phy_query_rf_reg(struct ieee80211_hw *hw,
- enum radio_path rfpath, u32 regaddr,
- u32 bitmask);
-extern void rtl92d_phy_set_rf_reg(struct ieee80211_hw *hw,
- enum radio_path rfpath, u32 regaddr,
- u32 bitmask, u32 data);
-extern bool rtl92d_phy_mac_config(struct ieee80211_hw *hw);
-extern bool rtl92d_phy_bb_config(struct ieee80211_hw *hw);
-extern bool rtl92d_phy_rf_config(struct ieee80211_hw *hw);
-extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw,
- enum radio_path rfpath);
-extern void rtl92d_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw);
-extern void rtl92d_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel);
-extern void rtl92d_phy_scan_operation_backup(struct ieee80211_hw *hw,
- u8 operation);
-extern void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw,
- enum nl80211_channel_type ch_type);
-extern u8 rtl92d_phy_sw_chnl(struct ieee80211_hw *hw);
+u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask);
+void rtl92d_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask,
+ u32 data);
+u32 rtl92d_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
+ u32 regaddr, u32 bitmask);
+void rtl92d_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
+ u32 regaddr, u32 bitmask, u32 data);
+bool rtl92d_phy_mac_config(struct ieee80211_hw *hw);
+bool rtl92d_phy_bb_config(struct ieee80211_hw *hw);
+bool rtl92d_phy_rf_config(struct ieee80211_hw *hw);
+bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw,
+ enum radio_path rfpath);
+void rtl92d_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw);
+void rtl92d_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel);
+void rtl92d_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation);
+void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw,
+ enum nl80211_channel_type ch_type);
+u8 rtl92d_phy_sw_chnl(struct ieee80211_hw *hw);
bool rtl92d_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
enum rf_content content,
enum radio_path rfpath);
bool rtl92d_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
-extern bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw,
- enum rf_pwrstate rfpwr_state);
+bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw,
+ enum rf_pwrstate rfpwr_state);
void rtl92d_phy_config_macphymode(struct ieee80211_hw *hw);
void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw);
@@ -173,6 +167,5 @@ void rtl92d_acquire_cckandrw_pagea_ctl(struct ieee80211_hw *hw,
unsigned long *flag);
u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl);
void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel);
-void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw);
#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.h b/drivers/net/wireless/rtlwifi/rtl8192de/rf.h
index 0fe1a48593e8..7303d12c266f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/rf.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/rf.h
@@ -30,15 +30,13 @@
#ifndef __RTL92D_RF_H__
#define __RTL92D_RF_H__
-extern void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw,
- u8 bandwidth);
-extern void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
- u8 *ppowerlevel);
-extern void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
- u8 *ppowerlevel, u8 channel);
-extern bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw);
-extern bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0);
-extern void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw,
- bool bmac0);
+void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth);
+void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel);
+void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel, u8 channel);
+bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw);
+bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0);
+void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw, bool bmac0);
#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
index 84d1181795b8..c81c83591940 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h
@@ -425,14 +425,9 @@
#define EXT_IMEM_CODE_DONE BIT(2)
#define IMEM_CHK_RPT BIT(1)
#define IMEM_CODE_DONE BIT(0)
-#define IMEM_CODE_DONE BIT(0)
-#define IMEM_CHK_RPT BIT(1)
#define EMEM_CODE_DONE BIT(2)
#define EMEM_CHK_RPT BIT(3)
-#define DMEM_CODE_DONE BIT(4)
#define IMEM_RDY BIT(5)
-#define BASECHG BIT(6)
-#define FWRDY BIT(7)
#define LOAD_FW_READY (IMEM_CODE_DONE | \
IMEM_CHK_RPT | \
EMEM_CODE_DONE | \
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h
index e7a59eba351a..bbb950dac5ba 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h
@@ -183,42 +183,39 @@ struct tx_power_struct {
u32 mcs_original_offset[4][16];
};
-extern u32 rtl8723ae_phy_query_bb_reg(struct ieee80211_hw *hw,
- u32 regaddr, u32 bitmask);
-extern void rtl8723ae_phy_set_bb_reg(struct ieee80211_hw *hw,
- u32 regaddr, u32 bitmask, u32 data);
-extern u32 rtl8723ae_phy_query_rf_reg(struct ieee80211_hw *hw,
- enum radio_path rfpath, u32 regaddr,
- u32 bitmask);
-extern void rtl8723ae_phy_set_rf_reg(struct ieee80211_hw *hw,
- enum radio_path rfpath, u32 regaddr,
- u32 bitmask, u32 data);
-extern bool rtl8723ae_phy_mac_config(struct ieee80211_hw *hw);
-extern bool rtl8723ae_phy_bb_config(struct ieee80211_hw *hw);
-extern bool rtl8723ae_phy_rf_config(struct ieee80211_hw *hw);
-extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw,
- enum radio_path rfpath);
-extern void rtl8723ae_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw);
-extern void rtl8723ae_phy_get_txpower_level(struct ieee80211_hw *hw,
- long *powerlevel);
-extern void rtl8723ae_phy_set_txpower_level(struct ieee80211_hw *hw,
- u8 channel);
-extern bool rtl8723ae_phy_update_txpower_dbm(struct ieee80211_hw *hw,
- long power_indbm);
-extern void rtl8723ae_phy_scan_operation_backup(struct ieee80211_hw *hw,
- u8 operation);
-extern void rtl8723ae_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
-extern void rtl8723ae_phy_set_bw_mode(struct ieee80211_hw *hw,
- enum nl80211_channel_type ch_type);
-extern void rtl8723ae_phy_sw_chnl_callback(struct ieee80211_hw *hw);
-extern u8 rtl8723ae_phy_sw_chnl(struct ieee80211_hw *hw);
-extern void rtl8723ae_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery);
+u32 rtl8723ae_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr,
+ u32 bitmask);
+void rtl8723ae_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask,
+ u32 data);
+u32 rtl8723ae_phy_query_rf_reg(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 regaddr,
+ u32 bitmask);
+void rtl8723ae_phy_set_rf_reg(struct ieee80211_hw *hw,
+ enum radio_path rfpath, u32 regaddr, u32 bitmask,
+ u32 data);
+bool rtl8723ae_phy_mac_config(struct ieee80211_hw *hw);
+bool rtl8723ae_phy_bb_config(struct ieee80211_hw *hw);
+bool rtl8723ae_phy_rf_config(struct ieee80211_hw *hw);
+bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw,
+ enum radio_path rfpath);
+void rtl8723ae_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw);
+void rtl8723ae_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel);
+void rtl8723ae_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel);
+bool rtl8723ae_phy_update_txpower_dbm(struct ieee80211_hw *hw,
+ long power_indbm);
+void rtl8723ae_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation);
+void rtl8723ae_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
+void rtl8723ae_phy_set_bw_mode(struct ieee80211_hw *hw,
+ enum nl80211_channel_type ch_type);
+void rtl8723ae_phy_sw_chnl_callback(struct ieee80211_hw *hw);
+u8 rtl8723ae_phy_sw_chnl(struct ieee80211_hw *hw);
+void rtl8723ae_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery);
void rtl8723ae_phy_lc_calibrate(struct ieee80211_hw *hw);
void rtl8723ae_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain);
bool rtl8723ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
enum radio_path rfpath);
bool rtl8723ae_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
-extern bool rtl8723ae_phy_set_rf_power_state(struct ieee80211_hw *hw,
- enum rf_pwrstate rfpwr_state);
+bool rtl8723ae_phy_set_rf_power_state(struct ieee80211_hw *hw,
+ enum rf_pwrstate rfpwr_state);
#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h b/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h
index d0f9dd79abea..57f1933ee663 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h
@@ -32,12 +32,11 @@
#define RF6052_MAX_TX_PWR 0x3F
-extern void rtl8723ae_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw,
- u8 bandwidth);
-extern void rtl8723ae_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
- u8 *ppowerlevel);
-extern void rtl8723ae_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
- u8 *ppowerlevel, u8 channel);
-extern bool rtl8723ae_phy_rf6052_config(struct ieee80211_hw *hw);
+void rtl8723ae_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth);
+void rtl8723ae_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel);
+void rtl8723ae_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+ u8 *ppowerlevel, u8 channel);
+bool rtl8723ae_phy_rf6052_config(struct ieee80211_hw *hw);
#endif
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index cc03e7c87cbe..d224dc3bb092 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -192,8 +192,6 @@ enum hardware_type {
(IS_HARDWARE_TYPE_8192DE(rtlhal) || IS_HARDWARE_TYPE_8192DU(rtlhal))
#define IS_HARDWARE_TYPE_8723(rtlhal) \
(IS_HARDWARE_TYPE_8723E(rtlhal) || IS_HARDWARE_TYPE_8723U(rtlhal))
-#define IS_HARDWARE_TYPE_8723U(rtlhal) \
- (rtlhal->hw_type == HARDWARE_TYPE_RTL8723U)
#define RX_HAL_IS_CCK_RATE(_pdesc)\
(_pdesc->rxmcs == DESC92_RATE1M || \
@@ -2057,7 +2055,7 @@ struct rtl_priv {
that it points to the data allocated
beyond this structure like:
rtl_pci_priv or rtl_usb_priv */
- u8 priv[0];
+ u8 priv[0] __aligned(sizeof(void *));
};
#define rtl_priv(hw) (((struct rtl_priv *)(hw)->priv))
diff --git a/drivers/net/wireless/ti/wl1251/spi.c b/drivers/net/wireless/ti/wl1251/spi.c
index c7dc6feab2ff..1342f81e683d 100644
--- a/drivers/net/wireless/ti/wl1251/spi.c
+++ b/drivers/net/wireless/ti/wl1251/spi.c
@@ -243,7 +243,7 @@ static int wl1251_spi_probe(struct spi_device *spi)
struct wl1251 *wl;
int ret;
- pdata = spi->dev.platform_data;
+ pdata = dev_get_platdata(&spi->dev);
if (!pdata) {
wl1251_error("no platform data");
return -ENODEV;
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 1c627da85083..591526b99154 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1704,7 +1704,7 @@ static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
static int wl12xx_setup(struct wl1271 *wl)
{
struct wl12xx_priv *priv = wl->priv;
- struct wlcore_platdev_data *pdev_data = wl->pdev->dev.platform_data;
+ struct wlcore_platdev_data *pdev_data = dev_get_platdata(&wl->pdev->dev);
struct wl12xx_platform_data *pdata = pdev_data->pdata;
wl->rtable = wl12xx_rtable;
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 38995f90040d..c30e1f19d8d3 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5900,7 +5900,7 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
{
struct wl1271 *wl = context;
struct platform_device *pdev = wl->pdev;
- struct wlcore_platdev_data *pdev_data = pdev->dev.platform_data;
+ struct wlcore_platdev_data *pdev_data = dev_get_platdata(&pdev->dev);
struct wl12xx_platform_data *pdata = pdev_data->pdata;
unsigned long irqflags;
int ret;
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c
index 1b0cd98e35f1..b2c018dccf18 100644
--- a/drivers/net/wireless/ti/wlcore/spi.c
+++ b/drivers/net/wireless/ti/wlcore/spi.c
@@ -335,7 +335,7 @@ static int wl1271_probe(struct spi_device *spi)
if (!pdev_data)
goto out;
- pdev_data->pdata = spi->dev.platform_data;
+ pdev_data->pdata = dev_get_platdata(&spi->dev);
if (!pdev_data->pdata) {
dev_err(&spi->dev, "no platform data\n");
ret = -ENODEV;
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index 70694ce38be2..dc82ef096f3b 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -37,7 +37,7 @@ config PARPORT_PC
tristate "PC-style hardware"
depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV && !S390 && \
(!M68K || ISA) && !MN10300 && !AVR32 && !BLACKFIN && \
- !XTENSA && !CRIS && !H8300
+ !XTENSA && !CRIS
---help---
You should say Y here if you have a PC-style parallel port. All
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 3d9504811126..43186feb4294 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -3,7 +3,7 @@ menu "PCI host controller drivers"
config PCI_MVEBU
bool "Marvell EBU PCIe controller"
- depends on ARCH_MVEBU || ARCH_KIRKWOOD
+ depends on ARCH_MVEBU || ARCH_DOVE || ARCH_KIRKWOOD
depends on OF
config PCIE_DW
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 729d5a101d62..77f8a7c58597 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -9,13 +9,17 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/mbus.h>
+#include <linux/msi.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/of_address.h>
-#include <linux/of_pci.h>
#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/of_pci.h>
#include <linux/of_platform.h>
/*
@@ -103,6 +107,7 @@ struct mvebu_pcie_port;
struct mvebu_pcie {
struct platform_device *pdev;
struct mvebu_pcie_port *ports;
+ struct msi_chip *msi;
struct resource io;
struct resource realio;
struct resource mem;
@@ -124,6 +129,9 @@ struct mvebu_pcie_port {
unsigned int io_target;
unsigned int io_attr;
struct clk *clk;
+ int reset_gpio;
+ int reset_active_low;
+ char *reset_name;
struct mvebu_sw_pci_bridge bridge;
struct device_node *dn;
struct mvebu_pcie *pcie;
@@ -163,7 +171,7 @@ static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie_port *port, int nr)
* BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
* WIN[0-3] -> DRAM bank[0-3]
*/
-static void __init mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
+static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
{
const struct mbus_dram_target_info *dram;
u32 size;
@@ -215,7 +223,7 @@ static void __init mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
port->base + PCIE_BAR_CTRL_OFF(1));
}
-static void __init mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
+static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
{
u16 cmd;
u32 mask;
@@ -626,7 +634,7 @@ static struct pci_ops mvebu_pcie_ops = {
.write = mvebu_pcie_wr_conf,
};
-static int __init mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
+static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
{
struct mvebu_pcie *pcie = sys_to_pcie(sys);
int i;
@@ -645,7 +653,7 @@ static int __init mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
return 1;
}
-static int __init mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
struct of_irq oirq;
int ret;
@@ -673,6 +681,12 @@ static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
return bus;
}
+void mvebu_pcie_add_bus(struct pci_bus *bus)
+{
+ struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);
+ bus->msi = pcie->msi;
+}
+
resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
const struct resource *res,
resource_size_t start,
@@ -696,7 +710,7 @@ resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
return start;
}
-static void __init mvebu_pcie_enable(struct mvebu_pcie *pcie)
+static void mvebu_pcie_enable(struct mvebu_pcie *pcie)
{
struct hw_pci hw;
@@ -709,6 +723,7 @@ static void __init mvebu_pcie_enable(struct mvebu_pcie *pcie)
hw.map_irq = mvebu_pcie_map_irq;
hw.ops = &mvebu_pcie_ops;
hw.align_resource = mvebu_pcie_align_resource;
+ hw.add_bus = mvebu_pcie_add_bus;
pci_common_init(&hw);
}
@@ -718,10 +733,8 @@ static void __init mvebu_pcie_enable(struct mvebu_pcie *pcie)
* <...> property for one that matches the given port/lane. Once
* found, maps it.
*/
-static void __iomem * __init
-mvebu_pcie_map_registers(struct platform_device *pdev,
- struct device_node *np,
- struct mvebu_pcie_port *port)
+static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev,
+ struct device_node *np, struct mvebu_pcie_port *port)
{
struct resource regs;
int ret = 0;
@@ -777,7 +790,22 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
return -ENOENT;
}
-static int __init mvebu_pcie_probe(struct platform_device *pdev)
+static void mvebu_pcie_msi_enable(struct mvebu_pcie *pcie)
+{
+ struct device_node *msi_node;
+
+ msi_node = of_parse_phandle(pcie->pdev->dev.of_node,
+ "msi-parent", 0);
+ if (!msi_node)
+ return;
+
+ pcie->msi = of_pci_find_msi_chip_by_node(msi_node);
+
+ if (pcie->msi)
+ pcie->msi->dev = &pcie->pdev->dev;
+}
+
+static int mvebu_pcie_probe(struct platform_device *pdev)
{
struct mvebu_pcie *pcie;
struct device_node *np = pdev->dev.of_node;
@@ -790,6 +818,7 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)
return -ENOMEM;
pcie->pdev = pdev;
+ platform_set_drvdata(pdev, pcie);
/* Get the PCIe memory and I/O aperture */
mvebu_mbus_get_pcie_mem_aperture(&pcie->mem);
@@ -818,13 +847,14 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)
return ret;
}
+ i = 0;
for_each_child_of_node(pdev->dev.of_node, child) {
if (!of_device_is_available(child))
continue;
- pcie->nports++;
+ i++;
}
- pcie->ports = devm_kzalloc(&pdev->dev, pcie->nports *
+ pcie->ports = devm_kzalloc(&pdev->dev, i *
sizeof(struct mvebu_pcie_port),
GFP_KERNEL);
if (!pcie->ports)
@@ -833,6 +863,7 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)
i = 0;
for_each_child_of_node(pdev->dev.of_node, child) {
struct mvebu_pcie_port *port = &pcie->ports[i];
+ enum of_gpio_flags flags;
if (!of_device_is_available(child))
continue;
@@ -873,11 +904,47 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)
continue;
}
+ port->reset_gpio = of_get_named_gpio_flags(child,
+ "reset-gpios", 0, &flags);
+ if (gpio_is_valid(port->reset_gpio)) {
+ u32 reset_udelay = 20000;
+
+ port->reset_active_low = flags & OF_GPIO_ACTIVE_LOW;
+ port->reset_name = kasprintf(GFP_KERNEL,
+ "pcie%d.%d-reset", port->port, port->lane);
+ of_property_read_u32(child, "reset-delay-us",
+ &reset_udelay);
+
+ ret = devm_gpio_request_one(&pdev->dev,
+ port->reset_gpio, GPIOF_DIR_OUT, port->reset_name);
+ if (ret) {
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ continue;
+ }
+
+ gpio_set_value(port->reset_gpio,
+ (port->reset_active_low) ? 1 : 0);
+ msleep(reset_udelay/1000);
+ }
+
+ port->clk = of_clk_get_by_name(child, NULL);
+ if (IS_ERR(port->clk)) {
+ dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",
+ port->port, port->lane);
+ continue;
+ }
+
+ ret = clk_prepare_enable(port->clk);
+ if (ret)
+ continue;
+
port->base = mvebu_pcie_map_registers(pdev, child, port);
if (IS_ERR(port->base)) {
dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n",
port->port, port->lane);
port->base = NULL;
+ clk_disable_unprepare(port->clk);
continue;
}
@@ -893,25 +960,14 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)
port->port, port->lane);
}
- port->clk = of_clk_get_by_name(child, NULL);
- if (IS_ERR(port->clk)) {
- dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",
- port->port, port->lane);
- iounmap(port->base);
- port->haslink = 0;
- continue;
- }
-
port->dn = child;
-
- clk_prepare_enable(port->clk);
spin_lock_init(&port->conf_lock);
-
mvebu_sw_pci_bridge_init(port);
-
i++;
}
+ pcie->nports = i;
+ mvebu_pcie_msi_enable(pcie);
mvebu_pcie_enable(pcie);
return 0;
@@ -920,6 +976,7 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)
static const struct of_device_id mvebu_pcie_of_match_table[] = {
{ .compatible = "marvell,armada-xp-pcie", },
{ .compatible = "marvell,armada-370-pcie", },
+ { .compatible = "marvell,dove-pcie", },
{ .compatible = "marvell,kirkwood-pcie", },
{},
};
@@ -931,16 +988,12 @@ static struct platform_driver mvebu_pcie_driver = {
.name = "mvebu-pcie",
.of_match_table =
of_match_ptr(mvebu_pcie_of_match_table),
+ /* driver unloading/unbinding currently not supported */
+ .suppress_bind_attrs = true,
},
+ .probe = mvebu_pcie_probe,
};
-
-static int __init mvebu_pcie_init(void)
-{
- return platform_driver_probe(&mvebu_pcie_driver,
- mvebu_pcie_probe);
-}
-
-subsys_initcall(mvebu_pcie_init);
+module_platform_driver(mvebu_pcie_driver);
MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
MODULE_DESCRIPTION("Marvell EBU PCIe driver");
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index 2a47e82821da..1ce8ee054f1a 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -338,7 +338,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
acpi_handle chandle, handle;
struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
- flags &= OSC_SHPC_NATIVE_HP_CONTROL;
+ flags &= OSC_PCI_SHPC_NATIVE_HP_CONTROL;
if (!flags) {
err("Invalid flags %u specified!\n", flags);
return -EINVAL;
@@ -411,13 +411,10 @@ EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware);
static int pcihp_is_ejectable(acpi_handle handle)
{
acpi_status status;
- acpi_handle tmp;
unsigned long long removable;
- status = acpi_get_handle(handle, "_ADR", &tmp);
- if (ACPI_FAILURE(status))
+ if (!acpi_has_method(handle, "_ADR"))
return 0;
- status = acpi_get_handle(handle, "_EJ0", &tmp);
- if (ACPI_SUCCESS(status))
+ if (acpi_has_method(handle, "_EJ0"))
return 1;
status = acpi_evaluate_integer(handle, "_RMV", NULL, &removable);
if (ACPI_SUCCESS(status) && removable)
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index e260f207a90e..d876e4b3c6a9 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -191,7 +191,7 @@ static inline const char *slot_name(struct slot *slot)
#include <linux/pci-acpi.h>
static inline int get_hp_hw_control_from_firmware(struct pci_dev *dev)
{
- u32 flags = OSC_SHPC_NATIVE_HP_CONTROL;
+ u32 flags = OSC_PCI_SHPC_NATIVE_HP_CONTROL;
return acpi_get_hp_hw_control_from_firmware(dev, flags);
}
#else
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index b0299e6d9a3f..dfd1f59de729 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -181,7 +181,6 @@ static bool acpi_pci_power_manageable(struct pci_dev *dev)
static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
{
acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
- acpi_handle tmp;
static const u8 state_conv[] = {
[PCI_D0] = ACPI_STATE_D0,
[PCI_D1] = ACPI_STATE_D1,
@@ -192,7 +191,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
int error = -EINVAL;
/* If the ACPI device has _EJ0, ignore the device */
- if (!handle || ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp)))
+ if (!handle || acpi_has_method(handle, "_EJ0"))
return -ENODEV;
switch (state) {
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 98f7b9b89507..38f3c0140dfb 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -135,6 +135,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
return retval;
return count;
}
+static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
/**
* store_remove_id - remove a PCI device ID from this driver
@@ -180,12 +181,14 @@ store_remove_id(struct device_driver *driver, const char *buf, size_t count)
return retval;
return count;
}
+static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id);
-static struct driver_attribute pci_drv_attrs[] = {
- __ATTR(new_id, S_IWUSR, NULL, store_new_id),
- __ATTR(remove_id, S_IWUSR, NULL, store_remove_id),
- __ATTR_NULL,
+static struct attribute *pci_drv_attrs[] = {
+ &driver_attr_new_id.attr,
+ &driver_attr_remove_id.attr,
+ NULL,
};
+ATTRIBUTE_GROUPS(pci_drv);
/**
* pci_match_id - See if a pci device matches a given pci_id table
@@ -1317,8 +1320,8 @@ struct bus_type pci_bus_type = {
.remove = pci_device_remove,
.shutdown = pci_device_shutdown,
.dev_attrs = pci_dev_attrs,
- .bus_attrs = pci_bus_attrs,
- .drv_attrs = pci_drv_attrs,
+ .bus_groups = pci_bus_groups,
+ .drv_groups = pci_drv_groups,
.pm = PCI_PM_OPS_PTR,
};
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 7128cfdd64aa..d8eb880bd1fc 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -302,10 +302,20 @@ static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf,
}
return count;
}
+static BUS_ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store);
-struct bus_attribute pci_bus_attrs[] = {
- __ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store),
- __ATTR_NULL
+struct attribute *pci_bus_attrs[] = {
+ &bus_attr_rescan.attr,
+ NULL,
+};
+
+static const struct attribute_group pci_bus_group = {
+ .attrs = pci_bus_attrs,
+};
+
+const struct attribute_group *pci_bus_groups[] = {
+ &pci_bus_group,
+ NULL,
};
static ssize_t
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 8a00c063d7bc..607be58dd728 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -156,7 +156,7 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
extern struct device_attribute pci_dev_attrs[];
extern const struct attribute_group *pcibus_groups[];
extern struct device_type pci_dev_type;
-extern struct bus_attribute pci_bus_attrs[];
+extern const struct attribute_group *pci_bus_groups[];
/**
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 7ef0f868b3e0..c90d0f8021e7 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -641,8 +641,7 @@ static void pci_set_bus_speed(struct pci_bus *bus)
return;
}
- pos = pci_find_capability(bridge, PCI_CAP_ID_EXP);
- if (pos) {
+ if (pci_is_pcie(bridge)) {
u32 linkcap;
u16 linksta;
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index b8f5acf02261..de24232c5191 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -245,7 +245,7 @@ static int at91_cf_dt_init(struct platform_device *pdev)
}
#endif
-static int __init at91_cf_probe(struct platform_device *pdev)
+static int at91_cf_probe(struct platform_device *pdev)
{
struct at91_cf_socket *cf;
struct at91_cf_data *board = pdev->dev.platform_data;
@@ -354,7 +354,7 @@ fail0a:
return status;
}
-static int __exit at91_cf_remove(struct platform_device *pdev)
+static int at91_cf_remove(struct platform_device *pdev)
{
struct at91_cf_socket *cf = platform_get_drvdata(pdev);
@@ -404,14 +404,13 @@ static struct platform_driver at91_cf_driver = {
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(at91_cf_dt_ids),
},
- .remove = __exit_p(at91_cf_remove),
+ .probe = at91_cf_probe,
+ .remove = at91_cf_remove,
.suspend = at91_cf_suspend,
.resume = at91_cf_resume,
};
-/*--------------------------------------------------------------------------*/
-
-module_platform_driver_probe(at91_cf_driver, at91_cf_probe);
+module_platform_driver(at91_cf_driver);
MODULE_DESCRIPTION("AT91 Compact Flash Driver");
MODULE_AUTHOR("David Brownell");
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index b6e864e8c9e8..21db2013543b 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -49,6 +49,24 @@ config PINCTRL_AB8505
bool "AB8505 pin controller driver"
depends on PINCTRL_ABX500 && ARCH_U8500
+config PINCTRL_ADI2
+ bool "ADI pin controller driver"
+ depends on BLACKFIN
+ select PINMUX
+ select IRQ_DOMAIN
+ help
+ This is the pin controller and gpio driver for ADI BF54x, BF60x and
+ future processors. This option is selected automatically when specific
+ machine and arch are selected to build.
+
+config PINCTRL_BF54x
+ def_bool y if BF54x
+ select PINCTRL_ADI2
+
+config PINCTRL_BF60x
+ def_bool y if BF60x
+ select PINCTRL_ADI2
+
config PINCTRL_AT91
bool "AT91 pinctrl driver"
depends on OF
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 496d9bf9e1b9..bbeb98086495 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -14,6 +14,9 @@ obj-$(CONFIG_PINCTRL_AB8500) += pinctrl-ab8500.o
obj-$(CONFIG_PINCTRL_AB8540) += pinctrl-ab8540.o
obj-$(CONFIG_PINCTRL_AB9540) += pinctrl-ab9540.o
obj-$(CONFIG_PINCTRL_AB8505) += pinctrl-ab8505.o
+obj-$(CONFIG_PINCTRL_ADI2) += pinctrl-adi2.o
+obj-$(CONFIG_PINCTRL_BF54x) += pinctrl-adi2-bf54x.o
+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
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index a138965c01cb..b8fcc38c0d11 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -490,7 +490,7 @@ exit:
* <devicename> <state> <pinname> are values that should match the pinctrl-maps
* <newvalue> reflects the new config and is driver dependant
*/
-static int pinconf_dbg_config_write(struct file *file,
+static ssize_t pinconf_dbg_config_write(struct file *file,
const char __user *user_buf, size_t count, loff_t *ppos)
{
struct pinctrl_maps *maps_node;
@@ -508,7 +508,7 @@ static int pinconf_dbg_config_write(struct file *file,
int i;
/* Get userspace string and assure termination */
- buf_size = min(count, (size_t)(sizeof(buf)-1));
+ buf_size = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
buf[buf_size] = 0;
diff --git a/drivers/pinctrl/pinctrl-adi2-bf54x.c b/drivers/pinctrl/pinctrl-adi2-bf54x.c
new file mode 100644
index 000000000000..ea9d9ab9cda1
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-adi2-bf54x.c
@@ -0,0 +1,592 @@
+/*
+ * Pinctrl Driver for ADI GPIO2 controller
+ *
+ * Copyright 2007-2013 Analog Devices Inc.
+ *
+ * Licensed under the GPLv2 or later
+ */
+
+#include <asm/portmux.h>
+#include "pinctrl-adi2.h"
+
+static const struct pinctrl_pin_desc adi_pads[] = {
+ PINCTRL_PIN(0, "PA0"),
+ PINCTRL_PIN(1, "PA1"),
+ PINCTRL_PIN(2, "PA2"),
+ PINCTRL_PIN(3, "PG3"),
+ PINCTRL_PIN(4, "PA4"),
+ PINCTRL_PIN(5, "PA5"),
+ PINCTRL_PIN(6, "PA6"),
+ PINCTRL_PIN(7, "PA7"),
+ PINCTRL_PIN(8, "PA8"),
+ PINCTRL_PIN(9, "PA9"),
+ PINCTRL_PIN(10, "PA10"),
+ PINCTRL_PIN(11, "PA11"),
+ PINCTRL_PIN(12, "PA12"),
+ PINCTRL_PIN(13, "PA13"),
+ PINCTRL_PIN(14, "PA14"),
+ PINCTRL_PIN(15, "PA15"),
+ PINCTRL_PIN(16, "PB0"),
+ PINCTRL_PIN(17, "PB1"),
+ PINCTRL_PIN(18, "PB2"),
+ PINCTRL_PIN(19, "PB3"),
+ PINCTRL_PIN(20, "PB4"),
+ PINCTRL_PIN(21, "PB5"),
+ PINCTRL_PIN(22, "PB6"),
+ PINCTRL_PIN(23, "PB7"),
+ PINCTRL_PIN(24, "PB8"),
+ PINCTRL_PIN(25, "PB9"),
+ PINCTRL_PIN(26, "PB10"),
+ PINCTRL_PIN(27, "PB11"),
+ PINCTRL_PIN(28, "PB12"),
+ PINCTRL_PIN(29, "PB13"),
+ PINCTRL_PIN(30, "PB14"),
+ PINCTRL_PIN(32, "PC0"),
+ PINCTRL_PIN(33, "PC1"),
+ PINCTRL_PIN(34, "PC2"),
+ PINCTRL_PIN(35, "PC3"),
+ PINCTRL_PIN(36, "PC4"),
+ PINCTRL_PIN(37, "PC5"),
+ PINCTRL_PIN(38, "PC6"),
+ PINCTRL_PIN(39, "PC7"),
+ PINCTRL_PIN(40, "PC8"),
+ PINCTRL_PIN(41, "PC9"),
+ PINCTRL_PIN(42, "PC10"),
+ PINCTRL_PIN(43, "PC11"),
+ PINCTRL_PIN(44, "PC12"),
+ PINCTRL_PIN(45, "PC13"),
+ PINCTRL_PIN(48, "PD0"),
+ PINCTRL_PIN(49, "PD1"),
+ PINCTRL_PIN(50, "PD2"),
+ PINCTRL_PIN(51, "PD3"),
+ PINCTRL_PIN(52, "PD4"),
+ PINCTRL_PIN(53, "PD5"),
+ PINCTRL_PIN(54, "PD6"),
+ PINCTRL_PIN(55, "PD7"),
+ PINCTRL_PIN(56, "PD8"),
+ PINCTRL_PIN(57, "PD9"),
+ PINCTRL_PIN(58, "PD10"),
+ PINCTRL_PIN(59, "PD11"),
+ PINCTRL_PIN(60, "PD12"),
+ PINCTRL_PIN(61, "PD13"),
+ PINCTRL_PIN(62, "PD14"),
+ PINCTRL_PIN(63, "PD15"),
+ PINCTRL_PIN(64, "PE0"),
+ PINCTRL_PIN(65, "PE1"),
+ PINCTRL_PIN(66, "PE2"),
+ PINCTRL_PIN(67, "PE3"),
+ PINCTRL_PIN(68, "PE4"),
+ PINCTRL_PIN(69, "PE5"),
+ PINCTRL_PIN(70, "PE6"),
+ PINCTRL_PIN(71, "PE7"),
+ PINCTRL_PIN(72, "PE8"),
+ PINCTRL_PIN(73, "PE9"),
+ PINCTRL_PIN(74, "PE10"),
+ PINCTRL_PIN(75, "PE11"),
+ PINCTRL_PIN(76, "PE12"),
+ PINCTRL_PIN(77, "PE13"),
+ PINCTRL_PIN(78, "PE14"),
+ PINCTRL_PIN(79, "PE15"),
+ PINCTRL_PIN(80, "PF0"),
+ PINCTRL_PIN(81, "PF1"),
+ PINCTRL_PIN(82, "PF2"),
+ PINCTRL_PIN(83, "PF3"),
+ PINCTRL_PIN(84, "PF4"),
+ PINCTRL_PIN(85, "PF5"),
+ PINCTRL_PIN(86, "PF6"),
+ PINCTRL_PIN(87, "PF7"),
+ PINCTRL_PIN(88, "PF8"),
+ PINCTRL_PIN(89, "PF9"),
+ PINCTRL_PIN(90, "PF10"),
+ PINCTRL_PIN(91, "PF11"),
+ PINCTRL_PIN(92, "PF12"),
+ PINCTRL_PIN(93, "PF13"),
+ PINCTRL_PIN(94, "PF14"),
+ PINCTRL_PIN(95, "PF15"),
+ PINCTRL_PIN(96, "PG0"),
+ PINCTRL_PIN(97, "PG1"),
+ PINCTRL_PIN(98, "PG2"),
+ PINCTRL_PIN(99, "PG3"),
+ PINCTRL_PIN(100, "PG4"),
+ PINCTRL_PIN(101, "PG5"),
+ PINCTRL_PIN(102, "PG6"),
+ PINCTRL_PIN(103, "PG7"),
+ PINCTRL_PIN(104, "PG8"),
+ PINCTRL_PIN(105, "PG9"),
+ PINCTRL_PIN(106, "PG10"),
+ PINCTRL_PIN(107, "PG11"),
+ PINCTRL_PIN(108, "PG12"),
+ PINCTRL_PIN(109, "PG13"),
+ PINCTRL_PIN(110, "PG14"),
+ PINCTRL_PIN(111, "PG15"),
+ PINCTRL_PIN(112, "PH0"),
+ PINCTRL_PIN(113, "PH1"),
+ PINCTRL_PIN(114, "PH2"),
+ PINCTRL_PIN(115, "PH3"),
+ PINCTRL_PIN(116, "PH4"),
+ PINCTRL_PIN(117, "PH5"),
+ PINCTRL_PIN(118, "PH6"),
+ PINCTRL_PIN(119, "PH7"),
+ PINCTRL_PIN(120, "PH8"),
+ PINCTRL_PIN(121, "PH9"),
+ PINCTRL_PIN(122, "PH10"),
+ PINCTRL_PIN(123, "PH11"),
+ PINCTRL_PIN(124, "PH12"),
+ PINCTRL_PIN(125, "PH13"),
+ PINCTRL_PIN(128, "PI0"),
+ PINCTRL_PIN(129, "PI1"),
+ PINCTRL_PIN(130, "PI2"),
+ PINCTRL_PIN(131, "PI3"),
+ PINCTRL_PIN(132, "PI4"),
+ PINCTRL_PIN(133, "PI5"),
+ PINCTRL_PIN(134, "PI6"),
+ PINCTRL_PIN(135, "PI7"),
+ PINCTRL_PIN(136, "PI8"),
+ PINCTRL_PIN(137, "PI9"),
+ PINCTRL_PIN(138, "PI10"),
+ PINCTRL_PIN(139, "PI11"),
+ PINCTRL_PIN(140, "PI12"),
+ PINCTRL_PIN(141, "PI13"),
+ PINCTRL_PIN(142, "PI14"),
+ PINCTRL_PIN(143, "PI15"),
+ PINCTRL_PIN(144, "PJ0"),
+ PINCTRL_PIN(145, "PJ1"),
+ PINCTRL_PIN(146, "PJ2"),
+ PINCTRL_PIN(147, "PJ3"),
+ PINCTRL_PIN(148, "PJ4"),
+ PINCTRL_PIN(149, "PJ5"),
+ PINCTRL_PIN(150, "PJ6"),
+ PINCTRL_PIN(151, "PJ7"),
+ PINCTRL_PIN(152, "PJ8"),
+ PINCTRL_PIN(153, "PJ9"),
+ PINCTRL_PIN(154, "PJ10"),
+ PINCTRL_PIN(155, "PJ11"),
+ PINCTRL_PIN(156, "PJ12"),
+ PINCTRL_PIN(157, "PJ13"),
+};
+
+static const unsigned uart0_pins[] = {
+ GPIO_PE7, GPIO_PE8,
+};
+
+static const unsigned uart1_pins[] = {
+ GPIO_PH0, GPIO_PH1,
+};
+
+static const unsigned uart1_ctsrts_pins[] = {
+ GPIO_PE9, GPIO_PE10,
+};
+
+static const unsigned uart2_pins[] = {
+ GPIO_PB4, GPIO_PB5,
+};
+
+static const unsigned uart3_pins[] = {
+ GPIO_PB6, GPIO_PB7,
+};
+
+static const unsigned uart3_ctsrts_pins[] = {
+ GPIO_PB2, GPIO_PB3,
+};
+
+static const unsigned rsi0_pins[] = {
+ GPIO_PC8, GPIO_PC9, GPIO_PC10, GPIO_PC11, GPIO_PC12, GPIO_PC13,
+};
+
+static const unsigned spi0_pins[] = {
+ GPIO_PE0, GPIO_PE1, GPIO_PE2,
+};
+
+static const unsigned spi1_pins[] = {
+ GPIO_PG8, GPIO_PG9, GPIO_PG10,
+};
+
+static const unsigned twi0_pins[] = {
+ GPIO_PE14, GPIO_PE15,
+};
+
+static const unsigned twi1_pins[] = {
+ GPIO_PB0, GPIO_PB1,
+};
+
+static const unsigned rotary_pins[] = {
+ GPIO_PH4, GPIO_PH3, GPIO_PH5,
+};
+
+static const unsigned can0_pins[] = {
+ GPIO_PG13, GPIO_PG12,
+};
+
+static const unsigned can1_pins[] = {
+ GPIO_PG14, GPIO_PG15,
+};
+
+static const unsigned smc0_pins[] = {
+ GPIO_PH8, GPIO_PH9, GPIO_PH10, GPIO_PH11, GPIO_PH12, GPIO_PH13,
+ GPIO_PI0, GPIO_PI1, GPIO_PI2, GPIO_PI3, GPIO_PI4, GPIO_PI5, GPIO_PI6,
+ GPIO_PI7, GPIO_PI8, GPIO_PI9, GPIO_PI10, GPIO_PI11,
+ GPIO_PI12, GPIO_PI13, GPIO_PI14, GPIO_PI15,
+};
+
+static const unsigned sport0_pins[] = {
+ GPIO_PC0, GPIO_PC2, GPIO_PC3, GPIO_PC4, GPIO_PC6, GPIO_PC7,
+};
+
+static const unsigned sport1_pins[] = {
+ GPIO_PD0, GPIO_PD2, GPIO_PD3, GPIO_PD4, GPIO_PD6, GPIO_PD7,
+};
+
+static const unsigned sport2_pins[] = {
+ GPIO_PA0, GPIO_PA2, GPIO_PA3, GPIO_PA4, GPIO_PA6, GPIO_PA7,
+};
+
+static const unsigned sport3_pins[] = {
+ GPIO_PA8, GPIO_PA10, GPIO_PA11, GPIO_PA12, GPIO_PA14, GPIO_PA15,
+};
+
+static const unsigned ppi0_8b_pins[] = {
+ GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6,
+ GPIO_PF7, GPIO_PF13, GPIO_PG0, GPIO_PG1, GPIO_PG2,
+};
+
+static const unsigned ppi0_16b_pins[] = {
+ GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6,
+ GPIO_PF7, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12,
+ GPIO_PF13, GPIO_PF14, GPIO_PF15,
+ GPIO_PG0, GPIO_PG1, GPIO_PG2,
+};
+
+static const unsigned ppi0_24b_pins[] = {
+ GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6,
+ GPIO_PF7, GPIO_PF8, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12,
+ GPIO_PF13, GPIO_PF14, GPIO_PF15, GPIO_PD0, GPIO_PD1, GPIO_PD2,
+ GPIO_PD3, GPIO_PD4, GPIO_PD5, GPIO_PG3, GPIO_PG4,
+ GPIO_PG0, GPIO_PG1, GPIO_PG2,
+};
+
+static const unsigned ppi1_8b_pins[] = {
+ GPIO_PD0, GPIO_PD1, GPIO_PD2, GPIO_PD3, GPIO_PD4, GPIO_PD5, GPIO_PD6,
+ GPIO_PD7, GPIO_PE11, GPIO_PE12, GPIO_PE13,
+};
+
+static const unsigned ppi1_16b_pins[] = {
+ GPIO_PD0, GPIO_PD1, GPIO_PD2, GPIO_PD3, GPIO_PD4, GPIO_PD5, GPIO_PD6,
+ GPIO_PD7, GPIO_PD8, GPIO_PD9, GPIO_PD10, GPIO_PD11, GPIO_PD12,
+ GPIO_PD13, GPIO_PD14, GPIO_PD15,
+ GPIO_PE11, GPIO_PE12, GPIO_PE13,
+};
+
+static const unsigned ppi2_8b_pins[] = {
+ GPIO_PD8, GPIO_PD9, GPIO_PD10, GPIO_PD11, GPIO_PD12,
+ GPIO_PD13, GPIO_PD14, GPIO_PD15,
+ GPIO_PA7, GPIO_PB0, GPIO_PB1, GPIO_PB2, GPIO_PB3,
+};
+
+static const unsigned atapi_pins[] = {
+ GPIO_PH2, GPIO_PJ3, GPIO_PJ4, GPIO_PJ5, GPIO_PJ6,
+ GPIO_PJ7, GPIO_PJ8, GPIO_PJ9, GPIO_PJ10,
+};
+
+static const unsigned atapi_alter_pins[] = {
+ GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6,
+ GPIO_PF7, GPIO_PF8, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12,
+ GPIO_PF13, GPIO_PF14, GPIO_PF15, GPIO_PG2, GPIO_PG3, GPIO_PG4,
+};
+
+static const unsigned nfc0_pins[] = {
+ GPIO_PJ1, GPIO_PJ2,
+};
+
+static const unsigned keys_4x4_pins[] = {
+ GPIO_PD8, GPIO_PD9, GPIO_PD10, GPIO_PD11,
+ GPIO_PD12, GPIO_PD13, GPIO_PD14, GPIO_PD15,
+};
+
+static const unsigned keys_8x8_pins[] = {
+ GPIO_PD8, GPIO_PD9, GPIO_PD10, GPIO_PD11,
+ GPIO_PD12, GPIO_PD13, GPIO_PD14, GPIO_PD15,
+ GPIO_PE0, GPIO_PE1, GPIO_PE2, GPIO_PE3,
+ GPIO_PE4, GPIO_PE5, GPIO_PE6, GPIO_PE7,
+};
+
+static const struct adi_pin_group adi_pin_groups[] = {
+ ADI_PIN_GROUP("uart0grp", uart0_pins),
+ ADI_PIN_GROUP("uart1grp", uart1_pins),
+ ADI_PIN_GROUP("uart1ctsrtsgrp", uart1_ctsrts_pins),
+ ADI_PIN_GROUP("uart2grp", uart2_pins),
+ ADI_PIN_GROUP("uart3grp", uart3_pins),
+ ADI_PIN_GROUP("uart3ctsrtsgrp", uart3_ctsrts_pins),
+ ADI_PIN_GROUP("rsi0grp", rsi0_pins),
+ ADI_PIN_GROUP("spi0grp", spi0_pins),
+ ADI_PIN_GROUP("spi1grp", spi1_pins),
+ ADI_PIN_GROUP("twi0grp", twi0_pins),
+ ADI_PIN_GROUP("twi1grp", twi1_pins),
+ ADI_PIN_GROUP("rotarygrp", rotary_pins),
+ ADI_PIN_GROUP("can0grp", can0_pins),
+ ADI_PIN_GROUP("can1grp", can1_pins),
+ ADI_PIN_GROUP("smc0grp", smc0_pins),
+ ADI_PIN_GROUP("sport0grp", sport0_pins),
+ ADI_PIN_GROUP("sport1grp", sport1_pins),
+ ADI_PIN_GROUP("sport2grp", sport2_pins),
+ ADI_PIN_GROUP("sport3grp", sport3_pins),
+ ADI_PIN_GROUP("ppi0_8bgrp", ppi0_8b_pins),
+ ADI_PIN_GROUP("ppi0_16bgrp", ppi0_16b_pins),
+ ADI_PIN_GROUP("ppi0_24bgrp", ppi0_24b_pins),
+ ADI_PIN_GROUP("ppi1_8bgrp", ppi1_8b_pins),
+ ADI_PIN_GROUP("ppi1_16bgrp", ppi1_16b_pins),
+ ADI_PIN_GROUP("ppi2_8bgrp", ppi2_8b_pins),
+ ADI_PIN_GROUP("atapigrp", atapi_pins),
+ ADI_PIN_GROUP("atapialtergrp", atapi_alter_pins),
+ ADI_PIN_GROUP("nfc0grp", nfc0_pins),
+ ADI_PIN_GROUP("keys_4x4grp", keys_4x4_pins),
+ ADI_PIN_GROUP("keys_8x8grp", keys_8x8_pins),
+};
+
+static const unsigned short uart0_mux[] = {
+ P_UART0_TX, P_UART0_RX,
+ 0
+};
+
+static const unsigned short uart1_mux[] = {
+ P_UART1_TX, P_UART1_RX,
+ 0
+};
+
+static const unsigned short uart1_ctsrts_mux[] = {
+ P_UART1_RTS, P_UART1_CTS,
+ 0
+};
+
+static const unsigned short uart2_mux[] = {
+ P_UART2_TX, P_UART2_RX,
+ 0
+};
+
+static const unsigned short uart3_mux[] = {
+ P_UART3_TX, P_UART3_RX,
+ 0
+};
+
+static const unsigned short uart3_ctsrts_mux[] = {
+ P_UART3_RTS, P_UART3_CTS,
+ 0
+};
+
+static const unsigned short rsi0_mux[] = {
+ P_SD_D0, P_SD_D1, P_SD_D2, P_SD_D3, P_SD_CLK, P_SD_CMD,
+ 0
+};
+
+static const unsigned short spi0_mux[] = {
+ P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0
+};
+
+static const unsigned short spi1_mux[] = {
+ P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0
+};
+
+static const unsigned short twi0_mux[] = {
+ P_TWI0_SCL, P_TWI0_SDA, 0
+};
+
+static const unsigned short twi1_mux[] = {
+ P_TWI1_SCL, P_TWI1_SDA, 0
+};
+
+static const unsigned short rotary_mux[] = {
+ P_CNT_CUD, P_CNT_CDG, P_CNT_CZM, 0
+};
+
+static const unsigned short sport0_mux[] = {
+ P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
+ P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
+};
+
+static const unsigned short sport1_mux[] = {
+ P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
+ P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
+};
+
+static const unsigned short sport2_mux[] = {
+ P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, P_SPORT2_RFS,
+ P_SPORT2_DRPRI, P_SPORT2_RSCLK, 0
+};
+
+static const unsigned short sport3_mux[] = {
+ P_SPORT3_TFS, P_SPORT3_DTPRI, P_SPORT3_TSCLK, P_SPORT3_RFS,
+ P_SPORT3_DRPRI, P_SPORT3_RSCLK, 0
+};
+
+static const unsigned short can0_mux[] = {
+ P_CAN0_RX, P_CAN0_TX, 0
+};
+
+static const unsigned short can1_mux[] = {
+ P_CAN1_RX, P_CAN1_TX, 0
+};
+
+static const unsigned short smc0_mux[] = {
+ P_A4, P_A5, P_A6, P_A7, P_A8, P_A9, P_A10, P_A11, P_A12,
+ P_A13, P_A14, P_A15, P_A16, P_A17, P_A18, P_A19, P_A20, P_A21,
+ P_A22, P_A23, P_A24, P_A25, P_NOR_CLK, 0,
+};
+
+static const unsigned short ppi0_8b_mux[] = {
+ P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+ P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+ P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+ 0,
+};
+
+static const unsigned short ppi0_16b_mux[] = {
+ P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+ P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+ P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+ P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15,
+ P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+ 0,
+};
+
+static const unsigned short ppi0_24b_mux[] = {
+ P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+ P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+ P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+ P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15,
+ P_PPI0_D16, P_PPI0_D17, P_PPI0_D18, P_PPI0_D19,
+ P_PPI0_D20, P_PPI0_D21, P_PPI0_D22, P_PPI0_D23,
+ P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+ 0,
+};
+
+static const unsigned short ppi1_8b_mux[] = {
+ P_PPI1_D0, P_PPI1_D1, P_PPI1_D2, P_PPI1_D3,
+ P_PPI1_D4, P_PPI1_D5, P_PPI1_D6, P_PPI1_D7,
+ P_PPI1_CLK, P_PPI1_FS1, P_PPI1_FS2,
+ 0,
+};
+
+static const unsigned short ppi1_16b_mux[] = {
+ P_PPI1_D0, P_PPI1_D1, P_PPI1_D2, P_PPI1_D3,
+ P_PPI1_D4, P_PPI1_D5, P_PPI1_D6, P_PPI1_D7,
+ P_PPI1_D8, P_PPI1_D9, P_PPI1_D10, P_PPI1_D11,
+ P_PPI1_D12, P_PPI1_D13, P_PPI1_D14, P_PPI1_D15,
+ P_PPI1_CLK, P_PPI1_FS1, P_PPI1_FS2,
+ 0,
+};
+
+static const unsigned short ppi2_8b_mux[] = {
+ P_PPI2_D0, P_PPI2_D1, P_PPI2_D2, P_PPI2_D3,
+ P_PPI2_D4, P_PPI2_D5, P_PPI2_D6, P_PPI2_D7,
+ P_PPI2_CLK, P_PPI2_FS1, P_PPI2_FS2,
+ 0,
+};
+
+static const unsigned short atapi_mux[] = {
+ P_ATAPI_RESET, P_ATAPI_DIOR, P_ATAPI_DIOW, P_ATAPI_CS0, P_ATAPI_CS1,
+ P_ATAPI_DMACK, P_ATAPI_DMARQ, P_ATAPI_INTRQ, P_ATAPI_IORDY,
+};
+
+static const unsigned short atapi_alter_mux[] = {
+ P_ATAPI_D0A, P_ATAPI_D1A, P_ATAPI_D2A, P_ATAPI_D3A, P_ATAPI_D4A,
+ P_ATAPI_D5A, P_ATAPI_D6A, P_ATAPI_D7A, P_ATAPI_D8A, P_ATAPI_D9A,
+ P_ATAPI_D10A, P_ATAPI_D11A, P_ATAPI_D12A, P_ATAPI_D13A, P_ATAPI_D14A,
+ P_ATAPI_D15A, P_ATAPI_A0A, P_ATAPI_A1A, P_ATAPI_A2A,
+ 0
+};
+
+static const unsigned short nfc0_mux[] = {
+ P_NAND_CE, P_NAND_RB,
+ 0
+};
+
+static const unsigned short keys_4x4_mux[] = {
+ P_KEY_ROW3, P_KEY_ROW2, P_KEY_ROW1, P_KEY_ROW0,
+ P_KEY_COL3, P_KEY_COL2, P_KEY_COL1, P_KEY_COL0,
+ 0
+};
+
+static const unsigned short keys_8x8_mux[] = {
+ P_KEY_ROW7, P_KEY_ROW6, P_KEY_ROW5, P_KEY_ROW4,
+ P_KEY_ROW3, P_KEY_ROW2, P_KEY_ROW1, P_KEY_ROW0,
+ P_KEY_COL7, P_KEY_COL6, P_KEY_COL5, P_KEY_COL4,
+ P_KEY_COL3, P_KEY_COL2, P_KEY_COL1, P_KEY_COL0,
+ 0
+};
+
+static const char * const uart0grp[] = { "uart0grp" };
+static const char * const uart1grp[] = { "uart1grp" };
+static const char * const uart1ctsrtsgrp[] = { "uart1ctsrtsgrp" };
+static const char * const uart2grp[] = { "uart2grp" };
+static const char * const uart3grp[] = { "uart3grp" };
+static const char * const uart3ctsrtsgrp[] = { "uart3ctsrtsgrp" };
+static const char * const rsi0grp[] = { "rsi0grp" };
+static const char * const spi0grp[] = { "spi0grp" };
+static const char * const spi1grp[] = { "spi1grp" };
+static const char * const twi0grp[] = { "twi0grp" };
+static const char * const twi1grp[] = { "twi1grp" };
+static const char * const rotarygrp[] = { "rotarygrp" };
+static const char * const can0grp[] = { "can0grp" };
+static const char * const can1grp[] = { "can1grp" };
+static const char * const smc0grp[] = { "smc0grp" };
+static const char * const sport0grp[] = { "sport0grp" };
+static const char * const sport1grp[] = { "sport1grp" };
+static const char * const sport2grp[] = { "sport2grp" };
+static const char * const sport3grp[] = { "sport3grp" };
+static const char * const ppi0_8bgrp[] = { "ppi0_8bgrp" };
+static const char * const ppi0_16bgrp[] = { "ppi0_16bgrp" };
+static const char * const ppi0_24bgrp[] = { "ppi0_24bgrp" };
+static const char * const ppi1_8bgrp[] = { "ppi1_8bgrp" };
+static const char * const ppi1_16bgrp[] = { "ppi1_16bgrp" };
+static const char * const ppi2_8bgrp[] = { "ppi2_8bgrp" };
+static const char * const atapigrp[] = { "atapigrp" };
+static const char * const atapialtergrp[] = { "atapialtergrp" };
+static const char * const nfc0grp[] = { "nfc0grp" };
+static const char * const keys_4x4grp[] = { "keys_4x4grp" };
+static const char * const keys_8x8grp[] = { "keys_8x8grp" };
+
+static const struct adi_pmx_func adi_pmx_functions[] = {
+ ADI_PMX_FUNCTION("uart0", uart0grp, uart0_mux),
+ ADI_PMX_FUNCTION("uart1", uart1grp, uart1_mux),
+ ADI_PMX_FUNCTION("uart1_ctsrts", uart1ctsrtsgrp, uart1_ctsrts_mux),
+ ADI_PMX_FUNCTION("uart2", uart2grp, uart2_mux),
+ ADI_PMX_FUNCTION("uart3", uart3grp, uart3_mux),
+ ADI_PMX_FUNCTION("uart3_ctsrts", uart3ctsrtsgrp, uart3_ctsrts_mux),
+ ADI_PMX_FUNCTION("rsi0", rsi0grp, rsi0_mux),
+ ADI_PMX_FUNCTION("spi0", spi0grp, spi0_mux),
+ ADI_PMX_FUNCTION("spi1", spi1grp, spi1_mux),
+ ADI_PMX_FUNCTION("twi0", twi0grp, twi0_mux),
+ ADI_PMX_FUNCTION("twi1", twi1grp, twi1_mux),
+ ADI_PMX_FUNCTION("rotary", rotarygrp, rotary_mux),
+ ADI_PMX_FUNCTION("can0", can0grp, can0_mux),
+ ADI_PMX_FUNCTION("can1", can1grp, can1_mux),
+ ADI_PMX_FUNCTION("smc0", smc0grp, smc0_mux),
+ ADI_PMX_FUNCTION("sport0", sport0grp, sport0_mux),
+ ADI_PMX_FUNCTION("sport1", sport1grp, sport1_mux),
+ ADI_PMX_FUNCTION("sport2", sport2grp, sport2_mux),
+ ADI_PMX_FUNCTION("sport3", sport3grp, sport3_mux),
+ ADI_PMX_FUNCTION("ppi0_8b", ppi0_8bgrp, ppi0_8b_mux),
+ ADI_PMX_FUNCTION("ppi0_16b", ppi0_16bgrp, ppi0_16b_mux),
+ ADI_PMX_FUNCTION("ppi0_24b", ppi0_24bgrp, ppi0_24b_mux),
+ ADI_PMX_FUNCTION("ppi1_8b", ppi1_8bgrp, ppi1_8b_mux),
+ ADI_PMX_FUNCTION("ppi1_16b", ppi1_16bgrp, ppi1_16b_mux),
+ ADI_PMX_FUNCTION("ppi2_8b", ppi2_8bgrp, ppi2_8b_mux),
+ ADI_PMX_FUNCTION("atapi", atapigrp, atapi_mux),
+ ADI_PMX_FUNCTION("atapi_alter", atapialtergrp, atapi_alter_mux),
+ ADI_PMX_FUNCTION("nfc0", nfc0grp, nfc0_mux),
+ ADI_PMX_FUNCTION("keys_4x4", keys_4x4grp, keys_4x4_mux),
+ ADI_PMX_FUNCTION("keys_8x8", keys_8x8grp, keys_8x8_mux),
+};
+
+static const struct adi_pinctrl_soc_data adi_bf54x_soc = {
+ .functions = adi_pmx_functions,
+ .nfunctions = ARRAY_SIZE(adi_pmx_functions),
+ .groups = adi_pin_groups,
+ .ngroups = ARRAY_SIZE(adi_pin_groups),
+ .pins = adi_pads,
+ .npins = ARRAY_SIZE(adi_pads),
+};
+
+void adi_pinctrl_soc_init(const struct adi_pinctrl_soc_data **soc)
+{
+ *soc = &adi_bf54x_soc;
+}
diff --git a/drivers/pinctrl/pinctrl-adi2-bf60x.c b/drivers/pinctrl/pinctrl-adi2-bf60x.c
new file mode 100644
index 000000000000..bf57aea2826c
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-adi2-bf60x.c
@@ -0,0 +1,521 @@
+/*
+ * Pinctrl Driver for ADI GPIO2 controller
+ *
+ * Copyright 2007-2013 Analog Devices Inc.
+ *
+ * Licensed under the GPLv2 or later
+ */
+
+#include <asm/portmux.h>
+#include "pinctrl-adi2.h"
+
+static const struct pinctrl_pin_desc adi_pads[] = {
+ PINCTRL_PIN(0, "PA0"),
+ PINCTRL_PIN(1, "PA1"),
+ PINCTRL_PIN(2, "PA2"),
+ PINCTRL_PIN(3, "PG3"),
+ PINCTRL_PIN(4, "PA4"),
+ PINCTRL_PIN(5, "PA5"),
+ PINCTRL_PIN(6, "PA6"),
+ PINCTRL_PIN(7, "PA7"),
+ PINCTRL_PIN(8, "PA8"),
+ PINCTRL_PIN(9, "PA9"),
+ PINCTRL_PIN(10, "PA10"),
+ PINCTRL_PIN(11, "PA11"),
+ PINCTRL_PIN(12, "PA12"),
+ PINCTRL_PIN(13, "PA13"),
+ PINCTRL_PIN(14, "PA14"),
+ PINCTRL_PIN(15, "PA15"),
+ PINCTRL_PIN(16, "PB0"),
+ PINCTRL_PIN(17, "PB1"),
+ PINCTRL_PIN(18, "PB2"),
+ PINCTRL_PIN(19, "PB3"),
+ PINCTRL_PIN(20, "PB4"),
+ PINCTRL_PIN(21, "PB5"),
+ PINCTRL_PIN(22, "PB6"),
+ PINCTRL_PIN(23, "PB7"),
+ PINCTRL_PIN(24, "PB8"),
+ PINCTRL_PIN(25, "PB9"),
+ PINCTRL_PIN(26, "PB10"),
+ PINCTRL_PIN(27, "PB11"),
+ PINCTRL_PIN(28, "PB12"),
+ PINCTRL_PIN(29, "PB13"),
+ PINCTRL_PIN(30, "PB14"),
+ PINCTRL_PIN(31, "PB15"),
+ PINCTRL_PIN(32, "PC0"),
+ PINCTRL_PIN(33, "PC1"),
+ PINCTRL_PIN(34, "PC2"),
+ PINCTRL_PIN(35, "PC3"),
+ PINCTRL_PIN(36, "PC4"),
+ PINCTRL_PIN(37, "PC5"),
+ PINCTRL_PIN(38, "PC6"),
+ PINCTRL_PIN(39, "PC7"),
+ PINCTRL_PIN(40, "PC8"),
+ PINCTRL_PIN(41, "PC9"),
+ PINCTRL_PIN(42, "PC10"),
+ PINCTRL_PIN(43, "PC11"),
+ PINCTRL_PIN(44, "PC12"),
+ PINCTRL_PIN(45, "PC13"),
+ PINCTRL_PIN(46, "PC14"),
+ PINCTRL_PIN(47, "PC15"),
+ PINCTRL_PIN(48, "PD0"),
+ PINCTRL_PIN(49, "PD1"),
+ PINCTRL_PIN(50, "PD2"),
+ PINCTRL_PIN(51, "PD3"),
+ PINCTRL_PIN(52, "PD4"),
+ PINCTRL_PIN(53, "PD5"),
+ PINCTRL_PIN(54, "PD6"),
+ PINCTRL_PIN(55, "PD7"),
+ PINCTRL_PIN(56, "PD8"),
+ PINCTRL_PIN(57, "PD9"),
+ PINCTRL_PIN(58, "PD10"),
+ PINCTRL_PIN(59, "PD11"),
+ PINCTRL_PIN(60, "PD12"),
+ PINCTRL_PIN(61, "PD13"),
+ PINCTRL_PIN(62, "PD14"),
+ PINCTRL_PIN(63, "PD15"),
+ PINCTRL_PIN(64, "PE0"),
+ PINCTRL_PIN(65, "PE1"),
+ PINCTRL_PIN(66, "PE2"),
+ PINCTRL_PIN(67, "PE3"),
+ PINCTRL_PIN(68, "PE4"),
+ PINCTRL_PIN(69, "PE5"),
+ PINCTRL_PIN(70, "PE6"),
+ PINCTRL_PIN(71, "PE7"),
+ PINCTRL_PIN(72, "PE8"),
+ PINCTRL_PIN(73, "PE9"),
+ PINCTRL_PIN(74, "PE10"),
+ PINCTRL_PIN(75, "PE11"),
+ PINCTRL_PIN(76, "PE12"),
+ PINCTRL_PIN(77, "PE13"),
+ PINCTRL_PIN(78, "PE14"),
+ PINCTRL_PIN(79, "PE15"),
+ PINCTRL_PIN(80, "PF0"),
+ PINCTRL_PIN(81, "PF1"),
+ PINCTRL_PIN(82, "PF2"),
+ PINCTRL_PIN(83, "PF3"),
+ PINCTRL_PIN(84, "PF4"),
+ PINCTRL_PIN(85, "PF5"),
+ PINCTRL_PIN(86, "PF6"),
+ PINCTRL_PIN(87, "PF7"),
+ PINCTRL_PIN(88, "PF8"),
+ PINCTRL_PIN(89, "PF9"),
+ PINCTRL_PIN(90, "PF10"),
+ PINCTRL_PIN(91, "PF11"),
+ PINCTRL_PIN(92, "PF12"),
+ PINCTRL_PIN(93, "PF13"),
+ PINCTRL_PIN(94, "PF14"),
+ PINCTRL_PIN(95, "PF15"),
+ PINCTRL_PIN(96, "PG0"),
+ PINCTRL_PIN(97, "PG1"),
+ PINCTRL_PIN(98, "PG2"),
+ PINCTRL_PIN(99, "PG3"),
+ PINCTRL_PIN(100, "PG4"),
+ PINCTRL_PIN(101, "PG5"),
+ PINCTRL_PIN(102, "PG6"),
+ PINCTRL_PIN(103, "PG7"),
+ PINCTRL_PIN(104, "PG8"),
+ PINCTRL_PIN(105, "PG9"),
+ PINCTRL_PIN(106, "PG10"),
+ PINCTRL_PIN(107, "PG11"),
+ PINCTRL_PIN(108, "PG12"),
+ PINCTRL_PIN(109, "PG13"),
+ PINCTRL_PIN(110, "PG14"),
+ PINCTRL_PIN(111, "PG15"),
+};
+
+static const unsigned uart0_pins[] = {
+ GPIO_PD7, GPIO_PD8,
+};
+
+static const unsigned uart0_ctsrts_pins[] = {
+ GPIO_PD9, GPIO_PD10,
+};
+
+static const unsigned uart1_pins[] = {
+ GPIO_PG15, GPIO_PG14,
+};
+
+static const unsigned uart1_ctsrts_pins[] = {
+ GPIO_PG10, GPIO_PG13,
+};
+
+static const unsigned rsi0_pins[] = {
+ GPIO_PG3, GPIO_PG2, GPIO_PG0, GPIO_PE15, GPIO_PG5, GPIO_PG6,
+};
+
+static const unsigned eth0_pins[] = {
+ GPIO_PC6, GPIO_PC7, GPIO_PC2, GPIO_PC0, GPIO_PC3, GPIO_PC1,
+ GPIO_PB13, GPIO_PD6, GPIO_PC5, GPIO_PC4, GPIO_PB14, GPIO_PB15,
+};
+
+static const unsigned eth1_pins[] = {
+ GPIO_PE10, GPIO_PE11, GPIO_PG3, GPIO_PG0, GPIO_PG2, GPIO_PE15,
+ GPIO_PG5, GPIO_PE12, GPIO_PE13, GPIO_PE14, GPIO_PG6, GPIO_PC9,
+};
+
+static const unsigned spi0_pins[] = {
+ GPIO_PD4, GPIO_PD2, GPIO_PD3,
+};
+
+static const unsigned spi1_pins[] = {
+ GPIO_PD5, GPIO_PD14, GPIO_PD13,
+};
+
+static const unsigned twi0_pins[] = {
+};
+
+static const unsigned twi1_pins[] = {
+};
+
+static const unsigned rotary_pins[] = {
+ GPIO_PG7, GPIO_PG11, GPIO_PG12,
+};
+
+static const unsigned can0_pins[] = {
+ GPIO_PG1, GPIO_PG4,
+};
+
+static const unsigned smc0_pins[] = {
+ GPIO_PA0, GPIO_PA1, GPIO_PA2, GPIO_PA3, GPIO_PA4, GPIO_PA5, GPIO_PA6,
+ GPIO_PA7, GPIO_PA8, GPIO_PA9, GPIO_PB2, GPIO_PA10, GPIO_PA11,
+ GPIO_PB3, GPIO_PA12, GPIO_PA13, GPIO_PA14, GPIO_PA15, GPIO_PB6,
+ GPIO_PB7, GPIO_PB8, GPIO_PB10, GPIO_PB11, GPIO_PB0,
+};
+
+static const unsigned sport0_pins[] = {
+ GPIO_PB5, GPIO_PB4, GPIO_PB9, GPIO_PB8, GPIO_PB7, GPIO_PB11,
+};
+
+static const unsigned sport1_pins[] = {
+ GPIO_PE2, GPIO_PE5, GPIO_PD15, GPIO_PE4, GPIO_PE3, GPIO_PE1,
+};
+
+static const unsigned sport2_pins[] = {
+ GPIO_PG4, GPIO_PG1, GPIO_PG9, GPIO_PG10, GPIO_PG7, GPIO_PB12,
+};
+
+static const unsigned ppi0_8b_pins[] = {
+ GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6,
+ GPIO_PF7, GPIO_PF13, GPIO_PF14, GPIO_PF15,
+ GPIO_PE6, GPIO_PE7, GPIO_PE8, GPIO_PE9,
+};
+
+static const unsigned ppi0_16b_pins[] = {
+ GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6,
+ GPIO_PF7, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12,
+ GPIO_PF13, GPIO_PF14, GPIO_PF15,
+ GPIO_PE6, GPIO_PE7, GPIO_PE8, GPIO_PE9,
+};
+
+static const unsigned ppi0_24b_pins[] = {
+ GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6,
+ GPIO_PF7, GPIO_PF8, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12,
+ GPIO_PF13, GPIO_PF14, GPIO_PF15, GPIO_PE0, GPIO_PE1, GPIO_PE2,
+ GPIO_PE3, GPIO_PE4, GPIO_PE5, GPIO_PE6, GPIO_PE7, GPIO_PE8,
+ GPIO_PE9, GPIO_PD12, GPIO_PD15,
+};
+
+static const unsigned ppi1_8b_pins[] = {
+ GPIO_PC0, GPIO_PC1, GPIO_PC2, GPIO_PC3, GPIO_PC4, GPIO_PC5, GPIO_PC6,
+ GPIO_PC7, GPIO_PC8, GPIO_PB13, GPIO_PB14, GPIO_PB15, GPIO_PD6,
+};
+
+static const unsigned ppi1_16b_pins[] = {
+ GPIO_PC0, GPIO_PC1, GPIO_PC2, GPIO_PC3, GPIO_PC4, GPIO_PC5, GPIO_PC6,
+ GPIO_PC7, GPIO_PC9, GPIO_PC10, GPIO_PC11, GPIO_PC12,
+ GPIO_PC13, GPIO_PC14, GPIO_PC15,
+ GPIO_PB13, GPIO_PB14, GPIO_PB15, GPIO_PD6,
+};
+
+static const unsigned ppi2_8b_pins[] = {
+ GPIO_PA0, GPIO_PA1, GPIO_PA2, GPIO_PA3, GPIO_PA4, GPIO_PA5, GPIO_PA6,
+ GPIO_PA7, GPIO_PB0, GPIO_PB1, GPIO_PB2, GPIO_PB3,
+};
+
+static const unsigned ppi2_16b_pins[] = {
+ GPIO_PA0, GPIO_PA1, GPIO_PA2, GPIO_PA3, GPIO_PA4, GPIO_PA5, GPIO_PA6,
+ GPIO_PA7, GPIO_PA8, GPIO_PA9, GPIO_PA10, GPIO_PA11, GPIO_PA12,
+ GPIO_PA13, GPIO_PA14, GPIO_PA15, GPIO_PB0, GPIO_PB1, GPIO_PB2,
+};
+
+static const unsigned lp0_pins[] = {
+ GPIO_PB0, GPIO_PB1, GPIO_PA0, GPIO_PA1, GPIO_PA2, GPIO_PA3,
+ GPIO_PA4, GPIO_PA5, GPIO_PA6, GPIO_PA7,
+};
+
+static const unsigned lp1_pins[] = {
+ GPIO_PB3, GPIO_PB2, GPIO_PA8, GPIO_PA9, GPIO_PA10, GPIO_PA11,
+ GPIO_PA12, GPIO_PA13, GPIO_PA14, GPIO_PA15,
+};
+
+static const unsigned lp2_pins[] = {
+ GPIO_PE6, GPIO_PE7, GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3,
+ GPIO_PF4, GPIO_PF5, GPIO_PF6, GPIO_PF7,
+};
+
+static const unsigned lp3_pins[] = {
+ GPIO_PE9, GPIO_PE8, GPIO_PF8, GPIO_PF9, GPIO_PF10, GPIO_PF11,
+ GPIO_PF12, GPIO_PF13, GPIO_PF14, GPIO_PF15,
+};
+
+static const struct adi_pin_group adi_pin_groups[] = {
+ ADI_PIN_GROUP("uart0grp", uart0_pins),
+ ADI_PIN_GROUP("uart0ctsrtsgrp", uart0_ctsrts_pins),
+ ADI_PIN_GROUP("uart1grp", uart1_pins),
+ ADI_PIN_GROUP("uart1ctsrtsgrp", uart1_ctsrts_pins),
+ ADI_PIN_GROUP("rsi0grp", rsi0_pins),
+ ADI_PIN_GROUP("eth0grp", eth0_pins),
+ ADI_PIN_GROUP("eth1grp", eth1_pins),
+ ADI_PIN_GROUP("spi0grp", spi0_pins),
+ ADI_PIN_GROUP("spi1grp", spi1_pins),
+ ADI_PIN_GROUP("twi0grp", twi0_pins),
+ ADI_PIN_GROUP("twi1grp", twi1_pins),
+ ADI_PIN_GROUP("rotarygrp", rotary_pins),
+ ADI_PIN_GROUP("can0grp", can0_pins),
+ ADI_PIN_GROUP("smc0grp", smc0_pins),
+ ADI_PIN_GROUP("sport0grp", sport0_pins),
+ ADI_PIN_GROUP("sport1grp", sport1_pins),
+ ADI_PIN_GROUP("sport2grp", sport2_pins),
+ ADI_PIN_GROUP("ppi0_8bgrp", ppi0_8b_pins),
+ ADI_PIN_GROUP("ppi0_16bgrp", ppi0_16b_pins),
+ ADI_PIN_GROUP("ppi0_24bgrp", ppi0_24b_pins),
+ ADI_PIN_GROUP("ppi1_8bgrp", ppi1_8b_pins),
+ ADI_PIN_GROUP("ppi1_16bgrp", ppi1_16b_pins),
+ ADI_PIN_GROUP("ppi2_8bgrp", ppi2_8b_pins),
+ ADI_PIN_GROUP("ppi2_16bgrp", ppi2_16b_pins),
+ ADI_PIN_GROUP("lp0grp", lp0_pins),
+ ADI_PIN_GROUP("lp1grp", lp1_pins),
+ ADI_PIN_GROUP("lp2grp", lp2_pins),
+ ADI_PIN_GROUP("lp3grp", lp3_pins),
+};
+
+static const unsigned short uart0_mux[] = {
+ P_UART0_TX, P_UART0_RX,
+ 0
+};
+
+static const unsigned short uart0_ctsrts_mux[] = {
+ P_UART0_RTS, P_UART0_CTS,
+ 0
+};
+
+static const unsigned short uart1_mux[] = {
+ P_UART1_TX, P_UART1_RX,
+ 0
+};
+
+static const unsigned short uart1_ctsrts_mux[] = {
+ P_UART1_RTS, P_UART1_CTS,
+ 0
+};
+
+static const unsigned short rsi0_mux[] = {
+ P_RSI_DATA0, P_RSI_DATA1, P_RSI_DATA2, P_RSI_DATA3,
+ P_RSI_CMD, P_RSI_CLK, 0
+};
+
+static const unsigned short eth0_mux[] = P_RMII0;
+static const unsigned short eth1_mux[] = P_RMII1;
+
+static const unsigned short spi0_mux[] = {
+ P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0
+};
+
+static const unsigned short spi1_mux[] = {
+ P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0
+};
+
+static const unsigned short twi0_mux[] = {
+ P_TWI0_SCL, P_TWI0_SDA, 0
+};
+
+static const unsigned short twi1_mux[] = {
+ P_TWI1_SCL, P_TWI1_SDA, 0
+};
+
+static const unsigned short rotary_mux[] = {
+ P_CNT_CUD, P_CNT_CDG, P_CNT_CZM, 0
+};
+
+static const unsigned short sport0_mux[] = {
+ P_SPORT0_ACLK, P_SPORT0_AFS, P_SPORT0_AD0, P_SPORT0_BCLK,
+ P_SPORT0_BFS, P_SPORT0_BD0, 0,
+};
+
+static const unsigned short sport1_mux[] = {
+ P_SPORT1_ACLK, P_SPORT1_AFS, P_SPORT1_AD0, P_SPORT1_BCLK,
+ P_SPORT1_BFS, P_SPORT1_BD0, 0,
+};
+
+static const unsigned short sport2_mux[] = {
+ P_SPORT2_ACLK, P_SPORT2_AFS, P_SPORT2_AD0, P_SPORT2_BCLK,
+ P_SPORT2_BFS, P_SPORT2_BD0, 0,
+};
+
+static const unsigned short can0_mux[] = {
+ P_CAN0_RX, P_CAN0_TX, 0
+};
+
+static const unsigned short smc0_mux[] = {
+ P_A3, P_A4, P_A5, P_A6, P_A7, P_A8, P_A9, P_A10, P_A11, P_A12,
+ P_A13, P_A14, P_A15, P_A16, P_A17, P_A18, P_A19, P_A20, P_A21,
+ P_A22, P_A23, P_A24, P_A25, P_NORCK, 0,
+};
+
+static const unsigned short ppi0_8b_mux[] = {
+ P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+ P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+ P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+ 0,
+};
+
+static const unsigned short ppi0_16b_mux[] = {
+ P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+ P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+ P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+ P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15,
+ P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+ 0,
+};
+
+static const unsigned short ppi0_24b_mux[] = {
+ P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+ P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+ P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+ P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15,
+ P_PPI0_D16, P_PPI0_D17, P_PPI0_D18, P_PPI0_D19,
+ P_PPI0_D20, P_PPI0_D21, P_PPI0_D22, P_PPI0_D23,
+ P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+ 0,
+};
+
+static const unsigned short ppi1_8b_mux[] = {
+ P_PPI1_D0, P_PPI1_D1, P_PPI1_D2, P_PPI1_D3,
+ P_PPI1_D4, P_PPI1_D5, P_PPI1_D6, P_PPI1_D7,
+ P_PPI1_CLK, P_PPI1_FS1, P_PPI1_FS2,
+ 0,
+};
+
+static const unsigned short ppi1_16b_mux[] = {
+ P_PPI1_D0, P_PPI1_D1, P_PPI1_D2, P_PPI1_D3,
+ P_PPI1_D4, P_PPI1_D5, P_PPI1_D6, P_PPI1_D7,
+ P_PPI1_D8, P_PPI1_D9, P_PPI1_D10, P_PPI1_D11,
+ P_PPI1_D12, P_PPI1_D13, P_PPI1_D14, P_PPI1_D15,
+ P_PPI1_CLK, P_PPI1_FS1, P_PPI1_FS2,
+ 0,
+};
+
+static const unsigned short ppi2_8b_mux[] = {
+ P_PPI2_D0, P_PPI2_D1, P_PPI2_D2, P_PPI2_D3,
+ P_PPI2_D4, P_PPI2_D5, P_PPI2_D6, P_PPI2_D7,
+ P_PPI2_CLK, P_PPI2_FS1, P_PPI2_FS2,
+ 0,
+};
+
+static const unsigned short ppi2_16b_mux[] = {
+ P_PPI2_D0, P_PPI2_D1, P_PPI2_D2, P_PPI2_D3,
+ P_PPI2_D4, P_PPI2_D5, P_PPI2_D6, P_PPI2_D7,
+ P_PPI2_D8, P_PPI2_D9, P_PPI2_D10, P_PPI2_D11,
+ P_PPI2_D12, P_PPI2_D13, P_PPI2_D14, P_PPI2_D15,
+ P_PPI2_CLK, P_PPI2_FS1, P_PPI2_FS2,
+ 0,
+};
+
+static const unsigned short lp0_mux[] = {
+ P_LP0_CLK, P_LP0_ACK, P_LP0_D0, P_LP0_D1, P_LP0_D2,
+ P_LP0_D3, P_LP0_D4, P_LP0_D5, P_LP0_D6, P_LP0_D7,
+ 0
+};
+
+static const unsigned short lp1_mux[] = {
+ P_LP1_CLK, P_LP1_ACK, P_LP1_D0, P_LP1_D1, P_LP1_D2,
+ P_LP1_D3, P_LP1_D4, P_LP1_D5, P_LP1_D6, P_LP1_D7,
+ 0
+};
+
+static const unsigned short lp2_mux[] = {
+ P_LP2_CLK, P_LP2_ACK, P_LP2_D0, P_LP2_D1, P_LP2_D2,
+ P_LP2_D3, P_LP2_D4, P_LP2_D5, P_LP2_D6, P_LP2_D7,
+ 0
+};
+
+static const unsigned short lp3_mux[] = {
+ P_LP3_CLK, P_LP3_ACK, P_LP3_D0, P_LP3_D1, P_LP3_D2,
+ P_LP3_D3, P_LP3_D4, P_LP3_D5, P_LP3_D6, P_LP3_D7,
+ 0
+};
+
+static const char * const uart0grp[] = { "uart0grp" };
+static const char * const uart0ctsrtsgrp[] = { "uart0ctsrtsgrp" };
+static const char * const uart1grp[] = { "uart1grp" };
+static const char * const uart1ctsrtsgrp[] = { "uart1ctsrtsgrp" };
+static const char * const rsi0grp[] = { "rsi0grp" };
+static const char * const eth0grp[] = { "eth0grp" };
+static const char * const eth1grp[] = { "eth1grp" };
+static const char * const spi0grp[] = { "spi0grp" };
+static const char * const spi1grp[] = { "spi1grp" };
+static const char * const twi0grp[] = { "twi0grp" };
+static const char * const twi1grp[] = { "twi1grp" };
+static const char * const rotarygrp[] = { "rotarygrp" };
+static const char * const can0grp[] = { "can0grp" };
+static const char * const smc0grp[] = { "smc0grp" };
+static const char * const sport0grp[] = { "sport0grp" };
+static const char * const sport1grp[] = { "sport1grp" };
+static const char * const sport2grp[] = { "sport2grp" };
+static const char * const ppi0_8bgrp[] = { "ppi0_8bgrp" };
+static const char * const ppi0_16bgrp[] = { "ppi0_16bgrp" };
+static const char * const ppi0_24bgrp[] = { "ppi0_24bgrp" };
+static const char * const ppi1_8bgrp[] = { "ppi1_8bgrp" };
+static const char * const ppi1_16bgrp[] = { "ppi1_16bgrp" };
+static const char * const ppi2_8bgrp[] = { "ppi2_8bgrp" };
+static const char * const ppi2_16bgrp[] = { "ppi2_16bgrp" };
+static const char * const lp0grp[] = { "lp0grp" };
+static const char * const lp1grp[] = { "lp1grp" };
+static const char * const lp2grp[] = { "lp2grp" };
+static const char * const lp3grp[] = { "lp3grp" };
+
+static const struct adi_pmx_func adi_pmx_functions[] = {
+ ADI_PMX_FUNCTION("uart0", uart0grp, uart0_mux),
+ ADI_PMX_FUNCTION("uart0_ctsrts", uart0ctsrtsgrp, uart0_ctsrts_mux),
+ ADI_PMX_FUNCTION("uart1", uart1grp, uart1_mux),
+ ADI_PMX_FUNCTION("uart1_ctsrts", uart1ctsrtsgrp, uart1_ctsrts_mux),
+ ADI_PMX_FUNCTION("rsi0", rsi0grp, rsi0_mux),
+ ADI_PMX_FUNCTION("eth0", eth0grp, eth0_mux),
+ ADI_PMX_FUNCTION("eth1", eth1grp, eth1_mux),
+ ADI_PMX_FUNCTION("spi0", spi0grp, spi0_mux),
+ ADI_PMX_FUNCTION("spi1", spi1grp, spi1_mux),
+ ADI_PMX_FUNCTION("twi0", twi0grp, twi0_mux),
+ ADI_PMX_FUNCTION("twi1", twi1grp, twi1_mux),
+ ADI_PMX_FUNCTION("rotary", rotarygrp, rotary_mux),
+ ADI_PMX_FUNCTION("can0", can0grp, can0_mux),
+ ADI_PMX_FUNCTION("smc0", smc0grp, smc0_mux),
+ ADI_PMX_FUNCTION("sport0", sport0grp, sport0_mux),
+ ADI_PMX_FUNCTION("sport1", sport1grp, sport1_mux),
+ ADI_PMX_FUNCTION("sport2", sport2grp, sport2_mux),
+ ADI_PMX_FUNCTION("ppi0_8b", ppi0_8bgrp, ppi0_8b_mux),
+ ADI_PMX_FUNCTION("ppi0_16b", ppi0_16bgrp, ppi0_16b_mux),
+ ADI_PMX_FUNCTION("ppi0_24b", ppi0_24bgrp, ppi0_24b_mux),
+ ADI_PMX_FUNCTION("ppi1_8b", ppi1_8bgrp, ppi1_8b_mux),
+ ADI_PMX_FUNCTION("ppi1_16b", ppi1_16bgrp, ppi1_16b_mux),
+ ADI_PMX_FUNCTION("ppi2_8b", ppi2_8bgrp, ppi2_8b_mux),
+ ADI_PMX_FUNCTION("ppi2_16b", ppi2_16bgrp, ppi2_16b_mux),
+ ADI_PMX_FUNCTION("lp0", lp0grp, lp0_mux),
+ ADI_PMX_FUNCTION("lp1", lp1grp, lp1_mux),
+ ADI_PMX_FUNCTION("lp2", lp2grp, lp2_mux),
+ ADI_PMX_FUNCTION("lp3", lp3grp, lp3_mux),
+};
+
+static const struct adi_pinctrl_soc_data adi_bf60x_soc = {
+ .functions = adi_pmx_functions,
+ .nfunctions = ARRAY_SIZE(adi_pmx_functions),
+ .groups = adi_pin_groups,
+ .ngroups = ARRAY_SIZE(adi_pin_groups),
+ .pins = adi_pads,
+ .npins = ARRAY_SIZE(adi_pads),
+};
+
+void adi_pinctrl_soc_init(const struct adi_pinctrl_soc_data **soc)
+{
+ *soc = &adi_bf60x_soc;
+}
diff --git a/drivers/pinctrl/pinctrl-adi2.c b/drivers/pinctrl/pinctrl-adi2.c
new file mode 100644
index 000000000000..7a24e59b4138
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-adi2.c
@@ -0,0 +1,1183 @@
+/*
+ * Pinctrl Driver for ADI GPIO2 controller
+ *
+ * Copyright 2007-2013 Analog Devices Inc.
+ *
+ * Licensed under the GPLv2 or later
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/irq.h>
+#include <linux/platform_data/pinctrl-adi2.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/syscore_ops.h>
+#include <linux/gpio.h>
+#include <asm/portmux.h>
+#include "pinctrl-adi2.h"
+#include "core.h"
+
+/*
+According to the BF54x HRM, pint means "pin interrupt".
+http://www.analog.com/static/imported-files/processor_manuals/ADSP-BF54x_hwr_rev1.2.pdf
+
+ADSP-BF54x processor Blackfin processors have four SIC interrupt chan-
+nels dedicated to pin interrupt purposes. These channels are managed by
+four hardware blocks, called PINT0, PINT1, PINT2, and PINT3. Every PINTx
+block can sense to up to 32 pins. While PINT0 and PINT1 can sense the
+pins of port A and port B, PINT2 and PINT3 manage all the pins from port
+C to port J as shown in Figure 9-2.
+
+n BF54x HRM:
+The ten GPIO ports are subdivided into 8-bit half ports, resulting in lower and
+upper half 8-bit units. The PINTx_ASSIGN registers control the 8-bit multi-
+plexers shown in Figure 9-3. Lower half units of eight pins can be
+forwarded to either byte 0 or byte 2 of either associated PINTx block.
+Upper half units can be forwarded to either byte 1 or byte 3 of the pin
+interrupt blocks, without further restrictions.
+
+All MMR registers in the pin interrupt module are 32 bits wide. To simply the
+mapping logic, this driver only maps a 16-bit gpio port to the upper or lower
+16 bits of a PINTx block. You can find the Figure 9-3 on page 583.
+
+Each IRQ domain is binding to a GPIO bank device. 2 GPIO bank devices can map
+to one PINT device. Two in "struct gpio_pint" are used to ease the PINT
+interrupt handler.
+
+The GPIO bank mapping to the lower 16 bits of the PINT device set its IRQ
+domain pointer in domain[0]. The IRQ domain pointer of the other bank is set
+to domain[1]. PINT interrupt handler adi_gpio_handle_pint_irq() finds out
+the current domain pointer according to whether the interrupt request mask
+is in lower 16 bits (domain[0]) or upper 16bits (domain[1]).
+
+A PINT device is not part of a GPIO port device in Blackfin. Multiple GPIO
+port devices can be mapped to the same PINT device.
+
+*/
+
+static LIST_HEAD(adi_pint_list);
+static LIST_HEAD(adi_gpio_port_list);
+
+#define DRIVER_NAME "pinctrl-adi2"
+
+#define PINT_HI_OFFSET 16
+
+/**
+ * struct gpio_port_saved - GPIO port registers that should be saved between
+ * power suspend and resume operations.
+ *
+ * @fer: PORTx_FER register
+ * @data: PORTx_DATA register
+ * @dir: PORTx_DIR register
+ * @inen: PORTx_INEN register
+ * @mux: PORTx_MUX register
+ */
+struct gpio_port_saved {
+ u16 fer;
+ u16 data;
+ u16 dir;
+ u16 inen;
+ u32 mux;
+};
+
+/**
+ * struct gpio_pint - Pin interrupt controller device. Multiple ADI GPIO
+ * banks can be mapped into one Pin interrupt controller.
+ *
+ * @node: All gpio_pint instances are added to a global list.
+ * @base: PINT device register base address
+ * @irq: IRQ of the PINT device, it is the parent IRQ of all
+ * GPIO IRQs mapping to this device.
+ * @domain: [0] irq domain of the gpio port, whose hardware interrupts are
+ * mapping to the low 16-bit of the pint registers.
+ * [1] irq domain of the gpio port, whose hardware interrupts are
+ * mapping to the high 16-bit of the pint registers.
+ * @regs: address pointer to the PINT device
+ * @map_count: No more than 2 GPIO banks can be mapped to this PINT device.
+ * @lock: This lock make sure the irq_chip operations to one PINT device
+ * for different GPIO interrrupts are atomic.
+ * @pint_map_port: Set up the mapping between one PINT device and
+ * multiple GPIO banks.
+ */
+struct gpio_pint {
+ struct list_head node;
+ void __iomem *base;
+ int irq;
+ struct irq_domain *domain[2];
+ struct gpio_pint_regs *regs;
+ struct adi_pm_pint_save saved_data;
+ int map_count;
+ spinlock_t lock;
+
+ int (*pint_map_port)(struct gpio_pint *pint, bool assign,
+ u8 map, struct irq_domain *domain);
+};
+
+/**
+ * ADI pin controller
+ *
+ * @dev: a pointer back to containing device
+ * @pctl: the pinctrl device
+ * @soc: SoC data for this specific chip
+ */
+struct adi_pinctrl {
+ struct device *dev;
+ struct pinctrl_dev *pctl;
+ const struct adi_pinctrl_soc_data *soc;
+};
+
+/**
+ * struct gpio_port - GPIO bank device. Multiple ADI GPIO banks can be mapped
+ * into one pin interrupt controller.
+ *
+ * @node: All gpio_port instances are added to a list.
+ * @base: GPIO bank device register base address
+ * @irq_base: base IRQ of the GPIO bank device
+ * @width: PIN number of the GPIO bank device
+ * @regs: address pointer to the GPIO bank device
+ * @saved_data: registers that should be saved between PM operations.
+ * @dev: device structure of this GPIO bank
+ * @pint: GPIO PINT device that this GPIO bank mapped to
+ * @pint_map: GIOP bank mapping code in PINT device
+ * @pint_assign: The 32-bit PINT registers can be divided into 2 parts. A
+ * GPIO bank can be mapped into either low 16 bits[0] or high 16
+ * bits[1] of each PINT register.
+ * @lock: This lock make sure the irq_chip operations to one PINT device
+ * for different GPIO interrrupts are atomic.
+ * @chip: abstract a GPIO controller
+ * @domain: The irq domain owned by the GPIO port.
+ * @rsvmap: Reservation map array for each pin in the GPIO bank
+ */
+struct gpio_port {
+ struct list_head node;
+ void __iomem *base;
+ unsigned int irq_base;
+ unsigned int width;
+ struct gpio_port_t *regs;
+ struct gpio_port_saved saved_data;
+ struct device *dev;
+
+ struct gpio_pint *pint;
+ u8 pint_map;
+ bool pint_assign;
+
+ spinlock_t lock;
+ struct gpio_chip chip;
+ struct irq_domain *domain;
+};
+
+static inline u8 pin_to_offset(struct pinctrl_gpio_range *range, unsigned pin)
+{
+ return pin - range->pin_base;
+}
+
+static inline u32 hwirq_to_pintbit(struct gpio_port *port, int hwirq)
+{
+ return port->pint_assign ? BIT(hwirq) << PINT_HI_OFFSET : BIT(hwirq);
+}
+
+static struct gpio_pint *find_gpio_pint(unsigned id)
+{
+ struct gpio_pint *pint;
+ int i = 0;
+
+ list_for_each_entry(pint, &adi_pint_list, node) {
+ if (id == i)
+ return pint;
+ i++;
+ }
+
+ return NULL;
+}
+
+static inline void port_setup(struct gpio_port *port, unsigned offset,
+ bool use_for_gpio)
+{
+ struct gpio_port_t *regs = port->regs;
+
+ if (use_for_gpio)
+ writew(readw(&regs->port_fer) & ~BIT(offset),
+ &regs->port_fer);
+ else
+ writew(readw(&regs->port_fer) | BIT(offset), &regs->port_fer);
+}
+
+static inline void portmux_setup(struct gpio_port *port, unsigned offset,
+ unsigned short function)
+{
+ struct gpio_port_t *regs = port->regs;
+ u32 pmux;
+
+ pmux = readl(&regs->port_mux);
+
+ /* The function field of each pin has 2 consecutive bits in
+ * the mux register.
+ */
+ pmux &= ~(0x3 << (2 * offset));
+ pmux |= (function & 0x3) << (2 * offset);
+
+ writel(pmux, &regs->port_mux);
+}
+
+static inline u16 get_portmux(struct gpio_port *port, unsigned offset)
+{
+ struct gpio_port_t *regs = port->regs;
+ u32 pmux = readl(&regs->port_mux);
+
+ /* The function field of each pin has 2 consecutive bits in
+ * the mux register.
+ */
+ return pmux >> (2 * offset) & 0x3;
+}
+
+static void adi_gpio_ack_irq(struct irq_data *d)
+{
+ unsigned long flags;
+ struct gpio_port *port = irq_data_get_irq_chip_data(d);
+ struct gpio_pint_regs *regs = port->pint->regs;
+ unsigned pintbit = hwirq_to_pintbit(port, d->hwirq);
+
+ spin_lock_irqsave(&port->lock, flags);
+ spin_lock_irqsave(&port->pint->lock, flags);
+
+ if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
+ if (readl(&regs->invert_set) & pintbit)
+ writel(pintbit, &regs->invert_clear);
+ else
+ writel(pintbit, &regs->invert_set);
+ }
+
+ writel(pintbit, &regs->request);
+
+ spin_unlock_irqrestore(&port->pint->lock, flags);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void adi_gpio_mask_ack_irq(struct irq_data *d)
+{
+ unsigned long flags;
+ struct gpio_port *port = irq_data_get_irq_chip_data(d);
+ struct gpio_pint_regs *regs = port->pint->regs;
+ unsigned pintbit = hwirq_to_pintbit(port, d->hwirq);
+
+ spin_lock_irqsave(&port->lock, flags);
+ spin_lock_irqsave(&port->pint->lock, flags);
+
+ if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
+ if (readl(&regs->invert_set) & pintbit)
+ writel(pintbit, &regs->invert_clear);
+ else
+ writel(pintbit, &regs->invert_set);
+ }
+
+ writel(pintbit, &regs->request);
+ writel(pintbit, &regs->mask_clear);
+
+ spin_unlock_irqrestore(&port->pint->lock, flags);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void adi_gpio_mask_irq(struct irq_data *d)
+{
+ unsigned long flags;
+ struct gpio_port *port = irq_data_get_irq_chip_data(d);
+ struct gpio_pint_regs *regs = port->pint->regs;
+
+ spin_lock_irqsave(&port->lock, flags);
+ spin_lock_irqsave(&port->pint->lock, flags);
+
+ writel(hwirq_to_pintbit(port, d->hwirq), &regs->mask_clear);
+
+ spin_unlock_irqrestore(&port->pint->lock, flags);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void adi_gpio_unmask_irq(struct irq_data *d)
+{
+ unsigned long flags;
+ struct gpio_port *port = irq_data_get_irq_chip_data(d);
+ struct gpio_pint_regs *regs = port->pint->regs;
+
+ spin_lock_irqsave(&port->lock, flags);
+ spin_lock_irqsave(&port->pint->lock, flags);
+
+ writel(hwirq_to_pintbit(port, d->hwirq), &regs->mask_set);
+
+ spin_unlock_irqrestore(&port->pint->lock, flags);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static unsigned int adi_gpio_irq_startup(struct irq_data *d)
+{
+ unsigned long flags;
+ struct gpio_port *port = irq_data_get_irq_chip_data(d);
+ struct gpio_pint_regs *regs = port->pint->regs;
+
+ if (!port) {
+ dev_err(port->dev, "GPIO IRQ %d :Not exist\n", d->irq);
+ return -ENODEV;
+ }
+
+ spin_lock_irqsave(&port->lock, flags);
+ spin_lock_irqsave(&port->pint->lock, flags);
+
+ port_setup(port, d->hwirq, true);
+ writew(BIT(d->hwirq), &port->regs->dir_clear);
+ writew(readw(&port->regs->inen) | BIT(d->hwirq), &port->regs->inen);
+
+ writel(hwirq_to_pintbit(port, d->hwirq), &regs->mask_set);
+
+ spin_unlock_irqrestore(&port->pint->lock, flags);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ return 0;
+}
+
+static void adi_gpio_irq_shutdown(struct irq_data *d)
+{
+ unsigned long flags;
+ struct gpio_port *port = irq_data_get_irq_chip_data(d);
+ struct gpio_pint_regs *regs = port->pint->regs;
+
+ spin_lock_irqsave(&port->lock, flags);
+ spin_lock_irqsave(&port->pint->lock, flags);
+
+ writel(hwirq_to_pintbit(port, d->hwirq), &regs->mask_clear);
+
+ spin_unlock_irqrestore(&port->pint->lock, flags);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static int adi_gpio_irq_type(struct irq_data *d, unsigned int type)
+{
+ unsigned long flags;
+ struct gpio_port *port = irq_data_get_irq_chip_data(d);
+ struct gpio_pint_regs *pint_regs = port->pint->regs;
+ unsigned pintmask;
+ unsigned int irq = d->irq;
+ int ret = 0;
+ char buf[16];
+
+ if (!port) {
+ dev_err(port->dev, "GPIO IRQ %d :Not exist\n", irq);
+ return -ENODEV;
+ }
+
+ pintmask = hwirq_to_pintbit(port, d->hwirq);
+
+ spin_lock_irqsave(&port->lock, flags);
+ spin_lock_irqsave(&port->pint->lock, flags);
+
+ /* In case of interrupt autodetect, set irq type to edge sensitive. */
+ if (type == IRQ_TYPE_PROBE)
+ type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+
+ if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
+ IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+ snprintf(buf, 16, "gpio-irq%d", irq);
+ port_setup(port, d->hwirq, true);
+ } else
+ goto out;
+
+ /* The GPIO interrupt is triggered only when its input value
+ * transfer from 0 to 1. So, invert the input value if the
+ * irq type is low or falling
+ */
+ if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
+ writel(pintmask, &pint_regs->invert_set);
+ else
+ writel(pintmask, &pint_regs->invert_clear);
+
+ /* In edge sensitive case, if the input value of the requested irq
+ * is already 1, invert it.
+ */
+ if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
+ if (gpio_get_value(port->chip.base + d->hwirq))
+ writel(pintmask, &pint_regs->invert_set);
+ else
+ writel(pintmask, &pint_regs->invert_clear);
+ }
+
+ if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
+ writel(pintmask, &pint_regs->edge_set);
+ __irq_set_handler_locked(irq, handle_edge_irq);
+ } else {
+ writel(pintmask, &pint_regs->edge_clear);
+ __irq_set_handler_locked(irq, handle_level_irq);
+ }
+
+out:
+ spin_unlock_irqrestore(&port->pint->lock, flags);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int adi_gpio_set_wake(struct irq_data *d, unsigned int state)
+{
+ struct gpio_port *port = irq_data_get_irq_chip_data(d);
+
+ if (!port || !port->pint || port->pint->irq != d->irq)
+ return -EINVAL;
+
+#ifndef SEC_GCTL
+ adi_internal_set_wake(port->pint->irq, state);
+#endif
+
+ return 0;
+}
+
+static int adi_pint_suspend(void)
+{
+ struct gpio_pint *pint;
+
+ list_for_each_entry(pint, &adi_pint_list, node) {
+ writel(0xffffffff, &pint->regs->mask_clear);
+ pint->saved_data.assign = readl(&pint->regs->assign);
+ pint->saved_data.edge_set = readl(&pint->regs->edge_set);
+ pint->saved_data.invert_set = readl(&pint->regs->invert_set);
+ }
+
+ return 0;
+}
+
+static void adi_pint_resume(void)
+{
+ struct gpio_pint *pint;
+
+ list_for_each_entry(pint, &adi_pint_list, node) {
+ writel(pint->saved_data.assign, &pint->regs->assign);
+ writel(pint->saved_data.edge_set, &pint->regs->edge_set);
+ writel(pint->saved_data.invert_set, &pint->regs->invert_set);
+ }
+}
+
+static int adi_gpio_suspend(void)
+{
+ struct gpio_port *port;
+
+ list_for_each_entry(port, &adi_gpio_port_list, node) {
+ port->saved_data.fer = readw(&port->regs->port_fer);
+ port->saved_data.mux = readl(&port->regs->port_mux);
+ port->saved_data.data = readw(&port->regs->data);
+ port->saved_data.inen = readw(&port->regs->inen);
+ port->saved_data.dir = readw(&port->regs->dir_set);
+ }
+
+ return adi_pint_suspend();
+}
+
+static void adi_gpio_resume(void)
+{
+ struct gpio_port *port;
+
+ adi_pint_resume();
+
+ list_for_each_entry(port, &adi_gpio_port_list, node) {
+ writel(port->saved_data.mux, &port->regs->port_mux);
+ writew(port->saved_data.fer, &port->regs->port_fer);
+ writew(port->saved_data.inen, &port->regs->inen);
+ writew(port->saved_data.data & port->saved_data.dir,
+ &port->regs->data_set);
+ writew(port->saved_data.dir, &port->regs->dir_set);
+ }
+
+}
+
+static struct syscore_ops gpio_pm_syscore_ops = {
+ .suspend = adi_gpio_suspend,
+ .resume = adi_gpio_resume,
+};
+#else /* CONFIG_PM */
+#define adi_gpio_set_wake NULL
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_IRQ_PREFLOW_FASTEOI
+static inline void preflow_handler(struct irq_desc *desc)
+{
+ if (desc->preflow_handler)
+ desc->preflow_handler(&desc->irq_data);
+}
+#else
+static inline void preflow_handler(struct irq_desc *desc) { }
+#endif
+
+static void adi_gpio_handle_pint_irq(unsigned int inta_irq,
+ struct irq_desc *desc)
+{
+ u32 request;
+ u32 level_mask, hwirq;
+ bool umask = false;
+ struct gpio_pint *pint = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct gpio_pint_regs *regs = pint->regs;
+ struct irq_domain *domain;
+
+ preflow_handler(desc);
+ chained_irq_enter(chip, desc);
+
+ request = readl(&regs->request);
+ level_mask = readl(&regs->edge_set) & request;
+
+ hwirq = 0;
+ domain = pint->domain[0];
+ while (request) {
+ /* domain pointer need to be changed only once at IRQ 16 when
+ * we go through IRQ requests from bit 0 to bit 31.
+ */
+ if (hwirq == PINT_HI_OFFSET)
+ domain = pint->domain[1];
+
+ if (request & 1) {
+ if (level_mask & BIT(hwirq)) {
+ umask = true;
+ chained_irq_exit(chip, desc);
+ }
+ generic_handle_irq(irq_find_mapping(domain,
+ hwirq % PINT_HI_OFFSET));
+ }
+
+ hwirq++;
+ request >>= 1;
+ }
+
+ if (!umask)
+ chained_irq_exit(chip, desc);
+}
+
+static struct irq_chip adi_gpio_irqchip = {
+ .name = "GPIO",
+ .irq_ack = adi_gpio_ack_irq,
+ .irq_mask = adi_gpio_mask_irq,
+ .irq_mask_ack = adi_gpio_mask_ack_irq,
+ .irq_unmask = adi_gpio_unmask_irq,
+ .irq_disable = adi_gpio_mask_irq,
+ .irq_enable = adi_gpio_unmask_irq,
+ .irq_set_type = adi_gpio_irq_type,
+ .irq_startup = adi_gpio_irq_startup,
+ .irq_shutdown = adi_gpio_irq_shutdown,
+ .irq_set_wake = adi_gpio_set_wake,
+};
+
+static int adi_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+ return pinctrl->soc->ngroups;
+}
+
+static const char *adi_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+ return pinctrl->soc->groups[selector].name;
+}
+
+static int adi_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+ const unsigned **pins,
+ unsigned *num_pins)
+{
+ struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+ *pins = pinctrl->soc->groups[selector].pins;
+ *num_pins = pinctrl->soc->groups[selector].num;
+ return 0;
+}
+
+static struct pinctrl_ops adi_pctrl_ops = {
+ .get_groups_count = adi_get_groups_count,
+ .get_group_name = adi_get_group_name,
+ .get_group_pins = adi_get_group_pins,
+};
+
+static int adi_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+ struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+ struct gpio_port *port;
+ struct pinctrl_gpio_range *range;
+ unsigned long flags;
+ unsigned short *mux, pin;
+
+ mux = (unsigned short *)pinctrl->soc->functions[selector].mux;
+
+ while (*mux) {
+ pin = P_IDENT(*mux);
+
+ range = pinctrl_find_gpio_range_from_pin(pctldev, pin);
+ if (range == NULL) /* should not happen */
+ return -ENODEV;
+
+ port = container_of(range->gc, struct gpio_port, chip);
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ portmux_setup(port, pin_to_offset(range, pin),
+ P_FUNCT2MUX(*mux));
+ port_setup(port, pin_to_offset(range, pin), false);
+ mux++;
+
+ spin_unlock_irqrestore(&port->lock, flags);
+ }
+
+ return 0;
+}
+
+static void adi_pinmux_disable(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+ struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+ struct gpio_port *port;
+ struct pinctrl_gpio_range *range;
+ unsigned long flags;
+ unsigned short *mux, pin;
+
+ mux = (unsigned short *)pinctrl->soc->functions[selector].mux;
+
+ while (*mux) {
+ pin = P_IDENT(*mux);
+
+ range = pinctrl_find_gpio_range_from_pin(pctldev, pin);
+ if (range == NULL) /* should not happen */
+ return;
+
+ port = container_of(range->gc, struct gpio_port, chip);
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ port_setup(port, pin_to_offset(range, pin), true);
+ mux++;
+
+ spin_unlock_irqrestore(&port->lock, flags);
+ }
+}
+
+static int adi_pinmux_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+ struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+ return pinctrl->soc->nfunctions;
+}
+
+static const char *adi_pinmux_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+ return pinctrl->soc->functions[selector].name;
+}
+
+static int adi_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+ *groups = pinctrl->soc->functions[selector].groups;
+ *num_groups = pinctrl->soc->functions[selector].num_groups;
+ return 0;
+}
+
+static int adi_pinmux_request_gpio(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range, unsigned pin)
+{
+ struct gpio_port *port;
+ unsigned long flags;
+ u8 offset;
+
+ port = container_of(range->gc, struct gpio_port, chip);
+ offset = pin_to_offset(range, pin);
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ port_setup(port, offset, true);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ return 0;
+}
+
+static struct pinmux_ops adi_pinmux_ops = {
+ .enable = adi_pinmux_enable,
+ .disable = adi_pinmux_disable,
+ .get_functions_count = adi_pinmux_get_funcs_count,
+ .get_function_name = adi_pinmux_get_func_name,
+ .get_function_groups = adi_pinmux_get_groups,
+ .gpio_request_enable = adi_pinmux_request_gpio,
+};
+
+
+static struct pinctrl_desc adi_pinmux_desc = {
+ .name = DRIVER_NAME,
+ .pctlops = &adi_pctrl_ops,
+ .pmxops = &adi_pinmux_ops,
+ .owner = THIS_MODULE,
+};
+
+static int adi_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void adi_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ pinctrl_free_gpio(chip->base + offset);
+}
+
+static int adi_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct gpio_port *port;
+ unsigned long flags;
+
+ port = container_of(chip, struct gpio_port, chip);
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ writew(BIT(offset), &port->regs->dir_clear);
+ writew(readw(&port->regs->inen) | BIT(offset), &port->regs->inen);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ return 0;
+}
+
+static void adi_gpio_set_value(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ struct gpio_port *port = container_of(chip, struct gpio_port, chip);
+ struct gpio_port_t *regs = port->regs;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ if (value)
+ writew(1 << offset, &regs->data_set);
+ else
+ writew(1 << offset, &regs->data_clear);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static int adi_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ struct gpio_port *port = container_of(chip, struct gpio_port, chip);
+ struct gpio_port_t *regs = port->regs;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ writew(readw(&regs->inen) & ~(1 << offset), &regs->inen);
+ adi_gpio_set_value(chip, offset, value);
+ writew(1 << offset, &regs->dir_set);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ return 0;
+}
+
+static int adi_gpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+ struct gpio_port *port = container_of(chip, struct gpio_port, chip);
+ struct gpio_port_t *regs = port->regs;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ ret = !!(readw(&regs->data) & BIT(offset));
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ return ret;
+}
+
+static int adi_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ struct gpio_port *port = container_of(chip, struct gpio_port, chip);
+
+ if (port->irq_base >= 0)
+ return irq_find_mapping(port->domain, offset);
+ else
+ return irq_create_mapping(port->domain, offset);
+}
+
+static int adi_pint_map_port(struct gpio_pint *pint, bool assign, u8 map,
+ struct irq_domain *domain)
+{
+ struct gpio_pint_regs *regs = pint->regs;
+ u32 map_mask;
+
+ if (pint->map_count > 1)
+ return -EINVAL;
+
+ pint->map_count++;
+
+ /* The map_mask of each gpio port is a 16-bit duplicate
+ * of the 8-bit map. It can be set to either high 16 bits or low
+ * 16 bits of the pint assignment register.
+ */
+ map_mask = (map << 8) | map;
+ if (assign) {
+ map_mask <<= PINT_HI_OFFSET;
+ writel((readl(&regs->assign) & 0xFFFF) | map_mask,
+ &regs->assign);
+ } else
+ writel((readl(&regs->assign) & 0xFFFF0000) | map_mask,
+ &regs->assign);
+
+ pint->domain[assign] = domain;
+
+ return 0;
+}
+
+static int adi_gpio_pint_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct gpio_pint *pint;
+
+ pint = devm_kzalloc(dev, sizeof(struct gpio_pint), GFP_KERNEL);
+ if (!pint) {
+ dev_err(dev, "Memory alloc failed\n");
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "Invalid mem resource\n");
+ return -ENODEV;
+ }
+
+ if (!devm_request_mem_region(dev, res->start, resource_size(res),
+ pdev->name)) {
+ dev_err(dev, "Region already claimed\n");
+ return -EBUSY;
+ }
+
+ pint->base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!pint->base) {
+ dev_err(dev, "Could not ioremap\n");
+ return -ENOMEM;
+ }
+
+ pint->regs = (struct gpio_pint_regs *)pint->base;
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(dev, "Invalid IRQ resource\n");
+ return -ENODEV;
+ }
+
+ spin_lock_init(&pint->lock);
+
+ pint->irq = res->start;
+ pint->pint_map_port = adi_pint_map_port;
+ platform_set_drvdata(pdev, pint);
+
+ irq_set_chained_handler(pint->irq, adi_gpio_handle_pint_irq);
+ irq_set_handler_data(pint->irq, pint);
+
+ list_add_tail(&pint->node, &adi_pint_list);
+
+ return 0;
+}
+
+static int adi_gpio_pint_remove(struct platform_device *pdev)
+{
+ struct gpio_pint *pint = platform_get_drvdata(pdev);
+
+ list_del(&pint->node);
+ irq_set_handler(pint->irq, handle_simple_irq);
+
+ return 0;
+}
+
+static int adi_gpio_irq_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ struct gpio_port *port = d->host_data;
+
+ if (!port)
+ return -EINVAL;
+
+ irq_set_chip_data(irq, port);
+ irq_set_chip_and_handler(irq, &adi_gpio_irqchip,
+ handle_level_irq);
+
+ return 0;
+}
+
+const struct irq_domain_ops adi_gpio_irq_domain_ops = {
+ .map = adi_gpio_irq_map,
+ .xlate = irq_domain_xlate_onecell,
+};
+
+static int adi_gpio_init_int(struct gpio_port *port)
+{
+ struct device_node *node = port->dev->of_node;
+ struct gpio_pint *pint = port->pint;
+ int ret;
+
+ port->domain = irq_domain_add_linear(node, port->width,
+ &adi_gpio_irq_domain_ops, port);
+ if (!port->domain) {
+ dev_err(port->dev, "Failed to create irqdomain\n");
+ return -ENOSYS;
+ }
+
+ /* According to BF54x and BF60x HRM, pin interrupt devices are not
+ * part of the GPIO port device. in GPIO interrupt mode, the GPIO
+ * pins of multiple port devices can be routed into one pin interrupt
+ * device. The mapping can be configured by setting pint assignment
+ * register with the mapping value of different GPIO port. This is
+ * done via function pint_map_port().
+ */
+ ret = pint->pint_map_port(port->pint, port->pint_assign,
+ port->pint_map, port->domain);
+ if (ret)
+ return ret;
+
+ if (port->irq_base >= 0) {
+ ret = irq_create_strict_mappings(port->domain, port->irq_base,
+ 0, port->width);
+ if (ret) {
+ dev_err(port->dev, "Couldn't associate to domain\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+#define DEVNAME_SIZE 16
+
+static int adi_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct adi_pinctrl_gpio_platform_data *pdata;
+ struct resource *res;
+ struct gpio_port *port;
+ char pinctrl_devname[DEVNAME_SIZE];
+ static int gpio;
+ int ret = 0, ret1;
+
+ pdata = dev->platform_data;
+ if (!pdata)
+ return -EINVAL;
+
+ port = devm_kzalloc(dev, sizeof(struct gpio_port), GFP_KERNEL);
+ if (!port) {
+ dev_err(dev, "Memory alloc failed\n");
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "Invalid mem resource\n");
+ return -ENODEV;
+ }
+
+ if (!devm_request_mem_region(dev, res->start, resource_size(res),
+ pdev->name)) {
+ dev_err(dev, "Region already claimed\n");
+ return -EBUSY;
+ }
+
+ port->base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!port->base) {
+ dev_err(dev, "Could not ioremap\n");
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res)
+ port->irq_base = -1;
+ else
+ port->irq_base = res->start;
+
+ port->width = pdata->port_width;
+ port->dev = dev;
+ port->regs = (struct gpio_port_t *)port->base;
+ port->pint_assign = pdata->pint_assign;
+ port->pint_map = pdata->pint_map;
+
+ port->pint = find_gpio_pint(pdata->pint_id);
+ if (port->pint) {
+ ret = adi_gpio_init_int(port);
+ if (ret)
+ return ret;
+ }
+
+ spin_lock_init(&port->lock);
+
+ platform_set_drvdata(pdev, port);
+
+ port->chip.label = "adi-gpio";
+ port->chip.direction_input = adi_gpio_direction_input;
+ port->chip.get = adi_gpio_get_value;
+ port->chip.direction_output = adi_gpio_direction_output;
+ port->chip.set = adi_gpio_set_value;
+ port->chip.request = adi_gpio_request;
+ port->chip.free = adi_gpio_free;
+ port->chip.to_irq = adi_gpio_to_irq;
+ if (pdata->port_gpio_base > 0)
+ port->chip.base = pdata->port_gpio_base;
+ else
+ port->chip.base = gpio;
+ port->chip.ngpio = port->width;
+ gpio = port->chip.base + port->width;
+
+ ret = gpiochip_add(&port->chip);
+ if (ret) {
+ dev_err(&pdev->dev, "Fail to add GPIO chip.\n");
+ goto out_remove_domain;
+ }
+
+ /* Add gpio pin range */
+ snprintf(pinctrl_devname, DEVNAME_SIZE, "pinctrl-adi2.%d",
+ pdata->pinctrl_id);
+ pinctrl_devname[DEVNAME_SIZE - 1] = 0;
+ ret = gpiochip_add_pin_range(&port->chip, pinctrl_devname,
+ 0, pdata->port_pin_base, port->width);
+ if (ret) {
+ dev_err(&pdev->dev, "Fail to add pin range to %s.\n",
+ pinctrl_devname);
+ goto out_remove_gpiochip;
+ }
+
+ list_add_tail(&port->node, &adi_gpio_port_list);
+
+ return 0;
+
+out_remove_gpiochip:
+ ret1 = gpiochip_remove(&port->chip);
+out_remove_domain:
+ if (port->pint)
+ irq_domain_remove(port->domain);
+
+ return ret;
+}
+
+static int adi_gpio_remove(struct platform_device *pdev)
+{
+ struct gpio_port *port = platform_get_drvdata(pdev);
+ int ret;
+ u8 offset;
+
+ list_del(&port->node);
+ gpiochip_remove_pin_ranges(&port->chip);
+ ret = gpiochip_remove(&port->chip);
+ if (port->pint) {
+ for (offset = 0; offset < port->width; offset++)
+ irq_dispose_mapping(irq_find_mapping(port->domain,
+ offset));
+ irq_domain_remove(port->domain);
+ }
+
+ return ret;
+}
+
+static int adi_pinctrl_probe(struct platform_device *pdev)
+{
+ struct adi_pinctrl *pinctrl;
+
+ pinctrl = devm_kzalloc(&pdev->dev, sizeof(*pinctrl), GFP_KERNEL);
+ if (!pinctrl)
+ return -ENOMEM;
+
+ pinctrl->dev = &pdev->dev;
+
+ adi_pinctrl_soc_init(&pinctrl->soc);
+
+ adi_pinmux_desc.pins = pinctrl->soc->pins;
+ adi_pinmux_desc.npins = pinctrl->soc->npins;
+
+ /* Now register the pin controller and all pins it handles */
+ pinctrl->pctl = pinctrl_register(&adi_pinmux_desc, &pdev->dev, pinctrl);
+ if (!pinctrl->pctl) {
+ dev_err(&pdev->dev, "could not register pinctrl ADI2 driver\n");
+ return -EINVAL;
+ }
+
+ platform_set_drvdata(pdev, pinctrl);
+
+ return 0;
+}
+
+static int adi_pinctrl_remove(struct platform_device *pdev)
+{
+ struct adi_pinctrl *pinctrl = platform_get_drvdata(pdev);
+
+ pinctrl_unregister(pinctrl->pctl);
+
+ return 0;
+}
+
+static struct platform_driver adi_pinctrl_driver = {
+ .probe = adi_pinctrl_probe,
+ .remove = adi_pinctrl_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ },
+};
+
+static struct platform_driver adi_gpio_pint_driver = {
+ .probe = adi_gpio_pint_probe,
+ .remove = adi_gpio_pint_remove,
+ .driver = {
+ .name = "adi-gpio-pint",
+ },
+};
+
+static struct platform_driver adi_gpio_driver = {
+ .probe = adi_gpio_probe,
+ .remove = adi_gpio_remove,
+ .driver = {
+ .name = "adi-gpio",
+ },
+};
+
+static int __init adi_pinctrl_setup(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&adi_pinctrl_driver);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&adi_gpio_pint_driver);
+ if (ret)
+ goto pint_error;
+
+ ret = platform_driver_register(&adi_gpio_driver);
+ if (ret)
+ goto gpio_error;
+
+#ifdef CONFIG_PM
+ register_syscore_ops(&gpio_pm_syscore_ops);
+#endif
+ return ret;
+gpio_error:
+ platform_driver_unregister(&adi_gpio_pint_driver);
+pint_error:
+ platform_driver_unregister(&adi_pinctrl_driver);
+
+ return ret;
+}
+arch_initcall(adi_pinctrl_setup);
+
+MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
+MODULE_DESCRIPTION("ADI gpio2 pin control driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/pinctrl-adi2.h b/drivers/pinctrl/pinctrl-adi2.h
new file mode 100644
index 000000000000..1f06f8df1fa3
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-adi2.h
@@ -0,0 +1,75 @@
+/*
+ * Pinctrl Driver for ADI GPIO2 controller
+ *
+ * Copyright 2007-2013 Analog Devices Inc.
+ *
+ * Licensed under the GPLv2 or later
+ */
+
+#ifndef PINCTRL_PINCTRL_ADI2_H
+#define PINCTRL_PINCTRL_ADI2_H
+
+#include <linux/pinctrl/pinctrl.h>
+
+ /**
+ * struct adi_pin_group - describes a pin group
+ * @name: the name of this pin group
+ * @pins: an array of pins
+ * @num: the number of pins in this array
+ */
+struct adi_pin_group {
+ const char *name;
+ const unsigned *pins;
+ const unsigned num;
+};
+
+#define ADI_PIN_GROUP(n, p) \
+ { \
+ .name = n, \
+ .pins = p, \
+ .num = ARRAY_SIZE(p), \
+ }
+
+ /**
+ * struct adi_pmx_func - describes function mux setting of pin groups
+ * @name: the name of this function mux setting
+ * @groups: an array of pin groups
+ * @num_groups: the number of pin groups in this array
+ * @mux: the function mux setting array, end by zero
+ */
+struct adi_pmx_func {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+ const unsigned short *mux;
+};
+
+#define ADI_PMX_FUNCTION(n, g, m) \
+ { \
+ .name = n, \
+ .groups = g, \
+ .num_groups = ARRAY_SIZE(g), \
+ .mux = m, \
+ }
+
+/**
+ * struct adi_pinctrl_soc_data - ADI pin controller per-SoC configuration
+ * @functions: The functions supported on this SoC.
+ * @nfunction: The number of entries in @functions.
+ * @groups: An array describing all pin groups the pin SoC supports.
+ * @ngroups: The number of entries in @groups.
+ * @pins: An array describing all pins the pin controller affects.
+ * @npins: The number of entries in @pins.
+ */
+struct adi_pinctrl_soc_data {
+ const struct adi_pmx_func *functions;
+ int nfunctions;
+ const struct adi_pin_group *groups;
+ int ngroups;
+ const struct pinctrl_pin_desc *pins;
+ int npins;
+};
+
+void adi_pinctrl_soc_init(const struct adi_pinctrl_soc_data **soc);
+
+#endif /* PINCTRL_PINCTRL_ADI2_H */
diff --git a/drivers/pinctrl/pinctrl-tegra114.c b/drivers/pinctrl/pinctrl-tegra114.c
index 622c4854977e..93c9e3899d5e 100644
--- a/drivers/pinctrl/pinctrl-tegra114.c
+++ b/drivers/pinctrl/pinctrl-tegra114.c
@@ -3,7 +3,7 @@
*
* Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
*
- * Arthur: Pritesh Raithatha <praithatha@nvidia.com>
+ * Author: Pritesh Raithatha <praithatha@nvidia.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -2763,7 +2763,6 @@ static struct platform_driver tegra114_pinctrl_driver = {
};
module_platform_driver(tegra114_pinctrl_driver);
-MODULE_ALIAS("platform:tegra114-pinctrl");
MODULE_AUTHOR("Pritesh Raithatha <praithatha@nvidia.com>");
-MODULE_DESCRIPTION("NVIDIA Tegra114 pincontrol driver");
+MODULE_DESCRIPTION("NVIDIA Tegra114 pinctrl driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index a6afd4108beb..aefcc32e5634 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -190,16 +190,10 @@ struct eeepc_laptop {
*/
static int write_acpi_int(acpi_handle handle, const char *method, int val)
{
- struct acpi_object_list params;
- union acpi_object in_obj;
acpi_status status;
- params.count = 1;
- params.pointer = &in_obj;
- in_obj.type = ACPI_TYPE_INTEGER;
- in_obj.integer.value = val;
+ status = acpi_execute_simple_method(handle, (char *)method, val);
- status = acpi_evaluate_object(handle, (char *)method, &params, NULL);
return (status == AE_OK ? 0 : -1);
}
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index 52b8a97efde1..9d30d69aa78f 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -219,8 +219,7 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2)
{ .type = ACPI_TYPE_INTEGER }
};
struct acpi_object_list arg_list = { 4, &params[0] };
- struct acpi_buffer output;
- union acpi_object out_obj;
+ unsigned long long value;
acpi_handle handle = NULL;
status = acpi_get_handle(fujitsu_hotkey->acpi_handle, "FUNC", &handle);
@@ -235,10 +234,7 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2)
params[2].integer.value = arg1;
params[3].integer.value = arg2;
- output.length = sizeof(out_obj);
- output.pointer = &out_obj;
-
- status = acpi_evaluate_object(handle, NULL, &arg_list, &output);
+ status = acpi_evaluate_integer(handle, NULL, &arg_list, &value);
if (ACPI_FAILURE(status)) {
vdbg_printk(FUJLAPTOP_DBG_WARN,
"FUNC 0x%x (args 0x%x, 0x%x, 0x%x) call failed\n",
@@ -246,18 +242,10 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2)
return -ENODEV;
}
- if (out_obj.type != ACPI_TYPE_INTEGER) {
- vdbg_printk(FUJLAPTOP_DBG_WARN,
- "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) did not "
- "return an integer\n",
- cmd, arg0, arg1, arg2);
- return -ENODEV;
- }
-
vdbg_printk(FUJLAPTOP_DBG_TRACE,
"FUNC 0x%x (args 0x%x, 0x%x, 0x%x) returned 0x%x\n",
- cmd, arg0, arg1, arg2, (int)out_obj.integer.value);
- return out_obj.integer.value;
+ cmd, arg0, arg1, arg2, (int)value);
+ return value;
}
#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
@@ -317,8 +305,6 @@ static enum led_brightness kblamps_get(struct led_classdev *cdev)
static int set_lcd_level(int level)
{
acpi_status status = AE_OK;
- union acpi_object arg0 = { ACPI_TYPE_INTEGER };
- struct acpi_object_list arg_list = { 1, &arg0 };
acpi_handle handle = NULL;
vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBLL [%d]\n",
@@ -333,9 +319,8 @@ static int set_lcd_level(int level)
return -ENODEV;
}
- arg0.integer.value = level;
- status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
+ status = acpi_execute_simple_method(handle, NULL, level);
if (ACPI_FAILURE(status))
return -ENODEV;
@@ -345,8 +330,6 @@ static int set_lcd_level(int level)
static int set_lcd_level_alt(int level)
{
acpi_status status = AE_OK;
- union acpi_object arg0 = { ACPI_TYPE_INTEGER };
- struct acpi_object_list arg_list = { 1, &arg0 };
acpi_handle handle = NULL;
vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBL2 [%d]\n",
@@ -361,9 +344,7 @@ static int set_lcd_level_alt(int level)
return -ENODEV;
}
- arg0.integer.value = level;
-
- status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
+ status = acpi_execute_simple_method(handle, NULL, level);
if (ACPI_FAILURE(status))
return -ENODEV;
@@ -586,11 +567,10 @@ static struct platform_driver fujitsupf_driver = {
static void dmi_check_cb_common(const struct dmi_system_id *id)
{
- acpi_handle handle;
pr_info("Identified laptop model '%s'\n", id->ident);
if (use_alt_lcd_levels == -1) {
- if (ACPI_SUCCESS(acpi_get_handle(NULL,
- "\\_SB.PCI0.LPCB.FJEX.SBL2", &handle)))
+ if (acpi_has_method(NULL,
+ "\\_SB.PCI0.LPCB.FJEX.SBL2"))
use_alt_lcd_levels = 1;
else
use_alt_lcd_levels = 0;
@@ -653,7 +633,6 @@ static struct dmi_system_id fujitsu_dmi_table[] = {
static int acpi_fujitsu_add(struct acpi_device *device)
{
- acpi_handle handle;
int result = 0;
int state = 0;
struct input_dev *input;
@@ -702,8 +681,7 @@ static int acpi_fujitsu_add(struct acpi_device *device)
fujitsu->dev = device;
- if (ACPI_SUCCESS
- (acpi_get_handle(device->handle, METHOD_NAME__INI, &handle))) {
+ if (acpi_has_method(device->handle, METHOD_NAME__INI)) {
vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n");
if (ACPI_FAILURE
(acpi_evaluate_object
@@ -803,7 +781,6 @@ static void acpi_fujitsu_notify(struct acpi_device *device, u32 event)
static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
{
- acpi_handle handle;
int result = 0;
int state = 0;
struct input_dev *input;
@@ -866,8 +843,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
fujitsu_hotkey->dev = device;
- if (ACPI_SUCCESS
- (acpi_get_handle(device->handle, METHOD_NAME__INI, &handle))) {
+ if (acpi_has_method(device->handle, METHOD_NAME__INI)) {
vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n");
if (ACPI_FAILURE
(acpi_evaluate_object
diff --git a/drivers/platform/x86/intel-rst.c b/drivers/platform/x86/intel-rst.c
index 41b740cb28bc..a2083a9e5662 100644
--- a/drivers/platform/x86/intel-rst.c
+++ b/drivers/platform/x86/intel-rst.c
@@ -29,24 +29,16 @@ static ssize_t irst_show_wakeup_events(struct device *dev,
char *buf)
{
struct acpi_device *acpi;
- struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
- union acpi_object *result;
+ unsigned long long value;
acpi_status status;
acpi = to_acpi_device(dev);
- status = acpi_evaluate_object(acpi->handle, "GFFS", NULL, &output);
+ status = acpi_evaluate_integer(acpi->handle, "GFFS", NULL, &value);
if (!ACPI_SUCCESS(status))
return -EINVAL;
- result = output.pointer;
-
- if (result->type != ACPI_TYPE_INTEGER) {
- kfree(result);
- return -EINVAL;
- }
-
- return sprintf(buf, "%lld\n", result->integer.value);
+ return sprintf(buf, "%lld\n", value);
}
static ssize_t irst_store_wakeup_events(struct device *dev,
@@ -54,8 +46,6 @@ static ssize_t irst_store_wakeup_events(struct device *dev,
const char *buf, size_t count)
{
struct acpi_device *acpi;
- struct acpi_object_list input;
- union acpi_object param;
acpi_status status;
unsigned long value;
int error;
@@ -67,13 +57,7 @@ static ssize_t irst_store_wakeup_events(struct device *dev,
if (error)
return error;
- param.type = ACPI_TYPE_INTEGER;
- param.integer.value = value;
-
- input.count = 1;
- input.pointer = &param;
-
- status = acpi_evaluate_object(acpi->handle, "SFFS", &input, NULL);
+ status = acpi_execute_simple_method(acpi->handle, "SFFS", value);
if (!ACPI_SUCCESS(status))
return -EINVAL;
@@ -91,24 +75,16 @@ static ssize_t irst_show_wakeup_time(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct acpi_device *acpi;
- struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
- union acpi_object *result;
+ unsigned long long value;
acpi_status status;
acpi = to_acpi_device(dev);
- status = acpi_evaluate_object(acpi->handle, "GFTV", NULL, &output);
+ status = acpi_evaluate_integer(acpi->handle, "GFTV", NULL, &value);
if (!ACPI_SUCCESS(status))
return -EINVAL;
- result = output.pointer;
-
- if (result->type != ACPI_TYPE_INTEGER) {
- kfree(result);
- return -EINVAL;
- }
-
- return sprintf(buf, "%lld\n", result->integer.value);
+ return sprintf(buf, "%lld\n", value);
}
static ssize_t irst_store_wakeup_time(struct device *dev,
@@ -116,8 +92,6 @@ static ssize_t irst_store_wakeup_time(struct device *dev,
const char *buf, size_t count)
{
struct acpi_device *acpi;
- struct acpi_object_list input;
- union acpi_object param;
acpi_status status;
unsigned long value;
int error;
@@ -129,13 +103,7 @@ static ssize_t irst_store_wakeup_time(struct device *dev,
if (error)
return error;
- param.type = ACPI_TYPE_INTEGER;
- param.integer.value = value;
-
- input.count = 1;
- input.pointer = &param;
-
- status = acpi_evaluate_object(acpi->handle, "SFTV", &input, NULL);
+ status = acpi_execute_simple_method(acpi->handle, "SFTV", value);
if (!ACPI_SUCCESS(status))
return -EINVAL;
diff --git a/drivers/platform/x86/intel-smartconnect.c b/drivers/platform/x86/intel-smartconnect.c
index 52259dcabecb..1838400dc036 100644
--- a/drivers/platform/x86/intel-smartconnect.c
+++ b/drivers/platform/x86/intel-smartconnect.c
@@ -25,37 +25,18 @@ MODULE_LICENSE("GPL");
static int smartconnect_acpi_init(struct acpi_device *acpi)
{
- struct acpi_object_list input;
- struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
- union acpi_object *result;
- union acpi_object param;
+ unsigned long long value;
acpi_status status;
- status = acpi_evaluate_object(acpi->handle, "GAOS", NULL, &output);
+ status = acpi_evaluate_integer(acpi->handle, "GAOS", NULL, &value);
if (!ACPI_SUCCESS(status))
return -EINVAL;
- result = output.pointer;
-
- if (result->type != ACPI_TYPE_INTEGER) {
- kfree(result);
- return -EINVAL;
- }
-
- if (result->integer.value & 0x1) {
- param.type = ACPI_TYPE_INTEGER;
- param.integer.value = 0;
-
- input.count = 1;
- input.pointer = &param;
-
+ if (value & 0x1) {
dev_info(&acpi->dev, "Disabling Intel Smart Connect\n");
- status = acpi_evaluate_object(acpi->handle, "SAOS", &input,
- NULL);
+ status = acpi_execute_simple_method(acpi->handle, "SAOS", 0);
}
- kfree(result);
-
return 0;
}
diff --git a/drivers/platform/x86/intel_menlow.c b/drivers/platform/x86/intel_menlow.c
index d6cfc1558c2f..11244f8703c4 100644
--- a/drivers/platform/x86/intel_menlow.c
+++ b/drivers/platform/x86/intel_menlow.c
@@ -156,19 +156,15 @@ static struct thermal_cooling_device_ops memory_cooling_ops = {
static int intel_menlow_memory_add(struct acpi_device *device)
{
int result = -ENODEV;
- acpi_status status = AE_OK;
- acpi_handle dummy;
struct thermal_cooling_device *cdev;
if (!device)
return -EINVAL;
- status = acpi_get_handle(device->handle, MEMORY_GET_BANDWIDTH, &dummy);
- if (ACPI_FAILURE(status))
+ if (!acpi_has_method(device->handle, MEMORY_GET_BANDWIDTH))
goto end;
- status = acpi_get_handle(device->handle, MEMORY_SET_BANDWIDTH, &dummy);
- if (ACPI_FAILURE(status))
+ if (!acpi_has_method(device->handle, MEMORY_SET_BANDWIDTH))
goto end;
cdev = thermal_cooling_device_register("Memory controller", device,
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index d3fd52036fd6..3b32852d6d2d 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -1509,7 +1509,6 @@ static void sony_nc_function_resume(void)
static int sony_nc_resume(struct device *dev)
{
struct sony_nc_value *item;
- acpi_handle handle;
for (item = sony_nc_values; item->name; item++) {
int ret;
@@ -1524,15 +1523,13 @@ static int sony_nc_resume(struct device *dev)
}
}
- if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
- &handle))) {
+ if (acpi_has_method(sony_nc_acpi_handle, "ECON")) {
int arg = 1;
if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL))
dprintk("ECON Method failed\n");
}
- if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
- &handle)))
+ if (acpi_has_method(sony_nc_acpi_handle, "SN00"))
sony_nc_function_resume();
return 0;
@@ -2690,7 +2687,6 @@ static void sony_nc_backlight_ng_read_limits(int handle,
static void sony_nc_backlight_setup(void)
{
- acpi_handle unused;
int max_brightness = 0;
const struct backlight_ops *ops = NULL;
struct backlight_properties props;
@@ -2725,8 +2721,7 @@ static void sony_nc_backlight_setup(void)
sony_nc_backlight_ng_read_limits(0x14c, &sony_bl_props);
max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
- } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
- &unused))) {
+ } else if (acpi_has_method(sony_nc_acpi_handle, "GBRT")) {
ops = &sony_backlight_ops;
max_brightness = SONY_MAX_BRIGHTNESS - 1;
@@ -2758,7 +2753,6 @@ static int sony_nc_add(struct acpi_device *device)
{
acpi_status status;
int result = 0;
- acpi_handle handle;
struct sony_nc_value *item;
pr_info("%s v%s\n", SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
@@ -2798,15 +2792,13 @@ static int sony_nc_add(struct acpi_device *device)
goto outplatform;
}
- if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
- &handle))) {
+ if (acpi_has_method(sony_nc_acpi_handle, "ECON")) {
int arg = 1;
if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL))
dprintk("ECON Method failed\n");
}
- if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
- &handle))) {
+ if (acpi_has_method(sony_nc_acpi_handle, "SN00")) {
dprintk("Doing SNC setup\n");
/* retrieve the available handles */
result = sony_nc_handles_setup(sony_pf_device);
@@ -2829,9 +2821,8 @@ static int sony_nc_add(struct acpi_device *device)
/* find the available acpiget as described in the DSDT */
for (; item->acpiget && *item->acpiget; ++item->acpiget) {
- if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
- *item->acpiget,
- &handle))) {
+ if (acpi_has_method(sony_nc_acpi_handle,
+ *item->acpiget)) {
dprintk("Found %s getter: %s\n",
item->name, *item->acpiget);
item->devattr.attr.mode |= S_IRUGO;
@@ -2841,9 +2832,8 @@ static int sony_nc_add(struct acpi_device *device)
/* find the available acpiset as described in the DSDT */
for (; item->acpiset && *item->acpiset; ++item->acpiset) {
- if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
- *item->acpiset,
- &handle))) {
+ if (acpi_has_method(sony_nc_acpi_handle,
+ *item->acpiset)) {
dprintk("Found %s setter: %s\n",
item->name, *item->acpiset);
item->devattr.attr.mode |= S_IWUSR;
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c
index 4ab618c63b45..67897c8740ba 100644
--- a/drivers/platform/x86/topstar-laptop.c
+++ b/drivers/platform/x86/topstar-laptop.c
@@ -80,13 +80,9 @@ static void acpi_topstar_notify(struct acpi_device *device, u32 event)
static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
{
acpi_status status;
- union acpi_object fncx_params[1] = {
- { .type = ACPI_TYPE_INTEGER }
- };
- struct acpi_object_list fncx_arg_list = { 1, &fncx_params[0] };
- fncx_params[0].integer.value = state ? 0x86 : 0x87;
- status = acpi_evaluate_object(device->handle, "FNCX", &fncx_arg_list, NULL);
+ status = acpi_execute_simple_method(device->handle, "FNCX",
+ state ? 0x86 : 0x87);
if (ACPI_FAILURE(status)) {
pr_err("Unable to switch FNCX notifications\n");
return -ENODEV;
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index eb3467ea6d86..0cfadb65f7c6 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -191,16 +191,9 @@ static __inline__ void _set_bit(u32 * word, u32 mask, int value)
static int write_acpi_int(const char *methodName, int val)
{
- struct acpi_object_list params;
- union acpi_object in_objs[1];
acpi_status status;
- params.count = ARRAY_SIZE(in_objs);
- params.pointer = in_objs;
- in_objs[0].type = ACPI_TYPE_INTEGER;
- in_objs[0].integer.value = val;
-
- status = acpi_evaluate_object(NULL, (char *)methodName, &params, NULL);
+ status = acpi_execute_simple_method(NULL, (char *)methodName, val);
return (status == AE_OK) ? 0 : -EIO;
}
@@ -947,21 +940,17 @@ static void toshiba_acpi_hotkey_work(struct work_struct *work)
*/
static int toshiba_acpi_query_hotkey(struct toshiba_acpi_dev *dev)
{
- struct acpi_buffer buf;
- union acpi_object out_obj;
+ unsigned long long value;
acpi_status status;
- buf.pointer = &out_obj;
- buf.length = sizeof(out_obj);
-
- status = acpi_evaluate_object(dev->acpi_dev->handle, "INFO",
- NULL, &buf);
- if (ACPI_FAILURE(status) || out_obj.type != ACPI_TYPE_INTEGER) {
+ status = acpi_evaluate_integer(dev->acpi_dev->handle, "INFO",
+ NULL, &value);
+ if (ACPI_FAILURE(status)) {
pr_err("ACPI INFO method execution failed\n");
return -EIO;
}
- return out_obj.integer.value;
+ return value;
}
static void toshiba_acpi_report_hotkey(struct toshiba_acpi_dev *dev,
@@ -981,7 +970,7 @@ static void toshiba_acpi_report_hotkey(struct toshiba_acpi_dev *dev,
static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
{
acpi_status status;
- acpi_handle ec_handle, handle;
+ acpi_handle ec_handle;
int error;
u32 hci_result;
@@ -1008,10 +997,7 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
*/
status = AE_ERROR;
ec_handle = ec_get_handle();
- if (ec_handle)
- status = acpi_get_handle(ec_handle, "NTFY", &handle);
-
- if (ACPI_SUCCESS(status)) {
+ if (ec_handle && acpi_has_method(ec_handle, "NTFY")) {
INIT_WORK(&dev->hotkey_work, toshiba_acpi_hotkey_work);
error = i8042_install_filter(toshiba_acpi_i8042_filter);
@@ -1027,10 +1013,9 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
* Determine hotkey query interface. Prefer using the INFO
* method when it is available.
*/
- status = acpi_get_handle(dev->acpi_dev->handle, "INFO", &handle);
- if (ACPI_SUCCESS(status)) {
+ if (acpi_has_method(dev->acpi_dev->handle, "INFO"))
dev->info_supported = 1;
- } else {
+ else {
hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
if (hci_result == HCI_SUCCESS)
dev->system_event_supported = 1;
@@ -1155,15 +1140,10 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev)
static const char *find_hci_method(acpi_handle handle)
{
- acpi_status status;
- acpi_handle hci_handle;
-
- status = acpi_get_handle(handle, "GHCI", &hci_handle);
- if (ACPI_SUCCESS(status))
+ if (acpi_has_method(handle, "GHCI"))
return "GHCI";
- status = acpi_get_handle(handle, "SPFC", &hci_handle);
- if (ACPI_SUCCESS(status))
+ if (acpi_has_method(handle, "SPFC"))
return "SPFC";
return NULL;
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 601ea9512242..62e8c221d01e 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -252,8 +252,6 @@ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
{
struct guid_block *block = NULL;
char method[5];
- struct acpi_object_list input;
- union acpi_object params[1];
acpi_status status;
acpi_handle handle;
@@ -263,13 +261,9 @@ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
if (!block)
return AE_NOT_EXIST;
- input.count = 1;
- input.pointer = params;
- params[0].type = ACPI_TYPE_INTEGER;
- params[0].integer.value = enable;
snprintf(method, 5, "WE%02X", block->notify_id);
- status = acpi_evaluate_object(handle, method, &input, NULL);
+ status = acpi_execute_simple_method(handle, method, enable);
if (status != AE_OK && status != AE_NOT_FOUND)
return status;
@@ -353,10 +347,10 @@ struct acpi_buffer *out)
{
struct guid_block *block = NULL;
struct wmi_block *wblock = NULL;
- acpi_handle handle, wc_handle;
+ acpi_handle handle;
acpi_status status, wc_status = AE_ERROR;
- struct acpi_object_list input, wc_input;
- union acpi_object wc_params[1], wq_params[1];
+ struct acpi_object_list input;
+ union acpi_object wq_params[1];
char method[5];
char wc_method[5] = "WC";
@@ -386,11 +380,6 @@ struct acpi_buffer *out)
* enable collection.
*/
if (block->flags & ACPI_WMI_EXPENSIVE) {
- wc_input.count = 1;
- wc_input.pointer = wc_params;
- wc_params[0].type = ACPI_TYPE_INTEGER;
- wc_params[0].integer.value = 1;
-
strncat(wc_method, block->object_id, 2);
/*
@@ -398,10 +387,9 @@ struct acpi_buffer *out)
* expensive, but have no corresponding WCxx method. So we
* should not fail if this happens.
*/
- wc_status = acpi_get_handle(handle, wc_method, &wc_handle);
- if (ACPI_SUCCESS(wc_status))
- wc_status = acpi_evaluate_object(handle, wc_method,
- &wc_input, NULL);
+ if (acpi_has_method(handle, wc_method))
+ wc_status = acpi_execute_simple_method(handle,
+ wc_method, 1);
}
strcpy(method, "WQ");
@@ -414,9 +402,7 @@ struct acpi_buffer *out)
* the WQxx method failed - we should disable collection anyway.
*/
if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) {
- wc_params[0].integer.value = 0;
- status = acpi_evaluate_object(handle,
- wc_method, &wc_input, NULL);
+ status = acpi_execute_simple_method(handle, wc_method, 0);
}
return status;
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 34049b0b4c73..747826d99059 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -239,8 +239,6 @@ static char *__init pnpacpi_get_id(struct acpi_device *device)
static int __init pnpacpi_add_device(struct acpi_device *device)
{
- acpi_handle temp = NULL;
- acpi_status status;
struct pnp_dev *dev;
char *pnpid;
struct acpi_hardware_id *id;
@@ -253,8 +251,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
* If a PnPacpi device is not present , the device
* driver should not be loaded.
*/
- status = acpi_get_handle(device->handle, "_CRS", &temp);
- if (ACPI_FAILURE(status))
+ if (!acpi_has_method(device->handle, "_CRS"))
return 0;
pnpid = pnpacpi_get_id(device);
@@ -271,16 +268,14 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
dev->data = device;
/* .enabled means the device can decode the resources */
dev->active = device->status.enabled;
- status = acpi_get_handle(device->handle, "_SRS", &temp);
- if (ACPI_SUCCESS(status))
+ if (acpi_has_method(device->handle, "_SRS"))
dev->capabilities |= PNP_CONFIGURABLE;
dev->capabilities |= PNP_READ;
if (device->flags.dynamic_status && (dev->capabilities & PNP_CONFIGURABLE))
dev->capabilities |= PNP_WRITE;
if (device->flags.removable)
dev->capabilities |= PNP_REMOVABLE;
- status = acpi_get_handle(device->handle, "_DIS", &temp);
- if (ACPI_SUCCESS(status))
+ if (acpi_has_method(device->handle, "_DIS"))
dev->capabilities |= PNP_DISABLE;
if (strlen(acpi_device_name(device)))
diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c
index ba6ce01035e4..f3dcd02390f1 100644
--- a/drivers/pwm/pwm-atmel-tcb.c
+++ b/drivers/pwm/pwm-atmel-tcb.c
@@ -249,6 +249,8 @@ static int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
}
}
+ cmr |= (tcbpwm->div & ATMEL_TC_TCCLKS);
+
__raw_writel(cmr, regs + ATMEL_TC_REG(group, CMR));
if (index == 0)
@@ -305,7 +307,7 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
i = slowclk;
rate = 32768;
min = div_u64(NSEC_PER_SEC, rate);
- max = min << 16;
+ max = min << tc->tcb_config->counter_width;
/* If period is too big return ERANGE error */
if (max < period_ns)
diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c
index 3e9b6a78ad18..2be2d24dbecb 100644
--- a/drivers/rapidio/rio-driver.c
+++ b/drivers/rapidio/rio-driver.c
@@ -224,7 +224,7 @@ struct bus_type rio_bus_type = {
.name = "rapidio",
.match = rio_match_bus,
.dev_attrs = rio_dev_attrs,
- .bus_attrs = rio_bus_attrs,
+ .bus_groups = rio_bus_groups,
.probe = rio_device_probe,
.remove = rio_device_remove,
.uevent = rio_uevent,
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c
index 9331be646dc3..795a4776cb0c 100644
--- a/drivers/rapidio/rio-sysfs.c
+++ b/drivers/rapidio/rio-sysfs.c
@@ -316,8 +316,18 @@ exit:
return rc;
}
+static BUS_ATTR(scan, (S_IWUSR|S_IWGRP), NULL, bus_scan_store);
-struct bus_attribute rio_bus_attrs[] = {
- __ATTR(scan, (S_IWUSR|S_IWGRP), NULL, bus_scan_store),
- __ATTR_NULL
+static struct attribute *rio_bus_attrs[] = {
+ &bus_attr_scan.attr,
+ NULL,
+};
+
+static const struct attribute_group rio_bus_group = {
+ .attrs = rio_bus_attrs,
+};
+
+const struct attribute_group *rio_bus_groups[] = {
+ &rio_bus_group,
+ NULL,
};
diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h
index 085215cd8502..57d2ad06a816 100644
--- a/drivers/rapidio/rio.h
+++ b/drivers/rapidio/rio.h
@@ -49,7 +49,7 @@ extern int rio_mport_scan(int mport_id);
/* Structures internal to the RIO core code */
extern struct device_attribute rio_dev_attrs[];
-extern struct bus_attribute rio_bus_attrs[];
+extern const struct attribute_group *rio_bus_groups[];
#define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16))
#define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16))
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index 70230974468c..f704d83c93c4 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -391,7 +391,8 @@ static int pm8607_regulator_probe(struct platform_device *pdev)
else
config.regmap = chip->regmap_companion;
- info->regulator = regulator_register(&info->desc, &config);
+ info->regulator = devm_regulator_register(&pdev->dev, &info->desc,
+ &config);
if (IS_ERR(info->regulator)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
info->desc.name);
@@ -402,14 +403,6 @@ static int pm8607_regulator_probe(struct platform_device *pdev)
return 0;
}
-static int pm8607_regulator_remove(struct platform_device *pdev)
-{
- struct pm8607_regulator_info *info = platform_get_drvdata(pdev);
-
- regulator_unregister(info->regulator);
- return 0;
-}
-
static struct platform_device_id pm8607_regulator_driver_ids[] = {
{
.name = "88pm860x-regulator",
@@ -428,7 +421,6 @@ static struct platform_driver pm8607_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = pm8607_regulator_probe,
- .remove = pm8607_regulator_remove,
.id_table = pm8607_regulator_driver_ids,
};
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index dfe58096b374..ce785f481281 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -28,16 +28,6 @@ config REGULATOR_DEBUG
help
Say yes here to enable debugging support.
-config REGULATOR_DUMMY
- bool "Provide a dummy regulator if regulator lookups fail"
- help
- If this option is enabled then when a regulator lookup fails
- and the board has not specified that it has provided full
- constraints the regulator core will provide an always
- enabled dummy regulator, allowing consumer drivers to continue.
-
- A warning will be generated when this substitution is done.
-
config REGULATOR_FIXED_VOLTAGE
tristate "Fixed voltage regulator support"
help
@@ -133,6 +123,14 @@ config REGULATOR_AS3711
This driver provides support for the voltage regulators on the
AS3711 PMIC
+config REGULATOR_AS3722
+ tristate "AMS AS3722 PMIC Regulators"
+ depends on MFD_AS3722
+ help
+ This driver provides support for the voltage regulators on the
+ AS3722 PMIC. This will enable support for all the software
+ controllable DCDC/LDO regulators.
+
config REGULATOR_DA903X
tristate "Dialog Semiconductor DA9030/DA9034 regulators"
depends on PMIC_DA903X
@@ -429,6 +427,14 @@ config REGULATOR_TI_ABB
on TI SoCs may be unstable without enabling this as it provides
device specific optimized bias to allow/optimize functionality.
+config REGULATOR_STW481X_VMMC
+ bool "ST Microelectronics STW481X VMMC regulator"
+ depends on MFD_STW481X
+ default y if MFD_STW481X
+ help
+ This driver supports the internal VMMC regulator in the STw481x
+ PMIC chips.
+
config REGULATOR_TPS51632
tristate "TI TPS51632 Power Regulator"
depends on I2C
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 185cce246022..01c597ea1744 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -3,7 +3,7 @@
#
-obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o helpers.o
+obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o helpers.o devres.o
obj-$(CONFIG_OF) += of_regulator.o
obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
@@ -18,6 +18,7 @@ obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
+obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o
@@ -56,6 +57,7 @@ obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
+obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c
index 881159dfcb5e..f70a9bfa5ff2 100644
--- a/drivers/regulator/aat2870-regulator.c
+++ b/drivers/regulator/aat2870-regulator.c
@@ -176,7 +176,7 @@ static int aat2870_regulator_probe(struct platform_device *pdev)
config.driver_data = ri;
config.init_data = dev_get_platdata(&pdev->dev);
- rdev = regulator_register(&ri->desc, &config);
+ rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "Failed to register regulator %s\n",
ri->desc.name);
@@ -187,21 +187,12 @@ static int aat2870_regulator_probe(struct platform_device *pdev)
return 0;
}
-static int aat2870_regulator_remove(struct platform_device *pdev)
-{
- struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
- regulator_unregister(rdev);
- return 0;
-}
-
static struct platform_driver aat2870_regulator_driver = {
.driver = {
.name = "aat2870-regulator",
.owner = THIS_MODULE,
},
.probe = aat2870_regulator_probe,
- .remove = aat2870_regulator_remove,
};
static int __init aat2870_regulator_init(void)
diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
index b2b203cb6b2f..48016a050d5f 100644
--- a/drivers/regulator/ad5398.c
+++ b/drivers/regulator/ad5398.c
@@ -219,7 +219,6 @@ static int ad5398_probe(struct i2c_client *client,
struct ad5398_chip_info *chip;
const struct ad5398_current_data_format *df =
(struct ad5398_current_data_format *)id->driver_data;
- int ret;
if (!init_data)
return -EINVAL;
@@ -240,33 +239,21 @@ static int ad5398_probe(struct i2c_client *client,
chip->current_offset = df->current_offset;
chip->current_mask = (chip->current_level - 1) << chip->current_offset;
- chip->rdev = regulator_register(&ad5398_reg, &config);
+ chip->rdev = devm_regulator_register(&client->dev, &ad5398_reg,
+ &config);
if (IS_ERR(chip->rdev)) {
- ret = PTR_ERR(chip->rdev);
dev_err(&client->dev, "failed to register %s %s\n",
id->name, ad5398_reg.name);
- goto err;
+ return PTR_ERR(chip->rdev);
}
i2c_set_clientdata(client, chip);
dev_dbg(&client->dev, "%s regulator driver is registered.\n", id->name);
return 0;
-
-err:
- return ret;
-}
-
-static int ad5398_remove(struct i2c_client *client)
-{
- struct ad5398_chip_info *chip = i2c_get_clientdata(client);
-
- regulator_unregister(chip->rdev);
- return 0;
}
static struct i2c_driver ad5398_driver = {
.probe = ad5398_probe,
- .remove = ad5398_remove,
.driver = {
.name = "ad5398",
},
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
index 0d4a8ccbb536..e42bfd17562a 100644
--- a/drivers/regulator/anatop-regulator.c
+++ b/drivers/regulator/anatop-regulator.c
@@ -200,7 +200,7 @@ static int anatop_regulator_probe(struct platform_device *pdev)
config.regmap = sreg->anatop;
/* register regulator */
- rdev = regulator_register(rdesc, &config);
+ rdev = devm_regulator_register(dev, rdesc, &config);
if (IS_ERR(rdev)) {
dev_err(dev, "failed to register %s\n",
rdesc->name);
@@ -223,7 +223,6 @@ static int anatop_regulator_remove(struct platform_device *pdev)
struct anatop_regulator *sreg = rdev_get_drvdata(rdev);
const char *name = sreg->name;
- regulator_unregister(rdev);
kfree(name);
return 0;
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
index 81d8681c3195..4f6c2055f6b2 100644
--- a/drivers/regulator/arizona-ldo1.c
+++ b/drivers/regulator/arizona-ldo1.c
@@ -226,7 +226,7 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
else
config.init_data = &ldo1->init_data;
- ldo1->regulator = regulator_register(desc, &config);
+ ldo1->regulator = devm_regulator_register(&pdev->dev, desc, &config);
if (IS_ERR(ldo1->regulator)) {
ret = PTR_ERR(ldo1->regulator);
dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n",
@@ -239,18 +239,8 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
return 0;
}
-static int arizona_ldo1_remove(struct platform_device *pdev)
-{
- struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev);
-
- regulator_unregister(ldo1->regulator);
-
- return 0;
-}
-
static struct platform_driver arizona_ldo1_driver = {
.probe = arizona_ldo1_probe,
- .remove = arizona_ldo1_remove,
.driver = {
.name = "arizona-ldo1",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c
index e87536bf0bed..724706a97dc4 100644
--- a/drivers/regulator/arizona-micsupp.c
+++ b/drivers/regulator/arizona-micsupp.c
@@ -225,7 +225,9 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
regmap_update_bits(arizona->regmap, ARIZONA_MIC_CHARGE_PUMP_1,
ARIZONA_CPMIC_BYPASS, 0);
- micsupp->regulator = regulator_register(&arizona_micsupp, &config);
+ micsupp->regulator = devm_regulator_register(&pdev->dev,
+ &arizona_micsupp,
+ &config);
if (IS_ERR(micsupp->regulator)) {
ret = PTR_ERR(micsupp->regulator);
dev_err(arizona->dev, "Failed to register mic supply: %d\n",
@@ -238,18 +240,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
return 0;
}
-static int arizona_micsupp_remove(struct platform_device *pdev)
-{
- struct arizona_micsupp *micsupp = platform_get_drvdata(pdev);
-
- regulator_unregister(micsupp->regulator);
-
- return 0;
-}
-
static struct platform_driver arizona_micsupp_driver = {
.probe = arizona_micsupp_probe,
- .remove = arizona_micsupp_remove,
.driver = {
.name = "arizona-micsupp",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c
index 8406cd745da2..fb27e6c8887c 100644
--- a/drivers/regulator/as3711-regulator.c
+++ b/drivers/regulator/as3711-regulator.c
@@ -273,33 +273,16 @@ static int as3711_regulator_probe(struct platform_device *pdev)
config.regmap = as3711->regmap;
config.of_node = of_node[id];
- rdev = regulator_register(&ri->desc, &config);
+ rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "Failed to register regulator %s\n",
ri->desc.name);
- ret = PTR_ERR(rdev);
- goto eregreg;
+ return PTR_ERR(rdev);
}
reg->rdev = rdev;
}
platform_set_drvdata(pdev, regs);
return 0;
-
-eregreg:
- while (--id >= 0)
- regulator_unregister(regs[id].rdev);
-
- return ret;
-}
-
-static int as3711_regulator_remove(struct platform_device *pdev)
-{
- struct as3711_regulator *regs = platform_get_drvdata(pdev);
- int id;
-
- for (id = 0; id < AS3711_REGULATOR_NUM; ++id)
- regulator_unregister(regs[id].rdev);
- return 0;
}
static struct platform_driver as3711_regulator_driver = {
@@ -308,7 +291,6 @@ static struct platform_driver as3711_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = as3711_regulator_probe,
- .remove = as3711_regulator_remove,
};
static int __init as3711_regulator_init(void)
diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c
new file mode 100644
index 000000000000..16a5d26a2d35
--- /dev/null
+++ b/drivers/regulator/as3722-regulator.c
@@ -0,0 +1,917 @@
+/*
+ * Voltage regulator support for AMS AS3722 PMIC
+ *
+ * Copyright (C) 2013 ams
+ *
+ * Author: Florian Lobmaier <florian.lobmaier@ams.com>
+ * Author: Laxman Dewangan <ldewangan@nvidia.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
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mfd/as3722.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/slab.h>
+
+/* Regulator IDs */
+enum as3722_regulators_id {
+ AS3722_REGULATOR_ID_SD0,
+ AS3722_REGULATOR_ID_SD1,
+ AS3722_REGULATOR_ID_SD2,
+ AS3722_REGULATOR_ID_SD3,
+ AS3722_REGULATOR_ID_SD4,
+ AS3722_REGULATOR_ID_SD5,
+ AS3722_REGULATOR_ID_SD6,
+ AS3722_REGULATOR_ID_LDO0,
+ AS3722_REGULATOR_ID_LDO1,
+ AS3722_REGULATOR_ID_LDO2,
+ AS3722_REGULATOR_ID_LDO3,
+ AS3722_REGULATOR_ID_LDO4,
+ AS3722_REGULATOR_ID_LDO5,
+ AS3722_REGULATOR_ID_LDO6,
+ AS3722_REGULATOR_ID_LDO7,
+ AS3722_REGULATOR_ID_LDO9,
+ AS3722_REGULATOR_ID_LDO10,
+ AS3722_REGULATOR_ID_LDO11,
+ AS3722_REGULATOR_ID_MAX,
+};
+
+struct as3722_register_mapping {
+ u8 regulator_id;
+ const char *name;
+ const char *sname;
+ u8 vsel_reg;
+ u8 vsel_mask;
+ int n_voltages;
+ u32 enable_reg;
+ u8 enable_mask;
+ u32 control_reg;
+ u8 mode_mask;
+ u32 sleep_ctrl_reg;
+ u8 sleep_ctrl_mask;
+};
+
+struct as3722_regulator_config_data {
+ struct regulator_init_data *reg_init;
+ bool enable_tracking;
+ int ext_control;
+};
+
+struct as3722_regulators {
+ struct device *dev;
+ struct as3722 *as3722;
+ struct regulator_dev *rdevs[AS3722_REGULATOR_ID_MAX];
+ struct regulator_desc desc[AS3722_REGULATOR_ID_MAX];
+ struct as3722_regulator_config_data
+ reg_config_data[AS3722_REGULATOR_ID_MAX];
+};
+
+static const struct as3722_register_mapping as3722_reg_lookup[] = {
+ {
+ .regulator_id = AS3722_REGULATOR_ID_SD0,
+ .name = "as3722-sd0",
+ .vsel_reg = AS3722_SD0_VOLTAGE_REG,
+ .vsel_mask = AS3722_SD_VSEL_MASK,
+ .enable_reg = AS3722_SD_CONTROL_REG,
+ .enable_mask = AS3722_SDn_CTRL(0),
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
+ .sleep_ctrl_mask = AS3722_SD0_EXT_ENABLE_MASK,
+ .control_reg = AS3722_SD0_CONTROL_REG,
+ .mode_mask = AS3722_SD0_MODE_FAST,
+ .n_voltages = AS3722_SD0_VSEL_MAX,
+ },
+ {
+ .regulator_id = AS3722_REGULATOR_ID_SD1,
+ .name = "as3722-sd1",
+ .vsel_reg = AS3722_SD1_VOLTAGE_REG,
+ .vsel_mask = AS3722_SD_VSEL_MASK,
+ .enable_reg = AS3722_SD_CONTROL_REG,
+ .enable_mask = AS3722_SDn_CTRL(1),
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
+ .sleep_ctrl_mask = AS3722_SD1_EXT_ENABLE_MASK,
+ .control_reg = AS3722_SD1_CONTROL_REG,
+ .mode_mask = AS3722_SD1_MODE_FAST,
+ .n_voltages = AS3722_SD0_VSEL_MAX,
+ },
+ {
+ .regulator_id = AS3722_REGULATOR_ID_SD2,
+ .name = "as3722-sd2",
+ .sname = "vsup-sd2",
+ .vsel_reg = AS3722_SD2_VOLTAGE_REG,
+ .vsel_mask = AS3722_SD_VSEL_MASK,
+ .enable_reg = AS3722_SD_CONTROL_REG,
+ .enable_mask = AS3722_SDn_CTRL(2),
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
+ .sleep_ctrl_mask = AS3722_SD2_EXT_ENABLE_MASK,
+ .control_reg = AS3722_SD23_CONTROL_REG,
+ .mode_mask = AS3722_SD2_MODE_FAST,
+ .n_voltages = AS3722_SD2_VSEL_MAX,
+ },
+ {
+ .regulator_id = AS3722_REGULATOR_ID_SD3,
+ .name = "as3722-sd3",
+ .sname = "vsup-sd3",
+ .vsel_reg = AS3722_SD3_VOLTAGE_REG,
+ .vsel_mask = AS3722_SD_VSEL_MASK,
+ .enable_reg = AS3722_SD_CONTROL_REG,
+ .enable_mask = AS3722_SDn_CTRL(3),
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
+ .sleep_ctrl_mask = AS3722_SD3_EXT_ENABLE_MASK,
+ .control_reg = AS3722_SD23_CONTROL_REG,
+ .mode_mask = AS3722_SD3_MODE_FAST,
+ .n_voltages = AS3722_SD2_VSEL_MAX,
+ },
+ {
+ .regulator_id = AS3722_REGULATOR_ID_SD4,
+ .name = "as3722-sd4",
+ .sname = "vsup-sd4",
+ .vsel_reg = AS3722_SD4_VOLTAGE_REG,
+ .vsel_mask = AS3722_SD_VSEL_MASK,
+ .enable_reg = AS3722_SD_CONTROL_REG,
+ .enable_mask = AS3722_SDn_CTRL(4),
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
+ .sleep_ctrl_mask = AS3722_SD4_EXT_ENABLE_MASK,
+ .control_reg = AS3722_SD4_CONTROL_REG,
+ .mode_mask = AS3722_SD4_MODE_FAST,
+ .n_voltages = AS3722_SD2_VSEL_MAX,
+ },
+ {
+ .regulator_id = AS3722_REGULATOR_ID_SD5,
+ .name = "as3722-sd5",
+ .sname = "vsup-sd5",
+ .vsel_reg = AS3722_SD5_VOLTAGE_REG,
+ .vsel_mask = AS3722_SD_VSEL_MASK,
+ .enable_reg = AS3722_SD_CONTROL_REG,
+ .enable_mask = AS3722_SDn_CTRL(5),
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
+ .sleep_ctrl_mask = AS3722_SD5_EXT_ENABLE_MASK,
+ .control_reg = AS3722_SD5_CONTROL_REG,
+ .mode_mask = AS3722_SD5_MODE_FAST,
+ .n_voltages = AS3722_SD2_VSEL_MAX,
+ },
+ {
+ .regulator_id = AS3722_REGULATOR_ID_SD6,
+ .name = "as3722-sd6",
+ .vsel_reg = AS3722_SD6_VOLTAGE_REG,
+ .vsel_mask = AS3722_SD_VSEL_MASK,
+ .enable_reg = AS3722_SD_CONTROL_REG,
+ .enable_mask = AS3722_SDn_CTRL(6),
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
+ .sleep_ctrl_mask = AS3722_SD6_EXT_ENABLE_MASK,
+ .control_reg = AS3722_SD6_CONTROL_REG,
+ .mode_mask = AS3722_SD6_MODE_FAST,
+ .n_voltages = AS3722_SD0_VSEL_MAX,
+ },
+ {
+ .regulator_id = AS3722_REGULATOR_ID_LDO0,
+ .name = "as3722-ldo0",
+ .sname = "vin-ldo0",
+ .vsel_reg = AS3722_LDO0_VOLTAGE_REG,
+ .vsel_mask = AS3722_LDO0_VSEL_MASK,
+ .enable_reg = AS3722_LDOCONTROL0_REG,
+ .enable_mask = AS3722_LDO0_CTRL,
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
+ .sleep_ctrl_mask = AS3722_LDO0_EXT_ENABLE_MASK,
+ .n_voltages = AS3722_LDO0_NUM_VOLT,
+ },
+ {
+ .regulator_id = AS3722_REGULATOR_ID_LDO1,
+ .name = "as3722-ldo1",
+ .sname = "vin-ldo1-6",
+ .vsel_reg = AS3722_LDO1_VOLTAGE_REG,
+ .vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDOCONTROL0_REG,
+ .enable_mask = AS3722_LDO1_CTRL,
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
+ .sleep_ctrl_mask = AS3722_LDO1_EXT_ENABLE_MASK,
+ .n_voltages = AS3722_LDO_NUM_VOLT,
+ },
+ {
+ .regulator_id = AS3722_REGULATOR_ID_LDO2,
+ .name = "as3722-ldo2",
+ .sname = "vin-ldo2-5-7",
+ .vsel_reg = AS3722_LDO2_VOLTAGE_REG,
+ .vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDOCONTROL0_REG,
+ .enable_mask = AS3722_LDO2_CTRL,
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
+ .sleep_ctrl_mask = AS3722_LDO2_EXT_ENABLE_MASK,
+ .n_voltages = AS3722_LDO_NUM_VOLT,
+ },
+ {
+ .regulator_id = AS3722_REGULATOR_ID_LDO3,
+ .name = "as3722-ldo3",
+ .name = "vin-ldo3-4",
+ .vsel_reg = AS3722_LDO3_VOLTAGE_REG,
+ .vsel_mask = AS3722_LDO3_VSEL_MASK,
+ .enable_reg = AS3722_LDOCONTROL0_REG,
+ .enable_mask = AS3722_LDO3_CTRL,
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
+ .sleep_ctrl_mask = AS3722_LDO3_EXT_ENABLE_MASK,
+ .n_voltages = AS3722_LDO3_NUM_VOLT,
+ },
+ {
+ .regulator_id = AS3722_REGULATOR_ID_LDO4,
+ .name = "as3722-ldo4",
+ .name = "vin-ldo3-4",
+ .vsel_reg = AS3722_LDO4_VOLTAGE_REG,
+ .vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDOCONTROL0_REG,
+ .enable_mask = AS3722_LDO4_CTRL,
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
+ .sleep_ctrl_mask = AS3722_LDO4_EXT_ENABLE_MASK,
+ .n_voltages = AS3722_LDO_NUM_VOLT,
+ },
+ {
+ .regulator_id = AS3722_REGULATOR_ID_LDO5,
+ .name = "as3722-ldo5",
+ .sname = "vin-ldo2-5-7",
+ .vsel_reg = AS3722_LDO5_VOLTAGE_REG,
+ .vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDOCONTROL0_REG,
+ .enable_mask = AS3722_LDO5_CTRL,
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
+ .sleep_ctrl_mask = AS3722_LDO5_EXT_ENABLE_MASK,
+ .n_voltages = AS3722_LDO_NUM_VOLT,
+ },
+ {
+ .regulator_id = AS3722_REGULATOR_ID_LDO6,
+ .name = "as3722-ldo6",
+ .sname = "vin-ldo1-6",
+ .vsel_reg = AS3722_LDO6_VOLTAGE_REG,
+ .vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDOCONTROL0_REG,
+ .enable_mask = AS3722_LDO6_CTRL,
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
+ .sleep_ctrl_mask = AS3722_LDO6_EXT_ENABLE_MASK,
+ .n_voltages = AS3722_LDO_NUM_VOLT,
+ },
+ {
+ .regulator_id = AS3722_REGULATOR_ID_LDO7,
+ .name = "as3722-ldo7",
+ .sname = "vin-ldo2-5-7",
+ .vsel_reg = AS3722_LDO7_VOLTAGE_REG,
+ .vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDOCONTROL0_REG,
+ .enable_mask = AS3722_LDO7_CTRL,
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
+ .sleep_ctrl_mask = AS3722_LDO7_EXT_ENABLE_MASK,
+ .n_voltages = AS3722_LDO_NUM_VOLT,
+ },
+ {
+ .regulator_id = AS3722_REGULATOR_ID_LDO9,
+ .name = "as3722-ldo9",
+ .sname = "vin-ldo9-10",
+ .vsel_reg = AS3722_LDO9_VOLTAGE_REG,
+ .vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDOCONTROL1_REG,
+ .enable_mask = AS3722_LDO9_CTRL,
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
+ .sleep_ctrl_mask = AS3722_LDO9_EXT_ENABLE_MASK,
+ .n_voltages = AS3722_LDO_NUM_VOLT,
+ },
+ {
+ .regulator_id = AS3722_REGULATOR_ID_LDO10,
+ .name = "as3722-ldo10",
+ .sname = "vin-ldo9-10",
+ .vsel_reg = AS3722_LDO10_VOLTAGE_REG,
+ .vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDOCONTROL1_REG,
+ .enable_mask = AS3722_LDO10_CTRL,
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
+ .sleep_ctrl_mask = AS3722_LDO10_EXT_ENABLE_MASK,
+ .n_voltages = AS3722_LDO_NUM_VOLT,
+ },
+ {
+ .regulator_id = AS3722_REGULATOR_ID_LDO11,
+ .name = "as3722-ldo11",
+ .sname = "vin-ldo11",
+ .vsel_reg = AS3722_LDO11_VOLTAGE_REG,
+ .vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDOCONTROL1_REG,
+ .enable_mask = AS3722_LDO11_CTRL,
+ .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
+ .sleep_ctrl_mask = AS3722_LDO11_EXT_ENABLE_MASK,
+ .n_voltages = AS3722_LDO_NUM_VOLT,
+ },
+};
+
+
+static const int as3722_ldo_current[] = { 150000, 300000 };
+static const int as3722_sd016_current[] = { 2500000, 3000000, 3500000 };
+
+static int as3722_current_to_index(int min_uA, int max_uA,
+ const int *curr_table, int n_currents)
+{
+ int i;
+
+ for (i = n_currents - 1; i >= 0; i--) {
+ if ((min_uA <= curr_table[i]) && (curr_table[i] <= max_uA))
+ return i;
+ }
+ return -EINVAL;
+}
+
+static int as3722_ldo_get_current_limit(struct regulator_dev *rdev)
+{
+ struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+ struct as3722 *as3722 = as3722_regs->as3722;
+ int id = rdev_get_id(rdev);
+ u32 val;
+ int ret;
+
+ ret = as3722_read(as3722, as3722_reg_lookup[id].vsel_reg, &val);
+ if (ret < 0) {
+ dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
+ as3722_reg_lookup[id].vsel_reg, ret);
+ return ret;
+ }
+ if (val & AS3722_LDO_ILIMIT_MASK)
+ return 300000;
+ return 150000;
+}
+
+static int as3722_ldo_set_current_limit(struct regulator_dev *rdev,
+ int min_uA, int max_uA)
+{
+ struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+ struct as3722 *as3722 = as3722_regs->as3722;
+ int id = rdev_get_id(rdev);
+ int ret;
+ u32 reg = 0;
+
+ ret = as3722_current_to_index(min_uA, max_uA, as3722_ldo_current,
+ ARRAY_SIZE(as3722_ldo_current));
+ if (ret < 0) {
+ dev_err(as3722_regs->dev,
+ "Current range min:max = %d:%d does not support\n",
+ min_uA, max_uA);
+ return ret;
+ }
+ if (ret)
+ reg = AS3722_LDO_ILIMIT_BIT;
+ return as3722_update_bits(as3722, as3722_reg_lookup[id].vsel_reg,
+ AS3722_LDO_ILIMIT_MASK, reg);
+}
+
+static struct regulator_ops as3722_ldo0_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_current_limit = as3722_ldo_get_current_limit,
+ .set_current_limit = as3722_ldo_set_current_limit,
+};
+
+static struct regulator_ops as3722_ldo0_extcntrl_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_current_limit = as3722_ldo_get_current_limit,
+ .set_current_limit = as3722_ldo_set_current_limit,
+};
+
+static int as3722_ldo3_set_tracking_mode(struct as3722_regulators *as3722_reg,
+ int id, u8 mode)
+{
+ struct as3722 *as3722 = as3722_reg->as3722;
+
+ switch (mode) {
+ case AS3722_LDO3_MODE_PMOS:
+ case AS3722_LDO3_MODE_PMOS_TRACKING:
+ case AS3722_LDO3_MODE_NMOS:
+ case AS3722_LDO3_MODE_SWITCH:
+ return as3722_update_bits(as3722,
+ as3722_reg_lookup[id].vsel_reg,
+ AS3722_LDO3_MODE_MASK, mode);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int as3722_ldo3_get_current_limit(struct regulator_dev *rdev)
+{
+ return 150000;
+}
+
+static struct regulator_ops as3722_ldo3_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_current_limit = as3722_ldo3_get_current_limit,
+};
+
+static struct regulator_ops as3722_ldo3_extcntrl_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_current_limit = as3722_ldo3_get_current_limit,
+};
+
+#define regulator_lin_range(_min_sel, _max_sel, _min_uV, _step_uV) \
+ { \
+ .min_sel = _min_sel, \
+ .max_sel = _max_sel, \
+ .uV_step = _step_uV, \
+ .min_uV = _min_uV, \
+ .max_uV = _min_uV + (_max_sel - _min_sel + 1) * _step_uV, \
+ }
+
+static const struct regulator_linear_range as3722_ldo_ranges[] = {
+ regulator_lin_range(0x01, 0x24, 800000, 25000),
+ regulator_lin_range(0x40, 0x7F, 1725000, 25000),
+};
+
+static struct regulator_ops as3722_ldo_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .get_current_limit = as3722_ldo_get_current_limit,
+ .set_current_limit = as3722_ldo_set_current_limit,
+};
+
+static struct regulator_ops as3722_ldo_extcntrl_ops = {
+ .map_voltage = regulator_map_voltage_linear_range,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .get_current_limit = as3722_ldo_get_current_limit,
+ .set_current_limit = as3722_ldo_set_current_limit,
+};
+
+static unsigned int as3722_sd_get_mode(struct regulator_dev *rdev)
+{
+ struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+ struct as3722 *as3722 = as3722_regs->as3722;
+ int id = rdev_get_id(rdev);
+ u32 val;
+ int ret;
+
+ if (!as3722_reg_lookup[id].control_reg)
+ return -ENOTSUPP;
+
+ ret = as3722_read(as3722, as3722_reg_lookup[id].control_reg, &val);
+ if (ret < 0) {
+ dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
+ as3722_reg_lookup[id].control_reg, ret);
+ return ret;
+ }
+
+ if (val & as3722_reg_lookup[id].mode_mask)
+ return REGULATOR_MODE_FAST;
+ else
+ return REGULATOR_MODE_NORMAL;
+}
+
+static int as3722_sd_set_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+ struct as3722 *as3722 = as3722_regs->as3722;
+ u8 id = rdev_get_id(rdev);
+ u8 val = 0;
+ int ret;
+
+ if (!as3722_reg_lookup[id].control_reg)
+ return -ERANGE;
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ val = as3722_reg_lookup[id].mode_mask;
+ case REGULATOR_MODE_NORMAL: /* fall down */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = as3722_update_bits(as3722, as3722_reg_lookup[id].control_reg,
+ as3722_reg_lookup[id].mode_mask, val);
+ if (ret < 0) {
+ dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n",
+ as3722_reg_lookup[id].control_reg, ret);
+ return ret;
+ }
+ return ret;
+}
+
+static int as3722_sd016_get_current_limit(struct regulator_dev *rdev)
+{
+ struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+ struct as3722 *as3722 = as3722_regs->as3722;
+ int id = rdev_get_id(rdev);
+ u32 val, reg;
+ int mask;
+ int ret;
+
+ switch (id) {
+ case AS3722_REGULATOR_ID_SD0:
+ reg = AS3722_OVCURRENT_REG;
+ mask = AS3722_OVCURRENT_SD0_TRIP_MASK;
+ break;
+ case AS3722_REGULATOR_ID_SD1:
+ reg = AS3722_OVCURRENT_REG;
+ mask = AS3722_OVCURRENT_SD1_TRIP_MASK;
+ break;
+ case AS3722_REGULATOR_ID_SD6:
+ reg = AS3722_OVCURRENT_DEB_REG;
+ mask = AS3722_OVCURRENT_SD6_TRIP_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+ ret = as3722_read(as3722, reg, &val);
+ if (ret < 0) {
+ dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
+ reg, ret);
+ return ret;
+ }
+ val &= mask;
+ val >>= ffs(mask) - 1;
+ if (val == 3)
+ return -EINVAL;
+ return as3722_sd016_current[val];
+}
+
+static int as3722_sd016_set_current_limit(struct regulator_dev *rdev,
+ int min_uA, int max_uA)
+{
+ struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+ struct as3722 *as3722 = as3722_regs->as3722;
+ int id = rdev_get_id(rdev);
+ int ret;
+ int val;
+ int mask;
+ u32 reg;
+
+ ret = as3722_current_to_index(min_uA, max_uA, as3722_sd016_current,
+ ARRAY_SIZE(as3722_sd016_current));
+ if (ret < 0) {
+ dev_err(as3722_regs->dev,
+ "Current range min:max = %d:%d does not support\n",
+ min_uA, max_uA);
+ return ret;
+ }
+
+ switch (id) {
+ case AS3722_REGULATOR_ID_SD0:
+ reg = AS3722_OVCURRENT_REG;
+ mask = AS3722_OVCURRENT_SD0_TRIP_MASK;
+ break;
+ case AS3722_REGULATOR_ID_SD1:
+ reg = AS3722_OVCURRENT_REG;
+ mask = AS3722_OVCURRENT_SD1_TRIP_MASK;
+ break;
+ case AS3722_REGULATOR_ID_SD6:
+ reg = AS3722_OVCURRENT_DEB_REG;
+ mask = AS3722_OVCURRENT_SD6_TRIP_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+ val = ret & mask;
+ val <<= ffs(mask) - 1;
+ return as3722_update_bits(as3722, reg, mask, val);
+}
+
+static const struct regulator_linear_range as3722_sd2345_ranges[] = {
+ regulator_lin_range(0x01, 0x40, 600000, 12500),
+ regulator_lin_range(0x41, 0x70, 1400000, 25000),
+ regulator_lin_range(0x71, 0x7F, 1725000, 50000),
+};
+
+static struct regulator_ops as3722_sd016_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_current_limit = as3722_sd016_get_current_limit,
+ .set_current_limit = as3722_sd016_set_current_limit,
+ .get_mode = as3722_sd_get_mode,
+ .set_mode = as3722_sd_set_mode,
+};
+
+static struct regulator_ops as3722_sd016_extcntrl_ops = {
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_current_limit = as3722_sd016_get_current_limit,
+ .set_current_limit = as3722_sd016_set_current_limit,
+ .get_mode = as3722_sd_get_mode,
+ .set_mode = as3722_sd_set_mode,
+};
+
+static struct regulator_ops as3722_sd2345_ops = {
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .get_mode = as3722_sd_get_mode,
+ .set_mode = as3722_sd_set_mode,
+};
+
+static struct regulator_ops as3722_sd2345_extcntrl_ops = {
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .get_mode = as3722_sd_get_mode,
+ .set_mode = as3722_sd_set_mode,
+};
+
+static int as3722_extreg_init(struct as3722_regulators *as3722_regs, int id,
+ int ext_pwr_ctrl)
+{
+ int ret;
+ unsigned int val;
+
+ if ((ext_pwr_ctrl < AS3722_EXT_CONTROL_ENABLE1) ||
+ (ext_pwr_ctrl > AS3722_EXT_CONTROL_ENABLE3))
+ return -EINVAL;
+
+ val = ext_pwr_ctrl << (ffs(as3722_reg_lookup[id].sleep_ctrl_mask) - 1);
+ ret = as3722_update_bits(as3722_regs->as3722,
+ as3722_reg_lookup[id].sleep_ctrl_reg,
+ as3722_reg_lookup[id].sleep_ctrl_mask, val);
+ if (ret < 0)
+ dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n",
+ as3722_reg_lookup[id].sleep_ctrl_reg, ret);
+ return ret;
+}
+
+static struct of_regulator_match as3722_regulator_matches[] = {
+ { .name = "sd0", },
+ { .name = "sd1", },
+ { .name = "sd2", },
+ { .name = "sd3", },
+ { .name = "sd4", },
+ { .name = "sd5", },
+ { .name = "sd6", },
+ { .name = "ldo0", },
+ { .name = "ldo1", },
+ { .name = "ldo2", },
+ { .name = "ldo3", },
+ { .name = "ldo4", },
+ { .name = "ldo5", },
+ { .name = "ldo6", },
+ { .name = "ldo7", },
+ { .name = "ldo9", },
+ { .name = "ldo10", },
+ { .name = "ldo11", },
+};
+
+static int as3722_get_regulator_dt_data(struct platform_device *pdev,
+ struct as3722_regulators *as3722_regs)
+{
+ struct device_node *np;
+ struct as3722_regulator_config_data *reg_config;
+ u32 prop;
+ int id;
+ int ret;
+
+ np = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
+ if (!np) {
+ dev_err(&pdev->dev, "Device is not having regulators node\n");
+ return -ENODEV;
+ }
+ pdev->dev.of_node = np;
+
+ ret = of_regulator_match(&pdev->dev, np, as3722_regulator_matches,
+ ARRAY_SIZE(as3722_regulator_matches));
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Parsing of regulator node failed: %d\n",
+ ret);
+ return ret;
+ }
+
+ for (id = 0; id < ARRAY_SIZE(as3722_regulator_matches); ++id) {
+ struct device_node *reg_node;
+
+ reg_config = &as3722_regs->reg_config_data[id];
+ reg_config->reg_init = as3722_regulator_matches[id].init_data;
+ reg_node = as3722_regulator_matches[id].of_node;
+
+ if (!reg_config->reg_init || !reg_node)
+ continue;
+
+ ret = of_property_read_u32(reg_node, "ams,ext-control", &prop);
+ if (!ret) {
+ if (prop < 3)
+ reg_config->ext_control = prop;
+ else
+ dev_warn(&pdev->dev,
+ "ext-control have invalid option: %u\n",
+ prop);
+ }
+ reg_config->enable_tracking =
+ of_property_read_bool(reg_node, "ams,enable-tracking");
+ }
+ return 0;
+}
+
+static int as3722_regulator_probe(struct platform_device *pdev)
+{
+ struct as3722 *as3722 = dev_get_drvdata(pdev->dev.parent);
+ struct as3722_regulators *as3722_regs;
+ struct as3722_regulator_config_data *reg_config;
+ struct regulator_dev *rdev;
+ struct regulator_config config = { };
+ struct regulator_ops *ops;
+ int id;
+ int ret;
+
+ as3722_regs = devm_kzalloc(&pdev->dev, sizeof(*as3722_regs),
+ GFP_KERNEL);
+ if (!as3722_regs)
+ return -ENOMEM;
+
+ as3722_regs->dev = &pdev->dev;
+ as3722_regs->as3722 = as3722;
+ platform_set_drvdata(pdev, as3722_regs);
+
+ ret = as3722_get_regulator_dt_data(pdev, as3722_regs);
+ if (ret < 0)
+ return ret;
+
+ config.dev = &pdev->dev;
+ config.driver_data = as3722_regs;
+ config.regmap = as3722->regmap;
+
+ for (id = 0; id < AS3722_REGULATOR_ID_MAX; id++) {
+ reg_config = &as3722_regs->reg_config_data[id];
+
+ as3722_regs->desc[id].name = as3722_reg_lookup[id].name;
+ as3722_regs->desc[id].supply_name = as3722_reg_lookup[id].sname;
+ as3722_regs->desc[id].id = as3722_reg_lookup[id].regulator_id;
+ as3722_regs->desc[id].n_voltages =
+ as3722_reg_lookup[id].n_voltages;
+ as3722_regs->desc[id].type = REGULATOR_VOLTAGE;
+ as3722_regs->desc[id].owner = THIS_MODULE;
+ as3722_regs->desc[id].enable_reg =
+ as3722_reg_lookup[id].enable_reg;
+ as3722_regs->desc[id].enable_mask =
+ as3722_reg_lookup[id].enable_mask;
+ as3722_regs->desc[id].vsel_reg = as3722_reg_lookup[id].vsel_reg;
+ as3722_regs->desc[id].vsel_mask =
+ as3722_reg_lookup[id].vsel_mask;
+ switch (id) {
+ case AS3722_REGULATOR_ID_LDO0:
+ if (reg_config->ext_control)
+ ops = &as3722_ldo0_extcntrl_ops;
+ else
+ ops = &as3722_ldo0_ops;
+ as3722_regs->desc[id].min_uV = 825000;
+ as3722_regs->desc[id].uV_step = 25000;
+ as3722_regs->desc[id].linear_min_sel = 1;
+ as3722_regs->desc[id].enable_time = 500;
+ break;
+ case AS3722_REGULATOR_ID_LDO3:
+ if (reg_config->ext_control)
+ ops = &as3722_ldo3_extcntrl_ops;
+ else
+ ops = &as3722_ldo3_ops;
+ as3722_regs->desc[id].min_uV = 620000;
+ as3722_regs->desc[id].uV_step = 20000;
+ as3722_regs->desc[id].linear_min_sel = 1;
+ as3722_regs->desc[id].enable_time = 500;
+ if (reg_config->enable_tracking) {
+ ret = as3722_ldo3_set_tracking_mode(as3722_regs,
+ id, AS3722_LDO3_MODE_PMOS_TRACKING);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "LDO3 tracking failed: %d\n",
+ ret);
+ return ret;
+ }
+ }
+ break;
+ case AS3722_REGULATOR_ID_SD0:
+ case AS3722_REGULATOR_ID_SD1:
+ case AS3722_REGULATOR_ID_SD6:
+ if (reg_config->ext_control)
+ ops = &as3722_sd016_extcntrl_ops;
+ else
+ ops = &as3722_sd016_ops;
+ as3722_regs->desc[id].min_uV = 610000;
+ as3722_regs->desc[id].uV_step = 10000;
+ as3722_regs->desc[id].linear_min_sel = 1;
+ break;
+ case AS3722_REGULATOR_ID_SD2:
+ case AS3722_REGULATOR_ID_SD3:
+ case AS3722_REGULATOR_ID_SD4:
+ case AS3722_REGULATOR_ID_SD5:
+ if (reg_config->ext_control)
+ ops = &as3722_sd2345_extcntrl_ops;
+ else
+ ops = &as3722_sd2345_ops;
+ as3722_regs->desc[id].linear_ranges =
+ as3722_sd2345_ranges;
+ as3722_regs->desc[id].n_linear_ranges =
+ ARRAY_SIZE(as3722_sd2345_ranges);
+ break;
+ default:
+ if (reg_config->ext_control)
+ ops = &as3722_ldo_extcntrl_ops;
+ else
+ ops = &as3722_ldo_ops;
+ as3722_regs->desc[id].min_uV = 825000;
+ as3722_regs->desc[id].uV_step = 25000;
+ as3722_regs->desc[id].linear_min_sel = 1;
+ as3722_regs->desc[id].enable_time = 500;
+ as3722_regs->desc[id].linear_ranges = as3722_ldo_ranges;
+ as3722_regs->desc[id].n_linear_ranges =
+ ARRAY_SIZE(as3722_ldo_ranges);
+ break;
+ }
+ as3722_regs->desc[id].ops = ops;
+ config.init_data = reg_config->reg_init;
+ config.of_node = as3722_regulator_matches[id].of_node;
+ rdev = devm_regulator_register(&pdev->dev,
+ &as3722_regs->desc[id], &config);
+ if (IS_ERR(rdev)) {
+ ret = PTR_ERR(rdev);
+ dev_err(&pdev->dev, "regulator %d register failed %d\n",
+ id, ret);
+ return ret;
+ }
+
+ as3722_regs->rdevs[id] = rdev;
+ if (reg_config->ext_control) {
+ ret = regulator_enable_regmap(rdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "Regulator %d enable failed: %d\n",
+ id, ret);
+ return ret;
+ }
+ ret = as3722_extreg_init(as3722_regs, id,
+ reg_config->ext_control);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "AS3722 ext control failed: %d", ret);
+ return ret;
+ }
+ }
+ }
+ return 0;
+}
+
+static const struct of_device_id of_as3722_regulator_match[] = {
+ { .compatible = "ams,as3722-regulator", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, of_as3722_regulator_match);
+
+static struct platform_driver as3722_regulator_driver = {
+ .driver = {
+ .name = "as3722-regulator",
+ .owner = THIS_MODULE,
+ .of_match_table = of_as3722_regulator_match,
+ },
+ .probe = as3722_regulator_probe,
+};
+
+module_platform_driver(as3722_regulator_driver);
+
+MODULE_ALIAS("platform:as3722-regulator");
+MODULE_DESCRIPTION("AS3722 regulator driver");
+MODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index a01b8b3b70ca..63330801c379 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -36,6 +36,7 @@
#include <trace/events/regulator.h>
#include "dummy.h"
+#include "internal.h"
#define rdev_crit(rdev, fmt, ...) \
pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
@@ -53,7 +54,6 @@ static LIST_HEAD(regulator_list);
static LIST_HEAD(regulator_map_list);
static LIST_HEAD(regulator_ena_gpio_list);
static bool has_full_constraints;
-static bool board_wants_dummy_regulator;
static struct dentry *debugfs_root;
@@ -82,25 +82,6 @@ struct regulator_enable_gpio {
unsigned int ena_gpio_invert:1;
};
-/*
- * struct regulator
- *
- * One for each consumer device.
- */
-struct regulator {
- struct device *dev;
- struct list_head list;
- unsigned int always_on:1;
- unsigned int bypass:1;
- int uA_load;
- int min_uV;
- int max_uV;
- char *supply_name;
- struct device_attribute dev_attr;
- struct regulator_dev *rdev;
- struct dentry *debugfs;
-};
-
static int _regulator_is_enabled(struct regulator_dev *rdev);
static int _regulator_disable(struct regulator_dev *rdev);
static int _regulator_get_voltage(struct regulator_dev *rdev);
@@ -923,6 +904,36 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
return 0;
}
+static int machine_constraints_current(struct regulator_dev *rdev,
+ struct regulation_constraints *constraints)
+{
+ struct regulator_ops *ops = rdev->desc->ops;
+ int ret;
+
+ if (!constraints->min_uA && !constraints->max_uA)
+ return 0;
+
+ if (constraints->min_uA > constraints->max_uA) {
+ rdev_err(rdev, "Invalid current constraints\n");
+ return -EINVAL;
+ }
+
+ if (!ops->set_current_limit || !ops->get_current_limit) {
+ rdev_warn(rdev, "Operation of current configuration missing\n");
+ return 0;
+ }
+
+ /* Set regulator current in constraints range */
+ ret = ops->set_current_limit(rdev, constraints->min_uA,
+ constraints->max_uA);
+ if (ret < 0) {
+ rdev_err(rdev, "Failed to set current constraint, %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
/**
* set_machine_constraints - sets regulator constraints
* @rdev: regulator source
@@ -953,6 +964,10 @@ static int set_machine_constraints(struct regulator_dev *rdev,
if (ret != 0)
goto out;
+ ret = machine_constraints_current(rdev, rdev->constraints);
+ if (ret != 0)
+ goto out;
+
/* do we need to setup our suspend state */
if (rdev->constraints->initial_state) {
ret = suspend_prepare(rdev, rdev->constraints->initial_state);
@@ -1186,6 +1201,8 @@ overflow_err:
static int _regulator_get_enable_time(struct regulator_dev *rdev)
{
+ if (rdev->constraints && rdev->constraints->enable_time)
+ return rdev->constraints->enable_time;
if (!rdev->desc->ops->enable_time)
return rdev->desc->enable_time;
return rdev->desc->ops->enable_time(rdev);
@@ -1243,16 +1260,16 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
/* Internal regulator request function */
static struct regulator *_regulator_get(struct device *dev, const char *id,
- bool exclusive)
+ bool exclusive, bool allow_dummy)
{
struct regulator_dev *rdev;
struct regulator *regulator = ERR_PTR(-EPROBE_DEFER);
const char *devname = NULL;
- int ret = 0;
+ int ret = -EPROBE_DEFER;
if (id == NULL) {
pr_err("get() with no identifier\n");
- return regulator;
+ return ERR_PTR(-EINVAL);
}
if (dev)
@@ -1264,34 +1281,37 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
if (rdev)
goto found;
+ regulator = ERR_PTR(ret);
+
/*
* If we have return value from dev_lookup fail, we do not expect to
* succeed, so, quit with appropriate error value
*/
- if (ret) {
- regulator = ERR_PTR(ret);
+ if (ret && ret != -ENODEV) {
goto out;
}
- if (board_wants_dummy_regulator) {
- rdev = dummy_regulator_rdev;
- goto found;
- }
-
-#ifdef CONFIG_REGULATOR_DUMMY
if (!devname)
devname = "deviceless";
- /* If the board didn't flag that it was fully constrained then
- * substitute in a dummy regulator so consumers can continue.
+ /*
+ * Assume that a regulator is physically present and enabled
+ * even if it isn't hooked up and just provide a dummy.
*/
- if (!has_full_constraints) {
- pr_warn("%s supply %s not found, using dummy regulator\n",
- devname, id);
+ if (has_full_constraints && allow_dummy) {
+ /*
+ * Log the substitution if regulator configuration is
+ * not complete to help development.
+ */
+ if (!has_full_constraints)
+ pr_warn("%s supply %s not found, using dummy regulator\n",
+ devname, id);
+
rdev = dummy_regulator_rdev;
goto found;
+ } else {
+ dev_err(dev, "dummy supplies not allowed\n");
}
-#endif
mutex_unlock(&regulator_list_mutex);
return regulator;
@@ -1349,44 +1369,10 @@ out:
*/
struct regulator *regulator_get(struct device *dev, const char *id)
{
- return _regulator_get(dev, id, false);
+ return _regulator_get(dev, id, false, true);
}
EXPORT_SYMBOL_GPL(regulator_get);
-static void devm_regulator_release(struct device *dev, void *res)
-{
- regulator_put(*(struct regulator **)res);
-}
-
-/**
- * devm_regulator_get - Resource managed regulator_get()
- * @dev: device for regulator "consumer"
- * @id: Supply name or regulator ID.
- *
- * Managed regulator_get(). Regulators returned from this function are
- * automatically regulator_put() on driver detach. See regulator_get() for more
- * information.
- */
-struct regulator *devm_regulator_get(struct device *dev, const char *id)
-{
- struct regulator **ptr, *regulator;
-
- ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
- if (!ptr)
- return ERR_PTR(-ENOMEM);
-
- regulator = regulator_get(dev, id);
- if (!IS_ERR(regulator)) {
- *ptr = regulator;
- devres_add(dev, ptr);
- } else {
- devres_free(ptr);
- }
-
- return regulator;
-}
-EXPORT_SYMBOL_GPL(devm_regulator_get);
-
/**
* regulator_get_exclusive - obtain exclusive access to a regulator.
* @dev: device for regulator "consumer"
@@ -1410,7 +1396,7 @@ EXPORT_SYMBOL_GPL(devm_regulator_get);
*/
struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
{
- return _regulator_get(dev, id, true);
+ return _regulator_get(dev, id, true, false);
}
EXPORT_SYMBOL_GPL(regulator_get_exclusive);
@@ -1439,40 +1425,10 @@ EXPORT_SYMBOL_GPL(regulator_get_exclusive);
*/
struct regulator *regulator_get_optional(struct device *dev, const char *id)
{
- return _regulator_get(dev, id, 0);
+ return _regulator_get(dev, id, false, false);
}
EXPORT_SYMBOL_GPL(regulator_get_optional);
-/**
- * devm_regulator_get_optional - Resource managed regulator_get_optional()
- * @dev: device for regulator "consumer"
- * @id: Supply name or regulator ID.
- *
- * Managed regulator_get_optional(). Regulators returned from this
- * function are automatically regulator_put() on driver detach. See
- * regulator_get_optional() for more information.
- */
-struct regulator *devm_regulator_get_optional(struct device *dev,
- const char *id)
-{
- struct regulator **ptr, *regulator;
-
- ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
- if (!ptr)
- return ERR_PTR(-ENOMEM);
-
- regulator = regulator_get_optional(dev, id);
- if (!IS_ERR(regulator)) {
- *ptr = regulator;
- devres_add(dev, ptr);
- } else {
- devres_free(ptr);
- }
-
- return regulator;
-}
-EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
-
/* Locks held by regulator_put() */
static void _regulator_put(struct regulator *regulator)
{
@@ -1499,36 +1455,6 @@ static void _regulator_put(struct regulator *regulator)
}
/**
- * devm_regulator_get_exclusive - Resource managed regulator_get_exclusive()
- * @dev: device for regulator "consumer"
- * @id: Supply name or regulator ID.
- *
- * Managed regulator_get_exclusive(). Regulators returned from this function
- * are automatically regulator_put() on driver detach. See regulator_get() for
- * more information.
- */
-struct regulator *devm_regulator_get_exclusive(struct device *dev,
- const char *id)
-{
- struct regulator **ptr, *regulator;
-
- ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
- if (!ptr)
- return ERR_PTR(-ENOMEM);
-
- regulator = _regulator_get(dev, id, 1);
- if (!IS_ERR(regulator)) {
- *ptr = regulator;
- devres_add(dev, ptr);
- } else {
- devres_free(ptr);
- }
-
- return regulator;
-}
-EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
-
-/**
* regulator_put - "free" the regulator source
* @regulator: regulator source
*
@@ -1544,35 +1470,6 @@ void regulator_put(struct regulator *regulator)
}
EXPORT_SYMBOL_GPL(regulator_put);
-static int devm_regulator_match(struct device *dev, void *res, void *data)
-{
- struct regulator **r = res;
- if (!r || !*r) {
- WARN_ON(!r || !*r);
- return 0;
- }
- return *r == data;
-}
-
-/**
- * devm_regulator_put - Resource managed regulator_put()
- * @regulator: regulator to free
- *
- * Deallocate a regulator allocated with devm_regulator_get(). Normally
- * this function will not need to be called and the resource management
- * code will ensure that the resource is freed.
- */
-void devm_regulator_put(struct regulator *regulator)
-{
- int rc;
-
- rc = devres_release(regulator->dev, devm_regulator_release,
- devm_regulator_match, regulator);
- if (rc != 0)
- WARN_ON(rc);
-}
-EXPORT_SYMBOL_GPL(devm_regulator_put);
-
/* Manage enable GPIO list. Same GPIO pin can be shared among regulators */
static int regulator_ena_gpio_request(struct regulator_dev *rdev,
const struct regulator_config *config)
@@ -1704,11 +1601,39 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
* together. */
trace_regulator_enable_delay(rdev_get_name(rdev));
- if (delay >= 1000) {
- mdelay(delay / 1000);
- udelay(delay % 1000);
- } else if (delay) {
- udelay(delay);
+ /*
+ * Delay for the requested amount of time as per the guidelines in:
+ *
+ * Documentation/timers/timers-howto.txt
+ *
+ * The assumption here is that regulators will never be enabled in
+ * atomic context and therefore sleeping functions can be used.
+ */
+ if (delay) {
+ unsigned int ms = delay / 1000;
+ unsigned int us = delay % 1000;
+
+ if (ms > 0) {
+ /*
+ * For small enough values, handle super-millisecond
+ * delays in the usleep_range() call below.
+ */
+ if (ms < 20)
+ us += ms * 1000;
+ else
+ msleep(ms);
+ }
+
+ /*
+ * Give the scheduler some room to coalesce with any other
+ * wakeup sources. For delays shorter than 10 us, don't even
+ * bother setting up high-resolution timers and just busy-
+ * loop.
+ */
+ if (us >= 10)
+ usleep_range(us, us + 100);
+ else
+ udelay(us);
}
trace_regulator_enable_complete(rdev_get_name(rdev));
@@ -2489,6 +2414,8 @@ static int _regulator_get_voltage(struct regulator_dev *rdev)
ret = rdev->desc->ops->get_voltage(rdev);
} else if (rdev->desc->ops->list_voltage) {
ret = rdev->desc->ops->list_voltage(rdev, 0);
+ } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) {
+ ret = rdev->desc->fixed_uV;
} else {
return -EINVAL;
}
@@ -2912,52 +2839,6 @@ err:
}
EXPORT_SYMBOL_GPL(regulator_bulk_get);
-/**
- * devm_regulator_bulk_get - managed get multiple regulator consumers
- *
- * @dev: Device to supply
- * @num_consumers: Number of consumers to register
- * @consumers: Configuration of consumers; clients are stored here.
- *
- * @return 0 on success, an errno on failure.
- *
- * This helper function allows drivers to get several regulator
- * consumers in one operation with management, the regulators will
- * automatically be freed when the device is unbound. If any of the
- * regulators cannot be acquired then any regulators that were
- * allocated will be freed before returning to the caller.
- */
-int devm_regulator_bulk_get(struct device *dev, int num_consumers,
- struct regulator_bulk_data *consumers)
-{
- int i;
- int ret;
-
- for (i = 0; i < num_consumers; i++)
- consumers[i].consumer = NULL;
-
- for (i = 0; i < num_consumers; i++) {
- consumers[i].consumer = devm_regulator_get(dev,
- consumers[i].supply);
- if (IS_ERR(consumers[i].consumer)) {
- ret = PTR_ERR(consumers[i].consumer);
- dev_err(dev, "Failed to get supply '%s': %d\n",
- consumers[i].supply, ret);
- consumers[i].consumer = NULL;
- goto err;
- }
- }
-
- return 0;
-
-err:
- for (i = 0; i < num_consumers && consumers[i].consumer; i++)
- devm_regulator_put(consumers[i].consumer);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
-
static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
{
struct regulator_bulk_data *bulk = data;
@@ -3170,7 +3051,8 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
/* some attributes need specific methods to be displayed */
if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) ||
(ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) ||
- (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0)) {
+ (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) ||
+ (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1))) {
status = device_create_file(dev, &dev_attr_microvolts);
if (status < 0)
return status;
@@ -3614,22 +3496,6 @@ void regulator_has_full_constraints(void)
EXPORT_SYMBOL_GPL(regulator_has_full_constraints);
/**
- * regulator_use_dummy_regulator - Provide a dummy regulator when none is found
- *
- * Calling this function will cause the regulator API to provide a
- * dummy regulator to consumers if no physical regulator is found,
- * allowing most consumers to proceed as though a regulator were
- * configured. This allows systems such as those with software
- * controllable regulators for the CPU core only to be brought up more
- * readily.
- */
-void regulator_use_dummy_regulator(void)
-{
- board_wants_dummy_regulator = true;
-}
-EXPORT_SYMBOL_GPL(regulator_use_dummy_regulator);
-
-/**
* rdev_get_drvdata - get rdev regulator driver data
* @rdev: regulator
*
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
index f06854cf8cf5..c61d96e9d925 100644
--- a/drivers/regulator/da903x.c
+++ b/drivers/regulator/da903x.c
@@ -463,7 +463,7 @@ static int da903x_regulator_probe(struct platform_device *pdev)
config.init_data = dev_get_platdata(&pdev->dev);
config.driver_data = ri;
- rdev = regulator_register(&ri->desc, &config);
+ rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
ri->desc.name);
@@ -474,21 +474,12 @@ static int da903x_regulator_probe(struct platform_device *pdev)
return 0;
}
-static int da903x_regulator_remove(struct platform_device *pdev)
-{
- struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
- regulator_unregister(rdev);
- return 0;
-}
-
static struct platform_driver da903x_regulator_driver = {
.driver = {
.name = "da903x-regulator",
.owner = THIS_MODULE,
},
.probe = da903x_regulator_probe,
- .remove = da903x_regulator_remove,
};
static int __init da903x_regulator_init(void)
diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c
index 1e4d483f6163..c427e42472e8 100644
--- a/drivers/regulator/da9052-regulator.c
+++ b/drivers/regulator/da9052-regulator.c
@@ -389,8 +389,9 @@ static int da9052_regulator_probe(struct platform_device *pdev)
#endif
}
- regulator->rdev = regulator_register(&regulator->info->reg_desc,
- &config);
+ regulator->rdev = devm_regulator_register(&pdev->dev,
+ &regulator->info->reg_desc,
+ &config);
if (IS_ERR(regulator->rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
regulator->info->reg_desc.name);
@@ -402,17 +403,8 @@ static int da9052_regulator_probe(struct platform_device *pdev)
return 0;
}
-static int da9052_regulator_remove(struct platform_device *pdev)
-{
- struct da9052_regulator *regulator = platform_get_drvdata(pdev);
-
- regulator_unregister(regulator->rdev);
- return 0;
-}
-
static struct platform_driver da9052_regulator_driver = {
.probe = da9052_regulator_probe,
- .remove = da9052_regulator_remove,
.driver = {
.name = "da9052-regulator",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c
index 77b53e5a231c..7f340206d329 100644
--- a/drivers/regulator/da9055-regulator.c
+++ b/drivers/regulator/da9055-regulator.c
@@ -564,13 +564,13 @@ static int da9055_regulator_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
- regulator->rdev = regulator_register(&regulator->info->reg_desc,
- &config);
+ regulator->rdev = devm_regulator_register(&pdev->dev,
+ &regulator->info->reg_desc,
+ &config);
if (IS_ERR(regulator->rdev)) {
dev_err(&pdev->dev, "Failed to register regulator %s\n",
regulator->info->reg_desc.name);
- ret = PTR_ERR(regulator->rdev);
- return ret;
+ return PTR_ERR(regulator->rdev);
}
/* Only LDO 5 and 6 has got the over current interrupt */
@@ -588,7 +588,7 @@ static int da9055_regulator_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"Failed to request Regulator IRQ %d: %d\n",
irq, ret);
- goto err_regulator;
+ return ret;
}
}
}
@@ -596,24 +596,10 @@ static int da9055_regulator_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, regulator);
return 0;
-
-err_regulator:
- regulator_unregister(regulator->rdev);
- return ret;
-}
-
-static int da9055_regulator_remove(struct platform_device *pdev)
-{
- struct da9055_regulator *regulator = platform_get_drvdata(pdev);
-
- regulator_unregister(regulator->rdev);
-
- return 0;
}
static struct platform_driver da9055_regulator_driver = {
.probe = da9055_regulator_probe,
- .remove = da9055_regulator_remove,
.driver = {
.name = "da9055-regulator",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c
index 1a7816390773..3d910f4f3a0e 100644
--- a/drivers/regulator/da9063-regulator.c
+++ b/drivers/regulator/da9063-regulator.c
@@ -709,7 +709,7 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
struct of_regulator_match **da9063_reg_matches)
{
da9063_reg_matches = NULL;
- return PTR_ERR(-ENODEV);
+ return ERR_PTR(-ENODEV);
}
#endif
@@ -717,7 +717,7 @@ static int da9063_regulator_probe(struct platform_device *pdev)
{
struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
struct da9063_pdata *da9063_pdata = dev_get_platdata(da9063->dev);
- struct of_regulator_match *da9063_reg_matches;
+ struct of_regulator_match *da9063_reg_matches = NULL;
struct da9063_regulators_pdata *regl_pdata;
const struct da9063_dev_model *model;
struct da9063_regulators *regulators;
diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c
new file mode 100644
index 000000000000..2672a029fa25
--- /dev/null
+++ b/drivers/regulator/devres.c
@@ -0,0 +1,252 @@
+/*
+ * devres.c -- Voltage/Current Regulator framework devres implementation.
+ *
+ * Copyright 2013 Linaro Ltd
+ *
+ * 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 <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/module.h>
+
+#include "internal.h"
+
+enum {
+ NORMAL_GET,
+ EXCLUSIVE_GET,
+ OPTIONAL_GET,
+};
+
+static void devm_regulator_release(struct device *dev, void *res)
+{
+ regulator_put(*(struct regulator **)res);
+}
+
+static struct regulator *_devm_regulator_get(struct device *dev, const char *id,
+ int get_type)
+{
+ struct regulator **ptr, *regulator;
+
+ ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ switch (get_type) {
+ case NORMAL_GET:
+ regulator = regulator_get(dev, id);
+ break;
+ case EXCLUSIVE_GET:
+ regulator = regulator_get_exclusive(dev, id);
+ break;
+ case OPTIONAL_GET:
+ regulator = regulator_get_optional(dev, id);
+ break;
+ default:
+ regulator = ERR_PTR(-EINVAL);
+ }
+
+ if (!IS_ERR(regulator)) {
+ *ptr = regulator;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return regulator;
+}
+
+/**
+ * devm_regulator_get - Resource managed regulator_get()
+ * @dev: device for regulator "consumer"
+ * @id: Supply name or regulator ID.
+ *
+ * Managed regulator_get(). Regulators returned from this function are
+ * automatically regulator_put() on driver detach. See regulator_get() for more
+ * information.
+ */
+struct regulator *devm_regulator_get(struct device *dev, const char *id)
+{
+ return _devm_regulator_get(dev, id, NORMAL_GET);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_get);
+
+/**
+ * devm_regulator_get_exclusive - Resource managed regulator_get_exclusive()
+ * @dev: device for regulator "consumer"
+ * @id: Supply name or regulator ID.
+ *
+ * Managed regulator_get_exclusive(). Regulators returned from this function
+ * are automatically regulator_put() on driver detach. See regulator_get() for
+ * more information.
+ */
+struct regulator *devm_regulator_get_exclusive(struct device *dev,
+ const char *id)
+{
+ return _devm_regulator_get(dev, id, EXCLUSIVE_GET);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
+
+/**
+ * devm_regulator_get_optional - Resource managed regulator_get_optional()
+ * @dev: device for regulator "consumer"
+ * @id: Supply name or regulator ID.
+ *
+ * Managed regulator_get_optional(). Regulators returned from this
+ * function are automatically regulator_put() on driver detach. See
+ * regulator_get_optional() for more information.
+ */
+struct regulator *devm_regulator_get_optional(struct device *dev,
+ const char *id)
+{
+ return _devm_regulator_get(dev, id, OPTIONAL_GET);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
+
+static int devm_regulator_match(struct device *dev, void *res, void *data)
+{
+ struct regulator **r = res;
+ if (!r || !*r) {
+ WARN_ON(!r || !*r);
+ return 0;
+ }
+ return *r == data;
+}
+
+/**
+ * devm_regulator_put - Resource managed regulator_put()
+ * @regulator: regulator to free
+ *
+ * Deallocate a regulator allocated with devm_regulator_get(). Normally
+ * this function will not need to be called and the resource management
+ * code will ensure that the resource is freed.
+ */
+void devm_regulator_put(struct regulator *regulator)
+{
+ int rc;
+
+ rc = devres_release(regulator->dev, devm_regulator_release,
+ devm_regulator_match, regulator);
+ if (rc != 0)
+ WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_put);
+
+/**
+ * devm_regulator_bulk_get - managed get multiple regulator consumers
+ *
+ * @dev: Device to supply
+ * @num_consumers: Number of consumers to register
+ * @consumers: Configuration of consumers; clients are stored here.
+ *
+ * @return 0 on success, an errno on failure.
+ *
+ * This helper function allows drivers to get several regulator
+ * consumers in one operation with management, the regulators will
+ * automatically be freed when the device is unbound. If any of the
+ * regulators cannot be acquired then any regulators that were
+ * allocated will be freed before returning to the caller.
+ */
+int devm_regulator_bulk_get(struct device *dev, int num_consumers,
+ struct regulator_bulk_data *consumers)
+{
+ int i;
+ int ret;
+
+ for (i = 0; i < num_consumers; i++)
+ consumers[i].consumer = NULL;
+
+ for (i = 0; i < num_consumers; i++) {
+ consumers[i].consumer = devm_regulator_get(dev,
+ consumers[i].supply);
+ if (IS_ERR(consumers[i].consumer)) {
+ ret = PTR_ERR(consumers[i].consumer);
+ dev_err(dev, "Failed to get supply '%s': %d\n",
+ consumers[i].supply, ret);
+ consumers[i].consumer = NULL;
+ goto err;
+ }
+ }
+
+ return 0;
+
+err:
+ for (i = 0; i < num_consumers && consumers[i].consumer; i++)
+ devm_regulator_put(consumers[i].consumer);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
+
+static void devm_rdev_release(struct device *dev, void *res)
+{
+ regulator_unregister(*(struct regulator_dev **)res);
+}
+
+/**
+ * devm_regulator_register - Resource managed regulator_register()
+ * @regulator_desc: regulator to register
+ * @config: runtime configuration for regulator
+ *
+ * Called by regulator drivers to register a regulator. Returns a
+ * valid pointer to struct regulator_dev on success or an ERR_PTR() on
+ * error. The regulator will automatically be released when the device
+ * is unbound.
+ */
+struct regulator_dev *devm_regulator_register(struct device *dev,
+ const struct regulator_desc *regulator_desc,
+ const struct regulator_config *config)
+{
+ struct regulator_dev **ptr, *rdev;
+
+ ptr = devres_alloc(devm_rdev_release, sizeof(*ptr),
+ GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ rdev = regulator_register(regulator_desc, config);
+ if (!IS_ERR(rdev)) {
+ *ptr = rdev;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return rdev;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_register);
+
+static int devm_rdev_match(struct device *dev, void *res, void *data)
+{
+ struct regulator_dev **r = res;
+ if (!r || !*r) {
+ WARN_ON(!r || !*r);
+ return 0;
+ }
+ return *r == data;
+}
+
+/**
+ * devm_regulator_unregister - Resource managed regulator_unregister()
+ * @regulator: regulator to free
+ *
+ * Unregister a regulator registered with devm_regulator_register().
+ * Normally this function will not need to be called and the resource
+ * management code will ensure that the resource is freed.
+ */
+void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev)
+{
+ int rc;
+
+ rc = devres_release(dev, devm_rdev_release, devm_rdev_match, rdev);
+ if (rc != 0)
+ WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_unregister);
diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
index 70b7220c587f..7ca3d9e3b0fe 100644
--- a/drivers/regulator/fan53555.c
+++ b/drivers/regulator/fan53555.c
@@ -218,9 +218,8 @@ static int fan53555_regulator_register(struct fan53555_device_info *di,
rdesc->vsel_mask = VSEL_NSEL_MASK;
rdesc->owner = THIS_MODULE;
- di->rdev = regulator_register(&di->desc, config);
+ di->rdev = devm_regulator_register(di->dev, &di->desc, config);
return PTR_ERR_OR_ZERO(di->rdev);
-
}
static struct regmap_config fan53555_regmap_config = {
@@ -291,14 +290,6 @@ static int fan53555_regulator_probe(struct i2c_client *client,
}
-static int fan53555_regulator_remove(struct i2c_client *client)
-{
- struct fan53555_device_info *di = i2c_get_clientdata(client);
-
- regulator_unregister(di->rdev);
- return 0;
-}
-
static const struct i2c_device_id fan53555_id[] = {
{"fan53555", -1},
{ },
@@ -309,7 +300,6 @@ static struct i2c_driver fan53555_regulator_driver = {
.name = "fan53555-regulator",
},
.probe = fan53555_regulator_probe,
- .remove = fan53555_regulator_remove,
.id_table = fan53555_id,
};
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index 7610920014d7..de811f3b921b 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -34,7 +34,6 @@
struct fixed_voltage_data {
struct regulator_desc desc;
struct regulator_dev *dev;
- int microvolts;
};
@@ -108,30 +107,7 @@ of_get_fixed_voltage_config(struct device *dev)
return config;
}
-static int fixed_voltage_get_voltage(struct regulator_dev *dev)
-{
- struct fixed_voltage_data *data = rdev_get_drvdata(dev);
-
- if (data->microvolts)
- return data->microvolts;
- else
- return -EINVAL;
-}
-
-static int fixed_voltage_list_voltage(struct regulator_dev *dev,
- unsigned selector)
-{
- struct fixed_voltage_data *data = rdev_get_drvdata(dev);
-
- if (selector != 0)
- return -EINVAL;
-
- return data->microvolts;
-}
-
static struct regulator_ops fixed_voltage_ops = {
- .get_voltage = fixed_voltage_get_voltage,
- .list_voltage = fixed_voltage_list_voltage,
};
static int reg_fixed_voltage_probe(struct platform_device *pdev)
@@ -186,7 +162,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
if (config->microvolts)
drvdata->desc.n_voltages = 1;
- drvdata->microvolts = config->microvolts;
+ drvdata->desc.fixed_uV = config->microvolts;
if (config->gpio >= 0)
cfg.ena_gpio = config->gpio;
@@ -222,7 +198,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, drvdata);
dev_dbg(&pdev->dev, "%s supplying %duV\n", drvdata->desc.name,
- drvdata->microvolts);
+ drvdata->desc.fixed_uV);
return 0;
diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h
new file mode 100644
index 000000000000..84bbda10c396
--- /dev/null
+++ b/drivers/regulator/internal.h
@@ -0,0 +1,38 @@
+/*
+ * internal.h -- Voltage/Current Regulator framework internal code
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ * Copyright 2008 SlimLogic Ltd.
+ *
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __REGULATOR_INTERNAL_H
+#define __REGULATOR_INTERNAL_H
+
+/*
+ * struct regulator
+ *
+ * One for each consumer device.
+ */
+struct regulator {
+ struct device *dev;
+ struct list_head list;
+ unsigned int always_on:1;
+ unsigned int bypass:1;
+ int uA_load;
+ int min_uV;
+ int max_uV;
+ char *supply_name;
+ struct device_attribute dev_attr;
+ struct regulator_dev *rdev;
+ struct dentry *debugfs;
+};
+
+#endif
diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c
index 88c1a3acf563..6e5da95fa025 100644
--- a/drivers/regulator/isl6271a-regulator.c
+++ b/drivers/regulator/isl6271a-regulator.c
@@ -112,7 +112,7 @@ static int isl6271a_probe(struct i2c_client *i2c,
struct regulator_config config = { };
struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev);
struct isl_pmic *pmic;
- int err, i;
+ int i;
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EIO;
@@ -133,32 +133,17 @@ static int isl6271a_probe(struct i2c_client *i2c,
config.init_data = NULL;
config.driver_data = pmic;
- pmic->rdev[i] = regulator_register(&isl_rd[i], &config);
+ pmic->rdev[i] = devm_regulator_register(&i2c->dev, &isl_rd[i],
+ &config);
if (IS_ERR(pmic->rdev[i])) {
dev_err(&i2c->dev, "failed to register %s\n", id->name);
- err = PTR_ERR(pmic->rdev[i]);
- goto error;
+ return PTR_ERR(pmic->rdev[i]);
}
}
i2c_set_clientdata(i2c, pmic);
return 0;
-
-error:
- while (--i >= 0)
- regulator_unregister(pmic->rdev[i]);
- return err;
-}
-
-static int isl6271a_remove(struct i2c_client *i2c)
-{
- struct isl_pmic *pmic = i2c_get_clientdata(i2c);
- int i;
-
- for (i = 0; i < 3; i++)
- regulator_unregister(pmic->rdev[i]);
- return 0;
}
static const struct i2c_device_id isl6271a_id[] = {
@@ -174,7 +159,6 @@ static struct i2c_driver isl6271a_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = isl6271a_probe,
- .remove = isl6271a_remove,
.id_table = isl6271a_id,
};
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
index 3a599ee0a456..e242dd316d36 100644
--- a/drivers/regulator/max1586.c
+++ b/drivers/regulator/max1586.c
@@ -166,7 +166,7 @@ static int max1586_pmic_probe(struct i2c_client *client,
struct max1586_platform_data *pdata = dev_get_platdata(&client->dev);
struct regulator_config config = { };
struct max1586_data *max1586;
- int i, id, ret = -ENOMEM;
+ int i, id;
max1586 = devm_kzalloc(&client->dev, sizeof(struct max1586_data) +
sizeof(struct regulator_dev *) * (MAX1586_V6 + 1),
@@ -193,7 +193,7 @@ static int max1586_pmic_probe(struct i2c_client *client,
continue;
if (id < MAX1586_V3 || id > MAX1586_V6) {
dev_err(&client->dev, "invalid regulator id %d\n", id);
- goto err;
+ return -EINVAL;
}
if (id == MAX1586_V3) {
@@ -207,33 +207,18 @@ static int max1586_pmic_probe(struct i2c_client *client,
config.init_data = pdata->subdevs[i].platform_data;
config.driver_data = max1586;
- rdev[i] = regulator_register(&max1586_reg[id], &config);
+ rdev[i] = devm_regulator_register(&client->dev,
+ &max1586_reg[id], &config);
if (IS_ERR(rdev[i])) {
- ret = PTR_ERR(rdev[i]);
dev_err(&client->dev, "failed to register %s\n",
max1586_reg[id].name);
- goto err;
+ return PTR_ERR(rdev[i]);
}
}
i2c_set_clientdata(client, max1586);
dev_info(&client->dev, "Maxim 1586 regulator driver loaded\n");
return 0;
-
-err:
- while (--i >= 0)
- regulator_unregister(rdev[i]);
- return ret;
-}
-
-static int max1586_pmic_remove(struct i2c_client *client)
-{
- struct max1586_data *max1586 = i2c_get_clientdata(client);
- int i;
-
- for (i = 0; i <= MAX1586_V6; i++)
- regulator_unregister(max1586->rdev[i]);
- return 0;
}
static const struct i2c_device_id max1586_id[] = {
@@ -244,7 +229,6 @@ MODULE_DEVICE_TABLE(i2c, max1586_id);
static struct i2c_driver max1586_pmic_driver = {
.probe = max1586_pmic_probe,
- .remove = max1586_pmic_remove,
.driver = {
.name = "max1586",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c
index f563057e5690..ae001ccf26f4 100644
--- a/drivers/regulator/max77686.c
+++ b/drivers/regulator/max77686.c
@@ -478,32 +478,16 @@ static int max77686_pmic_probe(struct platform_device *pdev)
config.of_node = pdata->regulators[i].of_node;
max77686->opmode[i] = regulators[i].enable_mask;
- max77686->rdev[i] = regulator_register(&regulators[i], &config);
+ max77686->rdev[i] = devm_regulator_register(&pdev->dev,
+ &regulators[i], &config);
if (IS_ERR(max77686->rdev[i])) {
- ret = PTR_ERR(max77686->rdev[i]);
dev_err(&pdev->dev,
"regulator init failed for %d\n", i);
- max77686->rdev[i] = NULL;
- goto err;
+ return PTR_ERR(max77686->rdev[i]);
}
}
return 0;
-err:
- while (--i >= 0)
- regulator_unregister(max77686->rdev[i]);
- return ret;
-}
-
-static int max77686_pmic_remove(struct platform_device *pdev)
-{
- struct max77686_data *max77686 = platform_get_drvdata(pdev);
- int i;
-
- for (i = 0; i < MAX77686_REGULATORS; i++)
- regulator_unregister(max77686->rdev[i]);
-
- return 0;
}
static const struct platform_device_id max77686_pmic_id[] = {
@@ -518,7 +502,6 @@ static struct platform_driver max77686_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = max77686_pmic_probe,
- .remove = max77686_pmic_remove,
.id_table = max77686_pmic_id,
};
diff --git a/drivers/regulator/max77693.c b/drivers/regulator/max77693.c
index ce4b96c15eba..feb20bf4ccab 100644
--- a/drivers/regulator/max77693.c
+++ b/drivers/regulator/max77693.c
@@ -230,7 +230,7 @@ static int max77693_pmic_probe(struct platform_device *pdev)
struct max77693_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct max77693_pmic_dev *max77693_pmic;
struct max77693_regulator_data *rdata = NULL;
- int num_rdata, i, ret;
+ int num_rdata, i;
struct regulator_config config;
num_rdata = max77693_pmic_init_rdata(&pdev->dev, &rdata);
@@ -266,36 +266,16 @@ static int max77693_pmic_probe(struct platform_device *pdev)
config.init_data = rdata[i].initdata;
config.of_node = rdata[i].of_node;
- max77693_pmic->rdev[i] = regulator_register(&regulators[id],
- &config);
+ max77693_pmic->rdev[i] = devm_regulator_register(&pdev->dev,
+ &regulators[id], &config);
if (IS_ERR(max77693_pmic->rdev[i])) {
- ret = PTR_ERR(max77693_pmic->rdev[i]);
dev_err(max77693_pmic->dev,
"Failed to initialize regulator-%d\n", id);
- max77693_pmic->rdev[i] = NULL;
- goto err;
+ return PTR_ERR(max77693_pmic->rdev[i]);
}
}
return 0;
- err:
- while (--i >= 0)
- regulator_unregister(max77693_pmic->rdev[i]);
-
- return ret;
-}
-
-static int max77693_pmic_remove(struct platform_device *pdev)
-{
- struct max77693_pmic_dev *max77693_pmic = platform_get_drvdata(pdev);
- struct regulator_dev **rdev = max77693_pmic->rdev;
- int i;
-
- for (i = 0; i < max77693_pmic->num_regulators; i++)
- if (rdev[i])
- regulator_unregister(rdev[i]);
-
- return 0;
}
static const struct platform_device_id max77693_pmic_id[] = {
@@ -311,7 +291,6 @@ static struct platform_driver max77693_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = max77693_pmic_probe,
- .remove = max77693_pmic_remove,
.id_table = max77693_pmic_id,
};
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index 19c6f08eafd5..7f049c92ee52 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -234,7 +234,8 @@ static int max8649_regulator_probe(struct i2c_client *client,
config.driver_data = info;
config.regmap = info->regmap;
- info->regulator = regulator_register(&dcdc_desc, &config);
+ info->regulator = devm_regulator_register(&client->dev, &dcdc_desc,
+ &config);
if (IS_ERR(info->regulator)) {
dev_err(info->dev, "failed to register regulator %s\n",
dcdc_desc.name);
@@ -244,16 +245,6 @@ static int max8649_regulator_probe(struct i2c_client *client,
return 0;
}
-static int max8649_regulator_remove(struct i2c_client *client)
-{
- struct max8649_regulator_info *info = i2c_get_clientdata(client);
-
- if (info)
- regulator_unregister(info->regulator);
-
- return 0;
-}
-
static const struct i2c_device_id max8649_id[] = {
{ "max8649", 0 },
{ }
@@ -262,7 +253,6 @@ MODULE_DEVICE_TABLE(i2c, max8649_id);
static struct i2c_driver max8649_driver = {
.probe = max8649_regulator_probe,
- .remove = max8649_regulator_remove,
.driver = {
.name = "max8649",
},
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
index 144bcacd734d..8d94d3d7f97f 100644
--- a/drivers/regulator/max8660.c
+++ b/drivers/regulator/max8660.c
@@ -439,7 +439,7 @@ static int max8660_probe(struct i2c_client *client,
for (i = 0; i < pdata->num_subdevs; i++) {
if (!pdata->subdevs[i].platform_data)
- goto err_out;
+ return ret;
boot_on = pdata->subdevs[i].platform_data->constraints.boot_on;
@@ -465,7 +465,7 @@ static int max8660_probe(struct i2c_client *client,
case MAX8660_V7:
if (type == MAX8661) {
dev_err(dev, "Regulator not on this chip!\n");
- goto err_out;
+ return -EINVAL;
}
if (boot_on)
@@ -475,7 +475,7 @@ static int max8660_probe(struct i2c_client *client,
default:
dev_err(dev, "invalid regulator %s\n",
pdata->subdevs[i].name);
- goto err_out;
+ return ret;
}
}
@@ -489,33 +489,18 @@ static int max8660_probe(struct i2c_client *client,
config.of_node = of_node[i];
config.driver_data = max8660;
- rdev[i] = regulator_register(&max8660_reg[id], &config);
+ rdev[i] = devm_regulator_register(&client->dev,
+ &max8660_reg[id], &config);
if (IS_ERR(rdev[i])) {
ret = PTR_ERR(rdev[i]);
- dev_err(dev, "failed to register %s\n",
+ dev_err(&client->dev, "failed to register %s\n",
max8660_reg[id].name);
- goto err_unregister;
+ return PTR_ERR(rdev[i]);
}
}
i2c_set_clientdata(client, max8660);
return 0;
-
-err_unregister:
- while (--i >= 0)
- regulator_unregister(rdev[i]);
-err_out:
- return ret;
-}
-
-static int max8660_remove(struct i2c_client *client)
-{
- struct max8660 *max8660 = i2c_get_clientdata(client);
- int i;
-
- for (i = 0; i < MAX8660_V_END; i++)
- regulator_unregister(max8660->rdev[i]);
- return 0;
}
static const struct i2c_device_id max8660_id[] = {
@@ -527,7 +512,6 @@ MODULE_DEVICE_TABLE(i2c, max8660_id);
static struct i2c_driver max8660_driver = {
.probe = max8660_probe,
- .remove = max8660_remove,
.driver = {
.name = "max8660",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c
index 4568c15fa78d..0c5fe6c6ac26 100644
--- a/drivers/regulator/max8907-regulator.c
+++ b/drivers/regulator/max8907-regulator.c
@@ -350,33 +350,17 @@ static int max8907_regulator_probe(struct platform_device *pdev)
pmic->desc[i].ops = &max8907_out5v_hwctl_ops;
}
- pmic->rdev[i] = regulator_register(&pmic->desc[i], &config);
+ pmic->rdev[i] = devm_regulator_register(&pdev->dev,
+ &pmic->desc[i], &config);
if (IS_ERR(pmic->rdev[i])) {
dev_err(&pdev->dev,
"failed to register %s regulator\n",
pmic->desc[i].name);
- ret = PTR_ERR(pmic->rdev[i]);
- goto err_unregister_regulator;
+ return PTR_ERR(pmic->rdev[i]);
}
}
return 0;
-
-err_unregister_regulator:
- while (--i >= 0)
- regulator_unregister(pmic->rdev[i]);
- return ret;
-}
-
-static int max8907_regulator_remove(struct platform_device *pdev)
-{
- struct max8907_regulator *pmic = platform_get_drvdata(pdev);
- int i;
-
- for (i = 0; i < MAX8907_NUM_REGULATORS; i++)
- regulator_unregister(pmic->rdev[i]);
-
- return 0;
}
static struct platform_driver max8907_regulator_driver = {
@@ -385,7 +369,6 @@ static struct platform_driver max8907_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = max8907_regulator_probe,
- .remove = max8907_regulator_remove,
};
static int __init max8907_regulator_init(void)
diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c
index 5b77ab7762e4..892aa1e5b96c 100644
--- a/drivers/regulator/max8973-regulator.c
+++ b/drivers/regulator/max8973-regulator.c
@@ -467,7 +467,7 @@ static int max8973_probe(struct i2c_client *client,
config.regmap = max->regmap;
/* Register the regulators */
- rdev = regulator_register(&max->desc, &config);
+ rdev = devm_regulator_register(&client->dev, &max->desc, &config);
if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev);
dev_err(max->dev, "regulator register failed, err %d\n", ret);
@@ -478,14 +478,6 @@ static int max8973_probe(struct i2c_client *client,
return 0;
}
-static int max8973_remove(struct i2c_client *client)
-{
- struct max8973_chip *max = i2c_get_clientdata(client);
-
- regulator_unregister(max->rdev);
- return 0;
-}
-
static const struct i2c_device_id max8973_id[] = {
{.name = "max8973",},
{},
@@ -499,7 +491,6 @@ static struct i2c_driver max8973_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = max8973_probe,
- .remove = max8973_remove,
.id_table = max8973_id,
};
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
index df20069f0537..bcd2488d1252 100644
--- a/drivers/regulator/max8997.c
+++ b/drivers/regulator/max8997.c
@@ -1081,7 +1081,7 @@ static int max8997_pmic_probe(struct platform_device *pdev)
pdata->buck1_voltage[i] +
buck1245_voltage_map_desc.step);
if (ret < 0)
- goto err_out;
+ return ret;
max8997->buck2_vol[i] = ret =
max8997_get_voltage_proper_val(
@@ -1090,7 +1090,7 @@ static int max8997_pmic_probe(struct platform_device *pdev)
pdata->buck2_voltage[i] +
buck1245_voltage_map_desc.step);
if (ret < 0)
- goto err_out;
+ return ret;
max8997->buck5_vol[i] = ret =
max8997_get_voltage_proper_val(
@@ -1099,7 +1099,7 @@ static int max8997_pmic_probe(struct platform_device *pdev)
pdata->buck5_voltage[i] +
buck1245_voltage_map_desc.step);
if (ret < 0)
- goto err_out;
+ return ret;
if (max_buck1 < max8997->buck1_vol[i])
max_buck1 = max8997->buck1_vol[i];
@@ -1143,24 +1143,23 @@ static int max8997_pmic_probe(struct platform_device *pdev)
!gpio_is_valid(pdata->buck125_gpios[1]) ||
!gpio_is_valid(pdata->buck125_gpios[2])) {
dev_err(&pdev->dev, "GPIO NOT VALID\n");
- ret = -EINVAL;
- goto err_out;
+ return -EINVAL;
}
ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[0],
"MAX8997 SET1");
if (ret)
- goto err_out;
+ return ret;
ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[1],
"MAX8997 SET2");
if (ret)
- goto err_out;
+ return ret;
ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[2],
"MAX8997 SET3");
if (ret)
- goto err_out;
+ return ret;
gpio_direction_output(pdata->buck125_gpios[0],
(max8997->buck125_gpioindex >> 2)
@@ -1205,33 +1204,16 @@ static int max8997_pmic_probe(struct platform_device *pdev)
config.driver_data = max8997;
config.of_node = pdata->regulators[i].reg_node;
- rdev[i] = regulator_register(&regulators[id], &config);
+ rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id],
+ &config);
if (IS_ERR(rdev[i])) {
- ret = PTR_ERR(rdev[i]);
dev_err(max8997->dev, "regulator init failed for %d\n",
id);
- rdev[i] = NULL;
- goto err;
+ return PTR_ERR(rdev[i]);
}
}
return 0;
-err:
- while (--i >= 0)
- regulator_unregister(rdev[i]);
-err_out:
- return ret;
-}
-
-static int max8997_pmic_remove(struct platform_device *pdev)
-{
- struct max8997_data *max8997 = platform_get_drvdata(pdev);
- struct regulator_dev **rdev = max8997->rdev;
- int i;
-
- for (i = 0; i < max8997->num_regulators; i++)
- regulator_unregister(rdev[i]);
- return 0;
}
static const struct platform_device_id max8997_pmic_id[] = {
@@ -1246,7 +1228,6 @@ static struct platform_driver max8997_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = max8997_pmic_probe,
- .remove = max8997_pmic_remove,
.id_table = max8997_pmic_id,
};
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c
index a4c53b2d1aaf..ae3f0656feb0 100644
--- a/drivers/regulator/max8998.c
+++ b/drivers/regulator/max8998.c
@@ -790,16 +790,14 @@ static int max8998_pmic_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"MAX8998 SET1 GPIO defined as 0 !\n");
WARN_ON(!pdata->buck1_set1);
- ret = -EIO;
- goto err_out;
+ return -EIO;
}
/* Check if SET2 is not equal to 0 */
if (!pdata->buck1_set2) {
dev_err(&pdev->dev,
"MAX8998 SET2 GPIO defined as 0 !\n");
WARN_ON(!pdata->buck1_set2);
- ret = -EIO;
- goto err_out;
+ return -EIO;
}
gpio_request(pdata->buck1_set1, "MAX8998 BUCK1_SET1");
@@ -823,7 +821,7 @@ static int max8998_pmic_probe(struct platform_device *pdev)
ret = max8998_write_reg(i2c,
MAX8998_REG_BUCK1_VOLTAGE1 + v, i);
if (ret)
- goto err_out;
+ return ret;
}
}
@@ -833,8 +831,7 @@ static int max8998_pmic_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"MAX8998 SET3 GPIO defined as 0 !\n");
WARN_ON(!pdata->buck2_set3);
- ret = -EIO;
- goto err_out;
+ return -EIO;
}
gpio_request(pdata->buck2_set3, "MAX8998 BUCK2_SET3");
gpio_direction_output(pdata->buck2_set3,
@@ -852,7 +849,7 @@ static int max8998_pmic_probe(struct platform_device *pdev)
ret = max8998_write_reg(i2c,
MAX8998_REG_BUCK2_VOLTAGE1 + v, i);
if (ret)
- goto err_out;
+ return ret;
}
}
@@ -875,34 +872,19 @@ static int max8998_pmic_probe(struct platform_device *pdev)
config.init_data = pdata->regulators[i].initdata;
config.driver_data = max8998;
- rdev[i] = regulator_register(&regulators[index], &config);
+ rdev[i] = devm_regulator_register(&pdev->dev,
+ &regulators[index], &config);
if (IS_ERR(rdev[i])) {
ret = PTR_ERR(rdev[i]);
dev_err(max8998->dev, "regulator %s init failed (%d)\n",
regulators[index].name, ret);
rdev[i] = NULL;
- goto err;
+ return ret;
}
}
return 0;
-err:
- while (--i >= 0)
- regulator_unregister(rdev[i]);
-err_out:
- return ret;
-}
-
-static int max8998_pmic_remove(struct platform_device *pdev)
-{
- struct max8998_data *max8998 = platform_get_drvdata(pdev);
- struct regulator_dev **rdev = max8998->rdev;
- int i;
-
- for (i = 0; i < max8998->num_regulators; i++)
- regulator_unregister(rdev[i]);
- return 0;
}
static const struct platform_device_id max8998_pmic_id[] = {
@@ -918,7 +900,6 @@ static struct platform_driver max8998_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = max8998_pmic_probe,
- .remove = max8998_pmic_remove,
.id_table = max8998_pmic_id,
};
diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c
index 5ff99d2703db..f036b26d4cfc 100644
--- a/drivers/regulator/mc13783-regulator.c
+++ b/drivers/regulator/mc13783-regulator.c
@@ -400,7 +400,7 @@ static int mc13783_regulator_probe(struct platform_device *pdev)
dev_get_platdata(&pdev->dev);
struct mc13xxx_regulator_init_data *mc13xxx_data;
struct regulator_config config = { };
- int i, ret, num_regulators;
+ int i, num_regulators;
num_regulators = mc13xxx_get_num_regulators_dt(pdev);
@@ -444,32 +444,16 @@ static int mc13783_regulator_probe(struct platform_device *pdev)
config.driver_data = priv;
config.of_node = node;
- priv->regulators[i] = regulator_register(desc, &config);
+ priv->regulators[i] = devm_regulator_register(&pdev->dev, desc,
+ &config);
if (IS_ERR(priv->regulators[i])) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
mc13783_regulators[i].desc.name);
- ret = PTR_ERR(priv->regulators[i]);
- goto err;
+ return PTR_ERR(priv->regulators[i]);
}
}
return 0;
-err:
- while (--i >= 0)
- regulator_unregister(priv->regulators[i]);
-
- return ret;
-}
-
-static int mc13783_regulator_remove(struct platform_device *pdev)
-{
- struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
- int i;
-
- for (i = 0; i < priv->num_regulators; i++)
- regulator_unregister(priv->regulators[i]);
-
- return 0;
}
static struct platform_driver mc13783_regulator_driver = {
@@ -477,7 +461,6 @@ static struct platform_driver mc13783_regulator_driver = {
.name = "mc13783-regulator",
.owner = THIS_MODULE,
},
- .remove = mc13783_regulator_remove,
.probe = mc13783_regulator_probe,
};
diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c
index 1037e07937cf..96c9f80d9550 100644
--- a/drivers/regulator/mc13892-regulator.c
+++ b/drivers/regulator/mc13892-regulator.c
@@ -611,43 +611,27 @@ static int mc13892_regulator_probe(struct platform_device *pdev)
config.driver_data = priv;
config.of_node = node;
- priv->regulators[i] = regulator_register(desc, &config);
+ priv->regulators[i] = devm_regulator_register(&pdev->dev, desc,
+ &config);
if (IS_ERR(priv->regulators[i])) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
mc13892_regulators[i].desc.name);
- ret = PTR_ERR(priv->regulators[i]);
- goto err;
+ return PTR_ERR(priv->regulators[i]);
}
}
return 0;
-err:
- while (--i >= 0)
- regulator_unregister(priv->regulators[i]);
- return ret;
err_unlock:
mc13xxx_unlock(mc13892);
return ret;
}
-static int mc13892_regulator_remove(struct platform_device *pdev)
-{
- struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
- int i;
-
- for (i = 0; i < priv->num_regulators; i++)
- regulator_unregister(priv->regulators[i]);
-
- return 0;
-}
-
static struct platform_driver mc13892_regulator_driver = {
.driver = {
.name = "mc13892-regulator",
.owner = THIS_MODULE,
},
- .remove = mc13892_regulator_remove,
.probe = mc13892_regulator_probe,
};
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 7827384680d6..ea4f36f2cbe2 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -23,6 +23,8 @@ static void of_get_regulation_constraints(struct device_node *np,
const __be32 *min_uA, *max_uA, *ramp_delay;
struct property *prop;
struct regulation_constraints *constraints = &(*init_data)->constraints;
+ int ret;
+ u32 pval;
constraints->name = of_get_property(np, "regulator-name", NULL);
@@ -73,6 +75,10 @@ static void of_get_regulation_constraints(struct device_node *np,
else
constraints->ramp_disable = true;
}
+
+ ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval);
+ if (!ret)
+ constraints->enable_time = pval;
}
/**
diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
index 488dfe7ce9a6..9d87c301ab91 100644
--- a/drivers/regulator/palmas-regulator.c
+++ b/drivers/regulator/palmas-regulator.c
@@ -33,6 +33,7 @@ struct regs_info {
u8 vsel_addr;
u8 ctrl_addr;
u8 tstep_addr;
+ int sleep_id;
};
static const struct regs_info palmas_regs_info[] = {
@@ -42,6 +43,7 @@ static const struct regs_info palmas_regs_info[] = {
.vsel_addr = PALMAS_SMPS12_VOLTAGE,
.ctrl_addr = PALMAS_SMPS12_CTRL,
.tstep_addr = PALMAS_SMPS12_TSTEP,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS12,
},
{
.name = "SMPS123",
@@ -49,12 +51,14 @@ static const struct regs_info palmas_regs_info[] = {
.vsel_addr = PALMAS_SMPS12_VOLTAGE,
.ctrl_addr = PALMAS_SMPS12_CTRL,
.tstep_addr = PALMAS_SMPS12_TSTEP,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS12,
},
{
.name = "SMPS3",
.sname = "smps3-in",
.vsel_addr = PALMAS_SMPS3_VOLTAGE,
.ctrl_addr = PALMAS_SMPS3_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS3,
},
{
.name = "SMPS45",
@@ -62,6 +66,7 @@ static const struct regs_info palmas_regs_info[] = {
.vsel_addr = PALMAS_SMPS45_VOLTAGE,
.ctrl_addr = PALMAS_SMPS45_CTRL,
.tstep_addr = PALMAS_SMPS45_TSTEP,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS45,
},
{
.name = "SMPS457",
@@ -69,6 +74,7 @@ static const struct regs_info palmas_regs_info[] = {
.vsel_addr = PALMAS_SMPS45_VOLTAGE,
.ctrl_addr = PALMAS_SMPS45_CTRL,
.tstep_addr = PALMAS_SMPS45_TSTEP,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS45,
},
{
.name = "SMPS6",
@@ -76,12 +82,14 @@ static const struct regs_info palmas_regs_info[] = {
.vsel_addr = PALMAS_SMPS6_VOLTAGE,
.ctrl_addr = PALMAS_SMPS6_CTRL,
.tstep_addr = PALMAS_SMPS6_TSTEP,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS6,
},
{
.name = "SMPS7",
.sname = "smps7-in",
.vsel_addr = PALMAS_SMPS7_VOLTAGE,
.ctrl_addr = PALMAS_SMPS7_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS7,
},
{
.name = "SMPS8",
@@ -89,108 +97,128 @@ static const struct regs_info palmas_regs_info[] = {
.vsel_addr = PALMAS_SMPS8_VOLTAGE,
.ctrl_addr = PALMAS_SMPS8_CTRL,
.tstep_addr = PALMAS_SMPS8_TSTEP,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS8,
},
{
.name = "SMPS9",
.sname = "smps9-in",
.vsel_addr = PALMAS_SMPS9_VOLTAGE,
.ctrl_addr = PALMAS_SMPS9_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS9,
},
{
.name = "SMPS10_OUT2",
.sname = "smps10-in",
.ctrl_addr = PALMAS_SMPS10_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS10,
},
{
.name = "SMPS10_OUT1",
.sname = "smps10-out2",
.ctrl_addr = PALMAS_SMPS10_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS10,
},
{
.name = "LDO1",
.sname = "ldo1-in",
.vsel_addr = PALMAS_LDO1_VOLTAGE,
.ctrl_addr = PALMAS_LDO1_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO1,
},
{
.name = "LDO2",
.sname = "ldo2-in",
.vsel_addr = PALMAS_LDO2_VOLTAGE,
.ctrl_addr = PALMAS_LDO2_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO2,
},
{
.name = "LDO3",
.sname = "ldo3-in",
.vsel_addr = PALMAS_LDO3_VOLTAGE,
.ctrl_addr = PALMAS_LDO3_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO3,
},
{
.name = "LDO4",
.sname = "ldo4-in",
.vsel_addr = PALMAS_LDO4_VOLTAGE,
.ctrl_addr = PALMAS_LDO4_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO4,
},
{
.name = "LDO5",
.sname = "ldo5-in",
.vsel_addr = PALMAS_LDO5_VOLTAGE,
.ctrl_addr = PALMAS_LDO5_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO5,
},
{
.name = "LDO6",
.sname = "ldo6-in",
.vsel_addr = PALMAS_LDO6_VOLTAGE,
.ctrl_addr = PALMAS_LDO6_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO6,
},
{
.name = "LDO7",
.sname = "ldo7-in",
.vsel_addr = PALMAS_LDO7_VOLTAGE,
.ctrl_addr = PALMAS_LDO7_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO7,
},
{
.name = "LDO8",
.sname = "ldo8-in",
.vsel_addr = PALMAS_LDO8_VOLTAGE,
.ctrl_addr = PALMAS_LDO8_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO8,
},
{
.name = "LDO9",
.sname = "ldo9-in",
.vsel_addr = PALMAS_LDO9_VOLTAGE,
.ctrl_addr = PALMAS_LDO9_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO9,
},
{
.name = "LDOLN",
.sname = "ldoln-in",
.vsel_addr = PALMAS_LDOLN_VOLTAGE,
.ctrl_addr = PALMAS_LDOLN_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDOLN,
},
{
.name = "LDOUSB",
.sname = "ldousb-in",
.vsel_addr = PALMAS_LDOUSB_VOLTAGE,
.ctrl_addr = PALMAS_LDOUSB_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDOUSB,
},
{
.name = "REGEN1",
.ctrl_addr = PALMAS_REGEN1_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_REGEN1,
},
{
.name = "REGEN2",
.ctrl_addr = PALMAS_REGEN2_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_REGEN2,
},
{
.name = "REGEN3",
.ctrl_addr = PALMAS_REGEN3_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_REGEN3,
},
{
.name = "SYSEN1",
.ctrl_addr = PALMAS_SYSEN1_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SYSEN1,
},
{
.name = "SYSEN2",
.ctrl_addr = PALMAS_SYSEN2_CTRL,
+ .sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SYSEN2,
},
};
@@ -201,13 +229,7 @@ static unsigned int palmas_smps_ramp_delay[4] = {0, 10000, 5000, 2500};
#define SMPS_CTRL_MODE_ECO 0x02
#define SMPS_CTRL_MODE_PWM 0x03
-/* These values are derived from the data sheet. And are the number of steps
- * where there is a voltage change, the ranges at beginning and end of register
- * max/min values where there are no change are ommitted.
- *
- * So they are basically (maxV-minV)/stepV
- */
-#define PALMAS_SMPS_NUM_VOLTAGES 117
+#define PALMAS_SMPS_NUM_VOLTAGES 122
#define PALMAS_SMPS10_NUM_VOLTAGES 2
#define PALMAS_LDO_NUM_VOLTAGES 50
@@ -484,6 +506,17 @@ static struct regulator_ops palmas_ops_smps = {
.set_ramp_delay = palmas_smps_set_ramp_delay,
};
+static struct regulator_ops palmas_ops_ext_control_smps = {
+ .set_mode = palmas_set_mode_smps,
+ .get_mode = palmas_get_mode_smps,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .list_voltage = palmas_list_voltage_smps,
+ .map_voltage = palmas_map_voltage_smps,
+ .set_voltage_time_sel = palma_smps_set_voltage_smps_time_sel,
+ .set_ramp_delay = palmas_smps_set_ramp_delay,
+};
+
static struct regulator_ops palmas_ops_smps10 = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
@@ -519,12 +552,37 @@ static struct regulator_ops palmas_ops_ldo = {
.map_voltage = regulator_map_voltage_linear,
};
+static struct regulator_ops palmas_ops_ext_control_ldo = {
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+};
+
static struct regulator_ops palmas_ops_extreg = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
};
+static struct regulator_ops palmas_ops_ext_control_extreg = {
+};
+
+static int palmas_regulator_config_external(struct palmas *palmas, int id,
+ struct palmas_reg_init *reg_init)
+{
+ int sleep_id = palmas_regs_info[id].sleep_id;
+ int ret;
+
+ ret = palmas_ext_control_req_config(palmas, sleep_id,
+ reg_init->roof_floor, true);
+ if (ret < 0)
+ dev_err(palmas->dev,
+ "Ext control config for regulator %d failed %d\n",
+ id, ret);
+ return ret;
+}
+
/*
* setup the hardware based sleep configuration of the SMPS/LDO regulators
* from the platform data. This is different to the software based control
@@ -583,7 +641,22 @@ static int palmas_smps_init(struct palmas *palmas, int id,
return ret;
}
+ if (reg_init->roof_floor && (id != PALMAS_REG_SMPS10_OUT1) &&
+ (id != PALMAS_REG_SMPS10_OUT2)) {
+ /* Enable externally controlled regulator */
+ addr = palmas_regs_info[id].ctrl_addr;
+ ret = palmas_smps_read(palmas, addr, &reg);
+ if (ret < 0)
+ return ret;
+ if (!(reg & PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK)) {
+ reg |= SMPS_CTRL_MODE_ON;
+ ret = palmas_smps_write(palmas, addr, reg);
+ if (ret < 0)
+ return ret;
+ }
+ return palmas_regulator_config_external(palmas, id, reg_init);
+ }
return 0;
}
@@ -614,6 +687,20 @@ static int palmas_ldo_init(struct palmas *palmas, int id,
if (ret)
return ret;
+ if (reg_init->roof_floor) {
+ /* Enable externally controlled regulator */
+ addr = palmas_regs_info[id].ctrl_addr;
+ ret = palmas_update_bits(palmas, PALMAS_LDO_BASE,
+ addr, PALMAS_LDO1_CTRL_MODE_ACTIVE,
+ PALMAS_LDO1_CTRL_MODE_ACTIVE);
+ if (ret < 0) {
+ dev_err(palmas->dev,
+ "LDO Register 0x%02x update failed %d\n",
+ addr, ret);
+ return ret;
+ }
+ return palmas_regulator_config_external(palmas, id, reg_init);
+ }
return 0;
}
@@ -636,6 +723,21 @@ static int palmas_extreg_init(struct palmas *palmas, int id,
addr, ret);
return ret;
}
+
+ if (reg_init->roof_floor) {
+ /* Enable externally controlled regulator */
+ addr = palmas_regs_info[id].ctrl_addr;
+ ret = palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
+ addr, PALMAS_REGEN1_CTRL_MODE_ACTIVE,
+ PALMAS_REGEN1_CTRL_MODE_ACTIVE);
+ if (ret < 0) {
+ dev_err(palmas->dev,
+ "Resource Register 0x%02x update failed %d\n",
+ addr, ret);
+ return ret;
+ }
+ return palmas_regulator_config_external(palmas, id, reg_init);
+ }
return 0;
}
@@ -746,9 +848,35 @@ static void palmas_dt_to_pdata(struct device *dev,
of_property_read_bool(palmas_matches[idx].of_node,
"ti,warm-reset");
- pdata->reg_init[idx]->roof_floor =
- of_property_read_bool(palmas_matches[idx].of_node,
- "ti,roof-floor");
+ ret = of_property_read_u32(palmas_matches[idx].of_node,
+ "ti,roof-floor", &prop);
+ /* EINVAL: Property not found */
+ if (ret != -EINVAL) {
+ int econtrol;
+
+ /* use default value, when no value is specified */
+ econtrol = PALMAS_EXT_CONTROL_NSLEEP;
+ if (!ret) {
+ switch (prop) {
+ case 1:
+ econtrol = PALMAS_EXT_CONTROL_ENABLE1;
+ break;
+ case 2:
+ econtrol = PALMAS_EXT_CONTROL_ENABLE2;
+ break;
+ case 3:
+ econtrol = PALMAS_EXT_CONTROL_NSLEEP;
+ break;
+ default:
+ WARN_ON(1);
+ dev_warn(dev,
+ "%s: Invalid roof-floor option: %u\n",
+ palmas_matches[idx].name, prop);
+ break;
+ }
+ }
+ pdata->reg_init[idx]->roof_floor = econtrol;
+ }
ret = of_property_read_u32(palmas_matches[idx].of_node,
"ti,mode-sleep", &prop);
@@ -862,7 +990,7 @@ static int palmas_regulators_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(&pdev->dev,
"reading TSTEP reg failed: %d\n", ret);
- goto err_unregister_regulator;
+ return ret;
}
pmic->desc[id].ramp_delay =
palmas_smps_ramp_delay[reg & 0x3];
@@ -874,7 +1002,9 @@ static int palmas_regulators_probe(struct platform_device *pdev)
reg_init = pdata->reg_init[id];
ret = palmas_smps_init(palmas, id, reg_init);
if (ret)
- goto err_unregister_regulator;
+ return ret;
+ } else {
+ reg_init = NULL;
}
/* Register the regulators */
@@ -915,11 +1045,15 @@ static int palmas_regulators_probe(struct platform_device *pdev)
ret = palmas_smps_read(pmic->palmas, addr, &reg);
if (ret)
- goto err_unregister_regulator;
+ return ret;
if (reg & PALMAS_SMPS12_VOLTAGE_RANGE)
pmic->range[id] = 1;
- pmic->desc[id].ops = &palmas_ops_smps;
+ if (reg_init && reg_init->roof_floor)
+ pmic->desc[id].ops =
+ &palmas_ops_ext_control_smps;
+ else
+ pmic->desc[id].ops = &palmas_ops_smps;
pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
pmic->desc[id].vsel_reg =
PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
@@ -931,7 +1065,7 @@ static int palmas_regulators_probe(struct platform_device *pdev)
addr = palmas_regs_info[id].ctrl_addr;
ret = palmas_smps_read(pmic->palmas, addr, &reg);
if (ret)
- goto err_unregister_regulator;
+ return ret;
pmic->current_reg_mode[id] = reg &
PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
}
@@ -947,13 +1081,13 @@ static int palmas_regulators_probe(struct platform_device *pdev)
pmic->desc[id].supply_name = palmas_regs_info[id].sname;
config.of_node = palmas_matches[id].of_node;
- rdev = regulator_register(&pmic->desc[id], &config);
+ rdev = devm_regulator_register(&pdev->dev, &pmic->desc[id],
+ &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev,
"failed to register %s regulator\n",
pdev->name);
- ret = PTR_ERR(rdev);
- goto err_unregister_regulator;
+ return PTR_ERR(rdev);
}
/* Save regulator for cleanup */
@@ -962,6 +1096,10 @@ static int palmas_regulators_probe(struct platform_device *pdev)
/* Start this loop from the id left from previous loop */
for (; id < PALMAS_NUM_REGS; id++) {
+ if (pdata && pdata->reg_init[id])
+ reg_init = pdata->reg_init[id];
+ else
+ reg_init = NULL;
/* Miss out regulators which are not available due
* to alternate functions.
@@ -975,10 +1113,15 @@ static int palmas_regulators_probe(struct platform_device *pdev)
if (id < PALMAS_REG_REGEN1) {
pmic->desc[id].n_voltages = PALMAS_LDO_NUM_VOLTAGES;
- pmic->desc[id].ops = &palmas_ops_ldo;
+ if (reg_init && reg_init->roof_floor)
+ pmic->desc[id].ops =
+ &palmas_ops_ext_control_ldo;
+ else
+ pmic->desc[id].ops = &palmas_ops_ldo;
pmic->desc[id].min_uV = 900000;
pmic->desc[id].uV_step = 50000;
pmic->desc[id].linear_min_sel = 1;
+ pmic->desc[id].enable_time = 500;
pmic->desc[id].vsel_reg =
PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
palmas_regs_info[id].vsel_addr);
@@ -997,9 +1140,18 @@ static int palmas_regulators_probe(struct platform_device *pdev)
pmic->desc[id].min_uV = 450000;
pmic->desc[id].uV_step = 25000;
}
+
+ /* LOD6 in vibrator mode will have enable time 2000us */
+ if (pdata && pdata->ldo6_vibrator &&
+ (id == PALMAS_REG_LDO6))
+ pmic->desc[id].enable_time = 2000;
} else {
pmic->desc[id].n_voltages = 1;
- pmic->desc[id].ops = &palmas_ops_extreg;
+ if (reg_init && reg_init->roof_floor)
+ pmic->desc[id].ops =
+ &palmas_ops_ext_control_extreg;
+ else
+ pmic->desc[id].ops = &palmas_ops_extreg;
pmic->desc[id].enable_reg =
PALMAS_BASE_TO_REG(PALMAS_RESOURCE_BASE,
palmas_regs_info[id].ctrl_addr);
@@ -1015,13 +1167,13 @@ static int palmas_regulators_probe(struct platform_device *pdev)
pmic->desc[id].supply_name = palmas_regs_info[id].sname;
config.of_node = palmas_matches[id].of_node;
- rdev = regulator_register(&pmic->desc[id], &config);
+ rdev = devm_regulator_register(&pdev->dev, &pmic->desc[id],
+ &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev,
"failed to register %s regulator\n",
pdev->name);
- ret = PTR_ERR(rdev);
- goto err_unregister_regulator;
+ return PTR_ERR(rdev);
}
/* Save regulator for cleanup */
@@ -1037,31 +1189,14 @@ static int palmas_regulators_probe(struct platform_device *pdev)
else
ret = palmas_extreg_init(palmas,
id, reg_init);
- if (ret) {
- regulator_unregister(pmic->rdev[id]);
- goto err_unregister_regulator;
- }
+ if (ret)
+ return ret;
}
}
}
return 0;
-
-err_unregister_regulator:
- while (--id >= 0)
- regulator_unregister(pmic->rdev[id]);
- return ret;
-}
-
-static int palmas_regulators_remove(struct platform_device *pdev)
-{
- struct palmas_pmic *pmic = platform_get_drvdata(pdev);
- int id;
-
- for (id = 0; id < PALMAS_NUM_REGS; id++)
- regulator_unregister(pmic->rdev[id]);
- return 0;
}
static struct of_device_id of_palmas_match_tbl[] = {
@@ -1083,7 +1218,6 @@ static struct platform_driver palmas_driver = {
.owner = THIS_MODULE,
},
.probe = palmas_regulators_probe,
- .remove = palmas_regulators_remove,
};
static int __init palmas_init(void)
diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c
index 5885b4504596..b58affb33143 100644
--- a/drivers/regulator/rc5t583-regulator.c
+++ b/drivers/regulator/rc5t583-regulator.c
@@ -173,33 +173,16 @@ skip_ext_pwr_config:
config.driver_data = reg;
config.regmap = rc5t583->regmap;
- rdev = regulator_register(&ri->desc, &config);
+ rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "Failed to register regulator %s\n",
ri->desc.name);
- ret = PTR_ERR(rdev);
- goto clean_exit;
+ return PTR_ERR(rdev);
}
reg->rdev = rdev;
}
platform_set_drvdata(pdev, regs);
return 0;
-
-clean_exit:
- while (--id >= 0)
- regulator_unregister(regs[id].rdev);
-
- return ret;
-}
-
-static int rc5t583_regulator_remove(struct platform_device *pdev)
-{
- struct rc5t583_regulator *regs = platform_get_drvdata(pdev);
- int id;
-
- for (id = 0; id < RC5T583_REGULATOR_MAX; ++id)
- regulator_unregister(regs[id].rdev);
- return 0;
}
static struct platform_driver rc5t583_regulator_driver = {
@@ -208,7 +191,6 @@ static struct platform_driver rc5t583_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = rc5t583_regulator_probe,
- .remove = rc5t583_regulator_remove,
};
static int __init rc5t583_regulator_init(void)
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 5eba2ff8c0e8..333677d68d0e 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -448,33 +448,17 @@ common_reg:
config.of_node = rdata[i].of_node;
}
- s2mps11->rdev[i] = regulator_register(&regulators[i], &config);
+ s2mps11->rdev[i] = devm_regulator_register(&pdev->dev,
+ &regulators[i], &config);
if (IS_ERR(s2mps11->rdev[i])) {
ret = PTR_ERR(s2mps11->rdev[i]);
dev_err(&pdev->dev, "regulator init failed for %d\n",
i);
- s2mps11->rdev[i] = NULL;
- goto err;
+ return ret;
}
}
return 0;
-err:
- for (i = 0; i < S2MPS11_REGULATOR_MAX; i++)
- regulator_unregister(s2mps11->rdev[i]);
-
- return ret;
-}
-
-static int s2mps11_pmic_remove(struct platform_device *pdev)
-{
- struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev);
- int i;
-
- for (i = 0; i < S2MPS11_REGULATOR_MAX; i++)
- regulator_unregister(s2mps11->rdev[i]);
-
- return 0;
}
static const struct platform_device_id s2mps11_pmic_id[] = {
@@ -489,7 +473,6 @@ static struct platform_driver s2mps11_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = s2mps11_pmic_probe,
- .remove = s2mps11_pmic_remove,
.id_table = s2mps11_pmic_id,
};
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index c24448bc43cf..2297fdf9ba7e 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -910,34 +910,17 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
config.regmap = iodev->regmap;
config.of_node = pdata->regulators[i].reg_node;
- rdev[i] = regulator_register(&regulators[id], &config);
+ rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id],
+ &config);
if (IS_ERR(rdev[i])) {
ret = PTR_ERR(rdev[i]);
dev_err(s5m8767->dev, "regulator init failed for %d\n",
id);
- rdev[i] = NULL;
- goto err;
+ return ret;
}
}
return 0;
-err:
- for (i = 0; i < s5m8767->num_regulators; i++)
- regulator_unregister(rdev[i]);
-
- return ret;
-}
-
-static int s5m8767_pmic_remove(struct platform_device *pdev)
-{
- struct s5m8767_info *s5m8767 = platform_get_drvdata(pdev);
- struct regulator_dev **rdev = s5m8767->rdev;
- int i;
-
- for (i = 0; i < s5m8767->num_regulators; i++)
- regulator_unregister(rdev[i]);
-
- return 0;
}
static const struct platform_device_id s5m8767_pmic_id[] = {
@@ -952,7 +935,6 @@ static struct platform_driver s5m8767_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = s5m8767_pmic_probe,
- .remove = s5m8767_pmic_remove,
.id_table = s5m8767_pmic_id,
};
diff --git a/drivers/regulator/stw481x-vmmc.c b/drivers/regulator/stw481x-vmmc.c
new file mode 100644
index 000000000000..5ae72a877259
--- /dev/null
+++ b/drivers/regulator/stw481x-vmmc.c
@@ -0,0 +1,110 @@
+/*
+ * Regulator driver for STw4810/STw4811 VMMC regulator.
+ *
+ * Copyright (C) 2013 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ *
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/mfd/stw481x.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+
+static const unsigned int stw481x_vmmc_voltages[] = {
+ 1800000,
+ 1800000,
+ 2850000,
+ 3000000,
+ 1850000,
+ 2600000,
+ 2700000,
+ 3300000,
+};
+
+static struct regulator_ops stw481x_vmmc_ops = {
+ .list_voltage = regulator_list_voltage_table,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+static struct regulator_desc vmmc_regulator = {
+ .name = "VMMC",
+ .id = 0,
+ .ops = &stw481x_vmmc_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .n_voltages = ARRAY_SIZE(stw481x_vmmc_voltages),
+ .volt_table = stw481x_vmmc_voltages,
+ .enable_time = 200, /* FIXME: look this up */
+ .enable_reg = STW_CONF1,
+ .enable_mask = STW_CONF1_PDN_VMMC,
+ .vsel_reg = STW_CONF1,
+ .vsel_mask = STW_CONF1_VMMC_MASK,
+};
+
+static int stw481x_vmmc_regulator_probe(struct platform_device *pdev)
+{
+ struct stw481x *stw481x = dev_get_platdata(&pdev->dev);
+ struct regulator_config config = { };
+ int ret;
+
+ /* First disable the external VMMC if it's active */
+ ret = regmap_update_bits(stw481x->map, STW_CONF2,
+ STW_CONF2_VMMC_EXT, 0);
+ if (ret) {
+ dev_err(&pdev->dev, "could not disable external VMMC\n");
+ return ret;
+ }
+
+ /* Register VMMC regulator */
+ config.dev = &pdev->dev;
+ config.driver_data = stw481x;
+ config.regmap = stw481x->map;
+ config.of_node = pdev->dev.of_node;
+ config.init_data = of_get_regulator_init_data(&pdev->dev,
+ pdev->dev.of_node);
+
+ stw481x->vmmc_regulator = regulator_register(&vmmc_regulator, &config);
+ if (IS_ERR(stw481x->vmmc_regulator)) {
+ dev_err(&pdev->dev,
+ "error initializing STw481x VMMC regulator\n");
+ return PTR_ERR(stw481x->vmmc_regulator);
+ }
+
+ dev_info(&pdev->dev, "initialized STw481x VMMC regulator\n");
+ return 0;
+}
+
+static int stw481x_vmmc_regulator_remove(struct platform_device *pdev)
+{
+ struct stw481x *stw481x = dev_get_platdata(&pdev->dev);
+
+ regulator_unregister(stw481x->vmmc_regulator);
+ return 0;
+}
+
+static const struct of_device_id stw481x_vmmc_match[] = {
+ { .compatible = "st,stw481x-vmmc", },
+ {},
+};
+
+static struct platform_driver stw481x_vmmc_regulator_driver = {
+ .driver = {
+ .name = "stw481x-vmmc-regulator",
+ .owner = THIS_MODULE,
+ },
+ .probe = stw481x_vmmc_regulator_probe,
+ .remove = stw481x_vmmc_regulator_remove,
+};
+
+module_platform_driver(stw481x_vmmc_regulator_driver);
diff --git a/drivers/regulator/ti-abb-regulator.c b/drivers/regulator/ti-abb-regulator.c
index d8e3e1262bc2..8c2a8195d8a7 100644
--- a/drivers/regulator/ti-abb-regulator.c
+++ b/drivers/regulator/ti-abb-regulator.c
@@ -696,39 +696,31 @@ static int ti_abb_probe(struct platform_device *pdev)
match = of_match_device(ti_abb_of_match, dev);
if (!match) {
/* We do not expect this to happen */
- ret = -ENODEV;
dev_err(dev, "%s: Unable to match device\n", __func__);
- goto err;
+ return -ENODEV;
}
if (!match->data) {
- ret = -EINVAL;
dev_err(dev, "%s: Bad data in match\n", __func__);
- goto err;
+ return -EINVAL;
}
abb = devm_kzalloc(dev, sizeof(struct ti_abb), GFP_KERNEL);
- if (!abb) {
- dev_err(dev, "%s: Unable to allocate ABB struct\n", __func__);
- ret = -ENOMEM;
- goto err;
- }
+ if (!abb)
+ return -ENOMEM;
abb->regs = match->data;
/* Map ABB resources */
pname = "base-address";
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
abb->base = devm_ioremap_resource(dev, res);
- if (IS_ERR(abb->base)) {
- ret = PTR_ERR(abb->base);
- goto err;
- }
+ if (IS_ERR(abb->base))
+ return PTR_ERR(abb->base);
pname = "int-address";
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
if (!res) {
dev_err(dev, "Missing '%s' IO resource\n", pname);
- ret = -ENODEV;
- goto err;
+ return -ENODEV;
}
/*
* We may have shared interrupt register offsets which are
@@ -738,8 +730,7 @@ static int ti_abb_probe(struct platform_device *pdev)
resource_size(res));
if (!abb->int_base) {
dev_err(dev, "Unable to map '%s'\n", pname);
- ret = -ENOMEM;
- goto err;
+ return -ENOMEM;
}
/* Map Optional resources */
@@ -759,17 +750,14 @@ static int ti_abb_probe(struct platform_device *pdev)
resource_size(res));
if (!abb->efuse_base) {
dev_err(dev, "Unable to map '%s'\n", pname);
- ret = -ENOMEM;
- goto err;
+ return -ENOMEM;
}
pname = "ldo-address";
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
abb->ldo_base = devm_ioremap_resource(dev, res);
- if (IS_ERR(abb->ldo_base)) {
- ret = PTR_ERR(abb->ldo_base);
- goto err;
- }
+ if (IS_ERR(abb->ldo_base))
+ return PTR_ERR(abb->ldo_base);
/* IF ldo_base is set, the following are mandatory */
pname = "ti,ldovbb-override-mask";
@@ -778,12 +766,11 @@ static int ti_abb_probe(struct platform_device *pdev)
&abb->ldovbb_override_mask);
if (ret) {
dev_err(dev, "Missing '%s' (%d)\n", pname, ret);
- goto err;
+ return ret;
}
if (!abb->ldovbb_override_mask) {
dev_err(dev, "Invalid property:'%s' set as 0!\n", pname);
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
pname = "ti,ldovbb-vset-mask";
@@ -792,12 +779,11 @@ static int ti_abb_probe(struct platform_device *pdev)
&abb->ldovbb_vset_mask);
if (ret) {
dev_err(dev, "Missing '%s' (%d)\n", pname, ret);
- goto err;
+ return ret;
}
if (!abb->ldovbb_vset_mask) {
dev_err(dev, "Invalid property:'%s' set as 0!\n", pname);
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
skip_opt:
@@ -807,31 +793,29 @@ skip_opt:
&abb->txdone_mask);
if (ret) {
dev_err(dev, "Missing '%s' (%d)\n", pname, ret);
- goto err;
+ return ret;
}
if (!abb->txdone_mask) {
dev_err(dev, "Invalid property:'%s' set as 0!\n", pname);
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
initdata = of_get_regulator_init_data(dev, pdev->dev.of_node);
if (!initdata) {
- ret = -ENOMEM;
dev_err(dev, "%s: Unable to alloc regulator init data\n",
__func__);
- goto err;
+ return -ENOMEM;
}
/* init ABB opp_sel table */
ret = ti_abb_init_table(dev, abb, initdata);
if (ret)
- goto err;
+ return ret;
/* init ABB timing */
ret = ti_abb_init_timings(dev, abb);
if (ret)
- goto err;
+ return ret;
desc = &abb->rdesc;
desc->name = dev_name(dev);
@@ -849,12 +833,12 @@ skip_opt:
config.driver_data = abb;
config.of_node = pdev->dev.of_node;
- rdev = regulator_register(desc, &config);
+ rdev = devm_regulator_register(dev, desc, &config);
if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev);
dev_err(dev, "%s: failed to register regulator(%d)\n",
__func__, ret);
- goto err;
+ return ret;
}
platform_set_drvdata(pdev, rdev);
@@ -862,31 +846,12 @@ skip_opt:
ti_abb_rmw(abb->regs->sr2_en_mask, 1, abb->regs->setup_reg, abb->base);
return 0;
-
-err:
- dev_err(dev, "%s: Failed to initialize(%d)\n", __func__, ret);
- return ret;
-}
-
-/**
- * ti_abb_remove() - cleanups
- * @pdev: ABB platform device
- *
- * Return: 0
- */
-static int ti_abb_remove(struct platform_device *pdev)
-{
- struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
- regulator_unregister(rdev);
- return 0;
}
MODULE_ALIAS("platform:ti_abb");
static struct platform_driver ti_abb_driver = {
.probe = ti_abb_probe,
- .remove = ti_abb_remove,
.driver = {
.name = "ti_abb",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
index 9392a7ca3d2d..b0a3f0917a27 100644
--- a/drivers/regulator/tps51632-regulator.c
+++ b/drivers/regulator/tps51632-regulator.c
@@ -343,7 +343,7 @@ static int tps51632_probe(struct i2c_client *client,
config.regmap = tps->regmap;
config.of_node = client->dev.of_node;
- rdev = regulator_register(&tps->desc, &config);
+ rdev = devm_regulator_register(&client->dev, &tps->desc, &config);
if (IS_ERR(rdev)) {
dev_err(tps->dev, "regulator register failed\n");
return PTR_ERR(rdev);
@@ -353,14 +353,6 @@ static int tps51632_probe(struct i2c_client *client,
return 0;
}
-static int tps51632_remove(struct i2c_client *client)
-{
- struct tps51632_chip *tps = i2c_get_clientdata(client);
-
- regulator_unregister(tps->rdev);
- return 0;
-}
-
static const struct i2c_device_id tps51632_id[] = {
{.name = "tps51632",},
{},
@@ -375,7 +367,6 @@ static struct i2c_driver tps51632_i2c_driver = {
.of_match_table = of_match_ptr(tps51632_of_match),
},
.probe = tps51632_probe,
- .remove = tps51632_remove,
.id_table = tps51632_id,
};
diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c
index 0b7ebb1ebf85..c2c0185a2dcd 100644
--- a/drivers/regulator/tps62360-regulator.c
+++ b/drivers/regulator/tps62360-regulator.c
@@ -476,7 +476,7 @@ static int tps62360_probe(struct i2c_client *client,
config.of_node = client->dev.of_node;
/* Register the regulators */
- rdev = regulator_register(&tps->desc, &config);
+ rdev = devm_regulator_register(&client->dev, &tps->desc, &config);
if (IS_ERR(rdev)) {
dev_err(tps->dev,
"%s(): regulator register failed with err %s\n",
@@ -488,20 +488,6 @@ static int tps62360_probe(struct i2c_client *client,
return 0;
}
-/**
- * tps62360_remove - tps62360 driver i2c remove handler
- * @client: i2c driver client device structure
- *
- * Unregister TPS driver as an i2c client device driver
- */
-static int tps62360_remove(struct i2c_client *client)
-{
- struct tps62360_chip *tps = i2c_get_clientdata(client);
-
- regulator_unregister(tps->rdev);
- return 0;
-}
-
static void tps62360_shutdown(struct i2c_client *client)
{
struct tps62360_chip *tps = i2c_get_clientdata(client);
@@ -535,7 +521,6 @@ static struct i2c_driver tps62360_i2c_driver = {
.of_match_table = of_match_ptr(tps62360_of_match),
},
.probe = tps62360_probe,
- .remove = tps62360_remove,
.shutdown = tps62360_shutdown,
.id_table = tps62360_id,
};
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index a15263d4bdff..a957579bd98b 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -277,12 +277,12 @@ static int tps_65023_probe(struct i2c_client *client,
config.regmap = tps->regmap;
/* Register the regulators */
- rdev = regulator_register(&tps->desc[i], &config);
+ rdev = devm_regulator_register(&client->dev, &tps->desc[i],
+ &config);
if (IS_ERR(rdev)) {
dev_err(&client->dev, "failed to register %s\n",
id->name);
- error = PTR_ERR(rdev);
- goto fail;
+ return PTR_ERR(rdev);
}
/* Save regulator for cleanup */
@@ -296,21 +296,6 @@ static int tps_65023_probe(struct i2c_client *client,
TPS65023_REG_CTRL2_CORE_ADJ, TPS65023_REG_CTRL2_CORE_ADJ);
return 0;
-
- fail:
- while (--i >= 0)
- regulator_unregister(tps->rdev[i]);
- return error;
-}
-
-static int tps_65023_remove(struct i2c_client *client)
-{
- struct tps_pmic *tps = i2c_get_clientdata(client);
- int i;
-
- for (i = 0; i < TPS65023_NUM_REGULATOR; i++)
- regulator_unregister(tps->rdev[i]);
- return 0;
}
static const struct tps_info tps65020_regs[] = {
@@ -430,7 +415,6 @@ static struct i2c_driver tps_65023_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = tps_65023_probe,
- .remove = tps_65023_remove,
.id_table = tps_65023_id,
};
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c
index 4117ff52dba1..162a0fae20b3 100644
--- a/drivers/regulator/tps6507x-regulator.c
+++ b/drivers/regulator/tps6507x-regulator.c
@@ -508,13 +508,13 @@ static int tps6507x_pmic_probe(struct platform_device *pdev)
config.of_node = tps6507x_reg_matches[i].of_node;
}
- rdev = regulator_register(&tps->desc[i], &config);
+ rdev = devm_regulator_register(&pdev->dev, &tps->desc[i],
+ &config);
if (IS_ERR(rdev)) {
dev_err(tps6507x_dev->dev,
"failed to register %s regulator\n",
pdev->name);
- error = PTR_ERR(rdev);
- goto fail;
+ return PTR_ERR(rdev);
}
/* Save regulator for cleanup */
@@ -525,22 +525,6 @@ static int tps6507x_pmic_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, tps6507x_dev);
return 0;
-
-fail:
- while (--i >= 0)
- regulator_unregister(tps->rdev[i]);
- return error;
-}
-
-static int tps6507x_pmic_remove(struct platform_device *pdev)
-{
- struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
- struct tps6507x_pmic *tps = tps6507x_dev->pmic;
- int i;
-
- for (i = 0; i < TPS6507X_NUM_REGULATOR; i++)
- regulator_unregister(tps->rdev[i]);
- return 0;
}
static struct platform_driver tps6507x_pmic_driver = {
@@ -549,7 +533,6 @@ static struct platform_driver tps6507x_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = tps6507x_pmic_probe,
- .remove = tps6507x_pmic_remove,
};
static int __init tps6507x_pmic_init(void)
diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c
index c8e70451df38..bd611cdf6e1c 100644
--- a/drivers/regulator/tps65090-regulator.c
+++ b/drivers/regulator/tps65090-regulator.c
@@ -279,7 +279,7 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(&pdev->dev,
"failed disable ext control\n");
- goto scrub;
+ return ret;
}
}
}
@@ -296,12 +296,11 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
else
config.of_node = NULL;
- rdev = regulator_register(ri->desc, &config);
+ rdev = devm_regulator_register(&pdev->dev, ri->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
ri->desc->name);
- ret = PTR_ERR(rdev);
- goto scrub;
+ return PTR_ERR(rdev);
}
ri->rdev = rdev;
@@ -309,36 +308,13 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data &&
tps_pdata->enable_ext_control) {
ret = tps65090_config_ext_control(ri, true);
- if (ret < 0) {
- /* Increment num to get unregister rdev */
- num++;
- goto scrub;
- }
+ if (ret < 0)
+ return ret;
}
}
platform_set_drvdata(pdev, pmic);
return 0;
-
-scrub:
- while (--num >= 0) {
- ri = &pmic[num];
- regulator_unregister(ri->rdev);
- }
- return ret;
-}
-
-static int tps65090_regulator_remove(struct platform_device *pdev)
-{
- struct tps65090_regulator *pmic = platform_get_drvdata(pdev);
- struct tps65090_regulator *ri;
- int num;
-
- for (num = 0; num < TPS65090_REGULATOR_MAX; ++num) {
- ri = &pmic[num];
- regulator_unregister(ri->rdev);
- }
- return 0;
}
static struct platform_driver tps65090_regulator_driver = {
@@ -347,7 +323,6 @@ static struct platform_driver tps65090_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = tps65090_regulator_probe,
- .remove = tps65090_regulator_remove,
};
static int __init tps65090_regulator_init(void)
diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c
index 90861d68a0b0..8860379fd6be 100644
--- a/drivers/regulator/tps65217-regulator.c
+++ b/drivers/regulator/tps65217-regulator.c
@@ -233,7 +233,7 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
struct regulator_init_data *reg_data;
struct regulator_dev *rdev;
struct regulator_config config = { };
- int i, ret;
+ int i;
if (tps->dev->of_node)
pdata = tps65217_parse_dt(pdev);
@@ -269,35 +269,18 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
if (tps->dev->of_node)
config.of_node = pdata->of_node[i];
- rdev = regulator_register(&regulators[i], &config);
+ rdev = devm_regulator_register(&pdev->dev, &regulators[i],
+ &config);
if (IS_ERR(rdev)) {
dev_err(tps->dev, "failed to register %s regulator\n",
pdev->name);
- ret = PTR_ERR(rdev);
- goto err_unregister_regulator;
+ return PTR_ERR(rdev);
}
/* Save regulator for cleanup */
tps->rdev[i] = rdev;
}
return 0;
-
-err_unregister_regulator:
- while (--i >= 0)
- regulator_unregister(tps->rdev[i]);
-
- return ret;
-}
-
-static int tps65217_regulator_remove(struct platform_device *pdev)
-{
- struct tps65217 *tps = platform_get_drvdata(pdev);
- unsigned int i;
-
- for (i = 0; i < TPS65217_NUM_REGULATOR; i++)
- regulator_unregister(tps->rdev[i]);
-
- return 0;
}
static struct platform_driver tps65217_regulator_driver = {
@@ -305,7 +288,6 @@ static struct platform_driver tps65217_regulator_driver = {
.name = "tps65217-pmic",
},
.probe = tps65217_regulator_probe,
- .remove = tps65217_regulator_remove,
};
static int __init tps65217_regulator_init(void)
diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c
index 62e8d28beabd..8b9ee3983a6c 100644
--- a/drivers/regulator/tps6524x-regulator.c
+++ b/drivers/regulator/tps6524x-regulator.c
@@ -588,7 +588,6 @@ static int pmic_remove(struct spi_device *spi)
regulator_unregister(hw->rdev[i]);
hw->rdev[i] = NULL;
}
- spi_set_drvdata(spi, NULL);
return 0;
}
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
index 2c9155b66f09..45e5d683d3f8 100644
--- a/drivers/regulator/tps6586x-regulator.c
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -379,15 +379,14 @@ static int tps6586x_regulator_probe(struct platform_device *pdev)
ri = find_regulator_info(id);
if (!ri) {
dev_err(&pdev->dev, "invalid regulator ID specified\n");
- err = -EINVAL;
- goto fail;
+ return -EINVAL;
}
err = tps6586x_regulator_preinit(pdev->dev.parent, ri);
if (err) {
dev_err(&pdev->dev,
"regulator %d preinit failed, e %d\n", id, err);
- goto fail;
+ return err;
}
config.dev = pdev->dev.parent;
@@ -397,12 +396,12 @@ static int tps6586x_regulator_probe(struct platform_device *pdev)
if (tps6586x_reg_matches)
config.of_node = tps6586x_reg_matches[id].of_node;
- rdev[id] = regulator_register(&ri->desc, &config);
+ rdev[id] = devm_regulator_register(&pdev->dev, &ri->desc,
+ &config);
if (IS_ERR(rdev[id])) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
ri->desc.name);
- err = PTR_ERR(rdev[id]);
- goto fail;
+ return PTR_ERR(rdev[id]);
}
if (reg_data) {
@@ -411,30 +410,13 @@ static int tps6586x_regulator_probe(struct platform_device *pdev)
if (err < 0) {
dev_err(&pdev->dev,
"Slew rate config failed, e %d\n", err);
- regulator_unregister(rdev[id]);
- goto fail;
+ return err;
}
}
}
platform_set_drvdata(pdev, rdev);
return 0;
-
-fail:
- while (--id >= 0)
- regulator_unregister(rdev[id]);
- return err;
-}
-
-static int tps6586x_regulator_remove(struct platform_device *pdev)
-{
- struct regulator_dev **rdev = platform_get_drvdata(pdev);
- int id = TPS6586X_ID_MAX_REGULATOR;
-
- while (--id >= 0)
- regulator_unregister(rdev[id]);
-
- return 0;
}
static struct platform_driver tps6586x_regulator_driver = {
@@ -443,7 +425,6 @@ static struct platform_driver tps6586x_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = tps6586x_regulator_probe,
- .remove = tps6586x_regulator_remove,
};
static int __init tps6586x_regulator_init(void)
diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
index 45c16447744b..b8167df71170 100644
--- a/drivers/regulator/tps65910-regulator.c
+++ b/drivers/regulator/tps65910-regulator.c
@@ -1177,35 +1177,19 @@ static int tps65910_probe(struct platform_device *pdev)
if (tps65910_reg_matches)
config.of_node = tps65910_reg_matches[i].of_node;
- rdev = regulator_register(&pmic->desc[i], &config);
+ rdev = devm_regulator_register(&pdev->dev, &pmic->desc[i],
+ &config);
if (IS_ERR(rdev)) {
dev_err(tps65910->dev,
"failed to register %s regulator\n",
pdev->name);
- err = PTR_ERR(rdev);
- goto err_unregister_regulator;
+ return PTR_ERR(rdev);
}
/* Save regulator for cleanup */
pmic->rdev[i] = rdev;
}
return 0;
-
-err_unregister_regulator:
- while (--i >= 0)
- regulator_unregister(pmic->rdev[i]);
- return err;
-}
-
-static int tps65910_remove(struct platform_device *pdev)
-{
- struct tps65910_reg *pmic = platform_get_drvdata(pdev);
- int i;
-
- for (i = 0; i < pmic->num_regulators; i++)
- regulator_unregister(pmic->rdev[i]);
-
- return 0;
}
static void tps65910_shutdown(struct platform_device *pdev)
@@ -1244,7 +1228,6 @@ static struct platform_driver tps65910_driver = {
.owner = THIS_MODULE,
},
.probe = tps65910_probe,
- .remove = tps65910_remove,
.shutdown = tps65910_shutdown,
};
diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c
index 281e52ac64ba..1ed4d049abfe 100644
--- a/drivers/regulator/tps65912-regulator.c
+++ b/drivers/regulator/tps65912-regulator.c
@@ -461,7 +461,7 @@ static int tps65912_probe(struct platform_device *pdev)
struct regulator_dev *rdev;
struct tps65912_reg *pmic;
struct tps65912_board *pmic_plat_data;
- int i, err;
+ int i;
pmic_plat_data = dev_get_platdata(tps65912->dev);
if (!pmic_plat_data)
@@ -504,34 +504,19 @@ static int tps65912_probe(struct platform_device *pdev)
config.init_data = reg_data;
config.driver_data = pmic;
- rdev = regulator_register(&pmic->desc[i], &config);
+ rdev = devm_regulator_register(&pdev->dev, &pmic->desc[i],
+ &config);
if (IS_ERR(rdev)) {
dev_err(tps65912->dev,
"failed to register %s regulator\n",
pdev->name);
- err = PTR_ERR(rdev);
- goto err;
+ return PTR_ERR(rdev);
}
/* Save regulator for cleanup */
pmic->rdev[i] = rdev;
}
return 0;
-
-err:
- while (--i >= 0)
- regulator_unregister(pmic->rdev[i]);
- return err;
-}
-
-static int tps65912_remove(struct platform_device *pdev)
-{
- struct tps65912_reg *tps65912_reg = platform_get_drvdata(pdev);
- int i;
-
- for (i = 0; i < TPS65912_NUM_REGULATOR; i++)
- regulator_unregister(tps65912_reg->rdev[i]);
- return 0;
}
static struct platform_driver tps65912_driver = {
@@ -540,7 +525,6 @@ static struct platform_driver tps65912_driver = {
.owner = THIS_MODULE,
},
.probe = tps65912_probe,
- .remove = tps65912_remove,
};
static int __init tps65912_init(void)
diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c
index 6511d0bfd896..71f457a42623 100644
--- a/drivers/regulator/tps80031-regulator.c
+++ b/drivers/regulator/tps80031-regulator.c
@@ -719,7 +719,7 @@ static int tps80031_regulator_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(&pdev->dev,
"regulator config failed, e %d\n", ret);
- goto fail;
+ return ret;
}
ret = tps80031_power_req_config(pdev->dev.parent,
@@ -727,41 +727,22 @@ static int tps80031_regulator_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(&pdev->dev,
"pwr_req config failed, err %d\n", ret);
- goto fail;
+ return ret;
}
}
- rdev = regulator_register(&ri->rinfo->desc, &config);
+ rdev = devm_regulator_register(&pdev->dev, &ri->rinfo->desc,
+ &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev,
"register regulator failed %s\n",
ri->rinfo->desc.name);
- ret = PTR_ERR(rdev);
- goto fail;
+ return PTR_ERR(rdev);
}
ri->rdev = rdev;
}
platform_set_drvdata(pdev, pmic);
return 0;
-fail:
- while (--num >= 0) {
- ri = &pmic[num];
- regulator_unregister(ri->rdev);
- }
- return ret;
-}
-
-static int tps80031_regulator_remove(struct platform_device *pdev)
-{
- struct tps80031_regulator *pmic = platform_get_drvdata(pdev);
- struct tps80031_regulator *ri = NULL;
- int num;
-
- for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) {
- ri = &pmic[num];
- regulator_unregister(ri->rdev);
- }
- return 0;
}
static struct platform_driver tps80031_regulator_driver = {
@@ -770,7 +751,6 @@ static struct platform_driver tps80031_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = tps80031_regulator_probe,
- .remove = tps80031_regulator_remove,
};
static int __init tps80031_regulator_init(void)
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index 11861cb861df..6823e6f2b88a 100644
--- a/drivers/regulator/wm831x-dcdc.c
+++ b/drivers/regulator/wm831x-dcdc.c
@@ -387,8 +387,9 @@ static struct regulator_ops wm831x_buckv_ops = {
* Set up DVS control. We just log errors since we can still run
* (with reduced performance) if we fail.
*/
-static void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
- struct wm831x_buckv_pdata *pdata)
+static void wm831x_buckv_dvs_init(struct platform_device *pdev,
+ struct wm831x_dcdc *dcdc,
+ struct wm831x_buckv_pdata *pdata)
{
struct wm831x *wm831x = dcdc->wm831x;
int ret;
@@ -402,9 +403,9 @@ static void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
*/
dcdc->dvs_gpio_state = pdata->dvs_init_state;
- ret = gpio_request_one(pdata->dvs_gpio,
- dcdc->dvs_gpio_state ? GPIOF_INIT_HIGH : 0,
- "DCDC DVS");
+ ret = devm_gpio_request_one(&pdev->dev, pdata->dvs_gpio,
+ dcdc->dvs_gpio_state ? GPIOF_INIT_HIGH : 0,
+ "DCDC DVS");
if (ret < 0) {
dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n",
dcdc->name, ret);
@@ -513,7 +514,8 @@ static int wm831x_buckv_probe(struct platform_device *pdev)
dcdc->dvs_vsel = ret & WM831X_DC1_DVS_VSEL_MASK;
if (pdata && pdata->dcdc[id])
- wm831x_buckv_dvs_init(dcdc, pdata->dcdc[id]->driver_data);
+ wm831x_buckv_dvs_init(pdev, dcdc,
+ pdata->dcdc[id]->driver_data);
config.dev = pdev->dev.parent;
if (pdata)
@@ -521,7 +523,8 @@ static int wm831x_buckv_probe(struct platform_device *pdev)
config.driver_data = dcdc;
config.regmap = wm831x->regmap;
- dcdc->regulator = regulator_register(&dcdc->desc, &config);
+ dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
+ &config);
if (IS_ERR(dcdc->regulator)) {
ret = PTR_ERR(dcdc->regulator);
dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
@@ -530,57 +533,35 @@ static int wm831x_buckv_probe(struct platform_device *pdev)
}
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
- ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
- IRQF_TRIGGER_RISING, dcdc->name, dcdc);
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ wm831x_dcdc_uv_irq,
+ IRQF_TRIGGER_RISING, dcdc->name, dcdc);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
irq, ret);
- goto err_regulator;
+ goto err;
}
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC"));
- ret = request_threaded_irq(irq, NULL, wm831x_dcdc_oc_irq,
- IRQF_TRIGGER_RISING, dcdc->name, dcdc);
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ wm831x_dcdc_oc_irq,
+ IRQF_TRIGGER_RISING, dcdc->name, dcdc);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request HC IRQ %d: %d\n",
irq, ret);
- goto err_uv;
+ goto err;
}
platform_set_drvdata(pdev, dcdc);
return 0;
-err_uv:
- free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")),
- dcdc);
-err_regulator:
- regulator_unregister(dcdc->regulator);
err:
- if (dcdc->dvs_gpio)
- gpio_free(dcdc->dvs_gpio);
return ret;
}
-static int wm831x_buckv_remove(struct platform_device *pdev)
-{
- struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
- struct wm831x *wm831x = dcdc->wm831x;
-
- free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC")),
- dcdc);
- free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")),
- dcdc);
- regulator_unregister(dcdc->regulator);
- if (dcdc->dvs_gpio)
- gpio_free(dcdc->dvs_gpio);
-
- return 0;
-}
-
static struct platform_driver wm831x_buckv_driver = {
.probe = wm831x_buckv_probe,
- .remove = wm831x_buckv_remove,
.driver = {
.name = "wm831x-buckv",
.owner = THIS_MODULE,
@@ -681,7 +662,8 @@ static int wm831x_buckp_probe(struct platform_device *pdev)
config.driver_data = dcdc;
config.regmap = wm831x->regmap;
- dcdc->regulator = regulator_register(&dcdc->desc, &config);
+ dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
+ &config);
if (IS_ERR(dcdc->regulator)) {
ret = PTR_ERR(dcdc->regulator);
dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
@@ -690,38 +672,25 @@ static int wm831x_buckp_probe(struct platform_device *pdev)
}
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
- ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
- IRQF_TRIGGER_RISING, dcdc->name, dcdc);
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ wm831x_dcdc_uv_irq,
+ IRQF_TRIGGER_RISING, dcdc->name, dcdc);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
irq, ret);
- goto err_regulator;
+ goto err;
}
platform_set_drvdata(pdev, dcdc);
return 0;
-err_regulator:
- regulator_unregister(dcdc->regulator);
err:
return ret;
}
-static int wm831x_buckp_remove(struct platform_device *pdev)
-{
- struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
-
- free_irq(wm831x_irq(dcdc->wm831x, platform_get_irq_byname(pdev, "UV")),
- dcdc);
- regulator_unregister(dcdc->regulator);
-
- return 0;
-}
-
static struct platform_driver wm831x_buckp_driver = {
.probe = wm831x_buckp_probe,
- .remove = wm831x_buckp_remove,
.driver = {
.name = "wm831x-buckp",
.owner = THIS_MODULE,
@@ -813,7 +782,8 @@ static int wm831x_boostp_probe(struct platform_device *pdev)
config.driver_data = dcdc;
config.regmap = wm831x->regmap;
- dcdc->regulator = regulator_register(&dcdc->desc, &config);
+ dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
+ &config);
if (IS_ERR(dcdc->regulator)) {
ret = PTR_ERR(dcdc->regulator);
dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
@@ -822,39 +792,26 @@ static int wm831x_boostp_probe(struct platform_device *pdev)
}
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
- ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
- IRQF_TRIGGER_RISING, dcdc->name,
- dcdc);
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ wm831x_dcdc_uv_irq,
+ IRQF_TRIGGER_RISING, dcdc->name,
+ dcdc);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
irq, ret);
- goto err_regulator;
+ goto err;
}
platform_set_drvdata(pdev, dcdc);
return 0;
-err_regulator:
- regulator_unregister(dcdc->regulator);
err:
return ret;
}
-static int wm831x_boostp_remove(struct platform_device *pdev)
-{
- struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
-
- free_irq(wm831x_irq(dcdc->wm831x, platform_get_irq_byname(pdev, "UV")),
- dcdc);
- regulator_unregister(dcdc->regulator);
-
- return 0;
-}
-
static struct platform_driver wm831x_boostp_driver = {
.probe = wm831x_boostp_probe,
- .remove = wm831x_boostp_remove,
.driver = {
.name = "wm831x-boostp",
.owner = THIS_MODULE,
@@ -914,7 +871,8 @@ static int wm831x_epe_probe(struct platform_device *pdev)
config.driver_data = dcdc;
config.regmap = wm831x->regmap;
- dcdc->regulator = regulator_register(&dcdc->desc, &config);
+ dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
+ &config);
if (IS_ERR(dcdc->regulator)) {
ret = PTR_ERR(dcdc->regulator);
dev_err(wm831x->dev, "Failed to register EPE%d: %d\n",
@@ -930,18 +888,8 @@ err:
return ret;
}
-static int wm831x_epe_remove(struct platform_device *pdev)
-{
- struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
-
- regulator_unregister(dcdc->regulator);
-
- return 0;
-}
-
static struct platform_driver wm831x_epe_driver = {
.probe = wm831x_epe_probe,
- .remove = wm831x_epe_remove,
.driver = {
.name = "wm831x-epe",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c
index 4eb373de1fac..0339b886df5d 100644
--- a/drivers/regulator/wm831x-isink.c
+++ b/drivers/regulator/wm831x-isink.c
@@ -194,7 +194,8 @@ static int wm831x_isink_probe(struct platform_device *pdev)
config.init_data = pdata->isink[id];
config.driver_data = isink;
- isink->regulator = regulator_register(&isink->desc, &config);
+ isink->regulator = devm_regulator_register(&pdev->dev, &isink->desc,
+ &config);
if (IS_ERR(isink->regulator)) {
ret = PTR_ERR(isink->regulator);
dev_err(wm831x->dev, "Failed to register ISINK%d: %d\n",
@@ -203,38 +204,26 @@ static int wm831x_isink_probe(struct platform_device *pdev)
}
irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0));
- ret = request_threaded_irq(irq, NULL, wm831x_isink_irq,
- IRQF_TRIGGER_RISING, isink->name, isink);
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ wm831x_isink_irq,
+ IRQF_TRIGGER_RISING, isink->name,
+ isink);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request ISINK IRQ %d: %d\n",
irq, ret);
- goto err_regulator;
+ goto err;
}
platform_set_drvdata(pdev, isink);
return 0;
-err_regulator:
- regulator_unregister(isink->regulator);
err:
return ret;
}
-static int wm831x_isink_remove(struct platform_device *pdev)
-{
- struct wm831x_isink *isink = platform_get_drvdata(pdev);
-
- free_irq(wm831x_irq(isink->wm831x, platform_get_irq(pdev, 0)), isink);
-
- regulator_unregister(isink->regulator);
-
- return 0;
-}
-
static struct platform_driver wm831x_isink_driver = {
.probe = wm831x_isink_probe,
- .remove = wm831x_isink_remove,
.driver = {
.name = "wm831x-isink",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c
index 1432b26ef2e9..482ebe8f47aa 100644
--- a/drivers/regulator/wm831x-ldo.c
+++ b/drivers/regulator/wm831x-ldo.c
@@ -63,7 +63,7 @@ static irqreturn_t wm831x_ldo_uv_irq(int irq, void *data)
*/
static const struct regulator_linear_range wm831x_gp_ldo_ranges[] = {
- { .min_uV = 900000, .max_uV = 1650000, .min_sel = 0, .max_sel = 14,
+ { .min_uV = 900000, .max_uV = 1600000, .min_sel = 0, .max_sel = 14,
.uV_step = 50000 },
{ .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31,
.uV_step = 100000 },
@@ -279,7 +279,8 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev)
config.driver_data = ldo;
config.regmap = wm831x->regmap;
- ldo->regulator = regulator_register(&ldo->desc, &config);
+ ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,
+ &config);
if (IS_ERR(ldo->regulator)) {
ret = PTR_ERR(ldo->regulator);
dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
@@ -288,39 +289,26 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev)
}
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
- ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq,
- IRQF_TRIGGER_RISING, ldo->name,
- ldo);
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ wm831x_ldo_uv_irq,
+ IRQF_TRIGGER_RISING, ldo->name,
+ ldo);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
irq, ret);
- goto err_regulator;
+ goto err;
}
platform_set_drvdata(pdev, ldo);
return 0;
-err_regulator:
- regulator_unregister(ldo->regulator);
err:
return ret;
}
-static int wm831x_gp_ldo_remove(struct platform_device *pdev)
-{
- struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
-
- free_irq(wm831x_irq(ldo->wm831x,
- platform_get_irq_byname(pdev, "UV")), ldo);
- regulator_unregister(ldo->regulator);
-
- return 0;
-}
-
static struct platform_driver wm831x_gp_ldo_driver = {
.probe = wm831x_gp_ldo_probe,
- .remove = wm831x_gp_ldo_remove,
.driver = {
.name = "wm831x-ldo",
.owner = THIS_MODULE,
@@ -332,7 +320,7 @@ static struct platform_driver wm831x_gp_ldo_driver = {
*/
static const struct regulator_linear_range wm831x_aldo_ranges[] = {
- { .min_uV = 1000000, .max_uV = 1650000, .min_sel = 0, .max_sel = 12,
+ { .min_uV = 1000000, .max_uV = 1600000, .min_sel = 0, .max_sel = 12,
.uV_step = 50000 },
{ .min_uV = 1700000, .max_uV = 3500000, .min_sel = 13, .max_sel = 31,
.uV_step = 100000 },
@@ -505,7 +493,8 @@ static int wm831x_aldo_probe(struct platform_device *pdev)
config.driver_data = ldo;
config.regmap = wm831x->regmap;
- ldo->regulator = regulator_register(&ldo->desc, &config);
+ ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,
+ &config);
if (IS_ERR(ldo->regulator)) {
ret = PTR_ERR(ldo->regulator);
dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
@@ -514,38 +503,25 @@ static int wm831x_aldo_probe(struct platform_device *pdev)
}
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
- ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq,
- IRQF_TRIGGER_RISING, ldo->name, ldo);
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ wm831x_ldo_uv_irq,
+ IRQF_TRIGGER_RISING, ldo->name, ldo);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
irq, ret);
- goto err_regulator;
+ goto err;
}
platform_set_drvdata(pdev, ldo);
return 0;
-err_regulator:
- regulator_unregister(ldo->regulator);
err:
return ret;
}
-static int wm831x_aldo_remove(struct platform_device *pdev)
-{
- struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
-
- free_irq(wm831x_irq(ldo->wm831x, platform_get_irq_byname(pdev, "UV")),
- ldo);
- regulator_unregister(ldo->regulator);
-
- return 0;
-}
-
static struct platform_driver wm831x_aldo_driver = {
.probe = wm831x_aldo_probe,
- .remove = wm831x_aldo_remove,
.driver = {
.name = "wm831x-aldo",
.owner = THIS_MODULE,
@@ -663,7 +639,8 @@ static int wm831x_alive_ldo_probe(struct platform_device *pdev)
config.driver_data = ldo;
config.regmap = wm831x->regmap;
- ldo->regulator = regulator_register(&ldo->desc, &config);
+ ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,
+ &config);
if (IS_ERR(ldo->regulator)) {
ret = PTR_ERR(ldo->regulator);
dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
@@ -679,18 +656,8 @@ err:
return ret;
}
-static int wm831x_alive_ldo_remove(struct platform_device *pdev)
-{
- struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
-
- regulator_unregister(ldo->regulator);
-
- return 0;
-}
-
static struct platform_driver wm831x_alive_ldo_driver = {
.probe = wm831x_alive_ldo_probe,
- .remove = wm831x_alive_ldo_remove,
.driver = {
.name = "wm831x-alive-ldo",
.owner = THIS_MODULE,
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index 835b5f0f344e..017e8695ca71 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -543,7 +543,7 @@ static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev,
}
static const struct regulator_linear_range wm8350_ldo_ranges[] = {
- { .min_uV = 900000, .max_uV = 1750000, .min_sel = 0, .max_sel = 15,
+ { .min_uV = 900000, .max_uV = 1650000, .min_sel = 0, .max_sel = 15,
.uV_step = 50000 },
{ .min_uV = 1800000, .max_uV = 3300000, .min_sel = 16, .max_sel = 31,
.uV_step = 100000 },
@@ -1206,7 +1206,8 @@ static int wm8350_regulator_probe(struct platform_device *pdev)
config.regmap = wm8350->regmap;
/* register regulator */
- rdev = regulator_register(&wm8350_reg[pdev->id], &config);
+ rdev = devm_regulator_register(&pdev->dev, &wm8350_reg[pdev->id],
+ &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register %s\n",
wm8350_reg[pdev->id].name);
@@ -1217,7 +1218,6 @@ static int wm8350_regulator_probe(struct platform_device *pdev)
ret = wm8350_register_irq(wm8350, wm8350_reg[pdev->id].irq,
pmic_uv_handler, 0, "UV", rdev);
if (ret < 0) {
- regulator_unregister(rdev);
dev_err(&pdev->dev, "failed to register regulator %s IRQ\n",
wm8350_reg[pdev->id].name);
return ret;
@@ -1233,8 +1233,6 @@ static int wm8350_regulator_remove(struct platform_device *pdev)
wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq, rdev);
- regulator_unregister(rdev);
-
return 0;
}
diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
index 58f51bec13f2..870b52f709bc 100644
--- a/drivers/regulator/wm8400-regulator.c
+++ b/drivers/regulator/wm8400-regulator.c
@@ -219,7 +219,8 @@ static int wm8400_regulator_probe(struct platform_device *pdev)
config.driver_data = wm8400;
config.regmap = wm8400->regmap;
- rdev = regulator_register(&regulators[pdev->id], &config);
+ rdev = devm_regulator_register(&pdev->dev, &regulators[pdev->id],
+ &config);
if (IS_ERR(rdev))
return PTR_ERR(rdev);
@@ -228,21 +229,11 @@ static int wm8400_regulator_probe(struct platform_device *pdev)
return 0;
}
-static int wm8400_regulator_remove(struct platform_device *pdev)
-{
- struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
- regulator_unregister(rdev);
-
- return 0;
-}
-
static struct platform_driver wm8400_regulator_driver = {
.driver = {
.name = "wm8400-regulator",
},
.probe = wm8400_regulator_probe,
- .remove = wm8400_regulator_remove,
};
/**
diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c
index 5ee2a208457c..71c5911f2e71 100644
--- a/drivers/regulator/wm8994-regulator.c
+++ b/drivers/regulator/wm8994-regulator.c
@@ -165,7 +165,9 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
ldo->init_data = *pdata->ldo[id].init_data;
}
- ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &config);
+ ldo->regulator = devm_regulator_register(&pdev->dev,
+ &wm8994_ldo_desc[id],
+ &config);
if (IS_ERR(ldo->regulator)) {
ret = PTR_ERR(ldo->regulator);
dev_err(wm8994->dev, "Failed to register LDO%d: %d\n",
@@ -181,18 +183,8 @@ err:
return ret;
}
-static int wm8994_ldo_remove(struct platform_device *pdev)
-{
- struct wm8994_ldo *ldo = platform_get_drvdata(pdev);
-
- regulator_unregister(ldo->regulator);
-
- return 0;
-}
-
static struct platform_driver wm8994_ldo_driver = {
.probe = wm8994_ldo_probe,
- .remove = wm8994_ldo_remove,
.driver = {
.name = "wm8994-ldo",
.owner = THIS_MODULE,
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 72c5cdbe0791..544be722937c 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -72,6 +72,7 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
} else
err = -EINVAL;
+ pm_stay_awake(rtc->dev.parent);
mutex_unlock(&rtc->ops_lock);
/* A timer might have just expired */
schedule_work(&rtc->irqwork);
@@ -113,6 +114,7 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs)
err = -EINVAL;
}
+ pm_stay_awake(rtc->dev.parent);
mutex_unlock(&rtc->ops_lock);
/* A timer might have just expired */
schedule_work(&rtc->irqwork);
@@ -771,9 +773,10 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
alarm.time = rtc_ktime_to_tm(timer->node.expires);
alarm.enabled = 1;
err = __rtc_set_alarm(rtc, &alarm);
- if (err == -ETIME)
+ if (err == -ETIME) {
+ pm_stay_awake(rtc->dev.parent);
schedule_work(&rtc->irqwork);
- else if (err) {
+ } else if (err) {
timerqueue_del(&rtc->timerqueue, &timer->node);
timer->enabled = 0;
return err;
@@ -818,8 +821,10 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer)
alarm.time = rtc_ktime_to_tm(next->expires);
alarm.enabled = 1;
err = __rtc_set_alarm(rtc, &alarm);
- if (err == -ETIME)
+ if (err == -ETIME) {
+ pm_stay_awake(rtc->dev.parent);
schedule_work(&rtc->irqwork);
+ }
}
}
@@ -845,7 +850,6 @@ void rtc_timer_do_work(struct work_struct *work)
mutex_lock(&rtc->ops_lock);
again:
- pm_relax(rtc->dev.parent);
__rtc_read_time(rtc, &tm);
now = rtc_tm_to_ktime(tm);
while ((next = timerqueue_getnext(&rtc->timerqueue))) {
@@ -880,6 +884,7 @@ again:
} else
rtc_alarm_disable(rtc);
+ pm_relax(rtc->dev.parent);
mutex_unlock(&rtc->ops_lock);
}
diff --git a/drivers/s390/block/scm_blk.h b/drivers/s390/block/scm_blk.h
index 8b387b32fd62..e59331e6c2e5 100644
--- a/drivers/s390/block/scm_blk.h
+++ b/drivers/s390/block/scm_blk.h
@@ -107,7 +107,7 @@ extern debug_info_t *scm_debug;
static inline void SCM_LOG_HEX(int level, void *data, int length)
{
- if (level > scm_debug->level)
+ if (!debug_level_enabled(scm_debug, level))
return;
while (length > 0) {
debug_event(scm_debug, level, data, length);
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index 8cd34bf644b3..77df9cb00688 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -145,9 +145,11 @@ bool __init sclp_has_linemode(void)
if (sccb->header.response_code != 0x20)
return 0;
- if (sccb->sclp_send_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))
- return 1;
- return 0;
+ if (!(sccb->sclp_send_mask & (EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK)))
+ return 0;
+ if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK)))
+ return 0;
+ return 1;
}
bool __init sclp_has_vt220(void)
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index a0f47c83fd62..3f4ca4e09a4c 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -810,7 +810,7 @@ static void tty3270_resize_work(struct work_struct *work)
struct winsize ws;
screen = tty3270_alloc_screen(tp->n_rows, tp->n_cols);
- if (!screen)
+ if (IS_ERR(screen))
return;
/* Switch to new output size */
spin_lock_bh(&tp->view.lock);
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c
index d028fd800c9c..f055df0b167f 100644
--- a/drivers/s390/cio/airq.c
+++ b/drivers/s390/cio/airq.c
@@ -194,15 +194,14 @@ EXPORT_SYMBOL(airq_iv_release);
*/
unsigned long airq_iv_alloc_bit(struct airq_iv *iv)
{
- const unsigned long be_to_le = BITS_PER_LONG - 1;
unsigned long bit;
if (!iv->avail)
return -1UL;
spin_lock(&iv->lock);
- bit = find_first_bit_left(iv->avail, iv->bits);
+ bit = find_first_bit_inv(iv->avail, iv->bits);
if (bit < iv->bits) {
- clear_bit(bit ^ be_to_le, iv->avail);
+ clear_bit_inv(bit, iv->avail);
if (bit >= iv->end)
iv->end = bit + 1;
} else
@@ -220,19 +219,17 @@ EXPORT_SYMBOL(airq_iv_alloc_bit);
*/
void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit)
{
- const unsigned long be_to_le = BITS_PER_LONG - 1;
-
if (!iv->avail)
return;
spin_lock(&iv->lock);
/* Clear (possibly left over) interrupt bit */
- clear_bit(bit ^ be_to_le, iv->vector);
+ clear_bit_inv(bit, iv->vector);
/* Make the bit position available again */
- set_bit(bit ^ be_to_le, iv->avail);
+ set_bit_inv(bit, iv->avail);
if (bit == iv->end - 1) {
/* Find new end of bit-field */
while (--iv->end > 0)
- if (!test_bit((iv->end - 1) ^ be_to_le, iv->avail))
+ if (!test_bit_inv(iv->end - 1, iv->avail))
break;
}
spin_unlock(&iv->lock);
@@ -251,15 +248,13 @@ EXPORT_SYMBOL(airq_iv_free_bit);
unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start,
unsigned long end)
{
- const unsigned long be_to_le = BITS_PER_LONG - 1;
unsigned long bit;
/* Find non-zero bit starting from 'ivs->next'. */
- bit = find_next_bit_left(iv->vector, end, start);
+ bit = find_next_bit_inv(iv->vector, end, start);
if (bit >= end)
return -1UL;
- /* Clear interrupt bit (find left uses big-endian bit numbers) */
- clear_bit(bit ^ be_to_le, iv->vector);
+ clear_bit_inv(bit, iv->vector);
return bit;
}
EXPORT_SYMBOL(airq_iv_scan);
diff --git a/drivers/s390/cio/eadm_sch.c b/drivers/s390/cio/eadm_sch.c
index d9eddcba7e88..6b54d8a05cd4 100644
--- a/drivers/s390/cio/eadm_sch.c
+++ b/drivers/s390/cio/eadm_sch.c
@@ -42,7 +42,7 @@ static debug_info_t *eadm_debug;
static void EADM_LOG_HEX(int level, void *data, int length)
{
- if (level > eadm_debug->level)
+ if (!debug_level_enabled(eadm_debug, level))
return;
while (length > 0) {
debug_event(eadm_debug, level, data, length);
diff --git a/drivers/s390/cio/qdio_debug.h b/drivers/s390/cio/qdio_debug.h
index 647b422bb22a..dfac9bfefea3 100644
--- a/drivers/s390/cio/qdio_debug.h
+++ b/drivers/s390/cio/qdio_debug.h
@@ -16,12 +16,6 @@
extern debug_info_t *qdio_dbf_setup;
extern debug_info_t *qdio_dbf_error;
-/* sort out low debug levels early to avoid wasted sprints */
-static inline int qdio_dbf_passes(debug_info_t *dbf_grp, int level)
-{
- return (level <= dbf_grp->level);
-}
-
#define DBF_ERR 3 /* error conditions */
#define DBF_WARN 4 /* warning conditions */
#define DBF_INFO 6 /* informational */
@@ -65,7 +59,7 @@ static inline void DBF_ERROR_HEX(void *addr, int len)
#define DBF_DEV_EVENT(level, device, text...) \
do { \
char debug_buffer[QDIO_DBF_LEN]; \
- if (qdio_dbf_passes(device->debug_area, level)) { \
+ if (debug_level_enabled(device->debug_area, level)) { \
snprintf(debug_buffer, QDIO_DBF_LEN, text); \
debug_text_event(device->debug_area, level, debug_buffer); \
} \
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 8ed52aa49122..556e2b8612ad 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -528,7 +528,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
case SLSB_P_INPUT_PRIMED:
inbound_primed(q, count);
q->first_to_check = add_buf(q->first_to_check, count);
- if (atomic_sub(count, &q->nr_buf_used) == 0)
+ if (atomic_sub_return(count, &q->nr_buf_used) == 0)
qperf_inc(q, inbound_queue_full);
if (q->irq_ptr->perf_stat_enabled)
account_sbals(q, count);
diff --git a/drivers/s390/crypto/zcrypt_debug.h b/drivers/s390/crypto/zcrypt_debug.h
index 841ea72e4a4e..28d9349de1ad 100644
--- a/drivers/s390/crypto/zcrypt_debug.h
+++ b/drivers/s390/crypto/zcrypt_debug.h
@@ -11,12 +11,6 @@
/* that gives us 15 characters in the text event views */
#define ZCRYPT_DBF_LEN 16
-/* sort out low debug levels early to avoid wasted sprints */
-static inline int zcrypt_dbf_passes(debug_info_t *dbf_grp, int level)
-{
- return (level <= dbf_grp->level);
-}
-
#define DBF_ERR 3 /* error conditions */
#define DBF_WARN 4 /* warning conditions */
#define DBF_INFO 6 /* informational */
@@ -25,7 +19,7 @@ static inline int zcrypt_dbf_passes(debug_info_t *dbf_grp, int level)
#define ZCRYPT_DBF_COMMON(level, text...) \
do { \
- if (zcrypt_dbf_passes(zcrypt_dbf_common, level)) { \
+ if (debug_level_enabled(zcrypt_dbf_common, level)) { \
char debug_buffer[ZCRYPT_DBF_LEN]; \
snprintf(debug_buffer, ZCRYPT_DBF_LEN, text); \
debug_text_event(zcrypt_dbf_common, level, \
@@ -35,7 +29,7 @@ static inline int zcrypt_dbf_passes(debug_info_t *dbf_grp, int level)
#define ZCRYPT_DBF_DEVICES(level, text...) \
do { \
- if (zcrypt_dbf_passes(zcrypt_dbf_devices, level)) { \
+ if (debug_level_enabled(zcrypt_dbf_devices, level)) { \
char debug_buffer[ZCRYPT_DBF_LEN]; \
snprintf(debug_buffer, ZCRYPT_DBF_LEN, text); \
debug_text_event(zcrypt_dbf_devices, level, \
@@ -45,7 +39,7 @@ static inline int zcrypt_dbf_passes(debug_info_t *dbf_grp, int level)
#define ZCRYPT_DBF_DEV(level, device, text...) \
do { \
- if (zcrypt_dbf_passes(device->dbf_area, level)) { \
+ if (debug_level_enabled(device->dbf_area, level)) { \
char debug_buffer[ZCRYPT_DBF_LEN]; \
snprintf(debug_buffer, ZCRYPT_DBF_LEN, text); \
debug_text_event(device->dbf_area, level, \
diff --git a/drivers/s390/net/claw.h b/drivers/s390/net/claw.h
index 1bc5904df19f..3339b9b607b3 100644
--- a/drivers/s390/net/claw.h
+++ b/drivers/s390/net/claw.h
@@ -114,15 +114,9 @@ do { \
debug_event(claw_dbf_##name,level,(void*)(addr),len); \
} while (0)
-/* Allow to sort out low debug levels early to avoid wasted sprints */
-static inline int claw_dbf_passes(debug_info_t *dbf_grp, int level)
-{
- return (level <= dbf_grp->level);
-}
-
#define CLAW_DBF_TEXT_(level,name,text...) \
do { \
- if (claw_dbf_passes(claw_dbf_##name, level)) { \
+ if (debug_level_enabled(claw_dbf_##name, level)) { \
sprintf(debug_buffer, text); \
debug_text_event(claw_dbf_##name, level, \
debug_buffer); \
diff --git a/drivers/s390/net/ctcm_dbug.c b/drivers/s390/net/ctcm_dbug.c
index 6514e1cb3f1c..8363f1c966ef 100644
--- a/drivers/s390/net/ctcm_dbug.c
+++ b/drivers/s390/net/ctcm_dbug.c
@@ -66,7 +66,7 @@ void ctcm_dbf_longtext(enum ctcm_dbf_names dbf_nix, int level, char *fmt, ...)
char dbf_txt_buf[64];
va_list args;
- if (level > (ctcm_dbf[dbf_nix].id)->level)
+ if (!debug_level_enabled(ctcm_dbf[dbf_nix].id, level))
return;
va_start(args, fmt);
vsnprintf(dbf_txt_buf, sizeof(dbf_txt_buf), fmt, args);
diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h
index 8c03392ac833..150fcb4cebc3 100644
--- a/drivers/s390/net/lcs.h
+++ b/drivers/s390/net/lcs.h
@@ -16,15 +16,9 @@ do { \
debug_event(lcs_dbf_##name,level,(void*)(addr),len); \
} while (0)
-/* Allow to sort out low debug levels early to avoid wasted sprints */
-static inline int lcs_dbf_passes(debug_info_t *dbf_grp, int level)
-{
- return (level <= dbf_grp->level);
-}
-
#define LCS_DBF_TEXT_(level,name,text...) \
do { \
- if (lcs_dbf_passes(lcs_dbf_##name, level)) { \
+ if (debug_level_enabled(lcs_dbf_##name, level)) { \
sprintf(debug_buffer, text); \
debug_text_event(lcs_dbf_##name, level, debug_buffer); \
} \
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 279ad504ec3c..9b333fcf1a4c 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -105,15 +105,9 @@ MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver");
DECLARE_PER_CPU(char[256], iucv_dbf_txt_buf);
-/* Allow to sort out low debug levels early to avoid wasted sprints */
-static inline int iucv_dbf_passes(debug_info_t *dbf_grp, int level)
-{
- return (level <= dbf_grp->level);
-}
-
#define IUCV_DBF_TEXT_(name, level, text...) \
do { \
- if (iucv_dbf_passes(iucv_dbf_##name, level)) { \
+ if (debug_level_enabled(iucv_dbf_##name, level)) { \
char* __buf = get_cpu_var(iucv_dbf_txt_buf); \
sprintf(__buf, text); \
debug_text_event(iucv_dbf_##name, level, __buf); \
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 0a328d0d11be..d7b66a28fe75 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -5096,7 +5096,7 @@ void qeth_dbf_longtext(debug_info_t *id, int level, char *fmt, ...)
char dbf_txt_buf[32];
va_list args;
- if (level > id->level)
+ if (!debug_level_enabled(id, level))
return;
va_start(args, fmt);
vsnprintf(dbf_txt_buf, sizeof(dbf_txt_buf), fmt, args);
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
index 3ac7a4b30dd9..0be3d48681ae 100644
--- a/drivers/s390/scsi/zfcp_dbf.h
+++ b/drivers/s390/scsi/zfcp_dbf.h
@@ -278,7 +278,7 @@ struct zfcp_dbf {
static inline
void zfcp_dbf_hba_fsf_resp(char *tag, int level, struct zfcp_fsf_req *req)
{
- if (level <= req->adapter->dbf->hba->level)
+ if (debug_level_enabled(req->adapter->dbf->hba, level))
zfcp_dbf_hba_fsf_res(tag, req);
}
@@ -317,7 +317,7 @@ void _zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *scmd,
struct zfcp_adapter *adapter = (struct zfcp_adapter *)
scmd->device->host->hostdata[0];
- if (level <= adapter->dbf->scsi->level)
+ if (debug_level_enabled(adapter->dbf->scsi, level))
zfcp_dbf_scsi(tag, scmd, req);
}
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index f8ca7becacca..7591fa4e28bb 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -766,49 +766,20 @@ bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad)
bfad->pcidev = pdev;
/* Adjust PCIe Maximum Read Request Size */
- if (pcie_max_read_reqsz > 0) {
- int pcie_cap_reg;
- u16 pcie_dev_ctl;
- u16 mask = 0xffff;
-
- switch (pcie_max_read_reqsz) {
- case 128:
- mask = 0x0;
- break;
- case 256:
- mask = 0x1000;
- break;
- case 512:
- mask = 0x2000;
- break;
- case 1024:
- mask = 0x3000;
- break;
- case 2048:
- mask = 0x4000;
- break;
- case 4096:
- mask = 0x5000;
- break;
- default:
- break;
- }
-
- pcie_cap_reg = pci_find_capability(pdev, PCI_CAP_ID_EXP);
- if (mask != 0xffff && pcie_cap_reg) {
- pcie_cap_reg += 0x08;
- pci_read_config_word(pdev, pcie_cap_reg, &pcie_dev_ctl);
- if ((pcie_dev_ctl & 0x7000) != mask) {
- printk(KERN_WARNING "BFA[%s]: "
+ if (pci_is_pcie(pdev) && pcie_max_read_reqsz) {
+ if (pcie_max_read_reqsz >= 128 &&
+ pcie_max_read_reqsz <= 4096 &&
+ is_power_of_2(pcie_max_read_reqsz)) {
+ int max_rq = pcie_get_readrq(pdev);
+ printk(KERN_WARNING "BFA[%s]: "
"pcie_max_read_request_size is %d, "
- "reset to %d\n", bfad->pci_name,
- (1 << ((pcie_dev_ctl & 0x7000) >> 12)) << 7,
+ "reset to %d\n", bfad->pci_name, max_rq,
pcie_max_read_reqsz);
-
- pcie_dev_ctl &= ~0x7000;
- pci_write_config_word(pdev, pcie_cap_reg,
- pcie_dev_ctl | mask);
- }
+ pcie_set_readrq(pdev, pcie_max_read_reqsz);
+ } else {
+ printk(KERN_WARNING "BFA[%s]: invalid "
+ "pcie_max_read_request_size %d ignored\n",
+ bfad->pci_name, pcie_max_read_reqsz);
}
}
diff --git a/drivers/scsi/csiostor/csio_hw.c b/drivers/scsi/csiostor/csio_hw.c
index 0eb35b9b3784..0eaec4748957 100644
--- a/drivers/scsi/csiostor/csio_hw.c
+++ b/drivers/scsi/csiostor/csio_hw.c
@@ -852,22 +852,6 @@ csio_hw_get_flash_params(struct csio_hw *hw)
return 0;
}
-static void
-csio_set_pcie_completion_timeout(struct csio_hw *hw, u8 range)
-{
- uint16_t val;
- int pcie_cap;
-
- if (!csio_pci_capability(hw->pdev, PCI_CAP_ID_EXP, &pcie_cap)) {
- pci_read_config_word(hw->pdev,
- pcie_cap + PCI_EXP_DEVCTL2, &val);
- val &= 0xfff0;
- val |= range ;
- pci_write_config_word(hw->pdev,
- pcie_cap + PCI_EXP_DEVCTL2, val);
- }
-}
-
/*****************************************************************************/
/* HW State machine assists */
/*****************************************************************************/
@@ -2069,8 +2053,10 @@ csio_hw_configure(struct csio_hw *hw)
goto out;
}
- /* Set pci completion timeout value to 4 seconds. */
- csio_set_pcie_completion_timeout(hw, 0xd);
+ /* Set PCIe completion timeout to 4 seconds */
+ if (pci_is_pcie(hw->pdev))
+ pcie_capability_clear_and_set_word(hw->pdev, PCI_EXP_DEVCTL2,
+ PCI_EXP_DEVCTL2_COMP_TIMEOUT, 0xd);
hw->chip_ops->chip_set_mem_win(hw, MEMWIN_CSIOSTOR);
diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c
index c9382d6eee78..1f4f22fe8281 100644
--- a/drivers/scsi/fcoe/fcoe_sysfs.c
+++ b/drivers/scsi/fcoe/fcoe_sysfs.c
@@ -553,16 +553,20 @@ static struct device_type fcoe_fcf_device_type = {
.release = fcoe_fcf_device_release,
};
-static struct bus_attribute fcoe_bus_attr_group[] = {
- __ATTR(ctlr_create, S_IWUSR, NULL, fcoe_ctlr_create_store),
- __ATTR(ctlr_destroy, S_IWUSR, NULL, fcoe_ctlr_destroy_store),
- __ATTR_NULL
+static BUS_ATTR(ctlr_create, S_IWUSR, NULL, fcoe_ctlr_create_store);
+static BUS_ATTR(ctlr_destroy, S_IWUSR, NULL, fcoe_ctlr_destroy_store);
+
+static struct attribute *fcoe_bus_attrs[] = {
+ &bus_attr_ctlr_create.attr,
+ &bus_attr_ctlr_destroy.attr,
+ NULL,
};
+ATTRIBUTE_GROUPS(fcoe_bus);
static struct bus_type fcoe_bus_type = {
.name = "fcoe",
.match = &fcoe_bus_match,
- .bus_attrs = fcoe_bus_attr_group,
+ .bus_groups = fcoe_bus_groups,
};
/**
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
index 62ee7131b204..30d20e74e48a 100644
--- a/drivers/scsi/qla2xxx/qla_mr.c
+++ b/drivers/scsi/qla2xxx/qla_mr.c
@@ -507,7 +507,7 @@ qlafx00_pci_config(scsi_qla_host_t *vha)
pci_write_config_word(ha->pdev, PCI_COMMAND, w);
/* PCIe -- adjust Maximum Read Request Size (2048). */
- if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP))
+ if (pci_is_pcie(ha->pdev))
pcie_set_readrq(ha->pdev, 2048);
ha->chip_revision = ha->pdev->revision;
@@ -660,10 +660,8 @@ char *
qlafx00_pci_info_str(struct scsi_qla_host *vha, char *str)
{
struct qla_hw_data *ha = vha->hw;
- int pcie_reg;
- pcie_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP);
- if (pcie_reg) {
+ if (pci_is_pcie(ha->pdev)) {
strcpy(str, "PCIe iSA");
return str;
}
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index b9c53cc40e1f..734eaa50b3cd 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -264,6 +264,7 @@ config SPI_FSL_SPI
config SPI_FSL_DSPI
tristate "Freescale DSPI controller"
select SPI_BITBANG
+ depends on SOC_VF610 || COMPILE_TEST
help
This enables support for the Freescale DSPI controller in master
mode. VF610 platform uses the controller.
@@ -369,7 +370,7 @@ config SPI_PXA2XX_PCI
config SPI_RSPI
tristate "Renesas RSPI controller"
- depends on SUPERH && SH_DMAE_BASE
+ depends on (SUPERH || ARCH_SHMOBILE) && SH_DMAE_BASE
help
SPI driver for Renesas RSPI blocks.
diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c
index 9a64c3fee218..595b62cb545d 100644
--- a/drivers/spi/spi-altera.c
+++ b/drivers/spi/spi-altera.c
@@ -219,7 +219,7 @@ static int altera_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, hw);
/* setup the state for the bitbang driver */
- hw->bitbang.master = spi_master_get(master);
+ hw->bitbang.master = master;
if (!hw->bitbang.master)
return err;
hw->bitbang.chipselect = altera_spi_chipsel;
diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c
index 37bad952ab38..821bf7ac218d 100644
--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -231,7 +231,7 @@ static int ath79_spi_probe(struct platform_device *pdev)
master->num_chipselect = pdata->num_chipselect;
}
- sp->bitbang.master = spi_master_get(master);
+ sp->bitbang.master = master;
sp->bitbang.chipselect = ath79_spi_chipselect;
sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0;
sp->bitbang.setup_transfer = spi_bitbang_setup_transfer;
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index fd7cc566095a..008bd1d03a6b 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -170,18 +170,18 @@
/* Bit manipulation macros */
#define SPI_BIT(name) \
(1 << SPI_##name##_OFFSET)
-#define SPI_BF(name,value) \
+#define SPI_BF(name, value) \
(((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET)
-#define SPI_BFEXT(name,value) \
+#define SPI_BFEXT(name, value) \
(((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1))
-#define SPI_BFINS(name,value,old) \
- ( ((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \
- | SPI_BF(name,value))
+#define SPI_BFINS(name, value, old) \
+ (((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \
+ | SPI_BF(name, value))
/* Register access macros */
-#define spi_readl(port,reg) \
+#define spi_readl(port, reg) \
__raw_readl((port)->regs + SPI_##reg)
-#define spi_writel(port,reg,value) \
+#define spi_writel(port, reg, value) \
__raw_writel((value), (port)->regs + SPI_##reg)
/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
@@ -1516,7 +1516,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
/* setup spi core then atmel-specific driver state */
ret = -ENOMEM;
- master = spi_alloc_master(&pdev->dev, sizeof *as);
+ master = spi_alloc_master(&pdev->dev, sizeof(*as));
if (!master)
goto out_free;
@@ -1583,7 +1583,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
/* Initialize the hardware */
ret = clk_prepare_enable(clk);
if (ret)
- goto out_unmap_regs;
+ goto out_free_irq;
spi_writel(as, CR, SPI_BIT(SWRST));
spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
if (as->caps.has_wdrbt) {
@@ -1614,6 +1614,7 @@ out_free_dma:
spi_writel(as, CR, SPI_BIT(SWRST));
spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
clk_disable_unprepare(clk);
+out_free_irq:
free_irq(irq, master);
out_unmap_regs:
iounmap(as->regs);
@@ -1675,29 +1676,30 @@ static int atmel_spi_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
-
-static int atmel_spi_suspend(struct platform_device *pdev, pm_message_t mesg)
+#ifdef CONFIG_PM_SLEEP
+static int atmel_spi_suspend(struct device *dev)
{
- struct spi_master *master = platform_get_drvdata(pdev);
+ struct spi_master *master = dev_get_drvdata(dev);
struct atmel_spi *as = spi_master_get_devdata(master);
clk_disable_unprepare(as->clk);
return 0;
}
-static int atmel_spi_resume(struct platform_device *pdev)
+static int atmel_spi_resume(struct device *dev)
{
- struct spi_master *master = platform_get_drvdata(pdev);
+ struct spi_master *master = dev_get_drvdata(dev);
struct atmel_spi *as = spi_master_get_devdata(master);
- return clk_prepare_enable(as->clk);
+ clk_prepare_enable(as->clk);
return 0;
}
+static SIMPLE_DEV_PM_OPS(atmel_spi_pm_ops, atmel_spi_suspend, atmel_spi_resume);
+
+#define ATMEL_SPI_PM_OPS (&atmel_spi_pm_ops)
#else
-#define atmel_spi_suspend NULL
-#define atmel_spi_resume NULL
+#define ATMEL_SPI_PM_OPS NULL
#endif
#if defined(CONFIG_OF)
@@ -1713,10 +1715,9 @@ static struct platform_driver atmel_spi_driver = {
.driver = {
.name = "atmel_spi",
.owner = THIS_MODULE,
+ .pm = ATMEL_SPI_PM_OPS,
.of_match_table = of_match_ptr(atmel_spi_dt_ids),
},
- .suspend = atmel_spi_suspend,
- .resume = atmel_spi_resume,
.probe = atmel_spi_probe,
.remove = atmel_spi_remove,
};
diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c
index 1d00d9b397dd..e06400a3a719 100644
--- a/drivers/spi/spi-au1550.c
+++ b/drivers/spi/spi-au1550.c
@@ -775,7 +775,7 @@ static int au1550_spi_probe(struct platform_device *pdev)
hw = spi_master_get_devdata(master);
- hw->master = spi_master_get(master);
+ hw->master = master;
hw->pdata = dev_get_platdata(&pdev->dev);
hw->dev = &pdev->dev;
diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c
index 91921b5f5817..6c81a5978eca 100644
--- a/drivers/spi/spi-bfin-sport.c
+++ b/drivers/spi/spi-bfin-sport.c
@@ -879,11 +879,10 @@ static int bfin_sport_spi_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
-static int
-bfin_sport_spi_suspend(struct platform_device *pdev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int bfin_sport_spi_suspend(struct device *dev)
{
- struct bfin_sport_spi_master_data *drv_data = platform_get_drvdata(pdev);
+ struct bfin_sport_spi_master_data *drv_data = dev_get_drvdata(dev);
int status;
status = bfin_sport_spi_stop_queue(drv_data);
@@ -896,10 +895,9 @@ bfin_sport_spi_suspend(struct platform_device *pdev, pm_message_t state)
return status;
}
-static int
-bfin_sport_spi_resume(struct platform_device *pdev)
+static int bfin_sport_spi_resume(struct device *dev)
{
- struct bfin_sport_spi_master_data *drv_data = platform_get_drvdata(pdev);
+ struct bfin_sport_spi_master_data *drv_data = dev_get_drvdata(dev);
int status;
/* Enable the SPI interface */
@@ -912,19 +910,22 @@ bfin_sport_spi_resume(struct platform_device *pdev)
return status;
}
+
+static SIMPLE_DEV_PM_OPS(bfin_sport_spi_pm_ops, bfin_sport_spi_suspend,
+ bfin_sport_spi_resume);
+
+#define BFIN_SPORT_SPI_PM_OPS (&bfin_sport_spi_pm_ops)
#else
-# define bfin_sport_spi_suspend NULL
-# define bfin_sport_spi_resume NULL
+#define BFIN_SPORT_SPI_PM_OPS NULL
#endif
static struct platform_driver bfin_sport_spi_driver = {
.driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = BFIN_SPORT_SPI_PM_OPS,
},
.probe = bfin_sport_spi_probe,
.remove = bfin_sport_spi_remove,
- .suspend = bfin_sport_spi_suspend,
- .resume = bfin_sport_spi_resume,
};
module_platform_driver(bfin_sport_spi_driver);
diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c
index 45bdf73d6868..1e2894315bb0 100644
--- a/drivers/spi/spi-bfin5xx.c
+++ b/drivers/spi/spi-bfin5xx.c
@@ -1410,10 +1410,10 @@ static int bfin_spi_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
-static int bfin_spi_suspend(struct platform_device *pdev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int bfin_spi_suspend(struct device *dev)
{
- struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
+ struct bfin_spi_master_data *drv_data = dev_get_drvdata(dev);
int status = 0;
status = bfin_spi_stop_queue(drv_data);
@@ -1432,9 +1432,9 @@ static int bfin_spi_suspend(struct platform_device *pdev, pm_message_t state)
return 0;
}
-static int bfin_spi_resume(struct platform_device *pdev)
+static int bfin_spi_resume(struct device *dev)
{
- struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
+ struct bfin_spi_master_data *drv_data = dev_get_drvdata(dev);
int status = 0;
bfin_write(&drv_data->regs->ctl, drv_data->ctrl_reg);
@@ -1443,25 +1443,27 @@ static int bfin_spi_resume(struct platform_device *pdev)
/* Start the queue running */
status = bfin_spi_start_queue(drv_data);
if (status != 0) {
- dev_err(&pdev->dev, "problem starting queue (%d)\n", status);
+ dev_err(dev, "problem starting queue (%d)\n", status);
return status;
}
return 0;
}
+
+static SIMPLE_DEV_PM_OPS(bfin_spi_pm_ops, bfin_spi_suspend, bfin_spi_resume);
+
+#define BFIN_SPI_PM_OPS (&bfin_spi_pm_ops)
#else
-#define bfin_spi_suspend NULL
-#define bfin_spi_resume NULL
-#endif /* CONFIG_PM */
+#define BFIN_SPI_PM_OPS NULL
+#endif
MODULE_ALIAS("platform:bfin-spi");
static struct platform_driver bfin_spi_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
+ .pm = BFIN_SPI_PM_OPS,
},
- .suspend = bfin_spi_suspend,
- .resume = bfin_spi_resume,
.remove = bfin_spi_remove,
};
diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c
index 8c11355dec23..0056623dfc6b 100644
--- a/drivers/spi/spi-bitbang.c
+++ b/drivers/spi/spi-bitbang.c
@@ -414,10 +414,16 @@ static int spi_bitbang_unprepare_hardware(struct spi_master *spi)
* This routine registers the spi_master, which will process requests in a
* dedicated task, keeping IRQs unblocked most of the time. To stop
* processing those requests, call spi_bitbang_stop().
+ *
+ * On success, this routine will take a reference to master. The caller is
+ * responsible for calling spi_bitbang_stop() to decrement the reference and
+ * spi_master_put() as counterpart of spi_alloc_master() to prevent a memory
+ * leak.
*/
int spi_bitbang_start(struct spi_bitbang *bitbang)
{
struct spi_master *master = bitbang->master;
+ int ret;
if (!master || !bitbang->chipselect)
return -EINVAL;
@@ -449,7 +455,11 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
/* driver may get busy before register() returns, especially
* if someone registered boardinfo for devices
*/
- return spi_register_master(master);
+ ret = spi_register_master(spi_master_get(master));
+ if (ret)
+ spi_master_put(master);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(spi_bitbang_start);
diff --git a/drivers/spi/spi-butterfly.c b/drivers/spi/spi-butterfly.c
index 5ed08e537433..b1ecea2d76b3 100644
--- a/drivers/spi/spi-butterfly.c
+++ b/drivers/spi/spi-butterfly.c
@@ -225,7 +225,7 @@ static void butterfly_attach(struct parport *p)
master->bus_num = 42;
master->num_chipselect = 2;
- pp->bitbang.master = spi_master_get(master);
+ pp->bitbang.master = master;
pp->bitbang.chipselect = butterfly_chipselect;
pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0;
diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c
index 5655acf55bfe..b597a92565dc 100644
--- a/drivers/spi/spi-clps711x.c
+++ b/drivers/spi/spi-clps711x.c
@@ -247,7 +247,6 @@ err_out:
gpio_free(hw->chipselect[i]);
spi_master_put(master);
- kfree(master);
return ret;
}
@@ -263,7 +262,6 @@ static int spi_clps711x_remove(struct platform_device *pdev)
gpio_free(hw->chipselect[i]);
spi_unregister_master(master);
- kfree(master);
return 0;
}
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index 8fbfe2483ffd..dd72445ba2ea 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -279,7 +279,8 @@ static int davinci_spi_setup_transfer(struct spi_device *spi,
struct davinci_spi *dspi;
struct davinci_spi_config *spicfg;
u8 bits_per_word = 0;
- u32 hz = 0, spifmt = 0, prescale = 0;
+ u32 hz = 0, spifmt = 0;
+ int prescale;
dspi = spi_master_get_devdata(spi->master);
spicfg = (struct davinci_spi_config *)spi->controller_data;
@@ -916,7 +917,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
if (ret)
goto unmap_io;
- dspi->bitbang.master = spi_master_get(master);
+ dspi->bitbang.master = master;
if (dspi->bitbang.master == NULL) {
ret = -ENODEV;
goto irq_free;
@@ -925,7 +926,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
dspi->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(dspi->clk)) {
ret = -ENODEV;
- goto put_master;
+ goto irq_free;
}
clk_prepare_enable(dspi->clk);
@@ -1015,8 +1016,6 @@ free_dma:
free_clk:
clk_disable_unprepare(dspi->clk);
clk_put(dspi->clk);
-put_master:
- spi_master_put(master);
irq_free:
free_irq(dspi->irq, dspi);
unmap_io:
@@ -1024,7 +1023,7 @@ unmap_io:
release_region:
release_mem_region(dspi->pbase, resource_size(r));
free_master:
- kfree(master);
+ spi_master_put(master);
err:
return ret;
}
@@ -1051,11 +1050,11 @@ static int davinci_spi_remove(struct platform_device *pdev)
clk_disable_unprepare(dspi->clk);
clk_put(dspi->clk);
- spi_master_put(master);
free_irq(dspi->irq, dspi);
iounmap(dspi->base);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(dspi->pbase, resource_size(r));
+ spi_master_put(master);
return 0;
}
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index 4aa8be865cc0..168c620947f4 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -74,7 +74,7 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
dwsmmio->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(dwsmmio->clk)) {
ret = PTR_ERR(dwsmmio->clk);
- goto err_irq;
+ goto err_unmap;
}
clk_enable(dwsmmio->clk);
@@ -94,8 +94,6 @@ err_clk:
clk_disable(dwsmmio->clk);
clk_put(dwsmmio->clk);
dwsmmio->clk = NULL;
-err_irq:
- free_irq(dws->irq, dws);
err_unmap:
iounmap(dws->regs);
err_release_reg:
@@ -115,7 +113,6 @@ static int dw_spi_mmio_remove(struct platform_device *pdev)
clk_put(dwsmmio->clk);
dwsmmio->clk = NULL;
- free_irq(dwsmmio->dws.irq, &dwsmmio->dws);
dw_spi_remove_host(&dwsmmio->dws);
iounmap(dwsmmio->dws.regs);
kfree(dwsmmio);
diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c
index 6055c8d9fdd7..6a708620816a 100644
--- a/drivers/spi/spi-dw-pci.c
+++ b/drivers/spi/spi-dw-pci.c
@@ -109,7 +109,6 @@ static void spi_pci_remove(struct pci_dev *pdev)
{
struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
- pci_set_drvdata(pdev, NULL);
dw_spi_remove_host(&dwpci->dws);
iounmap(dwpci->dws.regs);
pci_release_region(pdev, 0);
diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c
index 7d84418a01d8..5ce61e5f9770 100644
--- a/drivers/spi/spi-efm32.c
+++ b/drivers/spi/spi-efm32.c
@@ -347,7 +347,7 @@ static int efm32_spi_probe(struct platform_device *pdev)
ddata = spi_master_get_devdata(master);
- ddata->bitbang.master = spi_master_get(master);
+ ddata->bitbang.master = master;
ddata->bitbang.chipselect = efm32_spi_chipselect;
ddata->bitbang.setup_transfer = efm32_spi_setup_transfer;
ddata->bitbang.txrx_bufs = efm32_spi_txrx_bufs;
@@ -467,7 +467,6 @@ err_disable_clk:
clk_disable_unprepare(ddata->clk);
err:
spi_master_put(master);
- kfree(master);
}
return ret;
@@ -478,13 +477,14 @@ static int efm32_spi_remove(struct platform_device *pdev)
struct spi_master *master = platform_get_drvdata(pdev);
struct efm32_spi_ddata *ddata = spi_master_get_devdata(master);
+ spi_bitbang_stop(&ddata->bitbang);
+
efm32_spi_write32(ddata, 0, REG_IEN);
free_irq(ddata->txirq, ddata);
free_irq(ddata->rxirq, ddata);
clk_disable_unprepare(ddata->clk);
spi_master_put(master);
- kfree(master);
return 0;
}
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 6cd07d13ecab..bb8e0ad253a5 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -108,7 +108,7 @@ struct fsl_dspi {
struct spi_bitbang bitbang;
struct platform_device *pdev;
- void *base;
+ void __iomem *base;
int irq;
struct clk *clk;
@@ -165,7 +165,7 @@ static void hz_to_spi_baud(char *pbr, char *br, int speed_hz,
}
}
- pr_warn("Can not find valid buad rate,speed_hz is %d,clkrate is %ld\
+ pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld\
,we use the max prescaler value.\n", speed_hz, clkrate);
*pbr = ARRAY_SIZE(pbr_tbl) - 1;
*br = ARRAY_SIZE(brs) - 1;
@@ -450,7 +450,7 @@ static int dspi_probe(struct platform_device *pdev)
dspi = spi_master_get_devdata(master);
dspi->pdev = pdev;
- dspi->bitbang.master = spi_master_get(master);
+ dspi->bitbang.master = master;
dspi->bitbang.chipselect = dspi_chipselect;
dspi->bitbang.setup_transfer = dspi_setup_transfer;
dspi->bitbang.txrx_bufs = dspi_txrx_transfer;
@@ -476,15 +476,9 @@ static int dspi_probe(struct platform_device *pdev)
master->bus_num = bus_num;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "can't get platform resource\n");
- ret = -EINVAL;
- goto out_master_put;
- }
-
dspi->base = devm_ioremap_resource(&pdev->dev, res);
- if (!dspi->base) {
- ret = -EINVAL;
+ if (IS_ERR(dspi->base)) {
+ ret = PTR_ERR(dspi->base);
goto out_master_put;
}
@@ -526,7 +520,6 @@ out_clk_put:
clk_disable_unprepare(dspi->clk);
out_master_put:
spi_master_put(master);
- platform_set_drvdata(pdev, NULL);
return ret;
}
@@ -553,5 +546,5 @@ static struct platform_driver fsl_dspi_driver = {
module_platform_driver(fsl_dspi_driver);
MODULE_DESCRIPTION("Freescale DSPI Controller Driver");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index 68b69fec13a9..14c01b44ca7a 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -467,7 +467,7 @@ static int spi_gpio_probe(struct platform_device *pdev)
}
#endif
- spi_gpio->bitbang.master = spi_master_get(master);
+ spi_gpio->bitbang.master = master;
spi_gpio->bitbang.chipselect = spi_gpio_chipselect;
if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) {
@@ -486,7 +486,6 @@ static int spi_gpio_probe(struct platform_device *pdev)
status = spi_bitbang_start(&spi_gpio->bitbang);
if (status < 0) {
- spi_master_put(spi_gpio->bitbang.master);
gpio_free:
if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
gpio_free(SPI_MISO_GPIO);
@@ -510,13 +509,13 @@ static int spi_gpio_remove(struct platform_device *pdev)
/* stop() unregisters child devices too */
status = spi_bitbang_stop(&spi_gpio->bitbang);
- spi_master_put(spi_gpio->bitbang.master);
if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
gpio_free(SPI_MISO_GPIO);
if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
gpio_free(SPI_MOSI_GPIO);
gpio_free(SPI_SCK_GPIO);
+ spi_master_put(spi_gpio->bitbang.master);
return status;
}
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 15323d8bd9cf..02d9f468b2b6 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -786,7 +786,7 @@ static int spi_imx_probe(struct platform_device *pdev)
master->num_chipselect = num_cs;
spi_imx = spi_master_get_devdata(master);
- spi_imx->bitbang.master = spi_master_get(master);
+ spi_imx->bitbang.master = master;
for (i = 0; i < master->num_chipselect; i++) {
int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
diff --git a/drivers/spi/spi-lm70llp.c b/drivers/spi/spi-lm70llp.c
index 0759b5db9883..41c5765be746 100644
--- a/drivers/spi/spi-lm70llp.c
+++ b/drivers/spi/spi-lm70llp.c
@@ -222,7 +222,7 @@ static void spi_lm70llp_attach(struct parport *p)
/*
* SPI and bitbang hookup.
*/
- pp->bitbang.master = spi_master_get(master);
+ pp->bitbang.master = master;
pp->bitbang.chipselect = lm70_chipselect;
pp->bitbang.txrx_word[SPI_MODE_0] = lm70_txrx;
pp->bitbang.flags = SPI_3WIRE;
diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index dbc5e999a1f5..6adf4e35816d 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -522,8 +522,10 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
psc_num = master->bus_num;
snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
clk = devm_clk_get(dev, clk_name);
- if (IS_ERR(clk))
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
goto free_irq;
+ }
ret = clk_prepare_enable(clk);
if (ret)
goto free_irq;
diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c
index 47a68b43bcd5..e0c32bc69ee2 100644
--- a/drivers/spi/spi-nuc900.c
+++ b/drivers/spi/spi-nuc900.c
@@ -349,7 +349,7 @@ static int nuc900_spi_probe(struct platform_device *pdev)
}
hw = spi_master_get_devdata(master);
- hw->master = spi_master_get(master);
+ hw->master = master;
hw->pdata = dev_get_platdata(&pdev->dev);
hw->dev = &pdev->dev;
@@ -435,7 +435,6 @@ err_iomap:
kfree(hw->ioarea);
err_pdata:
spi_master_put(hw->master);
-
err_nomem:
return err;
}
diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c
index 333cb1badcd7..91c668596202 100644
--- a/drivers/spi/spi-oc-tiny.c
+++ b/drivers/spi/spi-oc-tiny.c
@@ -306,7 +306,7 @@ static int tiny_spi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, hw);
/* setup the state for the bitbang driver */
- hw->bitbang.master = spi_master_get(master);
+ hw->bitbang.master = master;
if (!hw->bitbang.master)
return err;
hw->bitbang.setup_transfer = tiny_spi_setup_transfer;
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 9c511a954d21..c13d523f1f48 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -1619,7 +1619,6 @@ static int verify_controller_parameters(struct pl022 *pl022,
dev_err(&pl022->adev->dev,
"RX FIFO Trigger Level is configured incorrectly\n");
return -EINVAL;
- break;
}
switch (chip_info->tx_lev_trig) {
case SSP_TX_1_OR_MORE_EMPTY_LOC:
@@ -1645,7 +1644,6 @@ static int verify_controller_parameters(struct pl022 *pl022,
dev_err(&pl022->adev->dev,
"TX FIFO Trigger Level is configured incorrectly\n");
return -EINVAL;
- break;
}
if (chip_info->iface == SSP_INTERFACE_NATIONAL_MICROWIRE) {
if ((chip_info->ctrl_len < SSP_BITS_4)
@@ -2288,7 +2286,6 @@ pl022_remove(struct amba_device *adev)
amba_release_regions(adev);
tasklet_disable(&pl022->pump_transfers);
spi_unregister_master(pl022->master);
- amba_set_drvdata(adev, NULL);
return 0;
}
diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c
index 0ee53c25ba58..c57740bb70d3 100644
--- a/drivers/spi/spi-ppc4xx.c
+++ b/drivers/spi/spi-ppc4xx.c
@@ -396,7 +396,7 @@ static int spi_ppc4xx_of_probe(struct platform_device *op)
master->dev.of_node = np;
platform_set_drvdata(op, master);
hw = spi_master_get_devdata(master);
- hw->master = spi_master_get(master);
+ hw->master = master;
hw->dev = dev;
init_completion(&hw->done);
@@ -558,6 +558,7 @@ static int spi_ppc4xx_of_remove(struct platform_device *op)
free_irq(hw->irqnum, hw);
iounmap(hw->regs);
free_gpios(hw);
+ spi_master_put(master);
return 0;
}
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 2eb06ee0b326..c1a50674c1e3 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -546,8 +546,17 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
if (pm_runtime_suspended(&drv_data->pdev->dev))
return IRQ_NONE;
- sccr1_reg = read_SSCR1(reg);
+ /*
+ * If the device is not yet in RPM suspended state and we get an
+ * interrupt that is meant for another device, check if status bits
+ * are all set to one. That means that the device is already
+ * powered off.
+ */
status = read_SSSR(reg);
+ if (status == ~0)
+ return IRQ_NONE;
+
+ sccr1_reg = read_SSCR1(reg);
/* Ignore possible writes if we don't need to write */
if (!(sccr1_reg & SSCR1_TIE))
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 8719206a03a0..4c8dbac11b42 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -59,6 +59,14 @@
#define RSPI_SPCMD6 0x1c
#define RSPI_SPCMD7 0x1e
+/*qspi only */
+#define QSPI_SPBFCR 0x18
+#define QSPI_SPBDCR 0x1a
+#define QSPI_SPBMUL0 0x1c
+#define QSPI_SPBMUL1 0x20
+#define QSPI_SPBMUL2 0x24
+#define QSPI_SPBMUL3 0x28
+
/* SPCR */
#define SPCR_SPRIE 0x80
#define SPCR_SPE 0x40
@@ -126,6 +134,8 @@
#define SPCMD_LSBF 0x1000
#define SPCMD_SPB_MASK 0x0f00
#define SPCMD_SPB_8_TO_16(bit) (((bit - 1) << 8) & SPCMD_SPB_MASK)
+#define SPCMD_SPB_8BIT 0x0000 /* qspi only */
+#define SPCMD_SPB_16BIT 0x0100
#define SPCMD_SPB_20BIT 0x0000
#define SPCMD_SPB_24BIT 0x0100
#define SPCMD_SPB_32BIT 0x0200
@@ -135,6 +145,10 @@
#define SPCMD_CPOL 0x0002
#define SPCMD_CPHA 0x0001
+/* SPBFCR */
+#define SPBFCR_TXRST 0x80 /* qspi only */
+#define SPBFCR_RXRST 0x40 /* qspi only */
+
struct rspi_data {
void __iomem *addr;
u32 max_speed_hz;
@@ -145,6 +159,7 @@ struct rspi_data {
spinlock_t lock;
struct clk *clk;
unsigned char spsr;
+ const struct spi_ops *ops;
/* for dmaengine */
struct dma_chan *chan_tx;
@@ -165,6 +180,11 @@ static void rspi_write16(struct rspi_data *rspi, u16 data, u16 offset)
iowrite16(data, rspi->addr + offset);
}
+static void rspi_write32(struct rspi_data *rspi, u32 data, u16 offset)
+{
+ iowrite32(data, rspi->addr + offset);
+}
+
static u8 rspi_read8(struct rspi_data *rspi, u16 offset)
{
return ioread8(rspi->addr + offset);
@@ -175,17 +195,98 @@ static u16 rspi_read16(struct rspi_data *rspi, u16 offset)
return ioread16(rspi->addr + offset);
}
-static unsigned char rspi_calc_spbr(struct rspi_data *rspi)
+/* optional functions */
+struct spi_ops {
+ int (*set_config_register)(struct rspi_data *rspi, int access_size);
+};
+
+/*
+ * functions for RSPI
+ */
+static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
{
- int tmp;
- unsigned char spbr;
+ int spbr;
+
+ /* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
+ rspi_write8(rspi, 0x00, RSPI_SPPCR);
- tmp = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1;
- spbr = clamp(tmp, 0, 255);
+ /* Sets transfer bit rate */
+ spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1;
+ rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
+
+ /* Sets number of frames to be used: 1 frame */
+ rspi_write8(rspi, 0x00, RSPI_SPDCR);
- return spbr;
+ /* Sets RSPCK, SSL, next-access delay value */
+ rspi_write8(rspi, 0x00, RSPI_SPCKD);
+ rspi_write8(rspi, 0x00, RSPI_SSLND);
+ rspi_write8(rspi, 0x00, RSPI_SPND);
+
+ /* Sets parity, interrupt mask */
+ rspi_write8(rspi, 0x00, RSPI_SPCR2);
+
+ /* Sets SPCMD */
+ rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | SPCMD_SSLKP,
+ RSPI_SPCMD0);
+
+ /* Sets RSPI mode */
+ rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
+
+ return 0;
}
+/*
+ * functions for QSPI
+ */
+static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
+{
+ u16 spcmd;
+ int spbr;
+
+ /* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
+ rspi_write8(rspi, 0x00, RSPI_SPPCR);
+
+ /* Sets transfer bit rate */
+ spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz);
+ rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
+
+ /* Sets number of frames to be used: 1 frame */
+ rspi_write8(rspi, 0x00, RSPI_SPDCR);
+
+ /* Sets RSPCK, SSL, next-access delay value */
+ rspi_write8(rspi, 0x00, RSPI_SPCKD);
+ rspi_write8(rspi, 0x00, RSPI_SSLND);
+ rspi_write8(rspi, 0x00, RSPI_SPND);
+
+ /* Data Length Setting */
+ if (access_size == 8)
+ spcmd = SPCMD_SPB_8BIT;
+ else if (access_size == 16)
+ spcmd = SPCMD_SPB_16BIT;
+ else if (access_size == 32)
+ spcmd = SPCMD_SPB_32BIT;
+
+ spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SSLKP | SPCMD_SPNDEN;
+
+ /* Resets transfer data length */
+ rspi_write32(rspi, 0, QSPI_SPBMUL0);
+
+ /* Resets transmit and receive buffer */
+ rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR);
+ /* Sets buffer to allow normal operation */
+ rspi_write8(rspi, 0x00, QSPI_SPBFCR);
+
+ /* Sets SPCMD */
+ rspi_write16(rspi, spcmd, RSPI_SPCMD0);
+
+ /* Enables SPI function in a master mode */
+ rspi_write8(rspi, SPCR_SPE | SPCR_MSTR, RSPI_SPCR);
+
+ return 0;
+}
+
+#define set_config_register(spi, n) spi->ops->set_config_register(spi, n)
+
static void rspi_enable_irq(struct rspi_data *rspi, u8 enable)
{
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR);
@@ -220,35 +321,6 @@ static void rspi_negate_ssl(struct rspi_data *rspi)
rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
}
-static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
-{
- /* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
- rspi_write8(rspi, 0x00, RSPI_SPPCR);
-
- /* Sets transfer bit rate */
- rspi_write8(rspi, rspi_calc_spbr(rspi), RSPI_SPBR);
-
- /* Sets number of frames to be used: 1 frame */
- rspi_write8(rspi, 0x00, RSPI_SPDCR);
-
- /* Sets RSPCK, SSL, next-access delay value */
- rspi_write8(rspi, 0x00, RSPI_SPCKD);
- rspi_write8(rspi, 0x00, RSPI_SSLND);
- rspi_write8(rspi, 0x00, RSPI_SPND);
-
- /* Sets parity, interrupt mask */
- rspi_write8(rspi, 0x00, RSPI_SPCR2);
-
- /* Sets SPCMD */
- rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | SPCMD_SSLKP,
- RSPI_SPCMD0);
-
- /* Sets RSPI mode */
- rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
-
- return 0;
-}
-
static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
struct spi_transfer *t)
{
@@ -616,7 +688,7 @@ static int rspi_setup(struct spi_device *spi)
spi->bits_per_word = 8;
rspi->max_speed_hz = spi->max_speed_hz;
- rspi_set_config_register(rspi, 8);
+ set_config_register(rspi, 8);
return 0;
}
@@ -745,7 +817,16 @@ static int rspi_probe(struct platform_device *pdev)
struct rspi_data *rspi;
int ret, irq;
char clk_name[16];
-
+ struct rspi_plat_data *rspi_pd = pdev->dev.platform_data;
+ const struct spi_ops *ops;
+ const struct platform_device_id *id_entry = pdev->id_entry;
+
+ ops = (struct spi_ops *)id_entry->driver_data;
+ /* ops parameter check */
+ if (!ops->set_config_register) {
+ dev_err(&pdev->dev, "there is no set_config_register\n");
+ return -ENODEV;
+ }
/* get base addr */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (unlikely(res == NULL)) {
@@ -767,7 +848,7 @@ static int rspi_probe(struct platform_device *pdev)
rspi = spi_master_get_devdata(master);
platform_set_drvdata(pdev, rspi);
-
+ rspi->ops = ops;
rspi->master = master;
rspi->addr = ioremap(res->start, resource_size(res));
if (rspi->addr == NULL) {
@@ -776,7 +857,7 @@ static int rspi_probe(struct platform_device *pdev)
goto error1;
}
- snprintf(clk_name, sizeof(clk_name), "rspi%d", pdev->id);
+ snprintf(clk_name, sizeof(clk_name), "%s%d", id_entry->name, pdev->id);
rspi->clk = clk_get(&pdev->dev, clk_name);
if (IS_ERR(rspi->clk)) {
dev_err(&pdev->dev, "cannot get clock\n");
@@ -790,7 +871,10 @@ static int rspi_probe(struct platform_device *pdev)
INIT_WORK(&rspi->ws, rspi_work);
init_waitqueue_head(&rspi->wait);
- master->num_chipselect = 2;
+ master->num_chipselect = rspi_pd->num_chipselect;
+ if (!master->num_chipselect)
+ master->num_chipselect = 2; /* default */
+
master->bus_num = pdev->id;
master->setup = rspi_setup;
master->transfer = rspi_transfer;
@@ -832,11 +916,28 @@ error1:
return ret;
}
+static struct spi_ops rspi_ops = {
+ .set_config_register = rspi_set_config_register,
+};
+
+static struct spi_ops qspi_ops = {
+ .set_config_register = qspi_set_config_register,
+};
+
+static struct platform_device_id spi_driver_ids[] = {
+ { "rspi", (kernel_ulong_t)&rspi_ops },
+ { "qspi", (kernel_ulong_t)&qspi_ops },
+ {},
+};
+
+MODULE_DEVICE_TABLE(platform, spi_driver_ids);
+
static struct platform_driver rspi_driver = {
.probe = rspi_probe,
.remove = rspi_remove,
+ .id_table = spi_driver_ids,
.driver = {
- .name = "rspi",
+ .name = "renesas_spi",
.owner = THIS_MODULE,
},
};
diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c
index ce318d95a6ee..0dc32a11bd3c 100644
--- a/drivers/spi/spi-s3c24xx.c
+++ b/drivers/spi/spi-s3c24xx.c
@@ -280,7 +280,7 @@ static inline u32 ack_bit(unsigned int irq)
* so the caller does not need to do anything more than start the transfer
* as normal, since the IRQ will have been re-routed to the FIQ handler.
*/
-void s3c24xx_spi_tryfiq(struct s3c24xx_spi *hw)
+static void s3c24xx_spi_tryfiq(struct s3c24xx_spi *hw)
{
struct pt_regs regs;
enum spi_fiq_mode mode;
@@ -524,7 +524,7 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
hw = spi_master_get_devdata(master);
memset(hw, 0, sizeof(struct s3c24xx_spi));
- hw->master = spi_master_get(master);
+ hw->master = master;
hw->pdata = pdata = dev_get_platdata(&pdev->dev);
hw->dev = &pdev->dev;
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index 512b8893893b..84cc6ac801fe 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -1428,9 +1428,9 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN,
sdd->regs + S3C64XX_SPI_INT_EN);
- if (spi_register_master(master)) {
- dev_err(&pdev->dev, "cannot register SPI master\n");
- ret = -EBUSY;
+ ret = devm_spi_register_master(&pdev->dev, master);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "cannot register SPI master: %d\n", ret);
goto err3;
}
@@ -1461,16 +1461,12 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
- spi_unregister_master(master);
-
writel(0, sdd->regs + S3C64XX_SPI_INT_EN);
clk_disable_unprepare(sdd->src_clk);
clk_disable_unprepare(sdd->clk);
- spi_master_put(master);
-
return 0;
}
@@ -1616,6 +1612,18 @@ static struct platform_device_id s3c64xx_spi_driver_ids[] = {
};
static const struct of_device_id s3c64xx_spi_dt_match[] = {
+ { .compatible = "samsung,s3c2443-spi",
+ .data = (void *)&s3c2443_spi_port_config,
+ },
+ { .compatible = "samsung,s3c6410-spi",
+ .data = (void *)&s3c6410_spi_port_config,
+ },
+ { .compatible = "samsung,s5pc100-spi",
+ .data = (void *)&s5pc100_spi_port_config,
+ },
+ { .compatible = "samsung,s5pv210-spi",
+ .data = (void *)&s5pv210_spi_port_config,
+ },
{ .compatible = "samsung,exynos4210-spi",
.data = (void *)&exynos4_spi_port_config,
},
@@ -1633,22 +1641,13 @@ static struct platform_driver s3c64xx_spi_driver = {
.pm = &s3c64xx_spi_pm,
.of_match_table = of_match_ptr(s3c64xx_spi_dt_match),
},
+ .probe = s3c64xx_spi_probe,
.remove = s3c64xx_spi_remove,
.id_table = s3c64xx_spi_driver_ids,
};
MODULE_ALIAS("platform:s3c64xx-spi");
-static int __init s3c64xx_spi_init(void)
-{
- return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe);
-}
-subsys_initcall(s3c64xx_spi_init);
-
-static void __exit s3c64xx_spi_exit(void)
-{
- platform_driver_unregister(&s3c64xx_spi_driver);
-}
-module_exit(s3c64xx_spi_exit);
+module_platform_driver(s3c64xx_spi_driver);
MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
MODULE_DESCRIPTION("S3C64XX SPI Controller Driver");
diff --git a/drivers/spi/spi-sh-sci.c b/drivers/spi/spi-sh-sci.c
index 8eefeb6007df..38eb24df796c 100644
--- a/drivers/spi/spi-sh-sci.c
+++ b/drivers/spi/spi-sh-sci.c
@@ -133,7 +133,7 @@ static int sh_sci_spi_probe(struct platform_device *dev)
sp->info = dev_get_platdata(&dev->dev);
/* setup spi bitbang adaptor */
- sp->bitbang.master = spi_master_get(master);
+ sp->bitbang.master = master;
sp->bitbang.master->bus_num = sp->info->bus_num;
sp->bitbang.master->num_chipselect = sp->info->num_chipselect;
sp->bitbang.chipselect = sh_sci_spi_chipselect;
diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c
index a1f21b747733..592b4aff651f 100644
--- a/drivers/spi/spi-sirf.c
+++ b/drivers/spi/spi-sirf.c
@@ -632,7 +632,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
if (ret)
goto free_master;
- sspi->bitbang.master = spi_master_get(master);
+ sspi->bitbang.master = master;
sspi->bitbang.chipselect = spi_sirfsoc_chipselect;
sspi->bitbang.setup_transfer = spi_sirfsoc_setup_transfer;
sspi->bitbang.txrx_bufs = spi_sirfsoc_transfer;
diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 145dd435483b..946ff7377352 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -267,7 +267,7 @@ static unsigned tegra_spi_calculate_curr_xfer_param(
unsigned max_len;
unsigned total_fifo_words;
- tspi->bytes_per_word = (bits_per_word - 1) / 8 + 1;
+ tspi->bytes_per_word = DIV_ROUND_UP(bits_per_word, 8);
if (bits_per_word == 8 || bits_per_word == 16) {
tspi->is_packed = 1;
diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c
index 1d814dc6e000..64c9cf511175 100644
--- a/drivers/spi/spi-tegra20-sflash.c
+++ b/drivers/spi/spi-tegra20-sflash.c
@@ -173,7 +173,7 @@ static unsigned tegra_sflash_calculate_curr_xfer_param(
unsigned remain_len = t->len - tsd->cur_pos;
unsigned max_word;
- tsd->bytes_per_word = (t->bits_per_word - 1) / 8 + 1;
+ tsd->bytes_per_word = DIV_ROUND_UP(t->bits_per_word, 8);
max_word = remain_len / tsd->bytes_per_word;
if (max_word > SPI_FIFO_DEPTH)
max_word = SPI_FIFO_DEPTH;
diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c
index c70353672a23..231b84523d37 100644
--- a/drivers/spi/spi-tegra20-slink.c
+++ b/drivers/spi/spi-tegra20-slink.c
@@ -283,7 +283,7 @@ static unsigned tegra_slink_calculate_curr_xfer_param(
unsigned total_fifo_words;
bits_per_word = t->bits_per_word;
- tspi->bytes_per_word = (bits_per_word - 1) / 8 + 1;
+ tspi->bytes_per_word = DIV_ROUND_UP(bits_per_word, 8);
if (bits_per_word == 8 || bits_per_word == 16) {
tspi->is_packed = 1;
diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c
index eaeeed51bbbf..777c40452bd1 100644
--- a/drivers/spi/spi-topcliff-pch.c
+++ b/drivers/spi/spi-topcliff-pch.c
@@ -1410,13 +1410,13 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev)
/* baseaddress + address offset) */
data->io_base_addr = pci_resource_start(board_dat->pdev, 1) +
PCH_ADDRESS_SIZE * plat_dev->id;
- data->io_remap_addr = pci_iomap(board_dat->pdev, 1, 0) +
- PCH_ADDRESS_SIZE * plat_dev->id;
+ data->io_remap_addr = pci_iomap(board_dat->pdev, 1, 0);
if (!data->io_remap_addr) {
dev_err(&plat_dev->dev, "%s pci_iomap failed\n", __func__);
ret = -ENOMEM;
goto err_pci_iomap;
}
+ data->io_remap_addr += PCH_ADDRESS_SIZE * plat_dev->id;
dev_dbg(&plat_dev->dev, "[ch%d] remap_addr=%p\n",
plat_dev->id, data->io_remap_addr);
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 0bf1b2c457a1..ec3a83f52ea2 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -372,7 +372,7 @@ static int xilinx_spi_probe(struct platform_device *pdev)
master->mode_bits = SPI_CPOL | SPI_CPHA;
xspi = spi_master_get_devdata(master);
- xspi->bitbang.master = spi_master_get(master);
+ xspi->bitbang.master = master;
xspi->bitbang.chipselect = xilinx_spi_chipselect;
xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer;
xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs;
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 9e039c60c068..8a2e685d21df 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -839,7 +839,6 @@ static void of_register_spi_devices(struct spi_master *master)
struct spi_device *spi;
struct device_node *nc;
const __be32 *prop;
- char modalias[SPI_NAME_SIZE + 4];
int rc;
int len;
@@ -944,9 +943,7 @@ static void of_register_spi_devices(struct spi_master *master)
spi->dev.of_node = nc;
/* Register the new device */
- snprintf(modalias, sizeof(modalias), "%s%s", SPI_MODULE_PREFIX,
- spi->modalias);
- request_module(modalias);
+ request_module("%s%s", SPI_MODULE_PREFIX, spi->modalias);
rc = spi_add_device(spi);
if (rc) {
dev_err(&master->dev, "spi_device register error %s\n",
@@ -1245,6 +1242,41 @@ done:
}
EXPORT_SYMBOL_GPL(spi_register_master);
+static void devm_spi_unregister(struct device *dev, void *res)
+{
+ spi_unregister_master(*(struct spi_master **)res);
+}
+
+/**
+ * dev_spi_register_master - register managed SPI master controller
+ * @dev: device managing SPI master
+ * @master: initialized master, originally from spi_alloc_master()
+ * Context: can sleep
+ *
+ * Register a SPI device as with spi_register_master() which will
+ * automatically be unregister
+ */
+int devm_spi_register_master(struct device *dev, struct spi_master *master)
+{
+ struct spi_master **ptr;
+ int ret;
+
+ ptr = devres_alloc(devm_spi_unregister, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return -ENOMEM;
+
+ ret = spi_register_master(master);
+ if (ret != 0) {
+ *ptr = master;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(devm_spi_register_master);
+
static int __unregister(struct device *dev, void *null)
{
spi_unregister_device(to_spi_device(dev));
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index ca5bcfe874d0..c53556a1899a 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -629,7 +629,6 @@ static int spidev_remove(struct spi_device *spi)
/* make sure ops on existing fds can abort cleanly */
spin_lock_irq(&spidev->spi_lock);
spidev->spi = NULL;
- spi_set_drvdata(spi, NULL);
spin_unlock_irq(&spidev->spi_lock);
/* prevent new opens */
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index c0c95be0f969..1e9ab6dfc90d 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -10,6 +10,7 @@ if ANDROID
config ANDROID_BINDER_IPC
bool "Android Binder IPC Driver"
+ depends on MMU
default n
---help---
Binder is used in Android for both communication between processes,
@@ -76,7 +77,7 @@ config SYNC
bool "Synchronization framework"
default n
select ANON_INODES
- help
+ ---help---
This option enables the framework for synchronization between multiple
drivers. Sync implementations can take advantage of hardware
synchronization built into devices like GPUs.
@@ -85,7 +86,7 @@ config SW_SYNC
bool "Software synchronization objects"
default n
depends on SYNC
- help
+ ---help---
A sync object driver that uses a 32bit counter to coordinate
syncrhronization. Useful when there is no hardware primitive backing
the synchronization.
@@ -94,7 +95,7 @@ config SW_SYNC_USER
bool "Userspace API for SW_SYNC"
default n
depends on SW_SYNC
- help
+ ---help---
Provides a user space API to the sw sync object.
*WARNING* improper use of this can result in deadlocking kernel
drivers from userspace.
diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c
index 6dc27dac679d..647694f43dcf 100644
--- a/drivers/staging/android/alarm-dev.c
+++ b/drivers/staging/android/alarm-dev.c
@@ -60,7 +60,12 @@ struct devalarm {
static struct devalarm alarms[ANDROID_ALARM_TYPE_COUNT];
-
+/**
+ * is_wakeup() - Checks to see if this alarm can wake the device
+ * @type: The type of alarm being checked
+ *
+ * Return: 1 if this is a wakeup alarm, otherwise 0
+ */
static int is_wakeup(enum android_alarm_type type)
{
return (type == ANDROID_ALARM_RTC_WAKEUP ||
@@ -76,7 +81,6 @@ static void devalarm_start(struct devalarm *alrm, ktime_t exp)
hrtimer_start(&alrm->u.hrt, exp, HRTIMER_MODE_ABS);
}
-
static int devalarm_try_to_cancel(struct devalarm *alrm)
{
if (is_wakeup(alrm->type))
diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c
index 8e76ddca0999..db5325c88f1c 100644
--- a/drivers/staging/android/ashmem.c
+++ b/drivers/staging/android/ashmem.c
@@ -37,41 +37,59 @@
#define ASHMEM_NAME_PREFIX_LEN (sizeof(ASHMEM_NAME_PREFIX) - 1)
#define ASHMEM_FULL_NAME_LEN (ASHMEM_NAME_LEN + ASHMEM_NAME_PREFIX_LEN)
-/*
- * ashmem_area - anonymous shared memory area
- * Lifecycle: From our parent file's open() until its release()
- * Locking: Protected by `ashmem_mutex'
- * Big Note: Mappings do NOT pin this structure; it dies on close()
+/**
+ * struct ashmem_area - The anonymous shared memory area
+ * @name: The optional name in /proc/pid/maps
+ * @unpinned_list: The list of all ashmem areas
+ * @file: The shmem-based backing file
+ * @size: The size of the mapping, in bytes
+ * @prot_masks: The allowed protection bits, as vm_flags
+ *
+ * The lifecycle of this structure is from our parent file's open() until
+ * its release(). It is also protected by 'ashmem_mutex'
+ *
+ * Warning: Mappings do NOT pin this structure; It dies on close()
*/
struct ashmem_area {
- char name[ASHMEM_FULL_NAME_LEN]; /* optional name in /proc/pid/maps */
- struct list_head unpinned_list; /* list of all ashmem areas */
- struct file *file; /* the shmem-based backing file */
- size_t size; /* size of the mapping, in bytes */
- unsigned long prot_mask; /* allowed prot bits, as vm_flags */
+ char name[ASHMEM_FULL_NAME_LEN];
+ struct list_head unpinned_list;
+ struct file *file;
+ size_t size;
+ unsigned long prot_mask;
};
-/*
- * ashmem_range - represents an interval of unpinned (evictable) pages
- * Lifecycle: From unpin to pin
- * Locking: Protected by `ashmem_mutex'
+/**
+ * struct ashmem_range - A range of unpinned/evictable pages
+ * @lru: The entry in the LRU list
+ * @unpinned: The entry in its area's unpinned list
+ * @asma: The associated anonymous shared memory area.
+ * @pgstart: The starting page (inclusive)
+ * @pgend: The ending page (inclusive)
+ * @purged: The purge status (ASHMEM_NOT or ASHMEM_WAS_PURGED)
+ *
+ * The lifecycle of this structure is from unpin to pin.
+ * It is protected by 'ashmem_mutex'
*/
struct ashmem_range {
- struct list_head lru; /* entry in LRU list */
- struct list_head unpinned; /* entry in its area's unpinned list */
- struct ashmem_area *asma; /* associated area */
- size_t pgstart; /* starting page, inclusive */
- size_t pgend; /* ending page, inclusive */
- unsigned int purged; /* ASHMEM_NOT or ASHMEM_WAS_PURGED */
+ struct list_head lru;
+ struct list_head unpinned;
+ struct ashmem_area *asma;
+ size_t pgstart;
+ size_t pgend;
+ unsigned int purged;
};
/* LRU list of unpinned pages, protected by ashmem_mutex */
static LIST_HEAD(ashmem_lru_list);
-/* Count of pages on our LRU list, protected by ashmem_mutex */
+/**
+ * long lru_count - The count of pages on our LRU list.
+ *
+ * This is protected by ashmem_mutex.
+ */
static unsigned long lru_count;
-/*
+/**
* ashmem_mutex - protects the list of and each individual ashmem_area
*
* Lock Ordering: ashmex_mutex -> i_mutex -> i_alloc_sem
@@ -105,28 +123,43 @@ static struct kmem_cache *ashmem_range_cachep __read_mostly;
#define PROT_MASK (PROT_EXEC | PROT_READ | PROT_WRITE)
+/**
+ * lru_add() - Adds a range of memory to the LRU list
+ * @range: The memory range being added.
+ *
+ * The range is first added to the end (tail) of the LRU list.
+ * After this, the size of the range is added to @lru_count
+ */
static inline void lru_add(struct ashmem_range *range)
{
list_add_tail(&range->lru, &ashmem_lru_list);
lru_count += range_size(range);
}
+/**
+ * lru_del() - Removes a range of memory from the LRU list
+ * @range: The memory range being removed
+ *
+ * The range is first deleted from the LRU list.
+ * After this, the size of the range is removed from @lru_count
+ */
static inline void lru_del(struct ashmem_range *range)
{
list_del(&range->lru);
lru_count -= range_size(range);
}
-/*
- * range_alloc - allocate and initialize a new ashmem_range structure
+/**
+ * range_alloc() - Allocates and initializes a new ashmem_range structure
+ * @asma: The associated ashmem_area
+ * @prev_range: The previous ashmem_range in the sorted asma->unpinned list
+ * @purged: Initial purge status (ASMEM_NOT_PURGED or ASHMEM_WAS_PURGED)
+ * @start: The starting page (inclusive)
+ * @end: The ending page (inclusive)
*
- * 'asma' - associated ashmem_area
- * 'prev_range' - the previous ashmem_range in the sorted asma->unpinned list
- * 'purged' - initial purge value (ASMEM_NOT_PURGED or ASHMEM_WAS_PURGED)
- * 'start' - starting page, inclusive
- * 'end' - ending page, inclusive
+ * This function is protected by ashmem_mutex.
*
- * Caller must hold ashmem_mutex.
+ * Return: 0 if successful, or -ENOMEM if there is an error
*/
static int range_alloc(struct ashmem_area *asma,
struct ashmem_range *prev_range, unsigned int purged,
@@ -151,6 +184,10 @@ static int range_alloc(struct ashmem_area *asma,
return 0;
}
+/**
+ * range_del() - Deletes and dealloctes an ashmem_range structure
+ * @range: The associated ashmem_range that has previously been allocated
+ */
static void range_del(struct ashmem_range *range)
{
list_del(&range->unpinned);
@@ -159,10 +196,17 @@ static void range_del(struct ashmem_range *range)
kmem_cache_free(ashmem_range_cachep, range);
}
-/*
- * range_shrink - shrinks a range
+/**
+ * range_shrink() - Shrinks an ashmem_range
+ * @range: The associated ashmem_range being shrunk
+ * @start: The starting byte of the new range
+ * @end: The ending byte of the new range
*
- * Caller must hold ashmem_mutex.
+ * This does not modify the data inside the existing range in any way - It
+ * simply shrinks the boundaries of the range.
+ *
+ * Theoretically, with a little tweaking, this could eventually be changed
+ * to range_resize, and expand the lru_count if the new range is larger.
*/
static inline void range_shrink(struct ashmem_range *range,
size_t start, size_t end)
@@ -176,6 +220,16 @@ static inline void range_shrink(struct ashmem_range *range,
lru_count -= pre - range_size(range);
}
+/**
+ * ashmem_open() - Opens an Anonymous Shared Memory structure
+ * @inode: The backing file's index node(?)
+ * @file: The backing file
+ *
+ * Please note that the ashmem_area is not returned by this function - It is
+ * instead written to "file->private_data".
+ *
+ * Return: 0 if successful, or another code if unsuccessful.
+ */
static int ashmem_open(struct inode *inode, struct file *file)
{
struct ashmem_area *asma;
@@ -197,6 +251,14 @@ static int ashmem_open(struct inode *inode, struct file *file)
return 0;
}
+/**
+ * ashmem_release() - Releases an Anonymous Shared Memory structure
+ * @ignored: The backing file's Index Node(?) - It is ignored here.
+ * @file: The backing file
+ *
+ * Return: 0 if successful. If it is anything else, go have a coffee and
+ * try again.
+ */
static int ashmem_release(struct inode *ignored, struct file *file)
{
struct ashmem_area *asma = file->private_data;
@@ -214,6 +276,15 @@ static int ashmem_release(struct inode *ignored, struct file *file)
return 0;
}
+/**
+ * ashmem_read() - Reads a set of bytes from an Ashmem-enabled file
+ * @file: The associated backing file.
+ * @buf: The buffer of data being written to
+ * @len: The number of bytes being read
+ * @pos: The position of the first byte to read.
+ *
+ * Return: 0 if successful, or another return code if not.
+ */
static ssize_t ashmem_read(struct file *file, char __user *buf,
size_t len, loff_t *pos)
{
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index 98ac020bf912..eaec1dab7fe4 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -1700,7 +1700,8 @@ err_no_context_mgr_node:
thread->return_error = return_error;
}
-int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
+static int binder_thread_write(struct binder_proc *proc,
+ struct binder_thread *thread,
void __user *buffer, size_t size, size_t *consumed)
{
uint32_t cmd;
@@ -1773,7 +1774,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
case BC_INCREFS_DONE:
case BC_ACQUIRE_DONE: {
void __user *node_ptr;
- void *cookie;
+ void __user *cookie;
struct binder_node *node;
if (get_user(node_ptr, (void * __user *)ptr))
@@ -2055,8 +2056,8 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
return 0;
}
-void binder_stat_br(struct binder_proc *proc, struct binder_thread *thread,
- uint32_t cmd)
+static void binder_stat_br(struct binder_proc *proc,
+ struct binder_thread *thread, uint32_t cmd)
{
trace_binder_return(cmd);
if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.br)) {
diff --git a/drivers/staging/android/timed_output.h b/drivers/staging/android/timed_output.h
index ec907ab2ff54..905c7cc9588e 100644
--- a/drivers/staging/android/timed_output.h
+++ b/drivers/staging/android/timed_output.h
@@ -31,7 +31,7 @@ struct timed_output_dev {
int state;
};
-extern int timed_output_dev_register(struct timed_output_dev *dev);
-extern void timed_output_dev_unregister(struct timed_output_dev *dev);
+int timed_output_dev_register(struct timed_output_dev *dev);
+void timed_output_dev_unregister(struct timed_output_dev *dev);
#endif
diff --git a/drivers/staging/bcm/InterfaceMisc.c b/drivers/staging/bcm/InterfaceMisc.c
index afca010f9db5..d9fa2bb03e11 100644
--- a/drivers/staging/bcm/InterfaceMisc.c
+++ b/drivers/staging/bcm/InterfaceMisc.c
@@ -104,7 +104,7 @@ int BcmRDM(void *arg,
void *buff,
int len)
{
- return InterfaceRDM((struct bcm_interface_adapter*)arg, addr, buff, len);
+ return InterfaceRDM((struct bcm_interface_adapter *)arg, addr, buff, len);
}
int BcmWRM(void *arg,
diff --git a/drivers/staging/bcm/PHSModule.c b/drivers/staging/bcm/PHSModule.c
index af5d22faa7f0..56c5bee6514e 100644
--- a/drivers/staging/bcm/PHSModule.c
+++ b/drivers/staging/bcm/PHSModule.c
@@ -596,7 +596,7 @@ ULONG PhsDeleteSFRules(IN void *pvContext, IN B_UINT16 uiVcid)
* 0 if successful,
* >0 Error.
*/
-ULONG PhsCompress(IN void *pvContext,
+static ULONG PhsCompress(IN void *pvContext,
IN B_UINT16 uiVcid,
IN B_UINT16 uiClsId,
IN void *pvInputBuffer,
@@ -677,7 +677,7 @@ ULONG PhsCompress(IN void *pvContext,
* 0 if successful,
* >0 Error.
*/
-ULONG PhsDeCompress(IN void *pvContext,
+static ULONG PhsDeCompress(IN void *pvContext,
IN B_UINT16 uiVcid,
IN void *pvInputBuffer,
OUT void *pvOutputBuffer,
@@ -829,7 +829,7 @@ UINT GetServiceFlowEntry(IN struct bcm_phs_table *psServiceFlowTable,
return PHS_INVALID_TABLE_INDEX;
}
-UINT GetClassifierEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
+static UINT GetClassifierEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
IN B_UINT32 uiClsid, enum bcm_phs_classifier_context eClsContext,
OUT struct bcm_phs_classifier_entry **ppstClassifierEntry)
{
@@ -880,7 +880,7 @@ static UINT GetPhsRuleEntry(IN struct bcm_phs_classifier_table *pstClassifierTab
return PHS_INVALID_TABLE_INDEX;
}
-UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid, IN B_UINT16 uiClsId,
+static UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid, IN B_UINT16 uiClsId,
IN struct bcm_phs_table *psServiceFlowTable,
struct bcm_phs_rule *psPhsRule,
B_UINT8 u8AssociatedPHSI)
@@ -913,7 +913,7 @@ UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid, IN B_UINT16 uiClsId,
return uiStatus;
}
-UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid,
+static UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid,
IN B_UINT16 uiClsId,
IN struct bcm_phs_entry *pstServiceFlowEntry,
struct bcm_phs_rule *psPhsRule,
@@ -1239,7 +1239,7 @@ void DumpPhsRules(struct bcm_phs_extension *pDeviceExtension)
* header.
* 0 -If PHS rule is NULL.If PHSI is 0 indicateing packet as uncompressed.
*/
-int phs_decompress(unsigned char *in_buf,
+static int phs_decompress(unsigned char *in_buf,
unsigned char *out_buf,
struct bcm_phs_rule *decomp_phs_rules,
UINT *header_size)
diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c
index 91a5715964b9..1f5b62b4b5a1 100644
--- a/drivers/staging/bcm/nvm.c
+++ b/drivers/staging/bcm/nvm.c
@@ -103,7 +103,7 @@ static UCHAR ReadEEPROMStatusRegister(struct bcm_mini_adapter *Adapter)
}
if (!(dwRetries%RETRIES_PER_DELAY))
udelay(1000);
- uiStatus = 0 ;
+ uiStatus = 0;
}
return uiData;
} /* ReadEEPROMStatusRegister */
@@ -1095,7 +1095,7 @@ static int BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter,
goto BeceemFlashBulkWrite_EXIT;
}
uiTemp = uiTemp - 1;
- index = index + 1 ;
+ index = index + 1;
}
}
Adapter->SelectedChip = RESET_CHIP_SELECT;
@@ -1276,7 +1276,7 @@ static int BeceemFlashBulkWriteStatus(struct bcm_mini_adapter *Adapter,
goto BeceemFlashBulkWriteStatus_EXIT;
}
uiTemp = uiTemp - 1;
- index = index + 1 ;
+ index = index + 1;
}
}
@@ -2831,7 +2831,7 @@ int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, enum bcm_flash2x
SectEndOffset = INVALID_OFFSET;
}
- return SectEndOffset ;
+ return SectEndOffset;
}
/*
@@ -3358,7 +3358,7 @@ int BcmSetActiveSection(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_secti
/* struct bcm_dsd_header sDSD = {0};
* struct bcm_iso_header sISO = {0};
*/
- int HighestPriDSD = 0 ;
+ int HighestPriDSD = 0;
int HighestPriISO = 0;
Status = IsSectionWritable(Adapter, eFlash2xSectVal);
@@ -4450,7 +4450,7 @@ int WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter,
BcmDoChipSelect(Adapter, uiOffset);
uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter);
- for (i = 0 ; i < uiNumBytes; i += Adapter->ulFlashWriteSize) {
+ for (i = 0; i < uiNumBytes; i += Adapter->ulFlashWriteSize) {
if (Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT)
Status = flashByteWrite(Adapter, uiPartOffset, pcBuff);
else
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index f73287eab373..24f3cf273e5b 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -485,6 +485,7 @@ config COMEDI_NI_ATMIO
tristate "NI AT-MIO E series ISA-PNP card support"
select COMEDI_8255
select COMEDI_NI_TIO
+ select COMEDI_FC
---help---
Enable support for National Instruments AT-MIO E series cards
National Instruments AT-MIO-16E-1 (ni_atmio),
diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
index 2e19f659cd22..6db099bdbc58 100644
--- a/drivers/staging/comedi/comedidev.h
+++ b/drivers/staging/comedi/comedidev.h
@@ -307,7 +307,26 @@ static inline bool comedi_range_is_unipolar(struct comedi_subdevice *s,
return s->range_table->range[range].min >= 0;
}
-/* some silly little inline functions */
+static inline bool comedi_chan_range_is_bipolar(struct comedi_subdevice *s,
+ unsigned int chan,
+ unsigned int range)
+{
+ return s->range_table_list[chan]->range[range].min < 0;
+}
+
+static inline bool comedi_chan_range_is_unipolar(struct comedi_subdevice *s,
+ unsigned int chan,
+ unsigned int range)
+{
+ return s->range_table_list[chan]->range[range].min >= 0;
+}
+
+/* munge between offset binary and two's complement values */
+static inline unsigned int comedi_offset_munge(struct comedi_subdevice *s,
+ unsigned int val)
+{
+ return val ^ s->maxdata ^ (s->maxdata >> 1);
+}
static inline unsigned int bytes_per_sample(const struct comedi_subdevice *subd)
{
@@ -345,6 +364,8 @@ void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset,
int comedi_dio_insn_config(struct comedi_device *, struct comedi_subdevice *,
struct comedi_insn *, unsigned int *data,
unsigned int mask);
+unsigned int comedi_dio_update_state(struct comedi_subdevice *,
+ unsigned int *data);
void *comedi_alloc_devpriv(struct comedi_device *, size_t);
int comedi_alloc_subdevices(struct comedi_device *, int);
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index 317a821b7906..8f02bf66e20b 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -190,6 +190,28 @@ int comedi_dio_insn_config(struct comedi_device *dev,
}
EXPORT_SYMBOL_GPL(comedi_dio_insn_config);
+/**
+ * comedi_dio_update_state() - update the internal state of DIO subdevices.
+ * @s: comedi_subdevice struct
+ * @data: the channel mask and bits to update
+ */
+unsigned int comedi_dio_update_state(struct comedi_subdevice *s,
+ unsigned int *data)
+{
+ unsigned int chanmask = (s->n_chan < 32) ? ((1 << s->n_chan) - 1)
+ : 0xffffffff;
+ unsigned int mask = data[0] & chanmask;
+ unsigned int bits = data[1];
+
+ if (mask) {
+ s->state &= ~mask;
+ s->state |= (bits & mask);
+ }
+
+ return mask;
+}
+EXPORT_SYMBOL_GPL(comedi_dio_update_state);
+
static int insn_rw_emulate_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
@@ -285,6 +307,13 @@ static int __comedi_device_postconfig(struct comedi_device *dev)
if (s->type == COMEDI_SUBD_UNUSED)
continue;
+ if (s->type == COMEDI_SUBD_DO) {
+ if (s->n_chan < 32)
+ s->io_bits = (1 << s->n_chan) - 1;
+ else
+ s->io_bits = 0xffffffff;
+ }
+
if (s->len_chanlist == 0)
s->len_chanlist = 1;
diff --git a/drivers/staging/comedi/drivers/8253.h b/drivers/staging/comedi/drivers/8253.h
index 3abedcd2527b..e3d737cf7302 100644
--- a/drivers/staging/comedi/drivers/8253.h
+++ b/drivers/staging/comedi/drivers/8253.h
@@ -21,6 +21,15 @@
#include "../comedi.h"
+/*
+ * Common oscillator base values in nanoseconds
+ */
+#define I8254_OSC_BASE_10MHZ 100
+#define I8254_OSC_BASE_5MHZ 200
+#define I8254_OSC_BASE_4MHZ 250
+#define I8254_OSC_BASE_2MHZ 500
+#define I8254_OSC_BASE_1MHZ 1000
+
#define i8253_cascade_ns_to_timer i8253_cascade_ns_to_timer_2div
static inline void i8253_cascade_ns_to_timer_2div_old(int i8253_osc_base,
diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
index 2f070fdbbb1d..5737bb4c29ab 100644
--- a/drivers/staging/comedi/drivers/8255.c
+++ b/drivers/staging/comedi/drivers/8255.c
@@ -126,30 +126,24 @@ EXPORT_SYMBOL_GPL(subdev_8255_interrupt);
static int subdev_8255_insn(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct subdev_8255_private *spriv = s->private;
unsigned long iobase = spriv->iobase;
unsigned int mask;
- unsigned int bits;
unsigned int v;
- mask = data[0];
- bits = data[1];
-
+ mask = comedi_dio_update_state(s, data);
if (mask) {
- v = s->state;
- v &= ~mask;
- v |= (bits & mask);
-
if (mask & 0xff)
- spriv->io(1, _8255_DATA, v & 0xff, iobase);
+ spriv->io(1, _8255_DATA, s->state & 0xff, iobase);
if (mask & 0xff00)
- spriv->io(1, _8255_DATA + 1, (v >> 8) & 0xff, iobase);
+ spriv->io(1, _8255_DATA + 1, (s->state >> 8) & 0xff,
+ iobase);
if (mask & 0xff0000)
- spriv->io(1, _8255_DATA + 2, (v >> 16) & 0xff, iobase);
-
- s->state = v;
+ spriv->io(1, _8255_DATA + 2, (s->state >> 16) & 0xff,
+ iobase);
}
v = spriv->io(0, _8255_DATA, 0, iobase);
@@ -288,9 +282,6 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s,
s->insn_bits = subdev_8255_insn;
s->insn_config = subdev_8255_insn_config;
- s->state = 0;
- s->io_bits = 0;
-
subdev_8255_do_config(dev, s);
return 0;
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
index 63dff7729ea8..dc87df032203 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
@@ -204,7 +204,6 @@ static int addi_auto_attach(struct comedi_device *dev,
s->len_chanlist =
devpriv->s_EeParameters.i_NbrDiChannel;
s->range_table = &range_digital;
- s->io_bits = 0; /* all bits input */
s->insn_config = this_board->di_config;
s->insn_read = this_board->di_read;
s->insn_write = this_board->di_write;
@@ -223,7 +222,6 @@ static int addi_auto_attach(struct comedi_device *dev,
s->len_chanlist =
devpriv->s_EeParameters.i_NbrDoChannel;
s->range_table = &range_digital;
- s->io_bits = 0xf; /* all bits output */
/* insn_config - for digital output memory */
s->insn_config = this_board->do_config;
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
index e3cc429403c0..84668544f52d 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
@@ -260,18 +260,13 @@ static int apci1564_do_insn_bits(struct comedi_device *dev,
unsigned int *data)
{
struct addi_private *devpriv = dev->private;
- unsigned int mask = data[0];
- unsigned int bits = data[1];
s->state = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
APCI1564_DIGITAL_OP_RW);
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
+ if (comedi_dio_update_state(s, data))
outl(s->state, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
APCI1564_DIGITAL_OP_RW);
- }
data[1] = s->state;
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
index 1449b92403e2..ac6e75d62e61 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
@@ -2175,21 +2175,16 @@ static int apci3120_do_insn_bits(struct comedi_device *dev,
unsigned int *data)
{
struct addi_private *devpriv = dev->private;
- unsigned int mask = data[0];
- unsigned int bits = data[1];
- unsigned int val;
- /* The do channels are bits 7:4 of the do register */
- val = devpriv->b_DigitalOutputRegister >> 4;
- if (mask) {
- val &= ~mask;
- val |= (bits & mask);
- devpriv->b_DigitalOutputRegister = val << 4;
+ if (comedi_dio_update_state(s, data)) {
+ /* The do channels are bits 7:4 of the do register */
+ devpriv->b_DigitalOutputRegister = s->state << 4;
- outb(val << 4, devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
+ outb(devpriv->b_DigitalOutputRegister,
+ devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
}
- data[1] = val;
+ data[1] = s->state;
return insn->n;
}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
index 32dce0329fd5..dc73d4d348ed 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
@@ -623,16 +623,11 @@ static int apci3200_do_insn_bits(struct comedi_device *dev,
unsigned int *data)
{
struct addi_private *devpriv = dev->private;
- unsigned int mask = data[0];
- unsigned int bits = data[1];
s->state = inl(devpriv->i_IobaseAddon) & 0xf;
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
+ if (comedi_dio_update_state(s, data))
outl(s->state, devpriv->i_IobaseAddon);
- }
data[1] = s->state;
diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c
index 08674c18cf42..9d1b1425c60b 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1516.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1516.c
@@ -90,16 +90,10 @@ static int apci1516_do_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
s->state = inw(dev->iobase + APCI1516_DO_REG);
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
+ if (comedi_dio_update_state(s, data))
outw(s->state, dev->iobase + APCI1516_DO_REG);
- }
data[1] = s->state;
diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c
index 96523744b8de..5ee204bcbeef 100644
--- a/drivers/staging/comedi/drivers/addi_apci_16xx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c
@@ -87,17 +87,8 @@ static int apci16xx_dio_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
- /* Only update the channels configured as outputs */
- mask &= s->io_bits;
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
-
+ if (comedi_dio_update_state(s, data))
outl(s->state, dev->iobase + APCI16XX_OUT_REG(s->index));
- }
data[1] = inl(dev->iobase + APCI16XX_IN_REG(s->index));
diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c
index 6b0ea16ff546..c77ee8732d38 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2032.c
@@ -57,16 +57,10 @@ static int apci2032_do_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
s->state = inl(dev->iobase + APCI2032_DO_REG);
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
+ if (comedi_dio_update_state(s, data))
outl(s->state, dev->iobase + APCI2032_DO_REG);
- }
data[1] = s->state;
diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c
index 92ac8ece8494..7fb32e778d8b 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2200.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2200.c
@@ -50,16 +50,10 @@ static int apci2200_do_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
s->state = inw(dev->iobase + APCI2200_DO_REG);
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
+ if (comedi_dio_update_state(s, data))
outw(s->state, dev->iobase + APCI2200_DO_REG);
- }
data[1] = s->state;
diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c
index d804957018ab..67d09e8afb2e 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3120.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3120.c
@@ -164,7 +164,6 @@ static int apci3120_auto_attach(struct comedi_device *dev,
s->maxdata = 1;
s->len_chanlist = this_board->i_NbrDiChannel;
s->range_table = &range_digital;
- s->io_bits = 0; /* all bits input */
s->insn_bits = apci3120_di_insn_bits;
/* Allocate and Initialise DO Subdevice Structures */
@@ -176,7 +175,6 @@ static int apci3120_auto_attach(struct comedi_device *dev,
s->maxdata = this_board->i_DoMaxdata;
s->len_chanlist = this_board->i_NbrDoChannel;
s->range_table = &range_digital;
- s->io_bits = 0xf; /* all bits output */
s->insn_bits = apci3120_do_insn_bits;
/* Allocate and Initialise Timer Subdevice Structures */
diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c
index d9650ffb7d2f..6138440b919e 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3501.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3501.c
@@ -161,16 +161,10 @@ static int apci3501_do_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
s->state = inl(dev->iobase + APCI3501_DO_REG);
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
+ if (comedi_dio_update_state(s, data))
outl(s->state, dev->iobase + APCI3501_DO_REG);
- }
data[1] = s->state;
diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
index cf5dd10eaf91..761cbf8f964b 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
@@ -664,16 +664,10 @@ static int apci3xxx_do_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
s->state = inl(dev->iobase + 48) & 0xf;
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
+ if (comedi_dio_update_state(s, data))
outl(s->state, dev->iobase + 48);
- }
data[1] = s->state;
@@ -717,16 +711,11 @@ static int apci3xxx_dio_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- unsigned int mask = data[0];
- unsigned int bits = data[1];
+ unsigned int mask;
unsigned int val;
- /* only update output channels */
- mask &= s->io_bits;
+ mask = comedi_dio_update_state(s, data);
if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
-
if (mask & 0xff)
outl(s->state & 0xff, dev->iobase + 80);
if (mask & 0xff0000)
diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
index a67ad57cefcb..dd092c7954a9 100644
--- a/drivers/staging/comedi/drivers/adl_pci6208.c
+++ b/drivers/staging/comedi/drivers/adl_pci6208.c
@@ -1,44 +1,35 @@
/*
- comedi/drivers/adl_pci6208.c
-
- Hardware driver for ADLink 6208 series cards:
- card | voltage output | current output
- -------------+-------------------+---------------
- PCI-6208V | 8 channels | -
- PCI-6216V | 16 channels | -
- PCI-6208A | 8 channels | 8 channels
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 2000 David A. Schleef <ds@schleef.org>
-
- 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.
-*/
+ * adl_pci6208.c
+ * Comedi driver for ADLink 6208 series cards
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ *
+ * 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.
+ */
+
/*
-Driver: adl_pci6208
-Description: ADLink PCI-6208/6216 Series Multi-channel Analog Output Cards
-Devices: (ADLink) PCI-6208 [adl_pci6208]
- (ADLink) PCI-6216 [adl_pci6216]
-Author: nsyeow <nsyeow@pd.jaring.my>
-Updated: Fri, 30 Jan 2004 14:44:27 +0800
-Status: untested
-
-Configuration Options: not applicable, uses PCI auto config
-
-References:
- - ni_660x.c
- - adl_pci9111.c copied the entire pci setup section
- - adl_pci9118.c
-*/
+ * Driver: adl_pci6208
+ * Description: ADLink PCI-6208/6216 Series Multi-channel Analog Output Cards
+ * Devices: (ADLink) PCI-6208 [adl_pci6208]
+ * (ADLink) PCI-6216 [adl_pci6216]
+ * Author: nsyeow <nsyeow@pd.jaring.my>
+ * Updated: Fri, 30 Jan 2004 14:44:27 +0800
+ * Status: untested
+ *
+ * Configuration Options: not applicable, uses PCI auto config
+ */
#include <linux/module.h>
+#include <linux/delay.h>
#include <linux/pci.h>
#include "../comedidev.h"
@@ -82,37 +73,56 @@ struct pci6208_private {
unsigned int ao_readback[PCI6208_MAX_AO_CHANNELS];
};
-static int pci6208_ao_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int pci6208_ao_wait_for_data_send(struct comedi_device *dev,
+ unsigned int timeout)
+{
+ unsigned int status;
+
+ while (timeout--) {
+ status = inw(dev->iobase + PCI6208_AO_STATUS);
+ if ((status & PCI6208_AO_STATUS_DATA_SEND) == 0)
+ return 0;
+ udelay(1);
+ }
+
+ return -ETIME;
+}
+
+static int pci6208_ao_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct pci6208_private *devpriv = dev->private;
- int chan = CR_CHAN(insn->chanspec);
- unsigned long invert = 1 << (16 - 1);
- unsigned long value = 0;
- unsigned short status;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int val = devpriv->ao_readback[chan];
+ int ret;
int i;
for (i = 0; i < insn->n; i++) {
- value = data[i] ^ invert;
+ val = data[i];
- do {
- status = inw(dev->iobase + PCI6208_AO_STATUS);
- } while (status & PCI6208_AO_STATUS_DATA_SEND);
+ /* D/A transfer rate is 2.2us, wait up to 10us */
+ ret = pci6208_ao_wait_for_data_send(dev, 10);
+ if (ret)
+ return ret;
- outw(value, dev->iobase + PCI6208_AO_CONTROL(chan));
+ /* the hardware expects two's complement values */
+ outw(comedi_offset_munge(s, val),
+ dev->iobase + PCI6208_AO_CONTROL(chan));
}
- devpriv->ao_readback[chan] = value;
+ devpriv->ao_readback[chan] = val;
return insn->n;
}
-static int pci6208_ao_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int pci6208_ao_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct pci6208_private *devpriv = dev->private;
- int chan = CR_CHAN(insn->chanspec);
+ unsigned int chan = CR_CHAN(insn->chanspec);
int i;
for (i = 0; i < insn->n; i++)
@@ -141,15 +151,8 @@ static int pci6208_do_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
-
+ if (comedi_dio_update_state(s, data))
outw(s->state, dev->iobase + PCI6208_DIO);
- }
data[1] = s->state;
@@ -193,8 +196,8 @@ static int pci6208_auto_attach(struct comedi_device *dev,
s->n_chan = boardinfo->ao_chans;
s->maxdata = 0xffff;
s->range_table = &range_bipolar10;
- s->insn_write = pci6208_ao_winsn;
- s->insn_read = pci6208_ao_rinsn;
+ s->insn_write = pci6208_ao_insn_write;
+ s->insn_read = pci6208_ao_insn_read;
s = &dev->subdevices[1];
/* digital input subdevice */
@@ -221,10 +224,6 @@ static int pci6208_auto_attach(struct comedi_device *dev,
val = inw(dev->iobase + PCI6208_DIO);
val = (val & PCI6208_DIO_DO_MASK) >> PCI6208_DIO_DO_SHIFT;
s->state = val;
- s->io_bits = 0x0f;
-
- dev_info(dev->class_dev, "%s: %s, I/O base=0x%04lx\n",
- dev->driver->driver_name, dev->board_name, dev->iobase);
return 0;
}
@@ -259,5 +258,5 @@ static struct pci_driver adl_pci6208_pci_driver = {
module_comedi_pci_driver(adl_pci6208_driver, adl_pci6208_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for ADLink 6208 series cards");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c
index 81b7203f824f..5617f5ca384a 100644
--- a/drivers/staging/comedi/drivers/adl_pci7x3x.c
+++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c
@@ -112,21 +112,10 @@ static int adl_pci7x3x_do_insn_bits(struct comedi_device *dev,
unsigned int *data)
{
unsigned long reg = (unsigned long)s->private;
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
+ if (comedi_dio_update_state(s, data))
outl(s->state, dev->iobase + reg);
- }
- /*
- * NOTE: The output register is not readable.
- * This returned state will not be correct until all the
- * outputs have been updated.
- */
data[1] = s->state;
return insn->n;
diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
index 78cea193504f..4db46f0f315e 100644
--- a/drivers/staging/comedi/drivers/adl_pci9111.c
+++ b/drivers/staging/comedi/drivers/adl_pci9111.c
@@ -86,8 +86,6 @@ TODO:
#define PCI9111_AI_INSTANT_READ_UDELAY_US 2
#define PCI9111_AI_INSTANT_READ_TIMEOUT 100
-#define PCI9111_8254_CLOCK_PERIOD_NS 500
-
/*
* IO address map and bit defines
*/
@@ -393,11 +391,10 @@ static int pci9111_ai_do_cmd_test(struct comedi_device *dev,
if (cmd->convert_src == TRIG_TIMER) {
tmp = cmd->convert_arg;
- i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
- &dev_private->div1,
- &dev_private->div2,
- &cmd->convert_arg,
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ,
+ &dev_private->div1,
+ &dev_private->div2,
+ &cmd->convert_arg, cmd->flags);
if (tmp != cmd->convert_arg)
error++;
}
@@ -813,15 +810,8 @@ static int pci9111_do_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
-
+ if (comedi_dio_update_state(s, data))
outw(s->state, dev->iobase + PCI9111_DIO_REG);
- }
data[1] = s->state;
diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
index 22196ada0362..bd5c8bbad090 100644
--- a/drivers/staging/comedi/drivers/adl_pci9118.c
+++ b/drivers/staging/comedi/drivers/adl_pci9118.c
@@ -671,13 +671,12 @@ static int pci9118_insn_bits_di(struct comedi_device *dev,
static int pci9118_insn_bits_do(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
+ if (comedi_dio_update_state(s, data))
outl(s->state & 0x0f, dev->iobase + PCI9118_DO);
- }
+
data[1] = s->state;
return insn->n;
@@ -793,7 +792,8 @@ static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
case 4:
if (*tim2 < this_board->ai_ns_min)
*tim2 = this_board->ai_ns_min;
- i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, div1, div2,
+ i8253_cascade_ns_to_timer(devpriv->i8254_osc_base,
+ div1, div2,
tim2, flags & TRIG_ROUND_NEAREST);
break;
case 2:
@@ -1278,9 +1278,9 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
if (cmd->scan_begin_src == TRIG_TIMER) {
tmp = cmd->scan_begin_arg;
- i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
- &divisor2, &cmd->scan_begin_arg,
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(devpriv->i8254_osc_base,
+ &divisor1, &divisor2,
+ &cmd->scan_begin_arg, cmd->flags);
if (cmd->scan_begin_arg < this_board->ai_ns_min)
cmd->scan_begin_arg = this_board->ai_ns_min;
if (tmp != cmd->scan_begin_arg)
@@ -1289,9 +1289,9 @@ static int pci9118_ai_cmdtest(struct comedi_device *dev,
if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
tmp = cmd->convert_arg;
- i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
- &divisor2, &cmd->convert_arg,
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(devpriv->i8254_osc_base,
+ &divisor1, &divisor2,
+ &cmd->convert_arg, cmd->flags);
if (cmd->convert_arg < this_board->ai_ns_min)
cmd->convert_arg = this_board->ai_ns_min;
if (tmp != cmd->convert_arg)
@@ -2075,7 +2075,6 @@ static int pci9118_common_attach(struct comedi_device *dev, int disable_irq,
s->maxdata = 1;
s->len_chanlist = 4;
s->range_table = &range_digital;
- s->io_bits = 0; /* all bits input */
s->insn_bits = pci9118_insn_bits_di;
s = &dev->subdevices[3];
@@ -2085,11 +2084,10 @@ static int pci9118_common_attach(struct comedi_device *dev, int disable_irq,
s->maxdata = 1;
s->len_chanlist = 4;
s->range_table = &range_digital;
- s->io_bits = 0xf; /* all bits output */
s->insn_bits = pci9118_insn_bits_do;
devpriv->valid = 1;
- devpriv->i8254_osc_base = 250; /* 250ns=4MHz */
+ devpriv->i8254_osc_base = I8254_OSC_BASE_4MHZ;
devpriv->ai_maskharderr = 0x10a;
/* default measure crash condition */
if (hw_err_mask) /* disable some requested */
diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
index cdf5ba26c590..8150a67cd1fb 100644
--- a/drivers/staging/comedi/drivers/adq12b.c
+++ b/drivers/staging/comedi/drivers/adq12b.c
@@ -119,7 +119,6 @@ struct adq12b_private {
int differential; /* option 3 of comedi_config */
int last_channel;
int last_range;
- unsigned int digital_state;
};
/*
@@ -186,23 +185,25 @@ static int adq12b_di_insn_bits(struct comedi_device *dev,
static int adq12b_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct adq12b_private *devpriv = dev->private;
- int channel;
-
- for (channel = 0; channel < 8; channel++)
- if (((data[0] >> channel) & 0x01) != 0)
- outb((((data[1] >> channel) & 0x01) << 3) | channel,
- dev->iobase + ADQ12B_OUTBR);
-
- /* store information to retrieve when asked for reading */
- if (data[0]) {
- devpriv->digital_state &= ~data[0];
- devpriv->digital_state |= (data[0] & data[1]);
+ unsigned int mask;
+ unsigned int chan;
+ unsigned int val;
+
+ mask = comedi_dio_update_state(s, data);
+ if (mask) {
+ for (chan = 0; chan < 8; chan++) {
+ if ((mask >> chan) & 0x01) {
+ val = (s->state >> chan) & 0x01;
+ outb((val << 3) | chan,
+ dev->iobase + ADQ12B_OUTBR);
+ }
+ }
}
- data[1] = devpriv->digital_state;
+ data[1] = s->state;
return insn->n;
}
@@ -223,7 +224,6 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
devpriv->unipolar = it->options[1];
devpriv->differential = it->options[2];
- devpriv->digital_state = 0;
/*
* initialize channel and range to -1 so we make sure we
* always write at least once to the CTREG in the instruction
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
index f84df46d326a..49b39ec22708 100644
--- a/drivers/staging/comedi/drivers/adv_pci1710.c
+++ b/drivers/staging/comedi/drivers/adv_pci1710.c
@@ -544,18 +544,14 @@ static int pci171x_insn_bits_di(struct comedi_device *dev,
return insn->n;
}
-/*
-==============================================================================
-*/
static int pci171x_insn_bits_do(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
+ if (comedi_dio_update_state(s, data))
outw(s->state, dev->iobase + PCI171x_DO);
- }
+
data[1] = s->state;
return insn->n;
@@ -1009,9 +1005,10 @@ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev,
} else {
devpriv->ai_et = 0;
}
- i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
- &divisor2, &devpriv->ai_timer1,
- devpriv->ai_flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(devpriv->i8254_osc_base,
+ &divisor1, &divisor2,
+ &devpriv->ai_timer1,
+ devpriv->ai_flags);
outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
if (mode != 2) {
/* start pacer */
@@ -1090,9 +1087,9 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
if (cmd->convert_src == TRIG_TIMER) {
tmp = cmd->convert_arg;
- i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
- &divisor2, &cmd->convert_arg,
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(devpriv->i8254_osc_base,
+ &divisor1, &divisor2,
+ &cmd->convert_arg, cmd->flags);
if (cmd->convert_arg < this_board->ai_ns_min)
cmd->convert_arg = this_board->ai_ns_min;
if (tmp != cmd->convert_arg)
@@ -1288,7 +1285,7 @@ static int pci1710_auto_attach(struct comedi_device *dev,
s->do_cmdtest = pci171x_ai_cmdtest;
s->do_cmd = pci171x_ai_cmd;
}
- devpriv->i8254_osc_base = 100; /* 100ns=10MHz */
+ devpriv->i8254_osc_base = I8254_OSC_BASE_10MHZ;
subdev++;
}
@@ -1320,7 +1317,6 @@ static int pci1710_auto_attach(struct comedi_device *dev,
s->maxdata = 1;
s->len_chanlist = this_board->n_dichan;
s->range_table = &range_digital;
- s->io_bits = 0; /* all bits input */
s->insn_bits = pci171x_insn_bits_di;
subdev++;
}
@@ -1333,9 +1329,6 @@ static int pci1710_auto_attach(struct comedi_device *dev,
s->maxdata = 1;
s->len_chanlist = this_board->n_dochan;
s->range_table = &range_digital;
- /* all bits output */
- s->io_bits = (1 << this_board->n_dochan) - 1;
- s->state = 0;
s->insn_bits = pci171x_insn_bits_do;
subdev++;
}
diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
index b793d6987b84..71321f75d0cd 100644
--- a/drivers/staging/comedi/drivers/adv_pci1723.c
+++ b/drivers/staging/comedi/drivers/adv_pci1723.c
@@ -205,19 +205,16 @@ static int pci1723_dio_insn_config(struct comedi_device *dev,
return insn->n;
}
-/*
- digital i/o bits read/write
-*/
static int pci1723_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
+ if (comedi_dio_update_state(s, data))
outw(s->state, dev->iobase + PCI1723_WRITE_DIGITAL_OUTPUT_CMD);
- }
+
data[1] = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA);
+
return insn->n;
}
diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
index f091fa0d304d..6bac665261f8 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -448,45 +448,39 @@ static int pci_dio_insn_bits_di_w(struct comedi_device *dev,
return insn->n;
}
-/*
-==============================================================================
-*/
static int pci_dio_insn_bits_do_b(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
const struct diosubd_data *d = (const struct diosubd_data *)s->private;
int i;
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
+ if (comedi_dio_update_state(s, data)) {
for (i = 0; i < d->regs; i++)
outb((s->state >> (8 * i)) & 0xff,
dev->iobase + d->addr + i);
}
+
data[1] = s->state;
return insn->n;
}
-/*
-==============================================================================
-*/
static int pci_dio_insn_bits_do_w(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
const struct diosubd_data *d = (const struct diosubd_data *)s->private;
int i;
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
+ if (comedi_dio_update_state(s, data)) {
for (i = 0; i < d->regs; i++)
outw((s->state >> (16 * i)) & 0xffff,
dev->iobase + d->addr + 2 * i);
}
+
data[1] = s->state;
return insn->n;
@@ -641,12 +635,10 @@ static int pci1760_insn_bits_di(struct comedi_device *dev,
return insn->n;
}
-/*
-==============================================================================
-*/
static int pci1760_insn_bits_do(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
int ret;
unsigned char omb[4] = {
@@ -657,14 +649,13 @@ static int pci1760_insn_bits_do(struct comedi_device *dev,
};
unsigned char imb[4];
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
+ if (comedi_dio_update_state(s, data)) {
omb[0] = s->state;
ret = pci1760_mbxrequest(dev, omb, imb);
if (!ret)
return ret;
}
+
data[1] = s->state;
return insn->n;
diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
index afe87cc89761..22b3dda135ff 100644
--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
+++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
@@ -45,9 +45,7 @@ static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
+ if (comedi_dio_update_state(s, data)) {
outb(s->state & 0xff, dev->iobase + AIO_IIRO_16_RELAY_0_7);
outb((s->state >> 8) & 0xff,
dev->iobase + AIO_IIRO_16_RELAY_8_15);
diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c
index c1f723e86146..2e4bf284d52c 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200_common.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c
@@ -941,31 +941,34 @@ static void dio200_subdev_8255_set_dir(struct comedi_device *dev,
dio200_write8(dev, subpriv->ofs + 3, config);
}
-/*
- * Handle 'insn_bits' for an '8255' DIO subdevice.
- */
static int dio200_subdev_8255_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct dio200_subdev_8255 *subpriv = s->private;
+ unsigned int mask;
+ unsigned int val;
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
- if (data[0] & 0xff)
+ mask = comedi_dio_update_state(s, data);
+ if (mask) {
+ if (mask & 0xff)
dio200_write8(dev, subpriv->ofs, s->state & 0xff);
- if (data[0] & 0xff00)
+ if (mask & 0xff00)
dio200_write8(dev, subpriv->ofs + 1,
(s->state >> 8) & 0xff);
- if (data[0] & 0xff0000)
+ if (mask & 0xff0000)
dio200_write8(dev, subpriv->ofs + 2,
(s->state >> 16) & 0xff);
}
- data[1] = dio200_read8(dev, subpriv->ofs);
- data[1] |= dio200_read8(dev, subpriv->ofs + 1) << 8;
- data[1] |= dio200_read8(dev, subpriv->ofs + 2) << 16;
- return 2;
+
+ val = dio200_read8(dev, subpriv->ofs);
+ val |= dio200_read8(dev, subpriv->ofs + 1) << 8;
+ val |= dio200_read8(dev, subpriv->ofs + 2) << 16;
+
+ data[1] = val;
+
+ return insn->n;
}
/*
@@ -1022,8 +1025,6 @@ static int dio200_subdev_8255_init(struct comedi_device *dev,
s->maxdata = 1;
s->insn_bits = dio200_subdev_8255_bits;
s->insn_config = dio200_subdev_8255_config;
- s->state = 0;
- s->io_bits = 0;
dio200_subdev_8255_set_dir(dev, s);
return 0;
}
diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
index e7108045f553..5b4b5ab34e2e 100644
--- a/drivers/staging/comedi/drivers/amplc_pc263.c
+++ b/drivers/staging/comedi/drivers/amplc_pc263.c
@@ -57,17 +57,16 @@ static const struct pc263_board pc263_boards[] = {
static int pc263_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- /* The insn data is a mask in data[0] and the new data
- * in data[1], each channel cooresponding to a bit. */
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
- /* Write out the new digital output lines */
- outb(s->state & 0xFF, dev->iobase);
- outb(s->state >> 8, dev->iobase + 1);
+ if (comedi_dio_update_state(s, data)) {
+ outb(s->state & 0xff, dev->iobase);
+ outb((s->state >> 8) & 0xff, dev->iobase + 1);
}
+
+ data[1] = s->state;
+
return insn->n;
}
diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
index 179de53a86f0..cf385b8e32bf 100644
--- a/drivers/staging/comedi/drivers/amplc_pci224.c
+++ b/drivers/staging/comedi/drivers/amplc_pci224.c
@@ -215,12 +215,6 @@ Caveats:
#define CLK_EXT 7 /* external clock */
/* Macro to construct clock input configuration register value. */
#define CLK_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
-/* Timebases in ns. */
-#define TIMEBASE_10MHZ 100
-#define TIMEBASE_1MHZ 1000
-#define TIMEBASE_100KHZ 10000
-#define TIMEBASE_10KHZ 100000
-#define TIMEBASE_1KHZ 1000000
/*
* Counter/timer gate input configuration sources.
@@ -843,26 +837,26 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
switch (round_mode) {
case TRIG_ROUND_NEAREST:
default:
- round = TIMEBASE_10MHZ / 2;
+ round = I8254_OSC_BASE_10MHZ / 2;
break;
case TRIG_ROUND_DOWN:
round = 0;
break;
case TRIG_ROUND_UP:
- round = TIMEBASE_10MHZ - 1;
+ round = I8254_OSC_BASE_10MHZ - 1;
break;
}
/* Be careful to avoid overflow! */
- div2 = cmd->scan_begin_arg / TIMEBASE_10MHZ;
- div2 += (round + cmd->scan_begin_arg % TIMEBASE_10MHZ) /
- TIMEBASE_10MHZ;
+ div2 = cmd->scan_begin_arg / I8254_OSC_BASE_10MHZ;
+ div2 += (round + cmd->scan_begin_arg % I8254_OSC_BASE_10MHZ) /
+ I8254_OSC_BASE_10MHZ;
if (div2 <= 0x10000) {
/* A single timer will suffice. */
if (div2 < 2)
div2 = 2;
- cmd->scan_begin_arg = div2 * TIMEBASE_10MHZ;
+ cmd->scan_begin_arg = div2 * I8254_OSC_BASE_10MHZ;
if (cmd->scan_begin_arg < div2 ||
- cmd->scan_begin_arg < TIMEBASE_10MHZ) {
+ cmd->scan_begin_arg < I8254_OSC_BASE_10MHZ) {
/* Overflow! */
cmd->scan_begin_arg = MAX_SCAN_PERIOD;
}
@@ -870,7 +864,8 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
/* Use two timers. */
div1 = devpriv->cached_div1;
div2 = devpriv->cached_div2;
- pci224_cascade_ns_to_timer(TIMEBASE_10MHZ, &div1, &div2,
+ pci224_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+ &div1, &div2,
&cmd->scan_begin_arg,
round_mode);
devpriv->cached_div1 = div1;
@@ -1002,19 +997,19 @@ static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
switch (round_mode) {
case TRIG_ROUND_NEAREST:
default:
- round = TIMEBASE_10MHZ / 2;
+ round = I8254_OSC_BASE_10MHZ / 2;
break;
case TRIG_ROUND_DOWN:
round = 0;
break;
case TRIG_ROUND_UP:
- round = TIMEBASE_10MHZ - 1;
+ round = I8254_OSC_BASE_10MHZ - 1;
break;
}
/* Be careful to avoid overflow! */
- div2 = cmd->scan_begin_arg / TIMEBASE_10MHZ;
- div2 += (round + cmd->scan_begin_arg % TIMEBASE_10MHZ) /
- TIMEBASE_10MHZ;
+ div2 = cmd->scan_begin_arg / I8254_OSC_BASE_10MHZ;
+ div2 += (round + cmd->scan_begin_arg % I8254_OSC_BASE_10MHZ) /
+ I8254_OSC_BASE_10MHZ;
if (div2 <= 0x10000) {
/* A single timer will suffice. */
if (div2 < 2)
@@ -1025,7 +1020,8 @@ static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
/* Use two timers. */
div1 = devpriv->cached_div1;
div2 = devpriv->cached_div2;
- pci224_cascade_ns_to_timer(TIMEBASE_10MHZ, &div1, &div2,
+ pci224_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+ &div1, &div2,
&ns, round_mode);
}
diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c
index 145bb48f618e..4bd4ef8e88cd 100644
--- a/drivers/staging/comedi/drivers/amplc_pci263.c
+++ b/drivers/staging/comedi/drivers/amplc_pci263.c
@@ -44,17 +44,16 @@ The state of the outputs can be read.
static int pci263_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- /* The insn data is a mask in data[0] and the new data
- * in data[1], each channel cooresponding to a bit. */
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
- /* Write out the new digital output lines */
- outb(s->state & 0xFF, dev->iobase);
- outb(s->state >> 8, dev->iobase + 1);
+ if (comedi_dio_update_state(s, data)) {
+ outb(s->state & 0xff, dev->iobase);
+ outb((s->state >> 8) & 0xff, dev->iobase + 1);
}
+
+ data[1] = s->state;
+
return insn->n;
}
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index 0ce93da70847..64d5f291553f 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -234,9 +234,9 @@ static int das16cs_ai_cmdtest(struct comedi_device *dev,
unsigned int div1 = 0, div2 = 0;
tmp = cmd->scan_begin_arg;
- i8253_cascade_ns_to_timer(100, &div1, &div2,
- &cmd->scan_begin_arg,
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+ &div1, &div2,
+ &cmd->scan_begin_arg, cmd->flags);
if (tmp != cmd->scan_begin_arg)
err++;
}
@@ -244,9 +244,9 @@ static int das16cs_ai_cmdtest(struct comedi_device *dev,
unsigned int div1 = 0, div2 = 0;
tmp = cmd->convert_arg;
- i8253_cascade_ns_to_timer(100, &div1, &div2,
- &cmd->scan_begin_arg,
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+ &div1, &div2,
+ &cmd->scan_begin_arg, cmd->flags);
if (tmp != cmd->convert_arg)
err++;
if (cmd->scan_begin_src == TRIG_TIMER &&
@@ -325,14 +325,11 @@ static int das16cs_ao_rinsn(struct comedi_device *dev,
static int das16cs_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
-
+ if (comedi_dio_update_state(s, data))
outw(s->state, dev->iobase + DAS16CS_DIO);
- }
data[1] = inw(dev->iobase + DAS16CS_DIO);
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index 41d89ee7fa33..0891659f9eb5 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -73,7 +73,6 @@ analog triggering on 1602 series
#include "amcc_s5933.h"
#include "comedi_fc.h"
-#define TIMER_BASE 100 /* 10MHz master clock */
#define AI_BUFFER_SIZE 1024 /* max ai fifo size */
#define AO_BUFFER_SIZE 1024 /* max ao fifo size */
#define NUM_CHANNELS_8800 8
@@ -880,21 +879,19 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
if (cmd->scan_begin_src == TRIG_TIMER) {
tmp = cmd->scan_begin_arg;
- i8253_cascade_ns_to_timer_2div(TIMER_BASE,
- &(devpriv->divisor1),
- &(devpriv->divisor2),
- &(cmd->scan_begin_arg),
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+ &devpriv->divisor1,
+ &devpriv->divisor2,
+ &cmd->scan_begin_arg, cmd->flags);
if (tmp != cmd->scan_begin_arg)
err++;
}
if (cmd->convert_src == TRIG_TIMER) {
tmp = cmd->convert_arg;
- i8253_cascade_ns_to_timer_2div(TIMER_BASE,
- &(devpriv->divisor1),
- &(devpriv->divisor2),
- &(cmd->convert_arg),
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+ &devpriv->divisor1,
+ &devpriv->divisor2,
+ &cmd->convert_arg, cmd->flags);
if (tmp != cmd->convert_arg)
err++;
}
@@ -932,9 +929,9 @@ static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns,
{
struct cb_pcidas_private *devpriv = dev->private;
- i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
- &(devpriv->divisor2), ns,
- rounding_flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+ &devpriv->divisor1, &devpriv->divisor2,
+ ns, rounding_flags);
/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 1,
@@ -1084,11 +1081,10 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
if (cmd->scan_begin_src == TRIG_TIMER) {
tmp = cmd->scan_begin_arg;
- i8253_cascade_ns_to_timer_2div(TIMER_BASE,
- &(devpriv->ao_divisor1),
- &(devpriv->ao_divisor2),
- &(cmd->scan_begin_arg),
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+ &devpriv->ao_divisor1,
+ &devpriv->ao_divisor2,
+ &cmd->scan_begin_arg, cmd->flags);
if (tmp != cmd->scan_begin_arg)
err++;
}
@@ -1209,11 +1205,10 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev,
/* load counters */
if (cmd->scan_begin_src == TRIG_TIMER) {
- i8253_cascade_ns_to_timer_2div(TIMER_BASE,
- &(devpriv->ao_divisor1),
- &(devpriv->ao_divisor2),
- &(cmd->scan_begin_arg),
- cmd->flags);
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+ &devpriv->ao_divisor1,
+ &devpriv->ao_divisor2,
+ &cmd->scan_begin_arg, cmd->flags);
/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 1,
diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
index 388dbd7a5d27..e49743aed65d 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
@@ -3490,18 +3490,15 @@ static int di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
return insn->n;
}
-static int do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int do_wbits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct pcidas64_private *devpriv = dev->private;
- data[0] &= 0xf;
- /* zero bits we are going to change */
- s->state &= ~data[0];
- /* set new bits */
- s->state |= data[0] & data[1];
-
- writeb(s->state, devpriv->dio_counter_iobase + DO_REG);
+ if (comedi_dio_update_state(s, data))
+ writeb(s->state, devpriv->dio_counter_iobase + DO_REG);
data[1] = s->state;
@@ -3526,14 +3523,14 @@ static int dio_60xx_config_insn(struct comedi_device *dev,
return insn->n;
}
-static int dio_60xx_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int dio_60xx_wbits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct pcidas64_private *devpriv = dev->private;
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
+ if (comedi_dio_update_state(s, data)) {
writeb(s->state,
devpriv->dio_counter_iobase + DIO_DATA_60XX_REG);
}
diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c
index f28a15f0274e..9de81c7712fb 100644
--- a/drivers/staging/comedi/drivers/comedi_parport.c
+++ b/drivers/staging/comedi/drivers/comedi_parport.c
@@ -1,168 +1,153 @@
/*
- comedi/drivers/comedi_parport.c
- hardware driver for standard parallel port
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 1998,2001 David A. Schleef <ds@schleef.org>
-
- 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.
-*/
-/*
-Driver: comedi_parport
-Description: Standard PC parallel port
-Author: ds
-Status: works in immediate mode
-Devices: [standard] parallel port (comedi_parport)
-Updated: Tue, 30 Apr 2002 21:11:45 -0700
-
-A cheap and easy way to get a few more digital I/O lines. Steal
-additional parallel ports from old computers or your neighbors'
-computers.
-
-Option list:
- 0: I/O port base for the parallel port.
- 1: IRQ
-
-Parallel Port Lines:
-
-pin subdev chan aka
---- ------ ---- ---
-1 2 0 strobe
-2 0 0 data 0
-3 0 1 data 1
-4 0 2 data 2
-5 0 3 data 3
-6 0 4 data 4
-7 0 5 data 5
-8 0 6 data 6
-9 0 7 data 7
-10 1 3 acknowledge
-11 1 4 busy
-12 1 2 output
-13 1 1 printer selected
-14 2 1 auto LF
-15 1 0 error
-16 2 2 init
-17 2 3 select printer
-18-25 ground
-
-Notes:
-
-Subdevices 0 is digital I/O, subdevice 1 is digital input, and
-subdevice 2 is digital output. Unlike other Comedi devices,
-subdevice 0 defaults to output.
-
-Pins 13 and 14 are inverted once by Comedi and once by the
-hardware, thus cancelling the effect.
-
-Pin 1 is a strobe, thus acts like one. There's no way in software
-to change this, at least on a standard parallel port.
-
-Subdevice 3 pretends to be a digital input subdevice, but it always
-returns 0 when read. However, if you run a command with
-scan_begin_src=TRIG_EXT, it uses pin 10 as a external triggering
-pin, which can be used to wake up tasks.
-*/
+ * comedi_parport.c
+ * Comedi driver for standard parallel port
+ *
+ * For more information see:
+ * http://retired.beyondlogic.org/spp/parallel.htm
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1998,2001 David A. Schleef <ds@schleef.org>
+ *
+ * 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.
+ */
+
/*
- see http://www.beyondlogic.org/ for information.
- or http://www.linux-magazin.de/ausgabe/1999/10/IO/io.html
+ * Driver: comedi_parport
+ * Description: Standard PC parallel port
+ * Author: ds
+ * Status: works in immediate mode
+ * Devices: (standard) parallel port [comedi_parport]
+ * Updated: Tue, 30 Apr 2002 21:11:45 -0700
+ *
+ * A cheap and easy way to get a few more digital I/O lines. Steal
+ * additional parallel ports from old computers or your neighbors'
+ * computers.
+ *
+ * Option list:
+ * 0: I/O port base for the parallel port.
+ * 1: IRQ (optional)
+ *
+ * Parallel Port Lines:
+ *
+ * pin subdev chan type name
+ * ----- ------ ---- ---- --------------
+ * 1 2 0 DO strobe
+ * 2 0 0 DIO data 0
+ * 3 0 1 DIO data 1
+ * 4 0 2 DIO data 2
+ * 5 0 3 DIO data 3
+ * 6 0 4 DIO data 4
+ * 7 0 5 DIO data 5
+ * 8 0 6 DIO data 6
+ * 9 0 7 DIO data 7
+ * 10 1 3 DI ack
+ * 11 1 4 DI busy
+ * 12 1 2 DI paper out
+ * 13 1 1 DI select in
+ * 14 2 1 DO auto LF
+ * 15 1 0 DI error
+ * 16 2 2 DO init
+ * 17 2 3 DO select printer
+ * 18-25 ground
+ *
+ * When an IRQ is configured subdevice 3 pretends to be a digital
+ * input subdevice, but it always returns 0 when read. However, if
+ * you run a command with scan_begin_src=TRIG_EXT, it uses pin 10
+ * as a external trigger, which can be used to wake up tasks.
*/
#include <linux/module.h>
-#include "../comedidev.h"
#include <linux/interrupt.h>
-#include "comedi_fc.h"
-
-#define PARPORT_SIZE 3
-
-#define PARPORT_A 0
-#define PARPORT_B 1
-#define PARPORT_C 2
+#include "../comedidev.h"
-struct parport_private {
- unsigned int a_data;
- unsigned int c_data;
- int enable_irq;
-};
+#include "comedi_fc.h"
-static int parport_insn_a(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+/*
+ * Register map
+ */
+#define PARPORT_DATA_REG 0x00
+#define PARPORT_STATUS_REG 0x01
+#define PARPORT_CTRL_REG 0x02
+#define PARPORT_CTRL_IRQ_ENA (1 << 4)
+#define PARPORT_CTRL_BIDIR_ENA (1 << 5)
+
+static int parport_data_reg_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct parport_private *devpriv = dev->private;
-
- if (data[0]) {
- devpriv->a_data &= ~data[0];
- devpriv->a_data |= (data[0] & data[1]);
-
- outb(devpriv->a_data, dev->iobase + PARPORT_A);
- }
+ if (comedi_dio_update_state(s, data))
+ outb(s->state, dev->iobase + PARPORT_DATA_REG);
- data[1] = inb(dev->iobase + PARPORT_A);
+ data[1] = inb(dev->iobase + PARPORT_DATA_REG);
return insn->n;
}
-static int parport_insn_config_a(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int parport_data_reg_insn_config(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct parport_private *devpriv = dev->private;
-
- if (data[0]) {
- s->io_bits = 0xff;
- devpriv->c_data &= ~(1 << 5);
- } else {
- s->io_bits = 0;
- devpriv->c_data |= (1 << 5);
- }
- outb(devpriv->c_data, dev->iobase + PARPORT_C);
+ unsigned int ctrl;
+ int ret;
+
+ ret = comedi_dio_insn_config(dev, s, insn, data, 0xff);
+ if (ret)
+ return ret;
+
+ ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
+ if (s->io_bits)
+ ctrl &= ~PARPORT_CTRL_BIDIR_ENA;
+ else
+ ctrl |= PARPORT_CTRL_BIDIR_ENA;
+ outb(ctrl, dev->iobase + PARPORT_CTRL_REG);
- return 1;
+ return insn->n;
}
-static int parport_insn_b(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int parport_status_reg_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- if (data[0]) {
- /* should writes be ignored? */
- /* anyone??? */
- }
-
- data[1] = (inb(dev->iobase + PARPORT_B) >> 3);
+ data[1] = inb(dev->iobase + PARPORT_STATUS_REG) >> 3;
return insn->n;
}
-static int parport_insn_c(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int parport_ctrl_reg_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct parport_private *devpriv = dev->private;
-
- data[0] &= 0x0f;
- if (data[0]) {
- devpriv->c_data &= ~data[0];
- devpriv->c_data |= (data[0] & data[1]);
+ unsigned int ctrl;
- outb(devpriv->c_data, dev->iobase + PARPORT_C);
+ if (comedi_dio_update_state(s, data)) {
+ ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
+ ctrl &= (PARPORT_CTRL_IRQ_ENA | PARPORT_CTRL_BIDIR_ENA);
+ ctrl |= s->state;
+ outb(ctrl, dev->iobase + PARPORT_CTRL_REG);
}
- data[1] = devpriv->c_data & 0xf;
+ data[1] = s->state;
return insn->n;
}
-static int parport_intr_insn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int parport_intr_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
data[1] = 0;
return insn->n;
@@ -213,12 +198,11 @@ static int parport_intr_cmdtest(struct comedi_device *dev,
static int parport_intr_cmd(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- struct parport_private *devpriv = dev->private;
+ unsigned int ctrl;
- devpriv->c_data |= 0x10;
- outb(devpriv->c_data, dev->iobase + PARPORT_C);
-
- devpriv->enable_irq = 1;
+ ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
+ ctrl |= PARPORT_CTRL_IRQ_ENA;
+ outb(ctrl, dev->iobase + PARPORT_CTRL_REG);
return 0;
}
@@ -226,12 +210,11 @@ static int parport_intr_cmd(struct comedi_device *dev,
static int parport_intr_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- struct parport_private *devpriv = dev->private;
-
- devpriv->c_data &= ~0x10;
- outb(devpriv->c_data, dev->iobase + PARPORT_C);
+ unsigned int ctrl;
- devpriv->enable_irq = 0;
+ ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
+ ctrl &= ~PARPORT_CTRL_IRQ_ENA;
+ outb(ctrl, dev->iobase + PARPORT_CTRL_REG);
return 0;
}
@@ -239,10 +222,11 @@ static int parport_intr_cancel(struct comedi_device *dev,
static irqreturn_t parport_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
- struct parport_private *devpriv = dev->private;
- struct comedi_subdevice *s = &dev->subdevices[3];
+ struct comedi_subdevice *s = dev->read_subdev;
+ unsigned int ctrl;
- if (!devpriv->enable_irq)
+ ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
+ if (!(ctrl & PARPORT_CTRL_IRQ_ENA))
return IRQ_NONE;
comedi_buf_put(s->async, 0);
@@ -255,79 +239,69 @@ static irqreturn_t parport_interrupt(int irq, void *d)
static int parport_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
- struct parport_private *devpriv;
struct comedi_subdevice *s;
- unsigned int irq;
int ret;
- ret = comedi_request_region(dev, it->options[0], PARPORT_SIZE);
+ ret = comedi_request_region(dev, it->options[0], 0x03);
if (ret)
return ret;
- irq = it->options[1];
- if (irq) {
- ret = request_irq(irq, parport_interrupt, 0, dev->board_name,
- dev);
- if (ret < 0) {
- dev_err(dev->class_dev, "irq not available\n");
- return -EINVAL;
- }
- dev->irq = irq;
+ if (it->options[1]) {
+ ret = request_irq(it->options[1], parport_interrupt, 0,
+ dev->board_name, dev);
+ if (ret == 0)
+ dev->irq = it->options[1];
}
- ret = comedi_alloc_subdevices(dev, 4);
+ ret = comedi_alloc_subdevices(dev, dev->irq ? 4 : 3);
if (ret)
return ret;
- devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
- if (!devpriv)
- return -ENOMEM;
-
+ /* Digial I/O subdevice - Parallel port DATA register */
s = &dev->subdevices[0];
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = 8;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = parport_insn_a;
- s->insn_config = parport_insn_config_a;
-
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 8;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = parport_data_reg_insn_bits;
+ s->insn_config = parport_data_reg_insn_config;
+
+ /* Digial Input subdevice - Parallel port STATUS register */
s = &dev->subdevices[1];
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
- s->n_chan = 5;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = parport_insn_b;
-
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 5;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = parport_status_reg_insn_bits;
+
+ /* Digial Output subdevice - Parallel port CONTROL register */
s = &dev->subdevices[2];
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE;
- s->n_chan = 4;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = parport_insn_c;
-
- s = &dev->subdevices[3];
- if (irq) {
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = 4;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = parport_ctrl_reg_insn_bits;
+
+ if (dev->irq) {
+ /* Digial Input subdevice - Interrupt support */
+ s = &dev->subdevices[3];
dev->read_subdev = s;
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
- s->n_chan = 1;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = parport_intr_insn;
- s->do_cmdtest = parport_intr_cmdtest;
- s->do_cmd = parport_intr_cmd;
- s->cancel = parport_intr_cancel;
- } else {
- s->type = COMEDI_SUBD_UNUSED;
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
+ s->n_chan = 1;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = parport_intr_insn_bits;
+ s->do_cmdtest = parport_intr_cmdtest;
+ s->do_cmd = parport_intr_cmd;
+ s->cancel = parport_intr_cancel;
}
- devpriv->a_data = 0;
- outb(devpriv->a_data, dev->iobase + PARPORT_A);
- devpriv->c_data = 0;
- outb(devpriv->c_data, dev->iobase + PARPORT_C);
+ outb(0, dev->iobase + PARPORT_DATA_REG);
+ outb(0, dev->iobase + PARPORT_CTRL_REG);
return 0;
}
@@ -341,5 +315,5 @@ static struct comedi_driver parport_driver = {
module_comedi_driver(parport_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi: Standard parallel port driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
index e781716bf355..89836c0828d9 100644
--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
+++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
@@ -40,17 +40,11 @@ Configuration Options: not applicable, uses comedi PCI auto config
static int contec_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
-
+ if (comedi_dio_update_state(s, data))
outw(s->state, dev->iobase + PIO1616L_DO_REG);
- }
data[1] = s->state;
diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
index 5f669709501f..15dd33e3e1c7 100644
--- a/drivers/staging/comedi/drivers/das08.c
+++ b/drivers/staging/comedi/drivers/das08.c
@@ -279,27 +279,23 @@ static int das08_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
return insn->n;
}
-static int das08_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int das08_do_wbits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct das08_private_struct *devpriv = dev->private;
- int wbits;
-
- /* get current settings of digital output lines */
- wbits = (devpriv->do_mux_bits >> 4) & 0xf;
- /* null bits we are going to set */
- wbits &= ~data[0];
- /* set new bit values */
- wbits |= data[0] & data[1];
- /* remember digital output bits */
- /* prevent race with setting of analog input mux */
- spin_lock(&dev->spinlock);
- devpriv->do_mux_bits &= ~DAS08_DO_MASK;
- devpriv->do_mux_bits |= DAS08_OP(wbits);
- outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL);
- spin_unlock(&dev->spinlock);
- data[1] = wbits;
+ if (comedi_dio_update_state(s, data)) {
+ /* prevent race with setting of analog input mux */
+ spin_lock(&dev->spinlock);
+ devpriv->do_mux_bits &= ~DAS08_DO_MASK;
+ devpriv->do_mux_bits |= DAS08_OP(s->state);
+ outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL);
+ spin_unlock(&dev->spinlock);
+ }
+
+ data[1] = s->state;
return insn->n;
}
@@ -316,17 +312,13 @@ static int das08jr_di_rbits(struct comedi_device *dev,
static int das08jr_do_wbits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct das08_private_struct *devpriv = dev->private;
-
- /* null bits we are going to set */
- devpriv->do_bits &= ~data[0];
- /* set new bit values */
- devpriv->do_bits |= data[0] & data[1];
- outb(devpriv->do_bits, dev->iobase + DAS08JR_DIO);
+ if (comedi_dio_update_state(s, data))
+ outb(s->state, dev->iobase + DAS08JR_DIO);
- data[1] = devpriv->do_bits;
+ data[1] = s->state;
return insn->n;
}
diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h
index cce1b584200a..46a314c5113e 100644
--- a/drivers/staging/comedi/drivers/das08.h
+++ b/drivers/staging/comedi/drivers/das08.h
@@ -41,7 +41,6 @@ struct das08_board_struct {
struct das08_private_struct {
unsigned int do_mux_bits; /* bits for do/mux register on boards without separate do register */
- unsigned int do_bits; /* bits for do register on boards with register dedicated to digital out only */
const unsigned int *pg_gainlist;
unsigned int ao_readback[2]; /* assume 2 AO channels */
};
diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
index 1b0793f33b9f..30f3995d7297 100644
--- a/drivers/staging/comedi/drivers/das16.c
+++ b/drivers/staging/comedi/drivers/das16.c
@@ -675,21 +675,19 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
if (cmd->scan_begin_src == TRIG_TIMER) {
unsigned int tmp = cmd->scan_begin_arg;
/* set divisors, correct timing arguments */
- i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
- &devpriv->divisor1,
- &devpriv->divisor2,
- &cmd->scan_begin_arg,
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(devpriv->clockbase,
+ &devpriv->divisor1,
+ &devpriv->divisor2,
+ &cmd->scan_begin_arg, cmd->flags);
err += (tmp != cmd->scan_begin_arg);
}
if (cmd->convert_src == TRIG_TIMER) {
unsigned int tmp = cmd->convert_arg;
/* set divisors, correct timing arguments */
- i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
- &devpriv->divisor1,
- &devpriv->divisor2,
- &cmd->convert_arg,
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(devpriv->clockbase,
+ &devpriv->divisor1,
+ &devpriv->divisor2,
+ &cmd->convert_arg, cmd->flags);
err += (tmp != cmd->convert_arg);
}
if (err)
@@ -725,11 +723,9 @@ static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
struct das16_private_struct *devpriv = dev->private;
unsigned long timer_base = dev->iobase + DAS16_TIMER_BASE_REG;
- i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
- &devpriv->divisor1,
- &devpriv->divisor2,
- &ns,
- rounding_flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(devpriv->clockbase,
+ &devpriv->divisor1, &devpriv->divisor2,
+ &ns, rounding_flags);
/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
i8254_load(timer_base, 0, 1, devpriv->divisor1, 2);
@@ -952,15 +948,8 @@ static int das16_do_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
-
+ if (comedi_dio_update_state(s, data))
outb(s->state, dev->iobase + DAS16_DIO_REG);
- }
data[1] = s->state;
@@ -1043,14 +1032,15 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
status = inb(dev->iobase + DAS1600_STATUS_REG);
if (status & DAS1600_STATUS_CLK_10MHZ)
- devpriv->clockbase = 100;
+ devpriv->clockbase = I8254_OSC_BASE_10MHZ;
else
- devpriv->clockbase = 1000;
+ devpriv->clockbase = I8254_OSC_BASE_1MHZ;
} else {
if (it->options[3])
- devpriv->clockbase = 1000 / it->options[3];
+ devpriv->clockbase = I8254_OSC_BASE_1MHZ /
+ it->options[3];
else
- devpriv->clockbase = 1000; /* 1 MHz default */
+ devpriv->clockbase = I8254_OSC_BASE_1MHZ;
}
/* initialize dma */
diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
index b943c449b691..579b74e471d9 100644
--- a/drivers/staging/comedi/drivers/das16m1.c
+++ b/drivers/staging/comedi/drivers/das16m1.c
@@ -63,8 +63,6 @@ irq can be omitted, although the cmd interface will not work without it.
#define DAS16M1_SIZE 16
#define DAS16M1_SIZE2 8
-#define DAS16M1_XTAL 100 /* 10 MHz master clock */
-
#define FIFO_SIZE 1024 /* 1024 sample fifo */
/*
@@ -134,7 +132,6 @@ struct das16m1_private_struct {
* counter yet (loaded by first sample conversion) */
u16 initial_hw_count;
short ai_buffer[FIFO_SIZE];
- unsigned int do_bits; /* saves status of digital output bits */
unsigned int divisor1; /* divides master clock to obtain conversion speed */
unsigned int divisor2; /* divides master clock to obtain conversion speed */
unsigned long extra_iobase;
@@ -208,11 +205,10 @@ static int das16m1_cmd_test(struct comedi_device *dev,
if (cmd->convert_src == TRIG_TIMER) {
tmp = cmd->convert_arg;
/* calculate counter values that give desired timing */
- i8253_cascade_ns_to_timer_2div(DAS16M1_XTAL,
- &(devpriv->divisor1),
- &(devpriv->divisor2),
- &(cmd->convert_arg),
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+ &devpriv->divisor1,
+ &devpriv->divisor2,
+ &cmd->convert_arg, cmd->flags);
if (tmp != cmd->convert_arg)
err++;
}
@@ -251,9 +247,10 @@ static unsigned int das16m1_set_pacer(struct comedi_device *dev,
{
struct das16m1_private_struct *devpriv = dev->private;
- i8253_cascade_ns_to_timer_2div(DAS16M1_XTAL, &(devpriv->divisor1),
- &(devpriv->divisor2), &ns,
- rounding_flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer_2div(I8254_OSC_BASE_10MHZ,
+ &devpriv->divisor1,
+ &devpriv->divisor2,
+ &ns, rounding_flags);
/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
i8254_load(dev->iobase + DAS16M1_8254_SECOND, 0, 1, devpriv->divisor1,
@@ -393,22 +390,13 @@ static int das16m1_di_rbits(struct comedi_device *dev,
static int das16m1_do_wbits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct das16m1_private_struct *devpriv = dev->private;
- unsigned int wbits;
-
- /* only set bits that have been masked */
- data[0] &= 0xf;
- wbits = devpriv->do_bits;
- /* zero bits that have been masked */
- wbits &= ~data[0];
- /* set masked bits */
- wbits |= data[0] & data[1];
- devpriv->do_bits = wbits;
- data[1] = wbits;
+ if (comedi_dio_update_state(s, data))
+ outb(s->state, dev->iobase + DAS16M1_DIO);
- outb(devpriv->do_bits, dev->iobase + DAS16M1_DIO);
+ data[1] = s->state;
return insn->n;
}
@@ -649,7 +637,7 @@ static int das16m1_attach(struct comedi_device *dev,
outb(TOTAL_CLEAR, dev->iobase + DAS16M1_8254_FIRST_CNTRL);
/* initialize digital output lines */
- outb(devpriv->do_bits, dev->iobase + DAS16M1_DIO);
+ outb(0, dev->iobase + DAS16M1_DIO);
/* set the interrupt level */
if (dev->irq)
diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
index 5b300294d322..f753a10c6549 100644
--- a/drivers/staging/comedi/drivers/das1800.c
+++ b/drivers/staging/comedi/drivers/das1800.c
@@ -108,7 +108,6 @@ TODO:
/* misc. defines */
#define DAS1800_SIZE 16 /* uses 16 io addresses */
#define FIFO_SIZE 1024 /* 1024 sample fifo */
-#define TIMER_BASE 200 /* 5 Mhz master clock */
#define UNIPOLAR 0x4 /* bit that determines whether input range is uni/bipolar */
#define DMA_BUF_SIZE 0x1ff00 /* size in bytes of dma buffers */
@@ -427,7 +426,6 @@ struct das1800_private {
volatile unsigned int count; /* number of data points left to be taken */
unsigned int divisor1; /* value to load into board's counter 1 for timed conversions */
unsigned int divisor2; /* value to load into board's counter 2 for timed conversions */
- int do_bits; /* digital output bits */
int irq_dma_bits; /* bits for control register b */
/* dma bits for control register b, stored so that dma can be
* turned on and off */
@@ -840,12 +838,11 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev,
if (cmd->scan_begin_src == TRIG_FOLLOW) {
tmp_arg = cmd->convert_arg;
/* calculate counter values that give desired timing */
- i8253_cascade_ns_to_timer_2div(TIMER_BASE,
- &(devpriv->divisor1),
- &(devpriv->divisor2),
- &(cmd->convert_arg),
- cmd->
- flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
+ &devpriv->divisor1,
+ &devpriv->divisor2,
+ &cmd->convert_arg,
+ cmd->flags);
if (tmp_arg != cmd->convert_arg)
err++;
}
@@ -870,16 +867,11 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev,
}
tmp_arg = cmd->scan_begin_arg;
/* calculate counter values that give desired timing */
- i8253_cascade_ns_to_timer_2div(TIMER_BASE,
- &(devpriv->
- divisor1),
- &(devpriv->
- divisor2),
- &(cmd->
- scan_begin_arg),
- cmd->
- flags &
- TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
+ &devpriv->divisor1,
+ &devpriv->divisor2,
+ &cmd->scan_begin_arg,
+ cmd->flags);
if (tmp_arg != cmd->scan_begin_arg)
err++;
}
@@ -1011,12 +1003,10 @@ static int setup_counters(struct comedi_device *dev,
if (cmd->convert_src == TRIG_TIMER) {
/* set conversion frequency */
period = cmd->convert_arg;
- i8253_cascade_ns_to_timer_2div(TIMER_BASE,
- &devpriv->divisor1,
- &devpriv->divisor2,
- &period,
- cmd->flags &
- TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
+ &devpriv->divisor1,
+ &devpriv->divisor2,
+ &period, cmd->flags);
if (das1800_set_frequency(dev) < 0)
return -1;
}
@@ -1024,9 +1014,10 @@ static int setup_counters(struct comedi_device *dev,
case TRIG_TIMER: /* in burst mode */
/* set scan frequency */
period = cmd->scan_begin_arg;
- i8253_cascade_ns_to_timer_2div(TIMER_BASE, &devpriv->divisor1,
- &devpriv->divisor2, &period,
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
+ &devpriv->divisor1,
+ &devpriv->divisor2,
+ &period, cmd->flags);
if (das1800_set_frequency(dev) < 0)
return -1;
break;
@@ -1319,24 +1310,15 @@ static int das1800_di_rbits(struct comedi_device *dev,
return insn->n;
}
-/* writes to digital output channels */
static int das1800_do_wbits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- struct das1800_private *devpriv = dev->private;
- unsigned int wbits;
-
- /* only set bits that have been masked */
- data[0] &= (1 << s->n_chan) - 1;
- wbits = devpriv->do_bits;
- wbits &= ~data[0];
- wbits |= data[0] & data[1];
- devpriv->do_bits = wbits;
-
- outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
+ if (comedi_dio_update_state(s, data))
+ outb(s->state, dev->iobase + DAS1800_DIGITAL);
- data[1] = devpriv->do_bits;
+ data[1] = s->state;
return insn->n;
}
@@ -1644,7 +1626,7 @@ static int das1800_attach(struct comedi_device *dev,
das1800_cancel(dev, dev->read_subdev);
/* initialize digital out channels */
- outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
+ outb(0, dev->iobase + DAS1800_DIGITAL);
/* initialize analog out channels */
if (thisboard->ao_ability == 1) {
diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
index 11e16114e4e3..5af0a5764a8c 100644
--- a/drivers/staging/comedi/drivers/das800.c
+++ b/drivers/staging/comedi/drivers/das800.c
@@ -66,7 +66,6 @@ cmd triggers supported:
#include "comedi_fc.h"
#define DAS800_SIZE 8
-#define TIMER_BASE 1000
#define N_CHAN_AI 8 /* number of analog input channels */
/* Registers for the das800 */
@@ -356,11 +355,10 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev,
int tmp = cmd->convert_arg;
/* calculate counter values that give desired timing */
- i8253_cascade_ns_to_timer_2div(TIMER_BASE,
- &devpriv->divisor1,
- &devpriv->divisor2,
- &cmd->convert_arg,
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_1MHZ,
+ &devpriv->divisor1,
+ &devpriv->divisor2,
+ &cmd->convert_arg, cmd->flags);
if (tmp != cmd->convert_arg)
err++;
}
@@ -630,13 +628,9 @@ static int das800_do_insn_bits(struct comedi_device *dev,
unsigned int *data)
{
struct das800_private *devpriv = dev->private;
- unsigned int mask = data[0];
- unsigned int bits = data[1];
unsigned long irq_flags;
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
+ if (comedi_dio_update_state(s, data)) {
devpriv->do_bits = s->state << 4;
spin_lock_irqsave(&dev->spinlock, irq_flags);
diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
index 118a4fd129f9..b04a5633f754 100644
--- a/drivers/staging/comedi/drivers/dmm32at.c
+++ b/drivers/staging/comedi/drivers/dmm32at.c
@@ -596,52 +596,40 @@ static int dmm32at_ao_rinsn(struct comedi_device *dev,
static int dmm32at_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct dmm32at_private *devpriv = dev->private;
- unsigned char diobits;
-
- /* The insn data is a mask in data[0] and the new data
- * in data[1], each channel cooresponding to a bit. */
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
- /* Write out the new digital output lines */
- /* outw(s->state,dev->iobase + DMM32AT_DIO); */
+ unsigned int mask;
+ unsigned int val;
+
+ mask = comedi_dio_update_state(s, data);
+ if (mask) {
+ /* get access to the DIO regs */
+ outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL);
+
+ /* if either part of dio is set for output */
+ if (((devpriv->dio_config & DMM32AT_DIRCL) == 0) ||
+ ((devpriv->dio_config & DMM32AT_DIRCH) == 0)) {
+ val = (s->state & 0x00ff0000) >> 16;
+ outb(val, dev->iobase + DMM32AT_DIOC);
+ }
+ if ((devpriv->dio_config & DMM32AT_DIRB) == 0) {
+ val = (s->state & 0x0000ff00) >> 8;
+ outb(val, dev->iobase + DMM32AT_DIOB);
+ }
+ if ((devpriv->dio_config & DMM32AT_DIRA) == 0) {
+ val = (s->state & 0x000000ff);
+ outb(val, dev->iobase + DMM32AT_DIOA);
+ }
}
- /* get access to the DIO regs */
- outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL);
-
- /* if either part of dio is set for output */
- if (((devpriv->dio_config & DMM32AT_DIRCL) == 0) ||
- ((devpriv->dio_config & DMM32AT_DIRCH) == 0)) {
- diobits = (s->state & 0x00ff0000) >> 16;
- outb(diobits, dev->iobase + DMM32AT_DIOC);
- }
- if ((devpriv->dio_config & DMM32AT_DIRB) == 0) {
- diobits = (s->state & 0x0000ff00) >> 8;
- outb(diobits, dev->iobase + DMM32AT_DIOB);
- }
- if ((devpriv->dio_config & DMM32AT_DIRA) == 0) {
- diobits = (s->state & 0x000000ff);
- outb(diobits, dev->iobase + DMM32AT_DIOA);
- }
+ val = inb(dev->iobase + DMM32AT_DIOA);
+ val |= inb(dev->iobase + DMM32AT_DIOB) << 8;
+ val |= inb(dev->iobase + DMM32AT_DIOC) << 16;
+ s->state = val;
- /* now read the state back in */
- s->state = inb(dev->iobase + DMM32AT_DIOC);
- s->state <<= 8;
- s->state |= inb(dev->iobase + DMM32AT_DIOB);
- s->state <<= 8;
- s->state |= inb(dev->iobase + DMM32AT_DIOA);
- data[1] = s->state;
-
- /* on return, data[1] contains the value of the digital
- * input and output lines. */
- /* data[1]=inw(dev->iobase + DMM32AT_DIO); */
- /* or we could just return the software copy of the output values if
- * it was a purely digital output subdevice */
- /* data[1]=s->state; */
+ data[1] = val;
return insn->n;
}
diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
index 38918a1198aa..811c8c59c017 100644
--- a/drivers/staging/comedi/drivers/dt2801.c
+++ b/drivers/staging/comedi/drivers/dt2801.c
@@ -260,7 +260,8 @@ static int dt2801_readdata(struct comedi_device *dev, int *data)
static int dt2801_readdata2(struct comedi_device *dev, int *data)
{
- int lb, hb;
+ int lb = 0;
+ int hb = 0;
int ret;
ret = dt2801_readdata(dev, &lb);
@@ -528,23 +529,23 @@ static int dt2801_ao_insn_write(struct comedi_device *dev,
static int dt2801_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- int which = 0;
-
- if (s == &dev->subdevices[3])
- which = 1;
+ int which = (s == &dev->subdevices[3]) ? 1 : 0;
+ unsigned int val = 0;
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
+ if (comedi_dio_update_state(s, data)) {
dt2801_writecmd(dev, DT_C_WRITE_DIG);
dt2801_writedata(dev, which);
dt2801_writedata(dev, s->state);
}
+
dt2801_writecmd(dev, DT_C_READ_DIG);
dt2801_writedata(dev, which);
- dt2801_readdata(dev, data + 1);
+ dt2801_readdata(dev, &val);
+
+ data[1] = val;
return insn->n;
}
diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
index a41a5716f358..0ca02fa7ba1b 100644
--- a/drivers/staging/comedi/drivers/dt2811.c
+++ b/drivers/staging/comedi/drivers/dt2811.c
@@ -353,11 +353,11 @@ static int dt2811_di_insn_bits(struct comedi_device *dev,
static int dt2811_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
- outb(s->state, dev->iobase + DT2811_DIO);
+ if (comedi_dio_update_state(s, data))
+ outb(s->state, dev->iobase + DT2811_DIO);
data[1] = s->state;
diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c
index f4a8529239b5..bf589936e546 100644
--- a/drivers/staging/comedi/drivers/dt2817.c
+++ b/drivers/staging/comedi/drivers/dt2817.c
@@ -80,36 +80,31 @@ static int dt2817_dio_insn_config(struct comedi_device *dev,
static int dt2817_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- unsigned int changed;
-
- /* It's questionable whether it is more important in
- * a driver like this to be deterministic or fast.
- * We choose fast. */
-
- if (data[0]) {
- changed = s->state;
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
- changed ^= s->state;
- changed &= s->io_bits;
- if (changed & 0x000000ff)
- outb(s->state & 0xff, dev->iobase + DT2817_DATA + 0);
- if (changed & 0x0000ff00)
- outb((s->state >> 8) & 0xff,
- dev->iobase + DT2817_DATA + 1);
- if (changed & 0x00ff0000)
- outb((s->state >> 16) & 0xff,
- dev->iobase + DT2817_DATA + 2);
- if (changed & 0xff000000)
- outb((s->state >> 24) & 0xff,
- dev->iobase + DT2817_DATA + 3);
+ unsigned long iobase = dev->iobase + DT2817_DATA;
+ unsigned int mask;
+ unsigned int val;
+
+ mask = comedi_dio_update_state(s, data);
+ if (mask) {
+ if (mask & 0x000000ff)
+ outb(s->state & 0xff, iobase + 0);
+ if (mask & 0x0000ff00)
+ outb((s->state >> 8) & 0xff, iobase + 1);
+ if (mask & 0x00ff0000)
+ outb((s->state >> 16) & 0xff, iobase + 2);
+ if (mask & 0xff000000)
+ outb((s->state >> 24) & 0xff, iobase + 3);
}
- data[1] = inb(dev->iobase + DT2817_DATA + 0);
- data[1] |= (inb(dev->iobase + DT2817_DATA + 1) << 8);
- data[1] |= (inb(dev->iobase + DT2817_DATA + 2) << 16);
- data[1] |= (inb(dev->iobase + DT2817_DATA + 3) << 24);
+
+ val = inb(iobase + 0);
+ val |= (inb(iobase + 1) << 8);
+ val |= (inb(iobase + 2) << 16);
+ val |= (inb(iobase + 3) << 24);
+
+ data[1] = val;
return insn->n;
}
diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
index da3ee859bdbc..e89126a15e53 100644
--- a/drivers/staging/comedi/drivers/dt282x.c
+++ b/drivers/staging/comedi/drivers/dt282x.c
@@ -967,14 +967,12 @@ static int dt282x_ao_cancel(struct comedi_device *dev,
static int dt282x_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
-
+ if (comedi_dio_update_state(s, data))
outw(s->state, dev->iobase + DT2821_DIODAT);
- }
+
data[1] = inw(dev->iobase + DT2821_DIODAT);
return insn->n;
diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
index 64ef87598b60..fec911fc8d68 100644
--- a/drivers/staging/comedi/drivers/dt3000.c
+++ b/drivers/staging/comedi/drivers/dt3000.c
@@ -665,13 +665,12 @@ static int dt3k_dio_insn_config(struct comedi_device *dev,
static int dt3k_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= data[1] & data[0];
+ if (comedi_dio_update_state(s, data))
dt3k_writesingle(dev, SUBS_DOUT, 0, s->state);
- }
+
data[1] = dt3k_readsingle(dev, SUBS_DIN, 0, 0);
return insn->n;
diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
index b5e6f33dc217..64565d4c902d 100644
--- a/drivers/staging/comedi/drivers/dt9812.c
+++ b/drivers/staging/comedi/drivers/dt9812.c
@@ -580,15 +580,8 @@ static int dt9812_do_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
-
+ if (comedi_dio_update_state(s, data))
dt9812_digital_out(dev, s->state);
- }
data[1] = s->state;
diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c
index fd525f499f2a..f2a9f1c2f3b6 100644
--- a/drivers/staging/comedi/drivers/dyna_pci10xx.c
+++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c
@@ -147,33 +147,23 @@ static int dyna_pci10xx_di_insn_bits(struct comedi_device *dev,
return insn->n;
}
-/* digital output bit interface */
static int dyna_pci10xx_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct dyna_pci10xx_private *devpriv = dev->private;
- /* The insn data is a mask in data[0] and the new data
- * in data[1], each channel cooresponding to a bit.
- * s->state contains the previous write data
- */
mutex_lock(&devpriv->mutex);
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
+ if (comedi_dio_update_state(s, data)) {
smp_mb();
outw_p(s->state, devpriv->BADR3);
udelay(10);
}
- /*
- * On return, data[1] contains the value of the digital
- * input and output lines. We just return the software copy of the
- * output values if it was a purely digital output subdevice.
- */
data[1] = s->state;
mutex_unlock(&devpriv->mutex);
+
return insn->n;
}
diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
index 3889d23292d0..15d87187b590 100644
--- a/drivers/staging/comedi/drivers/icp_multi.c
+++ b/drivers/staging/comedi/drivers/icp_multi.c
@@ -348,18 +348,13 @@ static int icp_multi_insn_bits_di(struct comedi_device *dev,
static int icp_multi_insn_bits_do(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct icp_multi_private *devpriv = dev->private;
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
-
- printk(KERN_DEBUG "Digital outputs = %4x \n", s->state);
-
+ if (comedi_dio_update_state(s, data))
writew(s->state, devpriv->io_addr + ICP_MULTI_DO);
- }
data[1] = readw(devpriv->io_addr + ICP_MULTI_DI);
@@ -548,7 +543,6 @@ static int icp_multi_auto_attach(struct comedi_device *dev,
s->maxdata = 1;
s->len_chanlist = 16;
s->range_table = &range_digital;
- s->io_bits = 0;
s->insn_bits = icp_multi_insn_bits_di;
s = &dev->subdevices[3];
@@ -558,8 +552,6 @@ static int icp_multi_auto_attach(struct comedi_device *dev,
s->maxdata = 1;
s->len_chanlist = 8;
s->range_table = &range_digital;
- s->io_bits = 0xff;
- s->state = 0;
s->insn_bits = icp_multi_insn_bits_do;
s = &dev->subdevices[4];
diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
index 5c3a318b4640..8577778441fa 100644
--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
+++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
@@ -378,13 +378,10 @@ static int ii20k_dio_insn_bits(struct comedi_device *dev,
unsigned int *data)
{
struct ii20k_private *devpriv = dev->private;
- unsigned int mask = data[0] & s->io_bits; /* outputs only */
- unsigned int bits = data[1];
+ unsigned int mask;
+ mask = comedi_dio_update_state(s, data);
if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
-
if (mask & 0x000000ff)
writeb((s->state >> 0) & 0xff,
devpriv->ioaddr + II20K_DIO0_REG);
diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
index 8f4afadab76a..aba7beae8e86 100644
--- a/drivers/staging/comedi/drivers/me4000.c
+++ b/drivers/staging/comedi/drivers/me4000.c
@@ -1313,29 +1313,12 @@ static int me4000_ao_insn_read(struct comedi_device *dev,
return 1;
}
-/*=============================================================================
- Digital I/O section
- ===========================================================================*/
-
static int me4000_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- /*
- * The insn data consists of a mask in data[0] and the new data
- * in data[1]. The mask defines which bits we are concerning about.
- * The new data must be anded with the mask.
- * Each channel corresponds to a bit.
- */
- if (data[0]) {
- /* Check if requested ports are configured for output */
- if ((s->io_bits & data[0]) != data[0])
- return -EIO;
-
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
-
- /* Write out the new digital output lines */
+ if (comedi_dio_update_state(s, data)) {
outl((s->state >> 0) & 0xFF,
dev->iobase + ME4000_DIO_PORT_0_REG);
outl((s->state >> 8) & 0xFF,
@@ -1346,8 +1329,6 @@ static int me4000_dio_insn_bits(struct comedi_device *dev,
dev->iobase + ME4000_DIO_PORT_3_REG);
}
- /* On return, data[1] contains the value of
- the digital input and output lines. */
data[1] = ((inl(dev->iobase + ME4000_DIO_PORT_0_REG) & 0xFF) << 0) |
((inl(dev->iobase + ME4000_DIO_PORT_1_REG) & 0xFF) << 8) |
((inl(dev->iobase + ME4000_DIO_PORT_2_REG) & 0xFF) << 16) |
diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
index a6f6d4a46587..24ec9ef9b1a0 100644
--- a/drivers/staging/comedi/drivers/me_daq.c
+++ b/drivers/staging/comedi/drivers/me_daq.c
@@ -222,15 +222,11 @@ static int me_dio_insn_bits(struct comedi_device *dev,
struct me_private_data *dev_private = dev->private;
void __iomem *mmio_porta = dev_private->me_regbase + ME_DIO_PORT_A;
void __iomem *mmio_portb = dev_private->me_regbase + ME_DIO_PORT_B;
- unsigned int mask = data[0];
- unsigned int bits = data[1];
+ unsigned int mask;
unsigned int val;
- mask &= s->io_bits; /* only update the COMEDI_OUTPUT channels */
+ mask = comedi_dio_update_state(s, data);
if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
-
if (mask & 0x0000ffff)
writew((s->state & 0xffff), mmio_porta);
if (mask & 0xffff0000)
@@ -545,7 +541,6 @@ static int me_auto_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->insn_bits = me_dio_insn_bits;
s->insn_config = me_dio_insn_config;
- s->io_bits = 0;
dev_info(dev->class_dev, "%s: %s attached\n",
dev->driver->driver_name, dev->board_name);
diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
index 9d75ea4e201b..3ca755eca285 100644
--- a/drivers/staging/comedi/drivers/multiq3.c
+++ b/drivers/staging/comedi/drivers/multiq3.c
@@ -163,11 +163,11 @@ static int multiq3_di_insn_bits(struct comedi_device *dev,
static int multiq3_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
- outw(s->state, dev->iobase + MULTIQ3_DIGOUT_PORT);
+ if (comedi_dio_update_state(s, data))
+ outw(s->state, dev->iobase + MULTIQ3_DIGOUT_PORT);
data[1] = s->state;
diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
index c2745f201f2c..44557c9671ac 100644
--- a/drivers/staging/comedi/drivers/ni_6527.c
+++ b/drivers/staging/comedi/drivers/ni_6527.c
@@ -163,29 +163,29 @@ static int ni6527_di_insn_bits(struct comedi_device *dev,
static int ni6527_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct ni6527_private *devpriv = dev->private;
+ unsigned int mask;
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
-
- /* The open relay state on the board cooresponds to 1,
- * but in Comedi, it is represented by 0. */
- if (data[0] & 0x0000ff) {
- writeb((s->state ^ 0xff),
+ mask = comedi_dio_update_state(s, data);
+ if (mask) {
+ /* Outputs are inverted */
+ if (mask & 0x0000ff) {
+ writeb(s->state ^ 0xff,
devpriv->mite->daq_io_addr + Port_Register(3));
}
- if (data[0] & 0x00ff00) {
+ if (mask & 0x00ff00) {
writeb((s->state >> 8) ^ 0xff,
devpriv->mite->daq_io_addr + Port_Register(4));
}
- if (data[0] & 0xff0000) {
+ if (mask & 0xff0000) {
writeb((s->state >> 16) ^ 0xff,
devpriv->mite->daq_io_addr + Port_Register(5));
}
}
+
data[1] = s->state;
return insn->n;
diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
index 3607336dafe2..8a991dcab24a 100644
--- a/drivers/staging/comedi/drivers/ni_660x.c
+++ b/drivers/staging/comedi/drivers/ni_660x.c
@@ -1213,7 +1213,6 @@ static int ni_660x_auto_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->insn_bits = ni_660x_dio_insn_bits;
s->insn_config = ni_660x_dio_insn_config;
- s->io_bits = 0; /* all bits default to input */
/* we use the ioconfig registers to control dio direction, so zero
output enables in stc dio control reg */
ni_660x_write_register(dev, 0, 0, STCDIOControl);
diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
index e2926ce3fb24..e4414cf110e7 100644
--- a/drivers/staging/comedi/drivers/ni_670x.c
+++ b/drivers/staging/comedi/drivers/ni_670x.c
@@ -136,20 +136,15 @@ static int ni_670x_ao_rinsn(struct comedi_device *dev,
static int ni_670x_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct ni_670x_private *devpriv = dev->private;
void __iomem *io_addr = devpriv->mite->daq_io_addr +
DIO_PORT0_DATA_OFFSET;
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
+ if (comedi_dio_update_state(s, data))
writel(s->state, io_addr);
- }
data[1] = readl(io_addr);
diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
index 2512ce8dfcaa..c77d34306119 100644
--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
+++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
@@ -684,13 +684,12 @@ static int a2150_set_chanlist(struct comedi_device *dev,
devpriv->config_bits |= CHANNEL_BITS(0x4 | start_channel);
break;
case 2:
- if (start_channel == 0) {
+ if (start_channel == 0)
devpriv->config_bits |= CHANNEL_BITS(0x2);
- } else if (start_channel == 2) {
+ else if (start_channel == 2)
devpriv->config_bits |= CHANNEL_BITS(0x3);
- } else {
+ else
return -1;
- }
break;
case 4:
devpriv->config_bits |= CHANNEL_BITS(0x1);
diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
index b9122fd835e1..4e4b227e091f 100644
--- a/drivers/staging/comedi/drivers/ni_at_ao.c
+++ b/drivers/staging/comedi/drivers/ni_at_ao.c
@@ -233,13 +233,11 @@ static int atao_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
static int atao_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
+ if (comedi_dio_update_state(s, data))
outw(s->state, dev->iobase + ATAO_DOUT);
- }
data[1] = inw(dev->iobase + ATAO_DIN);
diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
index bb3491f5ad21..a9f7d40d6db2 100644
--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
+++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
@@ -558,13 +558,12 @@ static int atmio16d_ao_insn_write(struct comedi_device *dev,
static int atmio16d_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] | data[1]);
+ if (comedi_dio_update_state(s, data))
outw(s->state, dev->iobase + MIO_16_DIG_OUT_REG);
- }
+
data[1] = inw(dev->iobase + MIO_16_DIG_IN_REG);
return insn->n;
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index 404f83de276d..e4cdca349157 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -72,18 +72,22 @@ Manuals: Register level: http://www.ni.com/pdf/manuals/340698.pdf
static int daq700_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
+ unsigned int mask;
+ unsigned int val;
- if (data[0] & 0xff)
+ mask = comedi_dio_update_state(s, data);
+ if (mask) {
+ if (mask & 0xff)
outb(s->state & 0xff, dev->iobase + DIO_W);
}
- data[1] = s->state & 0xff;
- data[1] |= inb(dev->iobase + DIO_R) << 8;
+ val = s->state & 0xff;
+ val |= inb(dev->iobase + DIO_R) << 8;
+
+ data[1] = val;
return insn->n;
}
@@ -212,7 +216,6 @@ static int daq700_auto_attach(struct comedi_device *dev,
s->maxdata = 1;
s->insn_bits = daq700_dio_insn_bits;
s->insn_config = daq700_dio_insn_config;
- s->state = 0;
s->io_bits = 0x00ff;
/* DAQCard-700 ai */
diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
index 1add114dc0bc..e91570dd6b0d 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.c
+++ b/drivers/staging/comedi/drivers/ni_labpc.c
@@ -73,7 +73,6 @@
#include "ni_labpc_isadma.h"
#define LABPC_SIZE 0x20 /* size of ISA io region */
-#define LABPC_TIMER_BASE 500 /* 2 MHz master clock */
#define LABPC_ADC_TIMEOUT 1000
enum scan_mode {
@@ -201,12 +200,6 @@ static int labpc_counter_set_mode(struct comedi_device *dev,
return i8254_set_mode(base_address, 0, counter_number, mode);
}
-static bool labpc_range_is_unipolar(struct comedi_subdevice *s,
- unsigned int range)
-{
- return s->range_table->range[range].min >= 0;
-}
-
static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
{
struct labpc_private *devpriv = dev->private;
@@ -272,7 +265,7 @@ static void labpc_setup_cmd6_reg(struct comedi_device *dev,
devpriv->cmd6 &= ~CMD6_NRSE;
/* bipolar or unipolar range? */
- if (labpc_range_is_unipolar(s, range))
+ if (comedi_range_is_unipolar(s, range))
devpriv->cmd6 |= CMD6_ADCUNI;
else
devpriv->cmd6 &= ~CMD6_ADCUNI;
@@ -465,13 +458,13 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd,
* clock speed on convert and scan counters)
*/
devpriv->divisor_b0 = (scan_period - 1) /
- (LABPC_TIMER_BASE * max_counter_value) + 1;
+ (I8254_OSC_BASE_2MHZ * max_counter_value) + 1;
if (devpriv->divisor_b0 < min_counter_value)
devpriv->divisor_b0 = min_counter_value;
if (devpriv->divisor_b0 > max_counter_value)
devpriv->divisor_b0 = max_counter_value;
- base_period = LABPC_TIMER_BASE * devpriv->divisor_b0;
+ base_period = I8254_OSC_BASE_2MHZ * devpriv->divisor_b0;
/* set a0 for conversion frequency and b1 for scan frequency */
switch (cmd->flags & TRIG_ROUND_MASK) {
@@ -516,22 +509,20 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd,
* calculate cascaded counter values
* that give desired scan timing
*/
- i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE,
- &(devpriv->divisor_b1),
- &(devpriv->divisor_b0),
- &scan_period,
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ,
+ &devpriv->divisor_b1,
+ &devpriv->divisor_b0,
+ &scan_period, cmd->flags);
labpc_set_ai_scan_period(cmd, mode, scan_period);
} else if (convert_period) {
/*
* calculate cascaded counter values
* that give desired conversion timing
*/
- i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE,
- &(devpriv->divisor_a0),
- &(devpriv->divisor_b0),
- &convert_period,
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ,
+ &devpriv->divisor_a0,
+ &devpriv->divisor_b0,
+ &convert_period, cmd->flags);
labpc_set_ai_convert_period(cmd, mode, convert_period);
}
}
@@ -1046,7 +1037,7 @@ static int labpc_ao_insn_write(struct comedi_device *dev,
/* set range */
if (board->is_labpc1200) {
range = CR_RANGE(insn->chanspec);
- if (labpc_range_is_unipolar(s, range))
+ if (comedi_range_is_unipolar(s, range))
devpriv->cmd6 |= CMD6_DACUNI(channel);
else
devpriv->cmd6 &= ~CMD6_DACUNI(channel);
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index 4e02770e834b..b9df2eeae6fb 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -3547,28 +3547,22 @@ static int ni_dio_insn_config(struct comedi_device *dev,
static int ni_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct ni_private *devpriv = dev->private;
-#ifdef DEBUG_DIO
- printk("ni_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0], data[1]);
-#endif
-
- if (data[0]) {
- /* Perform check to make sure we're not using the
- serial part of the dio */
- if ((data[0] & (DIO_SDIN | DIO_SDOUT))
- && devpriv->serial_interval_ns)
- return -EBUSY;
+ /* Make sure we're not using the serial part of the dio */
+ if ((data[0] & (DIO_SDIN | DIO_SDOUT)) && devpriv->serial_interval_ns)
+ return -EBUSY;
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
+ if (comedi_dio_update_state(s, data)) {
devpriv->dio_output &= ~DIO_Parallel_Data_Mask;
devpriv->dio_output |= DIO_Parallel_Data_Out(s->state);
devpriv->stc_writew(dev, devpriv->dio_output,
DIO_Output_Register);
}
+
data[1] = devpriv->stc_readw(dev, DIO_Parallel_Input_Register);
return insn->n;
@@ -3598,16 +3592,9 @@ static int ni_m_series_dio_insn_bits(struct comedi_device *dev,
{
struct ni_private *devpriv __maybe_unused = dev->private;
-#ifdef DEBUG_DIO
- printk("ni_m_series_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0],
- data[1]);
-#endif
-
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
+ if (comedi_dio_update_state(s, data))
ni_writel(s->state, M_Offset_Static_Digital_Output);
- }
+
data[1] = ni_readl(M_Offset_Static_Digital_Input);
return insn->n;
@@ -5355,20 +5342,20 @@ static int ni_config_filter(struct comedi_device *dev, unsigned pfi_channel,
static int ni_pfi_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
const struct ni_board_struct *board = comedi_board(dev);
struct ni_private *devpriv __maybe_unused = dev->private;
- if ((board->reg_type & ni_reg_m_series_mask) == 0) {
+ if (!(board->reg_type & ni_reg_m_series_mask))
return -ENOTSUPP;
- }
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
+
+ if (comedi_dio_update_state(s, data))
ni_writew(s->state, M_Offset_PFI_DO);
- }
+
data[1] = ni_readw(M_Offset_PFI_DI);
+
return insn->n;
}
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
index fad81bc97b6e..b6283a8a7cd4 100644
--- a/drivers/staging/comedi/drivers/ni_pcidio.c
+++ b/drivers/staging/comedi/drivers/ni_pcidio.c
@@ -657,15 +657,14 @@ static int ni_pcidio_insn_config(struct comedi_device *dev,
static int ni_pcidio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct nidio96_private *devpriv = dev->private;
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
+ if (comedi_dio_update_state(s, data))
writel(s->state, devpriv->mite->daq_io_addr + Port_IO(0));
- }
+
data[1] = readl(devpriv->mite->daq_io_addr + Port_IO(0));
return insn->n;
diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
index e859f85a8e17..89982fb52e50 100644
--- a/drivers/staging/comedi/drivers/pcl711.c
+++ b/drivers/staging/comedi/drivers/pcl711.c
@@ -1,258 +1,295 @@
/*
- comedi/drivers/pcl711.c
- hardware driver for PC-LabCard PCL-711 and AdSys ACL-8112
- and compatibles
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 1998 David A. Schleef <ds@schleef.org>
- Janne Jalkanen <jalkanen@cs.hut.fi>
- Eric Bunn <ebu@cs.hut.fi>
-
- 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.
+ * pcl711.c
+ * Comedi driver for PC-LabCard PCL-711 and AdSys ACL-8112 and compatibles
+ * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
+ * Janne Jalkanen <jalkanen@cs.hut.fi>
+ * Eric Bunn <ebu@cs.hut.fi>
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
+ *
+ * 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.
*/
-/*
-Driver: pcl711
-Description: Advantech PCL-711 and 711b, ADLink ACL-8112
-Author: ds, Janne Jalkanen <jalkanen@cs.hut.fi>, Eric Bunn <ebu@cs.hut.fi>
-Status: mostly complete
-Devices: [Advantech] PCL-711 (pcl711), PCL-711B (pcl711b),
- [AdLink] ACL-8112HG (acl8112hg), ACL-8112DG (acl8112dg)
-
-Since these boards do not have DMA or FIFOs, only immediate mode is
-supported.
-
-*/
/*
- Dave Andruczyk <dave@tech.buffalostate.edu> also wrote a
- driver for the PCL-711. I used a few ideas from his driver
- here. His driver also has more comments, if you are
- interested in understanding how this driver works.
- http://tech.buffalostate.edu/~dave/driver/
-
- The ACL-8112 driver was hacked from the sources of the PCL-711
- driver (the 744 chip used on the 8112 is almost the same as
- the 711b chip, but it has more I/O channels) by
- Janne Jalkanen (jalkanen@cs.hut.fi) and
- Erik Bunn (ebu@cs.hut.fi). Remerged with the PCL-711 driver
- by ds.
-
- [acl-8112]
- This driver supports both TRIGNOW and TRIGCLK,
- but does not yet support DMA transfers. It also supports
- both high (HG) and low (DG) versions of the card, though
- the HG version has been untested.
-
+ * Driver: pcl711
+ * Description: Advantech PCL-711 and 711b, ADLink ACL-8112
+ * Devices: (Advantech) PCL-711 [pcl711]
+ * (Advantech) PCL-711B [pcl711b]
+ * (AdLink) ACL-8112HG [acl8112hg]
+ * (AdLink) ACL-8112DG [acl8112dg]
+ * Author: David A. Schleef <ds@schleef.org>
+ * Janne Jalkanen <jalkanen@cs.hut.fi>
+ * Eric Bunn <ebu@cs.hut.fi>
+ * Updated:
+ * Status: mostly complete
+ *
+ * Configuration Options:
+ * [0] - I/O port base
+ * [1] - IRQ, optional
*/
#include <linux/module.h>
+#include <linux/delay.h>
#include <linux/interrupt.h>
-#include "../comedidev.h"
-#include <linux/delay.h>
+#include "../comedidev.h"
#include "comedi_fc.h"
#include "8253.h"
-#define PCL711_SIZE 16
-
-#define PCL711_CTR0 0
-#define PCL711_CTR1 1
-#define PCL711_CTR2 2
-#define PCL711_CTRCTL 3
-#define PCL711_AD_LO 4
-#define PCL711_DA0_LO 4
-#define PCL711_AD_HI 5
-#define PCL711_DA0_HI 5
-#define PCL711_DI_LO 6
-#define PCL711_DA1_LO 6
-#define PCL711_DI_HI 7
-#define PCL711_DA1_HI 7
-#define PCL711_CLRINTR 8
-#define PCL711_GAIN 9
-#define PCL711_MUX 10
-#define PCL711_MODE 11
-#define PCL711_SOFTTRIG 12
-#define PCL711_DO_LO 13
-#define PCL711_DO_HI 14
-
-static const struct comedi_lrange range_pcl711b_ai = { 5, {
- BIP_RANGE(5),
- BIP_RANGE(2.5),
- BIP_RANGE(1.25),
- BIP_RANGE(0.625),
- BIP_RANGE(0.3125)
- }
+/*
+ * I/O port register map
+ */
+#define PCL711_TIMER_BASE 0x00
+#define PCL711_AI_LSB_REG 0x04
+#define PCL711_AI_MSB_REG 0x05
+#define PCL711_AI_MSB_DRDY (1 << 4)
+#define PCL711_AO_LSB_REG(x) (0x04 + ((x) * 2))
+#define PCL711_AO_MSB_REG(x) (0x05 + ((x) * 2))
+#define PCL711_DI_LSB_REG 0x06
+#define PCL711_DI_MSB_REG 0x07
+#define PCL711_INT_STAT_REG 0x08
+#define PCL711_INT_STAT_CLR (0 << 0) /* any value will work */
+#define PCL711_AI_GAIN_REG 0x09
+#define PCL711_AI_GAIN(x) (((x) & 0xf) << 0)
+#define PCL711_MUX_REG 0x0a
+#define PCL711_MUX_CHAN(x) (((x) & 0xf) << 0)
+#define PCL711_MUX_CS0 (1 << 4)
+#define PCL711_MUX_CS1 (1 << 5)
+#define PCL711_MUX_DIFF (PCL711_MUX_CS0 | PCL711_MUX_CS1)
+#define PCL711_MODE_REG 0x0b
+#define PCL711_MODE_DEFAULT (0 << 0)
+#define PCL711_MODE_SOFTTRIG (1 << 0)
+#define PCL711_MODE_EXT (2 << 0)
+#define PCL711_MODE_EXT_IRQ (3 << 0)
+#define PCL711_MODE_PACER (4 << 0)
+#define PCL711_MODE_PACER_IRQ (6 << 0)
+#define PCL711_MODE_IRQ(x) (((x) & 0x7) << 4)
+#define PCL711_SOFTTRIG_REG 0x0c
+#define PCL711_SOFTTRIG (0 << 0) /* any value will work */
+#define PCL711_DO_LSB_REG 0x0d
+#define PCL711_DO_MSB_REG 0x0e
+
+static const struct comedi_lrange range_pcl711b_ai = {
+ 5, {
+ BIP_RANGE(5),
+ BIP_RANGE(2.5),
+ BIP_RANGE(1.25),
+ BIP_RANGE(0.625),
+ BIP_RANGE(0.3125)
+ }
};
-static const struct comedi_lrange range_acl8112hg_ai = { 12, {
- BIP_RANGE(5),
- BIP_RANGE(0.5),
- BIP_RANGE(0.05),
- BIP_RANGE(0.005),
- UNI_RANGE(10),
- UNI_RANGE(1),
- UNI_RANGE(0.1),
- UNI_RANGE(0.01),
- BIP_RANGE(10),
- BIP_RANGE(1),
- BIP_RANGE(0.1),
- BIP_RANGE(0.01)
- }
+static const struct comedi_lrange range_acl8112hg_ai = {
+ 12, {
+ BIP_RANGE(5),
+ BIP_RANGE(0.5),
+ BIP_RANGE(0.05),
+ BIP_RANGE(0.005),
+ UNI_RANGE(10),
+ UNI_RANGE(1),
+ UNI_RANGE(0.1),
+ UNI_RANGE(0.01),
+ BIP_RANGE(10),
+ BIP_RANGE(1),
+ BIP_RANGE(0.1),
+ BIP_RANGE(0.01)
+ }
};
-static const struct comedi_lrange range_acl8112dg_ai = { 9, {
- BIP_RANGE(5),
- BIP_RANGE(2.5),
- BIP_RANGE(1.25),
- BIP_RANGE(0.625),
- UNI_RANGE(10),
- UNI_RANGE(5),
- UNI_RANGE(2.5),
- UNI_RANGE(1.25),
- BIP_RANGE(10)
- }
+static const struct comedi_lrange range_acl8112dg_ai = {
+ 9, {
+ BIP_RANGE(5),
+ BIP_RANGE(2.5),
+ BIP_RANGE(1.25),
+ BIP_RANGE(0.625),
+ UNI_RANGE(10),
+ UNI_RANGE(5),
+ UNI_RANGE(2.5),
+ UNI_RANGE(1.25),
+ BIP_RANGE(10)
+ }
};
-/*
- * flags
- */
-
-#define PCL711_TIMEOUT 100
-#define PCL711_DRDY 0x10
-
-static const int i8253_osc_base = 500; /* 2 Mhz */
-
struct pcl711_board {
-
const char *name;
- int is_pcl711b;
- int is_8112;
- int is_dg;
- int n_ranges;
int n_aichan;
int n_aochan;
int maxirq;
const struct comedi_lrange *ai_range_type;
};
-struct pcl711_private {
+static const struct pcl711_board boardtypes[] = {
+ {
+ .name = "pcl711",
+ .n_aichan = 8,
+ .n_aochan = 1,
+ .ai_range_type = &range_bipolar5,
+ }, {
+ .name = "pcl711b",
+ .n_aichan = 8,
+ .n_aochan = 1,
+ .maxirq = 7,
+ .ai_range_type = &range_pcl711b_ai,
+ }, {
+ .name = "acl8112hg",
+ .n_aichan = 16,
+ .n_aochan = 2,
+ .maxirq = 15,
+ .ai_range_type = &range_acl8112hg_ai,
+ }, {
+ .name = "acl8112dg",
+ .n_aichan = 16,
+ .n_aochan = 2,
+ .maxirq = 15,
+ .ai_range_type = &range_acl8112dg_ai,
+ },
+};
- int board;
- int adchan;
- int ntrig;
- int aip[8];
- int mode;
+struct pcl711_private {
+ unsigned int ntrig;
unsigned int ao_readback[2];
unsigned int divisor1;
unsigned int divisor2;
};
+static void pcl711_ai_set_mode(struct comedi_device *dev, unsigned int mode)
+{
+ /*
+ * The pcl711b board uses bits in the mode register to select the
+ * interrupt. The other boards supported by this driver all use
+ * jumpers on the board.
+ *
+ * Enables the interrupt when needed on the pcl711b board. These
+ * bits do nothing on the other boards.
+ */
+ if (mode == PCL711_MODE_EXT_IRQ || mode == PCL711_MODE_PACER_IRQ)
+ mode |= PCL711_MODE_IRQ(dev->irq);
+
+ outb(mode, dev->iobase + PCL711_MODE_REG);
+}
+
+static unsigned int pcl711_ai_get_sample(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ unsigned int val;
+
+ val = inb(dev->iobase + PCL711_AI_MSB_REG) << 8;
+ val |= inb(dev->iobase + PCL711_AI_LSB_REG);
+
+ return val & s->maxdata;
+}
+
+static int pcl711_ai_cancel(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ outb(PCL711_INT_STAT_CLR, dev->iobase + PCL711_INT_STAT_REG);
+ pcl711_ai_set_mode(dev, PCL711_MODE_SOFTTRIG);
+ return 0;
+}
+
static irqreturn_t pcl711_interrupt(int irq, void *d)
{
- int lo, hi;
- int data;
struct comedi_device *dev = d;
- const struct pcl711_board *board = comedi_board(dev);
struct pcl711_private *devpriv = dev->private;
- struct comedi_subdevice *s = &dev->subdevices[0];
+ struct comedi_subdevice *s = dev->read_subdev;
+ unsigned int data;
if (!dev->attached) {
comedi_error(dev, "spurious interrupt");
return IRQ_HANDLED;
}
- hi = inb(dev->iobase + PCL711_AD_HI);
- lo = inb(dev->iobase + PCL711_AD_LO);
- outb(0, dev->iobase + PCL711_CLRINTR);
-
- data = (hi << 8) | lo;
+ data = pcl711_ai_get_sample(dev, s);
- /* FIXME! Nothing else sets ntrig! */
- if (!(--devpriv->ntrig)) {
- if (board->is_8112)
- outb(1, dev->iobase + PCL711_MODE);
- else
- outb(0, dev->iobase + PCL711_MODE);
+ outb(PCL711_INT_STAT_CLR, dev->iobase + PCL711_INT_STAT_REG);
- s->async->events |= COMEDI_CB_EOA;
+ if (comedi_buf_put(s->async, (short)data) == 0) {
+ s->async->events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
+ } else {
+ s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
+ if (s->async->cmd.stop_src == TRIG_COUNT &&
+ !(--devpriv->ntrig)) {
+ pcl711_ai_set_mode(dev, PCL711_MODE_SOFTTRIG);
+ s->async->events |= COMEDI_CB_EOA;
+ }
}
comedi_event(dev, s);
return IRQ_HANDLED;
}
-static void pcl711_set_changain(struct comedi_device *dev, int chan)
+static void pcl711_set_changain(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned int chanspec)
{
- const struct pcl711_board *board = comedi_board(dev);
- int chan_register;
-
- outb(CR_RANGE(chan), dev->iobase + PCL711_GAIN);
-
- chan_register = CR_CHAN(chan);
-
- if (board->is_8112) {
+ unsigned int chan = CR_CHAN(chanspec);
+ unsigned int range = CR_RANGE(chanspec);
+ unsigned int aref = CR_AREF(chanspec);
+ unsigned int mux = 0;
+
+ outb(PCL711_AI_GAIN(range), dev->iobase + PCL711_AI_GAIN_REG);
+
+ if (s->n_chan > 8) {
+ /* Select the correct MPC508A chip */
+ if (aref == AREF_DIFF) {
+ chan &= 0x7;
+ mux |= PCL711_MUX_DIFF;
+ } else {
+ if (chan < 8)
+ mux |= PCL711_MUX_CS0;
+ else
+ mux |= PCL711_MUX_CS1;
+ }
+ }
+ outb(mux | PCL711_MUX_CHAN(chan), dev->iobase + PCL711_MUX_REG);
+}
- /*
- * Set the correct channel. The two channel banks are switched
- * using the mask value.
- * NB: To use differential channels, you should use
- * mask = 0x30, but I haven't written the support for this
- * yet. /JJ
- */
+static int pcl711_ai_wait_for_eoc(struct comedi_device *dev,
+ unsigned int timeout)
+{
+ unsigned int msb;
- if (chan_register >= 8)
- chan_register = 0x20 | (chan_register & 0x7);
- else
- chan_register |= 0x10;
- } else {
- outb(chan_register, dev->iobase + PCL711_MUX);
+ while (timeout--) {
+ msb = inb(dev->iobase + PCL711_AI_MSB_REG);
+ if ((msb & PCL711_AI_MSB_DRDY) == 0)
+ return 0;
+ udelay(1);
}
+ return -ETIME;
}
-static int pcl711_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int pcl711_ai_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- const struct pcl711_board *board = comedi_board(dev);
- int i, n;
- int hi, lo;
-
- pcl711_set_changain(dev, insn->chanspec);
-
- for (n = 0; n < insn->n; n++) {
- /*
- * Write the correct mode (software polling) and start polling
- * by writing to the trigger register
- */
- outb(1, dev->iobase + PCL711_MODE);
-
- if (!board->is_8112)
- outb(0, dev->iobase + PCL711_SOFTTRIG);
-
- i = PCL711_TIMEOUT;
- while (--i) {
- hi = inb(dev->iobase + PCL711_AD_HI);
- if (!(hi & PCL711_DRDY))
- goto ok;
- udelay(1);
- }
- printk(KERN_ERR "comedi%d: pcl711: A/D timeout\n", dev->minor);
- return -ETIME;
+ int ret;
+ int i;
+
+ pcl711_set_changain(dev, s, insn->chanspec);
-ok:
- lo = inb(dev->iobase + PCL711_AD_LO);
+ pcl711_ai_set_mode(dev, PCL711_MODE_SOFTTRIG);
- data[n] = ((hi & 0xf) << 8) | lo;
+ for (i = 0; i < insn->n; i++) {
+ outb(PCL711_SOFTTRIG, dev->iobase + PCL711_SOFTTRIG_REG);
+
+ ret = pcl711_ai_wait_for_eoc(dev, 100);
+ if (ret)
+ return ret;
+
+ data[i] = pcl711_ai_get_sample(dev, s);
}
- return n;
+ return insn->n;
}
static int pcl711_ai_cmdtest(struct comedi_device *dev,
@@ -292,7 +329,6 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev,
err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
} else {
#define MAX_SPEED 1000
-#define TIMER_BASE 100
err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
MAX_SPEED);
}
@@ -313,11 +349,11 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev,
if (cmd->scan_begin_src == TRIG_TIMER) {
tmp = cmd->scan_begin_arg;
- i8253_cascade_ns_to_timer_2div(TIMER_BASE,
- &devpriv->divisor1,
- &devpriv->divisor2,
- &cmd->scan_begin_arg,
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ,
+ &devpriv->divisor1,
+ &devpriv->divisor2,
+ &cmd->scan_begin_arg,
+ cmd->flags);
if (tmp != cmd->scan_begin_arg)
err++;
}
@@ -331,110 +367,106 @@ static int pcl711_ai_cmdtest(struct comedi_device *dev,
static int pcl711_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
struct pcl711_private *devpriv = dev->private;
- int timer1, timer2;
struct comedi_cmd *cmd = &s->async->cmd;
- pcl711_set_changain(dev, cmd->chanlist[0]);
+ pcl711_set_changain(dev, s, cmd->chanlist[0]);
+
+ if (cmd->stop_src == TRIG_COUNT) {
+ if (cmd->stop_arg == 0) {
+ /* an empty acquisition */
+ s->async->events |= COMEDI_CB_EOA;
+ comedi_event(dev, s);
+ return 0;
+ }
+ devpriv->ntrig = cmd->stop_arg;
+ }
if (cmd->scan_begin_src == TRIG_TIMER) {
- /*
- * Set timers
- * timer chip is an 8253, with timers 1 and 2
- * cascaded
- * 0x74 = Select Counter 1 | LSB/MSB | Mode=2 | Binary
- * Mode 2 = Rate generator
- *
- * 0xb4 = Select Counter 2 | LSB/MSB | Mode=2 | Binary
- */
-
- timer1 = timer2 = 0;
- i8253_cascade_ns_to_timer(i8253_osc_base, &timer1, &timer2,
- &cmd->scan_begin_arg,
- TRIG_ROUND_NEAREST);
-
- outb(0x74, dev->iobase + PCL711_CTRCTL);
- outb(timer1 & 0xff, dev->iobase + PCL711_CTR1);
- outb((timer1 >> 8) & 0xff, dev->iobase + PCL711_CTR1);
- outb(0xb4, dev->iobase + PCL711_CTRCTL);
- outb(timer2 & 0xff, dev->iobase + PCL711_CTR2);
- outb((timer2 >> 8) & 0xff, dev->iobase + PCL711_CTR2);
-
- /* clear pending interrupts (just in case) */
- outb(0, dev->iobase + PCL711_CLRINTR);
-
- /*
- * Set mode to IRQ transfer
- */
- outb(devpriv->mode | 6, dev->iobase + PCL711_MODE);
+ i8254_load(dev->iobase + PCL711_TIMER_BASE, 0,
+ 1, devpriv->divisor1, I8254_MODE2 | I8254_BINARY);
+ i8254_load(dev->iobase + PCL711_TIMER_BASE, 0,
+ 2, devpriv->divisor2, I8254_MODE2 | I8254_BINARY);
+
+ outb(PCL711_INT_STAT_CLR, dev->iobase + PCL711_INT_STAT_REG);
+
+ pcl711_ai_set_mode(dev, PCL711_MODE_PACER_IRQ);
} else {
- /* external trigger */
- outb(devpriv->mode | 3, dev->iobase + PCL711_MODE);
+ pcl711_ai_set_mode(dev, PCL711_MODE_EXT_IRQ);
}
return 0;
}
-/*
- analog output
-*/
-static int pcl711_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static void pcl711_ao_write(struct comedi_device *dev,
+ unsigned int chan, unsigned int val)
{
- struct pcl711_private *devpriv = dev->private;
- int n;
- int chan = CR_CHAN(insn->chanspec);
+ outb(val & 0xff, dev->iobase + PCL711_AO_LSB_REG(chan));
+ outb((val >> 8) & 0xff, dev->iobase + PCL711_AO_MSB_REG(chan));
+}
- for (n = 0; n < insn->n; n++) {
- outb((data[n] & 0xff),
- dev->iobase + (chan ? PCL711_DA1_LO : PCL711_DA0_LO));
- outb((data[n] >> 8),
- dev->iobase + (chan ? PCL711_DA1_HI : PCL711_DA0_HI));
+static int pcl711_ao_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct pcl711_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int val = devpriv->ao_readback[chan];
+ int i;
- devpriv->ao_readback[chan] = data[n];
+ for (i = 0; i < insn->n; i++) {
+ val = data[i];
+ pcl711_ao_write(dev, chan, val);
}
+ devpriv->ao_readback[chan] = val;
- return n;
+ return insn->n;
}
static int pcl711_ao_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct pcl711_private *devpriv = dev->private;
- int n;
- int chan = CR_CHAN(insn->chanspec);
-
- for (n = 0; n < insn->n; n++)
- data[n] = devpriv->ao_readback[chan];
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ int i;
- return n;
+ for (i = 0; i < insn->n; i++)
+ data[i] = devpriv->ao_readback[chan];
+ return insn->n;
}
-/* Digital port read - Untested on 8112 */
static int pcl711_di_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- data[1] = inb(dev->iobase + PCL711_DI_LO) |
- (inb(dev->iobase + PCL711_DI_HI) << 8);
+ unsigned int val;
+
+ val = inb(dev->iobase + PCL711_DI_LSB_REG);
+ val |= (inb(dev->iobase + PCL711_DI_MSB_REG) << 8);
+
+ data[1] = val;
return insn->n;
}
-/* Digital port write - Untested on 8112 */
static int pcl711_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
+ unsigned int mask;
+
+ mask = comedi_dio_update_state(s, data);
+ if (mask) {
+ if (mask & 0x00ff)
+ outb(s->state & 0xff, dev->iobase + PCL711_DO_LSB_REG);
+ if (mask & 0xff00)
+ outb((s->state >> 8), dev->iobase + PCL711_DO_MSB_REG);
}
- if (data[0] & 0x00ff)
- outb(s->state & 0xff, dev->iobase + PCL711_DO_LO);
- if (data[0] & 0xff00)
- outb((s->state >> 8), dev->iobase + PCL711_DO_HI);
data[1] = s->state;
@@ -445,112 +477,82 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
const struct pcl711_board *board = comedi_board(dev);
struct pcl711_private *devpriv;
- int ret;
- unsigned int irq;
struct comedi_subdevice *s;
+ int ret;
+
+ devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
+ if (!devpriv)
+ return -ENOMEM;
- ret = comedi_request_region(dev, it->options[0], PCL711_SIZE);
+ ret = comedi_request_region(dev, it->options[0], 0x10);
if (ret)
return ret;
- /* grab our IRQ */
- irq = it->options[1];
- if (irq > board->maxirq) {
- printk(KERN_ERR "irq out of range\n");
- return -EINVAL;
- }
- if (irq) {
- if (request_irq(irq, pcl711_interrupt, 0, dev->board_name,
- dev)) {
- printk(KERN_ERR "unable to allocate irq %u\n", irq);
- return -EINVAL;
- } else {
- printk(KERN_INFO "( irq = %u )\n", irq);
- }
+ if (it->options[1] && it->options[1] <= board->maxirq) {
+ ret = request_irq(it->options[1], pcl711_interrupt, 0,
+ dev->board_name, dev);
+ if (ret == 0)
+ dev->irq = it->options[1];
}
- dev->irq = irq;
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
return ret;
- devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
- if (!devpriv)
- return -ENOMEM;
-
+ /* Analog Input subdevice */
s = &dev->subdevices[0];
- /* AI subdevice */
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND;
- s->n_chan = board->n_aichan;
- s->maxdata = 0xfff;
- s->len_chanlist = 1;
- s->range_table = board->ai_range_type;
- s->insn_read = pcl711_ai_insn;
- if (irq) {
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND;
+ if (board->n_aichan > 8)
+ s->subdev_flags |= SDF_DIFF;
+ s->n_chan = board->n_aichan;
+ s->maxdata = 0xfff;
+ s->range_table = board->ai_range_type;
+ s->insn_read = pcl711_ai_insn_read;
+ if (dev->irq) {
dev->read_subdev = s;
- s->subdev_flags |= SDF_CMD_READ;
- s->do_cmdtest = pcl711_ai_cmdtest;
- s->do_cmd = pcl711_ai_cmd;
+ s->subdev_flags |= SDF_CMD_READ;
+ s->len_chanlist = 1;
+ s->do_cmdtest = pcl711_ai_cmdtest;
+ s->do_cmd = pcl711_ai_cmd;
+ s->cancel = pcl711_ai_cancel;
}
+ /* Analog Output subdevice */
s = &dev->subdevices[1];
- /* AO subdevice */
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE;
- s->n_chan = board->n_aochan;
- s->maxdata = 0xfff;
- s->len_chanlist = 1;
- s->range_table = &range_bipolar5;
- s->insn_write = pcl711_ao_insn;
- s->insn_read = pcl711_ao_insn_read;
-
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = board->n_aochan;
+ s->maxdata = 0xfff;
+ s->range_table = &range_bipolar5;
+ s->insn_write = pcl711_ao_insn_write;
+ s->insn_read = pcl711_ao_insn_read;
+
+ /* Digital Input subdevice */
s = &dev->subdevices[2];
- /* 16-bit digital input */
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
- s->n_chan = 16;
- s->maxdata = 1;
- s->len_chanlist = 16;
- s->range_table = &range_digital;
- s->insn_bits = pcl711_di_insn_bits;
-
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = pcl711_di_insn_bits;
+
+ /* Digital Output subdevice */
s = &dev->subdevices[3];
- /* 16-bit digital out */
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE;
- s->n_chan = 16;
- s->maxdata = 1;
- s->len_chanlist = 16;
- s->range_table = &range_digital;
- s->state = 0;
- s->insn_bits = pcl711_do_insn_bits;
-
- /*
- this is the "base value" for the mode register, which is
- used for the irq on the PCL711
- */
- if (board->is_pcl711b)
- devpriv->mode = (dev->irq << 4);
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = pcl711_do_insn_bits;
/* clear DAC */
- outb(0, dev->iobase + PCL711_DA0_LO);
- outb(0, dev->iobase + PCL711_DA0_HI);
- outb(0, dev->iobase + PCL711_DA1_LO);
- outb(0, dev->iobase + PCL711_DA1_HI);
-
- printk(KERN_INFO "\n");
+ pcl711_ao_write(dev, 0, 0x0);
+ pcl711_ao_write(dev, 1, 0x0);
return 0;
}
-static const struct pcl711_board boardtypes[] = {
- { "pcl711", 0, 0, 0, 5, 8, 1, 0, &range_bipolar5 },
- { "pcl711b", 1, 0, 0, 5, 8, 1, 7, &range_pcl711b_ai },
- { "acl8112hg", 0, 1, 0, 12, 16, 2, 15, &range_acl8112hg_ai },
- { "acl8112dg", 0, 1, 1, 9, 16, 2, 15, &range_acl8112dg_ai },
-};
-
static struct comedi_driver pcl711_driver = {
.driver_name = "pcl711",
.module = THIS_MODULE,
@@ -563,5 +565,5 @@ static struct comedi_driver pcl711_driver = {
module_comedi_driver(pcl711_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for PCL-711 compatible boards");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
index a4d0bcc31e52..cf9568ee46e4 100644
--- a/drivers/staging/comedi/drivers/pcl726.c
+++ b/drivers/staging/comedi/drivers/pcl726.c
@@ -1,230 +1,356 @@
/*
- comedi/drivers/pcl726.c
-
- hardware driver for Advantech cards:
- card: PCL-726, PCL-727, PCL-728
- driver: pcl726, pcl727, pcl728
- and for ADLink cards:
- card: ACL-6126, ACL-6128
- driver: acl6126, acl6128
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 1998 David A. Schleef <ds@schleef.org>
-
- 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.
-*/
-/*
-Driver: pcl726
-Description: Advantech PCL-726 & compatibles
-Author: ds
-Status: untested
-Devices: [Advantech] PCL-726 (pcl726), PCL-727 (pcl727), PCL-728 (pcl728),
- [ADLink] ACL-6126 (acl6126), ACL-6128 (acl6128)
-
-Interrupts are not supported.
-
- Options for PCL-726:
- [0] - IO Base
- [2]...[7] - D/A output range for channel 1-6:
- 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V,
- 4: 4-20mA, 5: unknown (external reference)
-
- Options for PCL-727:
- [0] - IO Base
- [2]...[13] - D/A output range for channel 1-12:
- 0: 0-5V, 1: 0-10V, 2: +/-5V,
- 3: 4-20mA
-
- Options for PCL-728 and ACL-6128:
- [0] - IO Base
- [2], [3] - D/A output range for channel 1 and 2:
- 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V,
- 4: 4-20mA, 5: 0-20mA
-
- Options for ACL-6126:
- [0] - IO Base
- [1] - IRQ (0=disable, 3, 5, 6, 7, 9, 10, 11, 12, 15) (currently ignored)
- [2]...[7] - D/A output range for channel 1-6:
- 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V,
- 4: 4-20mA
-*/
+ * pcl726.c
+ * Comedi driver for 6/12-Channel D/A Output and DIO cards
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
+ *
+ * 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.
+ */
/*
- Thanks to Circuit Specialists for having programming info (!) on
- their web page. (http://www.cir.com/)
-*/
+ * Driver: pcl726
+ * Description: Advantech PCL-726 & compatibles
+ * Author: David A. Schleef <ds@schleef.org>
+ * Status: untested
+ * Devices: (Advantech) PCL-726 [pcl726]
+ * (Advantech) PCL-727 [pcl727]
+ * (Advantech) PCL-728 [pcl728]
+ * (ADLink) ACL-6126 [acl6126]
+ * (ADLink) ACL-6128 [acl6128]
+ *
+ * Configuration Options:
+ * [0] - IO Base
+ * [1] - IRQ (ACL-6126 only)
+ * [2] - D/A output range for channel 0
+ * [3] - D/A output range for channel 1
+ *
+ * Boards with > 2 analog output channels:
+ * [4] - D/A output range for channel 2
+ * [5] - D/A output range for channel 3
+ * [6] - D/A output range for channel 4
+ * [7] - D/A output range for channel 5
+ *
+ * Boards with > 6 analog output channels:
+ * [8] - D/A output range for channel 6
+ * [9] - D/A output range for channel 7
+ * [10] - D/A output range for channel 8
+ * [11] - D/A output range for channel 9
+ * [12] - D/A output range for channel 10
+ * [13] - D/A output range for channel 11
+ *
+ * For PCL-726 the D/A output ranges are:
+ * 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, 4: 4-20mA, 5: unknown
+ *
+ * For PCL-727:
+ * 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: 4-20mA
+ *
+ * For PCL-728 and ACL-6128:
+ * 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, 4: 4-20mA, 5: 0-20mA
+ *
+ * For ACL-6126:
+ * 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, 4: 4-20mA
+ */
#include <linux/module.h>
-#include "../comedidev.h"
-
-#undef ACL6126_IRQ /* no interrupt support (yet) */
+#include <linux/interrupt.h>
-#define PCL726_SIZE 16
-#define PCL727_SIZE 32
-#define PCL728_SIZE 8
+#include "../comedidev.h"
-#define PCL726_DAC0_HI 0
-#define PCL726_DAC0_LO 1
+#include "comedi_fc.h"
-#define PCL726_DO_HI 12
-#define PCL726_DO_LO 13
-#define PCL726_DI_HI 14
-#define PCL726_DI_LO 15
+#define PCL726_AO_MSB_REG(x) (0x00 + ((x) * 2))
+#define PCL726_AO_LSB_REG(x) (0x01 + ((x) * 2))
+#define PCL726_DO_MSB_REG 0x0c
+#define PCL726_DO_LSB_REG 0x0d
+#define PCL726_DI_MSB_REG 0x0e
+#define PCL726_DI_LSB_REG 0x0f
-#define PCL727_DO_HI 24
-#define PCL727_DO_LO 25
-#define PCL727_DI_HI 0
-#define PCL727_DI_LO 1
+#define PCL727_DI_MSB_REG 0x00
+#define PCL727_DI_LSB_REG 0x01
+#define PCL727_DO_MSB_REG 0x18
+#define PCL727_DO_LSB_REG 0x19
static const struct comedi_lrange *const rangelist_726[] = {
- &range_unipolar5, &range_unipolar10,
- &range_bipolar5, &range_bipolar10,
- &range_4_20mA, &range_unknown
+ &range_unipolar5,
+ &range_unipolar10,
+ &range_bipolar5,
+ &range_bipolar10,
+ &range_4_20mA,
+ &range_unknown
};
static const struct comedi_lrange *const rangelist_727[] = {
- &range_unipolar5, &range_unipolar10,
+ &range_unipolar5,
+ &range_unipolar10,
&range_bipolar5,
&range_4_20mA
};
static const struct comedi_lrange *const rangelist_728[] = {
- &range_unipolar5, &range_unipolar10,
- &range_bipolar5, &range_bipolar10,
- &range_4_20mA, &range_0_20mA
+ &range_unipolar5,
+ &range_unipolar10,
+ &range_bipolar5,
+ &range_bipolar10,
+ &range_4_20mA,
+ &range_0_20mA
};
struct pcl726_board {
-
- const char *name; /* driver name */
- int n_aochan; /* num of D/A chans */
- int num_of_ranges; /* num of ranges */
- unsigned int IRQbits; /* allowed interrupts */
- unsigned int io_range; /* len of IO space */
- char have_dio; /* 1=card have DI/DO ports */
- int di_hi; /* ports for DI/DO operations */
- int di_lo;
- int do_hi;
- int do_lo;
- const struct comedi_lrange *const *range_type_list;
- /* list of supported ranges */
+ const char *name;
+ unsigned long io_len;
+ unsigned int irq_mask;
+ const struct comedi_lrange *const *ao_ranges;
+ int ao_num_ranges;
+ int ao_nchan;
+ unsigned int have_dio:1;
+ unsigned int is_pcl727:1;
};
-static const struct pcl726_board boardtypes[] = {
- {"pcl726", 6, 6, 0x0000, PCL726_SIZE, 1,
- PCL726_DI_HI, PCL726_DI_LO, PCL726_DO_HI, PCL726_DO_LO,
- &rangelist_726[0],},
- {"pcl727", 12, 4, 0x0000, PCL727_SIZE, 1,
- PCL727_DI_HI, PCL727_DI_LO, PCL727_DO_HI, PCL727_DO_LO,
- &rangelist_727[0],},
- {"pcl728", 2, 6, 0x0000, PCL728_SIZE, 0,
- 0, 0, 0, 0,
- &rangelist_728[0],},
- {"acl6126", 6, 5, 0x96e8, PCL726_SIZE, 1,
- PCL726_DI_HI, PCL726_DI_LO, PCL726_DO_HI, PCL726_DO_LO,
- &rangelist_726[0],},
- {"acl6128", 2, 6, 0x0000, PCL728_SIZE, 0,
- 0, 0, 0, 0,
- &rangelist_728[0],},
+static const struct pcl726_board pcl726_boards[] = {
+ {
+ .name = "pcl726",
+ .io_len = 0x10,
+ .ao_ranges = &rangelist_726[0],
+ .ao_num_ranges = ARRAY_SIZE(rangelist_726),
+ .ao_nchan = 6,
+ .have_dio = 1,
+ }, {
+ .name = "pcl727",
+ .io_len = 0x20,
+ .ao_ranges = &rangelist_727[0],
+ .ao_num_ranges = ARRAY_SIZE(rangelist_727),
+ .ao_nchan = 12,
+ .have_dio = 1,
+ .is_pcl727 = 1,
+ }, {
+ .name = "pcl728",
+ .io_len = 0x08,
+ .ao_num_ranges = ARRAY_SIZE(rangelist_728),
+ .ao_ranges = &rangelist_728[0],
+ .ao_nchan = 2,
+ }, {
+ .name = "acl6126",
+ .io_len = 0x10,
+ .irq_mask = 0x96e8,
+ .ao_num_ranges = ARRAY_SIZE(rangelist_726),
+ .ao_ranges = &rangelist_726[0],
+ .ao_nchan = 6,
+ .have_dio = 1,
+ }, {
+ .name = "acl6128",
+ .io_len = 0x08,
+ .ao_num_ranges = ARRAY_SIZE(rangelist_728),
+ .ao_ranges = &rangelist_728[0],
+ .ao_nchan = 2,
+ },
};
struct pcl726_private {
-
- int bipolar[12];
const struct comedi_lrange *rangelist[12];
unsigned int ao_readback[12];
+ unsigned int cmd_running:1;
};
-static int pcl726_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int pcl726_intr_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ data[1] = 0;
+ return insn->n;
+}
+
+static int pcl726_intr_cmdtest(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_cmd *cmd)
+{
+ int err = 0;
+
+ /* Step 1 : check if triggers are trivially valid */
+
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
+
+ if (err)
+ return 1;
+
+ /* Step 2a : make sure trigger sources are unique */
+ /* Step 2b : and mutually compatible */
+
+ if (err)
+ return 2;
+
+ /* Step 3: check if arguments are trivially valid */
+
+ err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+ err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+ err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+ err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, 1);
+ err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+
+ if (err)
+ return 3;
+
+ /* step 4: ignored */
+
+ if (err)
+ return 4;
+
+ return 0;
+}
+
+static int pcl726_intr_cmd(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct pcl726_private *devpriv = dev->private;
+
+ devpriv->cmd_running = 1;
+
+ return 0;
+}
+
+static int pcl726_intr_cancel(struct comedi_device *dev,
+ struct comedi_subdevice *s)
{
struct pcl726_private *devpriv = dev->private;
- int hi, lo;
- int n;
- int chan = CR_CHAN(insn->chanspec);
-
- for (n = 0; n < insn->n; n++) {
- lo = data[n] & 0xff;
- hi = (data[n] >> 8) & 0xf;
- if (devpriv->bipolar[chan])
- hi ^= 0x8;
- /*
- * the programming info did not say which order
- * to write bytes. switch the order of the next
- * two lines if you get glitches.
- */
- outb(hi, dev->iobase + PCL726_DAC0_HI + 2 * chan);
- outb(lo, dev->iobase + PCL726_DAC0_LO + 2 * chan);
- devpriv->ao_readback[chan] = data[n];
+
+ devpriv->cmd_running = 0;
+
+ return 0;
+}
+
+static irqreturn_t pcl726_interrupt(int irq, void *d)
+{
+ struct comedi_device *dev = d;
+ struct comedi_subdevice *s = dev->read_subdev;
+ struct pcl726_private *devpriv = dev->private;
+
+ if (devpriv->cmd_running) {
+ pcl726_intr_cancel(dev, s);
+
+ comedi_buf_put(s->async, 0);
+ s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
+ comedi_event(dev, s);
}
- return n;
+ return IRQ_HANDLED;
+}
+
+static int pcl726_ao_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct pcl726_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int range = CR_RANGE(insn->chanspec);
+ unsigned int val;
+ int i;
+
+ for (i = 0; i < insn->n; i++) {
+ val = data[i];
+ devpriv->ao_readback[chan] = val;
+
+ /* bipolar data to the DAC is two's complement */
+ if (comedi_chan_range_is_bipolar(s, chan, range))
+ val = comedi_offset_munge(s, val);
+
+ /* order is important, MSB then LSB */
+ outb((val >> 8) & 0xff, dev->iobase + PCL726_AO_MSB_REG(chan));
+ outb(val & 0xff, dev->iobase + PCL726_AO_LSB_REG(chan));
+ }
+
+ return insn->n;
}
static int pcl726_ao_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct pcl726_private *devpriv = dev->private;
- int chan = CR_CHAN(insn->chanspec);
- int n;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ int i;
+
+ for (i = 0; i < insn->n; i++)
+ data[i] = devpriv->ao_readback[chan];
- for (n = 0; n < insn->n; n++)
- data[n] = devpriv->ao_readback[chan];
- return n;
+ return insn->n;
}
static int pcl726_di_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
const struct pcl726_board *board = comedi_board(dev);
+ unsigned int val;
- data[1] = inb(dev->iobase + board->di_lo) |
- (inb(dev->iobase + board->di_hi) << 8);
+ if (board->is_pcl727) {
+ val = inb(dev->iobase + PCL727_DI_LSB_REG);
+ val |= (inb(dev->iobase + PCL727_DI_MSB_REG) << 8);
+ } else {
+ val = inb(dev->iobase + PCL726_DI_LSB_REG);
+ val |= (inb(dev->iobase + PCL726_DI_MSB_REG) << 8);
+ }
+
+ data[1] = val;
return insn->n;
}
static int pcl726_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
const struct pcl726_board *board = comedi_board(dev);
-
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
+ unsigned long io = dev->iobase;
+ unsigned int mask;
+
+ mask = comedi_dio_update_state(s, data);
+ if (mask) {
+ if (board->is_pcl727) {
+ if (mask & 0x00ff)
+ outb(s->state & 0xff, io + PCL727_DO_LSB_REG);
+ if (mask & 0xff00)
+ outb((s->state >> 8), io + PCL727_DO_MSB_REG);
+ } else {
+ if (mask & 0x00ff)
+ outb(s->state & 0xff, io + PCL726_DO_LSB_REG);
+ if (mask & 0xff00)
+ outb((s->state >> 8), io + PCL726_DO_MSB_REG);
+ }
}
- if (data[1] & 0x00ff)
- outb(s->state & 0xff, dev->iobase + board->do_lo);
- if (data[1] & 0xff00)
- outb((s->state >> 8), dev->iobase + board->do_hi);
data[1] = s->state;
return insn->n;
}
-static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int pcl726_attach(struct comedi_device *dev,
+ struct comedi_devconfig *it)
{
const struct pcl726_board *board = comedi_board(dev);
struct pcl726_private *devpriv;
struct comedi_subdevice *s;
- int ret, i;
-#ifdef ACL6126_IRQ
- unsigned int irq;
-#endif
+ int subdev;
+ int ret;
+ int i;
- ret = comedi_request_region(dev, it->options[0], board->io_range);
+ ret = comedi_request_region(dev, it->options[0], board->io_len);
if (ret)
return ret;
@@ -232,97 +358,81 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (!devpriv)
return -ENOMEM;
- for (i = 0; i < 12; i++) {
- devpriv->bipolar[i] = 0;
- devpriv->rangelist[i] = &range_unknown;
- }
-
-#ifdef ACL6126_IRQ
- irq = 0;
- if (boardtypes[board].IRQbits != 0) { /* board support IRQ */
- irq = it->options[1];
- devpriv->first_chan = 2;
- if (irq) { /* we want to use IRQ */
- if (((1 << irq) & boardtypes[board].IRQbits) == 0) {
- printk(KERN_WARNING
- ", IRQ %d is out of allowed range,"
- " DISABLING IT", irq);
- irq = 0; /* Bad IRQ */
- } else {
- if (request_irq(irq, interrupt_pcl818, 0,
- dev->board_name, dev)) {
- printk(KERN_WARNING
- ", unable to allocate IRQ %d,"
- " DISABLING IT", irq);
- irq = 0; /* Can't use IRQ */
- } else {
- printk(", irq=%d", irq);
- }
- }
+ /*
+ * Hook up the external trigger source interrupt only if the
+ * user config option is valid and the board supports interrupts.
+ */
+ if (it->options[1] && (board->irq_mask & (1 << it->options[1]))) {
+ ret = request_irq(it->options[1], pcl726_interrupt, 0,
+ dev->board_name, dev);
+ if (ret == 0) {
+ /* External trigger source is from Pin-17 of CN3 */
+ dev->irq = it->options[1];
}
}
- dev->irq = irq;
-#endif
+ /* setup the per-channel analog output range_table_list */
+ for (i = 0; i < 12; i++) {
+ unsigned int opt = it->options[2 + i];
- printk("\n");
+ if (opt < board->ao_num_ranges && i < board->ao_nchan)
+ devpriv->rangelist[i] = board->ao_ranges[opt];
+ else
+ devpriv->rangelist[i] = &range_unknown;
+ }
- ret = comedi_alloc_subdevices(dev, 3);
+ subdev = board->have_dio ? 3 : 1;
+ if (dev->irq)
+ subdev++;
+ ret = comedi_alloc_subdevices(dev, subdev);
if (ret)
return ret;
- s = &dev->subdevices[0];
- /* ao */
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
- s->n_chan = board->n_aochan;
- s->maxdata = 0xfff;
- s->len_chanlist = 1;
- s->insn_write = pcl726_ao_insn;
- s->insn_read = pcl726_ao_insn_read;
- s->range_table_list = devpriv->rangelist;
- for (i = 0; i < board->n_aochan; i++) {
- int j;
-
- j = it->options[2 + 1];
- if ((j < 0) || (j >= board->num_of_ranges)) {
- printk
- ("Invalid range for channel %d! Must be 0<=%d<%d\n",
- i, j, board->num_of_ranges - 1);
- j = 0;
- }
- devpriv->rangelist[i] = board->range_type_list[j];
- if (devpriv->rangelist[i]->range[0].min ==
- -devpriv->rangelist[i]->range[0].max)
- devpriv->bipolar[i] = 1; /* bipolar range */
- }
+ subdev = 0;
- s = &dev->subdevices[1];
- /* di */
- if (!board->have_dio) {
- s->type = COMEDI_SUBD_UNUSED;
- } else {
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND;
- s->n_chan = 16;
- s->maxdata = 1;
- s->len_chanlist = 1;
- s->insn_bits = pcl726_di_insn_bits;
- s->range_table = &range_digital;
+ /* Analog Output subdevice */
+ s = &dev->subdevices[subdev++];
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
+ s->n_chan = board->ao_nchan;
+ s->maxdata = 0x0fff;
+ s->range_table_list = devpriv->rangelist;
+ s->insn_write = pcl726_ao_insn_write;
+ s->insn_read = pcl726_ao_insn_read;
+
+ if (board->have_dio) {
+ /* Digital Input subdevice */
+ s = &dev->subdevices[subdev++];
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->insn_bits = pcl726_di_insn_bits;
+ s->range_table = &range_digital;
+
+ /* Digital Output subdevice */
+ s = &dev->subdevices[subdev++];
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->insn_bits = pcl726_do_insn_bits;
+ s->range_table = &range_digital;
}
- s = &dev->subdevices[2];
- /* do */
- if (!board->have_dio) {
- s->type = COMEDI_SUBD_UNUSED;
- } else {
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
- s->n_chan = 16;
- s->maxdata = 1;
- s->len_chanlist = 1;
- s->insn_bits = pcl726_do_insn_bits;
- s->range_table = &range_digital;
+ if (dev->irq) {
+ /* Digial Input subdevice - Interrupt support */
+ s = &dev->subdevices[subdev++];
+ dev->read_subdev = s;
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
+ s->n_chan = 1;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = pcl726_intr_insn_bits;
+ s->do_cmdtest = pcl726_intr_cmdtest;
+ s->do_cmd = pcl726_intr_cmd;
+ s->cancel = pcl726_intr_cancel;
}
return 0;
@@ -333,12 +443,12 @@ static struct comedi_driver pcl726_driver = {
.module = THIS_MODULE,
.attach = pcl726_attach,
.detach = comedi_legacy_detach,
- .board_name = &boardtypes[0].name,
- .num_names = ARRAY_SIZE(boardtypes),
+ .board_name = &pcl726_boards[0].name,
+ .num_names = ARRAY_SIZE(pcl726_boards),
.offset = sizeof(struct pcl726_board),
};
module_comedi_driver(pcl726_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for Advantech PCL-726 & compatibles");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
index 2a659f23ecda..d041b714db29 100644
--- a/drivers/staging/comedi/drivers/pcl730.c
+++ b/drivers/staging/comedi/drivers/pcl730.c
@@ -167,20 +167,17 @@ static int pcl730_do_insn_bits(struct comedi_device *dev,
unsigned int *data)
{
unsigned long reg = (unsigned long)s->private;
- unsigned int mask = data[0];
- unsigned int bits = data[1];
+ unsigned int mask;
+ mask = comedi_dio_update_state(s, data);
if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
-
if (mask & 0x00ff)
outb(s->state & 0xff, dev->iobase + reg);
- if ((mask & 0xff00) && (s->n_chan > 8))
+ if ((mask & 0xff00) & (s->n_chan > 8))
outb((s->state >> 8) & 0xff, dev->iobase + reg + 1);
- if ((mask & 0xff0000) && (s->n_chan > 16))
+ if ((mask & 0xff0000) & (s->n_chan > 16))
outb((s->state >> 16) & 0xff, dev->iobase + reg + 2);
- if ((mask & 0xff000000) && (s->n_chan > 24))
+ if ((mask & 0xff000000) & (s->n_chan > 24))
outb((s->state >> 24) & 0xff, dev->iobase + reg + 3);
}
diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
index 03a098900d34..530aee14f07a 100644
--- a/drivers/staging/comedi/drivers/pcl812.c
+++ b/drivers/staging/comedi/drivers/pcl812.c
@@ -509,19 +509,16 @@ static int pcl812_di_insn_bits(struct comedi_device *dev,
return insn->n;
}
-/*
-==============================================================================
-*/
static int pcl812_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
+ if (comedi_dio_update_state(s, data)) {
outb(s->state & 0xff, dev->iobase + PCL812_DO_LO);
outb((s->state >> 8), dev->iobase + PCL812_DO_HI);
}
+
data[1] = s->state;
return insn->n;
@@ -592,9 +589,9 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev,
if (cmd->convert_src == TRIG_TIMER) {
tmp = cmd->convert_arg;
- i8253_cascade_ns_to_timer(board->i8254_osc_base, &divisor1,
- &divisor2, &cmd->convert_arg,
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(board->i8254_osc_base,
+ &divisor1, &divisor2,
+ &cmd->convert_arg, cmd->flags);
if (cmd->convert_arg < board->ai_ns_min)
cmd->convert_arg = board->ai_ns_min;
if (tmp != cmd->convert_arg)
@@ -640,8 +637,7 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
cmd->convert_arg = board->ai_ns_min;
i8253_cascade_ns_to_timer(board->i8254_osc_base,
&divisor1, &divisor2,
- &cmd->convert_arg,
- cmd->flags & TRIG_ROUND_MASK);
+ &cmd->convert_arg, cmd->flags);
}
start_pacer(dev, -1, 0, 0); /* stop pacer */
@@ -1443,40 +1439,40 @@ static void pcl812_detach(struct comedi_device *dev)
static const struct pcl812_board boardtypes[] = {
{"pcl812", boardPCL812, 16, 0, 2, 16, 16, 0x0fff,
- 33000, 500, &range_bipolar10, &range_unipolar5,
+ 33000, I8254_OSC_BASE_2MHZ, &range_bipolar10, &range_unipolar5,
0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
{"pcl812pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,
- 33000, 500, &range_pcl812pg_ai, &range_unipolar5,
+ 33000, I8254_OSC_BASE_2MHZ, &range_pcl812pg_ai, &range_unipolar5,
0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
{"acl8112pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,
- 10000, 500, &range_pcl812pg_ai, &range_unipolar5,
+ 10000, I8254_OSC_BASE_2MHZ, &range_pcl812pg_ai, &range_unipolar5,
0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
{"acl8112dg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
- 10000, 500, &range_acl8112dg_ai, &range_unipolar5,
+ 10000, I8254_OSC_BASE_2MHZ, &range_acl8112dg_ai, &range_unipolar5,
0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
{"acl8112hg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
- 10000, 500, &range_acl8112hg_ai, &range_unipolar5,
+ 10000, I8254_OSC_BASE_2MHZ, &range_acl8112hg_ai, &range_unipolar5,
0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
{"a821pgl", boardA821, 16, 8, 1, 16, 16, 0x0fff,
- 10000, 500, &range_pcl813b_ai, &range_unipolar5,
+ 10000, I8254_OSC_BASE_2MHZ, &range_pcl813b_ai, &range_unipolar5,
0x000c, 0x00, PCLx1x_IORANGE, 0},
{"a821pglnda", boardA821, 16, 8, 0, 0, 0, 0x0fff,
- 10000, 500, &range_pcl813b_ai, NULL,
+ 10000, I8254_OSC_BASE_2MHZ, &range_pcl813b_ai, NULL,
0x000c, 0x00, PCLx1x_IORANGE, 0},
{"a821pgh", boardA821, 16, 8, 1, 16, 16, 0x0fff,
- 10000, 500, &range_a821pgh_ai, &range_unipolar5,
+ 10000, I8254_OSC_BASE_2MHZ, &range_a821pgh_ai, &range_unipolar5,
0x000c, 0x00, PCLx1x_IORANGE, 0},
{"a822pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
- 10000, 500, &range_acl8112dg_ai, &range_unipolar5,
+ 10000, I8254_OSC_BASE_2MHZ, &range_acl8112dg_ai, &range_unipolar5,
0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
{"a822pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
- 10000, 500, &range_acl8112hg_ai, &range_unipolar5,
+ 10000, I8254_OSC_BASE_2MHZ, &range_acl8112hg_ai, &range_unipolar5,
0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
{"a823pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
- 8000, 500, &range_acl8112dg_ai, &range_unipolar5,
+ 8000, I8254_OSC_BASE_2MHZ, &range_acl8112dg_ai, &range_unipolar5,
0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
{"a823pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
- 8000, 500, &range_acl8112hg_ai, &range_unipolar5,
+ 8000, I8254_OSC_BASE_2MHZ, &range_acl8112hg_ai, &range_unipolar5,
0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
{"pcl813", boardPCL813, 32, 0, 0, 0, 0, 0x0fff,
0, 0, &range_pcl813b_ai, NULL,
@@ -1491,10 +1487,10 @@ static const struct pcl812_board boardtypes[] = {
0, 0, &range_iso813_1_ai, NULL,
0x0000, 0x00, PCLx1x_IORANGE, 0},
{"acl8216", boardACL8216, 16, 8, 2, 16, 16, 0xffff,
- 10000, 500, &range_pcl813b2_ai, &range_unipolar5,
+ 10000, I8254_OSC_BASE_2MHZ, &range_pcl813b2_ai, &range_unipolar5,
0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
{"a826pg", boardACL8216, 16, 8, 2, 16, 16, 0xffff,
- 10000, 500, &range_pcl813b2_ai, &range_unipolar5,
+ 10000, I8254_OSC_BASE_2MHZ, &range_pcl813b2_ai, &range_unipolar5,
0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
};
diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index f03134962596..2fd9b178e0c6 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -481,8 +481,7 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev,
tmp = cmd->convert_arg;
i8253_cascade_ns_to_timer(board->i8254_osc_base,
&divisor1, &divisor2,
- &cmd->convert_arg,
- cmd->flags & TRIG_ROUND_MASK);
+ &cmd->convert_arg, cmd->flags);
if (cmd->convert_arg < board->ai_ns_min)
cmd->convert_arg = board->ai_ns_min;
if (tmp != cmd->convert_arg)
@@ -528,9 +527,9 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
if (cmd->convert_arg < board->ai_ns_min)
cmd->convert_arg = board->ai_ns_min;
- i8253_cascade_ns_to_timer(board->i8254_osc_base, &divisor1,
- &divisor2, &cmd->convert_arg,
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(board->i8254_osc_base,
+ &divisor1, &divisor2,
+ &cmd->convert_arg, cmd->flags);
/* PCL816 crash if any divisor is set to 1 */
if (divisor1 == 1) {
@@ -1105,7 +1104,7 @@ static const struct pcl816_board boardtypes[] = {
0xffff, /* D/A maxdata */
1024,
1, /* ao chan list */
- 100},
+ I8254_OSC_BASE_10MHZ},
{"pcl814b", 8, 16, 10000, 1, 16, 16, &range_pcl816,
&range_pcl816, PCLx1x_RANGE,
0x00fc,
@@ -1114,7 +1113,7 @@ static const struct pcl816_board boardtypes[] = {
0x3fff,
1024,
1,
- 100},
+ I8254_OSC_BASE_10MHZ},
};
static struct comedi_driver pcl816_driver = {
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index a52ba82ff0e4..7be0c946bd7c 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -418,21 +418,15 @@ static int pcl818_di_insn_bits(struct comedi_device *dev,
return insn->n;
}
-/*
-==============================================================================
- DIGITAL OUTPUT MODE0, 818 cards
-
- only one sample per call is supported
-*/
static int pcl818_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
-
- outb(s->state & 0xff, dev->iobase + PCL818_DO_LO);
- outb((s->state >> 8), dev->iobase + PCL818_DO_HI);
+ if (comedi_dio_update_state(s, data)) {
+ outb(s->state & 0xff, dev->iobase + PCL818_DO_LO);
+ outb((s->state >> 8), dev->iobase + PCL818_DO_HI);
+ }
data[1] = s->state;
@@ -806,8 +800,9 @@ static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
devpriv->neverending_ai = 1; /* well, user want neverending */
if (mode == 1) {
- i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
- &divisor2, &cmd->convert_arg,
+ i8253_cascade_ns_to_timer(devpriv->i8253_osc_base,
+ &divisor1, &divisor2,
+ &cmd->convert_arg,
TRIG_ROUND_NEAREST);
if (divisor1 == 1) { /* PCL718/818 crash if any divisor is set to 1 */
divisor1 = 2;
@@ -1040,9 +1035,9 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
if (cmd->convert_src == TRIG_TIMER) {
tmp = cmd->convert_arg;
- i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
- &divisor2, &cmd->convert_arg,
- cmd->flags & TRIG_ROUND_MASK);
+ i8253_cascade_ns_to_timer(devpriv->i8253_osc_base,
+ &divisor1, &divisor2,
+ &cmd->convert_arg, cmd->flags);
if (cmd->convert_arg < board->ns_min)
cmd->convert_arg = board->ns_min;
if (tmp != cmd->convert_arg)
@@ -1438,9 +1433,9 @@ no_dma:
/* select 1/10MHz oscilator */
if ((it->options[3] == 0) || (it->options[3] == 10))
- devpriv->i8253_osc_base = 100;
+ devpriv->i8253_osc_base = I8254_OSC_BASE_10MHZ;
else
- devpriv->i8253_osc_base = 1000;
+ devpriv->i8253_osc_base = I8254_OSC_BASE_1MHZ;
/* max sampling speed */
devpriv->ns_min = board->ns_min;
diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
index 423f23676d26..fe482fdd512e 100644
--- a/drivers/staging/comedi/drivers/pcmad.c
+++ b/drivers/staging/comedi/drivers/pcmad.c
@@ -75,12 +75,6 @@ static int pcmad_ai_wait_for_eoc(struct comedi_device *dev,
return -ETIME;
}
-static bool pcmad_range_is_bipolar(struct comedi_subdevice *s,
- unsigned int range)
-{
- return s->range_table->range[range].min < 0;
-}
-
static int pcmad_ai_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
@@ -106,7 +100,7 @@ static int pcmad_ai_insn_read(struct comedi_device *dev,
if (s->maxdata == 0x0fff)
val >>= 4;
- if (pcmad_range_is_bipolar(s, range)) {
+ if (comedi_range_is_bipolar(s, range)) {
/* munge the two's complement value */
val ^= ((s->maxdata + 1) >> 1);
}
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index 9775d3622a62..ece3031711eb 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -690,18 +690,12 @@ static int daqp_do_insn_bits(struct comedi_device *dev,
unsigned int *data)
{
struct daqp_private *devpriv = dev->private;
- unsigned int mask = data[0];
- unsigned int bits = data[1];
if (devpriv->stop)
return -EIO;
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
-
+ if (comedi_dio_update_state(s, data))
outb(s->state, dev->iobase + DAQP_DIGITAL_IO);
- }
data[1] = s->state;
diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
index 93c980c62a23..3ec6632949bd 100644
--- a/drivers/staging/comedi/drivers/rtd520.c
+++ b/drivers/staging/comedi/drivers/rtd520.c
@@ -1217,15 +1217,9 @@ static int rtd_dio_insn_bits(struct comedi_device *dev,
unsigned int *data)
{
struct rtd_private *devpriv = dev->private;
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
+ if (comedi_dio_update_state(s, data))
writew(s->state & 0xff, devpriv->las0 + LAS0_DIO0);
- }
data[1] = readw(devpriv->las0 + LAS0_DIO0) & 0xff;
diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
index cbb4ba5b852a..e1f3671ac056 100644
--- a/drivers/staging/comedi/drivers/rti800.c
+++ b/drivers/staging/comedi/drivers/rti800.c
@@ -267,13 +267,7 @@ static int rti800_do_insn_bits(struct comedi_device *dev,
struct comedi_insn *insn,
unsigned int *data)
{
- unsigned int mask = data[0];
- unsigned int bits = data[1];
-
- if (mask) {
- s->state &= ~mask;
- s->state |= (bits & mask);
-
+ if (comedi_dio_update_state(s, data)) {
/* Outputs are inverted... */
outb(s->state ^ 0xff, dev->iobase + RTI800_DO);
}
diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
index d629463b85a2..9950f59b1192 100644
--- a/drivers/staging/comedi/drivers/s526.c
+++ b/drivers/staging/comedi/drivers/s526.c
@@ -499,14 +499,11 @@ static int s526_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
static int s526_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
-
+ if (comedi_dio_update_state(s, data))
outw(s->state, dev->iobase + REG_DIO);
- }
data[1] = inw(dev->iobase + REG_DIO) & 0xff;
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index d22b95dcb9bd..4eb4e7160bc3 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -1638,19 +1638,10 @@ static int s626_dio_insn_bits(struct comedi_device *dev,
unsigned int *data)
{
unsigned long group = (unsigned long)s->private;
- unsigned long mask = data[0];
- unsigned long bits = data[1];
-
- if (mask) {
- /* Check if requested channels are configured for output */
- if ((s->io_bits & mask) != mask)
- return -EIO;
-
- s->state &= ~mask;
- s->state |= (bits & mask);
+ if (comedi_dio_update_state(s, data))
DEBIwrite(dev, LP_WRDOUT(group), s->state);
- }
+
data[1] = DEBIread(dev, LP_RDDIN(group));
return insn->n;
diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
index 9e964950a560..daee2f42bde0 100644
--- a/drivers/staging/comedi/drivers/skel.c
+++ b/drivers/staging/comedi/drivers/skel.c
@@ -332,30 +332,44 @@ static int skel_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
return i;
}
-/* DIO devices are slightly special. Although it is possible to
+/*
+ * DIO devices are slightly special. Although it is possible to
* implement the insn_read/insn_write interface, it is much more
* useful to applications if you implement the insn_bits interface.
- * This allows packed reading/writing of the DIO channels. The
- * comedi core can convert between insn_bits and insn_read/write */
+ * This allows packed reading/writing of the DIO channels. The
+ * comedi core can convert between insn_bits and insn_read/write.
+ */
static int skel_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- /* The insn data is a mask in data[0] and the new data
- * in data[1], each channel cooresponding to a bit. */
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
+ /*
+ * The insn data is a mask in data[0] and the new data
+ * in data[1], each channel cooresponding to a bit.
+ *
+ * The core provided comedi_dio_update_state() function can
+ * be used to handle the internal state update to DIO subdevices
+ * with <= 32 channels. This function will return '0' if the
+ * state does not change or the mask of the channels that need
+ * to be updated.
+ */
+ if (comedi_dio_update_state(s, data)) {
/* Write out the new digital output lines */
- /* outw(s->state,dev->iobase + SKEL_DIO); */
+ /* outw(s->state, dev->iobase + SKEL_DIO); */
}
- /* on return, data[1] contains the value of the digital
- * input and output lines. */
- /* data[1]=inw(dev->iobase + SKEL_DIO); */
- /* or we could just return the software copy of the output values if
- * it was a purely digital output subdevice */
- /* data[1]=s->state; */
+ /*
+ * On return, data[1] contains the value of the digital
+ * input and output lines.
+ */
+ /* data[1] = inw(dev->iobase + SKEL_DIO); */
+
+ /*
+ * Or we could just return the software copy of the output
+ * values if it was a purely digital output subdevice.
+ */
+ /* data[1] = s->state; */
return insn->n;
}
diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
index 11758a515c1b..df22a78d2b7e 100644
--- a/drivers/staging/comedi/drivers/ssv_dnp.c
+++ b/drivers/staging/comedi/drivers/ssv_dnp.c
@@ -46,51 +46,43 @@ Status: unknown
#define PCMR 0xa3 /* Port C Mode Register */
#define PCDR 0xa7 /* Port C Data Register */
-/* ------------------------------------------------------------------------- */
-/* The insn_bits interface allows packed reading/writing of DIO channels. */
-/* The comedi core can convert between insn_bits and insn_read/write, so you */
-/* are able to use these instructions as well. */
-/* ------------------------------------------------------------------------- */
-
static int dnp_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- /* The insn data is a mask in data[0] and the new data in data[1], */
- /* each channel cooresponding to a bit. */
-
- /* Ports A and B are straight forward: each bit corresponds to an */
- /* output pin with the same order. Port C is different: bits 0...3 */
- /* correspond to bits 4...7 of the output register (PCDR). */
+ unsigned int mask;
+ unsigned int val;
- if (data[0]) {
+ /*
+ * Ports A and B are straight forward: each bit corresponds to an
+ * output pin with the same order. Port C is different: bits 0...3
+ * correspond to bits 4...7 of the output register (PCDR).
+ */
+ mask = comedi_dio_update_state(s, data);
+ if (mask) {
outb(PADR, CSCIR);
- outb((inb(CSCDR)
- & ~(u8) (data[0] & 0x0000FF))
- | (u8) (data[1] & 0x0000FF), CSCDR);
+ outb(s->state & 0xff, CSCDR);
outb(PBDR, CSCIR);
- outb((inb(CSCDR)
- & ~(u8) ((data[0] & 0x00FF00) >> 8))
- | (u8) ((data[1] & 0x00FF00) >> 8), CSCDR);
+ outb((s->state >> 8) & 0xff, CSCDR);
outb(PCDR, CSCIR);
- outb((inb(CSCDR)
- & ~(u8) ((data[0] & 0x0F0000) >> 12))
- | (u8) ((data[1] & 0x0F0000) >> 12), CSCDR);
+ val = inb(CSCDR) & 0x0f;
+ outb(((s->state >> 12) & 0xf0) | val, CSCDR);
}
- /* on return, data[1] contains the value of the digital input lines. */
outb(PADR, CSCIR);
- data[0] = inb(CSCDR);
+ val = inb(CSCDR);
outb(PBDR, CSCIR);
- data[0] += inb(CSCDR) << 8;
+ val |= (inb(CSCDR) << 8);
outb(PCDR, CSCIR);
- data[0] += ((inb(CSCDR) & 0xF0) << 12);
+ val |= ((inb(CSCDR) & 0xf0) << 12);
- return insn->n;
+ data[1] = val;
+ return insn->n;
}
static int dnp_dio_insn_config(struct comedi_device *dev,
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 701ad1a69394..9218d7336923 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -1133,15 +1133,13 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev,
{
struct usbdux_private *devpriv = dev->private;
- unsigned int mask = data[0];
- unsigned int bits = data[1];
int ret;
down(&devpriv->sem);
- s->state &= ~mask;
- s->state |= (bits & mask);
+ comedi_dio_update_state(s, data);
+ /* Always update the hardware. See the (*insn_config). */
devpriv->dux_commands[1] = s->io_bits;
devpriv->dux_commands[2] = s->state;
diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c
index c47f4087568f..5618e61893da 100644
--- a/drivers/staging/comedi/drivers/usbduxsigma.c
+++ b/drivers/staging/comedi/drivers/usbduxsigma.c
@@ -1059,15 +1059,13 @@ static int usbduxsigma_dio_insn_bits(struct comedi_device *dev,
unsigned int *data)
{
struct usbduxsigma_private *devpriv = dev->private;
- unsigned int mask = data[0];
- unsigned int bits = data[1];
int ret;
down(&devpriv->sem);
- s->state &= ~mask;
- s->state |= (bits & mask);
+ comedi_dio_update_state(s, data);
+ /* Always update the hardware. See the (*insn_config). */
devpriv->dux_commands[1] = s->io_bits & 0xff;
devpriv->dux_commands[4] = s->state & 0xff;
devpriv->dux_commands[2] = (s->io_bits >> 8) & 0xff;
diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c
index 06efa16b9af2..933b01a0f03d 100644
--- a/drivers/staging/comedi/drivers/vmk80xx.c
+++ b/drivers/staging/comedi/drivers/vmk80xx.c
@@ -462,9 +462,10 @@ static int vmk80xx_do_insn_bits(struct comedi_device *dev,
unsigned int *data)
{
struct vmk80xx_private *devpriv = dev->private;
- unsigned char *rx_buf, *tx_buf;
+ unsigned char *rx_buf = devpriv->usb_rx_buf;
+ unsigned char *tx_buf = devpriv->usb_tx_buf;
int reg, cmd;
- int retval;
+ int ret;
if (devpriv->model == VMK8061_MODEL) {
reg = VMK8061_DO_REG;
@@ -476,37 +477,27 @@ static int vmk80xx_do_insn_bits(struct comedi_device *dev,
down(&devpriv->limit_sem);
- rx_buf = devpriv->usb_rx_buf;
- tx_buf = devpriv->usb_tx_buf;
-
- if (data[0]) {
- tx_buf[reg] &= ~data[0];
- tx_buf[reg] |= (data[0] & data[1]);
-
- retval = vmk80xx_write_packet(dev, cmd);
-
- if (retval)
+ if (comedi_dio_update_state(s, data)) {
+ tx_buf[reg] = s->state;
+ ret = vmk80xx_write_packet(dev, cmd);
+ if (ret)
goto out;
}
if (devpriv->model == VMK8061_MODEL) {
tx_buf[0] = VMK8061_CMD_RD_DO;
-
- retval = vmk80xx_read_packet(dev);
-
- if (!retval) {
- data[1] = rx_buf[reg];
- retval = 2;
- }
+ ret = vmk80xx_read_packet(dev);
+ if (ret)
+ goto out;
+ data[1] = rx_buf[reg];
} else {
- data[1] = tx_buf[reg];
- retval = 2;
+ data[1] = s->state;
}
out:
up(&devpriv->limit_sem);
- return retval;
+ return ret ? ret : insn->n;
}
static int vmk80xx_cnt_insn_read(struct comedi_device *dev,
diff --git a/drivers/staging/crystalhd/crystalhd_hw.c b/drivers/staging/crystalhd/crystalhd_hw.c
index 5845e899ee80..043bd49843ff 100644
--- a/drivers/staging/crystalhd/crystalhd_hw.c
+++ b/drivers/staging/crystalhd/crystalhd_hw.c
@@ -1517,7 +1517,7 @@ static void crystalhd_rx_isr(struct crystalhd_hw *hw, uint32_t intr_sts)
uint32_t i, list_avail = 0;
enum BC_STATUS comp_sts = BC_STS_NO_DATA;
uint32_t y_err_sts, uv_err_sts, y_dn_sz = 0, uv_dn_sz = 0;
- bool ret = 0;
+ bool ret = false;
if (!hw) {
BCMLOG_ERR("Invalid Arguments\n");
@@ -1852,7 +1852,7 @@ bool crystalhd_hw_interrupt(struct crystalhd_adp *adp, struct crystalhd_hw *hw)
{
uint32_t intr_sts = 0;
uint32_t deco_intr = 0;
- bool rc = 0;
+ bool rc = false;
if (!adp || !hw->dev_started)
return rc;
@@ -1865,7 +1865,7 @@ bool crystalhd_hw_interrupt(struct crystalhd_adp *adp, struct crystalhd_hw *hw)
if (intr_sts) {
/* let system know we processed interrupt..*/
- rc = 1;
+ rc = true;
hw->stats.dev_interrupts++;
}
@@ -1886,7 +1886,7 @@ bool crystalhd_hw_interrupt(struct crystalhd_adp *adp, struct crystalhd_hw *hw)
/* FIXME: jarod: No udelay? might this be
the real reason mini pci-e cards were stalling out? */
bc_dec_reg_wr(adp, Stream2Host_Intr_Sts, 0);
- rc = 1;
+ rc = true;
}
/* Rx interrupts */
diff --git a/drivers/staging/dgap/Makefile b/drivers/staging/dgap/Makefile
index 9f1fce157c77..3abe8d2bb748 100644
--- a/drivers/staging/dgap/Makefile
+++ b/drivers/staging/dgap/Makefile
@@ -1,5 +1,3 @@
-EXTRA_CFLAGS += -DDG_NAME=\"dgap-1.3-16\" -DDG_PART=\"40002347_C\"
-
obj-$(CONFIG_DGAP) += dgap.o
diff --git a/drivers/staging/dgap/dgap_downld.h b/drivers/staging/dgap/dgap_downld.h
index f79e65cd1d51..271ac19257f9 100644
--- a/drivers/staging/dgap/dgap_downld.h
+++ b/drivers/staging/dgap/dgap_downld.h
@@ -35,7 +35,7 @@
struct fepimg {
int type; /* board type */
int len; /* length of image */
- char fepimage[1]; /* begining of image */
+ char fepimage[1]; /* beginning of image */
};
struct downldio {
diff --git a/drivers/staging/dgap/dgap_driver.c b/drivers/staging/dgap/dgap_driver.c
index 40ef785a0428..4c1515ee56e5 100644
--- a/drivers/staging/dgap/dgap_driver.c
+++ b/drivers/staging/dgap/dgap_driver.c
@@ -32,16 +32,12 @@
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h> /* For udelay */
#include <linux/slab.h>
#include <asm/uaccess.h> /* For copy_from_user/copy_to_user */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
#include <linux/sched.h>
-#endif
#include "dgap_driver.h"
#include "dgap_pci.h"
@@ -420,8 +416,7 @@ void dgap_cleanup_module(void)
unregister_chrdev(DIGI_DGAP_MAJOR, "dgap");
}
- if (dgap_config_buf)
- kfree(dgap_config_buf);
+ kfree(dgap_config_buf);
for (i = 0; i < dgap_NumBoards; ++i) {
dgap_remove_ports_sysfiles(dgap_Board[i]);
@@ -488,10 +483,8 @@ static void dgap_cleanup_board(struct board_t *brd)
}
}
- if (brd->flipbuf)
- kfree(brd->flipbuf);
- if (brd->flipflagbuf)
- kfree(brd->flipflagbuf);
+ kfree(brd->flipbuf);
+ kfree(brd->flipflagbuf);
dgap_Board[brd->boardnum] = NULL;
diff --git a/drivers/staging/dgap/dgap_driver.h b/drivers/staging/dgap/dgap_driver.h
index b1cf489a729c..7d631e80c00e 100644
--- a/drivers/staging/dgap/dgap_driver.h
+++ b/drivers/staging/dgap/dgap_driver.h
@@ -46,13 +46,16 @@
/*
* Driver identification, error and debugging statments
*
- * In theory, you can change all occurances of "digi" in the next
+ * In theory, you can change all occurrences of "digi" in the next
* three lines, and the driver printk's will all automagically change.
*
* APR((fmt, args, ...)); Always prints message
* DPR((fmt, args, ...)); Only prints if DGAP_TRACER is defined at
* compile time and dgap_debug!=0
*/
+#define DG_NAME "dgap-1.3-16"
+#define DG_PART "40002347_C"
+
#define PROCSTR "dgap" /* /proc entries */
#define DEVSTR "/dev/dg/dgap" /* /dev entries */
#define DRVSTR "dgap" /* Driver name string
diff --git a/drivers/staging/dgap/dgap_fep5.h b/drivers/staging/dgap/dgap_fep5.h
index 3a12ba5e3c2a..c9abc406a1e0 100644
--- a/drivers/staging/dgap/dgap_fep5.h
+++ b/drivers/staging/dgap/dgap_fep5.h
@@ -211,7 +211,7 @@ struct bs_t {
#define SIFLAG 0xea /* Set UNIX iflags */
#define SFLOWC 0xeb /* Set flow control characters */
#define STLOW 0xec /* Set transmit low water mark */
-#define RPAUSE 0xee /* Pause recieve */
+#define RPAUSE 0xee /* Pause receive */
#define RRESUME 0xef /* Resume receive */
#define CHRESET 0xf0 /* Reset Channel */
#define BUFSETALL 0xf2 /* Set Tx & Rx buffer size avail*/
diff --git a/drivers/staging/dgap/dgap_kcompat.h b/drivers/staging/dgap/dgap_kcompat.h
index 8ebf4b7373b7..0dc2404922ff 100644
--- a/drivers/staging/dgap/dgap_kcompat.h
+++ b/drivers/staging/dgap/dgap_kcompat.h
@@ -28,11 +28,6 @@
#ifndef __DGAP_KCOMPAT_H
#define __DGAP_KCOMPAT_H
-# ifndef KERNEL_VERSION
-# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-# endif
-
-
#if !defined(TTY_FLIPBUF_SIZE)
# define TTY_FLIPBUF_SIZE 512
#endif
@@ -66,28 +61,4 @@
module_param(VAR, long, PERM); \
MODULE_PARM_DESC(VAR, DESC);
-
-
-
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
-
-
-
-
-/* NOTHING YET */
-
-
-
-
-# else
-
-
-
-# error "this driver does not support anything below the 2.6.27 kernel series."
-
-
-
-# endif
-
#endif /* ! __DGAP_KCOMPAT_H */
diff --git a/drivers/staging/dgap/dgap_parse.c b/drivers/staging/dgap/dgap_parse.c
index 5497e6de0608..ff9d19449b43 100644
--- a/drivers/staging/dgap/dgap_parse.c
+++ b/drivers/staging/dgap/dgap_parse.c
@@ -904,7 +904,7 @@ int dgap_parsefile(char **in, int Remove)
/*
* dgap_sindex: much like index(), but it looks for a match of any character in
* the group, and returns that position. If the first character is a ^, then
- * this will match the first occurence not in that group.
+ * this will match the first occurrence not in that group.
*/
static char *dgap_sindex (char *string, char *group)
{
@@ -1013,8 +1013,10 @@ static void dgap_err(char *s)
static struct cnode *dgap_newnode(int t)
{
struct cnode *n;
- if ( (n = (struct cnode *) kmalloc(sizeof(struct cnode ), GFP_ATOMIC) ) != NULL) {
- memset( (char *)n, 0, sizeof(struct cnode ) );
+
+ n = kmalloc(sizeof(struct cnode), GFP_ATOMIC);
+ if (n != NULL) {
+ memset((char *)n, 0, sizeof(struct cnode));
n->type = t;
}
return(n);
@@ -1150,7 +1152,7 @@ uint dgap_config_get_altpin(struct board_t *bd)
/*
* Given a specific type of board, if found, detached link and
- * returns the first occurance in the list.
+ * returns the first occurrence in the list.
*/
struct cnode *dgap_find_config(int type, int bus, int slot)
{
diff --git a/drivers/staging/dgap/dgap_sysfs.c b/drivers/staging/dgap/dgap_sysfs.c
index 94da06fcf7e9..7f4ec9a18293 100644
--- a/drivers/staging/dgap/dgap_sysfs.c
+++ b/drivers/staging/dgap/dgap_sysfs.c
@@ -395,7 +395,7 @@ static ssize_t dgap_tty_state_show(struct device *d, struct device_attribute *at
if (!d)
return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
@@ -420,7 +420,7 @@ static ssize_t dgap_tty_baud_show(struct device *d, struct device_attribute *att
if (!d)
return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
@@ -445,7 +445,7 @@ static ssize_t dgap_tty_msignals_show(struct device *d, struct device_attribute
if (!d)
return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
@@ -479,7 +479,7 @@ static ssize_t dgap_tty_iflag_show(struct device *d, struct device_attribute *at
if (!d)
return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
@@ -504,7 +504,7 @@ static ssize_t dgap_tty_cflag_show(struct device *d, struct device_attribute *at
if (!d)
return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
@@ -529,7 +529,7 @@ static ssize_t dgap_tty_oflag_show(struct device *d, struct device_attribute *at
if (!d)
return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
@@ -554,7 +554,7 @@ static ssize_t dgap_tty_lflag_show(struct device *d, struct device_attribute *at
if (!d)
return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
@@ -579,7 +579,7 @@ static ssize_t dgap_tty_digi_flag_show(struct device *d, struct device_attribute
if (!d)
return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
@@ -604,7 +604,7 @@ static ssize_t dgap_tty_rxcount_show(struct device *d, struct device_attribute *
if (!d)
return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
@@ -629,7 +629,7 @@ static ssize_t dgap_tty_txcount_show(struct device *d, struct device_attribute *
if (!d)
return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
@@ -661,7 +661,7 @@ static ssize_t dgap_tty_name_show(struct device *d, struct device_attribute *att
if (!d)
return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGAP_UNIT_MAGIC)
return (0);
ch = un->un_ch;
diff --git a/drivers/staging/dgap/dgap_tty.c b/drivers/staging/dgap/dgap_tty.c
index b906db30b617..924e2bfcbe30 100644
--- a/drivers/staging/dgap/dgap_tty.c
+++ b/drivers/staging/dgap/dgap_tty.c
@@ -249,7 +249,7 @@ int dgap_tty_register(struct board_t *brd)
/*
* If we're doing transparent print, we have to do all of the above
- * again, seperately so we don't get the LD confused about what major
+ * again, separately so we don't get the LD confused about what major
* we are when we get into the dgap_tty_open() routine.
*/
brd->PrintDriver = alloc_tty_driver(MAXPORTS);
@@ -497,10 +497,8 @@ int dgap_tty_init(struct board_t *brd)
*/
void dgap_tty_post_uninit(void)
{
- if (dgap_TmpWriteBuf) {
- kfree(dgap_TmpWriteBuf);
- dgap_TmpWriteBuf = NULL;
- }
+ kfree(dgap_TmpWriteBuf);
+ dgap_TmpWriteBuf = NULL;
}
@@ -522,10 +520,8 @@ void dgap_tty_uninit(struct board_t *brd)
tty_unregister_device(brd->SerialDriver, i);
}
tty_unregister_driver(brd->SerialDriver);
- if (brd->SerialDriver->ttys) {
- kfree(brd->SerialDriver->ttys);
- brd->SerialDriver->ttys = NULL;
- }
+ kfree(brd->SerialDriver->ttys);
+ brd->SerialDriver->ttys = NULL;
put_tty_driver(brd->SerialDriver);
brd->dgap_Major_Serial_Registered = FALSE;
}
@@ -538,10 +534,8 @@ void dgap_tty_uninit(struct board_t *brd)
tty_unregister_device(brd->PrintDriver, i);
}
tty_unregister_driver(brd->PrintDriver);
- if (brd->PrintDriver->ttys) {
- kfree(brd->PrintDriver->ttys);
- brd->PrintDriver->ttys = NULL;
- }
+ kfree(brd->PrintDriver->ttys);
+ brd->PrintDriver->ttys = NULL;
put_tty_driver(brd->PrintDriver);
brd->dgap_Major_TransparentPrint_Registered = FALSE;
}
@@ -1069,7 +1063,7 @@ static int dgap_tty_open(struct tty_struct *tty, struct file *file)
DGAP_LOCK(brd->bd_lock, lock_flags);
- /* The wait above should guarentee this cannot happen */
+ /* The wait above should guarantee this cannot happen */
if (brd->state != BOARD_READY) {
DGAP_UNLOCK(brd->bd_lock, lock_flags);
return -ENXIO;
@@ -3513,10 +3507,6 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
return(-EINVAL);
}
- DGAP_UNLOCK(ch->ch_lock, lock_flags2);
- DGAP_UNLOCK(bd->bd_lock, lock_flags);
- return(-ENOIOCTLCMD);
-
case DIGI_GETA:
/* get information for ditty */
DGAP_UNLOCK(ch->ch_lock, lock_flags2);
@@ -3586,12 +3576,4 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
return(-ENOIOCTLCMD);
}
-
- DGAP_UNLOCK(ch->ch_lock, lock_flags2);
- DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
- DPR_IOCTL(("dgap_tty_ioctl end - cmd %s (%x), arg %lx\n",
- dgap_ioctl_name(cmd), cmd, arg));
-
- return(0);
}
diff --git a/drivers/staging/dgap/digi.h b/drivers/staging/dgap/digi.h
index 651e2e5e93c7..bcea4f734a32 100644
--- a/drivers/staging/dgap/digi.h
+++ b/drivers/staging/dgap/digi.h
@@ -203,9 +203,9 @@ struct shrink_buf_struct {
unsigned long shrink_buf_vaddr; /* Virtual address of board */
unsigned long shrink_buf_phys; /* Physical address of board */
unsigned long shrink_buf_bseg; /* Amount of board memory */
- unsigned long shrink_buf_hseg; /* '186 Begining of Dual-Port */
+ unsigned long shrink_buf_hseg; /* '186 Beginning of Dual-Port */
- unsigned long shrink_buf_lseg; /* '186 Begining of freed memory */
+ unsigned long shrink_buf_lseg; /* '186 Beginning of freed memory */
unsigned long shrink_buf_mseg; /* Linear address from start of
dual-port were freed memory
begins, host viewpoint. */
diff --git a/drivers/staging/dgap/downld.c b/drivers/staging/dgap/downld.c
index 57dfd6bafcf6..638c5da43c85 100644
--- a/drivers/staging/dgap/downld.c
+++ b/drivers/staging/dgap/downld.c
@@ -52,7 +52,7 @@ char *pgm;
void myperror();
/*
-** This structure is used to keep track of the diferent images available
+** This structure is used to keep track of the different images available
** to give to the driver. It is arranged so that the things that are
** constants or that have defaults are first inthe strucutre to simplify
** the table of initializers.
@@ -789,7 +789,7 @@ int main(int argc, char **argv)
/*
** myperror()
**
-** Same as normal perror(), but places the program name at the begining
+** Same as normal perror(), but places the program name at the beginning
** of the message.
*/
void myperror(char *s)
diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c
index 117e15808240..fa1bb633f036 100644
--- a/drivers/staging/dgnc/dgnc_cls.c
+++ b/drivers/staging/dgnc/dgnc_cls.c
@@ -43,7 +43,7 @@
#include "dgnc_tty.h"
#include "dgnc_trace.h"
-static inline void cls_parse_isr(struct board_t *brd, uint port);
+static inline void cls_parse_isr(struct dgnc_board *brd, uint port);
static inline void cls_clear_break(struct channel_t *ch, int force);
static inline void cls_set_cts_flow_control(struct channel_t *ch);
static inline void cls_set_rts_flow_control(struct channel_t *ch);
@@ -53,7 +53,7 @@ static inline void cls_set_no_output_flow_control(struct channel_t *ch);
static inline void cls_set_no_input_flow_control(struct channel_t *ch);
static void cls_parse_modem(struct channel_t *ch, uchar signals);
static void cls_tasklet(unsigned long data);
-static void cls_vpd(struct board_t *brd);
+static void cls_vpd(struct dgnc_board *brd);
static void cls_uart_init(struct channel_t *ch);
static void cls_uart_off(struct channel_t *ch);
static int cls_drain(struct tty_struct *tty, uint seconds);
@@ -393,7 +393,7 @@ static inline void cls_clear_break(struct channel_t *ch, int force)
/* Parse the ISR register for the specific port */
-static inline void cls_parse_isr(struct board_t *brd, uint port)
+static inline void cls_parse_isr(struct dgnc_board *brd, uint port)
{
struct channel_t *ch;
uchar isr = 0;
@@ -477,7 +477,7 @@ static void cls_param(struct tty_struct *tty)
uchar uart_ier = 0;
uint baud = 9600;
int quot = 0;
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
@@ -725,7 +725,7 @@ static void cls_param(struct tty_struct *tty)
*/
static void cls_tasklet(unsigned long data)
{
- struct board_t *bd = (struct board_t *) data;
+ struct dgnc_board *bd = (struct dgnc_board *) data;
struct channel_t *ch;
ulong lock_flags;
int i;
@@ -802,7 +802,7 @@ static void cls_tasklet(unsigned long data)
*/
static irqreturn_t cls_intr(int irq, void *voidbrd)
{
- struct board_t *brd = (struct board_t *) voidbrd;
+ struct dgnc_board *brd = (struct dgnc_board *) voidbrd;
uint i = 0;
uchar poll_reg;
unsigned long lock_flags;
@@ -976,17 +976,17 @@ static int cls_drain(struct tty_struct *tty, uint seconds)
int rc = 0;
if (!tty || tty->magic != TTY_MAGIC) {
- return (-ENXIO);
+ return -ENXIO;
}
un = (struct un_t *) tty->driver_data;
if (!un || un->magic != DGNC_UNIT_MAGIC) {
- return (-ENXIO);
+ return -ENXIO;
}
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
- return (-ENXIO);
+ return -ENXIO;
}
DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -1002,7 +1002,7 @@ static int cls_drain(struct tty_struct *tty, uint seconds)
if (rc)
DPR_IOCTL(("%d Drain - User ctrl c'ed\n", __LINE__));
- return (rc);
+ return rc;
}
@@ -1378,7 +1378,7 @@ static void cls_send_immediate_char(struct channel_t *ch, unsigned char c)
writeb(c, &ch->ch_cls_uart->txrx);
}
-static void cls_vpd(struct board_t *brd)
+static void cls_vpd(struct dgnc_board *brd)
{
ulong vpdbase; /* Start of io base of the card */
u8 __iomem *re_map_vpdbase;/* Remapped memory of the card */
diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c
index 71d2b83cc3a1..c398193e9b85 100644
--- a/drivers/staging/dgnc/dgnc_driver.c
+++ b/drivers/staging/dgnc/dgnc_driver.c
@@ -31,15 +31,10 @@
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/slab.h>
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
#include <linux/sched.h>
-#endif
-
#include "dgnc_driver.h"
#include "dgnc_pci.h"
#include "dpacompat.h"
@@ -71,16 +66,16 @@ PARM_INT(trcbuf_size, 0x100000, 0644, "Debugging trace buffer size.");
*
*/
static int dgnc_start(void);
-static int dgnc_finalize_board_init(struct board_t *brd);
+static int dgnc_finalize_board_init(struct dgnc_board *brd);
static void dgnc_init_globals(void);
static int dgnc_found_board(struct pci_dev *pdev, int id);
-static void dgnc_cleanup_board(struct board_t *brd);
+static void dgnc_cleanup_board(struct dgnc_board *brd);
static void dgnc_poll_handler(ulong dummy);
static int dgnc_init_pci(void);
static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static void dgnc_remove_one(struct pci_dev *dev);
static int dgnc_probe1(struct pci_dev *pdev, int card_type);
-static void dgnc_do_remap(struct board_t *brd);
+static void dgnc_do_remap(struct dgnc_board *brd);
/* Driver load/unload functions */
int dgnc_init_module(void);
@@ -106,7 +101,7 @@ static struct file_operations dgnc_BoardFops =
* Globals
*/
uint dgnc_NumBoards;
-struct board_t *dgnc_Board[MAXBOARDS];
+struct dgnc_board *dgnc_Board[MAXBOARDS];
DEFINE_SPINLOCK(dgnc_global_lock);
int dgnc_driver_state = DRIVER_INITIALIZED;
ulong dgnc_poll_counter;
@@ -225,7 +220,7 @@ int dgnc_init_module(void)
rc = dgnc_start();
if (rc < 0) {
- return(rc);
+ return rc;
}
/*
@@ -250,7 +245,7 @@ int dgnc_init_module(void)
}
DPR_INIT(("Finished init_module. Returning %d\n", rc));
- return (rc);
+ return rc;
}
@@ -286,21 +281,14 @@ static int dgnc_start(void)
if (rc <= 0) {
APR(("Can't register dgnc driver device (%d)\n", rc));
rc = -ENXIO;
- return(rc);
+ return rc;
}
dgnc_Major = rc;
dgnc_class = class_create(THIS_MODULE, "dgnc_mgmt");
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
- device_create_drvdata(dgnc_class, NULL,
- MKDEV(dgnc_Major, 0),
- NULL, "dgnc_mgmt");
-#else
device_create(dgnc_class, NULL,
MKDEV(dgnc_Major, 0),
NULL, "dgnc_mgmt");
-#endif
-
dgnc_Major_Control_Registered = TRUE;
}
@@ -311,7 +299,7 @@ static int dgnc_start(void)
if (rc < 0) {
APR(("tty preinit - not enough memory (%d)\n", rc));
- return(rc);
+ return rc;
}
/* Start the poller */
@@ -328,7 +316,7 @@ static int dgnc_start(void)
dgnc_driver_state = DRIVER_READY;
}
- return(rc);
+ return rc;
}
/*
@@ -418,7 +406,7 @@ void dgnc_cleanup_module(void)
*
* Free all the memory associated with a board
*/
-static void dgnc_cleanup_board(struct board_t *brd)
+static void dgnc_cleanup_board(struct dgnc_board *brd)
{
int i = 0;
@@ -491,7 +479,7 @@ static void dgnc_cleanup_board(struct board_t *brd)
*/
static int dgnc_found_board(struct pci_dev *pdev, int id)
{
- struct board_t *brd;
+ struct dgnc_board *brd;
unsigned int pci_irq;
int i = 0;
int rc = 0;
@@ -499,19 +487,19 @@ static int dgnc_found_board(struct pci_dev *pdev, int id)
/* get the board structure and prep it */
brd = dgnc_Board[dgnc_NumBoards] =
- (struct board_t *) kzalloc(sizeof(struct board_t), GFP_KERNEL);
+ kzalloc(sizeof(struct dgnc_board), GFP_KERNEL);
if (!brd) {
APR(("memory allocation for board structure failed\n"));
- return(-ENOMEM);
+ return -ENOMEM;
}
/* make a temporary message buffer for the boot messages */
brd->msgbuf = brd->msgbuf_head =
- (char *) kzalloc(sizeof(char) * 8192, GFP_KERNEL);
+ kzalloc(sizeof(char) * 8192, GFP_KERNEL);
if (!brd->msgbuf) {
kfree(brd);
APR(("memory allocation for board msgbuf failed\n"));
- return(-ENOMEM);
+ return -ENOMEM;
}
/* store the info for the board we've found */
@@ -663,7 +651,7 @@ static int dgnc_found_board(struct pci_dev *pdev, int id)
default:
APR(("Did not find any compatible Neo or Classic PCI boards in system.\n"));
- return (-ENXIO);
+ return -ENXIO;
}
@@ -725,22 +713,22 @@ static int dgnc_found_board(struct pci_dev *pdev, int id)
wake_up_interruptible(&brd->state_wait);
- return(0);
+ return 0;
failed:
- return (-ENXIO);
+ return -ENXIO;
}
-static int dgnc_finalize_board_init(struct board_t *brd) {
+static int dgnc_finalize_board_init(struct dgnc_board *brd) {
int rc = 0;
DPR_INIT(("dgnc_finalize_board_init() - start\n"));
if (!brd || brd->magic != DGNC_BOARD_MAGIC)
- return(-ENODEV);
+ return -ENODEV;
DPR_INIT(("dgnc_finalize_board_init() - start #2\n"));
@@ -756,13 +744,13 @@ static int dgnc_finalize_board_init(struct board_t *brd) {
DPR_INIT(("Requested and received usage of IRQ %d\n", brd->irq));
}
}
- return(rc);
+ return rc;
}
/*
* Remap PCI memory.
*/
-static void dgnc_do_remap(struct board_t *brd)
+static void dgnc_do_remap(struct dgnc_board *brd)
{
if (!brd || brd->magic != DGNC_BOARD_MAGIC)
@@ -802,7 +790,7 @@ static void dgnc_do_remap(struct board_t *brd)
static void dgnc_poll_handler(ulong dummy)
{
- struct board_t *brd;
+ struct dgnc_board *brd;
unsigned long lock_flags;
int i;
unsigned long new_time;
@@ -900,7 +888,7 @@ int dgnc_ms_sleep(ulong ms)
{
current->state = TASK_INTERRUPTIBLE;
schedule_timeout((ms * HZ) / 1000);
- return (signal_pending(current));
+ return signal_pending(current);
}
@@ -912,47 +900,47 @@ char *dgnc_ioctl_name(int cmd)
{
switch(cmd) {
- case TCGETA: return("TCGETA");
- case TCGETS: return("TCGETS");
- case TCSETA: return("TCSETA");
- case TCSETS: return("TCSETS");
- case TCSETAW: return("TCSETAW");
- case TCSETSW: return("TCSETSW");
- case TCSETAF: return("TCSETAF");
- case TCSETSF: return("TCSETSF");
- case TCSBRK: return("TCSBRK");
- case TCXONC: return("TCXONC");
- case TCFLSH: return("TCFLSH");
- case TIOCGSID: return("TIOCGSID");
-
- case TIOCGETD: return("TIOCGETD");
- case TIOCSETD: return("TIOCSETD");
- case TIOCGWINSZ: return("TIOCGWINSZ");
- case TIOCSWINSZ: return("TIOCSWINSZ");
-
- case TIOCMGET: return("TIOCMGET");
- case TIOCMSET: return("TIOCMSET");
- case TIOCMBIS: return("TIOCMBIS");
- case TIOCMBIC: return("TIOCMBIC");
+ case TCGETA: return "TCGETA";
+ case TCGETS: return "TCGETS";
+ case TCSETA: return "TCSETA";
+ case TCSETS: return "TCSETS";
+ case TCSETAW: return "TCSETAW";
+ case TCSETSW: return "TCSETSW";
+ case TCSETAF: return "TCSETAF";
+ case TCSETSF: return "TCSETSF";
+ case TCSBRK: return "TCSBRK";
+ case TCXONC: return "TCXONC";
+ case TCFLSH: return "TCFLSH";
+ case TIOCGSID: return "TIOCGSID";
+
+ case TIOCGETD: return "TIOCGETD";
+ case TIOCSETD: return "TIOCSETD";
+ case TIOCGWINSZ: return "TIOCGWINSZ";
+ case TIOCSWINSZ: return "TIOCSWINSZ";
+
+ case TIOCMGET: return "TIOCMGET";
+ case TIOCMSET: return "TIOCMSET";
+ case TIOCMBIS: return "TIOCMBIS";
+ case TIOCMBIC: return "TIOCMBIC";
/* from digi.h */
- case DIGI_SETA: return("DIGI_SETA");
- case DIGI_SETAW: return("DIGI_SETAW");
- case DIGI_SETAF: return("DIGI_SETAF");
- case DIGI_SETFLOW: return("DIGI_SETFLOW");
- case DIGI_SETAFLOW: return("DIGI_SETAFLOW");
- case DIGI_GETFLOW: return("DIGI_GETFLOW");
- case DIGI_GETAFLOW: return("DIGI_GETAFLOW");
- case DIGI_GETA: return("DIGI_GETA");
- case DIGI_GEDELAY: return("DIGI_GEDELAY");
- case DIGI_SEDELAY: return("DIGI_SEDELAY");
- case DIGI_GETCUSTOMBAUD: return("DIGI_GETCUSTOMBAUD");
- case DIGI_SETCUSTOMBAUD: return("DIGI_SETCUSTOMBAUD");
- case TIOCMODG: return("TIOCMODG");
- case TIOCMODS: return("TIOCMODS");
- case TIOCSDTR: return("TIOCSDTR");
- case TIOCCDTR: return("TIOCCDTR");
-
- default: return("unknown");
+ case DIGI_SETA: return "DIGI_SETA";
+ case DIGI_SETAW: return "DIGI_SETAW";
+ case DIGI_SETAF: return "DIGI_SETAF";
+ case DIGI_SETFLOW: return "DIGI_SETFLOW";
+ case DIGI_SETAFLOW: return "DIGI_SETAFLOW";
+ case DIGI_GETFLOW: return "DIGI_GETFLOW";
+ case DIGI_GETAFLOW: return "DIGI_GETAFLOW";
+ case DIGI_GETA: return "DIGI_GETA";
+ case DIGI_GEDELAY: return "DIGI_GEDELAY";
+ case DIGI_SEDELAY: return "DIGI_SEDELAY";
+ case DIGI_GETCUSTOMBAUD: return "DIGI_GETCUSTOMBAUD";
+ case DIGI_SETCUSTOMBAUD: return "DIGI_SETCUSTOMBAUD";
+ case TIOCMODG: return "TIOCMODG";
+ case TIOCMODS: return "TIOCMODS";
+ case TIOCSDTR: return "TIOCSDTR";
+ case TIOCCDTR: return "TIOCCDTR";
+
+ default: return "unknown";
}
}
diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h
index 218b15dccb7d..3519b803e753 100644
--- a/drivers/staging/dgnc/dgnc_driver.h
+++ b/drivers/staging/dgnc/dgnc_driver.h
@@ -45,7 +45,7 @@
/*
* Driver identification, error and debugging statments
*
- * In theory, you can change all occurances of "digi" in the next
+ * In theory, you can change all occurrences of "digi" in the next
* three lines, and the driver printk's will all automagically change.
*
* APR((fmt, args, ...)); Always prints message
@@ -246,7 +246,7 @@ enum {
*
*************************************************************************/
-struct board_t;
+struct dgnc_board;
struct channel_t;
/************************************************************************
@@ -259,7 +259,7 @@ struct board_ops {
void (*uart_off) (struct channel_t *ch);
int (*drain) (struct tty_struct *tty, uint seconds);
void (*param) (struct tty_struct *tty);
- void (*vpd) (struct board_t *brd);
+ void (*vpd) (struct dgnc_board *brd);
void (*assert_modem_signals) (struct channel_t *ch);
void (*flush_uart_write) (struct channel_t *ch);
void (*flush_uart_read) (struct channel_t *ch);
@@ -282,7 +282,7 @@ struct board_ops {
/*
* Per-board information
*/
-struct board_t {
+struct dgnc_board {
int magic; /* Board Magic number. */
int boardnum; /* Board number: 0-32 */
@@ -449,7 +449,7 @@ struct un_t {
************************************************************************/
struct channel_t {
int magic; /* Channel Magic Number */
- struct board_t *ch_bd; /* Board structure pointer */
+ struct dgnc_board *ch_bd; /* Board structure pointer */
struct digi_t ch_digi; /* Transparent Print structure */
struct un_t ch_tun; /* Terminal unit info */
struct un_t ch_pun; /* Printer unit info */
@@ -555,7 +555,7 @@ extern int dgnc_poll_tick; /* Poll interval - 20 ms */
extern int dgnc_trcbuf_size; /* Size of the ringbuffer */
extern spinlock_t dgnc_global_lock; /* Driver global spinlock */
extern uint dgnc_NumBoards; /* Total number of boards */
-extern struct board_t *dgnc_Board[MAXBOARDS]; /* Array of board structs */
+extern struct dgnc_board *dgnc_Board[MAXBOARDS]; /* Array of board structs */
extern ulong dgnc_poll_counter; /* Times the poller has run */
extern char *dgnc_state_text[]; /* Array of state text */
extern char *dgnc_driver_state_text[];/* Array of driver state text */
diff --git a/drivers/staging/dgnc/dgnc_kcompat.h b/drivers/staging/dgnc/dgnc_kcompat.h
index 00f589a13ab9..ed85152b0534 100644
--- a/drivers/staging/dgnc/dgnc_kcompat.h
+++ b/drivers/staging/dgnc/dgnc_kcompat.h
@@ -28,8 +28,6 @@
#ifndef __DGNC_KCOMPAT_H
#define __DGNC_KCOMPAT_H
-#include <linux/version.h>
-
# ifndef KERNEL_VERSION
# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
# endif
@@ -68,26 +66,4 @@
module_param(VAR, long, PERM); \
MODULE_PARM_DESC(VAR, DESC);
-
-
-
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
-
-
-
-/* NOTHING YET */
-
-
-
-# else
-
-
-
-# error "this driver does not support anything below the 2.6.27 kernel series."
-
-
-
-# endif
-
#endif /* ! __DGNC_KCOMPAT_H */
diff --git a/drivers/staging/dgnc/dgnc_mgmt.c b/drivers/staging/dgnc/dgnc_mgmt.c
index c4629d7c80b2..bb39f5dfa043 100644
--- a/drivers/staging/dgnc/dgnc_mgmt.c
+++ b/drivers/staging/dgnc/dgnc_mgmt.c
@@ -74,13 +74,13 @@ int dgnc_mgmt_open(struct inode *inode, struct file *file)
/* Only allow 1 open at a time on mgmt device */
if (dgnc_mgmt_in_use[minor]) {
DGNC_UNLOCK(dgnc_global_lock, lock_flags);
- return (-EBUSY);
+ return -EBUSY;
}
dgnc_mgmt_in_use[minor]++;
}
else {
DGNC_UNLOCK(dgnc_global_lock, lock_flags);
- return (-ENXIO);
+ return -ENXIO;
}
DGNC_UNLOCK(dgnc_global_lock, lock_flags);
@@ -154,7 +154,7 @@ long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ddi.dinfo_nboards, ddi.dinfo_version));
if (copy_to_user(uarg, &ddi, sizeof (ddi)))
- return(-EFAULT);
+ return -EFAULT;
break;
}
@@ -166,13 +166,13 @@ long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct digi_info di;
if (copy_from_user(&brd, uarg, sizeof(int))) {
- return(-EFAULT);
+ return -EFAULT;
}
DPR_MGMT(("DIGI_GETBD asking about board: %d\n", brd));
if ((brd < 0) || (brd > dgnc_NumBoards) || (dgnc_NumBoards == 0))
- return (-ENODEV);
+ return -ENODEV;
memset(&di, 0, sizeof(di));
@@ -196,7 +196,7 @@ long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
di.info_bdtype, di.info_bdstate, di.info_nports, di.info_physsize));
if (copy_to_user(uarg, &di, sizeof (di)))
- return (-EFAULT);
+ return -EFAULT;
break;
}
@@ -210,7 +210,7 @@ long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
uint channel = 0;
if (copy_from_user(&ni, uarg, sizeof(struct ni_info))) {
- return(-EFAULT);
+ return -EFAULT;
}
DPR_MGMT(("DIGI_GETBD asking about board: %d channel: %d\n",
@@ -221,16 +221,16 @@ long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
/* Verify boundaries on board */
if ((board < 0) || (board > dgnc_NumBoards) || (dgnc_NumBoards == 0))
- return (-ENODEV);
+ return -ENODEV;
/* Verify boundaries on channel */
if ((channel < 0) || (channel > dgnc_Board[board]->nasync))
- return (-ENODEV);
+ return -ENODEV;
ch = dgnc_Board[board]->channels[channel];
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (-ENODEV);
+ return -ENODEV;
memset(&ni, 0, sizeof(ni));
ni.board = board;
@@ -291,7 +291,7 @@ long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
DGNC_UNLOCK(ch->ch_lock, lock_flags);
if (copy_to_user(uarg, &ni, sizeof(ni)))
- return (-EFAULT);
+ return -EFAULT;
break;
}
diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c
index 8b9e09a83f75..0e2a5e144cfe 100644
--- a/drivers/staging/dgnc/dgnc_neo.c
+++ b/drivers/staging/dgnc/dgnc_neo.c
@@ -43,8 +43,8 @@
#include "dgnc_tty.h"
#include "dgnc_trace.h"
-static inline void neo_parse_lsr(struct board_t *brd, uint port);
-static inline void neo_parse_isr(struct board_t *brd, uint port);
+static inline void neo_parse_lsr(struct dgnc_board *brd, uint port);
+static inline void neo_parse_isr(struct dgnc_board *brd, uint port);
static void neo_copy_data_from_uart_to_queue(struct channel_t *ch);
static inline void neo_clear_break(struct channel_t *ch, int force);
static inline void neo_set_cts_flow_control(struct channel_t *ch);
@@ -56,7 +56,7 @@ static inline void neo_set_no_input_flow_control(struct channel_t *ch);
static inline void neo_set_new_start_stop_chars(struct channel_t *ch);
static void neo_parse_modem(struct channel_t *ch, uchar signals);
static void neo_tasklet(unsigned long data);
-static void neo_vpd(struct board_t *brd);
+static void neo_vpd(struct dgnc_board *brd);
static void neo_uart_init(struct channel_t *ch);
static void neo_uart_off(struct channel_t *ch);
static int neo_drain(struct tty_struct *tty, uint seconds);
@@ -107,7 +107,7 @@ static uint dgnc_offset_table[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0
* In this case, we are reading the DVID (Read-only Device Identification)
* value of the Neo card.
*/
-static inline void neo_pci_posting_flush(struct board_t *bd)
+static inline void neo_pci_posting_flush(struct dgnc_board *bd)
{
readb(bd->re_map_membase + 0x8D);
}
@@ -411,7 +411,7 @@ static inline void neo_clear_break(struct channel_t *ch, int force)
/*
* Parse the ISR register.
*/
-static inline void neo_parse_isr(struct board_t *brd, uint port)
+static inline void neo_parse_isr(struct dgnc_board *brd, uint port)
{
struct channel_t *ch;
uchar isr;
@@ -538,7 +538,7 @@ static inline void neo_parse_isr(struct board_t *brd, uint port)
}
-static inline void neo_parse_lsr(struct board_t *brd, uint port)
+static inline void neo_parse_lsr(struct dgnc_board *brd, uint port)
{
struct channel_t *ch;
int linestatus;
@@ -650,7 +650,7 @@ static void neo_param(struct tty_struct *tty)
uchar uart_ier = 0;
uint baud = 9600;
int quot = 0;
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
@@ -911,7 +911,7 @@ static void neo_param(struct tty_struct *tty)
*/
static void neo_tasklet(unsigned long data)
{
- struct board_t *bd = (struct board_t *) data;
+ struct dgnc_board *bd = (struct dgnc_board *) data;
struct channel_t *ch;
ulong lock_flags;
int i;
@@ -994,7 +994,7 @@ static void neo_tasklet(unsigned long data)
*/
static irqreturn_t neo_intr(int irq, void *voidbrd)
{
- struct board_t *brd = (struct board_t *) voidbrd;
+ struct dgnc_board *brd = (struct dgnc_board *) voidbrd;
struct channel_t *ch;
int port = 0;
int type = 0;
@@ -1111,7 +1111,7 @@ static irqreturn_t neo_intr(int irq, void *voidbrd)
* Why would I check EVERY possibility of type of
* interrupt, when we know its TXRDY???
* Becuz for some reason, even tho we got triggered for TXRDY,
- * it seems to be occassionally wrong. Instead of TX, which
+ * it seems to be occasionally wrong. Instead of TX, which
* it should be, I was getting things like RXDY too. Weird.
*/
neo_parse_isr(brd, port);
@@ -1404,17 +1404,17 @@ static int neo_drain(struct tty_struct *tty, uint seconds)
int rc = 0;
if (!tty || tty->magic != TTY_MAGIC) {
- return (-ENXIO);
+ return -ENXIO;
}
un = (struct un_t *) tty->driver_data;
if (!un || un->magic != DGNC_UNIT_MAGIC) {
- return (-ENXIO);
+ return -ENXIO;
}
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
- return (-ENXIO);
+ return -ENXIO;
}
DPR_IOCTL(("%d Drain wait started.\n", __LINE__));
@@ -1439,7 +1439,7 @@ static int neo_drain(struct tty_struct *tty, uint seconds)
DPR_IOCTL(("%d Drain wait finished.\n", __LINE__));
}
- return (rc);
+ return rc;
}
@@ -1939,7 +1939,7 @@ static unsigned int neo_read_eeprom(unsigned char __iomem *base, unsigned int ad
}
-static void neo_vpd(struct board_t *brd)
+static void neo_vpd(struct dgnc_board *brd)
{
unsigned int i = 0;
unsigned int a;
diff --git a/drivers/staging/dgnc/dgnc_neo.h b/drivers/staging/dgnc/dgnc_neo.h
index 7ec5710a4340..1a4abb128693 100644
--- a/drivers/staging/dgnc/dgnc_neo.h
+++ b/drivers/staging/dgnc/dgnc_neo.h
@@ -47,7 +47,7 @@ struct neo_uart_struct {
u8 fctr; /* WR FCTR - Feature Control Reg */
u8 efr; /* WR EFR - Enhanced Function Reg */
u8 tfifo; /* WR TXCNT/TXTRG - Transmit FIFO Reg */
- u8 rfifo; /* WR RXCNT/RXTRG - Recieve FIFO Reg */
+ u8 rfifo; /* WR RXCNT/RXTRG - Receive FIFO Reg */
u8 xoffchar1; /* WR XOFF 1 - XOff Character 1 Reg */
u8 xoffchar2; /* WR XOFF 2 - XOff Character 2 Reg */
u8 xonchar1; /* WR XON 1 - Xon Character 1 Reg */
diff --git a/drivers/staging/dgnc/dgnc_sysfs.c b/drivers/staging/dgnc/dgnc_sysfs.c
index 0ea6c8002805..946230c23487 100644
--- a/drivers/staging/dgnc/dgnc_sysfs.c
+++ b/drivers/staging/dgnc/dgnc_sysfs.c
@@ -152,19 +152,19 @@ void dgnc_remove_driver_sysfiles(struct pci_driver *dgnc_driver)
#define DGNC_VERIFY_BOARD(p, bd) \
if (!p) \
- return (0); \
+ return 0; \
\
bd = dev_get_drvdata(p); \
if (!bd || bd->magic != DGNC_BOARD_MAGIC) \
- return (0); \
+ return 0; \
if (bd->state != BOARD_READY) \
- return (0); \
+ return 0; \
static ssize_t dgnc_vpd_show(struct device *p, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
int count = 0;
int i = 0;
@@ -184,7 +184,7 @@ static DEVICE_ATTR(vpd, S_IRUSR, dgnc_vpd_show, NULL);
static ssize_t dgnc_serial_number_show(struct device *p, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
int count = 0;
DGNC_VERIFY_BOARD(p, bd);
@@ -201,7 +201,7 @@ static DEVICE_ATTR(serial_number, S_IRUSR, dgnc_serial_number_show, NULL);
static ssize_t dgnc_ports_state_show(struct device *p, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
int count = 0;
int i = 0;
@@ -219,7 +219,7 @@ static DEVICE_ATTR(ports_state, S_IRUSR, dgnc_ports_state_show, NULL);
static ssize_t dgnc_ports_baud_show(struct device *p, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
int count = 0;
int i = 0;
@@ -236,7 +236,7 @@ static DEVICE_ATTR(ports_baud, S_IRUSR, dgnc_ports_baud_show, NULL);
static ssize_t dgnc_ports_msignals_show(struct device *p, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
int count = 0;
int i = 0;
@@ -264,7 +264,7 @@ static DEVICE_ATTR(ports_msignals, S_IRUSR, dgnc_ports_msignals_show, NULL);
static ssize_t dgnc_ports_iflag_show(struct device *p, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
int count = 0;
int i = 0;
@@ -281,7 +281,7 @@ static DEVICE_ATTR(ports_iflag, S_IRUSR, dgnc_ports_iflag_show, NULL);
static ssize_t dgnc_ports_cflag_show(struct device *p, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
int count = 0;
int i = 0;
@@ -298,7 +298,7 @@ static DEVICE_ATTR(ports_cflag, S_IRUSR, dgnc_ports_cflag_show, NULL);
static ssize_t dgnc_ports_oflag_show(struct device *p, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
int count = 0;
int i = 0;
@@ -315,7 +315,7 @@ static DEVICE_ATTR(ports_oflag, S_IRUSR, dgnc_ports_oflag_show, NULL);
static ssize_t dgnc_ports_lflag_show(struct device *p, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
int count = 0;
int i = 0;
@@ -332,7 +332,7 @@ static DEVICE_ATTR(ports_lflag, S_IRUSR, dgnc_ports_lflag_show, NULL);
static ssize_t dgnc_ports_digi_flag_show(struct device *p, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
int count = 0;
int i = 0;
@@ -349,7 +349,7 @@ static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgnc_ports_digi_flag_show, NULL);
static ssize_t dgnc_ports_rxcount_show(struct device *p, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
int count = 0;
int i = 0;
@@ -366,7 +366,7 @@ static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgnc_ports_rxcount_show, NULL);
static ssize_t dgnc_ports_txcount_show(struct device *p, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
int count = 0;
int i = 0;
@@ -384,7 +384,7 @@ static DEVICE_ATTR(ports_txcount, S_IRUSR, dgnc_ports_txcount_show, NULL);
/* this function creates the sys files that will export each signal status
* to sysfs each value will be put in a separate filename
*/
-void dgnc_create_ports_sysfiles(struct board_t *bd)
+void dgnc_create_ports_sysfiles(struct dgnc_board *bd)
{
int rc = 0;
@@ -408,7 +408,7 @@ void dgnc_create_ports_sysfiles(struct board_t *bd)
/* removes all the sys files created for that port */
-void dgnc_remove_ports_sysfiles(struct board_t *bd)
+void dgnc_remove_ports_sysfiles(struct dgnc_board *bd)
{
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_state);
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_baud);
@@ -427,23 +427,23 @@ void dgnc_remove_ports_sysfiles(struct board_t *bd)
static ssize_t dgnc_tty_state_show(struct device *d, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
- return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ return 0;
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return (0);
+ return 0;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (0);
+ return 0;
bd = ch->ch_bd;
if (!bd || bd->magic != DGNC_BOARD_MAGIC)
- return (0);
+ return 0;
if (bd->state != BOARD_READY)
- return (0);
+ return 0;
return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? "Open" : "Closed");
}
@@ -452,23 +452,23 @@ static DEVICE_ATTR(state, S_IRUSR, dgnc_tty_state_show, NULL);
static ssize_t dgnc_tty_baud_show(struct device *d, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
- return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ return 0;
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return (0);
+ return 0;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (0);
+ return 0;
bd = ch->ch_bd;
if (!bd || bd->magic != DGNC_BOARD_MAGIC)
- return (0);
+ return 0;
if (bd->state != BOARD_READY)
- return (0);
+ return 0;
return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_old_baud);
}
@@ -477,23 +477,23 @@ static DEVICE_ATTR(baud, S_IRUSR, dgnc_tty_baud_show, NULL);
static ssize_t dgnc_tty_msignals_show(struct device *d, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
- return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ return 0;
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return (0);
+ return 0;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (0);
+ return 0;
bd = ch->ch_bd;
if (!bd || bd->magic != DGNC_BOARD_MAGIC)
- return (0);
+ return 0;
if (bd->state != BOARD_READY)
- return (0);
+ return 0;
if (ch->ch_open_count) {
return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
@@ -511,23 +511,23 @@ static DEVICE_ATTR(msignals, S_IRUSR, dgnc_tty_msignals_show, NULL);
static ssize_t dgnc_tty_iflag_show(struct device *d, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
- return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ return 0;
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return (0);
+ return 0;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (0);
+ return 0;
bd = ch->ch_bd;
if (!bd || bd->magic != DGNC_BOARD_MAGIC)
- return (0);
+ return 0;
if (bd->state != BOARD_READY)
- return (0);
+ return 0;
return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag);
}
@@ -536,23 +536,23 @@ static DEVICE_ATTR(iflag, S_IRUSR, dgnc_tty_iflag_show, NULL);
static ssize_t dgnc_tty_cflag_show(struct device *d, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
- return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ return 0;
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return (0);
+ return 0;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (0);
+ return 0;
bd = ch->ch_bd;
if (!bd || bd->magic != DGNC_BOARD_MAGIC)
- return (0);
+ return 0;
if (bd->state != BOARD_READY)
- return (0);
+ return 0;
return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag);
}
@@ -561,23 +561,23 @@ static DEVICE_ATTR(cflag, S_IRUSR, dgnc_tty_cflag_show, NULL);
static ssize_t dgnc_tty_oflag_show(struct device *d, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
- return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ return 0;
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return (0);
+ return 0;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (0);
+ return 0;
bd = ch->ch_bd;
if (!bd || bd->magic != DGNC_BOARD_MAGIC)
- return (0);
+ return 0;
if (bd->state != BOARD_READY)
- return (0);
+ return 0;
return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag);
}
@@ -586,23 +586,23 @@ static DEVICE_ATTR(oflag, S_IRUSR, dgnc_tty_oflag_show, NULL);
static ssize_t dgnc_tty_lflag_show(struct device *d, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
- return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ return 0;
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return (0);
+ return 0;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (0);
+ return 0;
bd = ch->ch_bd;
if (!bd || bd->magic != DGNC_BOARD_MAGIC)
- return (0);
+ return 0;
if (bd->state != BOARD_READY)
- return (0);
+ return 0;
return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag);
}
@@ -611,23 +611,23 @@ static DEVICE_ATTR(lflag, S_IRUSR, dgnc_tty_lflag_show, NULL);
static ssize_t dgnc_tty_digi_flag_show(struct device *d, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
- return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ return 0;
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return (0);
+ return 0;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (0);
+ return 0;
bd = ch->ch_bd;
if (!bd || bd->magic != DGNC_BOARD_MAGIC)
- return (0);
+ return 0;
if (bd->state != BOARD_READY)
- return (0);
+ return 0;
return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
}
@@ -636,23 +636,23 @@ static DEVICE_ATTR(digi_flag, S_IRUSR, dgnc_tty_digi_flag_show, NULL);
static ssize_t dgnc_tty_rxcount_show(struct device *d, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
- return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ return 0;
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return (0);
+ return 0;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (0);
+ return 0;
bd = ch->ch_bd;
if (!bd || bd->magic != DGNC_BOARD_MAGIC)
- return (0);
+ return 0;
if (bd->state != BOARD_READY)
- return (0);
+ return 0;
return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount);
}
@@ -661,23 +661,23 @@ static DEVICE_ATTR(rxcount, S_IRUSR, dgnc_tty_rxcount_show, NULL);
static ssize_t dgnc_tty_txcount_show(struct device *d, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
- return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ return 0;
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return (0);
+ return 0;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (0);
+ return 0;
bd = ch->ch_bd;
if (!bd || bd->magic != DGNC_BOARD_MAGIC)
- return (0);
+ return 0;
if (bd->state != BOARD_READY)
- return (0);
+ return 0;
return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount);
}
@@ -686,23 +686,23 @@ static DEVICE_ATTR(txcount, S_IRUSR, dgnc_tty_txcount_show, NULL);
static ssize_t dgnc_tty_name_show(struct device *d, struct device_attribute *attr, char *buf)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
if (!d)
- return (0);
- un = (struct un_t *) dev_get_drvdata(d);
+ return 0;
+ un = dev_get_drvdata(d);
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return (0);
+ return 0;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (0);
+ return 0;
bd = ch->ch_bd;
if (!bd || bd->magic != DGNC_BOARD_MAGIC)
- return (0);
+ return 0;
if (bd->state != BOARD_READY)
- return (0);
+ return 0;
return snprintf(buf, PAGE_SIZE, "%sn%d%c\n",
(un->un_type == DGNC_PRINT) ? "pr" : "tty",
diff --git a/drivers/staging/dgnc/dgnc_sysfs.h b/drivers/staging/dgnc/dgnc_sysfs.h
index 4b87ce1cc7a2..68c0de5898a4 100644
--- a/drivers/staging/dgnc/dgnc_sysfs.h
+++ b/drivers/staging/dgnc/dgnc_sysfs.h
@@ -26,14 +26,14 @@
#include <linux/device.h>
-struct board_t;
+struct dgnc_board;
struct channel_t;
struct un_t;
struct pci_driver;
struct class_device;
-extern void dgnc_create_ports_sysfiles(struct board_t *bd);
-extern void dgnc_remove_ports_sysfiles(struct board_t *bd);
+extern void dgnc_create_ports_sysfiles(struct dgnc_board *bd);
+extern void dgnc_remove_ports_sysfiles(struct dgnc_board *bd);
extern void dgnc_create_driver_sysfiles(struct pci_driver *);
extern void dgnc_remove_driver_sysfiles(struct pci_driver *);
diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c
index a7bb6bceb9e7..1350d6266524 100644
--- a/drivers/staging/dgnc/dgnc_tty.c
+++ b/drivers/staging/dgnc/dgnc_tty.c
@@ -38,7 +38,6 @@
*/
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/sched.h> /* For jiffies, task states */
#include <linux/interrupt.h> /* For tasklet and interrupt structs/defines */
#include <linux/module.h>
@@ -60,16 +59,14 @@
#include "dpacompat.h"
#include "dgnc_sysfs.h"
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
#define init_MUTEX(sem) sema_init(sem, 1)
#define DECLARE_MUTEX(name) \
struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
-#endif
/*
* internal variables
*/
-static struct board_t *dgnc_BoardsByMajor[256];
+static struct dgnc_board *dgnc_BoardsByMajor[256];
static uchar *dgnc_TmpWriteBuf = NULL;
static DECLARE_MUTEX(dgnc_TmpWriteSem);
@@ -126,13 +123,8 @@ static void dgnc_tty_flush_buffer(struct tty_struct *tty);
static void dgnc_tty_hangup(struct tty_struct *tty);
static int dgnc_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value);
static int dgnc_get_modem_info(struct channel_t *ch, unsigned int __user *value);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
static int dgnc_tty_tiocmget(struct tty_struct *tty);
static int dgnc_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear);
-#else
-static int dgnc_tty_tiocmget(struct tty_struct *tty, struct file *file);
-static int dgnc_tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear);
-#endif
static int dgnc_tty_send_break(struct tty_struct *tty, int msec);
static void dgnc_tty_wait_until_sent(struct tty_struct *tty, int timeout);
static int dgnc_tty_write(struct tty_struct *tty, const unsigned char *buf, int count);
@@ -190,10 +182,10 @@ int dgnc_tty_preinit(void)
if (!dgnc_TmpWriteBuf) {
DPR_INIT(("unable to allocate tmp write buf"));
- return (-ENOMEM);
+ return -ENOMEM;
}
- return(0);
+ return 0;
}
@@ -202,7 +194,7 @@ int dgnc_tty_preinit(void)
*
* Init the tty subsystem for this board.
*/
-int dgnc_tty_register(struct board_t *brd)
+int dgnc_tty_register(struct dgnc_board *brd)
{
int rc = 0;
@@ -232,23 +224,13 @@ int dgnc_tty_register(struct board_t *brd)
*/
brd->SerialDriver.ttys = kzalloc(brd->maxports * sizeof(struct tty_struct *), GFP_KERNEL);
if (!brd->SerialDriver.ttys)
- return(-ENOMEM);
+ return -ENOMEM;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
- brd->SerialDriver.refcount = brd->TtyRefCnt;
-#else
kref_init(&brd->SerialDriver.kref);
-#endif
-
brd->SerialDriver.termios = kzalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
if (!brd->SerialDriver.termios)
- return(-ENOMEM);
+ return -ENOMEM;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
- brd->SerialDriver.termios_locked = kzalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
- if (!brd->SerialDriver.termios_locked)
- return(-ENOMEM);
-#endif
/*
* Entry points for driver. Called by the kernel from
* tty_io.c and n_tty.c.
@@ -260,14 +242,14 @@ int dgnc_tty_register(struct board_t *brd)
rc = tty_register_driver(&brd->SerialDriver);
if (rc < 0) {
APR(("Can't register tty device (%d)\n", rc));
- return(rc);
+ return rc;
}
brd->dgnc_Major_Serial_Registered = TRUE;
}
/*
* If we're doing transparent print, we have to do all of the above
- * again, seperately so we don't get the LD confused about what major
+ * again, separately so we don't get the LD confused about what major
* we are when we get into the dgnc_tty_open() routine.
*/
brd->PrintDriver.magic = TTY_DRIVER_MAGIC;
@@ -286,28 +268,16 @@ int dgnc_tty_register(struct board_t *brd)
/*
* The kernel wants space to store pointers to
- * tty_struct's and termios's. Must be seperate from
+ * tty_struct's and termios's. Must be separated from
* the Serial Driver so we don't get confused
*/
brd->PrintDriver.ttys = kzalloc(brd->maxports * sizeof(struct tty_struct *), GFP_KERNEL);
if (!brd->PrintDriver.ttys)
- return(-ENOMEM);
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
- brd->PrintDriver.refcount = brd->TtyRefCnt;
-#else
+ return -ENOMEM;
kref_init(&brd->PrintDriver.kref);
-#endif
-
brd->PrintDriver.termios = kzalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
if (!brd->PrintDriver.termios)
- return(-ENOMEM);
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
- brd->PrintDriver.termios_locked = kzalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
- if (!brd->PrintDriver.termios_locked)
- return(-ENOMEM);
-#endif
+ return -ENOMEM;
/*
* Entry points for driver. Called by the kernel from
@@ -320,7 +290,7 @@ int dgnc_tty_register(struct board_t *brd)
rc = tty_register_driver(&brd->PrintDriver);
if (rc < 0) {
APR(("Can't register Transparent Print device (%d)\n", rc));
- return(rc);
+ return rc;
}
brd->dgnc_Major_TransparentPrint_Registered = TRUE;
}
@@ -331,7 +301,7 @@ int dgnc_tty_register(struct board_t *brd)
DPR_INIT(("DGNC REGISTER TTY: MAJOR: %d\n", brd->SerialDriver.major));
- return (rc);
+ return rc;
}
@@ -341,14 +311,14 @@ int dgnc_tty_register(struct board_t *brd)
* Init the tty subsystem. Called once per board after board has been
* downloaded and init'ed.
*/
-int dgnc_tty_init(struct board_t *brd)
+int dgnc_tty_init(struct dgnc_board *brd)
{
int i;
void __iomem *vaddr;
struct channel_t *ch;
if (!brd)
- return (-ENXIO);
+ return -ENXIO;
DPR_INIT(("dgnc_tty_init start\n"));
@@ -436,7 +406,7 @@ int dgnc_tty_init(struct board_t *brd)
DPR_INIT(("dgnc_tty_init finish\n"));
- return (0);
+ return 0;
}
@@ -460,7 +430,7 @@ void dgnc_tty_post_uninit(void)
* Uninitialize the TTY portion of this driver. Free all memory and
* resources.
*/
-void dgnc_tty_uninit(struct board_t *brd)
+void dgnc_tty_uninit(struct dgnc_board *brd)
{
int i = 0;
@@ -671,7 +641,7 @@ static void dgnc_wmove(struct channel_t *ch, char *buf, uint n)
*=======================================================================*/
void dgnc_input(struct channel_t *ch)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct tty_struct *tp;
struct tty_ldisc *ld;
uint rmask;
@@ -867,7 +837,7 @@ void dgnc_input(struct channel_t *ch)
************************************************************************/
void dgnc_carrier(struct channel_t *ch)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
int virt_carrier = 0;
int phys_carrier = 0;
@@ -1158,7 +1128,6 @@ void dgnc_wakeup_writes(struct channel_t *ch)
}
if (ch->ch_tun.un_flags & UN_ISOPEN) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
if ((ch->ch_tun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
ch->ch_tun.un_tty->ldisc->ops->write_wakeup)
{
@@ -1166,15 +1135,6 @@ void dgnc_wakeup_writes(struct channel_t *ch)
(ch->ch_tun.un_tty->ldisc->ops->write_wakeup)(ch->ch_tun.un_tty);
DGNC_LOCK(ch->ch_lock, lock_flags);
}
-#else
- if ((ch->ch_tun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- ch->ch_tun.un_tty->ldisc.ops->write_wakeup)
- {
- DGNC_UNLOCK(ch->ch_lock, lock_flags);
- (ch->ch_tun.un_tty->ldisc.ops->write_wakeup)(ch->ch_tun.un_tty);
- DGNC_LOCK(ch->ch_lock, lock_flags);
- }
-#endif
wake_up_interruptible(&ch->ch_tun.un_tty->write_wait);
@@ -1210,7 +1170,6 @@ void dgnc_wakeup_writes(struct channel_t *ch)
}
if (ch->ch_pun.un_flags & UN_ISOPEN) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
if ((ch->ch_pun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
ch->ch_pun.un_tty->ldisc->ops->write_wakeup)
{
@@ -1218,15 +1177,6 @@ void dgnc_wakeup_writes(struct channel_t *ch)
(ch->ch_pun.un_tty->ldisc->ops->write_wakeup)(ch->ch_pun.un_tty);
DGNC_LOCK(ch->ch_lock, lock_flags);
}
-#else
- if ((ch->ch_pun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- ch->ch_pun.un_tty->ldisc.ops->write_wakeup)
- {
- DGNC_UNLOCK(ch->ch_lock, lock_flags);
- (ch->ch_pun.un_tty->ldisc.ops->write_wakeup)(ch->ch_pun.un_tty);
- DGNC_LOCK(ch->ch_lock, lock_flags);
- }
-#endif
wake_up_interruptible(&ch->ch_pun.un_tty->write_wait);
@@ -1260,7 +1210,7 @@ void dgnc_wakeup_writes(struct channel_t *ch)
*/
static int dgnc_tty_open(struct tty_struct *tty, struct file *file)
{
- struct board_t *brd;
+ struct dgnc_board *brd;
struct channel_t *ch;
struct un_t *un;
uint major = 0;
@@ -1473,7 +1423,7 @@ static int dgnc_tty_open(struct tty_struct *tty, struct file *file)
DGNC_UNLOCK(ch->ch_lock, lock_flags);
DPR_OPEN(("dgnc_tty_open finished\n"));
- return (rc);
+ return rc;
}
@@ -1491,12 +1441,12 @@ static int dgnc_block_til_ready(struct tty_struct *tty, struct file *file, struc
int sleep_on_un_flags = 0;
if (!tty || tty->magic != TTY_MAGIC || !file || !ch || ch->magic != DGNC_CHANNEL_MAGIC) {
- return (-ENXIO);
+ return -ENXIO;
}
un = tty->driver_data;
if (!un || un->magic != DGNC_UNIT_MAGIC) {
- return (-ENXIO);
+ return -ENXIO;
}
DPR_OPEN(("dgnc_block_til_ready - before block.\n"));
@@ -1624,12 +1574,12 @@ static int dgnc_block_til_ready(struct tty_struct *tty, struct file *file, struc
if (retval) {
DPR_OPEN(("dgnc_block_til_ready - done. error. retval: %x\n", retval));
- return(retval);
+ return retval;
}
DPR_OPEN(("dgnc_block_til_ready - done no error. jiffies: %lu\n", jiffies));
- return(0);
+ return 0;
}
@@ -1667,7 +1617,7 @@ static void dgnc_tty_hangup(struct tty_struct *tty)
static void dgnc_tty_close(struct tty_struct *tty, struct file *file)
{
struct ktermios *ts;
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
ulong lock_flags;
@@ -1843,15 +1793,15 @@ static int dgnc_tty_chars_in_buffer(struct tty_struct *tty)
ulong lock_flags = 0;
if (tty == NULL)
- return(0);
+ return 0;
un = tty->driver_data;
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return (0);
+ return 0;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (0);
+ return 0;
DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -1873,7 +1823,7 @@ static int dgnc_tty_chars_in_buffer(struct tty_struct *tty)
DPR_WRITE(("dgnc_tty_chars_in_buffer. Port: %x - %d (head: %d tail: %d)\n",
ch->ch_portnum, chars, thead, ttail));
- return(chars);
+ return chars;
}
@@ -1891,22 +1841,22 @@ static int dgnc_maxcps_room(struct tty_struct *tty, int bytes_available)
struct un_t *un = NULL;
if (!tty)
- return (bytes_available);
+ return bytes_available;
un = tty->driver_data;
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return (bytes_available);
+ return bytes_available;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (bytes_available);
+ return bytes_available;
/*
* If its not the Transparent print device, return
* the full data amount.
*/
if (un->un_type != DGNC_PRINT)
- return (bytes_available);
+ return bytes_available;
if (ch->ch_digi.digi_maxcps > 0 && ch->ch_digi.digi_bufsize > 0 ) {
int cps_limit = 0;
@@ -1931,7 +1881,7 @@ static int dgnc_maxcps_room(struct tty_struct *tty, int bytes_available)
bytes_available = min(cps_limit, bytes_available);
}
- return (bytes_available);
+ return bytes_available;
}
@@ -1951,15 +1901,15 @@ static int dgnc_tty_write_room(struct tty_struct *tty)
ulong lock_flags = 0;
if (tty == NULL || dgnc_TmpWriteBuf == NULL)
- return(0);
+ return 0;
un = tty->driver_data;
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return (0);
+ return 0;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (0);
+ return 0;
DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -1994,7 +1944,7 @@ static int dgnc_tty_write_room(struct tty_struct *tty)
DPR_WRITE(("dgnc_tty_write_room - %d tail: %d head: %d\n", ret, tail, head));
- return(ret);
+ return ret;
}
@@ -2037,18 +1987,18 @@ static int dgnc_tty_write(struct tty_struct *tty,
int from_user = 0;
if (tty == NULL || dgnc_TmpWriteBuf == NULL)
- return(0);
+ return 0;
un = tty->driver_data;
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return(0);
+ return 0;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return(0);
+ return 0;
if (!count)
- return(0);
+ return 0;
DPR_WRITE(("dgnc_tty_write: Port: %x tty=%p user=%d len=%d\n",
ch->ch_portnum, tty, from_user, count));
@@ -2090,7 +2040,7 @@ static int dgnc_tty_write(struct tty_struct *tty,
*/
if (count <= 0) {
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- return(0);
+ return 0;
}
/*
@@ -2120,7 +2070,7 @@ static int dgnc_tty_write(struct tty_struct *tty,
*/
if (count <= 0) {
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- return(0);
+ return 0;
}
if (from_user) {
@@ -2136,7 +2086,7 @@ static int dgnc_tty_write(struct tty_struct *tty,
*/
/* we're allowed to block if it's from_user */
if (down_interruptible(&dgnc_TmpWriteSem)) {
- return (-EINTR);
+ return -EINTR;
}
/*
@@ -2147,7 +2097,7 @@ static int dgnc_tty_write(struct tty_struct *tty,
if (!count) {
up(&dgnc_TmpWriteSem);
- return(-EFAULT);
+ return -EFAULT;
}
DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -2229,18 +2179,15 @@ static int dgnc_tty_write(struct tty_struct *tty,
ch->ch_bd->bd_ops->copy_data_from_queue_to_uart(ch);
}
- return (count);
+ return count;
}
/*
* Return modem signals to ld.
*/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
+
static int dgnc_tty_tiocmget(struct tty_struct *tty)
-#else
-static int dgnc_tty_tiocmget(struct tty_struct *tty, struct file *file)
-#endif
{
struct channel_t *ch;
struct un_t *un;
@@ -2293,15 +2240,11 @@ static int dgnc_tty_tiocmget(struct tty_struct *tty, struct file *file)
*
* Set modem signals, called by ld.
*/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
+
static int dgnc_tty_tiocmset(struct tty_struct *tty,
unsigned int set, unsigned int clear)
-#else
-static int dgnc_tty_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear)
-#endif
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
int ret = -EIO;
@@ -2349,7 +2292,7 @@ static int dgnc_tty_tiocmset(struct tty_struct *tty, struct file *file,
DPR_IOCTL(("dgnc_tty_tiocmset finish\n"));
- return (0);
+ return 0;
}
@@ -2360,7 +2303,7 @@ static int dgnc_tty_tiocmset(struct tty_struct *tty, struct file *file,
*/
static int dgnc_tty_send_break(struct tty_struct *tty, int msec)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
int ret = -EIO;
@@ -2402,7 +2345,7 @@ static int dgnc_tty_send_break(struct tty_struct *tty, int msec)
DPR_IOCTL(("dgnc_tty_send_break finish\n"));
- return (0);
+ return 0;
}
@@ -2414,7 +2357,7 @@ static int dgnc_tty_send_break(struct tty_struct *tty, int msec)
*/
static void dgnc_tty_wait_until_sent(struct tty_struct *tty, int timeout)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
int rc;
@@ -2450,7 +2393,7 @@ static void dgnc_tty_wait_until_sent(struct tty_struct *tty, int timeout)
*/
static void dgnc_tty_send_xchar(struct tty_struct *tty, char c)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
ulong lock_flags;
@@ -2497,7 +2440,7 @@ static inline int dgnc_get_mstat(struct channel_t *ch)
DPR_IOCTL(("dgnc_getmstat start\n"));
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return(-ENXIO);
+ return -ENXIO;
DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -2522,7 +2465,7 @@ static inline int dgnc_get_mstat(struct channel_t *ch)
DPR_IOCTL(("dgnc_getmstat finish\n"));
- return(result);
+ return result;
}
@@ -2538,17 +2481,17 @@ static int dgnc_get_modem_info(struct channel_t *ch, unsigned int __user *value
DPR_IOCTL(("dgnc_get_modem_info start\n"));
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return(-ENXIO);
+ return -ENXIO;
result = dgnc_get_mstat(ch);
if (result < 0)
- return (-ENXIO);
+ return -ENXIO;
rc = put_user(result, value);
DPR_IOCTL(("dgnc_get_modem_info finish\n"));
- return(rc);
+ return rc;
}
@@ -2559,7 +2502,7 @@ static int dgnc_get_modem_info(struct channel_t *ch, unsigned int __user *value
*/
static int dgnc_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
int ret = -ENXIO;
@@ -2587,7 +2530,7 @@ static int dgnc_set_modem_info(struct tty_struct *tty, unsigned int command, uns
ret = get_user(arg, value);
if (ret)
- return(ret);
+ return ret;
switch (command) {
case TIOCMBIS:
@@ -2631,7 +2574,7 @@ static int dgnc_set_modem_info(struct tty_struct *tty, unsigned int command, uns
break;
default:
- return(-EINVAL);
+ return -EINVAL;
}
DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -2642,7 +2585,7 @@ static int dgnc_set_modem_info(struct tty_struct *tty, unsigned int command, uns
DPR_IOCTL(("dgnc_set_modem_info finish\n"));
- return (0);
+ return 0;
}
@@ -2662,18 +2605,18 @@ static int dgnc_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retin
ulong lock_flags;
if (!retinfo)
- return (-EFAULT);
+ return -EFAULT;
if (!tty || tty->magic != TTY_MAGIC)
- return (-EFAULT);
+ return -EFAULT;
un = tty->driver_data;
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return (-EFAULT);
+ return -EFAULT;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (-EFAULT);
+ return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
@@ -2682,9 +2625,9 @@ static int dgnc_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retin
DGNC_UNLOCK(ch->ch_lock, lock_flags);
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
- return (-EFAULT);
+ return -EFAULT;
- return (0);
+ return 0;
}
@@ -2698,7 +2641,7 @@ static int dgnc_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retin
*/
static int dgnc_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
struct digi_t new_digi;
@@ -2707,23 +2650,23 @@ static int dgnc_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_i
DPR_IOCTL(("DIGI_SETA start\n"));
if (!tty || tty->magic != TTY_MAGIC)
- return (-EFAULT);
+ return -EFAULT;
un = tty->driver_data;
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return (-EFAULT);
+ return -EFAULT;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (-EFAULT);
+ return -EFAULT;
bd = ch->ch_bd;
if (!bd || bd->magic != DGNC_BOARD_MAGIC)
- return (-EFAULT);
+ return -EFAULT;
if (copy_from_user(&new_digi, new_info, sizeof(struct digi_t))) {
DPR_IOCTL(("DIGI_SETA failed copy_from_user\n"));
- return(-EFAULT);
+ return -EFAULT;
}
DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -2773,7 +2716,7 @@ static int dgnc_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_i
DPR_IOCTL(("DIGI_SETA finish\n"));
- return(0);
+ return 0;
}
@@ -2782,7 +2725,7 @@ static int dgnc_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_i
*/
static void dgnc_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
unsigned long lock_flags;
@@ -2878,7 +2821,7 @@ static void dgnc_tty_unthrottle(struct tty_struct *tty)
static void dgnc_tty_start(struct tty_struct *tty)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
ulong lock_flags;
@@ -2912,7 +2855,7 @@ static void dgnc_tty_start(struct tty_struct *tty)
static void dgnc_tty_stop(struct tty_struct *tty)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
ulong lock_flags;
@@ -2959,7 +2902,7 @@ static void dgnc_tty_stop(struct tty_struct *tty)
*/
static void dgnc_tty_flush_chars(struct tty_struct *tty)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
ulong lock_flags;
@@ -3056,7 +2999,7 @@ static void dgnc_tty_flush_buffer(struct tty_struct *tty)
static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
unsigned long arg)
{
- struct board_t *bd;
+ struct dgnc_board *bd;
struct channel_t *ch;
struct un_t *un;
int rc;
@@ -3064,19 +3007,19 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
void __user *uarg = (void __user *) arg;
if (!tty || tty->magic != TTY_MAGIC)
- return (-ENODEV);
+ return -ENODEV;
un = tty->driver_data;
if (!un || un->magic != DGNC_UNIT_MAGIC)
- return (-ENODEV);
+ return -ENODEV;
ch = un->un_ch;
if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
- return (-ENODEV);
+ return -ENODEV;
bd = ch->ch_bd;
if (!bd || bd->magic != DGNC_BOARD_MAGIC)
- return (-ENODEV);
+ return -ENODEV;
DPR_IOCTL(("dgnc_tty_ioctl start on port %d - cmd %s (%x), arg %lx\n",
ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
@@ -3086,7 +3029,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
if (un->un_open_count <= 0) {
DPR_BASIC(("dgnc_tty_ioctl - unit not open.\n"));
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- return(-EIO);
+ return -EIO;
}
switch (cmd) {
@@ -3105,14 +3048,14 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
rc = tty_check_change(tty);
DGNC_UNLOCK(ch->ch_lock, lock_flags);
if (rc) {
- return(rc);
+ return rc;
}
rc = ch->ch_bd->bd_ops->drain(tty, 0);
if (rc) {
DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
- return(-EINTR);
+ return -EINTR;
}
DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -3126,7 +3069,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
- return(0);
+ return 0;
case TCSBRKP:
@@ -3138,13 +3081,13 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
rc = tty_check_change(tty);
DGNC_UNLOCK(ch->ch_lock, lock_flags);
if (rc) {
- return(rc);
+ return rc;
}
rc = ch->ch_bd->bd_ops->drain(tty, 0);
if (rc) {
DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
- return(-EINTR);
+ return -EINTR;
}
DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -3156,19 +3099,19 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
- return(0);
+ return 0;
case TIOCSBRK:
rc = tty_check_change(tty);
DGNC_UNLOCK(ch->ch_lock, lock_flags);
if (rc) {
- return(rc);
+ return rc;
}
rc = ch->ch_bd->bd_ops->drain(tty, 0);
if (rc) {
DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
- return(-EINTR);
+ return -EINTR;
}
DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -3180,7 +3123,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
- return(0);
+ return 0;
case TIOCCBRK:
/* Do Nothing */
@@ -3192,31 +3135,31 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
DGNC_UNLOCK(ch->ch_lock, lock_flags);
rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) arg);
- return(rc);
+ return rc;
case TIOCSSOFTCAR:
DGNC_UNLOCK(ch->ch_lock, lock_flags);
rc = get_user(arg, (unsigned long __user *) arg);
if (rc)
- return(rc);
+ return rc;
DGNC_LOCK(ch->ch_lock, lock_flags);
tty->termios.c_cflag = ((tty->termios.c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
ch->ch_bd->bd_ops->param(tty);
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- return(0);
+ return 0;
case TIOCMGET:
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- return(dgnc_get_modem_info(ch, uarg));
+ return dgnc_get_modem_info(ch, uarg);
case TIOCMBIS:
case TIOCMBIC:
case TIOCMSET:
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- return(dgnc_set_modem_info(tty, cmd, uarg));
+ return dgnc_set_modem_info(tty, cmd, uarg);
/*
* Here are any additional ioctl's that we want to implement
@@ -3235,7 +3178,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
rc = tty_check_change(tty);
if (rc) {
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- return(rc);
+ return rc;
}
if ((arg == TCIFLUSH) || (arg == TCIOFLUSH)) {
@@ -3265,7 +3208,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
/* pretend we didn't recognize this IOCTL */
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- return(-ENOIOCTLCMD);
+ return -ENOIOCTLCMD;
case TCSETSF:
case TCSETSW:
/*
@@ -3291,14 +3234,14 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
rc = ch->ch_bd->bd_ops->drain(tty, 0);
if (rc) {
DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d\n", rc));
- return(-EINTR);
+ return -EINTR;
}
DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
/* pretend we didn't recognize this */
- return(-ENOIOCTLCMD);
+ return -ENOIOCTLCMD;
case TCSETAW:
@@ -3306,21 +3249,21 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
rc = ch->ch_bd->bd_ops->drain(tty, 0);
if (rc) {
DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
- return(-EINTR);
+ return -EINTR;
}
/* pretend we didn't recognize this */
- return(-ENOIOCTLCMD);
+ return -ENOIOCTLCMD;
case TCXONC:
DGNC_UNLOCK(ch->ch_lock, lock_flags);
/* Make the ld do it */
- return(-ENOIOCTLCMD);
+ return -ENOIOCTLCMD;
case DIGI_GETA:
/* get information for ditty */
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- return(dgnc_tty_digigeta(tty, uarg));
+ return dgnc_tty_digigeta(tty, uarg);
case DIGI_SETAW:
case DIGI_SETAF:
@@ -3332,7 +3275,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
rc = ch->ch_bd->bd_ops->drain(tty, 0);
if (rc) {
DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
- return(-EINTR);
+ return -EINTR;
}
DGNC_LOCK(ch->ch_lock, lock_flags);
}
@@ -3343,7 +3286,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
case DIGI_SETA:
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- return(dgnc_tty_digiseta(tty, uarg));
+ return dgnc_tty_digiseta(tty, uarg);
case DIGI_LOOPBACK:
{
@@ -3352,7 +3295,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
DGNC_UNLOCK(ch->ch_lock, lock_flags);
rc = get_user(loopback, (unsigned int __user *) arg);
if (rc)
- return(rc);
+ return rc;
DGNC_LOCK(ch->ch_lock, lock_flags);
/* Enable/disable internal loopback for this port */
@@ -3363,13 +3306,13 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
ch->ch_bd->bd_ops->param(tty);
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- return(0);
+ return 0;
}
case DIGI_GETCUSTOMBAUD:
DGNC_UNLOCK(ch->ch_lock, lock_flags);
rc = put_user(ch->ch_custom_speed, (unsigned int __user *) arg);
- return(rc);
+ return rc;
case DIGI_SETCUSTOMBAUD:
{
@@ -3378,12 +3321,12 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
DGNC_UNLOCK(ch->ch_lock, lock_flags);
rc = get_user(new_rate, (unsigned int __user *) arg);
if (rc)
- return(rc);
+ return rc;
DGNC_LOCK(ch->ch_lock, lock_flags);
dgnc_set_custom_speed(ch, new_rate);
ch->ch_bd->bd_ops->param(tty);
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- return(0);
+ return 0;
}
/*
@@ -3399,11 +3342,11 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
DGNC_UNLOCK(ch->ch_lock, lock_flags);
rc = get_user(c, (unsigned char __user *) arg);
if (rc)
- return(rc);
+ return rc;
DGNC_LOCK(ch->ch_lock, lock_flags);
ch->ch_bd->bd_ops->send_immediate_char(ch, c);
DGNC_UNLOCK(ch->ch_lock, lock_flags);
- return(0);
+ return 0;
}
/*
@@ -3427,9 +3370,9 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
DGNC_UNLOCK(ch->ch_lock, lock_flags);
if (copy_to_user(uarg, &buf, sizeof(struct digi_getcounter))) {
- return (-EFAULT);
+ return -EFAULT;
}
- return(0);
+ return 0;
}
/*
@@ -3454,7 +3397,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
DGNC_UNLOCK(ch->ch_lock, lock_flags);
rc = put_user(events, (unsigned int __user *) arg);
- return(rc);
+ return rc;
}
/*
@@ -3475,7 +3418,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
* Get data from user first.
*/
if (copy_from_user(&buf, uarg, sizeof(struct digi_getbuffer))) {
- return (-EFAULT);
+ return -EFAULT;
}
DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -3521,9 +3464,9 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
DGNC_UNLOCK(ch->ch_lock, lock_flags);
if (copy_to_user(uarg, &buf, sizeof(struct digi_getbuffer))) {
- return (-EFAULT);
+ return -EFAULT;
}
- return(0);
+ return 0;
}
default:
DGNC_UNLOCK(ch->ch_lock, lock_flags);
@@ -3532,7 +3475,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
DPR_IOCTL(("dgnc_tty_ioctl end - cmd %s (%x), arg %lx\n",
dgnc_ioctl_name(cmd), cmd, arg));
- return(-ENOIOCTLCMD);
+ return -ENOIOCTLCMD;
}
DGNC_UNLOCK(ch->ch_lock, lock_flags);
@@ -3540,5 +3483,5 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
DPR_IOCTL(("dgnc_tty_ioctl end - cmd %s (%x), arg %lx\n",
dgnc_ioctl_name(cmd), cmd, arg));
- return(0);
+ return 0;
}
diff --git a/drivers/staging/dgnc/dgnc_tty.h b/drivers/staging/dgnc/dgnc_tty.h
index deb388d2f4cf..9d1c2847bd94 100644
--- a/drivers/staging/dgnc/dgnc_tty.h
+++ b/drivers/staging/dgnc/dgnc_tty.h
@@ -24,13 +24,13 @@
#include "dgnc_driver.h"
-int dgnc_tty_register(struct board_t *brd);
+int dgnc_tty_register(struct dgnc_board *brd);
int dgnc_tty_preinit(void);
-int dgnc_tty_init(struct board_t *);
+int dgnc_tty_init(struct dgnc_board *);
void dgnc_tty_post_uninit(void);
-void dgnc_tty_uninit(struct board_t *);
+void dgnc_tty_uninit(struct dgnc_board *);
void dgnc_input(struct channel_t *ch);
void dgnc_carrier(struct channel_t *ch);
diff --git a/drivers/staging/dgnc/digi.h b/drivers/staging/dgnc/digi.h
index eb6e37125727..6a9adf6591eb 100644
--- a/drivers/staging/dgnc/digi.h
+++ b/drivers/staging/dgnc/digi.h
@@ -201,9 +201,9 @@ struct shrink_buf_struct {
unsigned int shrink_buf_vaddr; /* Virtual address of board */
unsigned int shrink_buf_phys; /* Physical address of board */
unsigned int shrink_buf_bseg; /* Amount of board memory */
- unsigned int shrink_buf_hseg; /* '186 Begining of Dual-Port */
+ unsigned int shrink_buf_hseg; /* '186 Beginning of Dual-Port */
- unsigned int shrink_buf_lseg; /* '186 Begining of freed memory */
+ unsigned int shrink_buf_lseg; /* '186 Beginning of freed memory */
unsigned int shrink_buf_mseg; /* Linear address from start of
dual-port were freed memory
begins, host viewpoint. */
diff --git a/drivers/staging/dgrp/dgrp_sysfs.c b/drivers/staging/dgrp/dgrp_sysfs.c
index 8cee9c8bc38b..9a18a2c9e73b 100644
--- a/drivers/staging/dgrp/dgrp_sysfs.c
+++ b/drivers/staging/dgrp/dgrp_sysfs.c
@@ -157,7 +157,7 @@ static ssize_t dgrp_node_state_show(struct device *c,
if (!c)
return 0;
- nd = (struct nd_struct *) dev_get_drvdata(c);
+ nd = dev_get_drvdata(c);
if (!nd)
return 0;
@@ -174,7 +174,7 @@ static ssize_t dgrp_node_description_show(struct device *c,
if (!c)
return 0;
- nd = (struct nd_struct *) dev_get_drvdata(c);
+ nd = dev_get_drvdata(c);
if (!nd)
return 0;
@@ -192,7 +192,7 @@ static ssize_t dgrp_node_hw_version_show(struct device *c,
if (!c)
return 0;
- nd = (struct nd_struct *) dev_get_drvdata(c);
+ nd = dev_get_drvdata(c);
if (!nd)
return 0;
@@ -212,7 +212,7 @@ static ssize_t dgrp_node_hw_id_show(struct device *c,
if (!c)
return 0;
- nd = (struct nd_struct *) dev_get_drvdata(c);
+ nd = dev_get_drvdata(c);
if (!nd)
return 0;
@@ -232,7 +232,7 @@ static ssize_t dgrp_node_sw_version_show(struct device *c,
if (!c)
return 0;
- nd = (struct nd_struct *) dev_get_drvdata(c);
+ nd = dev_get_drvdata(c);
if (!nd)
return 0;
@@ -311,7 +311,7 @@ static ssize_t dgrp_tty_state_show(struct device *d,
if (!d)
return 0;
- un = (struct un_struct *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un)
return 0;
@@ -328,7 +328,7 @@ static ssize_t dgrp_tty_baud_show(struct device *d,
if (!d)
return 0;
- un = (struct un_struct *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un)
return 0;
ch = un->un_ch;
@@ -348,7 +348,7 @@ static ssize_t dgrp_tty_msignals_show(struct device *d,
if (!d)
return 0;
- un = (struct un_struct *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un)
return 0;
ch = un->un_ch;
@@ -377,7 +377,7 @@ static ssize_t dgrp_tty_iflag_show(struct device *d,
if (!d)
return 0;
- un = (struct un_struct *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un)
return 0;
ch = un->un_ch;
@@ -396,7 +396,7 @@ static ssize_t dgrp_tty_cflag_show(struct device *d,
if (!d)
return 0;
- un = (struct un_struct *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un)
return 0;
ch = un->un_ch;
@@ -415,7 +415,7 @@ static ssize_t dgrp_tty_oflag_show(struct device *d,
if (!d)
return 0;
- un = (struct un_struct *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un)
return 0;
ch = un->un_ch;
@@ -434,7 +434,7 @@ static ssize_t dgrp_tty_digi_flag_show(struct device *d,
if (!d)
return 0;
- un = (struct un_struct *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un)
return 0;
ch = un->un_ch;
@@ -453,7 +453,7 @@ static ssize_t dgrp_tty_rxcount_show(struct device *d,
if (!d)
return 0;
- un = (struct un_struct *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un)
return 0;
ch = un->un_ch;
@@ -472,7 +472,7 @@ static ssize_t dgrp_tty_txcount_show(struct device *d,
if (!d)
return 0;
- un = (struct un_struct *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un)
return 0;
ch = un->un_ch;
@@ -493,7 +493,7 @@ static ssize_t dgrp_tty_name_show(struct device *d,
if (!d)
return 0;
- un = (struct un_struct *) dev_get_drvdata(d);
+ un = dev_get_drvdata(d);
if (!un)
return 0;
ch = un->un_ch;
diff --git a/drivers/staging/dwc2/TODO b/drivers/staging/dwc2/TODO
new file mode 100644
index 000000000000..282470d55315
--- /dev/null
+++ b/drivers/staging/dwc2/TODO
@@ -0,0 +1,33 @@
+TODO:
+ - Dan Carpenter would like to see some cleanups to the microframe
+ scheduler code:
+ http://www.mail-archive.com/linux-usb@vger.kernel.org/msg26650.html
+
+ - Should merge the NAK holdoff patch from Raspberry Pi
+ (http://marc.info/?l=linux-usb&m=137625067103833). But as it stands
+ that patch is incomplete, it needs more investigation to see if it
+ can be made to work for non-Raspberry Pi platforms that lack the
+ special FIQ interrupt that the Pi has. Without this patch, the driver
+ has a high interrupt rate (8K/sec).
+
+ - The Raspberry Pi platform needs to have support for its FIQ interrupt
+ added, to get the same level of functionality as the downstream
+ driver. The raspberrypi.org developers have indicated they are
+ willing to help with that.
+
+ - Some of the default driver parameters (see 'struct dwc2_core_params'
+ in core.h) won't work for many platforms. So DT attributes will need
+ to be added for some of these. But that can be done as-needed as new
+ platforms are added.
+
+ - Eventually the driver should be merged with the s3c-hsotg peripheral
+ mode driver, so that both modes of operation can be supported with a
+ single driver. But I think that can wait till after the driver has
+ been moved to mainline.
+
+ - After that, OTG support can be added. I'm not sure how much demand
+ there is for that, though, so I have that as a low priority.
+
+Please send any patches for this driver to Paul Zimmerman <paulz@synopsys.com>
+and Greg Kroah-Hartman <gregkh@linuxfoundation.org>. And please CC linux-usb
+<linux-usb@vger.kernel.org> too.
diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c
index 06dae67a9d62..6d001b52f652 100644
--- a/drivers/staging/dwc2/core.c
+++ b/drivers/staging/dwc2/core.c
@@ -564,7 +564,7 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
/*
* This bit allows dynamic reloading of the HFIR register during
- * runtime. This bit needs to be programmed during inital configuration
+ * runtime. This bit needs to be programmed during initial configuration
* and its value must not be changed during runtime.
*/
if (hsotg->core_params->reload_ctl > 0) {
@@ -2205,7 +2205,7 @@ int dwc2_set_param_phy_type(struct dwc2_hsotg *hsotg, int val)
{
#ifndef NO_FS_PHY_HW_CHECKS
int valid = 0;
- u32 hs_phy_type, fs_phy_type;
+ u32 hs_phy_type, fs_phy_type;
#endif
int retval = 0;
@@ -2553,7 +2553,7 @@ int dwc2_set_param_ahbcfg(struct dwc2_hsotg *hsotg, int val)
hsotg->core_params->ahbcfg = val;
else
hsotg->core_params->ahbcfg = GAHBCFG_HBSTLEN_INCR4 <<
- GAHBCFG_HBSTLEN_SHIFT;
+ GAHBCFG_HBSTLEN_SHIFT;
return 0;
}
@@ -2736,6 +2736,26 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
return 0;
}
+int dwc2_set_param_uframe_sched(struct dwc2_hsotg *hsotg, int val)
+{
+ int retval = 0;
+
+ if (DWC2_PARAM_TEST(val, 0, 1)) {
+ if (val >= 0) {
+ dev_err(hsotg->dev,
+ "'%d' invalid for parameter uframe_sched\n",
+ val);
+ dev_err(hsotg->dev, "uframe_sched must be 0 or 1\n");
+ }
+ val = 1;
+ dev_dbg(hsotg->dev, "Setting uframe_sched to %d\n", val);
+ retval = -EINVAL;
+ }
+
+ hsotg->core_params->uframe_sched = val;
+ return retval;
+}
+
/*
* This function is called during module intialization to pass module parameters
* for the DWC_otg core. It returns non-0 if any parameters are invalid.
@@ -2782,6 +2802,7 @@ int dwc2_set_parameters(struct dwc2_hsotg *hsotg,
retval |= dwc2_set_param_reload_ctl(hsotg, params->reload_ctl);
retval |= dwc2_set_param_ahbcfg(hsotg, params->ahbcfg);
retval |= dwc2_set_param_otg_ver(hsotg, params->otg_ver);
+ retval |= dwc2_set_param_uframe_sched(hsotg, params->uframe_sched);
return retval;
}
diff --git a/drivers/staging/dwc2/core.h b/drivers/staging/dwc2/core.h
index 9102f66d0111..f7ba34b7071c 100644
--- a/drivers/staging/dwc2/core.h
+++ b/drivers/staging/dwc2/core.h
@@ -188,6 +188,7 @@ enum dwc2_lx_state {
* bits defined by GAHBCFG_CTRL_MASK are controlled
* by the driver and are ignored in this
* configuration value.
+ * @uframe_sched: True to enable the microframe scheduler
*
* The following parameters may be specified when starting the module. These
* parameters define how the DWC_otg controller should be configured. A
@@ -224,6 +225,7 @@ struct dwc2_core_params {
int ts_dline;
int reload_ctl;
int ahbcfg;
+ int uframe_sched;
};
/**
@@ -370,6 +372,7 @@ struct dwc2_hw_params {
* This value is in microseconds per (micro)frame. The
* assumption is that all periodic transfers may occur in
* the same (micro)frame.
+ * @frame_usecs: Internal variable used by the microframe scheduler
* @frame_number: Frame number read from the core at SOF. The value ranges
* from 0 to HFNUM_MAX_FRNUM.
* @periodic_qh_count: Count of periodic QHs, if using several eps. Used for
@@ -382,6 +385,8 @@ struct dwc2_hw_params {
* host channel is available for non-periodic transactions.
* @non_periodic_channels: Number of host channels assigned to non-periodic
* transfers
+ * @available_host_channels Number of host channels available for the microframe
+ * scheduler to use
* @hc_ptr_array: Array of pointers to the host channel descriptors.
* Allows accessing a host channel descriptor given the
* host channel number. This is useful in interrupt
@@ -436,6 +441,7 @@ struct dwc2_hsotg {
struct list_head periodic_sched_assigned;
struct list_head periodic_sched_queued;
u16 periodic_usecs;
+ u16 frame_usecs[8];
u16 frame_number;
u16 periodic_qh_count;
@@ -451,6 +457,7 @@ struct dwc2_hsotg {
struct list_head free_hc_list;
int periodic_channels;
int non_periodic_channels;
+ int available_host_channels;
struct dwc2_host_chan *hc_ptr_array[MAX_EPS_CHANNELS];
u8 *status_buf;
dma_addr_t status_buf_dma;
diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c
index da0d35cc33ce..83629d84155d 100644
--- a/drivers/staging/dwc2/hcd.c
+++ b/drivers/staging/dwc2/hcd.c
@@ -537,10 +537,15 @@ static void dwc2_hcd_reinit(struct dwc2_hsotg *hsotg)
int i;
hsotg->flags.d32 = 0;
-
hsotg->non_periodic_qh_ptr = &hsotg->non_periodic_sched_active;
- hsotg->non_periodic_channels = 0;
- hsotg->periodic_channels = 0;
+
+ if (hsotg->core_params->uframe_sched > 0) {
+ hsotg->available_host_channels =
+ hsotg->core_params->host_channels;
+ } else {
+ hsotg->non_periodic_channels = 0;
+ hsotg->periodic_channels = 0;
+ }
/*
* Put all channels in the free channel list and clean up channel
@@ -716,8 +721,7 @@ static int dwc2_hc_setup_align_buf(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
* @qh: Transactions from the first QTD for this QH are selected and assigned
* to a free host channel
*/
-static void dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg,
- struct dwc2_qh *qh)
+static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{
struct dwc2_host_chan *chan;
struct dwc2_hcd_urb *urb;
@@ -729,18 +733,18 @@ static void dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg,
if (list_empty(&qh->qtd_list)) {
dev_dbg(hsotg->dev, "No QTDs in QH list\n");
- return;
+ return -ENOMEM;
}
if (list_empty(&hsotg->free_hc_list)) {
dev_dbg(hsotg->dev, "No free channel to assign\n");
- return;
+ return -ENOMEM;
}
chan = list_first_entry(&hsotg->free_hc_list, struct dwc2_host_chan,
hc_list_entry);
- /* Remove the host channel from the free list */
+ /* Remove host channel from free list */
list_del_init(&chan->hc_list_entry);
qtd = list_first_entry(&qh->qtd_list, struct dwc2_qtd, qtd_list_entry);
@@ -780,6 +784,10 @@ static void dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg,
chan->data_pid_start = qh->data_toggle;
chan->multi_count = 1;
+ if ((urb->actual_length < 0 || urb->actual_length > urb->length) &&
+ !dwc2_hcd_is_pipe_in(&urb->pipe_info))
+ urb->actual_length = urb->length;
+
if (hsotg->core_params->dma_enable > 0) {
chan->xfer_dma = urb->dma + urb->actual_length;
@@ -817,7 +825,7 @@ static void dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg,
&hsotg->free_hc_list);
qtd->in_process = 0;
qh->channel = NULL;
- return;
+ return -ENOMEM;
}
} else {
chan->align_buf = 0;
@@ -836,6 +844,8 @@ static void dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg,
dwc2_hc_init(hsotg, chan);
chan->qh = qh;
+
+ return 0;
}
/**
@@ -864,8 +874,14 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions(
while (qh_ptr != &hsotg->periodic_sched_ready) {
if (list_empty(&hsotg->free_hc_list))
break;
+ if (hsotg->core_params->uframe_sched > 0) {
+ if (hsotg->available_host_channels <= 1)
+ break;
+ hsotg->available_host_channels--;
+ }
qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry);
- dwc2_assign_and_init_hc(hsotg, qh);
+ if (dwc2_assign_and_init_hc(hsotg, qh))
+ break;
/*
* Move the QH from the periodic ready schedule to the
@@ -884,13 +900,21 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions(
num_channels = hsotg->core_params->host_channels;
qh_ptr = hsotg->non_periodic_sched_inactive.next;
while (qh_ptr != &hsotg->non_periodic_sched_inactive) {
- if (hsotg->non_periodic_channels >= num_channels -
+ if (hsotg->core_params->uframe_sched <= 0 &&
+ hsotg->non_periodic_channels >= num_channels -
hsotg->periodic_channels)
break;
if (list_empty(&hsotg->free_hc_list))
break;
qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry);
- dwc2_assign_and_init_hc(hsotg, qh);
+ if (hsotg->core_params->uframe_sched > 0) {
+ if (hsotg->available_host_channels < 1)
+ break;
+ hsotg->available_host_channels--;
+ }
+
+ if (dwc2_assign_and_init_hc(hsotg, qh))
+ break;
/*
* Move the QH from the non-periodic inactive schedule to the
@@ -905,7 +929,8 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions(
else
ret_val = DWC2_TRANSACTION_ALL;
- hsotg->non_periodic_channels++;
+ if (hsotg->core_params->uframe_sched <= 0)
+ hsotg->non_periodic_channels++;
}
return ret_val;
@@ -2848,6 +2873,9 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq,
hsotg->hc_ptr_array[i] = channel;
}
+ if (hsotg->core_params->uframe_sched > 0)
+ dwc2_hcd_init_usecs(hsotg);
+
/* Initialize hsotg start work */
INIT_DELAYED_WORK(&hsotg->start_work, dwc2_hcd_start_func);
diff --git a/drivers/staging/dwc2/hcd.h b/drivers/staging/dwc2/hcd.h
index cc0a11708319..89a5484f5b74 100644
--- a/drivers/staging/dwc2/hcd.h
+++ b/drivers/staging/dwc2/hcd.h
@@ -238,6 +238,7 @@ enum dwc2_transaction_type {
* @interval: Interval between transfers in (micro)frames
* @sched_frame: (Micro)frame to initialize a periodic transfer.
* The transfer executes in the following (micro)frame.
+ * @frame_usecs: Internal variable used by the microframe scheduler
* @start_split_frame: (Micro)frame at which last start split was initialized
* @ntd: Actual number of transfer descriptors in a list
* @dw_align_buf: Used instead of original buffer if its physical address
@@ -271,6 +272,7 @@ struct dwc2_qh {
u16 usecs;
u16 interval;
u16 sched_frame;
+ u16 frame_usecs[8];
u16 start_split_frame;
u16 ntd;
u8 *dw_align_buf;
@@ -463,6 +465,7 @@ extern void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg,
/* Schedule Queue Functions */
/* Implemented in hcd_queue.c */
+extern void dwc2_hcd_init_usecs(struct dwc2_hsotg *hsotg);
extern void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
extern int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
extern void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
diff --git a/drivers/staging/dwc2/hcd_ddma.c b/drivers/staging/dwc2/hcd_ddma.c
index 69070f4442a8..c7d434519776 100644
--- a/drivers/staging/dwc2/hcd_ddma.c
+++ b/drivers/staging/dwc2/hcd_ddma.c
@@ -271,10 +271,14 @@ static void dwc2_release_channel_ddma(struct dwc2_hsotg *hsotg,
{
struct dwc2_host_chan *chan = qh->channel;
- if (dwc2_qh_is_non_per(qh))
- hsotg->non_periodic_channels--;
- else
+ if (dwc2_qh_is_non_per(qh)) {
+ if (hsotg->core_params->uframe_sched > 0)
+ hsotg->available_host_channels++;
+ else
+ hsotg->non_periodic_channels--;
+ } else {
dwc2_update_frame_list(hsotg, qh, 0);
+ }
/*
* The condition is added to prevent double cleanup try in case of
@@ -370,7 +374,8 @@ void dwc2_hcd_qh_free_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
if ((qh->ep_type == USB_ENDPOINT_XFER_ISOC ||
qh->ep_type == USB_ENDPOINT_XFER_INT) &&
- !hsotg->periodic_channels && hsotg->frame_list) {
+ (hsotg->core_params->uframe_sched > 0 ||
+ !hsotg->periodic_channels) && hsotg->frame_list) {
dwc2_per_sched_disable(hsotg);
dwc2_frame_list_free(hsotg);
}
diff --git a/drivers/staging/dwc2/hcd_intr.c b/drivers/staging/dwc2/hcd_intr.c
index e143f69939f5..cad433a75aba 100644
--- a/drivers/staging/dwc2/hcd_intr.c
+++ b/drivers/staging/dwc2/hcd_intr.c
@@ -748,18 +748,23 @@ cleanup:
dwc2_hc_cleanup(hsotg, chan);
list_add_tail(&chan->hc_list_entry, &hsotg->free_hc_list);
- switch (chan->ep_type) {
- case USB_ENDPOINT_XFER_CONTROL:
- case USB_ENDPOINT_XFER_BULK:
- hsotg->non_periodic_channels--;
- break;
- default:
- /*
- * Don't release reservations for periodic channels here.
- * That's done when a periodic transfer is descheduled (i.e.
- * when the QH is removed from the periodic schedule).
- */
- break;
+ if (hsotg->core_params->uframe_sched > 0) {
+ hsotg->available_host_channels++;
+ } else {
+ switch (chan->ep_type) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ case USB_ENDPOINT_XFER_BULK:
+ hsotg->non_periodic_channels--;
+ break;
+ default:
+ /*
+ * Don't release reservations for periodic channels
+ * here. That's done when a periodic transfer is
+ * descheduled (i.e. when the QH is removed from the
+ * periodic schedule).
+ */
+ break;
+ }
}
haintmsk = readl(hsotg->regs + HAINTMSK);
diff --git a/drivers/staging/dwc2/hcd_queue.c b/drivers/staging/dwc2/hcd_queue.c
index b1980ef28fa3..f200f1f6e1c6 100644
--- a/drivers/staging/dwc2/hcd_queue.c
+++ b/drivers/staging/dwc2/hcd_queue.c
@@ -251,12 +251,12 @@ void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
*
* @hsotg: The HCD state structure for the DWC OTG controller
*
- * Return: 0 if successful, negative error code otherise
+ * Return: 0 if successful, negative error code otherwise
*/
static int dwc2_periodic_channel_available(struct dwc2_hsotg *hsotg)
{
/*
- * Currently assuming that there is a dedicated host channnel for
+ * Currently assuming that there is a dedicated host channel for
* each periodic transaction plus at least one host channel for
* non-periodic transactions
*/
@@ -324,6 +324,146 @@ static int dwc2_check_periodic_bandwidth(struct dwc2_hsotg *hsotg,
}
/**
+ * Microframe scheduler
+ * track the total use in hsotg->frame_usecs
+ * keep each qh use in qh->frame_usecs
+ * when surrendering the qh then donate the time back
+ */
+static const unsigned short max_uframe_usecs[] = {
+ 100, 100, 100, 100, 100, 100, 30, 0
+};
+
+void dwc2_hcd_init_usecs(struct dwc2_hsotg *hsotg)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ hsotg->frame_usecs[i] = max_uframe_usecs[i];
+}
+
+static int dwc2_find_single_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
+{
+ unsigned short utime = qh->usecs;
+ int done = 0;
+ int i = 0;
+ int ret = -1;
+
+ while (!done) {
+ /* At the start hsotg->frame_usecs[i] = max_uframe_usecs[i] */
+ if (utime <= hsotg->frame_usecs[i]) {
+ hsotg->frame_usecs[i] -= utime;
+ qh->frame_usecs[i] += utime;
+ ret = i;
+ done = 1;
+ } else {
+ i++;
+ if (i == 8)
+ done = 1;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * use this for FS apps that can span multiple uframes
+ */
+static int dwc2_find_multi_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
+{
+ unsigned short utime = qh->usecs;
+ unsigned short xtime;
+ int t_left = utime;
+ int done = 0;
+ int i = 0;
+ int j;
+ int ret = -1;
+
+ while (!done) {
+ if (hsotg->frame_usecs[i] <= 0) {
+ i++;
+ if (i == 8) {
+ ret = -1;
+ done = 1;
+ }
+ continue;
+ }
+
+ /*
+ * we need n consecutive slots so use j as a start slot
+ * j plus j+1 must be enough time (for now)
+ */
+ xtime = hsotg->frame_usecs[i];
+ for (j = i + 1; j < 8; j++) {
+ /*
+ * if we add this frame remaining time to xtime we may
+ * be OK, if not we need to test j for a complete frame
+ */
+ if (xtime + hsotg->frame_usecs[j] < utime) {
+ if (hsotg->frame_usecs[j] <
+ max_uframe_usecs[j]) {
+ ret = -1;
+ break;
+ }
+ }
+ if (xtime >= utime) {
+ ret = i;
+ break;
+ }
+ /* add the frame time to x time */
+ xtime += hsotg->frame_usecs[j];
+ /* we must have a fully available next frame or break */
+ if (xtime < utime &&
+ hsotg->frame_usecs[j] == max_uframe_usecs[j]) {
+ ret = -1;
+ break;
+ }
+ }
+ if (ret >= 0) {
+ t_left = utime;
+ for (j = i; t_left > 0 && j < 8; j++) {
+ t_left -= hsotg->frame_usecs[j];
+ if (t_left <= 0) {
+ qh->frame_usecs[j] +=
+ hsotg->frame_usecs[j] + t_left;
+ hsotg->frame_usecs[j] = -t_left;
+ ret = i;
+ done = 1;
+ } else {
+ qh->frame_usecs[j] +=
+ hsotg->frame_usecs[j];
+ hsotg->frame_usecs[j] = 0;
+ }
+ }
+ } else {
+ i++;
+ if (i == 8) {
+ ret = -1;
+ done = 1;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int dwc2_find_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
+{
+ int ret;
+
+ if (qh->dev_speed == USB_SPEED_HIGH) {
+ /* if this is a hs transaction we need a full frame */
+ ret = dwc2_find_single_uframe(hsotg, qh);
+ } else {
+ /*
+ * if this is a fs transaction we may need a sequence
+ * of frames
+ */
+ ret = dwc2_find_multi_uframe(hsotg, qh);
+ }
+ return ret;
+}
+
+/**
* dwc2_check_max_xfer_size() - Checks that the max transfer size allowed in a
* host channel is large enough to handle the maximum data transfer in a single
* (micro)frame for a periodic transfer
@@ -367,15 +507,35 @@ static int dwc2_schedule_periodic(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
{
int status;
- status = dwc2_periodic_channel_available(hsotg);
- if (status) {
- dev_dbg(hsotg->dev,
- "%s: No host channel available for periodic transfer\n",
- __func__);
- return status;
+ if (hsotg->core_params->uframe_sched > 0) {
+ int frame = -1;
+
+ status = dwc2_find_uframe(hsotg, qh);
+ if (status == 0)
+ frame = 7;
+ else if (status > 0)
+ frame = status - 1;
+
+ /* Set the new frame up */
+ if (frame > -1) {
+ qh->sched_frame &= ~0x7;
+ qh->sched_frame |= (frame & 7);
+ }
+
+ if (status != -1)
+ status = 0;
+ } else {
+ status = dwc2_periodic_channel_available(hsotg);
+ if (status) {
+ dev_info(hsotg->dev,
+ "%s: No host channel available for periodic transfer\n",
+ __func__);
+ return status;
+ }
+
+ status = dwc2_check_periodic_bandwidth(hsotg, qh);
}
- status = dwc2_check_periodic_bandwidth(hsotg, qh);
if (status) {
dev_dbg(hsotg->dev,
"%s: Insufficient periodic bandwidth for periodic transfer\n",
@@ -399,8 +559,9 @@ static int dwc2_schedule_periodic(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
list_add_tail(&qh->qh_list_entry,
&hsotg->periodic_sched_inactive);
- /* Reserve periodic channel */
- hsotg->periodic_channels++;
+ if (hsotg->core_params->uframe_sched <= 0)
+ /* Reserve periodic channel */
+ hsotg->periodic_channels++;
/* Update claimed usecs per (micro)frame */
hsotg->periodic_usecs += qh->usecs;
@@ -418,13 +579,22 @@ static int dwc2_schedule_periodic(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
static void dwc2_deschedule_periodic(struct dwc2_hsotg *hsotg,
struct dwc2_qh *qh)
{
- list_del_init(&qh->qh_list_entry);
+ int i;
- /* Release periodic channel reservation */
- hsotg->periodic_channels--;
+ list_del_init(&qh->qh_list_entry);
/* Update claimed usecs per (micro)frame */
hsotg->periodic_usecs -= qh->usecs;
+
+ if (hsotg->core_params->uframe_sched > 0) {
+ for (i = 0; i < 8; i++) {
+ hsotg->frame_usecs[i] += qh->frame_usecs[i];
+ qh->frame_usecs[i] = 0;
+ }
+ } else {
+ /* Release periodic channel reservation */
+ hsotg->periodic_channels--;
+ }
}
/**
@@ -581,7 +751,10 @@ void dwc2_hcd_qh_deactivate(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
* Remove from periodic_sched_queued and move to
* appropriate queue
*/
- if (qh->sched_frame == frame_number)
+ if ((hsotg->core_params->uframe_sched > 0 &&
+ dwc2_frame_num_le(qh->sched_frame, frame_number))
+ || (hsotg->core_params->uframe_sched <= 0 &&
+ qh->sched_frame == frame_number))
list_move(&qh->qh_list_entry,
&hsotg->periodic_sched_ready);
else
diff --git a/drivers/staging/dwc2/pci.c b/drivers/staging/dwc2/pci.c
index 9020260d5df8..3d14c8870fca 100644
--- a/drivers/staging/dwc2/pci.c
+++ b/drivers/staging/dwc2/pci.c
@@ -84,6 +84,7 @@ static const struct dwc2_core_params dwc2_module_params = {
.ts_dline = -1,
.reload_ctl = -1,
.ahbcfg = -1,
+ .uframe_sched = -1,
};
/**
diff --git a/drivers/staging/et131x/Module.symvers b/drivers/staging/et131x/Module.symvers
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/drivers/staging/et131x/Module.symvers
diff --git a/drivers/staging/et131x/README b/drivers/staging/et131x/README
index 9272a24ae61c..8da96a6d2c92 100644
--- a/drivers/staging/et131x/README
+++ b/drivers/staging/et131x/README
@@ -11,7 +11,12 @@ TODO:
- Look at reducing the number of spinlocks
- Simplify code in nic_rx_pkts(), when determining multicast_pkts_rcvd
- Implement NAPI support
- - in et131x_tx(), don't return NETDEV_TX_BUSY, just drop the packet with kfree_skb().
+ - In et131x_tx(), don't return NETDEV_TX_BUSY, just drop the packet with kfree_skb().
+ - Reduce the number of split lines by careful consideration of variable names etc.
+ - Do this in et131x.c:
+ struct fbr_lookup *fbr;
+ fbr = rx_local->fbr[id];
+ Then replace all the instances of "rx_local->fbr[id]" with fbr.
Please send patches to:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c
index f73e58f5ef8d..7cd3d3470758 100644
--- a/drivers/staging/et131x/et131x.c
+++ b/drivers/staging/et131x/et131x.c
@@ -493,11 +493,8 @@ struct et131x_adapter {
spinlock_t send_hw_lock;
spinlock_t rcv_lock;
- spinlock_t rcv_pend_lock;
spinlock_t fbr_lock;
- spinlock_t phy_lock;
-
/* Packet Filter and look ahead size */
u32 packet_filter;
@@ -2777,10 +2774,9 @@ static void et131x_handle_recv_interrupt(struct et131x_adapter *adapter)
adapter->net_stats.rx_packets++;
/* Set the status on the packet, either resources or success */
- if (adapter->rx_ring.num_ready_recv < RFD_LOW_WATER_MARK) {
- dev_warn(&adapter->pdev->dev,
- "RFD's are running out\n");
- }
+ if (adapter->rx_ring.num_ready_recv < RFD_LOW_WATER_MARK)
+ dev_warn(&adapter->pdev->dev, "RFD's are running out\n");
+
count++;
}
@@ -3100,11 +3096,10 @@ static int send_packet(struct sk_buff *skb, struct et131x_adapter *adapter)
shbufva = (u16 *) skb->data;
if ((shbufva[0] == 0xffff) &&
- (shbufva[1] == 0xffff) && (shbufva[2] == 0xffff)) {
+ (shbufva[1] == 0xffff) && (shbufva[2] == 0xffff))
tcb->flags |= FMP_DEST_BROAD;
- } else if ((shbufva[0] & 0x3) == 0x0001) {
+ else if ((shbufva[0] & 0x3) == 0x0001)
tcb->flags |= FMP_DEST_MULTI;
- }
}
tcb->next = NULL;
@@ -3926,9 +3921,7 @@ static struct et131x_adapter *et131x_adapter_init(struct net_device *netdev,
spin_lock_init(&adapter->tcb_ready_qlock);
spin_lock_init(&adapter->send_hw_lock);
spin_lock_init(&adapter->rcv_lock);
- spin_lock_init(&adapter->rcv_pend_lock);
spin_lock_init(&adapter->fbr_lock);
- spin_lock_init(&adapter->phy_lock);
adapter->registry_jumbo_packet = 1514; /* 1514-9216 */
diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c
index ff92f34e4746..62df009e5ac7 100644
--- a/drivers/staging/fwserial/fwserial.c
+++ b/drivers/staging/fwserial/fwserial.c
@@ -2394,7 +2394,8 @@ static int fwserial_create(struct fw_unit *unit)
list_del_rcu(&serial->list);
if (create_loop_dev)
- tty_unregister_device(fwloop_driver, loop_idx(serial->ports[j]));
+ tty_unregister_device(fwloop_driver,
+ loop_idx(serial->ports[j]));
unregister_ttys:
for (--j; j >= 0; --j)
tty_unregister_device(fwtty_driver, serial->ports[j]->index);
diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c
index 5b8f0f6c9938..aae86ddd658b 100644
--- a/drivers/staging/iio/accel/lis3l02dq_ring.c
+++ b/drivers/staging/iio/accel/lis3l02dq_ring.c
@@ -146,11 +146,7 @@ static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p)
if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
len = lis3l02dq_get_buffer_element(indio_dev, data);
- /* Guaranteed to be aligned with 8 byte boundary */
- if (indio_dev->scan_timestamp)
- *(s64 *)((u8 *)data + ALIGN(len, sizeof(s64)))
- = pf->timestamp;
- iio_push_to_buffers(indio_dev, (u8 *)data);
+ iio_push_to_buffers_with_timestamp(indio_dev, data, pf->timestamp);
kfree(data);
done:
diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
index 48a25ba290f5..6a9ca20ea22d 100644
--- a/drivers/staging/iio/accel/sca3000_core.c
+++ b/drivers/staging/iio/accel/sca3000_core.c
@@ -624,9 +624,9 @@ static ssize_t sca3000_set_frequency(struct device *dev,
struct sca3000_state *st = iio_priv(indio_dev);
int ret, base_freq = 0;
int ctrlval;
- long val;
+ int val;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtoint(buf, 10, &val);
if (ret)
return ret;
@@ -931,12 +931,12 @@ static ssize_t sca3000_set_free_fall_mode(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
- long val;
+ u8 val;
int ret;
u8 protect_mask = SCA3000_FREE_FALL_DETECT;
mutex_lock(&st->lock);
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou8(buf, 10, &val);
if (ret)
goto error_ret;
diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c
index 3e5e860aa38e..0f2ee3373d9a 100644
--- a/drivers/staging/iio/accel/sca3000_ring.c
+++ b/drivers/staging/iio/accel/sca3000_ring.c
@@ -177,11 +177,11 @@ static ssize_t sca3000_set_ring_int(struct device *dev,
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- long val;
+ u8 val;
int ret;
mutex_lock(&st->lock);
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou8(buf, 10, &val);
if (ret)
goto error_ret;
ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1);
diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
index 3283e2829536..83bb44b38152 100644
--- a/drivers/staging/iio/adc/ad7192.c
+++ b/drivers/staging/iio/adc/ad7192.c
@@ -623,17 +623,17 @@ static int ad7192_probe(struct spi_device *spi)
return -ENODEV;
}
- indio_dev = iio_device_alloc(sizeof(*st));
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
st = iio_priv(indio_dev);
- st->reg = regulator_get(&spi->dev, "vcc");
+ st->reg = devm_regulator_get(&spi->dev, "vcc");
if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);
if (ret)
- goto error_put_reg;
+ return ret;
voltage_uv = regulator_get_voltage(st->reg);
}
@@ -677,11 +677,6 @@ error_remove_trigger:
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
-error_put_reg:
- if (!IS_ERR(st->reg))
- regulator_put(st->reg);
-
- iio_device_free(indio_dev);
return ret;
}
@@ -694,10 +689,8 @@ static int ad7192_remove(struct spi_device *spi)
iio_device_unregister(indio_dev);
ad_sd_cleanup_buffer_and_trigger(indio_dev);
- if (!IS_ERR(st->reg)) {
+ if (!IS_ERR(st->reg))
regulator_disable(st->reg);
- regulator_put(st->reg);
- }
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c
index c19618bc37c4..e7191e44a970 100644
--- a/drivers/staging/iio/adc/ad7280a.c
+++ b/drivers/staging/iio/adc/ad7280a.c
@@ -835,8 +835,9 @@ static int ad7280_probe(struct spi_device *spi)
int ret;
const unsigned short tACQ_ns[4] = {465, 1010, 1460, 1890};
const unsigned short nAVG[4] = {1, 2, 4, 8};
- struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+ struct iio_dev *indio_dev;
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
@@ -860,7 +861,7 @@ static int ad7280_probe(struct spi_device *spi)
ret = ad7280_chain_setup(st);
if (ret < 0)
- goto error_free_device;
+ return ret;
st->slave_num = ret;
st->scan_cnt = (st->slave_num + 1) * AD7280A_NUM_CH;
@@ -891,7 +892,7 @@ static int ad7280_probe(struct spi_device *spi)
ret = ad7280_channel_init(st);
if (ret < 0)
- goto error_free_device;
+ return ret;
indio_dev->num_channels = ret;
indio_dev->channels = st->channels;
@@ -940,9 +941,6 @@ error_free_attr:
error_free_channels:
kfree(st->channels);
-error_free_device:
- iio_device_free(indio_dev);
-
return ret;
}
@@ -960,7 +958,6 @@ static int ad7280_remove(struct spi_device *spi)
kfree(st->channels);
kfree(st->iio_attr);
- iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c
index a2e61c2fc8d1..1dae1efe41c7 100644
--- a/drivers/staging/iio/adc/ad7291.c
+++ b/drivers/staging/iio/adc/ad7291.c
@@ -528,21 +528,19 @@ static int ad7291_probe(struct i2c_client *client,
struct iio_dev *indio_dev;
int ret = 0;
- indio_dev = iio_device_alloc(sizeof(*chip));
- if (indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
+ if (!indio_dev)
+ return -ENOMEM;
chip = iio_priv(indio_dev);
if (pdata && pdata->use_external_ref) {
- chip->reg = regulator_get(&client->dev, "vref");
+ chip->reg = devm_regulator_get(&client->dev, "vref");
if (IS_ERR(chip->reg))
- goto error_free;
+ return ret;
ret = regulator_enable(chip->reg);
if (ret)
- goto error_put_reg;
+ return ret;
}
mutex_init(&chip->state_lock);
@@ -601,12 +599,7 @@ error_unreg_irq:
error_disable_reg:
if (chip->reg)
regulator_disable(chip->reg);
-error_put_reg:
- if (chip->reg)
- regulator_put(chip->reg);
-error_free:
- iio_device_free(indio_dev);
-error_ret:
+
return ret;
}
@@ -620,12 +613,8 @@ static int ad7291_remove(struct i2c_client *client)
if (client->irq)
free_irq(client->irq, indio_dev);
- if (chip->reg) {
+ if (chip->reg)
regulator_disable(chip->reg);
- regulator_put(chip->reg);
- }
-
- iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c
index 72868ceda360..f042027b5291 100644
--- a/drivers/staging/iio/adc/ad7606_core.c
+++ b/drivers/staging/iio/adc/ad7606_core.c
@@ -425,8 +425,7 @@ static irqreturn_t ad7606_interrupt(int irq, void *dev_id)
struct ad7606_state *st = iio_priv(indio_dev);
if (iio_buffer_enabled(indio_dev)) {
- if (!work_pending(&st->poll_work))
- schedule_work(&st->poll_work);
+ schedule_work(&st->poll_work);
} else {
st->done = true;
wake_up_interruptible(&st->wq_data_avail);
@@ -466,12 +465,11 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq,
struct ad7606_platform_data *pdata = dev->platform_data;
struct ad7606_state *st;
int ret;
- struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+ struct iio_dev *indio_dev;
- if (indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
+ if (!indio_dev)
+ return ERR_PTR(-ENOMEM);
st = iio_priv(indio_dev);
@@ -489,11 +487,11 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq,
st->oversampling = pdata->default_os;
}
- st->reg = regulator_get(dev, "vcc");
+ st->reg = devm_regulator_get(dev, "vcc");
if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);
if (ret)
- goto error_put_reg;
+ return ERR_PTR(ret);
}
st->pdata = pdata;
@@ -554,11 +552,6 @@ error_free_gpios:
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
-error_put_reg:
- if (!IS_ERR(st->reg))
- regulator_put(st->reg);
- iio_device_free(indio_dev);
-error_ret:
return ERR_PTR(ret);
}
@@ -570,13 +563,10 @@ int ad7606_remove(struct iio_dev *indio_dev, int irq)
ad7606_ring_cleanup(indio_dev);
free_irq(irq, indio_dev);
- if (!IS_ERR(st->reg)) {
+ if (!IS_ERR(st->reg))
regulator_disable(st->reg);
- regulator_put(st->reg);
- }
ad7606_free_gpios(st);
- iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c
index 2b25cb07fe41..3bf174cb19b1 100644
--- a/drivers/staging/iio/adc/ad7606_ring.c
+++ b/drivers/staging/iio/adc/ad7606_ring.c
@@ -46,7 +46,6 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s)
struct ad7606_state *st = container_of(work_s, struct ad7606_state,
poll_work);
struct iio_dev *indio_dev = iio_priv_to_dev(st);
- s64 time_ns;
__u8 *buf;
int ret;
@@ -78,12 +77,7 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s)
goto done;
}
- time_ns = iio_get_time_ns();
-
- if (indio_dev->scan_timestamp)
- *((s64 *)(buf + indio_dev->scan_bytes - sizeof(s64))) = time_ns;
-
- iio_push_to_buffers(indio_dev, buf);
+ iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns());
done:
gpio_set_value(st->pdata->gpio_convst, 0);
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c
index e1f88603d7e0..4f2522a9edfb 100644
--- a/drivers/staging/iio/adc/ad7780.c
+++ b/drivers/staging/iio/adc/ad7780.c
@@ -171,7 +171,7 @@ static int ad7780_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
int ret, voltage_uv = 0;
- indio_dev = iio_device_alloc(sizeof(*st));
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
@@ -180,11 +180,11 @@ static int ad7780_probe(struct spi_device *spi)
ad_sd_init(&st->sd, indio_dev, spi, &ad7780_sigma_delta_info);
- st->reg = regulator_get(&spi->dev, "vcc");
+ st->reg = devm_regulator_get(&spi->dev, "vcc");
if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);
if (ret)
- goto error_put_reg;
+ return ret;
voltage_uv = regulator_get_voltage(st->reg);
}
@@ -210,8 +210,8 @@ static int ad7780_probe(struct spi_device *spi)
if (pdata && gpio_is_valid(pdata->gpio_pdrst)) {
- ret = gpio_request_one(pdata->gpio_pdrst, GPIOF_OUT_INIT_LOW,
- "AD7780 /PDRST");
+ ret = devm_gpio_request_one(&spi->dev, pdata->gpio_pdrst,
+ GPIOF_OUT_INIT_LOW, "AD7780 /PDRST");
if (ret) {
dev_err(&spi->dev, "failed to request GPIO PDRST\n");
goto error_disable_reg;
@@ -223,7 +223,7 @@ static int ad7780_probe(struct spi_device *spi)
ret = ad_sd_setup_buffer_and_trigger(indio_dev);
if (ret)
- goto error_free_gpio;
+ goto error_disable_reg;
ret = iio_device_register(indio_dev);
if (ret)
@@ -233,17 +233,9 @@ static int ad7780_probe(struct spi_device *spi)
error_cleanup_buffer_and_trigger:
ad_sd_cleanup_buffer_and_trigger(indio_dev);
-error_free_gpio:
- if (pdata && gpio_is_valid(pdata->gpio_pdrst))
- gpio_free(pdata->gpio_pdrst);
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
-error_put_reg:
- if (!IS_ERR(st->reg))
- regulator_put(st->reg);
-
- iio_device_free(indio_dev);
return ret;
}
@@ -256,14 +248,8 @@ static int ad7780_remove(struct spi_device *spi)
iio_device_unregister(indio_dev);
ad_sd_cleanup_buffer_and_trigger(indio_dev);
- if (gpio_is_valid(st->powerdown_gpio))
- gpio_free(st->powerdown_gpio);
-
- if (!IS_ERR(st->reg)) {
+ if (!IS_ERR(st->reg))
regulator_disable(st->reg);
- regulator_put(st->reg);
- }
- iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c
index 8470036a3378..9f48e5c74eed 100644
--- a/drivers/staging/iio/adc/ad7816.c
+++ b/drivers/staging/iio/adc/ad7816.c
@@ -356,11 +356,9 @@ static int ad7816_probe(struct spi_device *spi_dev)
return -EINVAL;
}
- indio_dev = iio_device_alloc(sizeof(*chip));
- if (indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ indio_dev = devm_iio_device_alloc(&spi_dev->dev, sizeof(*chip));
+ if (!indio_dev)
+ return -ENOMEM;
chip = iio_priv(indio_dev);
/* this is only used for device removal purposes */
dev_set_drvdata(&spi_dev->dev, indio_dev);
@@ -372,25 +370,28 @@ static int ad7816_probe(struct spi_device *spi_dev)
chip->convert_pin = pins[1];
chip->busy_pin = pins[2];
- ret = gpio_request(chip->rdwr_pin, spi_get_device_id(spi_dev)->name);
+ ret = devm_gpio_request(&spi_dev->dev, chip->rdwr_pin,
+ spi_get_device_id(spi_dev)->name);
if (ret) {
dev_err(&spi_dev->dev, "Fail to request rdwr gpio PIN %d.\n",
chip->rdwr_pin);
- goto error_free_device;
+ return ret;
}
gpio_direction_input(chip->rdwr_pin);
- ret = gpio_request(chip->convert_pin, spi_get_device_id(spi_dev)->name);
+ ret = devm_gpio_request(&spi_dev->dev, chip->convert_pin,
+ spi_get_device_id(spi_dev)->name);
if (ret) {
dev_err(&spi_dev->dev, "Fail to request convert gpio PIN %d.\n",
chip->convert_pin);
- goto error_free_gpio_rdwr;
+ return ret;
}
gpio_direction_input(chip->convert_pin);
- ret = gpio_request(chip->busy_pin, spi_get_device_id(spi_dev)->name);
+ ret = devm_gpio_request(&spi_dev->dev, chip->busy_pin,
+ spi_get_device_id(spi_dev)->name);
if (ret) {
dev_err(&spi_dev->dev, "Fail to request busy gpio PIN %d.\n",
chip->busy_pin);
- goto error_free_gpio_convert;
+ return ret;
}
gpio_direction_input(chip->busy_pin);
@@ -401,51 +402,31 @@ static int ad7816_probe(struct spi_device *spi_dev)
if (spi_dev->irq) {
/* Only low trigger is supported in ad7816/7/8 */
- ret = request_threaded_irq(spi_dev->irq,
- NULL,
- &ad7816_event_handler,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- indio_dev->name,
- indio_dev);
+ ret = devm_request_threaded_irq(&spi_dev->dev, spi_dev->irq,
+ NULL,
+ &ad7816_event_handler,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ indio_dev->name,
+ indio_dev);
if (ret)
- goto error_free_gpio;
+ return ret;
}
ret = iio_device_register(indio_dev);
if (ret)
- goto error_free_irq;
+ return ret;
dev_info(&spi_dev->dev, "%s temperature sensor and ADC registered.\n",
indio_dev->name);
return 0;
-error_free_irq:
- free_irq(spi_dev->irq, indio_dev);
-error_free_gpio:
- gpio_free(chip->busy_pin);
-error_free_gpio_convert:
- gpio_free(chip->convert_pin);
-error_free_gpio_rdwr:
- gpio_free(chip->rdwr_pin);
-error_free_device:
- iio_device_free(indio_dev);
-error_ret:
- return ret;
}
static int ad7816_remove(struct spi_device *spi_dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(&spi_dev->dev);
- struct ad7816_chip_info *chip = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
- dev_set_drvdata(&spi_dev->dev, NULL);
- if (spi_dev->irq)
- free_irq(spi_dev->irq, indio_dev);
- gpio_free(chip->busy_pin);
- gpio_free(chip->convert_pin);
- gpio_free(chip->rdwr_pin);
- iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c
index 2b2049c8bc6b..3f5142b284d1 100644
--- a/drivers/staging/iio/adc/ad799x_core.c
+++ b/drivers/staging/iio/adc/ad799x_core.c
@@ -586,8 +586,9 @@ static int ad799x_probe(struct i2c_client *client,
int ret;
struct ad799x_platform_data *pdata = client->dev.platform_data;
struct ad799x_state *st;
- struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+ struct iio_dev *indio_dev;
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
@@ -606,11 +607,11 @@ static int ad799x_probe(struct i2c_client *client,
st->int_vref_mv = pdata->vref_mv;
- st->reg = regulator_get(&client->dev, "vcc");
+ st->reg = devm_regulator_get(&client->dev, "vcc");
if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);
if (ret)
- goto error_put_reg;
+ return ret;
}
st->client = client;
@@ -650,10 +651,6 @@ error_cleanup_ring:
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
-error_put_reg:
- if (!IS_ERR(st->reg))
- regulator_put(st->reg);
- iio_device_free(indio_dev);
return ret;
}
@@ -668,12 +665,9 @@ static int ad799x_remove(struct i2c_client *client)
free_irq(client->irq, indio_dev);
ad799x_ring_cleanup(indio_dev);
- if (!IS_ERR(st->reg)) {
+ if (!IS_ERR(st->reg))
regulator_disable(st->reg);
- regulator_put(st->reg);
- }
kfree(st->rx_buf);
- iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c
index c2ebae12ee19..0ff6c03a483e 100644
--- a/drivers/staging/iio/adc/ad799x_ring.c
+++ b/drivers/staging/iio/adc/ad799x_ring.c
@@ -35,7 +35,6 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct ad799x_state *st = iio_priv(indio_dev);
- s64 time_ns;
int b_sent;
u8 cmd;
@@ -65,13 +64,8 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p)
if (b_sent < 0)
goto out;
- time_ns = iio_get_time_ns();
-
- if (indio_dev->scan_timestamp)
- memcpy(st->rx_buf + indio_dev->scan_bytes - sizeof(s64),
- &time_ns, sizeof(time_ns));
-
- iio_push_to_buffers(indio_dev, st->rx_buf);
+ iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
+ iio_get_time_ns());
out:
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c
index 9a4bb0999b51..ce7ff3e6cd21 100644
--- a/drivers/staging/iio/adc/lpc32xx_adc.c
+++ b/drivers/staging/iio/adc/lpc32xx_adc.c
@@ -137,43 +137,39 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "failed to get platform I/O memory\n");
- retval = -EBUSY;
- goto errout1;
+ return -EBUSY;
}
- iodev = iio_device_alloc(sizeof(struct lpc32xx_adc_info));
- if (!iodev) {
- dev_err(&pdev->dev, "failed allocating iio device\n");
- retval = -ENOMEM;
- goto errout1;
- }
+ iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
+ if (!iodev)
+ return -ENOMEM;
info = iio_priv(iodev);
- info->adc_base = ioremap(res->start, resource_size(res));
+ info->adc_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
if (!info->adc_base) {
dev_err(&pdev->dev, "failed mapping memory\n");
- retval = -EBUSY;
- goto errout2;
+ return -EBUSY;
}
- info->clk = clk_get(&pdev->dev, NULL);
+ info->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(info->clk)) {
dev_err(&pdev->dev, "failed getting clock\n");
- goto errout3;
+ return PTR_ERR(info->clk);
}
irq = platform_get_irq(pdev, 0);
if ((irq < 0) || (irq >= NR_IRQS)) {
dev_err(&pdev->dev, "failed getting interrupt resource\n");
- retval = -EINVAL;
- goto errout4;
+ return -EINVAL;
}
- retval = request_irq(irq, lpc32xx_adc_isr, 0, MOD_NAME, info);
+ retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0,
+ MOD_NAME, info);
if (retval < 0) {
dev_err(&pdev->dev, "failed requesting interrupt\n");
- goto errout4;
+ return retval;
}
platform_set_drvdata(pdev, iodev);
@@ -189,35 +185,18 @@ static int lpc32xx_adc_probe(struct platform_device *pdev)
retval = iio_device_register(iodev);
if (retval)
- goto errout5;
+ return retval;
dev_info(&pdev->dev, "LPC32XX ADC driver loaded, IRQ %d\n", irq);
return 0;
-
-errout5:
- free_irq(irq, info);
-errout4:
- clk_put(info->clk);
-errout3:
- iounmap(info->adc_base);
-errout2:
- iio_device_free(iodev);
-errout1:
- return retval;
}
static int lpc32xx_adc_remove(struct platform_device *pdev)
{
struct iio_dev *iodev = platform_get_drvdata(pdev);
- struct lpc32xx_adc_info *info = iio_priv(iodev);
- int irq = platform_get_irq(pdev, 0);
iio_device_unregister(iodev);
- free_irq(irq, info);
- clk_put(info->clk);
- iounmap(info->adc_base);
- iio_device_free(iodev);
return 0;
}
diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index a08c1736458b..9da64bf00039 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -625,13 +625,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p)
j++;
}
- if (iio->scan_timestamp) {
- s64 *timestamp = (s64 *)((u8 *)lradc->buffer +
- ALIGN(j, sizeof(s64)));
- *timestamp = pf->timestamp;
- }
-
- iio_push_to_buffers(iio, (u8 *)lradc->buffer);
+ iio_push_to_buffers_with_timestamp(iio, lradc->buffer, pf->timestamp);
iio_trigger_notify_done(iio->trig);
@@ -987,7 +981,7 @@ static int mxs_lradc_probe(struct platform_device *pdev)
/* Register the touchscreen input device. */
ret = mxs_lradc_ts_register(lradc);
if (ret)
- goto err_dev;
+ goto err_ts_register;
/* Register IIO device. */
ret = iio_device_register(iio);
@@ -1000,6 +994,8 @@ static int mxs_lradc_probe(struct platform_device *pdev)
err_ts:
mxs_lradc_ts_unregister(lradc);
+err_ts_register:
+ mxs_lradc_hw_stop(lradc);
err_dev:
mxs_lradc_trigger_remove(iio);
err_trig:
@@ -1012,13 +1008,11 @@ static int mxs_lradc_remove(struct platform_device *pdev)
struct iio_dev *iio = platform_get_drvdata(pdev);
struct mxs_lradc *lradc = iio_priv(iio);
+ iio_device_unregister(iio);
mxs_lradc_ts_unregister(lradc);
-
mxs_lradc_hw_stop(lradc);
-
- iio_device_unregister(iio);
- iio_triggered_buffer_cleanup(iio);
mxs_lradc_trigger_remove(iio);
+ iio_triggered_buffer_cleanup(iio);
return 0;
}
@@ -1038,3 +1032,4 @@ module_platform_driver(mxs_lradc_driver);
MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
MODULE_DESCRIPTION("Freescale i.MX28 LRADC driver");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c
index 1e1356825d6d..80266e801d56 100644
--- a/drivers/staging/iio/addac/adt7316.c
+++ b/drivers/staging/iio/addac/adt7316.c
@@ -412,13 +412,13 @@ static ssize_t adt7316_store_ad_channel(struct device *dev,
struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 config2;
- unsigned long data = 0;
+ u8 data;
int ret;
if (!(chip->config2 & ADT7316_AD_SINGLE_CH_MODE))
return -EPERM;
- ret = strict_strtoul(buf, 10, &data);
+ ret = kstrtou8(buf, 10, &data);
if (ret)
return -EINVAL;
@@ -823,10 +823,10 @@ static ssize_t adt7316_store_DAC_2Vref_ch_mask(struct device *dev,
struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 dac_config;
- unsigned long data = 0;
+ u8 data;
int ret;
- ret = strict_strtoul(buf, 16, &data);
+ ret = kstrtou8(buf, 16, &data);
if (ret || data > ADT7316_DA_2VREF_CH_MASK)
return -EINVAL;
@@ -878,13 +878,13 @@ static ssize_t adt7316_store_DAC_update_mode(struct device *dev,
struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 dac_config;
- unsigned long data;
+ u8 data;
int ret;
if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA))
return -EPERM;
- ret = strict_strtoul(buf, 10, &data);
+ ret = kstrtou8(buf, 10, &data);
if (ret || data > ADT7316_DA_EN_MODE_MASK)
return -EINVAL;
@@ -933,7 +933,7 @@ static ssize_t adt7316_store_update_DAC(struct device *dev,
struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 ldac_config;
- unsigned long data;
+ u8 data;
int ret;
if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA) {
@@ -941,7 +941,7 @@ static ssize_t adt7316_store_update_DAC(struct device *dev,
ADT7316_DA_EN_MODE_LDAC)
return -EPERM;
- ret = strict_strtoul(buf, 16, &data);
+ ret = kstrtou8(buf, 16, &data);
if (ret || data > ADT7316_LDAC_EN_DA_MASK)
return -EINVAL;
@@ -1079,11 +1079,11 @@ static ssize_t adt7316_store_DAC_internal_Vref(struct device *dev,
struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
u8 ldac_config;
- unsigned long data;
+ u8 data;
int ret;
if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) {
- ret = strict_strtoul(buf, 16, &data);
+ ret = kstrtou8(buf, 16, &data);
if (ret || data > 3)
return -EINVAL;
@@ -1093,7 +1093,7 @@ static ssize_t adt7316_store_DAC_internal_Vref(struct device *dev,
else if (data & 0x2)
ldac_config |= ADT7516_DAC_CD_IN_VREF;
} else {
- ret = strict_strtoul(buf, 16, &data);
+ ret = kstrtou8(buf, 16, &data);
if (ret)
return -EINVAL;
@@ -1281,11 +1281,11 @@ static ssize_t adt7316_show_temp_offset(struct adt7316_chip_info *chip,
static ssize_t adt7316_store_temp_offset(struct adt7316_chip_info *chip,
int offset_addr, const char *buf, size_t len)
{
- long data;
+ int data;
u8 val;
int ret;
- ret = strict_strtol(buf, 10, &data);
+ ret = kstrtoint(buf, 10, &data);
if (ret || data > 127 || data < -128)
return -EINVAL;
@@ -1442,7 +1442,7 @@ static ssize_t adt7316_store_DAC(struct adt7316_chip_info *chip,
int channel, const char *buf, size_t len)
{
u8 msb, lsb, offset;
- unsigned long data;
+ u16 data;
int ret;
if (channel >= ADT7316_DA_MSB_DATA_REGS ||
@@ -1454,7 +1454,7 @@ static ssize_t adt7316_store_DAC(struct adt7316_chip_info *chip,
offset = chip->dac_bits - 8;
- ret = strict_strtoul(buf, 10, &data);
+ ret = kstrtou16(buf, 10, &data);
if (ret || data >= (1 << chip->dac_bits))
return -EINVAL;
@@ -1830,11 +1830,11 @@ static ssize_t adt7316_set_int_mask(struct device *dev,
{
struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
- unsigned long data;
+ u16 data;
int ret;
u8 mask;
- ret = strict_strtoul(buf, 16, &data);
+ ret = kstrtou16(buf, 16, &data);
if (ret || data >= ADT7316_VDD_INT_MASK + 1)
return -EINVAL;
@@ -1901,7 +1901,7 @@ static inline ssize_t adt7316_set_ad_bound(struct device *dev,
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct iio_dev *dev_info = dev_to_iio_dev(dev);
struct adt7316_chip_info *chip = iio_priv(dev_info);
- long data;
+ int data;
u8 val;
int ret;
@@ -1909,7 +1909,7 @@ static inline ssize_t adt7316_set_ad_bound(struct device *dev,
this_attr->address > ADT7316_EX_TEMP_LOW)
return -EPERM;
- ret = strict_strtol(buf, 10, &data);
+ ret = kstrtoint(buf, 10, &data);
if (ret)
return -EINVAL;
@@ -2106,11 +2106,9 @@ int adt7316_probe(struct device *dev, struct adt7316_bus *bus,
unsigned short *adt7316_platform_data = dev->platform_data;
int ret = 0;
- indio_dev = iio_device_alloc(sizeof(*chip));
- if (indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*chip));
+ if (!indio_dev)
+ return -ENOMEM;
chip = iio_priv(indio_dev);
/* this is only used for device removal purposes */
dev_set_drvdata(dev, indio_dev);
@@ -2146,58 +2144,44 @@ int adt7316_probe(struct device *dev, struct adt7316_bus *bus,
if (adt7316_platform_data[0])
chip->bus.irq_flags = adt7316_platform_data[0];
- ret = request_threaded_irq(chip->bus.irq,
- NULL,
- &adt7316_event_handler,
- chip->bus.irq_flags | IRQF_ONESHOT,
- indio_dev->name,
- indio_dev);
+ ret = devm_request_threaded_irq(dev, chip->bus.irq,
+ NULL,
+ &adt7316_event_handler,
+ chip->bus.irq_flags |
+ IRQF_ONESHOT,
+ indio_dev->name,
+ indio_dev);
if (ret)
- goto error_free_dev;
+ return ret;
if (chip->bus.irq_flags & IRQF_TRIGGER_HIGH)
chip->config1 |= ADT7316_INT_POLARITY;
}
ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, chip->config1);
- if (ret) {
- ret = -EIO;
- goto error_unreg_irq;
- }
+ if (ret)
+ return -EIO;
ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, chip->config3);
- if (ret) {
- ret = -EIO;
- goto error_unreg_irq;
- }
+ if (ret)
+ return -EIO;
ret = iio_device_register(indio_dev);
if (ret)
- goto error_unreg_irq;
+ return ret;
dev_info(dev, "%s temperature sensor, ADC and DAC registered.\n",
indio_dev->name);
return 0;
-
-error_unreg_irq:
- free_irq(chip->bus.irq, indio_dev);
-error_free_dev:
- iio_device_free(indio_dev);
-error_ret:
- return ret;
}
EXPORT_SYMBOL(adt7316_probe);
int adt7316_remove(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct adt7316_chip_info *chip = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
- if (chip->bus.irq)
- free_irq(chip->bus.irq, indio_dev);
- iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/frequency/ad5930.c b/drivers/staging/iio/frequency/ad5930.c
index 69e90e9e60ea..a4aeee6ffdf2 100644
--- a/drivers/staging/iio/frequency/ad5930.c
+++ b/drivers/staging/iio/frequency/ad5930.c
@@ -94,11 +94,9 @@ static int ad5930_probe(struct spi_device *spi)
struct iio_dev *idev;
int ret = 0;
- idev = iio_device_alloc(sizeof(*st));
- if (idev == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ idev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!idev)
+ return -ENOMEM;
spi_set_drvdata(spi, idev);
st = iio_priv(idev);
@@ -110,24 +108,18 @@ static int ad5930_probe(struct spi_device *spi)
ret = iio_device_register(idev);
if (ret)
- goto error_free_dev;
+ return ret;
spi->max_speed_hz = 2000000;
spi->mode = SPI_MODE_3;
spi->bits_per_word = 16;
spi_setup(spi);
return 0;
-
-error_free_dev:
- iio_device_free(idev);
-error_ret:
- return ret;
}
static int ad5930_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c
index 4e18380c5141..c7d0307c8e76 100644
--- a/drivers/staging/iio/frequency/ad9832.c
+++ b/drivers/staging/iio/frequency/ad9832.c
@@ -81,9 +81,9 @@ static ssize_t ad9832_write(struct device *dev,
struct ad9832_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
- long val;
+ unsigned long val;
- ret = strict_strtoul(buf, 10, &val);
+ ret = kstrtoul(buf, 10, &val);
if (ret)
goto error_ret;
@@ -214,14 +214,14 @@ static int ad9832_probe(struct spi_device *spi)
return -ENODEV;
}
- reg = regulator_get(&spi->dev, "vcc");
+ reg = devm_regulator_get(&spi->dev, "vcc");
if (!IS_ERR(reg)) {
ret = regulator_enable(reg);
if (ret)
- goto error_put_reg;
+ return ret;
}
- indio_dev = iio_device_alloc(sizeof(*st));
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_disable_reg;
@@ -279,47 +279,42 @@ static int ad9832_probe(struct spi_device *spi)
ret = spi_sync(st->spi, &st->msg);
if (ret) {
dev_err(&spi->dev, "device init failed\n");
- goto error_free_device;
+ goto error_disable_reg;
}
ret = ad9832_write_frequency(st, AD9832_FREQ0HM, pdata->freq0);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
ret = ad9832_write_frequency(st, AD9832_FREQ1HM, pdata->freq1);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
ret = ad9832_write_phase(st, AD9832_PHASE0H, pdata->phase0);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
ret = ad9832_write_phase(st, AD9832_PHASE1H, pdata->phase1);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
ret = ad9832_write_phase(st, AD9832_PHASE2H, pdata->phase2);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
ret = ad9832_write_phase(st, AD9832_PHASE3H, pdata->phase3);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
ret = iio_device_register(indio_dev);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
return 0;
-error_free_device:
- iio_device_free(indio_dev);
error_disable_reg:
if (!IS_ERR(reg))
regulator_disable(reg);
-error_put_reg:
- if (!IS_ERR(reg))
- regulator_put(reg);
return ret;
}
@@ -330,11 +325,8 @@ static int ad9832_remove(struct spi_device *spi)
struct ad9832_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
- if (!IS_ERR(st->reg)) {
+ if (!IS_ERR(st->reg))
regulator_disable(st->reg);
- regulator_put(st->reg);
- }
- iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c
index 5cba3c01f417..86cda6176093 100644
--- a/drivers/staging/iio/frequency/ad9834.c
+++ b/drivers/staging/iio/frequency/ad9834.c
@@ -70,9 +70,9 @@ static ssize_t ad9834_write(struct device *dev,
struct ad9834_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
- long val;
+ unsigned long val;
- ret = strict_strtoul(buf, 10, &val);
+ ret = kstrtoul(buf, 10, &val);
if (ret)
goto error_ret;
@@ -327,14 +327,14 @@ static int ad9834_probe(struct spi_device *spi)
return -ENODEV;
}
- reg = regulator_get(&spi->dev, "vcc");
+ reg = devm_regulator_get(&spi->dev, "vcc");
if (!IS_ERR(reg)) {
ret = regulator_enable(reg);
if (ret)
- goto error_put_reg;
+ return ret;
}
- indio_dev = iio_device_alloc(sizeof(*st));
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (indio_dev == NULL) {
ret = -ENOMEM;
goto error_disable_reg;
@@ -388,39 +388,35 @@ static int ad9834_probe(struct spi_device *spi)
ret = spi_sync(st->spi, &st->msg);
if (ret) {
dev_err(&spi->dev, "device init failed\n");
- goto error_free_device;
+ goto error_disable_reg;
}
ret = ad9834_write_frequency(st, AD9834_REG_FREQ0, pdata->freq0);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
ret = ad9834_write_frequency(st, AD9834_REG_FREQ1, pdata->freq1);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
ret = ad9834_write_phase(st, AD9834_REG_PHASE0, pdata->phase0);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
ret = ad9834_write_phase(st, AD9834_REG_PHASE1, pdata->phase1);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
ret = iio_device_register(indio_dev);
if (ret)
- goto error_free_device;
+ goto error_disable_reg;
return 0;
-error_free_device:
- iio_device_free(indio_dev);
error_disable_reg:
if (!IS_ERR(reg))
regulator_disable(reg);
-error_put_reg:
- if (!IS_ERR(reg))
- regulator_put(reg);
+
return ret;
}
@@ -430,11 +426,8 @@ static int ad9834_remove(struct spi_device *spi)
struct ad9834_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
- if (!IS_ERR(st->reg)) {
+ if (!IS_ERR(st->reg))
regulator_disable(st->reg);
- regulator_put(st->reg);
- }
- iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/frequency/ad9850.c b/drivers/staging/iio/frequency/ad9850.c
index 01a8a93031f5..af877ff680e9 100644
--- a/drivers/staging/iio/frequency/ad9850.c
+++ b/drivers/staging/iio/frequency/ad9850.c
@@ -80,11 +80,9 @@ static int ad9850_probe(struct spi_device *spi)
struct iio_dev *idev;
int ret = 0;
- idev = iio_device_alloc(sizeof(*st));
- if (idev == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ idev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!idev)
+ return -ENOMEM;
spi_set_drvdata(spi, idev);
st = iio_priv(idev);
mutex_init(&st->lock);
@@ -96,24 +94,18 @@ static int ad9850_probe(struct spi_device *spi)
ret = iio_device_register(idev);
if (ret)
- goto error_free_dev;
+ return ret;
spi->max_speed_hz = 2000000;
spi->mode = SPI_MODE_3;
spi->bits_per_word = 16;
spi_setup(spi);
return 0;
-
-error_free_dev:
- iio_device_free(idev);
-error_ret:
- return ret;
}
static int ad9850_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/frequency/ad9852.c b/drivers/staging/iio/frequency/ad9852.c
index 1344031232bc..4be2cf8c2ab6 100644
--- a/drivers/staging/iio/frequency/ad9852.c
+++ b/drivers/staging/iio/frequency/ad9852.c
@@ -229,11 +229,9 @@ static int ad9852_probe(struct spi_device *spi)
struct iio_dev *idev;
int ret = 0;
- idev = iio_device_alloc(sizeof(*st));
- if (idev == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ idev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!idev)
+ return -ENOMEM;
st = iio_priv(idev);
spi_set_drvdata(spi, idev);
mutex_init(&st->lock);
@@ -245,7 +243,7 @@ static int ad9852_probe(struct spi_device *spi)
ret = iio_device_register(idev);
if (ret)
- goto error_free_dev;
+ return ret;
spi->max_speed_hz = 2000000;
spi->mode = SPI_MODE_3;
spi->bits_per_word = 8;
@@ -253,18 +251,11 @@ static int ad9852_probe(struct spi_device *spi)
ad9852_init(st);
return 0;
-
-error_free_dev:
- iio_device_free(idev);
-
-error_ret:
- return ret;
}
static int ad9852_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/frequency/ad9910.c b/drivers/staging/iio/frequency/ad9910.c
index e48f874c1fc2..a7d528ef620c 100644
--- a/drivers/staging/iio/frequency/ad9910.c
+++ b/drivers/staging/iio/frequency/ad9910.c
@@ -367,11 +367,9 @@ static int ad9910_probe(struct spi_device *spi)
struct iio_dev *idev;
int ret = 0;
- idev = iio_device_alloc(sizeof(*st));
- if (idev == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ idev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!idev)
+ return -ENOMEM;
spi_set_drvdata(spi, idev);
st = iio_priv(idev);
mutex_init(&st->lock);
@@ -383,24 +381,18 @@ static int ad9910_probe(struct spi_device *spi)
ret = iio_device_register(idev);
if (ret)
- goto error_free_dev;
+ return ret;
spi->max_speed_hz = 2000000;
spi->mode = SPI_MODE_3;
spi->bits_per_word = 8;
spi_setup(spi);
ad9910_init(st);
return 0;
-
-error_free_dev:
- iio_device_free(idev);
-error_ret:
- return ret;
}
static int ad9910_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/frequency/ad9951.c b/drivers/staging/iio/frequency/ad9951.c
index 8234e3c915c4..0094c2f392ad 100644
--- a/drivers/staging/iio/frequency/ad9951.c
+++ b/drivers/staging/iio/frequency/ad9951.c
@@ -176,11 +176,9 @@ static int ad9951_probe(struct spi_device *spi)
struct iio_dev *idev;
int ret = 0;
- idev = iio_device_alloc(sizeof(*st));
- if (idev == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ idev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!idev)
+ return -ENOMEM;
spi_set_drvdata(spi, idev);
st = iio_priv(idev);
mutex_init(&st->lock);
@@ -193,25 +191,18 @@ static int ad9951_probe(struct spi_device *spi)
ret = iio_device_register(idev);
if (ret)
- goto error_free_dev;
+ return ret;
spi->max_speed_hz = 2000000;
spi->mode = SPI_MODE_3;
spi->bits_per_word = 8;
spi_setup(spi);
ad9951_init(st);
return 0;
-
-error_free_dev:
- iio_device_free(idev);
-
-error_ret:
- return ret;
}
static int ad9951_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c
index 0e8e02a3cf5b..141ec6188dea 100644
--- a/drivers/staging/iio/iio_simple_dummy.c
+++ b/drivers/staging/iio/iio_simple_dummy.c
@@ -90,6 +90,11 @@ static const struct iio_chan_spec iio_dummy_channels[] = {
* when converting to standard units (microvolts)
*/
BIT(IIO_CHAN_INFO_SCALE),
+ /*
+ * sampling_frequency
+ * The frequency in Hz at which the channels are sampled
+ */
+ .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ),
/* The ordering of elements in the buffer via an enum */
.scan_index = voltage0,
.scan_type = { /* Description of storage in buffer */
@@ -130,6 +135,10 @@ static const struct iio_chan_spec iio_dummy_channels[] = {
* input channels of type IIO_VOLTAGE.
*/
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+ /*
+ * sampling_frequency
+ * The frequency in Hz at which the channels are sampled
+ */
.scan_index = diffvoltage1m2,
.scan_type = { /* Description of storage in buffer */
.sign = 's', /* signed */
@@ -147,6 +156,7 @@ static const struct iio_chan_spec iio_dummy_channels[] = {
.channel2 = 4,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ),
.scan_index = diffvoltage3m4,
.scan_type = {
.sign = 's',
@@ -173,6 +183,7 @@ static const struct iio_chan_spec iio_dummy_channels[] = {
*/
BIT(IIO_CHAN_INFO_CALIBSCALE) |
BIT(IIO_CHAN_INFO_CALIBBIAS),
+ .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ),
.scan_index = accelx,
.scan_type = { /* Description of storage in buffer */
.sign = 's', /* signed */
@@ -272,6 +283,11 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev,
*val2 = st->accel_calibscale->val2;
ret = IIO_VAL_INT_PLUS_MICRO;
break;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = 3;
+ *val2 = 33;
+ ret = IIO_VAL_INT_PLUS_NANO;
+ break;
default:
break;
}
diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c
index 72f400c3cbcb..09c93ac7351a 100644
--- a/drivers/staging/iio/iio_simple_dummy_buffer.c
+++ b/drivers/staging/iio/iio_simple_dummy_buffer.c
@@ -82,11 +82,8 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p)
len += 2;
}
}
- /* Store the timestamp at an 8 byte aligned offset */
- if (indio_dev->scan_timestamp)
- *(s64 *)((u8 *)data + ALIGN(len, sizeof(s64)))
- = iio_get_time_ns();
- iio_push_to_buffers(indio_dev, (u8 *)data);
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data, iio_get_time_ns());
kfree(data);
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
index 6330af656a0f..712f3c22ce64 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -323,10 +323,10 @@ static ssize_t ad5933_store_frequency(struct device *dev,
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5933_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- long val;
+ unsigned long val;
int ret;
- ret = strict_strtoul(buf, 10, &val);
+ ret = kstrtoul(buf, 10, &val);
if (ret)
return ret;
@@ -400,12 +400,12 @@ static ssize_t ad5933_store(struct device *dev,
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad5933_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
- long val;
+ u16 val;
int i, ret = 0;
unsigned short dat;
if (this_attr->address != AD5933_IN_PGA_GAIN) {
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou16(buf, 10, &val);
if (ret)
return ret;
}
@@ -434,7 +434,7 @@ static ssize_t ad5933_store(struct device *dev,
ret = ad5933_cmd(st, 0);
break;
case AD5933_OUT_SETTLING_CYCLES:
- val = clamp(val, 0L, 0x7FFL);
+ val = clamp(val, (u16)0, (u16)0x7FF);
st->settling_cycles = val;
/* 2x, 4x handling, see datasheet */
@@ -448,7 +448,7 @@ static ssize_t ad5933_store(struct device *dev,
AD5933_REG_SETTLING_CYCLES, 2, (u8 *)&dat);
break;
case AD5933_FREQ_POINTS:
- val = clamp(val, 0L, 511L);
+ val = clamp(val, (u16)0, (u16)511);
st->freq_points = val;
dat = cpu_to_be16(val);
@@ -676,7 +676,7 @@ static void ad5933_work(struct work_struct *work)
} else {
buf[0] = be16_to_cpu(buf[0]);
}
- iio_push_to_buffers(indio_dev, (u8 *)buf);
+ iio_push_to_buffers(indio_dev, buf);
} else {
/* no data available - try again later */
schedule_delayed_work(&st->work, st->poll_time_jiffies);
@@ -703,7 +703,9 @@ static int ad5933_probe(struct i2c_client *client,
int ret, voltage_uv = 0;
struct ad5933_platform_data *pdata = client->dev.platform_data;
struct ad5933_state *st;
- struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+ struct iio_dev *indio_dev;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
@@ -716,11 +718,11 @@ static int ad5933_probe(struct i2c_client *client,
else
st->pdata = pdata;
- st->reg = regulator_get(&client->dev, "vcc");
+ st->reg = devm_regulator_get(&client->dev, "vcc");
if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);
if (ret)
- goto error_put_reg;
+ return ret;
voltage_uv = regulator_get_voltage(st->reg);
}
@@ -778,11 +780,6 @@ error_unreg_ring:
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
-error_put_reg:
- if (!IS_ERR(st->reg))
- regulator_put(st->reg);
-
- iio_device_free(indio_dev);
return ret;
}
@@ -795,11 +792,8 @@ static int ad5933_remove(struct i2c_client *client)
iio_device_unregister(indio_dev);
iio_buffer_unregister(indio_dev);
iio_kfifo_free(indio_dev->buffer);
- if (!IS_ERR(st->reg)) {
+ if (!IS_ERR(st->reg))
regulator_disable(st->reg);
- regulator_put(st->reg);
- }
- iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
index e4998e4d4434..488e690388c9 100644
--- a/drivers/staging/iio/light/isl29018.c
+++ b/drivers/staging/iio/light/isl29018.c
@@ -240,7 +240,7 @@ static ssize_t store_range(struct device *dev,
unsigned long lval;
unsigned int new_range;
- if (strict_strtoul(buf, 10, &lval))
+ if (kstrtoul(buf, 10, &lval))
return -EINVAL;
if (!(lval == 1000UL || lval == 4000UL ||
@@ -279,18 +279,18 @@ static ssize_t store_resolution(struct device *dev,
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct isl29018_chip *chip = iio_priv(indio_dev);
int status;
- unsigned long lval;
+ unsigned int val;
unsigned int new_adc_bit;
- if (strict_strtoul(buf, 10, &lval))
+ if (kstrtouint(buf, 10, &val))
return -EINVAL;
- if (!(lval == 4 || lval == 8 || lval == 12 || lval == 16)) {
+ if (!(val == 4 || val == 8 || val == 12 || val == 16)) {
dev_err(dev, "The resolution is not supported\n");
return -EINVAL;
}
mutex_lock(&chip->lock);
- status = isl29018_set_resolution(chip, lval, &new_adc_bit);
+ status = isl29018_set_resolution(chip, val, &new_adc_bit);
if (status < 0) {
mutex_unlock(&chip->lock);
dev_err(dev, "Error in setting resolution\n");
@@ -319,11 +319,11 @@ static ssize_t store_prox_infrared_suppression(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct isl29018_chip *chip = iio_priv(indio_dev);
- unsigned long lval;
+ int val;
- if (strict_strtoul(buf, 10, &lval))
+ if (kstrtoint(buf, 10, &val))
return -EINVAL;
- if (!(lval == 0UL || lval == 1UL)) {
+ if (!(val == 0 || val == 1)) {
dev_err(dev, "The mode is not supported\n");
return -EINVAL;
}
@@ -331,7 +331,7 @@ static ssize_t store_prox_infrared_suppression(struct device *dev,
/* get the "proximity scheme" i.e. if the chip does on chip
infrared suppression (1 means perform on chip suppression) */
mutex_lock(&chip->lock);
- chip->prox_scheme = (int)lval;
+ chip->prox_scheme = val;
mutex_unlock(&chip->lock);
return count;
diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c
index b377dd3b76ad..f8c659568c38 100644
--- a/drivers/staging/iio/light/tsl2583.c
+++ b/drivers/staging/iio/light/tsl2583.c
@@ -493,9 +493,9 @@ static ssize_t taos_power_state_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- unsigned long value;
+ int value;
- if (strict_strtoul(buf, 0, &value))
+ if (kstrtoint(buf, 0, &value))
return -EINVAL;
if (value == 0)
@@ -536,9 +536,9 @@ static ssize_t taos_gain_store(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct tsl2583_chip *chip = iio_priv(indio_dev);
- unsigned long value;
+ int value;
- if (strict_strtoul(buf, 0, &value))
+ if (kstrtoint(buf, 0, &value))
return -EINVAL;
switch (value) {
@@ -582,9 +582,9 @@ static ssize_t taos_als_time_store(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct tsl2583_chip *chip = iio_priv(indio_dev);
- unsigned long value;
+ int value;
- if (strict_strtoul(buf, 0, &value))
+ if (kstrtoint(buf, 0, &value))
return -EINVAL;
if ((value < 50) || (value > 650))
@@ -619,9 +619,9 @@ static ssize_t taos_als_trim_store(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct tsl2583_chip *chip = iio_priv(indio_dev);
- unsigned long value;
+ int value;
- if (strict_strtoul(buf, 0, &value))
+ if (kstrtoint(buf, 0, &value))
return -EINVAL;
if (value)
@@ -644,9 +644,9 @@ static ssize_t taos_als_cal_target_store(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct tsl2583_chip *chip = iio_priv(indio_dev);
- unsigned long value;
+ int value;
- if (strict_strtoul(buf, 0, &value))
+ if (kstrtoint(buf, 0, &value))
return -EINVAL;
if (value)
@@ -671,9 +671,9 @@ static ssize_t taos_do_calibrate(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- unsigned long value;
+ int value;
- if (strict_strtoul(buf, 0, &value))
+ if (kstrtoint(buf, 0, &value))
return -EINVAL;
if (value == 1)
@@ -815,12 +815,9 @@ static int taos_probe(struct i2c_client *clientp,
return -EOPNOTSUPP;
}
- indio_dev = iio_device_alloc(sizeof(*chip));
- if (indio_dev == NULL) {
- ret = -ENOMEM;
- dev_err(&clientp->dev, "iio allocation failed\n");
- goto fail1;
- }
+ indio_dev = devm_iio_device_alloc(&clientp->dev, sizeof(*chip));
+ if (!indio_dev)
+ return -ENOMEM;
chip = iio_priv(indio_dev);
chip->client = clientp;
i2c_set_clientdata(clientp, indio_dev);
@@ -835,14 +832,14 @@ static int taos_probe(struct i2c_client *clientp,
if (ret < 0) {
dev_err(&clientp->dev, "i2c_smbus_write_bytes() to cmd "
"reg failed in taos_probe(), err = %d\n", ret);
- goto fail2;
+ return ret;
}
ret = i2c_smbus_read_byte(clientp);
if (ret < 0) {
dev_err(&clientp->dev, "i2c_smbus_read_byte from "
"reg failed in taos_probe(), err = %d\n", ret);
- goto fail2;
+ return ret;
}
buf[i] = ret;
}
@@ -850,14 +847,14 @@ static int taos_probe(struct i2c_client *clientp,
if (!taos_tsl258x_device(buf)) {
dev_info(&clientp->dev, "i2c device found but does not match "
"expected id in taos_probe()\n");
- goto fail2;
+ return -EINVAL;
}
ret = i2c_smbus_write_byte(clientp, (TSL258X_CMD_REG | TSL258X_CNTRL));
if (ret < 0) {
dev_err(&clientp->dev, "i2c_smbus_write_byte() to cmd reg "
"failed in taos_probe(), err = %d\n", ret);
- goto fail2;
+ return ret;
}
indio_dev->info = &tsl2583_info;
@@ -867,7 +864,7 @@ static int taos_probe(struct i2c_client *clientp,
ret = iio_device_register(indio_dev);
if (ret) {
dev_err(&clientp->dev, "iio registration failed\n");
- goto fail2;
+ return ret;
}
/* Load up the V2 defaults (these are hard coded defaults for now) */
@@ -878,10 +875,6 @@ static int taos_probe(struct i2c_client *clientp,
dev_info(&clientp->dev, "Light sensor found.\n");
return 0;
-fail1:
- iio_device_free(indio_dev);
-fail2:
- return ret;
}
#ifdef CONFIG_PM_SLEEP
@@ -926,7 +919,6 @@ static SIMPLE_DEV_PM_OPS(taos_pm_ops, taos_suspend, taos_resume);
static int taos_remove(struct i2c_client *client)
{
iio_device_unregister(i2c_get_clientdata(client));
- iio_device_free(i2c_get_clientdata(client));
return 0;
}
diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c
index c99f890cc6c6..9c43dcf444c2 100644
--- a/drivers/staging/iio/light/tsl2x7x_core.c
+++ b/drivers/staging/iio/light/tsl2x7x_core.c
@@ -550,7 +550,7 @@ prox_poll_err:
static void tsl2x7x_defaults(struct tsl2X7X_chip *chip)
{
/* If Operational settings defined elsewhere.. */
- if (chip->pdata && chip->pdata->platform_default_settings != 0)
+ if (chip->pdata && chip->pdata->platform_default_settings)
memcpy(&(chip->tsl2x7x_settings),
chip->pdata->platform_default_settings,
sizeof(tsl2x7x_default_settings));
@@ -951,7 +951,6 @@ static ssize_t tsl2x7x_gain_available_show(struct device *dev,
case tsl2771:
case tmd2771:
return snprintf(buf, PAGE_SIZE, "%s\n", "1 8 16 128");
- break;
}
return snprintf(buf, PAGE_SIZE, "%s\n", "1 8 16 120");
@@ -1346,7 +1345,6 @@ static int tsl2x7x_read_raw(struct iio_dev *indio_dev,
break;
default:
return -EINVAL;
- break;
}
break;
case IIO_CHAN_INFO_RAW:
@@ -1366,7 +1364,6 @@ static int tsl2x7x_read_raw(struct iio_dev *indio_dev,
break;
default:
return -EINVAL;
- break;
}
break;
case IIO_CHAN_INFO_CALIBSCALE:
@@ -1419,7 +1416,6 @@ static int tsl2x7x_write_raw(struct iio_dev *indio_dev,
case tsl2772:
case tmd2772:
return -EINVAL;
- break;
}
chip->tsl2x7x_settings.als_gain = 3;
break;
@@ -1431,7 +1427,6 @@ static int tsl2x7x_write_raw(struct iio_dev *indio_dev,
case tsl2771:
case tmd2771:
return -EINVAL;
- break;
}
chip->tsl2x7x_settings.als_gain = 3;
break;
@@ -1508,18 +1503,15 @@ static int tsl2x7x_device_id(unsigned char *id, int target)
case tsl2671:
case tsl2771:
return ((*id & 0xf0) == TRITON_ID);
- break;
case tmd2671:
case tmd2771:
return ((*id & 0xf0) == HALIBUT_ID);
- break;
case tsl2572:
case tsl2672:
case tmd2672:
case tsl2772:
case tmd2772:
return ((*id & 0xf0) == SWORDFISH_ID);
- break;
}
return -EINVAL;
@@ -1851,7 +1843,7 @@ static int tsl2x7x_probe(struct i2c_client *clientp,
struct iio_dev *indio_dev;
struct tsl2X7X_chip *chip;
- indio_dev = iio_device_alloc(sizeof(*chip));
+ indio_dev = devm_iio_device_alloc(&clientp->dev, sizeof(*chip));
if (!indio_dev)
return -ENOMEM;
@@ -1862,22 +1854,21 @@ static int tsl2x7x_probe(struct i2c_client *clientp,
ret = tsl2x7x_i2c_read(chip->client,
TSL2X7X_CHIPID, &device_id);
if (ret < 0)
- goto fail1;
+ return ret;
if ((!tsl2x7x_device_id(&device_id, id->driver_data)) ||
(tsl2x7x_device_id(&device_id, id->driver_data) == -EINVAL)) {
dev_info(&chip->client->dev,
"%s: i2c device found does not match expected id\n",
__func__);
- ret = -EINVAL;
- goto fail1;
+ return -EINVAL;
}
ret = i2c_smbus_write_byte(clientp, (TSL2X7X_CMD_REG | TSL2X7X_CNTRL));
if (ret < 0) {
dev_err(&clientp->dev, "%s: write to cmd reg failed. err = %d\n",
__func__, ret);
- goto fail1;
+ return ret;
}
/* ALS and PROX functions can be invoked via user space poll
@@ -1899,16 +1890,17 @@ static int tsl2x7x_probe(struct i2c_client *clientp,
indio_dev->num_channels = chip->chip_info->chan_table_elements;
if (clientp->irq) {
- ret = request_threaded_irq(clientp->irq,
- NULL,
- &tsl2x7x_event_handler,
- IRQF_TRIGGER_RISING | IRQF_ONESHOT,
- "TSL2X7X_event",
- indio_dev);
+ ret = devm_request_threaded_irq(&clientp->dev, clientp->irq,
+ NULL,
+ &tsl2x7x_event_handler,
+ IRQF_TRIGGER_RISING |
+ IRQF_ONESHOT,
+ "TSL2X7X_event",
+ indio_dev);
if (ret) {
dev_err(&clientp->dev,
"%s: irq request failed", __func__);
- goto fail1;
+ return ret;
}
}
@@ -1921,20 +1913,12 @@ static int tsl2x7x_probe(struct i2c_client *clientp,
if (ret) {
dev_err(&clientp->dev,
"%s: iio registration failed\n", __func__);
- goto fail2;
+ return ret;
}
dev_info(&clientp->dev, "%s Light sensor found.\n", id->name);
return 0;
-
-fail2:
- if (clientp->irq)
- free_irq(clientp->irq, indio_dev);
-fail1:
- iio_device_free(indio_dev);
-
- return ret;
}
static int tsl2x7x_suspend(struct device *dev)
@@ -1980,10 +1964,6 @@ static int tsl2x7x_remove(struct i2c_client *client)
tsl2x7x_chip_off(indio_dev);
iio_device_unregister(indio_dev);
- if (client->irq)
- free_irq(client->irq, indio_dev);
-
- iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
index c3f3f539e787..76e0cf43197e 100644
--- a/drivers/staging/iio/magnetometer/hmc5843.c
+++ b/drivers/staging/iio/magnetometer/hmc5843.c
@@ -643,11 +643,9 @@ static int hmc5843_probe(struct i2c_client *client,
struct iio_dev *indio_dev;
int err = 0;
- indio_dev = iio_device_alloc(sizeof(*data));
- if (indio_dev == NULL) {
- err = -ENOMEM;
- goto exit;
- }
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (indio_dev == NULL)
+ return -ENOMEM;
/* default settings at probe */
data = iio_priv(indio_dev);
@@ -665,24 +663,16 @@ static int hmc5843_probe(struct i2c_client *client,
err = iio_device_register(indio_dev);
if (err)
- goto exit_free2;
+ return err;
return 0;
-
-exit_free2:
- iio_device_free(indio_dev);
-exit:
- return err;
}
static int hmc5843_remove(struct i2c_client *client)
{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
-
- iio_device_unregister(indio_dev);
+ iio_device_unregister(i2c_get_clientdata(client));
/* sleep mode to save power */
hmc5843_configure(client, HMC5843_MODE_SLEEP);
- iio_device_free(indio_dev);
return 0;
}
@@ -691,14 +681,14 @@ static int hmc5843_remove(struct i2c_client *client)
static int hmc5843_suspend(struct device *dev)
{
hmc5843_configure(to_i2c_client(dev), HMC5843_MODE_SLEEP);
+
return 0;
}
static int hmc5843_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
- struct hmc5843_data *data = iio_priv(indio_dev);
+ struct hmc5843_data *data = iio_priv(i2c_get_clientdata(client));
hmc5843_configure(client, data->operating_mode);
@@ -730,6 +720,6 @@ static struct i2c_driver hmc5843_driver = {
};
module_i2c_driver(hmc5843_driver);
-MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti@ti.com");
+MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti@ti.com>");
MODULE_DESCRIPTION("HMC5843/5883/5883L driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
index 74025fbae679..6200335d12f7 100644
--- a/drivers/staging/iio/meter/ade7753.c
+++ b/drivers/staging/iio/meter/ade7753.c
@@ -186,9 +186,9 @@ static ssize_t ade7753_write_8bit(struct device *dev,
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
- long val;
+ u8 val;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou8(buf, 10, &val);
if (ret)
goto error_ret;
ret = ade7753_spi_write_reg_8(dev, this_attr->address, val);
@@ -204,9 +204,9 @@ static ssize_t ade7753_write_16bit(struct device *dev,
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
- long val;
+ u16 val;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou16(buf, 10, &val);
if (ret)
goto error_ret;
ret = ade7753_spi_write_reg_16(dev, this_attr->address, val);
@@ -399,11 +399,11 @@ static ssize_t ade7753_write_frequency(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7753_state *st = iio_priv(indio_dev);
- unsigned long val;
+ u16 val;
int ret;
u16 reg, t;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou16(buf, 10, &val);
if (ret)
return ret;
if (val == 0)
@@ -497,11 +497,9 @@ static int ade7753_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
- indio_dev = iio_device_alloc(sizeof(*st));
- if (indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
/* this is only used for removal purposes */
spi_set_drvdata(spi, indio_dev);
@@ -517,19 +515,13 @@ static int ade7753_probe(struct spi_device *spi)
/* Get the device into a sane initial state */
ret = ade7753_initial_setup(indio_dev);
if (ret)
- goto error_free_dev;
+ return ret;
ret = iio_device_register(indio_dev);
if (ret)
- goto error_free_dev;
+ return ret;
return 0;
-
-error_free_dev:
- iio_device_free(indio_dev);
-
-error_ret:
- return ret;
}
/* fixme, confirm ordering in this function */
@@ -539,7 +531,6 @@ static int ade7753_remove(struct spi_device *spi)
iio_device_unregister(indio_dev);
ade7753_stop_device(&indio_dev->dev);
- iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c
index f649ebe55a04..2e046f6e4fb4 100644
--- a/drivers/staging/iio/meter/ade7754.c
+++ b/drivers/staging/iio/meter/ade7754.c
@@ -186,9 +186,9 @@ static ssize_t ade7754_write_8bit(struct device *dev,
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
- long val;
+ u8 val;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou8(buf, 10, &val);
if (ret)
goto error_ret;
ret = ade7754_spi_write_reg_8(dev, this_attr->address, val);
@@ -204,9 +204,9 @@ static ssize_t ade7754_write_16bit(struct device *dev,
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
- long val;
+ u16 val;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou16(buf, 10, &val);
if (ret)
goto error_ret;
ret = ade7754_spi_write_reg_16(dev, this_attr->address, val);
@@ -419,11 +419,11 @@ static ssize_t ade7754_write_frequency(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7754_state *st = iio_priv(indio_dev);
- unsigned long val;
+ u16 val;
int ret;
u8 reg, t;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou16(buf, 10, &val);
if (ret)
return ret;
if (val == 0)
@@ -520,11 +520,9 @@ static int ade7754_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
- indio_dev = iio_device_alloc(sizeof(*st));
- if (indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
/* this is only used for removal purposes */
spi_set_drvdata(spi, indio_dev);
@@ -540,18 +538,12 @@ static int ade7754_probe(struct spi_device *spi)
/* Get the device into a sane initial state */
ret = ade7754_initial_setup(indio_dev);
if (ret)
- goto error_free_dev;
+ return ret;
ret = iio_device_register(indio_dev);
if (ret)
- goto error_free_dev;
+ return ret;
return 0;
-
-error_free_dev:
- iio_device_free(indio_dev);
-
-error_ret:
- return ret;
}
/* fixme, confirm ordering in this function */
@@ -561,7 +553,6 @@ static int ade7754_remove(struct spi_device *spi)
iio_device_unregister(indio_dev);
ade7754_stop_device(&indio_dev->dev);
- iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c
index 6005d4aab0c3..cba183e24838 100644
--- a/drivers/staging/iio/meter/ade7758_core.c
+++ b/drivers/staging/iio/meter/ade7758_core.c
@@ -269,9 +269,9 @@ static ssize_t ade7758_write_8bit(struct device *dev,
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
- long val;
+ u8 val;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou8(buf, 10, &val);
if (ret)
goto error_ret;
ret = ade7758_spi_write_reg_8(dev, this_attr->address, val);
@@ -287,9 +287,9 @@ static ssize_t ade7758_write_16bit(struct device *dev,
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
- long val;
+ u16 val;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou16(buf, 10, &val);
if (ret)
goto error_ret;
ret = ade7758_spi_write_reg_16(dev, this_attr->address, val);
@@ -502,11 +502,11 @@ static ssize_t ade7758_write_frequency(struct device *dev,
size_t len)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- unsigned long val;
+ u16 val;
int ret;
u8 reg, t;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou16(buf, 10, &val);
if (ret)
return ret;
@@ -849,12 +849,11 @@ static int ade7758_probe(struct spi_device *spi)
{
int ret;
struct ade7758_state *st;
- struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+ struct iio_dev *indio_dev;
- if (indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
st = iio_priv(indio_dev);
/* this is only used for removal purposes */
@@ -862,10 +861,8 @@ static int ade7758_probe(struct spi_device *spi)
/* Allocate the comms buffers */
st->rx = kcalloc(ADE7758_MAX_RX, sizeof(*st->rx), GFP_KERNEL);
- if (st->rx == NULL) {
- ret = -ENOMEM;
- goto error_free_dev;
- }
+ if (!st->rx)
+ return -ENOMEM;
st->tx = kcalloc(ADE7758_MAX_TX, sizeof(*st->tx), GFP_KERNEL);
if (st->tx == NULL) {
ret = -ENOMEM;
@@ -920,9 +917,6 @@ error_free_tx:
kfree(st->tx);
error_free_rx:
kfree(st->rx);
-error_free_dev:
- iio_device_free(indio_dev);
-error_ret:
return ret;
}
@@ -939,8 +933,6 @@ static int ade7758_remove(struct spi_device *spi)
kfree(st->tx);
kfree(st->rx);
- iio_device_free(indio_dev);
-
return 0;
}
diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c
index 7d5db7175578..4080995c99b6 100644
--- a/drivers/staging/iio/meter/ade7758_ring.c
+++ b/drivers/staging/iio/meter/ade7758_ring.c
@@ -69,11 +69,7 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p)
if (ade7758_spi_read_burst(indio_dev) >= 0)
*dat32 = get_unaligned_be32(&st->rx_buf[5]) & 0xFFFFFF;
- /* Guaranteed to be aligned with 8 byte boundary */
- if (indio_dev->scan_timestamp)
- dat64[1] = pf->timestamp;
-
- iio_push_to_buffers(indio_dev, (u8 *)dat64);
+ iio_push_to_buffers_with_timestamp(indio_dev, dat64, pf->timestamp);
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c
index d214ac4932cb..145f896aae2b 100644
--- a/drivers/staging/iio/meter/ade7759.c
+++ b/drivers/staging/iio/meter/ade7759.c
@@ -185,9 +185,9 @@ static ssize_t ade7759_write_8bit(struct device *dev,
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
- long val;
+ u8 val;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou8(buf, 10, &val);
if (ret)
goto error_ret;
ret = ade7759_spi_write_reg_8(dev, this_attr->address, val);
@@ -203,9 +203,9 @@ static ssize_t ade7759_write_16bit(struct device *dev,
{
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
int ret;
- long val;
+ u16 val;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou16(buf, 10, &val);
if (ret)
goto error_ret;
ret = ade7759_spi_write_reg_16(dev, this_attr->address, val);
@@ -360,11 +360,11 @@ static ssize_t ade7759_write_frequency(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7759_state *st = iio_priv(indio_dev);
- unsigned long val;
+ u16 val;
int ret;
u16 reg, t;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou16(buf, 10, &val);
if (ret)
return ret;
if (val == 0)
@@ -444,11 +444,9 @@ static int ade7759_probe(struct spi_device *spi)
struct iio_dev *indio_dev;
/* setup the industrialio driver allocated elements */
- indio_dev = iio_device_alloc(sizeof(*st));
- if (indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
/* this is only used for removal purposes */
spi_set_drvdata(spi, indio_dev);
@@ -463,18 +461,13 @@ static int ade7759_probe(struct spi_device *spi)
/* Get the device into a sane initial state */
ret = ade7759_initial_setup(indio_dev);
if (ret)
- goto error_free_dev;
+ return ret;
ret = iio_device_register(indio_dev);
if (ret)
- goto error_free_dev;
+ return ret;
return 0;
-
-error_free_dev:
- iio_device_free(indio_dev);
-error_ret:
- return ret;
}
/* fixme, confirm ordering in this function */
@@ -484,7 +477,6 @@ static int ade7759_remove(struct spi_device *spi)
iio_device_unregister(indio_dev);
ade7759_stop_device(&indio_dev->dev);
- iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/meter/ade7854-i2c.c b/drivers/staging/iio/meter/ade7854-i2c.c
index db9ef6c86c1e..5b33c7f1aa91 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -208,7 +208,7 @@ static int ade7854_i2c_probe(struct i2c_client *client,
struct ade7854_state *st;
struct iio_dev *indio_dev;
- indio_dev = iio_device_alloc(sizeof(*st));
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
st = iio_priv(indio_dev);
@@ -225,8 +225,6 @@ static int ade7854_i2c_probe(struct i2c_client *client,
st->irq = client->irq;
ret = ade7854_probe(indio_dev, &client->dev);
- if (ret)
- iio_device_free(indio_dev);
return ret;
}
diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c
index 4c6d2041260b..94f73bbbc0fd 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -278,7 +278,7 @@ static int ade7854_spi_probe(struct spi_device *spi)
struct ade7854_state *st;
struct iio_dev *indio_dev;
- indio_dev = iio_device_alloc(sizeof(*st));
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (indio_dev == NULL)
return -ENOMEM;
st = iio_priv(indio_dev);
@@ -296,8 +296,6 @@ static int ade7854_spi_probe(struct spi_device *spi)
ret = ade7854_probe(indio_dev, &spi->dev);
- if (ret)
- iio_device_free(indio_dev);
return ret;
}
diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c
index e8379c0f1173..d620bbd603a3 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -100,9 +100,9 @@ static ssize_t ade7854_write_8bit(struct device *dev,
struct ade7854_state *st = iio_priv(indio_dev);
int ret;
- long val;
+ u8 val;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou8(buf, 10, &val);
if (ret)
goto error_ret;
ret = st->write_reg_8(dev, this_attr->address, val);
@@ -121,9 +121,9 @@ static ssize_t ade7854_write_16bit(struct device *dev,
struct ade7854_state *st = iio_priv(indio_dev);
int ret;
- long val;
+ u16 val;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou16(buf, 10, &val);
if (ret)
goto error_ret;
ret = st->write_reg_16(dev, this_attr->address, val);
@@ -142,9 +142,9 @@ static ssize_t ade7854_write_24bit(struct device *dev,
struct ade7854_state *st = iio_priv(indio_dev);
int ret;
- long val;
+ u32 val;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou32(buf, 10, &val);
if (ret)
goto error_ret;
ret = st->write_reg_24(dev, this_attr->address, val);
@@ -163,9 +163,9 @@ static ssize_t ade7854_write_32bit(struct device *dev,
struct ade7854_state *st = iio_priv(indio_dev);
int ret;
- long val;
+ u32 val;
- ret = strict_strtol(buf, 10, &val);
+ ret = kstrtou32(buf, 10, &val);
if (ret)
goto error_ret;
ret = st->write_reg_32(dev, this_attr->address, val);
@@ -550,7 +550,7 @@ int ade7854_probe(struct iio_dev *indio_dev, struct device *dev)
ret = iio_device_register(indio_dev);
if (ret)
- goto error_free_dev;
+ return ret;
/* Get the device into a sane initial state */
ret = ade7854_initial_setup(indio_dev);
@@ -561,9 +561,6 @@ int ade7854_probe(struct iio_dev *indio_dev, struct device *dev)
error_unreg_dev:
iio_device_unregister(indio_dev);
-error_free_dev:
- iio_device_free(indio_dev);
-
return ret;
}
EXPORT_SYMBOL(ade7854_probe);
@@ -571,7 +568,6 @@ EXPORT_SYMBOL(ade7854_probe);
int ade7854_remove(struct iio_dev *indio_dev)
{
iio_device_unregister(indio_dev);
- iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c
index 71221161aa6b..62d30179301f 100644
--- a/drivers/staging/iio/resolver/ad2s1200.c
+++ b/drivers/staging/iio/resolver/ad2s1200.c
@@ -107,16 +107,16 @@ static int ad2s1200_probe(struct spi_device *spi)
unsigned short *pins = spi->dev.platform_data;
for (pn = 0; pn < AD2S1200_PN; pn++)
- if (gpio_request_one(pins[pn], GPIOF_DIR_OUT, DRV_NAME)) {
- pr_err("%s: request gpio pin %d failed\n",
- DRV_NAME, pins[pn]);
- goto error_ret;
+ ret = devm_gpio_request_one(&spi->dev, pins[pn], GPIOF_DIR_OUT,
+ DRV_NAME);
+ if (ret) {
+ dev_err(&spi->dev, "request gpio pin %d failed\n",
+ pins[pn]);
+ return ret;
}
- indio_dev = iio_device_alloc(sizeof(*st));
- if (indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
spi_set_drvdata(spi, indio_dev);
st = iio_priv(indio_dev);
mutex_init(&st->lock);
@@ -133,26 +133,18 @@ static int ad2s1200_probe(struct spi_device *spi)
ret = iio_device_register(indio_dev);
if (ret)
- goto error_free_dev;
+ return ret;
spi->max_speed_hz = AD2S1200_HZ;
spi->mode = SPI_MODE_3;
spi_setup(spi);
return 0;
-
-error_free_dev:
- iio_device_free(indio_dev);
-error_ret:
- for (--pn; pn >= 0; pn--)
- gpio_free(pins[pn]);
- return ret;
}
static int ad2s1200_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c
index dcdadbbcf7e8..6966d5f76648 100644
--- a/drivers/staging/iio/resolver/ad2s1210.c
+++ b/drivers/staging/iio/resolver/ad2s1210.c
@@ -206,10 +206,10 @@ static ssize_t ad2s1210_store_fclkin(struct device *dev,
size_t len)
{
struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
- unsigned long fclkin;
+ unsigned int fclkin;
int ret;
- ret = strict_strtoul(buf, 10, &fclkin);
+ ret = kstrtouint(buf, 10, &fclkin);
if (ret)
return ret;
if (fclkin < AD2S1210_MIN_CLKIN || fclkin > AD2S1210_MAX_CLKIN) {
@@ -243,10 +243,10 @@ static ssize_t ad2s1210_store_fexcit(struct device *dev,
const char *buf, size_t len)
{
struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
- unsigned long fexcit;
+ unsigned int fexcit;
int ret;
- ret = strict_strtoul(buf, 10, &fexcit);
+ ret = kstrtouint(buf, 10, &fexcit);
if (ret < 0)
return ret;
if (fexcit < AD2S1210_MIN_EXCIT || fexcit > AD2S1210_MAX_EXCIT) {
@@ -282,11 +282,11 @@ static ssize_t ad2s1210_store_control(struct device *dev,
const char *buf, size_t len)
{
struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
- unsigned long udata;
+ unsigned char udata;
unsigned char data;
int ret;
- ret = strict_strtoul(buf, 16, &udata);
+ ret = kstrtou8(buf, 16, &udata);
if (ret)
return -EINVAL;
@@ -337,10 +337,10 @@ static ssize_t ad2s1210_store_resolution(struct device *dev,
{
struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
unsigned char data;
- unsigned long udata;
+ unsigned char udata;
int ret;
- ret = strict_strtoul(buf, 10, &udata);
+ ret = kstrtou8(buf, 10, &udata);
if (ret || udata < 10 || udata > 16) {
pr_err("ad2s1210: resolution out of range\n");
return -EINVAL;
@@ -438,11 +438,11 @@ static ssize_t ad2s1210_store_reg(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len)
{
struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
- unsigned long data;
+ unsigned char data;
int ret;
struct iio_dev_attr *iattr = to_iio_dev_attr(attr);
- ret = strict_strtoul(buf, 10, &data);
+ ret = kstrtou8(buf, 10, &data);
if (ret)
return -EINVAL;
mutex_lock(&st->lock);
@@ -669,16 +669,14 @@ static int ad2s1210_probe(struct spi_device *spi)
if (spi->dev.platform_data == NULL)
return -EINVAL;
- indio_dev = iio_device_alloc(sizeof(*st));
- if (indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
st = iio_priv(indio_dev);
st->pdata = spi->dev.platform_data;
ret = ad2s1210_setup_gpios(st);
if (ret < 0)
- goto error_free_dev;
+ return ret;
spi_set_drvdata(spi, indio_dev);
@@ -709,9 +707,6 @@ static int ad2s1210_probe(struct spi_device *spi)
error_free_gpios:
ad2s1210_free_gpios(st);
-error_free_dev:
- iio_device_free(indio_dev);
-error_ret:
return ret;
}
@@ -721,7 +716,6 @@ static int ad2s1210_remove(struct spi_device *spi)
iio_device_unregister(indio_dev);
ad2s1210_free_gpios(iio_priv(indio_dev));
- iio_device_free(indio_dev);
return 0;
}
diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c
index 40b825286d4a..e24c5890652f 100644
--- a/drivers/staging/iio/resolver/ad2s90.c
+++ b/drivers/staging/iio/resolver/ad2s90.c
@@ -64,11 +64,9 @@ static int ad2s90_probe(struct spi_device *spi)
struct ad2s90_state *st;
int ret = 0;
- indio_dev = iio_device_alloc(sizeof(*st));
- if (indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
st = iio_priv(indio_dev);
spi_set_drvdata(spi, indio_dev);
@@ -83,7 +81,7 @@ static int ad2s90_probe(struct spi_device *spi)
ret = iio_device_register(indio_dev);
if (ret)
- goto error_free_dev;
+ return ret;
/* need 600ns between CS and the first falling edge of SCLK */
spi->max_speed_hz = 830000;
@@ -91,17 +89,11 @@ static int ad2s90_probe(struct spi_device *spi)
spi_setup(spi);
return 0;
-
-error_free_dev:
- iio_device_free(indio_dev);
-error_ret:
- return ret;
}
static int ad2s90_remove(struct spi_device *spi)
{
iio_device_unregister(spi_get_drvdata(spi));
- iio_device_free(spi_get_drvdata(spi));
return 0;
}
diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
index 38a158b77b1d..ebb189c68d88 100644
--- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
+++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
@@ -83,32 +83,28 @@ static ssize_t iio_bfin_tmr_frequency_store(struct device *dev,
{
struct iio_trigger *trig = to_iio_trigger(dev);
struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig);
- unsigned long val;
+ unsigned int val;
bool enabled;
int ret;
- ret = strict_strtoul(buf, 10, &val);
+ ret = kstrtouint(buf, 10, &val);
if (ret)
- goto error_ret;
+ return ret;
if (val > 100000) {
- ret = -EINVAL;
- goto error_ret;
- }
+ return -EINVAL;
enabled = get_enabled_gptimers() & st->t->bit;
if (enabled)
disable_gptimers(st->t->bit);
- if (!val)
- goto error_ret;
+ if (val == 0)
+ return count;
val = get_sclk() / val;
- if (val <= 4 || val <= st->duty) {
- ret = -EINVAL;
- goto error_ret;
- }
+ if (val <= 4 || val <= st->duty)
+ return -EINVAL;
set_gptimer_period(st->t->id, val);
set_gptimer_pwidth(st->t->id, val - st->duty);
@@ -116,8 +112,7 @@ static ssize_t iio_bfin_tmr_frequency_store(struct device *dev,
if (enabled)
enable_gptimers(st->t->bit);
-error_ret:
- return ret ? ret : count;
+ return count;
}
static ssize_t iio_bfin_tmr_frequency_show(struct device *dev,
diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
index 79695974b1d4..48a6afa84088 100644
--- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
@@ -53,10 +53,10 @@ static ssize_t iio_trig_periodic_write_freq(struct device *dev,
{
struct iio_trigger *trig = to_iio_trigger(dev);
struct iio_prtc_trigger_info *trig_info = iio_trigger_get_drvdata(trig);
- unsigned long val;
+ int val;
int ret;
- ret = strict_strtoul(buf, 10, &val);
+ ret = kstrtoint(buf, 10, &val);
if (ret)
goto error_ret;
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
index 47c5888461ff..a2e52a0c53c9 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -41,7 +41,6 @@ struct imx_drm_device {
struct list_head encoder_list;
struct list_head connector_list;
struct mutex mutex;
- int references;
int pipes;
struct drm_fbdev_cma *fbhelper;
};
@@ -241,8 +240,6 @@ struct drm_device *imx_drm_device_get(void)
}
}
- imxdrm->references++;
-
return imxdrm->drm;
unwind_crtc:
@@ -280,8 +277,6 @@ void imx_drm_device_put(void)
list_for_each_entry(enc, &imxdrm->encoder_list, list)
module_put(enc->owner);
- imxdrm->references--;
-
mutex_unlock(&imxdrm->mutex);
}
EXPORT_SYMBOL_GPL(imx_drm_device_put);
@@ -485,7 +480,7 @@ int imx_drm_add_crtc(struct drm_crtc *crtc,
mutex_lock(&imxdrm->mutex);
- if (imxdrm->references) {
+ if (imxdrm->drm->open_count) {
ret = -EBUSY;
goto err_busy;
}
@@ -564,7 +559,7 @@ int imx_drm_add_encoder(struct drm_encoder *encoder,
mutex_lock(&imxdrm->mutex);
- if (imxdrm->references) {
+ if (imxdrm->drm->open_count) {
ret = -EBUSY;
goto err_busy;
}
@@ -709,7 +704,7 @@ int imx_drm_add_connector(struct drm_connector *connector,
mutex_lock(&imxdrm->mutex);
- if (imxdrm->references) {
+ if (imxdrm->drm->open_count) {
ret = -EBUSY;
goto err_busy;
}
diff --git a/drivers/staging/imx-drm/imx-ldb.c b/drivers/staging/imx-drm/imx-ldb.c
index af733ea48565..b81ed41766b9 100644
--- a/drivers/staging/imx-drm/imx-ldb.c
+++ b/drivers/staging/imx-drm/imx-ldb.c
@@ -421,7 +421,7 @@ static const char *imx_ldb_bit_mappings[] = {
[LVDS_BIT_MAP_JEIDA] = "jeida",
};
-const int of_get_data_mapping(struct device_node *np)
+static const int of_get_data_mapping(struct device_node *np)
{
const char *bm;
int ret, i;
diff --git a/drivers/staging/lustre/lustre/Kconfig b/drivers/staging/lustre/lustre/Kconfig
index 2156a44d0740..93d59b6a60da 100644
--- a/drivers/staging/lustre/lustre/Kconfig
+++ b/drivers/staging/lustre/lustre/Kconfig
@@ -16,7 +16,7 @@ config LUSTRE_FS
this file system support as a module, choose M here: the module will
be called lustre.
- To mount Lustre file systems , you also need to install the user space
+ To mount Lustre file systems, you also need to install the user space
mount.lustre and other user space commands which can be found in the
lustre-client package, available from
http://downloads.whamcloud.com/public/lustre/
diff --git a/drivers/staging/lustre/lustre/libcfs/hash.c b/drivers/staging/lustre/lustre/libcfs/hash.c
index 0dd12c8c91b6..29ce3807fc88 100644
--- a/drivers/staging/lustre/lustre/libcfs/hash.c
+++ b/drivers/staging/lustre/lustre/libcfs/hash.c
@@ -1965,7 +1965,7 @@ cfs_hash_rehash_worker(cfs_workitem_t *wi)
if (bkts != NULL)
cfs_hash_buckets_free(bkts, bsize, new_size, old_size);
if (rc != 0)
- CDEBUG(D_INFO, "early quit of of rehashing: %d\n", rc);
+ CDEBUG(D_INFO, "early quit of rehashing: %d\n", rc);
/* return 1 only if cfs_wi_exit is called */
return rc == -ESRCH;
}
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c
index ea9e9490031f..6a26c6664f88 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c
@@ -167,7 +167,7 @@ static int cfs_access_process_vm(struct task_struct *tsk, unsigned long addr,
return 0;
down_read(&mm->mmap_sem);
- /* ignore errors, just check how much was sucessfully transfered */
+ /* ignore errors, just check how much was successfully transferred */
while (len) {
int bytes, rc, offset;
void *maddr;
diff --git a/drivers/staging/lustre/lustre/libcfs/prng.c b/drivers/staging/lustre/lustre/libcfs/prng.c
index 69224d84bc4b..f87e9e516546 100644
--- a/drivers/staging/lustre/lustre/libcfs/prng.c
+++ b/drivers/staging/lustre/lustre/libcfs/prng.c
@@ -70,7 +70,7 @@ static unsigned int seed_y = 362436069;
* cfs_rand - creates new seeds
*
* First it creates new seeds from the previous seeds. Then it generates a
- * new psuedo random number for use.
+ * new pseudo random number for use.
*
* Returns a pseudo-random 32-bit integer
*/
@@ -84,7 +84,7 @@ unsigned int cfs_rand(void)
EXPORT_SYMBOL(cfs_rand);
/**
- * cfs_srand - sets the inital seed
+ * cfs_srand - sets the initial seed
* @seed1 : (seed_x) should have the most entropy in the low bits of the word
* @seed2 : (seed_y) should have the most entropy in the high bits of the word
*
diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c
index 09844be5eec4..1f079034bd8f 100644
--- a/drivers/staging/lustre/lustre/llite/dir.c
+++ b/drivers/staging/lustre/lustre/llite/dir.c
@@ -743,7 +743,7 @@ int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump,
/* In the following we use the fact that LOV_USER_MAGIC_V1 and
LOV_USER_MAGIC_V3 have the same initial fields so we do not
- need the make the distiction between the 2 versions */
+ need to make the distinction between the 2 versions */
if (set_default && mgc->u.cli.cl_mgc_mgsexp) {
char *param = NULL;
char *buf;
diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c
index bc534db12431..8c4b4fa0d59b 100644
--- a/drivers/staging/lustre/lustre/llite/file.c
+++ b/drivers/staging/lustre/lustre/llite/file.c
@@ -364,7 +364,7 @@ static int ll_intent_file_open(struct file *file, void *lmm,
that case that lock is also ok */
/* We can also get here if there was cached open handle in revalidate_it
* but it disappeared while we were getting from there to ll_file_open.
- * But this means this file was closed and immediatelly opened which
+ * But this means this file was closed and immediately opened which
* makes a good candidate for using OPEN lock */
/* If lmmsize & lmm are not 0, we are just setting stripe info
* parameters. No need for the open lock */
@@ -2456,8 +2456,8 @@ static int ll_inode_revalidate_fini(struct inode *inode, int rc)
if (rc == -ENOENT) {
clear_nlink(inode);
/* This path cannot be hit for regular files unless in
- * case of obscure races, so no need to to validate
- * size. */
+ * case of obscure races, so no need to validate size.
+ */
if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
return 0;
} else if (rc != 0) {
diff --git a/drivers/staging/lustre/lustre/llite/llite_close.c b/drivers/staging/lustre/lustre/llite/llite_close.c
index 1f5825c87a79..e2996c46b2c0 100644
--- a/drivers/staging/lustre/lustre/llite/llite_close.c
+++ b/drivers/staging/lustre/lustre/llite/llite_close.c
@@ -159,7 +159,7 @@ void ll_ioepoch_close(struct inode *inode, struct md_op_data *op_data,
}
if (flags & LLIF_DONE_WRITING) {
/* Some pages are still dirty, it is early to send
- * DONE_WRITE. Wait untill all pages will be flushed
+ * DONE_WRITE. Wait until all pages will be flushed
* and try DONE_WRITE again later. */
LASSERT(!(lli->lli_flags & LLIF_DONE_WRITING));
lli->lli_flags |= LLIF_DONE_WRITING;
diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c
index 8eaa38e91b99..f6b5f4b95f37 100644
--- a/drivers/staging/lustre/lustre/llite/statahead.c
+++ b/drivers/staging/lustre/lustre/llite/statahead.c
@@ -647,7 +647,7 @@ static void ll_post_statahead(struct ll_statahead_info *sai)
*/
LASSERT(fid_is_zero(&minfo->mi_data.op_fid2));
- /* XXX: No fid in reply, this is probaly cross-ref case.
+ /* XXX: No fid in reply, this is probably cross-ref case.
* SA can't handle it yet. */
if (body->valid & OBD_MD_MDS)
GOTO(out, rc = -EAGAIN);
diff --git a/drivers/staging/lustre/lustre/lvfs/fsfilt.c b/drivers/staging/lustre/lustre/lvfs/fsfilt.c
index e86df7356cb1..0d6ed69ddb22 100644
--- a/drivers/staging/lustre/lustre/lvfs/fsfilt.c
+++ b/drivers/staging/lustre/lustre/lvfs/fsfilt.c
@@ -50,9 +50,8 @@ static struct fsfilt_operations *fsfilt_search_type(const char *type)
list_for_each(p, &fsfilt_types) {
found = list_entry(p, struct fsfilt_operations, fs_list);
- if (!strcmp(found->fs_type, type)) {
+ if (!strcmp(found->fs_type, type))
return found;
- }
}
return NULL;
}
@@ -62,7 +61,8 @@ int fsfilt_register_ops(struct fsfilt_operations *fs_ops)
struct fsfilt_operations *found;
/* lock fsfilt_types list */
- if ((found = fsfilt_search_type(fs_ops->fs_type))) {
+ found = fsfilt_search_type(fs_ops->fs_type);
+ if (found) {
if (found != fs_ops) {
CERROR("different operations for type %s\n",
fs_ops->fs_type);
@@ -103,14 +103,16 @@ struct fsfilt_operations *fsfilt_get_ops(const char *type)
struct fsfilt_operations *fs_ops;
/* lock fsfilt_types list */
- if (!(fs_ops = fsfilt_search_type(type))) {
+ fs_ops = fsfilt_search_type(type);
+ if (!fs_ops) {
char name[32];
int rc;
snprintf(name, sizeof(name) - 1, "fsfilt_%s", type);
name[sizeof(name) - 1] = '\0';
- if (!(rc = request_module("%s", name))) {
+ rc = request_module("%s", name);
+ if (!rc) {
fs_ops = fsfilt_search_type(type);
CDEBUG(D_INFO, "Loaded module '%s'\n", name);
if (!fs_ops)
diff --git a/drivers/staging/lustre/lustre/lvfs/lvfs_lib.c b/drivers/staging/lustre/lustre/lvfs/lvfs_lib.c
index 97a8be2300dd..b21e40cdacab 100644
--- a/drivers/staging/lustre/lustre/lvfs/lvfs_lib.c
+++ b/drivers/staging/lustre/lustre/lvfs/lvfs_lib.c
@@ -154,11 +154,10 @@ int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid)
spin_lock(&stats->ls_lock);
if (stats->ls_biggest_alloc_num <= cpuid)
stats->ls_biggest_alloc_num = cpuid + 1;
- if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) {
+ if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
spin_unlock_irqrestore(&stats->ls_lock, flags);
- } else {
+ else
spin_unlock(&stats->ls_lock);
- }
}
/* initialize the ls_percpu[cpuid] non-zero counter */
for (i = 0; i < stats->ls_num; ++i) {
diff --git a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c
index 18e1b47a1d65..f6268dcec542 100644
--- a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c
+++ b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c
@@ -80,7 +80,8 @@ static void push_group_info(struct lvfs_run_ctxt *save,
struct cred *cred;
task_lock(current);
save->group_info = current_cred()->group_info;
- if ((cred = prepare_creds())) {
+ cred = prepare_creds();
+ if (cred) {
cred->group_info = ginfo;
commit_creds(cred);
}
@@ -96,7 +97,8 @@ static void pop_group_info(struct lvfs_run_ctxt *save,
} else {
struct cred *cred;
task_lock(current);
- if ((cred = prepare_creds())) {
+ cred = prepare_creds();
+ if (cred) {
cred->group_info = save->group_info;
commit_creds(cred);
}
@@ -137,7 +139,8 @@ void push_ctxt(struct lvfs_run_ctxt *save, struct lvfs_run_ctxt *new_ctx,
save->luc.luc_fsgid = current_fsgid();
save->luc.luc_cap = current_cap();
- if ((cred = prepare_creds())) {
+ cred = prepare_creds();
+ if (cred) {
cred->uid = uc->luc_uid;
cred->gid = uc->luc_gid;
cred->fsuid = uc->luc_fsuid;
@@ -180,7 +183,8 @@ void pop_ctxt(struct lvfs_run_ctxt *saved, struct lvfs_run_ctxt *new_ctx,
current->fs->umask = saved->luc.luc_umask;
if (uc) {
struct cred *cred;
- if ((cred = prepare_creds())) {
+ cred = prepare_creds();
+ if (cred) {
cred->uid = saved->luc.luc_uid;
cred->gid = saved->luc.luc_gid;
cred->fsuid = saved->luc.luc_fsuid;
@@ -253,31 +257,31 @@ __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
return 0;
switch (field) {
- case LPROCFS_FIELDS_FLAGS_CONFIG:
- ret = header->lc_config;
- break;
- case LPROCFS_FIELDS_FLAGS_SUM:
- ret = lc->lc_sum;
- if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
- ret += lc->lc_sum_irq;
- break;
- case LPROCFS_FIELDS_FLAGS_MIN:
- ret = lc->lc_min;
- break;
- case LPROCFS_FIELDS_FLAGS_MAX:
- ret = lc->lc_max;
- break;
- case LPROCFS_FIELDS_FLAGS_AVG:
- ret = (lc->lc_max - lc->lc_min) / 2;
- break;
- case LPROCFS_FIELDS_FLAGS_SUMSQUARE:
- ret = lc->lc_sumsquare;
- break;
- case LPROCFS_FIELDS_FLAGS_COUNT:
- ret = lc->lc_count;
- break;
- default:
- break;
+ case LPROCFS_FIELDS_FLAGS_CONFIG:
+ ret = header->lc_config;
+ break;
+ case LPROCFS_FIELDS_FLAGS_SUM:
+ ret = lc->lc_sum;
+ if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
+ ret += lc->lc_sum_irq;
+ break;
+ case LPROCFS_FIELDS_FLAGS_MIN:
+ ret = lc->lc_min;
+ break;
+ case LPROCFS_FIELDS_FLAGS_MAX:
+ ret = lc->lc_max;
+ break;
+ case LPROCFS_FIELDS_FLAGS_AVG:
+ ret = (lc->lc_max - lc->lc_min) / 2;
+ break;
+ case LPROCFS_FIELDS_FLAGS_SUMSQUARE:
+ ret = lc->lc_sumsquare;
+ break;
+ case LPROCFS_FIELDS_FLAGS_COUNT:
+ ret = lc->lc_count;
+ break;
+ default:
+ break;
};
return ret;
diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c
index 2644edf438c1..c8b43442dc74 100644
--- a/drivers/staging/lustre/lustre/obdecho/echo_client.c
+++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c
@@ -1387,7 +1387,7 @@ echo_copyout_lsm (struct lov_stripe_md *lsm, void *_ulsm, int ulsm_nob)
if (nob > ulsm_nob)
return (-EINVAL);
- if (copy_to_user (ulsm, lsm, sizeof(ulsm)))
+ if (copy_to_user (ulsm, lsm, sizeof(*ulsm)))
return (-EFAULT);
for (i = 0; i < lsm->lsm_stripe_count; i++) {
diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
index 6547f46a7729..316103ab7c3c 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
@@ -207,7 +207,7 @@ static void enc_pools_release_free_pages(long npages)
p_idx++;
g_idx = 0;
}
- };
+ }
/* free unused pools */
while (p_idx_max1 < p_idx_max2) {
diff --git a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c b/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c
index a4c589604b02..9a6d5c0b1339 100644
--- a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c
@@ -346,7 +346,7 @@ static int enc_get_mpeg_dma(struct solo_dev *solo_dev, dma_addr_t dma,
/* Build a descriptor queue out of an SG list and send it to the P2M for
* processing. */
static int solo_send_desc(struct solo_enc_dev *solo_enc, int skip,
- struct vb2_dma_sg_desc *vbuf, int off, int size,
+ struct sg_table *vbuf, int off, int size,
unsigned int base, unsigned int base_size)
{
struct solo_dev *solo_dev = solo_enc->solo_dev;
@@ -359,7 +359,7 @@ static int solo_send_desc(struct solo_enc_dev *solo_enc, int skip,
solo_enc->desc_count = 1;
- for_each_sg(vbuf->sglist, sg, vbuf->num_pages, i) {
+ for_each_sg(vbuf->sgl, sg, vbuf->nents, i) {
struct solo_p2m_desc *desc;
dma_addr_t dma;
int len;
@@ -434,7 +434,7 @@ static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
struct vb2_buffer *vb, struct vop_header *vh)
{
struct solo_dev *solo_dev = solo_enc->solo_dev;
- struct vb2_dma_sg_desc *vbuf = vb2_dma_sg_plane_desc(vb, 0);
+ struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
int frame_size;
int ret;
@@ -443,7 +443,7 @@ static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
if (vb2_plane_size(vb, 0) < vh->jpeg_size + solo_enc->jpeg_len)
return -EIO;
- sg_copy_from_buffer(vbuf->sglist, vbuf->num_pages,
+ sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
solo_enc->jpeg_header,
solo_enc->jpeg_len);
@@ -451,12 +451,12 @@ static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
& ~(DMA_ALIGN - 1);
vb2_set_plane_payload(vb, 0, vh->jpeg_size + solo_enc->jpeg_len);
- dma_map_sg(&solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages,
+ dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
DMA_FROM_DEVICE);
ret = solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf, vh->jpeg_off,
frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
SOLO_JPEG_EXT_SIZE(solo_dev));
- dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages,
+ dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
DMA_FROM_DEVICE);
return ret;
}
@@ -465,7 +465,7 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
struct vb2_buffer *vb, struct vop_header *vh)
{
struct solo_dev *solo_dev = solo_enc->solo_dev;
- struct vb2_dma_sg_desc *vbuf = vb2_dma_sg_plane_desc(vb, 0);
+ struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
int frame_off, frame_size;
int skip = 0;
int ret;
@@ -475,7 +475,7 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
/* If this is a key frame, add extra header */
if (!vh->vop_type) {
- sg_copy_from_buffer(vbuf->sglist, vbuf->num_pages,
+ sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
solo_enc->vop,
solo_enc->vop_len);
@@ -494,12 +494,12 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
frame_size = (vh->mpeg_size + skip + (DMA_ALIGN - 1))
& ~(DMA_ALIGN - 1);
- dma_map_sg(&solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages,
+ dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
DMA_FROM_DEVICE);
ret = solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
SOLO_MP4E_EXT_ADDR(solo_dev),
SOLO_MP4E_EXT_SIZE(solo_dev));
- dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sglist, vbuf->num_pages,
+ dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
DMA_FROM_DEVICE);
return ret;
}
diff --git a/drivers/staging/netlogic/xlr_net.h b/drivers/staging/netlogic/xlr_net.h
index f91d27e9d7c4..cea796633711 100644
--- a/drivers/staging/netlogic/xlr_net.h
+++ b/drivers/staging/netlogic/xlr_net.h
@@ -1096,4 +1096,4 @@ struct xlr_net_priv {
u64 *class_3_spill;
};
-extern void xlr_set_gmac_speed(struct xlr_net_priv *priv);
+void xlr_set_gmac_speed(struct xlr_net_priv *priv);
diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c
index d7b3c82b5ead..45dfe94199ae 100644
--- a/drivers/staging/octeon-usb/cvmx-usb.c
+++ b/drivers/staging/octeon-usb/cvmx-usb.c
@@ -604,7 +604,7 @@ int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number,
}
}
- memset(usb, 0, sizeof(usb));
+ memset(usb, 0, sizeof(*usb));
usb->init_flags = flags;
/* Initialize the USB state structure */
diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c
index e14a1bb04361..8897d2d38578 100644
--- a/drivers/staging/octeon/ethernet-rx.c
+++ b/drivers/staging/octeon/ethernet-rx.c
@@ -72,7 +72,7 @@ struct cvm_oct_core_state {
int baseline_cores;
/*
* The number of additional cores that could be processing
- * input packtes.
+ * input packets.
*/
atomic_t available_cores;
cpumask_t cpu_state;
@@ -526,7 +526,7 @@ void cvm_oct_rx_initialize(void)
cvm_oct_napi_poll, rx_napi_weight);
napi_enable(&cvm_oct_napi[i].napi);
}
- /* Register an IRQ hander for to receive POW interrupts */
+ /* Register an IRQ handler to receive POW interrupts */
i = request_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group,
cvm_oct_do_interrupt, 0, "Ethernet", cvm_oct_device);
diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c
index 5631dd9f8201..dbfef1a05176 100644
--- a/drivers/staging/octeon/ethernet-tx.c
+++ b/drivers/staging/octeon/ethernet-tx.c
@@ -709,7 +709,7 @@ void cvm_oct_tx_initialize(void)
/* Disable the interrupt. */
cvmx_write_csr(CVMX_CIU_TIMX(1), 0);
- /* Register an IRQ hander for to receive CIU_TIMX(1) interrupts */
+ /* Register an IRQ handler to receive CIU_TIMX(1) interrupts */
i = request_irq(OCTEON_IRQ_TIMER1,
cvm_oct_tx_cleanup_watchdog, 0,
"Ethernet", cvm_oct_device);
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c
index 198595e8d742..92b02891704d 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon.c
@@ -383,7 +383,7 @@ static void dcon_set_source(struct dcon_priv *dcon, int arg)
dcon->pending_src = arg;
- if ((dcon->curr_src != arg) && !work_pending(&dcon->switch_source))
+ if (dcon->curr_src != arg)
schedule_work(&dcon->switch_source);
}
diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c
index 4247d60c9186..9f6ebdb23740 100644
--- a/drivers/staging/quickstart/quickstart.c
+++ b/drivers/staging/quickstart/quickstart.c
@@ -390,10 +390,6 @@ static int __init quickstart_init(void)
{
int ret;
- /* ACPI Check */
- if (acpi_disabled)
- return -ENODEV;
-
/* ACPI driver register */
ret = acpi_bus_register_driver(&quickstart_acpi_driver);
if (ret)
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index 5947a6f8e16f..48ce9a66907c 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -1704,7 +1704,7 @@ short rtl8180_tx(struct net_device *dev, u8 *txbuf, int len, int priority,
u16 RtsDur = 0;
u16 ThisFrameTime = 0;
u16 TxDescDuration = 0;
- u8 ownbit_flag = false;
+ bool ownbit_flag = false;
switch (priority) {
case MANAGE_PRIORITY:
@@ -3268,7 +3268,6 @@ fail_free:
pci_disable_device(pdev);
DMESG("wlan driver load failed\n");
- pci_set_drvdata(pdev, NULL);
return ret;
}
diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c
index 2c73823d2245..2c678f409573 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ap.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ap.c
@@ -348,7 +348,7 @@ void expire_timeout_chk(struct adapter *padapter)
if (psta->state & WIFI_SLEEP_STATE) {
if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
- /* to check if alive by another methods if staion is at ps mode. */
+ /* to check if alive by another methods if station is at ps mode. */
psta->expire_to = pstapriv->expire_to;
psta->state |= WIFI_STA_ALIVE_CHK_STATE;
diff --git a/drivers/staging/rtl8188eu/core/rtw_br_ext.c b/drivers/staging/rtl8188eu/core/rtw_br_ext.c
index fbca394cf4fc..9f40742ee5cf 100644
--- a/drivers/staging/rtl8188eu/core/rtw_br_ext.c
+++ b/drivers/staging/rtl8188eu/core/rtw_br_ext.c
@@ -527,7 +527,7 @@ int nat25_db_handle(struct adapter *priv, struct sk_buff *skb, int method)
case NAT25_CHECK:
return -1;
case NAT25_INSERT:
- /* some muticast with source IP is all zero, maybe other case is illegal */
+ /* some multicast with source IP is all zero, maybe other case is illegal */
/* in class A, B, C, host address is all zero or all one is illegal */
if (iph->saddr == 0)
return 0;
@@ -677,9 +677,8 @@ int nat25_db_handle(struct adapter *priv, struct sk_buff *skb, int method)
switch (method) {
case NAT25_CHECK:
if (!memcmp(skb->data+ETH_ALEN, ipx->ipx_source.node, ETH_ALEN))
- DEBUG_INFO("NAT25: Check IPX skb_copy\n");
+ DEBUG_INFO("NAT25: Check IPX skb_copy\n");
return 0;
- return -1;
case NAT25_INSERT:
DEBUG_INFO("NAT25: Insert IPX, Dest =%08x,%02x%02x%02x%02x%02x%02x,%04x Source =%08x,%02x%02x%02x%02x%02x%02x,%04x\n",
ipx->ipx_dest.net,
diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c
index 9632ef48fbc1..06be02c79ce8 100644
--- a/drivers/staging/rtl8188eu/core/rtw_cmd.c
+++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c
@@ -1162,7 +1162,7 @@ _func_enter_;
else
memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);
- /* jeff: set this becasue at least sw key is ready */
+ /* jeff: set this because at least sw key is ready */
padapter->securitypriv.busetkipkey = true;
res = rtw_enqueue_cmd(pcmdpriv, ph2c);
diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c
index 869434c4cf69..806f56f1c437 100644
--- a/drivers/staging/rtl8188eu/core/rtw_efuse.c
+++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c
@@ -159,7 +159,7 @@ Efuse_CalculateWordCnts(u8 word_en)
/* */
/* Description: */
/* Execute E-Fuse read byte operation. */
-/* Refered from SD1 Richard. */
+/* Referred from SD1 Richard. */
/* */
/* Assumption: */
/* 1. Boot from E-Fuse and successfully auto-load. */
@@ -214,7 +214,7 @@ ReadEFuseByte(
/* Description: */
/* 1. Execute E-Fuse read byte operation according as map offset and */
/* save to E-Fuse table. */
-/* 2. Refered from SD1 Richard. */
+/* 2. Referred from SD1 Richard. */
/* */
/* Assumption: */
/* 1. Boot from E-Fuse and successfully auto-load. */
@@ -542,7 +542,7 @@ u8 rtw_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
{
u8 offset, word_en;
u8 *map;
- u8 newdata[PGPKT_DATA_SIZE];
+ u8 newdata[PGPKT_DATA_SIZE + 1];
s32 i, idx;
u8 ret = _SUCCESS;
u16 mapLen = 0;
@@ -564,7 +564,7 @@ u8 rtw_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
offset = (addr >> 3);
word_en = 0xF;
- _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE);
+ _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
i = addr & 0x7; /* index of one package */
idx = 0; /* data index */
@@ -634,7 +634,7 @@ u8 rtw_BT_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data
{
u8 offset, word_en;
u8 *map;
- u8 newdata[PGPKT_DATA_SIZE];
+ u8 newdata[PGPKT_DATA_SIZE + 1];
s32 i, idx;
u8 ret = _SUCCESS;
u16 mapLen = 0;
@@ -656,7 +656,7 @@ u8 rtw_BT_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data
offset = (addr >> 3);
word_en = 0xF;
- _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE);
+ _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
i = addr & 0x7; /* index of one package */
idx = 0; /* data index */
diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
index 6fc77428e83a..e6f98fb8f113 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
@@ -1129,7 +1129,7 @@ void rtw_macaddr_cfg(u8 *mac_addr)
mac[3] = 0x87;
mac[4] = 0x00;
mac[5] = 0x00;
- /* use default mac addresss */
+ /* use default mac address */
memcpy(mac_addr, mac, ETH_ALEN);
DBG_88E("MAC Address from efuse error, assign default one !!!\n");
}
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c
index ea6607196d84..ac3535d33a45 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c
@@ -557,7 +557,7 @@ _func_enter_;
sq_final = ((u32)(src->PhyInfo.SignalQuality)+(u32)(dst->PhyInfo.SignalQuality)*4)/5;
rssi_final = (src->Rssi+dst->Rssi*4)/5;
} else {
- /* bss info not receving from the right channel, use the original RX signal infos */
+ /* bss info not receiving from the right channel, use the original RX signal infos */
ss_final = dst->PhyInfo.SignalStrength;
sq_final = dst->PhyInfo.SignalQuality;
rssi_final = dst->Rssi;
@@ -636,7 +636,7 @@ _func_enter_;
pnetwork->aid = 0;
pnetwork->join_res = 0;
- /* bss info not receving from the right channel */
+ /* bss info not receiving from the right channel */
if (pnetwork->network.PhyInfo.SignalQuality == 101)
pnetwork->network.PhyInfo.SignalQuality = 0;
} else {
@@ -656,7 +656,7 @@ _func_enter_;
pnetwork->last_scanned = rtw_get_current_time();
- /* bss info not receving from the right channel */
+ /* bss info not receiving from the right channel */
if (pnetwork->network.PhyInfo.SignalQuality == 101)
pnetwork->network.PhyInfo.SignalQuality = 0;
rtw_list_insert_tail(&(pnetwork->list), &(queue->queue));
@@ -670,7 +670,7 @@ _func_enter_;
pnetwork->last_scanned = rtw_get_current_time();
- /* target.Reserved[0]== 1, means that scaned network is a bcn frame. */
+ /* target.Reserved[0]== 1, means that scanned network is a bcn frame. */
if ((pnetwork->network.IELength > target->IELength) && (target->Reserved[0] == 1))
update_ie = false;
@@ -1130,7 +1130,7 @@ static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, str
padapter->securitypriv.wps_ie_len = 0;
}
/* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info */
- /* if A-MPDU Rx is enabled, reseting rx_ordering_ctrl wstart_b(indicate_seq) to default value = 0xffff */
+ /* if A-MPDU Rx is enabled, resetting rx_ordering_ctrl wstart_b(indicate_seq) to default value = 0xffff */
/* todo: check if AP can send A-MPDU packets */
for (i = 0; i < 16; i++) {
/* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
@@ -1210,7 +1210,7 @@ static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_net
rtw_update_ht_cap(padapter, cur_network->network.IEs, cur_network->network.IELength);
}
-/* Notes: the fucntion could be > passive_level (the same context as Rx tasklet) */
+/* Notes: the function could be > passive_level (the same context as Rx tasklet) */
/* pnetwork: returns from rtw_joinbss_event_callback */
/* ptarget_wlan: found from scanned_queue */
/* if join_res > 0, for (fw_state == WIFI_STATION_STATE), we check if "ptarget_sta" & "ptarget_wlan" exist. */
@@ -2177,7 +2177,7 @@ _func_enter_;
_func_exit_;
}
-/* the fucntion is at passive_level */
+/* the function is at passive_level */
void rtw_joinbss_reset(struct adapter *padapter)
{
u8 threshold;
@@ -2205,7 +2205,7 @@ void rtw_joinbss_reset(struct adapter *padapter)
}
}
-/* the fucntion is >= passive_level */
+/* the function is >= passive_level */
unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len)
{
u32 ielen, out_len;
@@ -2273,7 +2273,7 @@ unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_
return phtpriv->ht_option;
}
-/* the fucntion is > passive_level (in critical_section) */
+/* the function is > passive_level (in critical_section) */
void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len)
{
u8 *p, max_ampdu_sz;
@@ -2332,7 +2332,7 @@ void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len)
else
pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R[i];
}
- /* switch to the 40M Hz mode accoring to the AP */
+ /* switch to the 40M Hz mode according to the AP */
pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
switch ((pmlmeinfo->HT_info.infos[0] & 0x3)) {
case HT_EXTCHNL_OFFSET_UPPER:
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
index 4b2eb8e9b562..9982dd0e2060 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
@@ -2349,7 +2349,7 @@ static void issue_p2p_GO_response(struct adapter *padapter, u8 *raddr, u8 *frame
if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
/* Commented by Albert 2011/03/08 */
/* According to the P2P specification */
- /* if the sending device will be client, the P2P Capability should be reserved of group negotation response frame */
+ /* if the sending device will be client, the P2P Capability should be reserved of group negotiation response frame */
p2pie[p2pielen++] = 0;
} else {
/* Be group owner or meet the error case */
@@ -6698,7 +6698,7 @@ u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, str
}
}
- /* mark bss info receving from nearby channel as SignalQuality 101 */
+ /* mark bss info receiving from nearby channel as SignalQuality 101 */
if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
bssid->PhyInfo.SignalQuality = 101;
return _SUCCESS;
@@ -8110,7 +8110,7 @@ u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
Save_DM_Func_Flag(padapter);
Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
- /* config the initial gain under scaning, need to write the BB registers */
+ /* config the initial gain under scanning, need to write the BB registers */
#ifdef CONFIG_88EU_P2P
if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
initialgain = 0x1E;
diff --git a/drivers/staging/rtl8188eu/core/rtw_mp.c b/drivers/staging/rtl8188eu/core/rtw_mp.c
index c7ff2e4d1f23..9832dcbbd07f 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mp.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mp.c
@@ -907,7 +907,7 @@ u32 mp_query_psd(struct adapter *pAdapter, u8 *data)
sscanf(data, "pts =%d, start =%d, stop =%d", &psd_pts, &psd_start, &psd_stop);
}
- _rtw_memset(data, '\0', sizeof(data));
+ _rtw_memset(data, '\0', sizeof(*data));
i = psd_start;
while (i < psd_stop) {
diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c
index 201165787362..ba8e53463d10 100644
--- a/drivers/staging/rtl8188eu/core/rtw_recv.c
+++ b/drivers/staging/rtl8188eu/core/rtw_recv.c
@@ -204,11 +204,14 @@ void rtw_init_recvframe(union recv_frame *precvframe, struct recv_priv *precvpri
int rtw_free_recvframe(union recv_frame *precvframe, struct __queue *pfree_recv_queue)
{
unsigned long irqL;
- struct adapter *padapter = precvframe->u.hdr.adapter;
- struct recv_priv *precvpriv = &padapter->recvpriv;
+ struct adapter *padapter;
+ struct recv_priv *precvpriv;
_func_enter_;
-
+ if (!precvframe)
+ return _FAIL;
+ padapter = precvframe->u.hdr.adapter;
+ precvpriv = &padapter->recvpriv;
if (precvframe->u.hdr.pkt) {
dev_kfree_skb_any(precvframe->u.hdr.pkt);/* free skb by driver */
precvframe->u.hdr.pkt = NULL;
@@ -1798,16 +1801,14 @@ static int amsdu_to_msdu(struct adapter *padapter, union recv_frame *prframe)
memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, ETH_ALEN);
}
- /* Indicat the packets to upper layer */
- if (sub_skb) {
- /* Insert NAT2.5 RX here! */
- sub_skb->protocol = eth_type_trans(sub_skb, padapter->pnetdev);
- sub_skb->dev = padapter->pnetdev;
+ /* Indicate the packets to upper layer */
+ /* Insert NAT2.5 RX here! */
+ sub_skb->protocol = eth_type_trans(sub_skb, padapter->pnetdev);
+ sub_skb->dev = padapter->pnetdev;
- sub_skb->ip_summed = CHECKSUM_NONE;
+ sub_skb->ip_summed = CHECKSUM_NONE;
- netif_rx(sub_skb);
- }
+ netif_rx(sub_skb);
}
exit:
diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c
index 0f076d0cb5f8..e08845729772 100644
--- a/drivers/staging/rtl8188eu/core/rtw_security.c
+++ b/drivers/staging/rtl8188eu/core/rtw_security.c
@@ -916,7 +916,7 @@ _func_enter_;
add1b[i] = 0x00;
}
- swap_halfs[0] = in[2]; /* Swap halfs */
+ swap_halfs[0] = in[2]; /* Swap halves */
swap_halfs[1] = in[3];
swap_halfs[2] = in[0];
swap_halfs[3] = in[1];
diff --git a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
index c2977be92fb1..cd3c9a7c3044 100644
--- a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
+++ b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
@@ -267,9 +267,8 @@ _func_enter_;
rtw_mfree_sta_priv_lock(pstapriv);
- if (pstapriv->pallocated_stainfo_buf) {
+ if (pstapriv->pallocated_stainfo_buf)
rtw_vmfree(pstapriv->pallocated_stainfo_buf, sizeof(struct sta_info)*NUM_STA+4);
- }
}
_func_exit_;
@@ -315,7 +314,7 @@ _func_enter_;
rtw_list_insert_tail(&psta->hash_list, phash_list);
- pstapriv->asoc_sta_count++ ;
+ pstapriv->asoc_sta_count++;
_exit_critical_bh(&(pstapriv->sta_hash_lock), &irql2);
@@ -419,7 +418,7 @@ _func_enter_;
_cancel_timer_ex(&psta->addba_retry_timer);
/* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
- for (i = 0; i < 16 ; i++) {
+ for (i = 0; i < 16; i++) {
unsigned long irql;
struct list_head *phead, *plist;
union recv_frame *prframe;
diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
index 8018edd3d42e..153ec61493ab 100644
--- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
+++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
@@ -80,7 +80,7 @@ int cckratesonly_included(unsigned char *rate, int ratelen)
for (i = 0; i < ratelen; i++) {
if ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
(((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22))
- return false;
+ return false;
}
return true;
@@ -766,7 +766,7 @@ void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
for (i = 0; i < (pIE->Length); i++) {
if (i != 2) {
- /* Got the endian issue here. */
+ /* Got the endian issue here. */
pmlmeinfo->HT_caps.u.HT_cap[i] &= (pIE->data[i]);
} else {
/* modify from fw by Thomas 2010/11/17 */
@@ -1096,13 +1096,13 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len)
}
kfree(bssid);
+ _func_exit_;
return _SUCCESS;
_mismatch:
kfree(bssid);
- return _FAIL;
-
_func_exit_;
+ return _FAIL;
}
void update_beacon_info(struct adapter *padapter, u8 *pframe, uint pkt_len, struct sta_info *psta)
@@ -1186,7 +1186,7 @@ unsigned int should_forbid_n_rate(struct adapter *padapter)
case _RSN_IE_2_:
if ((_rtw_memcmp((pIE->data + 8), RSN_CIPHER_SUITE_CCMP, 4)) ||
(_rtw_memcmp((pIE->data + 12), RSN_CIPHER_SUITE_CCMP, 4)))
- return false;
+ return false;
default:
break;
}
@@ -1368,21 +1368,21 @@ void update_tx_basic_rate(struct adapter *padapter, u8 wirelessmode)
#ifdef CONFIG_88EU_P2P
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
- /* Added by Albert 2011/03/22 */
- /* In the P2P mode, the driver should not support the b mode. */
- /* So, the Tx packet shouldn't use the CCK rate */
+ /* Added by Albert 2011/03/22 */
+ /* In the P2P mode, the driver should not support the b mode. */
+ /* So, the Tx packet shouldn't use the CCK rate */
if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
return;
#endif /* CONFIG_88EU_P2P */
_rtw_memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
- if ((wirelessmode & WIRELESS_11B) && (wirelessmode == WIRELESS_11B)) {
+ if ((wirelessmode & WIRELESS_11B) && (wirelessmode == WIRELESS_11B))
memcpy(supported_rates, rtw_basic_rate_cck, 4);
- } else if (wirelessmode & WIRELESS_11B) {
+ else if (wirelessmode & WIRELESS_11B)
memcpy(supported_rates, rtw_basic_rate_mix, 7);
- } else {
+ else
memcpy(supported_rates, rtw_basic_rate_ofdm, 3);
- }
+
if (wirelessmode & WIRELESS_11B)
update_mgnt_tx_rate(padapter, IEEE80211_CCK_RATE_1MB);
@@ -1435,7 +1435,7 @@ unsigned char check_assoc_AP(u8 *pframe, uint len)
DBG_88E("link to Airgo Cap\n");
return HT_IOT_PEER_AIRGO;
} else if (_rtw_memcmp(pIE->data, EPIGRAM_OUI, 3)) {
- epigram_vendor_flag = 1;
+ epigram_vendor_flag = 1;
if (ralink_vendor_flag) {
DBG_88E("link to Tenda W311R AP\n");
return HT_IOT_PEER_TENDA;
diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c
index bb5cd95c564e..a594e51d2e1c 100644
--- a/drivers/staging/rtl8188eu/core/rtw_xmit.c
+++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c
@@ -1556,7 +1556,7 @@ static struct xmit_frame *dequeue_one_xmitframe(struct xmit_priv *pxmitpriv, str
xmitframe_phead = get_list_head(pframe_queue);
xmitframe_plist = get_next(xmitframe_phead);
- while (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
+ if (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
xmitframe_plist = get_next(xmitframe_plist);
@@ -1564,12 +1564,7 @@ static struct xmit_frame *dequeue_one_xmitframe(struct xmit_priv *pxmitpriv, str
rtw_list_delete(&pxmitframe->list);
ptxservq->qcnt--;
-
- break;
-
- pxmitframe = NULL;
}
-
return pxmitframe;
}
diff --git a/drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c b/drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c
index e4f20da91b43..bb43793fd1ec 100644
--- a/drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c
+++ b/drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c
@@ -1276,407 +1276,6 @@ static void phy_LCCalibrate_8188E(struct adapter *adapt, bool is2t)
}
}
-/* Analog Pre-distortion calibration */
-#define APK_BB_REG_NUM 8
-#define APK_CURVE_REG_NUM 4
-#define PATH_NUM 2
-
-static void phy_APCalibrate_8188E(struct adapter *adapt, s8 delta, bool is2t)
-{
- struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
- struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
- u32 regD[PATH_NUM];
- u32 tmpreg, index, offset, apkbound;
- u8 path, i, pathbound = PATH_NUM;
- u32 BB_backup[APK_BB_REG_NUM];
- u32 BB_REG[APK_BB_REG_NUM] = {
- rFPGA1_TxBlock, rOFDM0_TRxPathEnable,
- rFPGA0_RFMOD, rOFDM0_TRMuxPar,
- rFPGA0_XCD_RFInterfaceSW, rFPGA0_XAB_RFInterfaceSW,
- rFPGA0_XA_RFInterfaceOE, rFPGA0_XB_RFInterfaceOE };
- u32 BB_AP_MODE[APK_BB_REG_NUM] = {
- 0x00000020, 0x00a05430, 0x02040000,
- 0x000800e4, 0x00204000 };
- u32 BB_normal_AP_MODE[APK_BB_REG_NUM] = {
- 0x00000020, 0x00a05430, 0x02040000,
- 0x000800e4, 0x22204000 };
-
- u32 AFE_backup[IQK_ADDA_REG_NUM];
- u32 AFE_REG[IQK_ADDA_REG_NUM] = {
- rFPGA0_XCD_SwitchControl, rBlue_Tooth,
- rRx_Wait_CCA, rTx_CCK_RFON,
- rTx_CCK_BBON, rTx_OFDM_RFON,
- rTx_OFDM_BBON, rTx_To_Rx,
- rTx_To_Tx, rRx_CCK,
- rRx_OFDM, rRx_Wait_RIFS,
- rRx_TO_Rx, rStandby,
- rSleep, rPMPD_ANAEN };
-
- u32 MAC_backup[IQK_MAC_REG_NUM];
- u32 MAC_REG[IQK_MAC_REG_NUM] = {
- REG_TXPAUSE, REG_BCN_CTRL,
- REG_BCN_CTRL_1, REG_GPIO_MUXCFG};
-
- u32 APK_RF_init_value[PATH_NUM][APK_BB_REG_NUM] = {
- {0x0852c, 0x1852c, 0x5852c, 0x1852c, 0x5852c},
- {0x2852e, 0x0852e, 0x3852e, 0x0852e, 0x0852e}
- };
-
- u32 APK_normal_RF_init_value[PATH_NUM][APK_BB_REG_NUM] = {
- {0x0852c, 0x0a52c, 0x3a52c, 0x5a52c, 0x5a52c}, /* path settings equal to path b settings */
- {0x0852c, 0x0a52c, 0x5a52c, 0x5a52c, 0x5a52c}
- };
-
- u32 APK_RF_value_0[PATH_NUM][APK_BB_REG_NUM] = {
- {0x52019, 0x52014, 0x52013, 0x5200f, 0x5208d},
- {0x5201a, 0x52019, 0x52016, 0x52033, 0x52050}
- };
-
- u32 APK_normal_RF_value_0[PATH_NUM][APK_BB_REG_NUM] = {
- {0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a}, /* path settings equal to path b settings */
- {0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a}
- };
-
- u32 AFE_on_off[PATH_NUM] = {
- 0x04db25a4, 0x0b1b25a4}; /* path A on path B off / path A off path B on */
-
- u32 APK_offset[PATH_NUM] = {
- rConfig_AntA, rConfig_AntB};
-
- u32 APK_normal_offset[PATH_NUM] = {
- rConfig_Pmpd_AntA, rConfig_Pmpd_AntB};
-
- u32 APK_value[PATH_NUM] = {
- 0x92fc0000, 0x12fc0000};
-
- u32 APK_normal_value[PATH_NUM] = {
- 0x92680000, 0x12680000};
-
- s8 APK_delta_mapping[APK_BB_REG_NUM][13] = {
- {-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
- {-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
- {-6, -4, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
- {-1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6},
- {-11, -9, -7, -5, -3, -1, 0, 0, 0, 0, 0, 0, 0}
- };
-
- u32 APK_normal_setting_value_1[13] = {
- 0x01017018, 0xf7ed8f84, 0x1b1a1816, 0x2522201e, 0x322e2b28,
- 0x433f3a36, 0x5b544e49, 0x7b726a62, 0xa69a8f84, 0xdfcfc0b3,
- 0x12680000, 0x00880000, 0x00880000
- };
-
- u32 APK_normal_setting_value_2[16] = {
- 0x01c7021d, 0x01670183, 0x01000123, 0x00bf00e2, 0x008d00a3,
- 0x0068007b, 0x004d0059, 0x003a0042, 0x002b0031, 0x001f0025,
- 0x0017001b, 0x00110014, 0x000c000f, 0x0009000b, 0x00070008,
- 0x00050006
- };
-
- u32 APK_result[PATH_NUM][APK_BB_REG_NUM]; /* val_1_1a, val_1_2a, val_2a, val_3a, val_4a */
- s32 BB_offset, delta_V, delta_offset;
-
- if (*(dm_odm->mp_mode) == 1) {
- struct mpt_context *pMptCtx = &(adapt->mppriv.MptCtx);
- pMptCtx->APK_bound[0] = 45;
- pMptCtx->APK_bound[1] = 52;
- }
-
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("==>phy_APCalibrate_8188E() delta %d\n", delta));
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("AP Calibration for %s\n", (is2t ? "2T2R" : "1T1R")));
- if (!is2t)
- pathbound = 1;
-
- /* 2 FOR NORMAL CHIP SETTINGS */
-
-/* Temporarily do not allow normal driver to do the following settings
- * because these offset and value will cause RF internal PA to be
- * unpredictably disabled by HW, such that RF Tx signal will disappear
- * after disable/enable card many times on 88CU. RF SD and DD have not
- * find the root cause, so we remove these actions temporarily.
- */
- if (*(dm_odm->mp_mode) != 1)
- return;
- /* settings adjust for normal chip */
- for (index = 0; index < PATH_NUM; index++) {
- APK_offset[index] = APK_normal_offset[index];
- APK_value[index] = APK_normal_value[index];
- AFE_on_off[index] = 0x6fdb25a4;
- }
-
- for (index = 0; index < APK_BB_REG_NUM; index++) {
- for (path = 0; path < pathbound; path++) {
- APK_RF_init_value[path][index] = APK_normal_RF_init_value[path][index];
- APK_RF_value_0[path][index] = APK_normal_RF_value_0[path][index];
- }
- BB_AP_MODE[index] = BB_normal_AP_MODE[index];
- }
-
- apkbound = 6;
-
- /* save BB default value */
- for (index = 0; index < APK_BB_REG_NUM; index++) {
- if (index == 0) /* skip */
- continue;
- BB_backup[index] = ODM_GetBBReg(dm_odm, BB_REG[index], bMaskDWord);
- }
-
- /* save MAC default value */
- _PHY_SaveMACRegisters(adapt, MAC_REG, MAC_backup);
-
- /* save AFE default value */
- _PHY_SaveADDARegisters(adapt, AFE_REG, AFE_backup, IQK_ADDA_REG_NUM);
-
- for (path = 0; path < pathbound; path++) {
- if (path == RF_PATH_A) {
- /* path A APK */
- /* load APK setting */
- /* path-A */
- offset = rPdp_AntA;
- for (index = 0; index < 11; index++) {
- ODM_SetBBReg(dm_odm, offset, bMaskDWord, APK_normal_setting_value_1[index]);
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
- ("phy_APCalibrate_8188E() offset 0x%x value 0x%x\n",
- offset, ODM_GetBBReg(dm_odm, offset, bMaskDWord)));
- offset += 0x04;
- }
-
- ODM_SetBBReg(dm_odm, rConfig_Pmpd_AntB, bMaskDWord, 0x12680000);
-
- offset = rConfig_AntA;
- for (; index < 13; index++) {
- ODM_SetBBReg(dm_odm, offset, bMaskDWord, APK_normal_setting_value_1[index]);
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
- ("phy_APCalibrate_8188E() offset 0x%x value 0x%x\n",
- offset, ODM_GetBBReg(dm_odm, offset, bMaskDWord)));
- offset += 0x04;
- }
-
- /* page-B1 */
- ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0x40000000);
-
- /* path A */
- offset = rPdp_AntA;
- for (index = 0; index < 16; index++) {
- ODM_SetBBReg(dm_odm, offset, bMaskDWord, APK_normal_setting_value_2[index]);
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
- ("phy_APCalibrate_8188E() offset 0x%x value 0x%x\n",
- offset, ODM_GetBBReg(dm_odm, offset, bMaskDWord)));
-
- offset += 0x04;
- }
- ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0x00000000);
- } else if (path == RF_PATH_B) {
- /* path B APK */
- /* load APK setting */
- /* path-B */
- offset = rPdp_AntB;
- for (index = 0; index < 10; index++) {
- ODM_SetBBReg(dm_odm, offset, bMaskDWord, APK_normal_setting_value_1[index]);
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
- ("phy_APCalibrate_8188E() offset 0x%x value 0x%x\n",
- offset, ODM_GetBBReg(dm_odm, offset, bMaskDWord)));
-
- offset += 0x04;
- }
- ODM_SetBBReg(dm_odm, rConfig_Pmpd_AntA, bMaskDWord, 0x12680000);
- PHY_SetBBReg(adapt, rConfig_Pmpd_AntB, bMaskDWord, 0x12680000);
-
- offset = rConfig_AntA;
- index = 11;
- for (; index < 13; index++) { /* offset 0xb68, 0xb6c */
- ODM_SetBBReg(dm_odm, offset, bMaskDWord, APK_normal_setting_value_1[index]);
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
- ("phy_APCalibrate_8188E() offset 0x%x value 0x%x\n",
- offset, ODM_GetBBReg(dm_odm, offset, bMaskDWord)));
- offset += 0x04;
- }
-
- /* page-B1 */
- ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0x40000000);
-
- /* path B */
- offset = 0xb60;
- for (index = 0; index < 16; index++) {
- ODM_SetBBReg(dm_odm, offset, bMaskDWord, APK_normal_setting_value_2[index]);
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
- ("phy_APCalibrate_8188E() offset 0x%x value 0x%x\n",
- offset, ODM_GetBBReg(dm_odm, offset, bMaskDWord)));
-
- offset += 0x04;
- }
- ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0);
- }
-
- /* save RF default value */
- regD[path] = PHY_QueryRFReg(adapt, path, RF_TXBIAS_A, bMaskDWord);
-
- /* Path A AFE all on, path B AFE All off or vise versa */
- for (index = 0; index < IQK_ADDA_REG_NUM; index++)
- ODM_SetBBReg(dm_odm, AFE_REG[index], bMaskDWord, AFE_on_off[path]);
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
- ("phy_APCalibrate_8188E() offset 0xe70 %x\n",
- ODM_GetBBReg(dm_odm, rRx_Wait_CCA, bMaskDWord)));
-
- /* BB to AP mode */
- if (path == 0) {
- for (index = 0; index < APK_BB_REG_NUM; index++) {
- if (index == 0) /* skip */
- continue;
- else if (index < 5)
- ODM_SetBBReg(dm_odm, BB_REG[index], bMaskDWord, BB_AP_MODE[index]);
- else if (BB_REG[index] == 0x870)
- ODM_SetBBReg(dm_odm, BB_REG[index], bMaskDWord, BB_backup[index]|BIT10|BIT26);
- else
- ODM_SetBBReg(dm_odm, BB_REG[index], BIT10, 0x0);
- }
-
- ODM_SetBBReg(dm_odm, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
- ODM_SetBBReg(dm_odm, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
- } else {
- /* path B */
- ODM_SetBBReg(dm_odm, rTx_IQK_Tone_B, bMaskDWord, 0x01008c00);
- ODM_SetBBReg(dm_odm, rRx_IQK_Tone_B, bMaskDWord, 0x01008c00);
- }
-
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
- ("phy_APCalibrate_8188E() offset 0x800 %x\n",
- ODM_GetBBReg(dm_odm, 0x800, bMaskDWord)));
-
- /* MAC settings */
- _PHY_MACSettingCalibration(adapt, MAC_REG, MAC_backup);
-
- if (path == RF_PATH_A) {
- /* Path B to standby mode */
- ODM_SetRFReg(dm_odm, RF_PATH_B, RF_AC, bMaskDWord, 0x10000);
- } else {
- /* Path A to standby mode */
- ODM_SetRFReg(dm_odm, RF_PATH_A, RF_AC, bMaskDWord, 0x10000);
- ODM_SetRFReg(dm_odm, RF_PATH_A, RF_MODE1, bMaskDWord, 0x1000f);
- ODM_SetRFReg(dm_odm, RF_PATH_A, RF_MODE2, bMaskDWord, 0x20103);
- }
-
- delta_offset = ((delta+14)/2);
- if (delta_offset < 0)
- delta_offset = 0;
- else if (delta_offset > 12)
- delta_offset = 12;
-
- /* AP calibration */
- for (index = 0; index < APK_BB_REG_NUM; index++) {
- if (index != 1) /* only DO PA11+PAD01001, AP RF setting */
- continue;
-
- tmpreg = APK_RF_init_value[path][index];
- if (!dm_odm->RFCalibrateInfo.bAPKThermalMeterIgnore) {
- BB_offset = (tmpreg & 0xF0000) >> 16;
-
- if (!(tmpreg & BIT15)) /* sign bit 0 */
- BB_offset = -BB_offset;
-
- delta_V = APK_delta_mapping[index][delta_offset];
-
- BB_offset += delta_V;
-
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
- ("phy_APCalibrate_8188E() APK index %d tmpreg 0x%x delta_V %d delta_offset %d\n",
- index, tmpreg, delta_V, delta_offset));
-
- if (BB_offset < 0) {
- tmpreg = tmpreg & (~BIT15);
- BB_offset = -BB_offset;
- } else {
- tmpreg = tmpreg | BIT15;
- }
- tmpreg = (tmpreg & 0xFFF0FFFF) | (BB_offset << 16);
- }
-
- ODM_SetRFReg(dm_odm, path, RF_IPA_A, bMaskDWord, 0x8992e);
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("phy_APCalibrate_8188E() offset 0xc %x\n", PHY_QueryRFReg(adapt, path, RF_IPA_A, bMaskDWord)));
- ODM_SetRFReg(dm_odm, path, RF_AC, bMaskDWord, APK_RF_value_0[path][index]);
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("phy_APCalibrate_8188E() offset 0x0 %x\n", PHY_QueryRFReg(adapt, path, RF_AC, bMaskDWord)));
- ODM_SetRFReg(dm_odm, path, RF_TXBIAS_A, bMaskDWord, tmpreg);
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("phy_APCalibrate_8188E() offset 0xd %x\n", PHY_QueryRFReg(adapt, path, RF_TXBIAS_A, bMaskDWord)));
- /* PA11+PAD01111, one shot */
- i = 0;
- do {
- ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0x80000000);
- ODM_SetBBReg(dm_odm, APK_offset[path], bMaskDWord, APK_value[0]);
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("phy_APCalibrate_8188E() offset 0x%x value 0x%x\n", APK_offset[path], ODM_GetBBReg(dm_odm, APK_offset[path], bMaskDWord)));
- ODM_delay_ms(3);
- ODM_SetBBReg(dm_odm, APK_offset[path], bMaskDWord, APK_value[1]);
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("phy_APCalibrate_8188E() offset 0x%x value 0x%x\n", APK_offset[path], ODM_GetBBReg(dm_odm, APK_offset[path], bMaskDWord)));
-
- ODM_delay_ms(20);
- ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0x00000000);
-
- if (path == RF_PATH_A)
- tmpreg = ODM_GetBBReg(dm_odm, rAPK, 0x03E00000);
- else
- tmpreg = ODM_GetBBReg(dm_odm, rAPK, 0xF8000000);
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("phy_APCalibrate_8188E() offset 0xbd8[25:21] %x\n", tmpreg));
-
- i++;
- } while (tmpreg > apkbound && i < 4);
-
- APK_result[path][index] = tmpreg;
- }
- }
-
- /* reload MAC default value */
- _PHY_ReloadMACRegisters(adapt, MAC_REG, MAC_backup);
-
- /* reload BB default value */
- for (index = 0; index < APK_BB_REG_NUM; index++) {
- if (index == 0) /* skip */
- continue;
- ODM_SetBBReg(dm_odm, BB_REG[index], bMaskDWord, BB_backup[index]);
- }
-
- /* reload AFE default value */
- reload_adda_reg(adapt, AFE_REG, AFE_backup, IQK_ADDA_REG_NUM);
-
- /* reload RF path default value */
- for (path = 0; path < pathbound; path++) {
- ODM_SetRFReg(dm_odm, path, 0xd, bMaskDWord, regD[path]);
- if (path == RF_PATH_B) {
- ODM_SetRFReg(dm_odm, RF_PATH_A, RF_MODE1, bMaskDWord, 0x1000f);
- ODM_SetRFReg(dm_odm, RF_PATH_A, RF_MODE2, bMaskDWord, 0x20101);
- }
-
- /* note no index == 0 */
- if (APK_result[path][1] > 6)
- APK_result[path][1] = 6;
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("apk path %d result %d 0x%x \t", path, 1, APK_result[path][1]));
- }
-
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("\n"));
-
- for (path = 0; path < pathbound; path++) {
- ODM_SetRFReg(dm_odm, path, 0x3, bMaskDWord,
- ((APK_result[path][1] << 15) | (APK_result[path][1] << 10) | (APK_result[path][1] << 5) | APK_result[path][1]));
- if (path == RF_PATH_A)
- ODM_SetRFReg(dm_odm, path, 0x4, bMaskDWord,
- ((APK_result[path][1] << 15) | (APK_result[path][1] << 10) | (0x00 << 5) | 0x05));
- else
- ODM_SetRFReg(dm_odm, path, 0x4, bMaskDWord,
- ((APK_result[path][1] << 15) | (APK_result[path][1] << 10) | (0x02 << 5) | 0x05));
- ODM_SetRFReg(dm_odm, path, RF_BS_PA_APSET_G9_G11, bMaskDWord,
- ((0x08 << 15) | (0x08 << 10) | (0x08 << 5) | 0x08));
- }
-
- dm_odm->RFCalibrateInfo.bAPKdone = true;
-
- ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("<==phy_APCalibrate_8188E()\n"));
-}
-
-#define DP_BB_REG_NUM 7
-#define DP_RF_REG_NUM 1
-#define DP_RETRY_LIMIT 10
-#define DP_PATH_NUM 2
-#define DP_DPK_NUM 3
-#define DP_DPK_VALUE_NUM 2
-
void PHY_IQCalibrate_8188E(struct adapter *adapt, bool recovery)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
@@ -1867,28 +1466,6 @@ void PHY_LCCalibrate_8188E(struct adapter *adapt)
("LCK:Finish!!!interface %d\n", dm_odm->InterfaceIndex));
}
-void PHY_APCalibrate_8188E(struct adapter *adapt, s8 delta)
-{
- struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
- struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
-
- return;
- if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
- return;
-
-#if FOR_BRAZIL_PRETEST != 1
- if (dm_odm->RFCalibrateInfo.bAPKdone)
-#endif
- return;
-
- if (dm_odm->RFType == ODM_2T2R) {
- phy_APCalibrate_8188E(adapt, delta, true);
- } else {
- /* For 88C 1T1R */
- phy_APCalibrate_8188E(adapt, delta, false);
- }
-}
-
static void phy_setrfpathswitch_8188e(struct adapter *adapt, bool main, bool is2t)
{
struct hal_data_8188e *pHalData = GET_HAL_DATA(adapt);
diff --git a/drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c b/drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c
index e913a22a6426..5700dbce5b8c 100644
--- a/drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c
+++ b/drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c
@@ -85,7 +85,7 @@ u8 HalPwrSeqCmdParsing(struct adapter *padapter, u8 cut_vers, u8 fab_vers,
value &= ~(GET_PWR_CFG_MASK(pwrcfgcmd));
value |= (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd));
- /* Write the value back to sytem register */
+ /* Write the value back to system register */
rtw_write8(padapter, offset, value);
break;
case PWR_CMD_POLLING:
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
index 8c8587754517..0b0c68c9865c 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
@@ -484,7 +484,7 @@ static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u
*pLength = pktlen;
}
-/* To check if reserved page content is destroyed by beacon beacuse beacon is too large. */
+/* To check if reserved page content is destroyed by beacon because beacon is too large. */
/* 2010.06.23. Added by tynli. */
void CheckFwRsvdPageContent(struct adapter *Adapter)
{
@@ -496,9 +496,9 @@ void CheckFwRsvdPageContent(struct adapter *Adapter)
/* (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp. */
/* Input: */
/* bDLFinished - false: At the first time we will send all the packets as a large packet to Hw, */
-/* so we need to set the packet length to total lengh. */
+/* so we need to set the packet length to total length. */
/* true: At the second time, we should send the first packet (default:beacon) */
-/* to Hw again and set the lengh in descriptor to the real beacon lengh. */
+/* to Hw again and set the length in descriptor to the real beacon length. */
/* 2009.10.15 by tynli. */
static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
{
@@ -671,7 +671,7 @@ _func_enter_;
DBG_88E("%s: 1 Download RSVD success! DLBcnCount:%u, poll:%u\n", __func__, DLBcnCount, poll);
/* */
/* We just can send the reserved page twice during the time that Tx thread is stopped (e.g. pnpsetpower) */
- /* becuase we need to free the Tx BCN Desc which is used by the first reserved page packet. */
+ /* because we need to free the Tx BCN Desc which is used by the first reserved page packet. */
/* At run time, we cannot get the Tx Desc until it is released in TxHandleInterrupt() so we will return */
/* the beacon TCB in the following code. 2011.11.23. by tynli. */
/* */
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c
index 9c2e7a20c09e..ec0028d4e61a 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c
@@ -57,7 +57,7 @@ static void Init_ODM_ComInfo_88E(struct adapter *Adapter)
u8 cut_ver, fab_ver;
/* Init Value */
- _rtw_memset(dm_odm, 0, sizeof(dm_odm));
+ _rtw_memset(dm_odm, 0, sizeof(*dm_odm));
dm_odm->Adapter = Adapter;
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
index 292ba62d722f..51f03c3b53a4 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
@@ -1479,7 +1479,6 @@ static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuse
static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt, bool bPseudoTest)
{
- bool bRet = false;
u16 efuse_addr = *pAddr;
u8 badworden = 0;
u32 PgWriteSuccess = 0;
@@ -1497,7 +1496,6 @@ static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u
else
return true;
}
- return bRet;
}
static bool
@@ -1653,7 +1651,7 @@ hal_EfusePgCheckAvailableAddr(
{
u16 efuse_max_available_len = 0;
- /* Change to check TYPE_EFUSE_MAP_LEN , beacuse 8188E raw 256, logic map over 256. */
+ /* Change to check TYPE_EFUSE_MAP_LEN , because 8188E raw 256, logic map over 256. */
EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&efuse_max_available_len, false);
if (Efuse_GetCurrentSize(pAdapter, efuseType, bPseudoTest) >= efuse_max_available_len)
@@ -2100,7 +2098,7 @@ static u8 Hal_GetChnlGroup88E(u8 chnl, u8 *pGroup)
if (chnl <= 14) {
bIn24G = true;
- if (chnl < 3) /* Chanel 1-2 */
+ if (chnl < 3) /* Channel 1-2 */
*pGroup = 0;
else if (chnl < 6) /* Channel 3-5 */
*pGroup = 1;
@@ -2182,7 +2180,7 @@ void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *PROMContent, bool Auto
pHalData->bTXPowerDataReadFromEEPORM = true;
for (rfPath = 0; rfPath < pHalData->NumTotalRFPath; rfPath++) {
- for (ch = 0; ch <= CHANNEL_MAX_NUMBER; ch++) {
+ for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
bIn24G = Hal_GetChnlGroup88E(ch, &group);
if (bIn24G) {
pHalData->Index24G_CCK_Base[rfPath][ch] = pwrInfo24G.IndexCCK_Base[rfPath][group];
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c b/drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c
index ff468a68e327..68bb96d83c81 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c
@@ -559,7 +559,7 @@ static int phy_BB8188E_Config_ParaFile(struct adapter *Adapter)
/* */
/* 1. Read PHY_REG.TXT BB INIT!! */
- /* We will seperate as 88C / 92C according to chip version */
+ /* We will separate as 88C / 92C according to chip version */
/* */
if (HAL_STATUS_FAILURE == ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv, CONFIG_BB_PHY_REG))
rtStatus = _FAIL;
@@ -685,7 +685,7 @@ static u8 phy_DbmToTxPwrIdx(struct adapter *Adapter, enum wireless_mode Wireless
/* */
/* Tested by MP, we found that CCK Index 0 equals to 8dbm, OFDM legacy equals to */
- /* 3dbm, and OFDM HT equals to 0dbm repectively. */
+ /* 3dbm, and OFDM HT equals to 0dbm respectively. */
/* Note: */
/* The mapping may be different by different NICs. Do not use this formula for what needs accurate result. */
/* By Bruce, 2008-01-29. */
@@ -1006,12 +1006,12 @@ _PHY_SetBWMode92C(
switch (pHalData->CurrentChannelBW) {
case HT_CHANNEL_WIDTH_20:
regBwOpMode |= BW_OPMODE_20MHZ;
- /* 2007/02/07 Mark by Emily becasue we have not verify whether this register works */
+ /* 2007/02/07 Mark by Emily because we have not verify whether this register works */
rtw_write8(Adapter, REG_BWOPMODE, regBwOpMode);
break;
case HT_CHANNEL_WIDTH_40:
regBwOpMode &= ~BW_OPMODE_20MHZ;
- /* 2007/02/07 Mark by Emily becasue we have not verify whether this register works */
+ /* 2007/02/07 Mark by Emily because we have not verify whether this register works */
rtw_write8(Adapter, REG_BWOPMODE, regBwOpMode);
regRRSR_RSC = (regRRSR_RSC&0x90) | (pHalData->nCur40MhzPrimeSC<<5);
rtw_write8(Adapter, REG_RRSR+2, regRRSR_RSC);
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c b/drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c
index bfdf9b3ce77f..299e03e3daf6 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c
@@ -181,7 +181,7 @@ i * Currently, we cannot fully disable driver dynamic
* tx power mechanism because it is referenced by BT
* coexist mechanism.
* In the future, two mechanism shall be separated from
- * each other and maintained independantly. */
+ * each other and maintained independently. */
if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) {
TxAGC[RF_PATH_A] = 0x10101010;
TxAGC[RF_PATH_B] = 0x10101010;
@@ -216,11 +216,11 @@ i * Currently, we cannot fully disable driver dynamic
ODM_TxPwrTrackAdjust88E(&pHalData->odmpriv, 1, &direction, &pwrtrac_value);
if (direction == 1) {
- /* Increase TX pwoer */
+ /* Increase TX power */
TxAGC[0] += pwrtrac_value;
TxAGC[1] += pwrtrac_value;
} else if (direction == 2) {
- /* Decrease TX pwoer */
+ /* Decrease TX power */
TxAGC[0] -= pwrtrac_value;
TxAGC[1] -= pwrtrac_value;
}
@@ -292,7 +292,7 @@ static void get_rx_power_val_by_reg(struct adapter *Adapter, u8 Channel,
if (pHalData->pwrGroupCnt == 1)
chnlGroup = 0;
if (pHalData->pwrGroupCnt >= pHalData->PGMaxGroup) {
- if (Channel < 3) /* Chanel 1-2 */
+ if (Channel < 3) /* Channel 1-2 */
chnlGroup = 0;
else if (Channel < 6) /* Channel 3-5 */
chnlGroup = 1;
@@ -349,7 +349,7 @@ static void get_rx_power_val_by_reg(struct adapter *Adapter, u8 Channel,
}
/* 20100427 Joseph: Driver dynamic Tx power shall not affect Tx power. It shall be determined by power training mechanism. */
/* Currently, we cannot fully disable driver dynamic tx power mechanism because it is referenced by BT coexist mechanism. */
-/* In the future, two mechanism shall be separated from each other and maintained independantly. Thanks for Lanhsin's reminder. */
+/* In the future, two mechanism shall be separated from each other and maintained independently. Thanks for Lanhsin's reminder. */
/* 92d do not need this */
if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1)
writeVal = 0x14141414;
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
index bd8a9ae5d077..8f43f4966f22 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
@@ -332,7 +332,7 @@ static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bag
/* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. */
/* (1) The sequence number of each non-Qos frame / broadcast / multicast / */
- /* mgnt frame should be controled by Hw because Fw will also send null data */
+ /* mgnt frame should be controlled by Hw because Fw will also send null data */
/* which we cannot control when Fw LPS enable. */
/* --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */
/* (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */
diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c
index 5e656ce45407..cca973211b2f 100644
--- a/drivers/staging/rtl8188eu/hal/usb_halinit.c
+++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c
@@ -464,7 +464,7 @@ static void _InitRetryFunction(struct adapter *Adapter)
/*-----------------------------------------------------------------------------
* Function: usb_AggSettingTxUpdate()
*
- * Overview: Seperate TX/RX parameters update independent for TP detection and
+ * Overview: Separate TX/RX parameters update independent for TP detection and
* dynamic TX/RX aggreagtion parameters update.
*
* Input: struct adapter *
@@ -473,7 +473,7 @@ static void _InitRetryFunction(struct adapter *Adapter)
*
* Revised History:
* When Who Remark
- * 12/10/2010 MHC Seperate to smaller function.
+ * 12/10/2010 MHC Separate to smaller function.
*
*---------------------------------------------------------------------------*/
static void usb_AggSettingTxUpdate(struct adapter *Adapter)
@@ -496,7 +496,7 @@ static void usb_AggSettingTxUpdate(struct adapter *Adapter)
/*-----------------------------------------------------------------------------
* Function: usb_AggSettingRxUpdate()
*
- * Overview: Seperate TX/RX parameters update independent for TP detection and
+ * Overview: Separate TX/RX parameters update independent for TP detection and
* dynamic TX/RX aggreagtion parameters update.
*
* Input: struct adapter *
@@ -505,7 +505,7 @@ static void usb_AggSettingTxUpdate(struct adapter *Adapter)
*
* Revised History:
* When Who Remark
- * 12/10/2010 MHC Seperate to smaller function.
+ * 12/10/2010 MHC Separate to smaller function.
*
*---------------------------------------------------------------------------*/
static void
@@ -847,7 +847,7 @@ _func_enter_;
/* */
/* Init CR MACTXEN, MACRXEN after setting RxFF boundary REG_TRXFF_BNDY to patch */
- /* Hw bug which Hw initials RxFF boundry size to a value which is larger than the real Rx buffer size in 88E. */
+ /* Hw bug which Hw initials RxFF boundary size to a value which is larger than the real Rx buffer size in 88E. */
/* */
/* Enable MACTXEN/MACRXEN block */
value16 = rtw_read16(Adapter, REG_CR);
diff --git a/drivers/staging/rtl8188eu/hal/usb_ops_linux.c b/drivers/staging/rtl8188eu/hal/usb_ops_linux.c
index bc564169b2f0..2a20f2348108 100644
--- a/drivers/staging/rtl8188eu/hal/usb_ops_linux.c
+++ b/drivers/staging/rtl8188eu/hal/usb_ops_linux.c
@@ -605,68 +605,68 @@ _func_enter_;
return _FAIL;
}
+ if (!precvbuf) {
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+ ("usb_read_port:precvbuf==NULL\n"));
+ return _FAIL;
+ }
+
if ((!precvbuf->reuse) || (precvbuf->pskb == NULL)) {
precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
if (NULL != precvbuf->pskb)
precvbuf->reuse = true;
}
- if (precvbuf != NULL) {
- rtl8188eu_init_recvbuf(adapter, precvbuf);
-
- /* re-assign for linux based on skb */
- if ((!precvbuf->reuse) || (precvbuf->pskb == NULL)) {
- precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
- if (precvbuf->pskb == NULL) {
- RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("init_recvbuf(): alloc_skb fail!\n"));
- DBG_88E("#### usb_read_port() alloc_skb fail!#####\n");
- return _FAIL;
- }
-
- tmpaddr = (size_t)precvbuf->pskb->data;
- alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
- skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
-
- precvbuf->phead = precvbuf->pskb->head;
- precvbuf->pdata = precvbuf->pskb->data;
- precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
- precvbuf->pend = skb_end_pointer(precvbuf->pskb);
- precvbuf->pbuf = precvbuf->pskb->data;
- } else { /* reuse skb */
- precvbuf->phead = precvbuf->pskb->head;
- precvbuf->pdata = precvbuf->pskb->data;
- precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
- precvbuf->pend = skb_end_pointer(precvbuf->pskb);
- precvbuf->pbuf = precvbuf->pskb->data;
+ rtl8188eu_init_recvbuf(adapter, precvbuf);
- precvbuf->reuse = false;
+ /* re-assign for linux based on skb */
+ if ((!precvbuf->reuse) || (precvbuf->pskb == NULL)) {
+ precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
+ if (precvbuf->pskb == NULL) {
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("init_recvbuf(): alloc_skb fail!\n"));
+ DBG_88E("#### usb_read_port() alloc_skb fail!#####\n");
+ return _FAIL;
}
- precvpriv->rx_pending_cnt++;
+ tmpaddr = (size_t)precvbuf->pskb->data;
+ alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
+ skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
+
+ precvbuf->phead = precvbuf->pskb->head;
+ precvbuf->pdata = precvbuf->pskb->data;
+ precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
+ precvbuf->pend = skb_end_pointer(precvbuf->pskb);
+ precvbuf->pbuf = precvbuf->pskb->data;
+ } else { /* reuse skb */
+ precvbuf->phead = precvbuf->pskb->head;
+ precvbuf->pdata = precvbuf->pskb->data;
+ precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
+ precvbuf->pend = skb_end_pointer(precvbuf->pskb);
+ precvbuf->pbuf = precvbuf->pskb->data;
+
+ precvbuf->reuse = false;
+ }
- purb = precvbuf->purb;
+ precvpriv->rx_pending_cnt++;
- /* translate DMA FIFO addr to pipehandle */
- pipe = ffaddr2pipehdl(pdvobj, addr);
+ purb = precvbuf->purb;
- usb_fill_bulk_urb(purb, pusbd, pipe,
- precvbuf->pbuf,
- MAX_RECVBUF_SZ,
- usb_read_port_complete,
- precvbuf);/* context is precvbuf */
+ /* translate DMA FIFO addr to pipehandle */
+ pipe = ffaddr2pipehdl(pdvobj, addr);
- err = usb_submit_urb(purb, GFP_ATOMIC);
- if ((err) && (err != (-EPERM))) {
- RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
- ("cannot submit rx in-token(err=0x%.8x), URB_STATUS =0x%.8x",
- err, purb->status));
- DBG_88E("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n",
- err, purb->status);
- ret = _FAIL;
- }
- } else {
+ usb_fill_bulk_urb(purb, pusbd, pipe,
+ precvbuf->pbuf,
+ MAX_RECVBUF_SZ,
+ usb_read_port_complete,
+ precvbuf);/* context is precvbuf */
+
+ err = usb_submit_urb(purb, GFP_ATOMIC);
+ if ((err) && (err != (-EPERM))) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
- ("usb_read_port:precvbuf ==NULL\n"));
+ ("cannot submit rx in-token(err=0x%.8x), URB_STATUS =0x%.8x",
+ err, purb->status));
+ DBG_88E("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n",
+ err, purb->status);
ret = _FAIL;
}
diff --git a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h
index c4769e20a5c3..25cae8147e73 100644
--- a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h
+++ b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h
@@ -75,7 +75,7 @@ enum rf_radio_path {
#define MAX_PG_GROUP 13
-#define RF_PATH_MAX 2
+#define RF_PATH_MAX 3
#define MAX_RF_PATH RF_PATH_MAX
#define MAX_TX_COUNT 4 /* path numbers */
diff --git a/drivers/staging/rtl8188eu/include/Hal8188EPhyReg.h b/drivers/staging/rtl8188eu/include/Hal8188EPhyReg.h
index 0e06d29b2d2a..9f2969bf8355 100644
--- a/drivers/staging/rtl8188eu/include/Hal8188EPhyReg.h
+++ b/drivers/staging/rtl8188eu/include/Hal8188EPhyReg.h
@@ -26,7 +26,7 @@
/* 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 */
/* 3. RF register 0x00-2E */
/* 4. Bit Mask for BB/RF register */
-/* 5. Other defintion for BB/RF R/W */
+/* 5. Other definition for BB/RF R/W */
/* */
diff --git a/drivers/staging/rtl8188eu/include/HalPhyRf_8188e.h b/drivers/staging/rtl8188eu/include/HalPhyRf_8188e.h
index fa583f248320..287e9f9eae4a 100644
--- a/drivers/staging/rtl8188eu/include/HalPhyRf_8188e.h
+++ b/drivers/staging/rtl8188eu/include/HalPhyRf_8188e.h
@@ -45,8 +45,6 @@ void PHY_IQCalibrate_8188E(struct adapter *Adapter, bool ReCovery);
void PHY_LCCalibrate_8188E(struct adapter *pAdapter);
/* AP calibrate */
-void PHY_APCalibrate_8188E(struct adapter *pAdapter, s8 delta);
-
void PHY_DigitalPredistortion_8188E(struct adapter *pAdapter);
void _PHY_SaveADDARegisters(struct adapter *pAdapter, u32 *ADDAReg,
diff --git a/drivers/staging/rtl8188eu/include/odm.h b/drivers/staging/rtl8188eu/include/odm.h
index 4787bacdcad8..eaa4bc1b2255 100644
--- a/drivers/staging/rtl8188eu/include/odm.h
+++ b/drivers/staging/rtl8188eu/include/odm.h
@@ -283,8 +283,6 @@ struct odm_rate_adapt {
/* Declare for common info */
-#define MAX_PATH_NUM_92CS 2
-
struct odm_phy_status_info {
u8 RxPWDBAll;
u8 SignalQuality; /* in 0-100 index. */
@@ -950,7 +948,7 @@ struct odm_dm_struct {
struct timer_list FastAntTrainingTimer;
}; /* DM_Dynamic_Mechanism_Structure */
-#define ODM_RF_PATH_MAX 2
+#define ODM_RF_PATH_MAX 3
enum ODM_RF_RADIO_PATH {
ODM_RF_PATH_A = 0, /* Radio Path A */
diff --git a/drivers/staging/rtl8188eu/include/odm_HWConfig.h b/drivers/staging/rtl8188eu/include/odm_HWConfig.h
index 63779f5b2a3c..df5272221bad 100644
--- a/drivers/staging/rtl8188eu/include/odm_HWConfig.h
+++ b/drivers/staging/rtl8188eu/include/odm_HWConfig.h
@@ -69,7 +69,7 @@ struct phy_rx_agc_info {
};
struct phy_status_rpt {
- struct phy_rx_agc_info path_agc[2];
+ struct phy_rx_agc_info path_agc[3];
u8 ch_corr[2];
u8 cck_sig_qual_ofdm_pwdb_all;
u8 cck_agc_rpt_ofdm_cfosho_a;
@@ -79,7 +79,7 @@ struct phy_status_rpt {
u8 path_cfotail[2];
u8 pcts_mask[2];
s8 stream_rxevm[2];
- u8 path_rxsnr[2];
+ u8 path_rxsnr[3];
u8 noise_power_db_lsb;
u8 rsvd_2[3];
u8 stream_csi[2];
diff --git a/drivers/staging/rtl8188eu/include/odm_debug.h b/drivers/staging/rtl8188eu/include/odm_debug.h
index a9ba6df26b9d..622f4c1418b4 100644
--- a/drivers/staging/rtl8188eu/include/odm_debug.h
+++ b/drivers/staging/rtl8188eu/include/odm_debug.h
@@ -27,7 +27,7 @@
/* Define the debug levels */
/* */
/* 1. DBG_TRACE and DBG_LOUD are used for normal cases. */
-/* They can help SW engineer to develope or trace states changed */
+/* They can help SW engineer to develop or trace states changed */
/* and also help HW enginner to trace every operation to and from HW, */
/* e.g IO, Tx, Rx. */
/* */
diff --git a/drivers/staging/rtl8188eu/include/rtw_cmd.h b/drivers/staging/rtl8188eu/include/rtw_cmd.h
index 819285b9a781..8cafd7adfdcd 100644
--- a/drivers/staging/rtl8188eu/include/rtw_cmd.h
+++ b/drivers/staging/rtl8188eu/include/rtw_cmd.h
@@ -745,7 +745,7 @@ struct TDLSoption_param
Result:
0x00: success
-0x01: sucess, and check Response.
+0x01: success, and check Response.
0x02: cmd ignored due to duplicated sequcne number
0x03: cmd dropped due to invalid cmd code
0x04: reserved.
diff --git a/drivers/staging/rtl8188eu/include/rtw_led.h b/drivers/staging/rtl8188eu/include/rtw_led.h
index 2e618043d353..d0da4fd40d18 100644
--- a/drivers/staging/rtl8188eu/include/rtw_led.h
+++ b/drivers/staging/rtl8188eu/include/rtw_led.h
@@ -163,14 +163,14 @@ enum LED_STRATEGY_871x {
void LedControl8188eu(struct adapter *padapter, enum LED_CTL_MODE LedAction);
struct led_priv{
- /* add for led controll */
+ /* add for led control */
struct LED_871x SwLed0;
struct LED_871x SwLed1;
enum LED_STRATEGY_871x LedStrategy;
u8 bRegUseLed;
void (*LedControlHandler)(struct adapter *padapter,
enum LED_CTL_MODE LedAction);
- /* add for led controll */
+ /* add for led control */
};
#define rtw_led_control(adapt, action) \
diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h
index 22538e61695a..4a7143e0eed0 100644
--- a/drivers/staging/rtl8188eu/include/rtw_mlme.h
+++ b/drivers/staging/rtl8188eu/include/rtw_mlme.h
@@ -53,11 +53,11 @@
#define WIFI_SITE_MONITOR 0x00000800 /* to indicate the station is under site surveying */
#define WIFI_MP_STATE 0x00010000
-#define WIFI_MP_CTX_BACKGROUND 0x00020000 /* in continous tx background */
-#define WIFI_MP_CTX_ST 0x00040000 /* in continous tx with single-tone */
-#define WIFI_MP_CTX_BACKGROUND_PENDING 0x00080000 /* pending in continous tx background due to out of skb */
-#define WIFI_MP_CTX_CCK_HW 0x00100000 /* in continous tx */
-#define WIFI_MP_CTX_CCK_CS 0x00200000 /* in continous tx with carrier suppression */
+#define WIFI_MP_CTX_BACKGROUND 0x00020000 /* in continuous tx background */
+#define WIFI_MP_CTX_ST 0x00040000 /* in continuous tx with single-tone */
+#define WIFI_MP_CTX_BACKGROUND_PENDING 0x00080000 /* pending in continuous tx background due to out of skb */
+#define WIFI_MP_CTX_CCK_HW 0x00100000 /* in continuous tx */
+#define WIFI_MP_CTX_CCK_CS 0x00200000 /* in continuous tx with carrier suppression */
#define WIFI_MP_LPBK_STATE 0x00400000
#define _FW_UNDER_LINKING WIFI_UNDER_LINKING
@@ -239,7 +239,7 @@ struct wifidirect_info {
u8 profileindex; /* Used to point to the index of profileinfo array */
u8 peer_operating_ch;
u8 find_phase_state_exchange_cnt;
- /* The device password ID for group negotation */
+ /* The device password ID for group negotiation */
u16 device_password_id_for_nego;
u8 negotiation_dialog_token;
/* SSID information for group negotitation */
diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
index 853ab80a2b86..b1bfa2e30fdb 100644
--- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
+++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
@@ -107,7 +107,7 @@ extern unsigned char WMM_PARA_OUI[];
/* Note: */
/* We just add new channel plan when the new channel plan is different
* from any of the following channel plan. */
-/* If you just wnat to customize the acitions(scan period or join actions)
+/* If you just want to customize the actions(scan period or join actions)
* about one of the channel plan, */
/* customize them in struct rt_channel_info in the RT_CHANNEL_LIST. */
enum RT_CHANNEL_DOMAIN {
diff --git a/drivers/staging/rtl8188eu/include/rtw_mp_phy_regdef.h b/drivers/staging/rtl8188eu/include/rtw_mp_phy_regdef.h
index 3ad22076de3f..30fd17f23bf1 100644
--- a/drivers/staging/rtl8188eu/include/rtw_mp_phy_regdef.h
+++ b/drivers/staging/rtl8188eu/include/rtw_mp_phy_regdef.h
@@ -56,7 +56,7 @@
/* 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 */
/* 3. RF register 0x00-2E */
/* 4. Bit Mask for BB/RF register */
-/* 5. Other defintion for BB/RF R/W */
+/* 5. Other definition for BB/RF R/W */
/* */
diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h
index bae8885c57f9..be9c30c57419 100644
--- a/drivers/staging/rtl8188eu/include/rtw_recv.h
+++ b/drivers/staging/rtl8188eu/include/rtw_recv.h
@@ -83,7 +83,7 @@ struct signal_stat {
u32 total_num; /* num of valid elements */
u32 total_val; /* sum of valid elements */
};
-#define MAX_PATH_NUM_92CS 2
+#define MAX_PATH_NUM_92CS 3
struct phy_info {
u8 RxPWDBAll;
u8 SignalQuality; /* in 0-100 index. */
diff --git a/drivers/staging/rtl8188eu/include/rtw_rf.h b/drivers/staging/rtl8188eu/include/rtw_rf.h
index 089ecee6c1f9..2df88370de59 100644
--- a/drivers/staging/rtl8188eu/include/rtw_rf.h
+++ b/drivers/staging/rtl8188eu/include/rtw_rf.h
@@ -119,7 +119,7 @@ enum ht_channel_width {
};
/* */
-/* Represent Extention Channel Offset in HT Capabilities */
+/* Represent Extension Channel Offset in HT Capabilities */
/* This is available only in 40Mhz mode. */
/* */
enum ht_extchnl_offset {
diff --git a/drivers/staging/rtl8188eu/include/sta_info.h b/drivers/staging/rtl8188eu/include/sta_info.h
index 3ed2a39741ad..3e909db1d41a 100644
--- a/drivers/staging/rtl8188eu/include/sta_info.h
+++ b/drivers/staging/rtl8188eu/include/sta_info.h
@@ -338,7 +338,7 @@ struct sta_priv {
*/
struct sta_info *sta_aid[NUM_STA];
- u16 sta_dz_bitmap;/* only support 15 stations, staion aid bitmap
+ u16 sta_dz_bitmap;/* only support 15 stations, station aid bitmap
* for sleeping sta. */
u16 tim_bitmap; /* only support 15 stations, aid=0~15 mapping
* bit0~bit15 */
diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h
index a615659f9471..84e519974199 100644
--- a/drivers/staging/rtl8188eu/include/wifi.h
+++ b/drivers/staging/rtl8188eu/include/wifi.h
@@ -984,7 +984,7 @@ enum ht_cap_ampdu_factor {
#define P2P_PROVISION_TIMEOUT 5000
/* 3 seconds timeout for sending the prov disc request concurrent mode */
#define P2P_CONCURRENT_PROVISION_TIME 3000
-/* 5 seconds timeout for receiving the group negotation response */
+/* 5 seconds timeout for receiving the group negotiation response */
#define P2P_GO_NEGO_TIMEOUT 5000
/* 3 seconds timeout for sending the negotiation request under concurrent mode */
#define P2P_CONCURRENT_GO_NEGO_TIME 3000
diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
index cd4100fb3645..ae5458770234 100644
--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
@@ -938,7 +938,7 @@ static int rtw_wx_set_pmkid(struct net_device *dev,
memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
if (pPMK->cmd == IW_PMKSA_ADD) {
DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n");
- if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN) == true)
+ if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
return ret;
else
ret = true;
@@ -1039,7 +1039,7 @@ static int rtw_wx_get_range(struct net_device *dev,
range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
/* TODO: Find real 'good' to 'bad' threshol value for RSSI */
- range->avg_qual.level = 20 + -98;
+ range->avg_qual.level = 178; /* -78 dBm */
range->avg_qual.noise = 0;
range->avg_qual.updated = 7; /* Updated all three */
@@ -1074,7 +1074,7 @@ static int rtw_wx_get_range(struct net_device *dev,
/* The following code will proivde the security capability to network manager. */
/* If the driver doesn't provide this capability to network manager, */
-/* the WPA/WPA2 routers can't be choosen in the network manager. */
+/* the WPA/WPA2 routers can't be chosen in the network manager. */
/*
#define IW_SCAN_CAPA_NONE 0x00
@@ -1373,7 +1373,7 @@ _func_enter_;
}
}
- /* it has still some scan paramater to parse, we only do this now... */
+ /* it has still some scan parameter to parse, we only do this now... */
_status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
} else {
_status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
@@ -2626,7 +2626,7 @@ static int rtw_get_ap_info(struct net_device *dev,
return -EINVAL;
}
- if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN) == true) {
+ if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
/* BSSID match, then check if supporting wpa/wpa2 */
DBG_88E("BSSID:%pM\n", (bssid));
@@ -2961,7 +2961,7 @@ static int rtw_p2p_get_status(struct net_device *dev,
/* Commented by Albert 20110520 */
/* This function will return the config method description */
-/* This config method description will show us which config method the remote P2P device is intented to use */
+/* This config method description will show us which config method the remote P2P device is intended to use */
/* by sending the provisioning discovery request frame. */
static int rtw_p2p_get_req_cm(struct net_device *dev,
@@ -3413,7 +3413,7 @@ static int rtw_p2p_get_invitation_procedure(struct net_device *dev,
/* +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 initation procedure is support or not. */
+ /* The application wants to know P2P initiation procedure is supported or not. */
/* Format: iwpriv wlanx p2p_get2 InvProc = 00:E0:4C:00:00:05 */
DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
@@ -4040,7 +4040,7 @@ static int rtw_rereg_nd_name(struct net_device *dev,
if (0 != ret)
goto exit;
- if (!memcmp(rereg_priv->old_ifname, "disable%d", 9) == true) {
+ if (!memcmp(rereg_priv->old_ifname, "disable%d", 9)) {
padapter->ledpriv.bRegUseLed = rereg_priv->old_bRegUseLed;
rtw_hal_sw_led_init(padapter);
rtw_ips_mode_req(&padapter->pwrctrlpriv, rereg_priv->old_ips_mode);
@@ -4049,7 +4049,7 @@ static int rtw_rereg_nd_name(struct net_device *dev,
strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
- if (!memcmp(new_ifname, "disable%d", 9) == true) {
+ if (!memcmp(new_ifname, "disable%d", 9)) {
DBG_88E("%s disable\n", __func__);
/* free network queue for Android's timming issue */
rtw_free_network_queue(padapter, true);
@@ -4884,7 +4884,6 @@ static int set_group_key(struct adapter *padapter, u8 *key, u8 alg, int keyid)
case _TKIP_:
case _TKIP_WTMIC_:
case _AES_:
- keylen = 16;
default:
keylen = 16;
}
@@ -6146,7 +6145,7 @@ static int rtw_mp_efuse_set(struct net_device *dev,
for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
- /* Change to check TYPE_EFUSE_MAP_LEN, beacuse 8188E raw 256, logic map over 256. */
+ /* Change to check TYPE_EFUSE_MAP_LEN, because 8188E raw 256, logic map over 256. */
EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_size, false);
if ((addr+cnts) > max_available_size) {
DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
@@ -6221,7 +6220,7 @@ static int rtw_mp_efuse_set(struct net_device *dev,
for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
- /* Change to check TYPE_EFUSE_MAP_LEN, beacuse 8188E raw 256, logic map over 256. */
+ /* Change to check TYPE_EFUSE_MAP_LEN, because 8188E raw 256, logic map over 256. */
EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_size, false);
if ((addr+cnts) > max_available_size) {
DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
@@ -6973,7 +6972,7 @@ static int rtw_mp_ctx(struct net_device *dev,
stop = strncmp(extra, "stop", 4);
sscanf(extra, "count =%d, pkt", &count);
- _rtw_memset(extra, '\0', sizeof(extra));
+ _rtw_memset(extra, '\0', sizeof(*extra));
if (stop == 0) {
bStartTest = 0; /* To set Stop */
diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
index 63bc913eba6d..da9f0d5f76f7 100644
--- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c
+++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
@@ -85,7 +85,7 @@ static int rtw_uapsd_acvi_en;
static int rtw_uapsd_acvo_en;
int rtw_ht_enable = 1;
-int rtw_cbw40_enable = 3; /* 0 :diable, bit(0): enable 2.4g, bit(1): enable 5g */
+int rtw_cbw40_enable = 3; /* 0 :disable, bit(0): enable 2.4g, bit(1): enable 5g */
int rtw_ampdu_enable = 1;/* for enable tx_ampdu */
static int rtw_rx_stbc = 1;/* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */
static int rtw_ampdu_amsdu;/* 0: disabled, 1:enabled, 2:auto */
diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c
index 4e0bfb7e153b..5a9e9e4558aa 100644
--- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c
+++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c
@@ -627,13 +627,14 @@ RETURN:
int rtw_change_ifname(struct adapter *padapter, const char *ifname)
{
struct net_device *pnetdev;
- struct net_device *cur_pnetdev = padapter->pnetdev;
+ struct net_device *cur_pnetdev;
struct rereg_nd_name_data *rereg_priv;
int ret;
if (!padapter)
goto error;
+ cur_pnetdev = padapter->pnetdev;
rereg_priv = &padapter->rereg_nd_name_priv;
/* free the old_pnetdev */
@@ -794,7 +795,7 @@ void *rtw_cbuf_pop(struct rtw_cbuf *cbuf)
}
/**
- * rtw_cbuf_alloc - allocte a rtw_cbuf with given size and do initialization
+ * rtw_cbuf_alloc - allocate a rtw_cbuf with given size and do initialization
* @size: size of pointer
*
* Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
diff --git a/drivers/staging/rtl8188eu/os_dep/recv_linux.c b/drivers/staging/rtl8188eu/os_dep/recv_linux.c
index e2f4e7d77170..3852ff43810d 100644
--- a/drivers/staging/rtl8188eu/os_dep/recv_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/recv_linux.c
@@ -77,8 +77,7 @@ int rtw_os_recvbuf_resource_alloc(struct adapter *padapter,
int rtw_os_recvbuf_resource_free(struct adapter *padapter,
struct recv_buf *precvbuf)
{
- if (precvbuf->purb)
- usb_free_urb(precvbuf->purb);
+ usb_free_urb(precvbuf->purb);
return _SUCCESS;
}
@@ -224,8 +223,7 @@ _func_exit_;
_recv_indicatepkt_drop:
/* enqueue back to free_recv_queue */
- if (precv_frame)
- rtw_free_recvframe(precv_frame, pfree_recv_queue);
+ rtw_free_recvframe(precv_frame, pfree_recv_queue);
_func_exit_;
return _FAIL;
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
index d3078d200e50..7d14779310d3 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
@@ -54,6 +54,7 @@ static struct usb_device_id rtw_usb_id_tbl[] = {
/*=== Customer ID ===*/
/****** 8188EUS ********/
{USB_DEVICE(0x8179, 0x07B8)}, /* Abocom - Abocom */
+ {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
{} /* Terminating entry */
};
@@ -736,7 +737,7 @@ static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
status = _SUCCESS;
free_hal_data:
- if (status != _SUCCESS && padapter->HalData)
+ if (status != _SUCCESS)
kfree(padapter->HalData);
handle_dualmac:
if (status != _SUCCESS)
diff --git a/drivers/staging/rtl8192e/dot11d.h b/drivers/staging/rtl8192e/dot11d.h
index 71f4549a378f..fb7683fa5ffd 100644
--- a/drivers/staging/rtl8192e/dot11d.h
+++ b/drivers/staging/rtl8192e/dot11d.h
@@ -38,7 +38,7 @@ enum dot11d_state {
/**
* struct rt_dot11d_info * @CountryIeLen: value greater than 0 if @CountryIeBuf contains
* valid country information element.
- * @chanell_map: holds channel values
+ * @channel_map: holds channel values
* 0 - invalid,
* 1 - valid (active scan),
* 2 - valid (passive scan)
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
index 74fbd70d5838..6616b3a20bc9 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
@@ -1866,15 +1866,15 @@ static void rtl8192_TranslateRxSignalStuff(struct net_device *dev,
type = WLAN_FC_GET_TYPE(fc);
praddr = hdr->addr1;
- bpacket_match_bssid = ((RTLLIB_FTYPE_CTL != type) &&
- (!compare_ether_addr(priv->rtllib->
- current_network.bssid,
- (fc & RTLLIB_FCTL_TODS) ? hdr->addr1 :
- (fc & RTLLIB_FCTL_FROMDS) ? hdr->addr2 : hdr->addr3))
- && (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV));
- bpacket_toself = bpacket_match_bssid && /* check this */
- (!compare_ether_addr(praddr,
- priv->rtllib->dev->dev_addr));
+ bpacket_match_bssid =
+ ((RTLLIB_FTYPE_CTL != type) &&
+ ether_addr_equal(priv->rtllib->current_network.bssid,
+ (fc & RTLLIB_FCTL_TODS) ? hdr->addr1 :
+ (fc & RTLLIB_FCTL_FROMDS) ? hdr->addr2 :
+ hdr->addr3) &&
+ (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV));
+ bpacket_toself = bpacket_match_bssid && /* check this */
+ ether_addr_equal(praddr, priv->rtllib->dev->dev_addr);
if (WLAN_FC_GET_FRAMETYPE(fc) == RTLLIB_STYPE_BEACON)
bPacketBeacon = true;
if (bpacket_match_bssid)
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
index e06844355551..7d322f3980e1 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
@@ -2982,7 +2982,6 @@ err_rel_rtllib:
free_rtllib(dev);
DMESG("wlan driver load failed\n");
- pci_set_drvdata(pdev, NULL);
err_pci_disable:
pci_disable_device(pdev);
return err;
diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c
index 8aeaed5a987d..8ee80c50303a 100644
--- a/drivers/staging/rtl8192e/rtllib_rx.c
+++ b/drivers/staging/rtl8192e/rtllib_rx.c
@@ -957,16 +957,15 @@ static void rtllib_rx_extract_addr(struct rtllib_device *ieee,
static int rtllib_rx_data_filter(struct rtllib_device *ieee, u16 fc,
u8 *dst, u8 *src, u8 *bssid, u8 *addr2)
{
- u8 zero_addr[ETH_ALEN] = {0};
u8 type, stype;
type = WLAN_FC_GET_TYPE(fc);
stype = WLAN_FC_GET_STYPE(fc);
/* Filter frames from different BSS */
- if (((fc & RTLLIB_FCTL_DSTODS) != RTLLIB_FCTL_DSTODS)
- && (compare_ether_addr(ieee->current_network.bssid, bssid) != 0)
- && memcmp(ieee->current_network.bssid, zero_addr, ETH_ALEN)) {
+ if (((fc & RTLLIB_FCTL_DSTODS) != RTLLIB_FCTL_DSTODS) &&
+ !ether_addr_equal(ieee->current_network.bssid, bssid) &&
+ !is_zero_ether_addr(ieee->current_network.bssid)) {
return -1;
}
@@ -974,8 +973,8 @@ static int rtllib_rx_data_filter(struct rtllib_device *ieee, u16 fc,
if (ieee->IntelPromiscuousModeInfo.bPromiscuousOn &&
ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame) {
if ((fc & RTLLIB_FCTL_TODS) && !(fc & RTLLIB_FCTL_FROMDS) &&
- (compare_ether_addr(dst, ieee->current_network.bssid) != 0) &&
- (compare_ether_addr(bssid, ieee->current_network.bssid) == 0)) {
+ !ether_addr_equal(dst, ieee->current_network.bssid) &&
+ ether_addr_equal(bssid, ieee->current_network.bssid)) {
return -1;
}
}
@@ -1275,7 +1274,7 @@ static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb,
/*Filter pkt not to me*/
multicast = is_multicast_ether_addr(hdr->addr1);
unicast = !multicast;
- if (unicast && (compare_ether_addr(dev->dev_addr, hdr->addr1) != 0)) {
+ if (unicast && !ether_addr_equal(dev->dev_addr, hdr->addr1)) {
if (ieee->bNetPromiscuousMode)
bToOtherSTA = true;
else
diff --git a/drivers/staging/rtl8192u/r8190_rtl8256.h b/drivers/staging/rtl8192u/r8190_rtl8256.h
index 592e7807fa42..fa6dd37d85e6 100644
--- a/drivers/staging/rtl8192u/r8190_rtl8256.h
+++ b/drivers/staging/rtl8192u/r8190_rtl8256.h
@@ -13,11 +13,7 @@
#ifndef RTL8225H
#define RTL8225H
-#ifdef RTL8190P
-#define RTL819X_TOTAL_RF_PATH 4 //for 90P
-#else
#define RTL819X_TOTAL_RF_PATH 2 //for 8192U
-#endif
extern void PHY_SetRF8256Bandwidth(struct net_device *dev , HT_CHANNEL_WIDTH Bandwidth);
extern void PHY_RF8256_Config(struct net_device *dev);
extern void phy_RF8256_Config_ParaFile(struct net_device *dev);
diff --git a/drivers/staging/rtl8192u/r8192U.h b/drivers/staging/rtl8192u/r8192U.h
index b484ee128c13..4c46bb25a6b3 100644
--- a/drivers/staging/rtl8192u/r8192U.h
+++ b/drivers/staging/rtl8192u/r8192U.h
@@ -409,15 +409,11 @@ typedef struct rx_drvinfo_819x_usb {
#define USB_HWDESC_HEADER_LEN sizeof(tx_desc_819x_usb)
#define TX_PACKET_SHIFT_BYTES (USB_HWDESC_HEADER_LEN + sizeof(tx_fwinfo_819x_usb))
#define MAX_FRAGMENT_COUNT 8
-#ifdef RTL8192U
#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
#define MAX_TRANSMIT_BUFFER_SIZE 32000
#else
#define MAX_TRANSMIT_BUFFER_SIZE 8000
#endif
-#else
-#define MAX_TRANSMIT_BUFFER_SIZE (1600+(MAX_802_11_HEADER_LENGTH+ENCRYPTION_MAX_OVERHEAD)*MAX_FRAGMENT_COUNT)
-#endif
#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
#define TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES (sizeof(tx_desc_819x_usb_aggr_subframe) + sizeof(tx_fwinfo_819x_usb))
#endif
diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c
index a6e4c37d9c78..41fb67b7337d 100644
--- a/drivers/staging/rtl8192u/r8192U_dm.c
+++ b/drivers/staging/rtl8192u/r8192U_dm.c
@@ -100,14 +100,6 @@ static void dm_check_txpower_tracking(struct net_device *dev);
//static void dm_txpower_reset_recovery(struct net_device *dev);
-// DM --> BB init gain restore
-#ifndef RTL8192U
-static void dm_bb_initialgain_restore(struct net_device *dev);
-
-
-// DM --> BB init gain backup
-static void dm_bb_initialgain_backup(struct net_device *dev);
-#endif
// DM --> Dynamic Init Gain by RSSI
static void dm_dig_init(struct net_device *dev);
static void dm_ctrl_initgain_byrssi(struct net_device *dev);
@@ -122,12 +114,7 @@ static void dm_init_ctstoself(struct net_device *dev);
// DM --> EDCA turbo mode control
static void dm_check_edca_turbo(struct net_device *dev);
-// DM --> HW RF control
-static void dm_check_rfctrl_gpio(struct net_device *dev);
-
-#ifndef RTL8190P
//static void dm_gpio_change_rf(struct net_device *dev);
-#endif
// DM --> Check PBC
static void dm_check_pbc_gpio(struct net_device *dev);
@@ -269,7 +256,6 @@ extern void hal_dm_watchdog(struct net_device *dev)
dm_ctrl_initgain_byrssi(dev);
dm_check_edca_turbo(dev);
dm_bandwidth_autoswitch(dev);
- dm_check_rfctrl_gpio(dev);
dm_check_rx_path_selection(dev);
dm_check_fsync(dev);
@@ -620,16 +606,11 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
tx_cmd.Op = TXCMD_SET_TX_PWR_TRACKING;
tx_cmd.Length = 4;
tx_cmd.Value = Value;
-#ifdef RTL8192U
rtStatus = SendTxCommandPacket(dev, &tx_cmd, 12);
if (rtStatus == RT_STATUS_FAILURE)
{
RT_TRACE(COMP_POWER_TRACKING, "Set configuration with tx cmd queue fail!\n");
}
-#else
- cmpk_message_handle_tx(dev, (u8 *)&tx_cmd,
- DESC_PACKET_TYPE_INIT, sizeof(DCMD_TXCMD_T));
-#endif
mdelay(1);
//DbgPrint("hi, vivi, strange\n");
for(i = 0;i <= 30; i++)
@@ -641,11 +622,7 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
mdelay(1);
continue;
}
-#ifdef RTL8190P
- read_nic_word(dev, 0x1bc, &Avg_TSSI_Meas);
-#else
read_nic_word(dev, 0x13c, &Avg_TSSI_Meas);
-#endif
if(Avg_TSSI_Meas == 0)
{
write_nic_byte(dev, 0x1ba, 0);
@@ -654,14 +631,10 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
for(k = 0;k < 5; k++)
{
-#ifdef RTL8190P
- read_nic_byte(dev, 0x1d8+k, &tmp_report[k]);
-#else
if(k !=4)
read_nic_byte(dev, 0x134+k, &tmp_report[k]);
else
read_nic_byte(dev, 0x13e, &tmp_report[k]);
-#endif
RT_TRACE(COMP_POWER_TRACKING, "TSSI_report_value = %d\n", tmp_report[k]);
}
@@ -708,10 +681,6 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
RT_TRACE(COMP_POWER_TRACKING, "tx power track is done\n");
RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex);
RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real);
-#ifdef RTL8190P
- RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex = %d\n", priv->rfc_txpowertrackingindex);
- RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex_real = %d\n", priv->rfc_txpowertrackingindex_real);
-#endif
RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference);
RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation);
return;
@@ -720,11 +689,7 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
{
if(Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK)
{
- if((priv->rfa_txpowertrackingindex > 0)
-#ifdef RTL8190P
- &&(priv->rfc_txpowertrackingindex > 0)
-#endif
- )
+ if (priv->rfa_txpowertrackingindex > 0)
{
priv->rfa_txpowertrackingindex--;
if(priv->rfa_txpowertrackingindex_real > 4)
@@ -732,33 +697,16 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
priv->rfa_txpowertrackingindex_real--;
rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
}
-#ifdef RTL8190P
- priv->rfc_txpowertrackingindex--;
- if(priv->rfc_txpowertrackingindex_real > 4)
- {
- priv->rfc_txpowertrackingindex_real--;
- rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
- }
-#endif
}
}
else
{
- if((priv->rfa_txpowertrackingindex < 36)
-#ifdef RTL8190P
- &&(priv->rfc_txpowertrackingindex < 36)
-#endif
- )
+ if (priv->rfa_txpowertrackingindex < 36)
{
priv->rfa_txpowertrackingindex++;
priv->rfa_txpowertrackingindex_real++;
rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
-#ifdef RTL8190P
- priv->rfc_txpowertrackingindex++;
- priv->rfc_txpowertrackingindex_real++;
- rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
-#endif
}
}
priv->cck_present_attentuation_difference
@@ -788,10 +736,6 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
}
RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex);
RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real);
-#ifdef RTL8190P
- RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex = %d\n", priv->rfc_txpowertrackingindex);
- RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex_real = %d\n", priv->rfc_txpowertrackingindex_real);
-#endif
RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference);
RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation);
@@ -937,14 +881,10 @@ extern void dm_txpower_trackingcallback(struct work_struct *work)
struct r8192_priv *priv = container_of(dwork,struct r8192_priv,txpower_tracking_wq);
struct net_device *dev = priv->ieee80211->dev;
-#ifdef RTL8190P
- dm_TXPowerTrackingCallback_TSSI(dev);
-#else
if(priv->bDcut == TRUE)
dm_TXPowerTrackingCallback_TSSI(dev);
else
dm_TXPowerTrackingCallback_ThermalMeter(dev);
-#endif
}
@@ -1472,14 +1412,10 @@ static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev)
void dm_initialize_txpower_tracking(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
-#ifdef RTL8190P
- dm_InitializeTXPowerTracking_TSSI(dev);
-#else
if(priv->bDcut == TRUE)
dm_InitializeTXPowerTracking_TSSI(dev);
else
dm_InitializeTXPowerTracking_ThermalMeter(dev);
-#endif
}// dm_InitializeTXPowerTracking
@@ -1677,14 +1613,10 @@ extern void dm_cck_txpower_adjust(
{ // dm_CCKTxPowerAdjust
struct r8192_priv *priv = ieee80211_priv(dev);
-#ifdef RTL8190P
- dm_CCKTxPowerAdjust_TSSI(dev, binch14);
-#else
if(priv->bDcut == TRUE)
dm_CCKTxPowerAdjust_TSSI(dev, binch14);
else
dm_CCKTxPowerAdjust_ThermalMeter(dev, binch14);
-#endif
}
@@ -2194,11 +2126,7 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
{
/* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
// 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
- #ifdef RTL8190P
- write_nic_byte(dev, rOFDM0_RxDetector1, 0x40);
- #else
- write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
- #endif
+ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
write_nic_byte(pAdapter, rOFDM0_RxDetector1, 0x40);
*/
@@ -2265,11 +2193,7 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
{
/* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
// 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
- #ifdef RTL8190P
- write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
- #else
- write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
- #endif
+ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
/*
else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
@@ -2342,11 +2266,7 @@ static void dm_ctrl_initgain_byrssi_highpwr(
// 3.1 Higher PD_TH for OFDM for high power state.
if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
{
- #ifdef RTL8190P
- write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
- #else
- write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
- #endif
+ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
@@ -2370,11 +2290,7 @@ static void dm_ctrl_initgain_byrssi_highpwr(
// 3.2 Recover PD_TH for OFDM for normal power region.
if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
{
- #ifdef RTL8190P
- write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
- #else
- write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
- #endif
+ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
*/
@@ -2516,11 +2432,7 @@ static void dm_pd_th(
{
/* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
// 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
- #ifdef RTL8190P
- write_nic_byte(dev, rOFDM0_RxDetector1, 0x40);
- #else
- write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
- #endif
+ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
write_nic_byte(dev, rOFDM0_RxDetector1, 0x40);
*/
@@ -2535,11 +2447,7 @@ static void dm_pd_th(
{
/* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
// 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
- #ifdef RTL8190P
- write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
- #else
- write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
- #endif
+ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
*/
@@ -2552,11 +2460,7 @@ static void dm_pd_th(
// Higher PD_TH for OFDM for high power state.
if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
{
- #ifdef RTL8190P
- write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
- #else
- write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
- #endif
+ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
*/
@@ -2823,44 +2727,6 @@ static void dm_ctstoself(struct net_device *dev)
}
}
-
-/*-----------------------------------------------------------------------------
- * Function: dm_check_rfctrl_gpio()
- *
- * Overview: Copy 8187B template for 9xseries.
- *
- * Input: NONE
- *
- * Output: NONE
- *
- * Return: NONE
- *
- * Revised History:
- * When Who Remark
- * 05/28/2008 amy Create Version 0 porting from windows code.
- *
- *---------------------------------------------------------------------------*/
-static void dm_check_rfctrl_gpio(struct net_device *dev)
-{
- //struct r8192_priv *priv = ieee80211_priv(dev);
-
- // Work around for DTM test, we will not enable HW - radio on/off because r/w
- // page 1 register before extra bus is enabled causing system failures when resuming
- // from S4. 20080218, Emily
-
- // Stop to execute workitem to prevent S3/S4 bug.
-#ifdef RTL8190P
- return;
-#endif
-#ifdef RTL8192U
- return;
-#endif
-#ifdef RTL8192E
- queue_delayed_work(priv->priv_wq,&priv->gpio_change_rf_wq,0);
-#endif
-
-} /* dm_CheckRfCtrlGPIO */
-
/*-----------------------------------------------------------------------------
* Function: dm_check_pbc_gpio()
*
@@ -2879,7 +2745,6 @@ static void dm_check_rfctrl_gpio(struct net_device *dev)
*---------------------------------------------------------------------------*/
static void dm_check_pbc_gpio(struct net_device *dev)
{
-#ifdef RTL8192U
struct r8192_priv *priv = ieee80211_priv(dev);
u8 tmp1byte;
@@ -2895,83 +2760,9 @@ static void dm_check_pbc_gpio(struct net_device *dev)
RT_TRACE(COMP_IO, "CheckPbcGPIO - PBC is pressed\n");
priv->bpbc_pressed = true;
}
-#endif
}
-#ifdef RTL8192E
-
-/*-----------------------------------------------------------------------------
- * Function: dm_GPIOChangeRF
- * Overview: PCI will not support workitem call back HW radio on-off control.
- *
- * Input: NONE
- *
- * Output: NONE
- *
- * Return: NONE
- *
- * Revised History:
- * When Who Remark
- * 02/21/2008 MHC Create Version 0.
- *
- *---------------------------------------------------------------------------*/
-extern void dm_gpio_change_rf_callback(struct work_struct *work)
-{
- struct delayed_work *dwork = container_of(work,struct delayed_work,work);
- struct r8192_priv *priv = container_of(dwork,struct r8192_priv,gpio_change_rf_wq);
- struct net_device *dev = priv->ieee80211->dev;
- u8 tmp1byte;
- RT_RF_POWER_STATE eRfPowerStateToSet;
- bool bActuallySet = false;
-
- do{
- bActuallySet=false;
-
- if(!priv->up)
- {
- RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF),"dm_gpio_change_rf_callback(): Callback function breaks out!!\n");
- }
- else
- {
- // 0x108 GPIO input register is read only
- //set 0x108 B1= 1: RF-ON; 0: RF-OFF.
- read_nic_byte(dev, GPI, &tmp1byte);
-
- eRfPowerStateToSet = (tmp1byte&BIT1) ? eRfOn : eRfOff;
-
- if((priv->bHwRadioOff == true) && (eRfPowerStateToSet == eRfOn))
- {
- RT_TRACE(COMP_RF, "gpiochangeRF - HW Radio ON\n");
-
- priv->bHwRadioOff = false;
- bActuallySet = true;
- }
- else if ((priv->bHwRadioOff == false) && (eRfPowerStateToSet == eRfOff))
- {
- RT_TRACE(COMP_RF, "gpiochangeRF - HW Radio OFF\n");
- priv->bHwRadioOff = true;
- bActuallySet = true;
- }
-
- if(bActuallySet)
- {
- #ifdef TO_DO
- MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW);
- //DrvIFIndicateCurrentPhyStatus(pAdapter);
- #endif
- }
- else
- {
- msleep(2000);
- }
-
- }
- }while(TRUE)
-
-} /* dm_GPIOChangeRF */
-
-#endif
/*-----------------------------------------------------------------------------
* Function: DM_RFPathCheckWorkItemCallBack()
*
@@ -3329,11 +3120,7 @@ static void dm_init_fsync (struct net_device *dev)
priv->ieee80211->fsync_time_interval = 500;
priv->ieee80211->fsync_rate_bitmap = 0x0f000800;
priv->ieee80211->fsync_rssi_threshold = 30;
-#ifdef RTL8190P
- priv->ieee80211->bfsync_enable = true;
-#else
priv->ieee80211->bfsync_enable = false;
-#endif
priv->ieee80211->fsync_multiple_timeinterval = 3;
priv->ieee80211->fsync_firstdiff_ratethreshold= 100;
priv->ieee80211->fsync_seconddiff_ratethreshold= 200;
@@ -3416,20 +3203,12 @@ extern void dm_fsync_timer_callback(unsigned long data)
priv->bswitch_fsync = !priv->bswitch_fsync;
if(priv->bswitch_fsync)
{
- #ifdef RTL8190P
- write_nic_byte(dev, 0xC36, 0x00);
- #else
write_nic_byte(dev,0xC36, 0x1c);
- #endif
write_nic_byte(dev, 0xC3e, 0x90);
}
else
{
- #ifdef RTL8190P
- write_nic_byte(dev, 0xC36, 0x40);
- #else
write_nic_byte(dev, 0xC36, 0x5c);
- #endif
write_nic_byte(dev, 0xC3e, 0x96);
}
}
@@ -3438,11 +3217,7 @@ extern void dm_fsync_timer_callback(unsigned long data)
if(priv->bswitch_fsync)
{
priv->bswitch_fsync = false;
- #ifdef RTL8190P
- write_nic_byte(dev, 0xC36, 0x40);
- #else
write_nic_byte(dev, 0xC36, 0x5c);
- #endif
write_nic_byte(dev, 0xC3e, 0x96);
}
}
@@ -3465,19 +3240,11 @@ extern void dm_fsync_timer_callback(unsigned long data)
if(priv->bswitch_fsync)
{
priv->bswitch_fsync = false;
- #ifdef RTL8190P
- write_nic_byte(dev, 0xC36, 0x40);
- #else
write_nic_byte(dev, 0xC36, 0x5c);
- #endif
write_nic_byte(dev, 0xC3e, 0x96);
}
priv->ContinueDiffCount = 0;
- #ifdef RTL8190P
- write_nic_dword(dev, rOFDM0_RxDetector2, 0x164052cd);
- #else
write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
- #endif
}
RT_TRACE(COMP_HALDM, "ContinueDiffCount %d\n", priv->ContinueDiffCount);
RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync);
@@ -3502,19 +3269,13 @@ static void dm_EndSWFsync(struct net_device *dev)
{
priv->bswitch_fsync = false;
- #ifdef RTL8190P
- write_nic_byte(dev, 0xC36, 0x40);
- #else
- write_nic_byte(dev, 0xC36, 0x5c);
- #endif
+ write_nic_byte(dev, 0xC36, 0x5c);
write_nic_byte(dev, 0xC3e, 0x96);
}
priv->ContinueDiffCount = 0;
-#ifndef RTL8190P
write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
-#endif
}
@@ -3553,9 +3314,7 @@ static void dm_StartSWFsync(struct net_device *dev)
priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval);
add_timer(&priv->fsync_timer);
-#ifndef RTL8190P
write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cd);
-#endif
}
@@ -3624,11 +3383,7 @@ void dm_check_fsync(struct net_device *dev)
{
if(reg_c38_State != RegC38_Fsync_AP_BCM)
{ //For broadcom AP we write different default value
- #ifdef RTL8190P
- write_nic_byte(dev, rOFDM0_RxDetector3, 0x15);
- #else
- write_nic_byte(dev, rOFDM0_RxDetector3, 0x95);
- #endif
+ write_nic_byte(dev, rOFDM0_RxDetector3, 0x95);
reg_c38_State = RegC38_Fsync_AP_BCM;
}
@@ -3659,11 +3414,7 @@ void dm_check_fsync(struct net_device *dev)
{
if(reg_c38_State != RegC38_NonFsync_Other_AP)
{
- #ifdef RTL8190P
- write_nic_byte(dev, rOFDM0_RxDetector3, 0x10);
- #else
- write_nic_byte(dev, rOFDM0_RxDetector3, 0x90);
- #endif
+ write_nic_byte(dev, rOFDM0_RxDetector3, 0x90);
reg_c38_State = RegC38_NonFsync_Other_AP;
}
@@ -3845,10 +3596,8 @@ static void dm_dynamic_txpower(struct net_device *dev)
SetTxPowerLevel8190(Adapter,pHalData->CurrentChannel);
#endif
-#ifdef RTL8192U
rtl8192_phy_setTxPower(dev,priv->ieee80211->current_network.channel);
//pHalData->bStartTxCtrlByTPCNFR = FALSE; //Clear th flag of Set TX Power from Sitesurvey
-#endif
}
priv->bLastDTPFlag_High = priv->bDynamicTxHighPower;
priv->bLastDTPFlag_Low = priv->bDynamicTxLowPower;
@@ -3885,9 +3634,6 @@ static void dm_send_rssi_tofw(struct net_device *dev)
tx_cmd.Op = TXCMD_SET_RX_RSSI;
tx_cmd.Length = 4;
tx_cmd.Value = priv->undecorated_smoothed_pwdb;
-
- cmpk_message_handle_tx(dev, (u8 *)&tx_cmd,
- DESC_PACKET_TYPE_INIT, sizeof(DCMD_TXCMD_T));
}
/*---------------------------Define function prototype------------------------*/
diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.c b/drivers/staging/rtl8192u/r819xU_cmdpkt.c
index 5bc361b16d4c..f40f9c895f56 100644
--- a/drivers/staging/rtl8192u/r819xU_cmdpkt.c
+++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.c
@@ -37,6 +37,8 @@ rt_status SendTxCommandPacket(struct net_device *dev, void *pData, u32 DataLen)
/* Get TCB and local buffer from common pool.
(It is shared by CmdQ, MgntQ, and USB coalesce DataQ) */
skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + DataLen + 4);
+ if (!skb)
+ return RT_STATUS_FAILURE;
memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
tcb_desc->queue_index = TXCMD_QUEUE;
@@ -60,105 +62,6 @@ rt_status SendTxCommandPacket(struct net_device *dev, void *pData, u32 DataLen)
}
/*-----------------------------------------------------------------------------
- * Function: cmpk_message_handle_tx()
- *
- * Overview: Driver internal module can call the API to send message to
- * firmware side. For example, you can send a debug command packet.
- * Or you can send a request for FW to modify RLX4181 LBUS HW bank.
- * Otherwise, you can change MAC/PHT/RF register by firmware at
- * run time. We do not support message more than one segment now.
- *
- * Input: NONE
- *
- * Output: NONE
- *
- * Return: NONE
- *
- * Revised History:
- * When Who Remark
- * 05/06/2008 amy porting from windows code.
- *
- *---------------------------------------------------------------------------*/
-extern rt_status cmpk_message_handle_tx(struct net_device *dev,
- u8 *codevirtualaddress,
- u32 packettype, u32 buffer_len)
-{
-
- bool rt_status = true;
-#ifdef RTL8192U
- return rt_status;
-#else
- struct r8192_priv *priv = ieee80211_priv(dev);
- u16 frag_threshold;
- u16 frag_length, frag_offset = 0;
-
- rt_firmware *pfirmware = priv->pFirmware;
- struct sk_buff *skb;
- unsigned char *seg_ptr;
- cb_desc *tcb_desc;
- u8 bLastIniPkt;
-
- firmware_init_param(dev);
- /* Fragmentation might be required */
- frag_threshold = pfirmware->cmdpacket_frag_thresold;
- do {
- if ((buffer_len - frag_offset) > frag_threshold) {
- frag_length = frag_threshold;
- bLastIniPkt = 0;
-
- } else {
- frag_length = buffer_len - frag_offset;
- bLastIniPkt = 1;
-
- }
-
- /* Allocate skb buffer to contain firmware info and tx
- descriptor info add 4 to avoid packet appending overflow. */
-#ifdef RTL8192U
- skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
-#else
- skb = dev_alloc_skb(frag_length + 4);
-#endif
- memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
- tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
- tcb_desc->queue_index = TXCMD_QUEUE;
- tcb_desc->bCmdOrInit = packettype;
- tcb_desc->bLastIniPkt = bLastIniPkt;
-
-#ifdef RTL8192U
- skb_reserve(skb, USB_HWDESC_HEADER_LEN);
-#endif
-
- seg_ptr = skb_put(skb, buffer_len);
- /*
- * Transform from little endian to big endian
- * and pending zero
- */
- memcpy(seg_ptr, codevirtualaddress, buffer_len);
- tcb_desc->txbuf_size = (u16)buffer_len;
-
-
- if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) ||
- (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) ||
- (priv->ieee80211->queue_stop)) {
- RT_TRACE(COMP_FIRMWARE, "======> tx full!\n");
- skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
- } else {
- priv->ieee80211->softmac_hard_start_xmit(skb, dev);
- }
-
- codevirtualaddress += frag_length;
- frag_offset += frag_length;
-
- } while (frag_offset < buffer_len);
-
- return rt_status;
-
-
-#endif
-}
-
-/*-----------------------------------------------------------------------------
* Function: cmpk_counttxstatistic()
*
* Overview:
diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.h b/drivers/staging/rtl8192u/r819xU_cmdpkt.h
index ebe403270a5b..c79878af7021 100644
--- a/drivers/staging/rtl8192u/r819xU_cmdpkt.h
+++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.h
@@ -192,8 +192,6 @@ typedef enum _rt_status{
RT_STATUS_RESOURCE
}rt_status,*prt_status;
-extern rt_status cmpk_message_handle_tx(struct net_device *dev, u8 *codevirtualaddress, u32 packettype, u32 buffer_len);
-
extern u32 cmpk_message_handle_rx(struct net_device *dev, struct ieee80211_rx_stats *pstats);
extern rt_status SendTxCommandPacket( struct net_device *dev, void *pData, u32 DataLen);
diff --git a/drivers/staging/rtl8192u/r819xU_firmware.c b/drivers/staging/rtl8192u/r819xU_firmware.c
index bb924ac97e47..d6a6de3a64f5 100644
--- a/drivers/staging/rtl8192u/r819xU_firmware.c
+++ b/drivers/staging/rtl8192u/r819xU_firmware.c
@@ -61,20 +61,16 @@ bool fw_download_code(struct net_device *dev, u8 *code_virtual_address, u32 buff
/* Allocate skb buffer to contain firmware info and tx descriptor info
* add 4 to avoid packet appending overflow.
* */
- #ifdef RTL8192U
skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
- #else
- skb = dev_alloc_skb(frag_length + 4);
- #endif
+ if (!skb)
+ return false;
memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
tcb_desc->queue_index = TXCMD_QUEUE;
tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
tcb_desc->bLastIniPkt = bLastIniPkt;
- #ifdef RTL8192U
skb_reserve(skb, USB_HWDESC_HEADER_LEN);
- #endif
seg_ptr = skb->data;
/*
* Transform from little endian to big endian
@@ -299,16 +295,10 @@ bool init_firmware(struct net_device *dev)
mapped_file = pfirmware->firmware_buf;
file_length = fw_entry->size;
} else {
-#ifdef RTL8190P
- memcpy(pfirmware->firmware_buf,fw_entry->data,fw_entry->size);
- mapped_file = pfirmware->firmware_buf;
- file_length = fw_entry->size;
-#else
memset(pfirmware->firmware_buf,0,128);
memcpy(&pfirmware->firmware_buf[128],fw_entry->data,fw_entry->size);
mapped_file = pfirmware->firmware_buf;
file_length = fw_entry->size + 128;
-#endif
}
pfirmware->firmware_buf_size = file_length;
}else if (rst_opt == OPT_FIRMWARE_RESET ) {
@@ -340,15 +330,6 @@ bool init_firmware(struct net_device *dev)
* will set polling bit when firmware code is also configured
*/
pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE;
-#ifdef RTL8190P
- // To initialize IMEM, CPU move code from 0x80000080, hence, we send 0x80 byte packet
- rt_status = fwSendNullPacket(dev, RTL8190_CPU_START_OFFSET);
- if (rt_status != true)
- {
- RT_TRACE(COMP_INIT, "fwSendNullPacket() fail ! \n");
- goto download_firmware_fail;
- }
-#endif
//mdelay(1000);
/*
* To initialize IMEM, CPU move code from 0x80000080,
diff --git a/drivers/staging/rtl8192u/r819xU_phy.c b/drivers/staging/rtl8192u/r819xU_phy.c
index a6fac081e42c..17ac1202c906 100644
--- a/drivers/staging/rtl8192u/r819xU_phy.c
+++ b/drivers/staging/rtl8192u/r819xU_phy.c
@@ -1799,12 +1799,6 @@ extern void InitialGainOperateWorkItemCallBack(struct work_struct *work)
RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xa0a is %x\n",
priv->initgain_backup.cca);
-#ifdef RTL8190P
- SetTxPowerLevel8190(Adapter, priv->CurrentChannel);
-#endif
-#ifdef RTL8192E
- SetTxPowerLevel8190(Adapter, priv->CurrentChannel);
-#endif
rtl8192_phy_setTxPower(dev, priv->ieee80211->current_network.channel);
if (dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM)
diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c
index c812d6c7dc31..dbefa43e4c2c 100644
--- a/drivers/staging/rtl8712/usb_intf.c
+++ b/drivers/staging/rtl8712/usb_intf.c
@@ -353,11 +353,6 @@ static void disable_ht_for_spec_devid(const struct usb_device_id *pdid,
}
}
-static u8 key_2char2num(u8 hch, u8 lch)
-{
- return (hex_to_bin(hch) << 4) | hex_to_bin(lch);
-}
-
/*
* drv_init() - a device potentially for us
*
@@ -465,16 +460,7 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf,
r8712_efuse_pg_packet_read(padapter, offset,
&pdata[i]);
- if (r8712_initmac) {
- /* Users specify the mac address */
- int jj, kk;
-
- for (jj = 0, kk = 0; jj < ETH_ALEN;
- jj++, kk += 3)
- mac[jj] =
- key_2char2num(r8712_initmac[kk],
- r8712_initmac[kk + 1]);
- } else {
+ if (!r8712_initmac || !mac_pton(r8712_initmac, mac)) {
/* Use the mac address stored in the Efuse
* offset = 0x12 for usb in efuse
*/
diff --git a/drivers/staging/silicom/bpctl_mod.c b/drivers/staging/silicom/bpctl_mod.c
index 495272d01348..39dc92a271ab 100644
--- a/drivers/staging/silicom/bpctl_mod.c
+++ b/drivers/staging/silicom/bpctl_mod.c
@@ -1,11 +1,11 @@
/******************************************************************************/
/* */
-/* Bypass Control utility, Copyright (c) 2005-20011 Silicom */
+/* Bypass Control utility, Copyright (c) 2005-2011 Silicom */
/* */
/* 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, located in the file LICENSE. */
-/* Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. */
+/* Copyright(c) 2007 - 2009, 2013 Intel Corporation. All rights reserved. */
/* */
/* */
/******************************************************************************/
@@ -124,80 +124,60 @@ int bp_proc_create(void);
int is_bypass_fn(struct bpctl_dev *pbpctl_dev);
int get_dev_idx_bsf(int bus, int slot, int func);
-static unsigned long str_to_hex(char *p);
+static int bp_get_dev_idx_bsf(struct net_device *dev, int *index)
+{
+ struct ethtool_drvinfo drvinfo = {0};
+ char *buf;
+ int bus, slot, func;
+
+ if (dev->ethtool_ops && dev->ethtool_ops->get_drvinfo)
+ dev->ethtool_ops->get_drvinfo(dev, &drvinfo);
+ else
+ return -EOPNOTSUPP;
+
+ if (!drvinfo.bus_info)
+ return -ENODATA;
+ if (!strcmp(drvinfo.bus_info, "N/A"))
+ return -ENODATA;
+
+ buf = strchr(drvinfo.bus_info, ':');
+ if (!buf)
+ return -EINVAL;
+ buf++;
+ if (sscanf(buf, "%x:%x.%x", &bus, &slot, &func) != 3)
+ return -EINVAL;
+
+ *index = get_dev_idx_bsf(bus, slot, func);
+ return 0;
+}
+
static int bp_device_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
static struct bpctl_dev *pbpctl_dev, *pbpctl_dev_m;
int dev_num = 0, ret = 0, ret_d = 0, time_left = 0;
+
/* printk("BP_PROC_SUPPORT event =%d %s %d\n", event,dev->name, dev->ifindex ); */
/* return NOTIFY_DONE; */
if (!dev)
return NOTIFY_DONE;
- if (event == NETDEV_REGISTER) {
- {
- struct ethtool_drvinfo drvinfo;
- char cbuf[32];
- char *buf = NULL;
- char res[10];
- int i = 0, ifindex, idx_dev = 0;
- int bus = 0, slot = 0, func = 0;
- ifindex = dev->ifindex;
-
- memset(res, 0, 10);
- memset(&drvinfo, 0, sizeof(struct ethtool_drvinfo));
-
- if (dev->ethtool_ops && dev->ethtool_ops->get_drvinfo) {
- memset(&drvinfo, 0, sizeof(drvinfo));
- dev->ethtool_ops->get_drvinfo(dev, &drvinfo);
- } else
- return NOTIFY_DONE;
- if (!drvinfo.bus_info)
- return NOTIFY_DONE;
- if (!strcmp(drvinfo.bus_info, "N/A"))
- return NOTIFY_DONE;
- memcpy(&cbuf, drvinfo.bus_info, 32);
- buf = &cbuf[0];
- while (*buf++ != ':')
- ;
- for (i = 0; i < 10; i++, buf++) {
- if (*buf == ':')
- break;
- res[i] = *buf;
-
- }
- buf++;
- bus = str_to_hex(res);
- memset(res, 0, 10);
-
- for (i = 0; i < 10; i++, buf++) {
- if (*buf == '.')
- break;
- res[i] = *buf;
-
- }
- buf++;
- slot = str_to_hex(res);
- func = str_to_hex(buf);
- idx_dev = get_dev_idx_bsf(bus, slot, func);
-
- if (idx_dev != -1) {
+ if (event == NETDEV_REGISTER) {
+ int idx_dev;
- bpctl_dev_arr[idx_dev].ifindex = ifindex;
- bpctl_dev_arr[idx_dev].ndev = dev;
+ if (bp_get_dev_idx_bsf(dev, &idx_dev))
+ return NOTIFY_DONE;
- bypass_proc_remove_dev_sd(&bpctl_dev_arr
- [idx_dev]);
- bypass_proc_create_dev_sd(&bpctl_dev_arr
- [idx_dev]);
+ if (idx_dev == -1)
+ return NOTIFY_DONE;
- }
+ bpctl_dev_arr[idx_dev].ifindex = dev->ifindex;
+ bpctl_dev_arr[idx_dev].ndev = dev;
- }
+ bypass_proc_remove_dev_sd(&bpctl_dev_arr[idx_dev]);
+ bypass_proc_create_dev_sd(&bpctl_dev_arr[idx_dev]);
return NOTIFY_DONE;
-
}
if (event == NETDEV_UNREGISTER) {
int idx_dev = 0;
@@ -5269,36 +5249,6 @@ int get_dev_idx_bsf(int bus, int slot, int func)
return -1;
}
-static void str_low(char *str)
-{
- int i;
-
- for (i = 0; i < strlen(str); i++)
- if ((str[i] >= 65) && (str[i] <= 90))
- str[i] += 32;
-}
-
-static unsigned long str_to_hex(char *p)
-{
- unsigned long hex = 0;
- unsigned long length = strlen(p), shift = 0;
- unsigned char dig = 0;
-
- str_low(p);
- length = strlen(p);
-
- if (length == 0)
- return 0;
-
- do {
- dig = p[--length];
- dig = dig < 'a' ? (dig - '0') : (dig - 'a' + 0xa);
- hex |= (dig << shift);
- shift += 4;
- } while (length);
- return hex;
-}
-
static int get_dev_idx(int ifindex)
{
int idx_dev = 0;
@@ -5329,70 +5279,26 @@ static struct bpctl_dev *get_dev_idx_p(int ifindex)
static void if_scan_init(void)
{
- int idx_dev = 0;
struct net_device *dev;
- int ifindex;
+
/* rcu_read_lock(); */
/* rtnl_lock(); */
/* rcu_read_lock(); */
for_each_netdev(&init_net, dev) {
+ int idx_dev;
- struct ethtool_drvinfo drvinfo;
- char cbuf[32];
- char *buf = NULL;
- char res[10];
- int i = 0;
- int bus = 0, slot = 0, func = 0;
- ifindex = dev->ifindex;
-
- memset(res, 0, 10);
- memset(&drvinfo, 0, sizeof(struct ethtool_drvinfo));
-
- if (dev->ethtool_ops && dev->ethtool_ops->get_drvinfo) {
- memset(&drvinfo, 0, sizeof(drvinfo));
- dev->ethtool_ops->get_drvinfo(dev, &drvinfo);
- } else
+ if (bp_get_dev_idx_bsf(dev, &idx_dev))
continue;
- if (!strcmp(drvinfo.bus_info, "N/A"))
- continue;
- memcpy(&cbuf, drvinfo.bus_info, 32);
- buf = &cbuf[0];
- while (*buf++ != ':')
- ;
- for (i = 0; i < 10; i++, buf++) {
- if (*buf == ':')
- break;
- res[i] = *buf;
-
- }
- buf++;
- bus = str_to_hex(res);
- memset(res, 0, 10);
-
- for (i = 0; i < 10; i++, buf++) {
- if (*buf == '.')
- break;
- res[i] = *buf;
-
- }
- buf++;
- slot = str_to_hex(res);
- func = str_to_hex(buf);
- idx_dev = get_dev_idx_bsf(bus, slot, func);
-
- if (idx_dev != -1) {
-
- bpctl_dev_arr[idx_dev].ifindex = ifindex;
- bpctl_dev_arr[idx_dev].ndev = dev;
-
- }
+ if (idx_dev == -1)
+ continue;
+ bpctl_dev_arr[idx_dev].ifindex = dev->ifindex;
+ bpctl_dev_arr[idx_dev].ndev = dev;
}
/* rtnl_unlock(); */
/* rcu_read_unlock(); */
-
}
static long device_ioctl(struct file *file, /* see include/linux/fs.h */
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
index 869dcd3b385a..b6eb5df7a426 100644
--- a/drivers/staging/slicoss/slicoss.c
+++ b/drivers/staging/slicoss/slicoss.c
@@ -791,8 +791,8 @@ static bool slic_mac_filter(struct adapter *adapter,
struct mcast_address *mcaddr = adapter->mcastaddrs;
while (mcaddr) {
- if (!compare_ether_addr(mcaddr->address,
- ether_frame->ether_dhost)) {
+ if (ether_addr_equal(mcaddr->address,
+ ether_frame->ether_dhost)) {
adapter->rcv_multicasts++;
netdev->stats.multicast++;
return true;
@@ -2333,7 +2333,7 @@ static int slic_mcast_add_list(struct adapter *adapter, char *address)
/* Check to see if it already exists */
mlist = adapter->mcastaddrs;
while (mlist) {
- if (!compare_ether_addr(mlist->address, address))
+ if (ether_addr_equal(mlist->address, address))
return 0;
mlist = mlist->next;
}
diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c
index 8add64b1cb09..5c857618d905 100644
--- a/drivers/staging/sm7xxfb/sm7xxfb.c
+++ b/drivers/staging/sm7xxfb/sm7xxfb.c
@@ -933,7 +933,6 @@ static void smtcfb_pci_remove(struct pci_dev *pdev)
struct smtcfb_info *sfb;
sfb = pci_get_drvdata(pdev);
- pci_set_drvdata(pdev, NULL);
smtc_unmap_smem(sfb);
smtc_unmap_mmio(sfb);
unregister_framebuffer(&sfb->fb);
diff --git a/drivers/staging/speakup/Kconfig b/drivers/staging/speakup/Kconfig
index 8c3e7a60a9be..efd6f4560d3e 100644
--- a/drivers/staging/speakup/Kconfig
+++ b/drivers/staging/speakup/Kconfig
@@ -51,6 +51,7 @@ config SPEAKUP_SYNTH_ACNTSA
config SPEAKUP_SYNTH_ACNTPC
tristate "Accent PC synthesizer support"
+ depends on ISA || COMPILE_TEST
---help---
This is the Speakup driver for the accent pc
synthesizer. You can say y to build it into the kernel,
@@ -102,6 +103,7 @@ config SPEAKUP_SYNTH_DECEXT
config SPEAKUP_SYNTH_DECPC
depends on m
+ depends on ISA || COMPILE_TEST
tristate "DECtalk PC (big ISA card) synthesizer support"
---help---
@@ -124,6 +126,7 @@ config SPEAKUP_SYNTH_DECPC
config SPEAKUP_SYNTH_DTLK
tristate "DoubleTalk PC synthesizer support"
+ depends on ISA || COMPILE_TEST
---help---
This is the Speakup driver for the internal DoubleTalk
@@ -134,6 +137,7 @@ config SPEAKUP_SYNTH_DTLK
config SPEAKUP_SYNTH_KEYPC
tristate "Keynote Gold PC synthesizer support"
+ depends on ISA || COMPILE_TEST
---help---
This is the Speakup driver for the Keynote Gold
diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c
index 51bdea3a5bea..f31afa2cffb7 100644
--- a/drivers/staging/speakup/kobjects.c
+++ b/drivers/staging/speakup/kobjects.c
@@ -586,6 +586,25 @@ ssize_t spk_var_show(struct kobject *kobj, struct kobj_attribute *attr,
EXPORT_SYMBOL_GPL(spk_var_show);
/*
+ * Used to reset either default_pitch or default_vol.
+ */
+static inline void spk_reset_default_value(char *header_name,
+ int *synth_default_value, int idx)
+{
+ struct st_var_header *param;
+
+ if (synth && synth_default_value) {
+ param = spk_var_header_by_name(header_name);
+ if (param) {
+ spk_set_num_var(synth_default_value[idx],
+ param, E_NEW_DEFAULT);
+ spk_set_num_var(0, param, E_DEFAULT);
+ pr_info("%s reset to default value\n", param->name);
+ }
+ }
+}
+
+/*
* This function is called when a user echos a value to one of the
* variable parameters.
*/
@@ -624,56 +643,47 @@ ssize_t spk_var_store(struct kobject *kobj, struct kobj_attribute *attr,
if (ret == -ERANGE) {
var_data = param->data;
pr_warn("value for %s out of range, expect %d to %d\n",
- attr->attr.name,
+ param->name,
var_data->u.n.low, var_data->u.n.high);
}
+
+ /*
+ * If voice was just changed, we might need to reset our default
+ * pitch and volume.
+ */
+ if (param->var_id == VOICE && synth &&
+ (ret == 0 || ret == -ERESTART)) {
+ var_data = param->data;
+ value = var_data->u.n.value;
+ spk_reset_default_value("pitch", synth->default_pitch,
+ value);
+ spk_reset_default_value("vol", synth->default_vol,
+ value);
+ }
break;
case VAR_STRING:
- len = strlen(buf);
- if ((len >= 1) && (buf[len - 1] == '\n'))
+ len = strlen(cp);
+ if ((len >= 1) && (cp[len - 1] == '\n'))
--len;
- if ((len >= 2) && (buf[0] == '"') && (buf[len - 1] == '"')) {
- ++buf;
+ if ((len >= 2) && (cp[0] == '"') && (cp[len - 1] == '"')) {
+ ++cp;
len -= 2;
}
- cp = (char *) buf;
cp[len] = '\0';
- ret = spk_set_string_var(buf, param, len);
+ ret = spk_set_string_var(cp, param, len);
if (ret == -E2BIG)
pr_warn("value too long for %s\n",
- attr->attr.name);
+ param->name);
break;
default:
pr_warn("%s unknown type %d\n",
param->name, (int)param->var_type);
break;
}
- /*
- * If voice was just changed, we might need to reset our default
- * pitch and volume.
- */
- if (strcmp(attr->attr.name, "voice") == 0) {
- if (synth && synth->default_pitch) {
- param = spk_var_header_by_name("pitch");
- if (param) {
- spk_set_num_var(synth->default_pitch[value],
- param, E_NEW_DEFAULT);
- spk_set_num_var(0, param, E_DEFAULT);
- }
- }
- if (synth && synth->default_vol) {
- param = spk_var_header_by_name("vol");
- if (param) {
- spk_set_num_var(synth->default_vol[value],
- param, E_NEW_DEFAULT);
- spk_set_num_var(0, param, E_DEFAULT);
- }
- }
- }
spin_unlock_irqrestore(&speakup_info.spinlock, flags);
if (ret == -ERESTART)
- pr_info("%s reset to default value\n", attr->attr.name);
+ pr_info("%s reset to default value\n", param->name);
return count;
}
EXPORT_SYMBOL_GPL(spk_var_store);
diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c
index d8957a556626..76a1ff0e6275 100644
--- a/drivers/staging/usbip/stub_dev.c
+++ b/drivers/staging/usbip/stub_dev.c
@@ -357,8 +357,9 @@ static int stub_probe(struct usb_interface *interface,
busid_priv = get_busid_priv(udev_busid);
if (!busid_priv || (busid_priv->status == STUB_BUSID_REMOV) ||
(busid_priv->status == STUB_BUSID_OTHER)) {
- dev_info(&interface->dev, "%s is not in match_busid table... "
- "skip!\n", udev_busid);
+ dev_info(&interface->dev,
+ "%s is not in match_busid table... skip!\n",
+ udev_busid);
/*
* Return value should be ENODEV or ENOXIO to continue trying
@@ -375,8 +376,10 @@ static int stub_probe(struct usb_interface *interface,
}
if (!strcmp(udev->bus->bus_name, "vhci_hcd")) {
- dev_dbg(&udev->dev, "%s is attached on vhci_hcd... skip!\n",
- udev_busid);
+ dev_dbg(&udev->dev,
+ "%s is attached on vhci_hcd... skip!\n",
+ udev_busid);
+
return -ENODEV;
}
@@ -386,10 +389,10 @@ static int stub_probe(struct usb_interface *interface,
return -ENODEV;
busid_priv->interf_count++;
- dev_info(&interface->dev, "usbip-host: register new interface "
- "(bus %u dev %u ifn %u)\n",
- udev->bus->busnum, udev->devnum,
- interface->cur_altsetting->desc.bInterfaceNumber);
+ dev_info(&interface->dev,
+ "usbip-host: register new interface (bus %u dev %u ifn %u)\n",
+ udev->bus->busnum, udev->devnum,
+ interface->cur_altsetting->desc.bInterfaceNumber);
/* set private data to usb_interface */
usb_set_intfdata(interface, sdev);
@@ -412,9 +415,10 @@ static int stub_probe(struct usb_interface *interface,
if (!sdev)
return -ENOMEM;
- dev_info(&interface->dev, "usbip-host: register new device "
- "(bus %u dev %u ifn %u)\n", udev->bus->busnum, udev->devnum,
- interface->cur_altsetting->desc.bInterfaceNumber);
+ dev_info(&interface->dev,
+ "usbip-host: register new device (bus %u dev %u ifn %u)\n",
+ udev->bus->busnum, udev->devnum,
+ interface->cur_altsetting->desc.bInterfaceNumber);
busid_priv->interf_count = 0;
busid_priv->shutdown_busid = 0;
diff --git a/drivers/staging/usbip/stub_main.c b/drivers/staging/usbip/stub_main.c
index 33027cce6700..baf857f7cc88 100644
--- a/drivers/staging/usbip/stub_main.c
+++ b/drivers/staging/usbip/stub_main.c
@@ -255,14 +255,14 @@ static int __init usbip_host_init(void)
}
ret = usb_register(&stub_driver);
- if (ret < 0) {
+ if (ret) {
pr_err("usb_register failed %d\n", ret);
goto err_usb_register;
}
ret = driver_create_file(&stub_driver.drvwrap.driver,
&driver_attr_match_busid);
- if (ret < 0) {
+ if (ret) {
pr_err("driver_create_file failed\n");
goto err_create_file;
}
diff --git a/drivers/staging/usbip/userspace/configure.ac b/drivers/staging/usbip/userspace/configure.ac
index 2be4060f9036..0ee5d9263996 100644
--- a/drivers/staging/usbip/userspace/configure.ac
+++ b/drivers/staging/usbip/userspace/configure.ac
@@ -70,7 +70,6 @@ AC_ARG_WITH([tcp-wrappers],
[AC_MSG_RESULT([not found]); exit 1])
else
AC_MSG_RESULT([no]);
- LIBS="$saved_LIBS"
fi],
dnl [ACTION-IF-NOT-GIVEN]
[AC_MSG_RESULT([(default)])
diff --git a/drivers/staging/usbip/userspace/doc/usbip.8 b/drivers/staging/usbip/userspace/doc/usbip.8
index ccdadc87c478..a6097be25d28 100644
--- a/drivers/staging/usbip/userspace/doc/usbip.8
+++ b/drivers/staging/usbip/userspace/doc/usbip.8
@@ -3,7 +3,7 @@
usbip \- manage USB/IP devices
.SH SYNOPSIS
.B usbip
-[\foptions\R] <\fIcommand\fR> <\fIargs\fR>
+[\fIoptions\fR] <\fIcommand\fR> <\fIargs\fR>
.SH DESCRIPTION
On a USB/IP server, devices can be listed, bound, and unbound using
@@ -23,6 +23,12 @@ Print debugging information.
Log to syslog.
.PP
+.HP
+\fB\-\-tcp-port PORT\fR
+.IP
+Connect to PORT on remote host (used for attach and list --remote).
+.PP
+
.SH COMMANDS
.HP
\fBversion\fR
diff --git a/drivers/staging/usbip/userspace/doc/usbipd.8 b/drivers/staging/usbip/userspace/doc/usbipd.8
index d896936f1780..ac4635db3f03 100644
--- a/drivers/staging/usbip/userspace/doc/usbipd.8
+++ b/drivers/staging/usbip/userspace/doc/usbipd.8
@@ -14,10 +14,22 @@ Devices have to explicitly be exported using
before usbipd makes them available to other hosts.
The daemon accepts connections from USB/IP clients
-on TCP port 3240.
+on TCP port 3240 by default.
.SH OPTIONS
.HP
+\fB\-4\fR, \fB\-\-ipv4\fR
+.IP
+Bind to IPv4. Default is both.
+.PP
+
+.HP
+\fB\-6\fR, \fB\-\-ipv6\fR
+.IP
+Bind to IPv6. Default is both.
+.PP
+
+.HP
\fB\-D\fR, \fB\-\-daemon\fR
.IP
Run as a daemon process.
@@ -29,6 +41,19 @@ Run as a daemon process.
Print debugging information.
.PP
+.HP
+\fB\-PFILE\fR, \fB\-\-pid FILE\fR
+.IP
+Write process id to FILE.
+.br
+If no FILE specified, use /var/run/usbipd.pid
+.PP
+
+\fB\-tPORT\fR, \fB\-\-tcp\-port PORT\fR
+.IP
+Listen on TCP/IP port PORT.
+.PP
+
\fB\-h\fR, \fB\-\-help\fR
.IP
Print the program help message and exit.
diff --git a/drivers/staging/usbip/userspace/src/usbip_network.c b/drivers/staging/usbip/userspace/src/usbip_network.c
index c39a07f1d38c..b4c37e76a6e0 100644
--- a/drivers/staging/usbip/userspace/src/usbip_network.c
+++ b/drivers/staging/usbip/userspace/src/usbip_network.c
@@ -25,6 +25,10 @@
#include <netinet/tcp.h>
#include <unistd.h>
+#ifdef HAVE_LIBWRAP
+#include <tcpd.h>
+#endif
+
#include "usbip_common.h"
#include "usbip_network.h"
@@ -239,6 +243,18 @@ int usbip_net_set_keepalive(int sockfd)
return ret;
}
+int usbip_net_set_v6only(int sockfd)
+{
+ const int val = 1;
+ int ret;
+
+ ret = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val));
+ if (ret < 0)
+ dbg("setsockopt: IPV6_V6ONLY");
+
+ return ret;
+}
+
/*
* IPv6 Ready
*/
diff --git a/drivers/staging/usbip/userspace/src/usbip_network.h b/drivers/staging/usbip/userspace/src/usbip_network.h
index 2d0e4277b62b..f19ae19799b4 100644
--- a/drivers/staging/usbip/userspace/src/usbip_network.h
+++ b/drivers/staging/usbip/userspace/src/usbip_network.h
@@ -180,6 +180,7 @@ int usbip_net_recv_op_common(int sockfd, uint16_t *code);
int usbip_net_set_reuseaddr(int sockfd);
int usbip_net_set_nodelay(int sockfd);
int usbip_net_set_keepalive(int sockfd);
+int usbip_net_set_v6only(int sockfd);
int usbip_net_tcp_connect(char *hostname, char *port);
#endif /* __USBIP_NETWORK_H */
diff --git a/drivers/staging/usbip/userspace/src/usbipd.c b/drivers/staging/usbip/userspace/src/usbipd.c
index 1c76cfd274d0..7980f8b5517b 100644
--- a/drivers/staging/usbip/userspace/src/usbipd.c
+++ b/drivers/staging/usbip/userspace/src/usbipd.c
@@ -56,6 +56,13 @@ static const char usbip_version_string[] = PACKAGE_STRING;
static const char usbipd_help_string[] =
"usage: usbipd [options]\n"
+ "\n"
+ " -4, --ipv4\n"
+ " Bind to IPv4. Default is both.\n"
+ "\n"
+ " -6, --ipv6\n"
+ " Bind to IPv6. Default is both.\n"
+ "\n"
" -D, --daemon\n"
" Run as a daemon process.\n"
"\n"
@@ -354,14 +361,15 @@ static void addrinfo_to_text(struct addrinfo *ai, char buf[],
snprintf(buf, buf_size, "%s:%s", hbuf, sbuf);
}
-static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[])
+static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[],
+ int maxsockfd)
{
struct addrinfo *ai;
int ret, nsockfd = 0;
const size_t ai_buf_size = NI_MAXHOST + NI_MAXSERV + 2;
char ai_buf[ai_buf_size];
- for (ai = ai_head; ai && nsockfd < MAXSOCKFD; ai = ai->ai_next) {
+ for (ai = ai_head; ai && nsockfd < maxsockfd; ai = ai->ai_next) {
int sock;
addrinfo_to_text(ai, ai_buf, ai_buf_size);
dbg("opening %s", ai_buf);
@@ -374,6 +382,9 @@ static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[])
usbip_net_set_reuseaddr(sock);
usbip_net_set_nodelay(sock);
+ /* We use seperate sockets for IPv4 and IPv6
+ * (see do_standalone_mode()) */
+ usbip_net_set_v6only(sock);
if (sock >= FD_SETSIZE) {
err("FD_SETSIZE: %s: sock=%d, max=%d",
@@ -402,11 +413,6 @@ static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[])
sockfdlist[nsockfd++] = sock;
}
- if (nsockfd == 0)
- return -1;
-
- dbg("listening on %d address%s", nsockfd, (nsockfd == 1) ? "" : "es");
-
return nsockfd;
}
@@ -473,11 +479,11 @@ static void remove_pid_file()
}
}
-static int do_standalone_mode(int daemonize)
+static int do_standalone_mode(int daemonize, int ipv4, int ipv6)
{
struct addrinfo *ai_head;
int sockfdlist[MAXSOCKFD];
- int nsockfd;
+ int nsockfd, family;
int i, terminate;
struct pollfd *fds;
struct timespec timeout;
@@ -501,21 +507,36 @@ static int do_standalone_mode(int daemonize)
set_signal();
write_pid_file();
- ai_head = do_getaddrinfo(NULL, PF_UNSPEC);
+ info("starting " PROGNAME " (%s)", usbip_version_string);
+
+ /*
+ * To suppress warnings on systems with bindv6only disabled
+ * (default), we use seperate sockets for IPv6 and IPv4 and set
+ * IPV6_V6ONLY on the IPv6 sockets.
+ */
+ if (ipv4 && ipv6)
+ family = AF_UNSPEC;
+ else if (ipv4)
+ family = AF_INET;
+ else
+ family = AF_INET6;
+
+ ai_head = do_getaddrinfo(NULL, family);
if (!ai_head) {
usbip_host_driver_close();
return -1;
}
-
- info("starting " PROGNAME " (%s)", usbip_version_string);
-
- nsockfd = listen_all_addrinfo(ai_head, sockfdlist);
+ nsockfd = listen_all_addrinfo(ai_head, sockfdlist,
+ sizeof(sockfdlist) / sizeof(*sockfdlist));
+ freeaddrinfo(ai_head);
if (nsockfd <= 0) {
err("failed to open a listening socket");
- freeaddrinfo(ai_head);
usbip_host_driver_close();
return -1;
}
+
+ dbg("listening on %d address%s", nsockfd, (nsockfd == 1) ? "" : "es");
+
fds = calloc(nsockfd, sizeof(struct pollfd));
for (i = 0; i < nsockfd; i++) {
fds[i].fd = sockfdlist[i];
@@ -551,7 +572,6 @@ static int do_standalone_mode(int daemonize)
info("shutting down " PROGNAME);
free(fds);
- freeaddrinfo(ai_head);
usbip_host_driver_close();
return 0;
@@ -560,6 +580,9 @@ static int do_standalone_mode(int daemonize)
int main(int argc, char *argv[])
{
static const struct option longopts[] = {
+ { "ipv4", no_argument, NULL, '4' },
+ { "ipv6", no_argument, NULL, '6' },
+ { "daemon", no_argument, NULL, 'D' },
{ "daemon", no_argument, NULL, 'D' },
{ "debug", no_argument, NULL, 'd' },
{ "pid", optional_argument, NULL, 'P' },
@@ -576,6 +599,7 @@ int main(int argc, char *argv[])
} cmd;
int daemonize = 0;
+ int ipv4 = 0, ipv6 = 0;
int opt, rc = -1;
pid_file = NULL;
@@ -587,12 +611,18 @@ int main(int argc, char *argv[])
cmd = cmd_standalone_mode;
for (;;) {
- opt = getopt_long(argc, argv, "DdP::t:hv", longopts, NULL);
+ opt = getopt_long(argc, argv, "46DdP::t:hv", longopts, NULL);
if (opt == -1)
break;
switch (opt) {
+ case '4':
+ ipv4 = 1;
+ break;
+ case '6':
+ ipv6 = 1;
+ break;
case 'D':
daemonize = 1;
break;
@@ -618,9 +648,12 @@ int main(int argc, char *argv[])
}
}
+ if (!ipv4 && !ipv6)
+ ipv4 = ipv6 = 1;
+
switch (cmd) {
case cmd_standalone_mode:
- rc = do_standalone_mode(daemonize);
+ rc = do_standalone_mode(daemonize, ipv4, ipv6);
remove_pid_file();
break;
case cmd_version:
diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c
index d7974cb2cc6f..e810ad53e2ac 100644
--- a/drivers/staging/usbip/vhci_hcd.c
+++ b/drivers/staging/usbip/vhci_hcd.c
@@ -999,12 +999,6 @@ static int vhci_hcd_probe(struct platform_device *pdev)
usbip_dbg_vhci_hc("name %s id %d\n", pdev->name, pdev->id);
- /* will be removed */
- if (pdev->dev.dma_mask) {
- dev_info(&pdev->dev, "vhci_hcd DMA not supported\n");
- return -EINVAL;
- }
-
/*
* Allocate and initialize hcd.
* Our private data is also allocated automatically.
@@ -1146,11 +1140,11 @@ static int __init vhci_hcd_init(void)
return -ENODEV;
ret = platform_driver_register(&vhci_driver);
- if (ret < 0)
+ if (ret)
goto err_driver_register;
ret = platform_device_register(&the_pdev);
- if (ret < 0)
+ if (ret)
goto err_platform_device_register;
pr_info(DRIVER_DESC " v" USBIP_VERSION "\n");
diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c
index f983915168b7..a23b591eeac3 100644
--- a/drivers/staging/vt6655/bssdb.c
+++ b/drivers/staging/vt6655/bssdb.c
@@ -148,7 +148,8 @@ BSSpSearchBSSList(
if (pDevice->bLinkPass == false) pCurrBSS->bSelected = false;
if ((pCurrBSS->bActive) &&
(pCurrBSS->bSelected == false)) {
- if (!compare_ether_addr(pCurrBSS->abyBSSID, pbyBSSID)) {
+ if (ether_addr_equal(pCurrBSS->abyBSSID,
+ pbyBSSID)) {
if (pSSID != NULL) {
// compare ssid
if (!memcmp(pSSID->abySSID,
@@ -275,7 +276,8 @@ BSSvClearBSSList(
for (ii = 0; ii < MAX_BSS_NUM; ii++) {
if (bKeepCurrBSSID) {
if (pMgmt->sBSSList[ii].bActive &&
- !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pMgmt->abyCurrBSSID)) {
+ ether_addr_equal(pMgmt->sBSSList[ii].abyBSSID,
+ pMgmt->abyCurrBSSID)) {
// bKeepCurrBSSID = false;
continue;
}
@@ -318,7 +320,7 @@ BSSpAddrIsInBSSList(
for (ii = 0; ii < MAX_BSS_NUM; ii++) {
pBSSList = &(pMgmt->sBSSList[ii]);
if (pBSSList->bActive) {
- if (!compare_ether_addr(pBSSList->abyBSSID, abyBSSID)) {
+ if (ether_addr_equal(pBSSList->abyBSSID, abyBSSID)) {
if (pSSID->len == ((PWLAN_IE_SSID)pBSSList->abySSID)->len) {
if (memcmp(pSSID->abySSID,
((PWLAN_IE_SSID)pBSSList->abySSID)->abySSID,
@@ -733,7 +735,8 @@ BSSDBbIsSTAInNodeDB(void *pMgmtObject, unsigned char *abyDstAddr,
// Index = 0 reserved for AP Node
for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) {
if (pMgmt->sNodeDBTable[ii].bActive) {
- if (!compare_ether_addr(abyDstAddr, pMgmt->sNodeDBTable[ii].abyMACAddr)) {
+ if (ether_addr_equal(abyDstAddr,
+ pMgmt->sNodeDBTable[ii].abyMACAddr)) {
*puNodeIndex = ii;
return true;
}
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index 7f36a7103c3e..e93fdc88d844 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -1153,10 +1153,6 @@ static void device_free_info(PSDevice pDevice) {
pci_release_regions(pDevice->pcid);
if (dev)
free_netdev(dev);
-
- if (pDevice->pcid) {
- pci_set_drvdata(pDevice->pcid, NULL);
- }
}
static bool device_init_rings(PSDevice pDevice) {
diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c
index a9533f3f2529..0ff51cb4a207 100644
--- a/drivers/staging/vt6655/dpc.c
+++ b/drivers/staging/vt6655/dpc.c
@@ -172,9 +172,9 @@ s_vProcessRxMACHeader(PSDevice pDevice, unsigned char *pbyRxBufferAddr,
};
pbyRxBuffer = (unsigned char *)(pbyRxBufferAddr + cbHeaderSize);
- if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_Bridgetunnel[0])) {
+ if (ether_addr_equal(pbyRxBuffer, pDevice->abySNAP_Bridgetunnel)) {
cbHeaderSize += 6;
- } else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) {
+ } else if (ether_addr_equal(pbyRxBuffer, pDevice->abySNAP_RFC1042)) {
cbHeaderSize += 6;
pwType = (unsigned short *)(pbyRxBufferAddr + cbHeaderSize);
if ((*pwType != TYPE_PKT_IPX) && (*pwType != cpu_to_le16(0xF380))) {
@@ -420,7 +420,8 @@ device_receive_frame(
s_vGetDASA(skb->data+4, &cbHeaderSize, &pDevice->sRxEthHeader);
// filter packet send from myself
- if (!compare_ether_addr((unsigned char *)&(pDevice->sRxEthHeader.abySrcAddr[0]), pDevice->abyCurrentNetAddr))
+ if (ether_addr_equal(pDevice->sRxEthHeader.abySrcAddr,
+ pDevice->abyCurrentNetAddr))
return false;
if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) {
diff --git a/drivers/staging/vt6655/iwctl.c b/drivers/staging/vt6655/iwctl.c
index 9de698ef25f5..4bff8aa96be7 100644
--- a/drivers/staging/vt6655/iwctl.c
+++ b/drivers/staging/vt6655/iwctl.c
@@ -663,7 +663,8 @@ int iwctl_siwap(struct net_device *dev,
unsigned int ii, uSameBssidNum = 0;
for (ii = 0; ii < MAX_BSS_NUM; ii++) {
if (pMgmt->sBSSList[ii].bActive &&
- !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pMgmt->abyDesireBSSID)) {
+ ether_addr_equal(pMgmt->sBSSList[ii].abyBSSID,
+ pMgmt->abyDesireBSSID)) {
uSameBssidNum++;
}
}
@@ -840,7 +841,8 @@ int iwctl_siwessid(struct net_device *dev,
// by means of judging if there are two same BSSID exist in list ?
for (ii = 0; ii < MAX_BSS_NUM; ii++) {
if (pMgmt->sBSSList[ii].bActive &&
- !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pCurr->abyBSSID)) {
+ ether_addr_equal(pMgmt->sBSSList[ii].abyBSSID,
+ pCurr->abyBSSID)) {
uSameBssidNum++;
}
}
diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c
index 92b84b5ea115..04c1304d16e5 100644
--- a/drivers/staging/vt6655/key.c
+++ b/drivers/staging/vt6655/key.c
@@ -141,7 +141,7 @@ bool KeybGetKey(
*pKey = NULL;
for (i = 0; i < MAX_KEY_TABLE; i++) {
if ((pTable->KeyTable[i].bInUse == true) &&
- !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+ ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
if (dwKeyIndex == 0xFFFFFFFF) {
if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) {
*pKey = &(pTable->KeyTable[i].PairwiseKey);
@@ -208,7 +208,7 @@ bool KeybSetKey(
j = i;
}
if ((pTable->KeyTable[i].bInUse == true) &&
- !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+ ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
// found table already exist
if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
// Pairwise key
@@ -385,7 +385,7 @@ bool KeybRemoveKey(
for (i = 0; i < MAX_KEY_TABLE; i++) {
if ((pTable->KeyTable[i].bInUse == true) &&
- !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+ ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
s_vCheckKeyTableValid(pTable, dwIoBase);
@@ -429,7 +429,7 @@ bool KeybRemoveAllKey(
for (i = 0; i < MAX_KEY_TABLE; i++) {
if ((pTable->KeyTable[i].bInUse == true) &&
- !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+ ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
for (u = 0; u < MAX_GROUP_KEY; u++) {
pTable->KeyTable[i].GroupKey[u].bKeyValid = false;
@@ -512,7 +512,7 @@ bool KeybGetTransmitKey(
*pKey = NULL;
for (i = 0; i < MAX_KEY_TABLE; i++) {
if ((pTable->KeyTable[i].bInUse == true) &&
- !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+ ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
if (dwKeyType == PAIRWISE_KEY) {
if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) {
*pKey = &(pTable->KeyTable[i].PairwiseKey);
diff --git a/drivers/staging/vt6655/vntwifi.c b/drivers/staging/vt6655/vntwifi.c
index d8f4f8e7d05e..d2bdb71fe62d 100644
--- a/drivers/staging/vt6655/vntwifi.c
+++ b/drivers/staging/vt6655/vntwifi.c
@@ -752,25 +752,3 @@ VNTWIFIbChannelSwitch(
//spin_unlock_irq(&pDevice->lock);
return true;
}
-
-/*
- bool
- VNTWIFIbRadarPresent(
- void *pMgmtObject,
- unsigned char byChannel
-) {
- PSMgmtObject pMgmt = (PSMgmtObject) pMgmtObject;
- if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) &&
- (byChannel == (unsigned char) pMgmt->uCurrChannel) &&
- (pMgmt->bSwitchChannel != true) &&
- (pMgmt->b11hEnable == true)) {
- if (!compare_ether_addr(pMgmt->abyIBSSDFSOwner, CARDpGetCurrentAddress(pMgmt->pAdapter))) {
- pMgmt->byNewChannel = CARDbyAutoChannelSelect(pMgmt->pAdapter,(unsigned char) pMgmt->uCurrChannel);
- pMgmt->bSwitchChannel = true;
- }
- BEACONbSendBeacon(pMgmt);
- CARDbChannelSwitch(pMgmt->pAdapter, 0, pMgmt->byNewChannel, 10);
- }
- return true;
- }
-*/
diff --git a/drivers/staging/vt6655/wcmd.c b/drivers/staging/vt6655/wcmd.c
index d551653537b4..9c57eefe78fb 100644
--- a/drivers/staging/vt6655/wcmd.c
+++ b/drivers/staging/vt6655/wcmd.c
@@ -233,7 +233,7 @@ s_vProbeChannel(
*
*
* Return Value:
- * A ptr to Tx frame or NULL on allocation failue
+ * A ptr to Tx frame or NULL on allocation failure
*
-*/
diff --git a/drivers/staging/vt6655/wctl.c b/drivers/staging/vt6655/wctl.c
index 9eb81b4eee80..f05f9f55398b 100644
--- a/drivers/staging/vt6655/wctl.c
+++ b/drivers/staging/vt6655/wctl.c
@@ -75,8 +75,8 @@ bool WCTLbIsDuplicate(PSCache pCache, PS802_11Header pMACHeader)
for (ii = 0; ii < DUPLICATE_RX_CACHE_LENGTH; ii++) {
pCacheEntry = &(pCache->asCacheEntry[uIndex]);
if ((pCacheEntry->wFmSequence == pMACHeader->wSeqCtl) &&
- (!compare_ether_addr(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0])))
-) {
+ ether_addr_equal(pCacheEntry->abyAddr2,
+ pMACHeader->abyAddr2)) {
/* Duplicate match */
return true;
}
@@ -111,8 +111,8 @@ unsigned int WCTLuSearchDFCB(PSDevice pDevice, PS802_11Header pMACHeader)
for (ii = 0; ii < pDevice->cbDFCB; ii++) {
if ((pDevice->sRxDFCB[ii].bInUse == true) &&
- (!compare_ether_addr(&(pDevice->sRxDFCB[ii].abyAddr2[0]), &(pMACHeader->abyAddr2[0])))
-) {
+ ether_addr_equal(pDevice->sRxDFCB[ii].abyAddr2,
+ pMACHeader->abyAddr2)) {
//
return ii;
}
diff --git a/drivers/staging/vt6655/wmgr.c b/drivers/staging/vt6655/wmgr.c
index 9938813f997a..ed4b32b6d9ce 100644
--- a/drivers/staging/vt6655/wmgr.c
+++ b/drivers/staging/vt6655/wmgr.c
@@ -1680,7 +1680,8 @@ s_vMgrRxDeauthentication(
vMgrDecodeDeauthen(&sFrame);
DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "AP deauthed me, reason=%d.\n", cpu_to_le16((*(sFrame.pwReason))));
// TODO: update BSS list for specific BSSID if pre-authentication case
- if (!compare_ether_addr(sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID)) {
+ if (ether_addr_equal(sFrame.pHdr->sA3.abyAddr3,
+ pMgmt->abyCurrBSSID)) {
if (pMgmt->eCurrState >= WMAC_STATE_AUTHPENDING) {
pMgmt->sNodeDBTable[0].bActive = false;
pMgmt->eCurrMode = WMAC_MODE_STANDBY;
diff --git a/drivers/staging/vt6655/wpactl.c b/drivers/staging/vt6655/wpactl.c
index e8d9ecd2913a..044368a46c53 100644
--- a/drivers/staging/vt6655/wpactl.c
+++ b/drivers/staging/vt6655/wpactl.c
@@ -394,7 +394,7 @@ int wpa_set_keys(PSDevice pDevice, void *ctx, bool fcpfkernel)
} else {
// Key Table Full
- if (!compare_ether_addr(&param->addr[0], pDevice->abyBSSID)) {
+ if (ether_addr_equal(param->addr, pDevice->abyBSSID)) {
//DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n"));
//spin_unlock_irq(&pDevice->lock);
return -EINVAL;
diff --git a/drivers/staging/vt6656/bssdb.c b/drivers/staging/vt6656/bssdb.c
index ee79bbdf1a06..ed1d609cc25f 100644
--- a/drivers/staging/vt6656/bssdb.c
+++ b/drivers/staging/vt6656/bssdb.c
@@ -126,7 +126,7 @@ PKnownBSS BSSpSearchBSSList(struct vnt_private *pDevice,
if ((pCurrBSS->bActive) &&
(pCurrBSS->bSelected == false)) {
- if (!compare_ether_addr(pCurrBSS->abyBSSID, pbyBSSID)) {
+ if (ether_addr_equal(pCurrBSS->abyBSSID, pbyBSSID)) {
if (pSSID != NULL) {
// compare ssid
if ( !memcmp(pSSID->abySSID,
@@ -242,8 +242,8 @@ void BSSvClearBSSList(struct vnt_private *pDevice, int bKeepCurrBSSID)
for (ii = 0; ii < MAX_BSS_NUM; ii++) {
if (bKeepCurrBSSID) {
if (pMgmt->sBSSList[ii].bActive &&
- !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID,
- pMgmt->abyCurrBSSID)) {
+ ether_addr_equal(pMgmt->sBSSList[ii].abyBSSID,
+ pMgmt->abyCurrBSSID)) {
//mike mark: there are two BSSID's in list. If that AP is in hidden ssid mode, one SSID is null,
// but other's might not be obvious, so if it associate's with your STA,
// you must keep the two of them!!
@@ -277,7 +277,7 @@ PKnownBSS BSSpAddrIsInBSSList(struct vnt_private *pDevice,
for (ii = 0; ii < MAX_BSS_NUM; ii++) {
pBSSList = &(pMgmt->sBSSList[ii]);
if (pBSSList->bActive) {
- if (!compare_ether_addr(pBSSList->abyBSSID, abyBSSID)) {
+ if (ether_addr_equal(pBSSList->abyBSSID, abyBSSID)) {
if (pSSID->len == ((PWLAN_IE_SSID)pBSSList->abySSID)->len){
if (memcmp(pSSID->abySSID,
((PWLAN_IE_SSID)pBSSList->abySSID)->abySSID,
@@ -623,8 +623,8 @@ int BSSbIsSTAInNodeDB(struct vnt_private *pDevice,
// Index = 0 reserved for AP Node
for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) {
if (pMgmt->sNodeDBTable[ii].bActive) {
- if (!compare_ether_addr(abyDstAddr,
- pMgmt->sNodeDBTable[ii].abyMACAddr)) {
+ if (ether_addr_equal(abyDstAddr,
+ pMgmt->sNodeDBTable[ii].abyMACAddr)) {
*puNodeIndex = ii;
return true;
}
diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c
index 5158ff4b346a..e430b35463b6 100644
--- a/drivers/staging/vt6656/channel.c
+++ b/drivers/staging/vt6656/channel.c
@@ -403,7 +403,7 @@ exit:
void CHvInitChannelTable(struct vnt_private *pDevice)
{
- int bMultiBand = false;
+ bool bMultiBand = false;
int ii;
for (ii = 1; ii <= CB_MAX_CHANNEL; ii++)
diff --git a/drivers/staging/vt6656/desc.h b/drivers/staging/vt6656/desc.h
index 4675135aa258..afe7074c3037 100644
--- a/drivers/staging/vt6656/desc.h
+++ b/drivers/staging/vt6656/desc.h
@@ -146,15 +146,6 @@
/*
* TX FIFO header
*/
-typedef struct tagSTxBufHead {
- u32 adwTxKey[4];
- u16 wFIFOCtl;
- u16 wTimeStamp;
- u16 wFragCtl;
- u16 wReserved;
-} __attribute__ ((__packed__))
-STxBufHead, *PSTxBufHead;
-typedef const STxBufHead *PCSTxBufHead;
typedef struct tagSTxShortBufHead {
u16 wFIFOCtl;
diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c
index ea7d443b11d0..29381b466e20 100644
--- a/drivers/staging/vt6656/dpc.c
+++ b/drivers/staging/vt6656/dpc.c
@@ -136,9 +136,9 @@ static void s_vProcessRxMACHeader(struct vnt_private *pDevice,
};
pbyRxBuffer = (u8 *) (pbyRxBufferAddr + cbHeaderSize);
- if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_Bridgetunnel[0])) {
+ if (ether_addr_equal(pbyRxBuffer, pDevice->abySNAP_Bridgetunnel)) {
cbHeaderSize += 6;
- } else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) {
+ } else if (ether_addr_equal(pbyRxBuffer, pDevice->abySNAP_RFC1042)) {
cbHeaderSize += 6;
pwType = (u16 *) (pbyRxBufferAddr + cbHeaderSize);
if ((*pwType == cpu_to_be16(ETH_P_IPX)) ||
@@ -361,7 +361,7 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, struct vnt_rcb *pRCB,
if ((pMgmt->eCurrMode == WMAC_MODE_STANDBY) ||
(pMgmt->eCurrMode == WMAC_MODE_ESS_STA)) {
if (pMgmt->sNodeDBTable[0].bActive) {
- if (!compare_ether_addr(pMgmt->abyCurrBSSID, pMACHeader->addr2)) {
+ if (ether_addr_equal(pMgmt->abyCurrBSSID, pMACHeader->addr2)) {
if (pMgmt->sNodeDBTable[0].uInActiveCount != 0)
pMgmt->sNodeDBTable[0].uInActiveCount = 0;
}
@@ -374,8 +374,7 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, struct vnt_rcb *pRCB,
return false;
}
- if (compare_ether_addr(pDevice->abyCurrentNetAddr,
- pMACHeader->addr1)) {
+ if (!ether_addr_equal(pDevice->abyCurrentNetAddr, pMACHeader->addr1)) {
return false;
}
}
@@ -383,8 +382,8 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, struct vnt_rcb *pRCB,
// Use for TKIP MIC
s_vGetDASA(pbyFrame, &cbHeaderSize, &pDevice->sRxEthHeader);
- if (!compare_ether_addr((u8 *)&(pDevice->sRxEthHeader.h_source[0]),
- pDevice->abyCurrentNetAddr))
+ if (ether_addr_equal((u8 *)pDevice->sRxEthHeader.h_source,
+ pDevice->abyCurrentNetAddr))
return false;
if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) {
diff --git a/drivers/staging/vt6656/hostap.c b/drivers/staging/vt6656/hostap.c
index c699a3058b39..7d96fe7a3e41 100644
--- a/drivers/staging/vt6656/hostap.c
+++ b/drivers/staging/vt6656/hostap.c
@@ -414,7 +414,7 @@ static int hostap_set_encryption(struct vnt_private *pDevice,
int ret = 0;
s32 iNodeIndex = -1;
int ii;
- int bKeyTableFull = false;
+ bool bKeyTableFull = false;
u16 wKeyCtl = 0;
param->u.crypt.err = 0;
diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c
index d0cf7d8a20e5..59688881a9a0 100644
--- a/drivers/staging/vt6656/iwctl.c
+++ b/drivers/staging/vt6656/iwctl.c
@@ -657,8 +657,8 @@ int iwctl_siwap(struct net_device *dev, struct iw_request_info *info,
unsigned uSameBssidNum = 0;
for (ii = 0; ii < MAX_BSS_NUM; ii++) {
if (pMgmt->sBSSList[ii].bActive &&
- !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID,
- pMgmt->abyDesireBSSID)) {
+ ether_addr_equal(pMgmt->sBSSList[ii].abyBSSID,
+ pMgmt->abyDesireBSSID)) {
uSameBssidNum++;
}
}
@@ -840,8 +840,8 @@ int iwctl_siwessid(struct net_device *dev, struct iw_request_info *info,
// are two same BSSID exist in list ?
for (ii = 0; ii < MAX_BSS_NUM; ii++) {
if (pMgmt->sBSSList[ii].bActive &&
- !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID,
- pCurr->abyBSSID)) {
+ ether_addr_equal(pMgmt->sBSSList[ii].abyBSSID,
+ pCurr->abyBSSID)) {
uSameBssidNum++;
}
}
@@ -1634,6 +1634,9 @@ int iwctl_siwencodeext(struct net_device *dev, struct iw_request_info *info,
if (pMgmt == NULL)
return -EFAULT;
+ if (!(pDevice->flags & DEVICE_FLAGS_OPENED))
+ return -ENODEV;
+
buf = kzalloc(sizeof(struct viawget_wpa_param), GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c
index 205590b0e9c8..be92c048a12e 100644
--- a/drivers/staging/vt6656/key.c
+++ b/drivers/staging/vt6656/key.c
@@ -151,7 +151,7 @@ int KeybGetKey(PSKeyManagement pTable, u8 *pbyBSSID, u32 dwKeyIndex,
*pKey = NULL;
for (i=0;i<MAX_KEY_TABLE;i++) {
if ((pTable->KeyTable[i].bInUse == true) &&
- !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+ ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
if (dwKeyIndex == 0xFFFFFFFF) {
if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) {
*pKey = &(pTable->KeyTable[i].PairwiseKey);
@@ -213,7 +213,7 @@ int KeybSetKey(struct vnt_private *pDevice, PSKeyManagement pTable,
j = i;
}
if ((pTable->KeyTable[i].bInUse == true) &&
- !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+ ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
// found table already exist
if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
// Pairwise key
@@ -395,7 +395,7 @@ int KeybRemoveKey(struct vnt_private *pDevice, PSKeyManagement pTable,
} else {
for (i=0;i<MAX_KEY_TABLE;i++) {
if ( (pTable->KeyTable[i].bInUse == true) &&
- !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+ ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
@@ -445,7 +445,7 @@ int KeybRemoveAllKey(struct vnt_private *pDevice, PSKeyManagement pTable,
for (i=0;i<MAX_KEY_TABLE;i++) {
if ((pTable->KeyTable[i].bInUse == true) &&
- !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+ ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
for (u = 0; u < MAX_GROUP_KEY; u++)
pTable->KeyTable[i].GroupKey[u].bKeyValid = false;
@@ -480,7 +480,7 @@ int KeybGetTransmitKey(PSKeyManagement pTable, u8 *pbyBSSID, u32 dwKeyType,
for (i = 0; i < MAX_KEY_TABLE; i++) {
if ((pTable->KeyTable[i].bInUse == true) &&
- !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+ ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
if (dwKeyType == PAIRWISE_KEY) {
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index 536971786ae8..6f9d28182445 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -1098,6 +1098,8 @@ static int device_close(struct net_device *dev)
memset(pMgmt->abyCurrBSSID, 0, 6);
pMgmt->eCurrState = WMAC_STATE_IDLE;
+ pDevice->flags &= ~DEVICE_FLAGS_OPENED;
+
device_free_tx_bufs(pDevice);
device_free_rx_bufs(pDevice);
device_free_int_bufs(pDevice);
@@ -1109,7 +1111,6 @@ static int device_close(struct net_device *dev)
usb_free_urb(pDevice->pInterruptURB);
BSSvClearNodeDBTable(pDevice, 0);
- pDevice->flags &=(~DEVICE_FLAGS_OPENED);
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_close2 \n");
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index fb743a8811bb..6b12d0cc6ef2 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -99,9 +99,9 @@ static void s_vSaveTxPktInfo(struct vnt_private *pDevice, u8 byPktNum,
static void *s_vGetFreeContext(struct vnt_private *pDevice);
static void s_vGenerateTxParameter(struct vnt_private *pDevice,
- u8 byPktType, u16 wCurrentRate, void *pTxBufHead, void *pvRrvTime,
- void *rts_cts, u32 cbFrameSize, int bNeedACK, u32 uDMAIdx,
- struct ethhdr *psEthHeader, bool need_rts);
+ u8 byPktType, u16 wCurrentRate, struct vnt_tx_buffer *tx_buffer,
+ struct vnt_mic_hdr **mic_hdr, u32 need_mic, u32 cbFrameSize,
+ int bNeedACK, u32 uDMAIdx, struct ethhdr *psEthHeader, bool need_rts);
static u32 s_uFillDataHead(struct vnt_private *pDevice,
u8 byPktType, u16 wCurrentRate, void *pTxDataHead, u32 cbFrameLength,
@@ -148,6 +148,8 @@ static void *s_vGetFreeContext(struct vnt_private *pDevice)
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"GetFreeContext()\n");
for (ii = 0; ii < pDevice->cbTD; ii++) {
+ if (!pDevice->apTD[ii])
+ return NULL;
pContext = pDevice->apTD[ii];
if (pContext->bBoolInUse == false) {
pContext->bBoolInUse = true;
@@ -840,17 +842,17 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
-*/
static void s_vGenerateTxParameter(struct vnt_private *pDevice,
- u8 byPktType, u16 wCurrentRate, void *pTxBufHead, void *pvRrvTime,
- void *rts_cts, u32 cbFrameSize, int bNeedACK, u32 uDMAIdx,
- struct ethhdr *psEthHeader, bool need_rts)
+ u8 byPktType, u16 wCurrentRate, struct vnt_tx_buffer *tx_buffer,
+ struct vnt_mic_hdr **mic_hdr, u32 need_mic, u32 cbFrameSize,
+ int bNeedACK, u32 uDMAIdx, struct ethhdr *psEthHeader, bool need_rts)
{
- union vnt_tx_data_head *head = rts_cts;
+ struct vnt_tx_fifo_head *pFifoHead = &tx_buffer->fifo_head;
+ union vnt_tx_data_head *head = NULL;
u32 cbMACHdLen = WLAN_HDR_ADDR3_LEN; /* 24 */
u16 wFifoCtl;
u8 byFBOption = AUTO_FB_NONE;
//DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter...\n");
- PSTxBufHead pFifoHead = (PSTxBufHead)pTxBufHead;
pFifoHead->wReserved = wCurrentRate;
wFifoCtl = pFifoHead->wFIFOCtl;
@@ -861,7 +863,7 @@ static void s_vGenerateTxParameter(struct vnt_private *pDevice,
byFBOption = AUTO_FB_1;
}
- if (!pvRrvTime)
+ if (!pFifoHead)
return;
if (pDevice->bLongHeader)
@@ -870,8 +872,8 @@ static void s_vGenerateTxParameter(struct vnt_private *pDevice,
if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
if (need_rts) {
//Fill RsvTime
- struct vnt_rrv_time_rts *pBuf =
- (struct vnt_rrv_time_rts *)pvRrvTime;
+ struct vnt_rrv_time_rts *pBuf = &tx_buffer->tx_head.tx_rts.rts;
+
pBuf->wRTSTxRrvTime_aa = s_uGetRTSCTSRsvTime(pDevice, 2,
byPktType, cbFrameSize, wCurrentRate);
pBuf->wRTSTxRrvTime_ba = s_uGetRTSCTSRsvTime(pDevice, 1,
@@ -883,14 +885,22 @@ static void s_vGenerateTxParameter(struct vnt_private *pDevice,
pBuf->wTxRrvTime_b = vnt_rxtx_rsvtime_le16(pDevice,
PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate,
bNeedACK);
+
+ if (need_mic) {
+ *mic_hdr = &tx_buffer->tx_head.tx_rts.tx.mic.hdr;
+ head = &tx_buffer->tx_head.tx_rts.tx.mic.head;
+ } else {
+ head = &tx_buffer->tx_head.tx_rts.tx.head;
+ }
+
/* Fill RTS */
s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
bNeedACK, psEthHeader, wCurrentRate, byFBOption);
}
else {//RTS_needless, PCF mode
//Fill RsvTime
- struct vnt_rrv_time_cts *pBuf =
- (struct vnt_rrv_time_cts *)pvRrvTime;
+ struct vnt_rrv_time_cts *pBuf = &tx_buffer->tx_head.tx_cts.cts;
+
pBuf->wTxRrvTime_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType,
cbFrameSize, wCurrentRate, bNeedACK);
pBuf->wTxRrvTime_b = vnt_rxtx_rsvtime_le16(pDevice,
@@ -898,6 +908,14 @@ static void s_vGenerateTxParameter(struct vnt_private *pDevice,
pDevice->byTopCCKBasicRate, bNeedACK);
pBuf->wCTSTxRrvTime_ba = s_uGetRTSCTSRsvTime(pDevice, 3,
byPktType, cbFrameSize, wCurrentRate);
+
+ if (need_mic) {
+ *mic_hdr = &tx_buffer->tx_head.tx_cts.tx.mic.hdr;
+ head = &tx_buffer->tx_head.tx_cts.tx.mic.head;
+ } else {
+ head = &tx_buffer->tx_head.tx_cts.tx.head;
+ }
+
/* Fill CTS */
s_vFillCTSHead(pDevice, uDMAIdx, byPktType, head,
cbFrameSize, bNeedACK, wCurrentRate, byFBOption);
@@ -906,19 +924,30 @@ static void s_vGenerateTxParameter(struct vnt_private *pDevice,
else if (byPktType == PK_TYPE_11A) {
if (need_rts) {
//Fill RsvTime
- struct vnt_rrv_time_ab *pBuf =
- (struct vnt_rrv_time_ab *)pvRrvTime;
+ struct vnt_rrv_time_ab *pBuf = &tx_buffer->tx_head.tx_ab.ab;
+
pBuf->wRTSTxRrvTime = s_uGetRTSCTSRsvTime(pDevice, 2,
byPktType, cbFrameSize, wCurrentRate);
pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, byPktType,
cbFrameSize, wCurrentRate, bNeedACK);
+
+ if (need_mic) {
+ *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
+ head = &tx_buffer->tx_head.tx_ab.tx.mic.head;
+ } else {
+ head = &tx_buffer->tx_head.tx_ab.tx.head;
+ }
+
/* Fill RTS */
s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
bNeedACK, psEthHeader, wCurrentRate, byFBOption);
} else {
//Fill RsvTime
- struct vnt_rrv_time_ab *pBuf =
- (struct vnt_rrv_time_ab *)pvRrvTime;
+ struct vnt_rrv_time_ab *pBuf = &tx_buffer->tx_head.tx_ab.ab;
+
+ if (need_mic)
+ *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
+
pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11A,
cbFrameSize, wCurrentRate, bNeedACK);
}
@@ -926,20 +955,31 @@ static void s_vGenerateTxParameter(struct vnt_private *pDevice,
else if (byPktType == PK_TYPE_11B) {
if (need_rts) {
//Fill RsvTime
- struct vnt_rrv_time_ab *pBuf =
- (struct vnt_rrv_time_ab *)pvRrvTime;
+ struct vnt_rrv_time_ab *pBuf = &tx_buffer->tx_head.tx_ab.ab;
+
pBuf->wRTSTxRrvTime = s_uGetRTSCTSRsvTime(pDevice, 0,
byPktType, cbFrameSize, wCurrentRate);
pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B,
cbFrameSize, wCurrentRate, bNeedACK);
+
+ if (need_mic) {
+ *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
+ head = &tx_buffer->tx_head.tx_ab.tx.mic.head;
+ } else {
+ head = &tx_buffer->tx_head.tx_ab.tx.head;
+ }
+
/* Fill RTS */
s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
bNeedACK, psEthHeader, wCurrentRate, byFBOption);
}
else { //RTS_needless, non PCF mode
//Fill RsvTime
- struct vnt_rrv_time_ab *pBuf =
- (struct vnt_rrv_time_ab *)pvRrvTime;
+ struct vnt_rrv_time_ab *pBuf = &tx_buffer->tx_head.tx_ab.ab;
+
+ if (need_mic)
+ *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
+
pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B,
cbFrameSize, wCurrentRate, bNeedACK);
}
@@ -953,11 +993,12 @@ static void s_vGenerateTxParameter(struct vnt_private *pDevice,
*/
static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
- struct vnt_tx_buffer *pTxBufHead, int bNeedEncryption,
+ struct vnt_tx_buffer *tx_buffer, int bNeedEncryption,
u32 uSkbPacketLen, u32 uDMAIdx, struct ethhdr *psEthHeader,
u8 *pPacket, PSKeyItem pTransmitKey, u32 uNodeIndex, u16 wCurrentRate,
u32 *pcbHeaderLen, u32 *pcbTotalLen)
{
+ struct vnt_tx_fifo_head *pTxBufHead = &tx_buffer->fifo_head;
struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
u32 cbFrameSize, cbFrameBodySize;
u32 cb802_1_H_len;
@@ -971,9 +1012,7 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
= {0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8};
u32 uDuration;
u32 cbHeaderLength = 0, uPadding = 0;
- void *pvRrvTime;
struct vnt_mic_hdr *pMICHDR;
- void *rts_cts = NULL;
void *pvTxDataHd;
u8 byFBOption = AUTO_FB_NONE, byFragType;
u16 wTxBufSize;
@@ -981,7 +1020,7 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
u32 *pdwMIC_L, *pdwMIC_R;
int bSoftWEP = false;
- pvRrvTime = pMICHDR = pvTxDataHd = NULL;
+ pMICHDR = pvTxDataHd = NULL;
if (bNeedEncryption && pTransmitKey->pvKeyTable) {
if (((PSKeyTable)pTransmitKey->pvKeyTable)->bSoftWEP == true)
@@ -1103,16 +1142,11 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
}
pbyTxBufferAddr = (u8 *) &(pTxBufHead->adwTxKey[0]);
- wTxBufSize = sizeof(STxBufHead);
+ wTxBufSize = sizeof(struct vnt_tx_fifo_head);
+
if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
if (byFBOption == AUTO_FB_NONE) {
if (bRTS == true) {//RTS_need
- pvRrvTime = (struct vnt_rrv_time_rts *)
- (pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_rts));
- rts_cts = (struct vnt_rts_g *) (pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_rts) + cbMICHDR);
pvTxDataHd = (struct vnt_tx_datahead_g *) (pbyTxBufferAddr +
wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
cbMICHDR + sizeof(struct vnt_rts_g));
@@ -1121,12 +1155,6 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
sizeof(struct vnt_tx_datahead_g);
}
else { //RTS_needless
- pvRrvTime = (struct vnt_rrv_time_cts *)
- (pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_cts));
- rts_cts = (struct vnt_cts *) (pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_cts) + cbMICHDR);
pvTxDataHd = (struct vnt_tx_datahead_g *)(pbyTxBufferAddr +
wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
cbMICHDR + sizeof(struct vnt_cts));
@@ -1137,12 +1165,6 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
} else {
// Auto Fall Back
if (bRTS == true) {//RTS_need
- pvRrvTime = (struct vnt_rrv_time_rts *)(pbyTxBufferAddr +
- wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_rts));
- rts_cts = (struct vnt_rts_g_fb *)(pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_rts) + cbMICHDR);
pvTxDataHd = (struct vnt_tx_datahead_g_fb *) (pbyTxBufferAddr +
wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
cbMICHDR + sizeof(struct vnt_rts_g_fb));
@@ -1151,12 +1173,6 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
sizeof(struct vnt_tx_datahead_g_fb);
}
else if (bRTS == false) { //RTS_needless
- pvRrvTime = (struct vnt_rrv_time_cts *)
- (pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_cts));
- rts_cts = (struct vnt_cts_fb *) (pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_cts) + cbMICHDR);
pvTxDataHd = (struct vnt_tx_datahead_g_fb *) (pbyTxBufferAddr +
wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
cbMICHDR + sizeof(struct vnt_cts_fb));
@@ -1169,12 +1185,6 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
else {//802.11a/b packet
if (byFBOption == AUTO_FB_NONE) {
if (bRTS == true) {//RTS_need
- pvRrvTime = (struct vnt_rrv_time_ab *) (pbyTxBufferAddr +
- wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_ab));
- rts_cts = (struct vnt_rts_ab *) (pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
pvTxDataHd = (struct vnt_tx_datahead_ab *)(pbyTxBufferAddr +
wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR +
sizeof(struct vnt_rts_ab));
@@ -1183,10 +1193,6 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
sizeof(struct vnt_tx_datahead_ab);
}
else if (bRTS == false) { //RTS_needless, no MICHDR
- pvRrvTime = (struct vnt_rrv_time_ab *)(pbyTxBufferAddr +
- wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_ab));
pvTxDataHd = (struct vnt_tx_datahead_ab *)(pbyTxBufferAddr +
wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
@@ -1195,12 +1201,6 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
} else {
// Auto Fall Back
if (bRTS == true) {//RTS_need
- pvRrvTime = (struct vnt_rrv_time_ab *)(pbyTxBufferAddr +
- wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_ab));
- rts_cts = (struct vnt_rts_a_fb *)(pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
pvTxDataHd = (struct vnt_tx_datahead_a_fb *)(pbyTxBufferAddr +
wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR +
sizeof(struct vnt_rts_a_fb));
@@ -1209,10 +1209,6 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
sizeof(struct vnt_tx_datahead_a_fb);
}
else if (bRTS == false) { //RTS_needless
- pvRrvTime = (struct vnt_rrv_time_ab *)(pbyTxBufferAddr +
- wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_ab));
pvTxDataHd = (struct vnt_tx_datahead_a_fb *)(pbyTxBufferAddr +
wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
@@ -1235,7 +1231,7 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
//Fill FIFO,RrvTime,RTS,and CTS
s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
- (void *)pbyTxBufferAddr, pvRrvTime, rts_cts,
+ tx_buffer, &pMICHDR, cbMICHDR,
cbFrameSize, bNeedACK, uDMAIdx, psEthHeader, bRTS);
//Fill DataHead
uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK,
@@ -1467,13 +1463,13 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
{
struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
struct vnt_tx_buffer *pTX_Buffer;
- PSTxBufHead pTxBufHead;
struct vnt_usb_send_context *pContext;
+ struct vnt_tx_fifo_head *pTxBufHead;
struct ieee80211_hdr *pMACHeader;
struct ethhdr sEthHeader;
u8 byPktType, *pbyTxBufferAddr;
- void *rts_cts = NULL;
- void *pvTxDataHd, *pvRrvTime, *pMICHDR;
+ void *pvTxDataHd;
+ struct vnt_mic_hdr *pMICHDR = NULL;
u32 uDuration, cbReqCount, cbHeaderSize, cbFrameBodySize, cbFrameSize;
int bNeedACK, bIsPSPOLL = false;
u32 cbIVlen = 0, cbICVlen = 0, cbMIClen = 0, cbFCSlen = 4;
@@ -1490,10 +1486,10 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
}
pTX_Buffer = (struct vnt_tx_buffer *)&pContext->Data[0];
- pbyTxBufferAddr = (u8 *)&(pTX_Buffer->adwTxKey[0]);
cbFrameBodySize = pPacket->cbPayloadLen;
- pTxBufHead = (PSTxBufHead) pbyTxBufferAddr;
- wTxBufSize = sizeof(STxBufHead);
+ pTxBufHead = &pTX_Buffer->fifo_head;
+ pbyTxBufferAddr = (u8 *)&pTxBufHead->adwTxKey[0];
+ wTxBufSize = sizeof(struct vnt_tx_fifo_head);
if (pDevice->byBBType == BB_TYPE_11A) {
wCurrentRate = RATE_6M;
@@ -1605,19 +1601,12 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
//Set RrvTime/RTS/CTS Buffer
if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
-
- pvRrvTime = (struct vnt_rrv_time_cts *) (pbyTxBufferAddr + wTxBufSize);
- pMICHDR = NULL;
- rts_cts = (struct vnt_cts *) (pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_cts));
pvTxDataHd = (struct vnt_tx_datahead_g *)(pbyTxBufferAddr + wTxBufSize +
sizeof(struct vnt_rrv_time_cts) + sizeof(struct vnt_cts));
cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
sizeof(struct vnt_cts) + sizeof(struct vnt_tx_datahead_g);
}
else { // 802.11a/b packet
- pvRrvTime = (struct vnt_rrv_time_ab *) (pbyTxBufferAddr + wTxBufSize);
- pMICHDR = NULL;
pvTxDataHd = (struct vnt_tx_datahead_ab *) (pbyTxBufferAddr +
wTxBufSize + sizeof(struct vnt_rrv_time_ab));
cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
@@ -1637,7 +1626,7 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
/* Fill FIFO,RrvTime,RTS,and CTS */
s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
- pbyTxBufferAddr, pvRrvTime, rts_cts,
+ pTX_Buffer, &pMICHDR, 0,
cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, false);
//Fill DataHead
@@ -1725,10 +1714,14 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice,
pContext->uBufLen = (u16)cbReqCount + 4; //USB header
if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) {
- s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr1[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl);
+ s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+ &pMACHeader->addr1[0], (u16)cbFrameSize,
+ pTxBufHead->wFIFOCtl);
}
else {
- s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr3[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl);
+ s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+ &pMACHeader->addr3[0], (u16)cbFrameSize,
+ pTxBufHead->wFIFOCtl);
}
PIPEnsSendBulkOut(pDevice,pContext);
@@ -1823,15 +1816,14 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
{
struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
struct vnt_tx_buffer *pTX_Buffer;
+ struct vnt_tx_fifo_head *pTxBufHead;
u8 byPktType;
u8 *pbyTxBufferAddr;
- void *rts_cts = NULL;
void *pvTxDataHd;
u32 uDuration, cbReqCount;
struct ieee80211_hdr *pMACHeader;
u32 cbHeaderSize, cbFrameBodySize;
int bNeedACK, bIsPSPOLL = false;
- PSTxBufHead pTxBufHead;
u32 cbFrameSize;
u32 cbIVlen = 0, cbICVlen = 0, cbMIClen = 0, cbFCSlen = 4;
u32 uPadding = 0;
@@ -1842,7 +1834,7 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
u16 wTxBufSize;
u32 cbMacHdLen;
struct ethhdr sEthHeader;
- void *pvRrvTime, *pMICHDR;
+ struct vnt_mic_hdr *pMICHDR;
u32 wCurrentRate = RATE_1M;
PUWLAN_80211HDR p80211Header;
u32 uNodeIndex = 0;
@@ -1853,7 +1845,7 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
u32 cbExtSuppRate = 0;
struct vnt_usb_send_context *pContext;
- pvRrvTime = pMICHDR = pvTxDataHd = NULL;
+ pMICHDR = pvTxDataHd = NULL;
if(skb->len <= WLAN_HDR_ADDR3_LEN) {
cbFrameBodySize = 0;
@@ -1872,9 +1864,9 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
}
pTX_Buffer = (struct vnt_tx_buffer *)&pContext->Data[0];
- pbyTxBufferAddr = (u8 *)(&pTX_Buffer->adwTxKey[0]);
- pTxBufHead = (PSTxBufHead) pbyTxBufferAddr;
- wTxBufSize = sizeof(STxBufHead);
+ pTxBufHead = &pTX_Buffer->fifo_head;
+ pbyTxBufferAddr = (u8 *)&pTxBufHead->adwTxKey[0];
+ wTxBufSize = sizeof(struct vnt_tx_fifo_head);
if (pDevice->byBBType == BB_TYPE_11A) {
wCurrentRate = RATE_6M;
@@ -2012,11 +2004,6 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
//the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter()
if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
- pvRrvTime = (struct vnt_rrv_time_cts *) (pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_cts));
- rts_cts = (struct vnt_cts *) (pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_cts) + cbMICHDR);
pvTxDataHd = (struct vnt_tx_datahead_g *) (pbyTxBufferAddr +
wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR +
sizeof(struct vnt_cts));
@@ -2025,10 +2012,6 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
}
else {//802.11a/b packet
-
- pvRrvTime = (struct vnt_rrv_time_ab *) (pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_ab));
pvTxDataHd = (struct vnt_tx_datahead_ab *)(pbyTxBufferAddr +
wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR +
@@ -2047,7 +2030,7 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
/* Fill FIFO,RrvTime,RTS,and CTS */
s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
- pbyTxBufferAddr, pvRrvTime, rts_cts,
+ pTX_Buffer, &pMICHDR, cbMICHDR,
cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, false);
//Fill DataHead
@@ -2181,10 +2164,14 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb)
pContext->uBufLen = (u16)cbReqCount + 4; //USB header
if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) {
- s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr1[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl);
+ s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+ &pMACHeader->addr1[0], (u16)cbFrameSize,
+ pTxBufHead->wFIFOCtl);
}
else {
- s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr3[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl);
+ s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+ &pMACHeader->addr3[0], (u16)cbFrameSize,
+ pTxBufHead->wFIFOCtl);
}
PIPEnsSendBulkOut(pDevice,pContext);
return ;
@@ -2566,7 +2553,10 @@ int nsDMA_tx_packet(struct vnt_private *pDevice,
pContext->Type = CONTEXT_DATA_PACKET;
pContext->uBufLen = (u16)BytesToWrite + 4 ; //USB header
- s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pContext->sEthHeader.h_dest[0]), (u16) (BytesToWrite-uHeaderLen), pTX_Buffer->wFIFOCtl);
+ s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+ &pContext->sEthHeader.h_dest[0],
+ (u16)(BytesToWrite-uHeaderLen),
+ pTX_Buffer->fifo_head.wFIFOCtl);
status = PIPEnsSendBulkOut(pDevice,pContext);
@@ -2717,7 +2707,10 @@ int bRelayPacketSend(struct vnt_private *pDevice, u8 *pbySkbData, u32 uDataLen,
pContext->Type = CONTEXT_DATA_PACKET;
pContext->uBufLen = (u16)BytesToWrite + 4 ; //USB header
- s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pContext->sEthHeader.h_dest[0]), (u16) (BytesToWrite-uHeaderLen), pTX_Buffer->wFIFOCtl);
+ s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+ &pContext->sEthHeader.h_dest[0],
+ (u16)(BytesToWrite - uHeaderLen),
+ pTX_Buffer->fifo_head.wFIFOCtl);
status = PIPEnsSendBulkOut(pDevice,pContext);
diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h
index 4bbee1c2fcac..bbda9a3a83c0 100644
--- a/drivers/staging/vt6656/rxtx.h
+++ b/drivers/staging/vt6656/rxtx.h
@@ -180,10 +180,32 @@ union vnt_tx_data_head {
struct vnt_cts_fb cts_g_fb;
};
-struct vnt_tx_buffer {
- u8 byType;
- u8 byPKTNO;
- u16 wTxByteCount;
+struct vnt_tx_mic_hdr {
+ struct vnt_mic_hdr hdr;
+ union vnt_tx_data_head head;
+} __packed;
+
+union vnt_tx {
+ struct vnt_tx_mic_hdr mic;
+ union vnt_tx_data_head head;
+};
+
+union vnt_tx_head {
+ struct {
+ struct vnt_rrv_time_rts rts;
+ union vnt_tx tx;
+ } __packed tx_rts;
+ struct {
+ struct vnt_rrv_time_cts cts;
+ union vnt_tx tx;
+ } __packed tx_cts;
+ struct {
+ struct vnt_rrv_time_ab ab;
+ union vnt_tx tx;
+ } __packed tx_ab;
+};
+
+struct vnt_tx_fifo_head {
u32 adwTxKey[4];
u16 wFIFOCtl;
u16 wTimeStamp;
@@ -191,6 +213,14 @@ struct vnt_tx_buffer {
u16 wReserved;
} __packed;
+struct vnt_tx_buffer {
+ u8 byType;
+ u8 byPKTNO;
+ u16 wTxByteCount;
+ struct vnt_tx_fifo_head fifo_head;
+ union vnt_tx_head tx_head;
+} __packed;
+
struct vnt_beacon_buffer {
u8 byType;
u8 byPKTNO;
diff --git a/drivers/staging/vt6656/wctl.c b/drivers/staging/vt6656/wctl.c
index 47a655db51ef..814342cd948e 100644
--- a/drivers/staging/vt6656/wctl.c
+++ b/drivers/staging/vt6656/wctl.c
@@ -69,8 +69,7 @@ bool WCTLbIsDuplicate (PSCache pCache, struct ieee80211_hdr *pMACHeader)
for (ii = 0; ii < DUPLICATE_RX_CACHE_LENGTH; ii++) {
pCacheEntry = &(pCache->asCacheEntry[uIndex]);
if ((pCacheEntry->wFmSequence == pMACHeader->seq_ctrl) &&
- (!compare_ether_addr(&(pCacheEntry->abyAddr2[0]),
- &(pMACHeader->addr2[0]))) &&
+ ether_addr_equal(pCacheEntry->abyAddr2, pMACHeader->addr2) &&
(LOBYTE(pCacheEntry->wFrameCtl) == LOBYTE(pMACHeader->frame_control))
) {
/* Duplicate match */
@@ -110,8 +109,8 @@ unsigned int WCTLuSearchDFCB(struct vnt_private *pDevice,
for (ii = 0; ii < pDevice->cbDFCB; ii++) {
if ((pDevice->sRxDFCB[ii].bInUse == true) &&
- (!compare_ether_addr(&(pDevice->sRxDFCB[ii].abyAddr2[0]),
- &(pMACHeader->addr2[0])))) {
+ ether_addr_equal(pDevice->sRxDFCB[ii].abyAddr2,
+ pMACHeader->addr2)) {
return ii;
}
}
diff --git a/drivers/staging/vt6656/wmgr.c b/drivers/staging/vt6656/wmgr.c
index b6cbd138a2b4..a69b88313948 100644
--- a/drivers/staging/vt6656/wmgr.c
+++ b/drivers/staging/vt6656/wmgr.c
@@ -1422,8 +1422,8 @@ static void s_vMgrRxDeauthentication(struct vnt_private *pDevice,
pDevice->fWPA_Authened = false;
DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO "AP deauthed me, reason=%d.\n", cpu_to_le16((*(sFrame.pwReason))));
// TODO: update BSS list for specific BSSID if pre-authentication case
- if (!compare_ether_addr(sFrame.pHdr->sA3.abyAddr3,
- pMgmt->abyCurrBSSID)) {
+ if (ether_addr_equal(sFrame.pHdr->sA3.abyAddr3,
+ pMgmt->abyCurrBSSID)) {
if (pMgmt->eCurrState >= WMAC_STATE_AUTHPENDING) {
pMgmt->sNodeDBTable[0].bActive = false;
pMgmt->eCurrMode = WMAC_MODE_STANDBY;
@@ -3095,7 +3095,7 @@ struct vnt_tx_mgmt *s_MgrMakeProbeResponse(struct vnt_private *pDevice,
*
*
* Return Value:
- * A ptr to frame or NULL on allocation failue
+ * A ptr to frame or NULL on allocation failure
*
-*/
diff --git a/drivers/staging/vt6656/wpactl.c b/drivers/staging/vt6656/wpactl.c
index 9f1b413ce86f..003bd7c614e5 100644
--- a/drivers/staging/vt6656/wpactl.c
+++ b/drivers/staging/vt6656/wpactl.c
@@ -227,7 +227,7 @@ int wpa_set_keys(struct vnt_private *pDevice, void *ctx)
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n");
} else {
// Key Table Full
- if (!compare_ether_addr(&param->addr[0], pDevice->abyBSSID)) {
+ if (ether_addr_equal(param->addr, pDevice->abyBSSID)) {
//DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n"));
return -EINVAL;
} else {
diff --git a/drivers/staging/winbond/mto.c b/drivers/staging/winbond/mto.c
index 560c0ab617d1..b031ecd4f3c0 100644
--- a/drivers/staging/winbond/mto.c
+++ b/drivers/staging/winbond/mto.c
@@ -21,6 +21,7 @@
#include "wbhal.h"
#include "wb35reg_f.h"
#include "core.h"
+#include "mto.h"
/* Declare SQ3 to rate and fragmentation threshold table */
/* Declare fragmentation threshold table */
@@ -45,12 +46,6 @@ static int retryrate_rec[MTO_MAX_DATA_RATE_LEVELS];
static u8 boSparseTxTraffic;
-void MTO_Init(struct wbsoft_priv *adapter);
-void TxRateReductionCtrl(struct wbsoft_priv *adapter);
-void MTO_SetTxCount(struct wbsoft_priv *adapter, u8 t0, u8 index);
-void MTO_TxFailed(struct wbsoft_priv *adapter);
-void hal_get_dto_para(struct wbsoft_priv *adapter, char *buffer);
-
/*
* ===========================================================================
* MTO_Init --
diff --git a/drivers/staging/winbond/mto.h b/drivers/staging/winbond/mto.h
index a0f659cf99ff..8d41eeda45bf 100644
--- a/drivers/staging/winbond/mto.h
+++ b/drivers/staging/winbond/mto.h
@@ -127,12 +127,8 @@ extern u16 MTO_Frag_Th_Tbl[];
#define MTO_DATA_RATE() MTO_Data_Rate_Tbl[MTO_RATE_LEVEL()]
#define MTO_FRAG_TH() MTO_Frag_Th_Tbl[MTO_FRAG_TH_LEVEL()]
-extern void MTO_Init(struct wbsoft_priv *);
-extern void MTO_PeriodicTimerExpired(struct wbsoft_priv *);
-extern void MTO_SetDTORateRange(struct wbsoft_priv *, u8 *, u8);
-extern u8 MTO_GetTxRate(struct wbsoft_priv *adapter, u32 fpdu_len);
-extern u8 MTO_GetTxFallbackRate(struct wbsoft_priv *adapter);
-extern void MTO_SetTxCount(struct wbsoft_priv *adapter, u8 t0, u8 index);
+void MTO_Init(struct wbsoft_priv *);
+void MTO_SetTxCount(struct wbsoft_priv *adapter, u8 t0, u8 index);
#endif /* __MTO_H__ */
diff --git a/drivers/staging/winbond/phy_calibration.c b/drivers/staging/winbond/phy_calibration.c
index cfbfbbb53866..d970660f6523 100644
--- a/drivers/staging/winbond/phy_calibration.c
+++ b/drivers/staging/winbond/phy_calibration.c
@@ -27,10 +27,12 @@
#define DEG2RAD(X) (0.017453 * (X))
static const s32 Angles[] = {
- FIXED(DEG2RAD(45.0)), FIXED(DEG2RAD(26.565)), FIXED(DEG2RAD(14.0362)),
- FIXED(DEG2RAD(7.12502)), FIXED(DEG2RAD(3.57633)), FIXED(DEG2RAD(1.78991)),
- FIXED(DEG2RAD(0.895174)), FIXED(DEG2RAD(0.447614)), FIXED(DEG2RAD(0.223811)),
- FIXED(DEG2RAD(0.111906)), FIXED(DEG2RAD(0.055953)), FIXED(DEG2RAD(0.027977))
+ FIXED(DEG2RAD(45.0)), FIXED(DEG2RAD(26.565)),
+ FIXED(DEG2RAD(14.0362)), FIXED(DEG2RAD(7.12502)),
+ FIXED(DEG2RAD(3.57633)), FIXED(DEG2RAD(1.78991)),
+ FIXED(DEG2RAD(0.895174)), FIXED(DEG2RAD(0.447614)),
+ FIXED(DEG2RAD(0.223811)), FIXED(DEG2RAD(0.111906)),
+ FIXED(DEG2RAD(0.055953)), FIXED(DEG2RAD(0.027977))
};
/****************** LOCAL FUNCTION DECLARATION SECTION **********************/
@@ -296,7 +298,8 @@ void _sin_cos(s32 angle, s32 *sin, s32 *cos)
}
}
-static unsigned char hal_get_dxx_reg(struct hw_data *pHwData, u16 number, u32 *pValue)
+static unsigned char hal_get_dxx_reg(struct hw_data *pHwData, u16 number,
+ u32 *pValue)
{
if (number < 0x1000)
number += 0x1000;
@@ -304,7 +307,8 @@ static unsigned char hal_get_dxx_reg(struct hw_data *pHwData, u16 number, u32 *p
}
#define hw_get_dxx_reg(_A, _B, _C) hal_get_dxx_reg(_A, _B, (u32 *)_C)
-static unsigned char hal_set_dxx_reg(struct hw_data *pHwData, u16 number, u32 value)
+static unsigned char hal_set_dxx_reg(struct hw_data *pHwData, u16 number,
+ u32 value)
{
unsigned char ret;
@@ -407,7 +411,8 @@ void _rxadc_dc_offset_cancellation_winbond(struct hw_data *phw_data, u32 frequen
PHY_DEBUG(("[CAL] ** adc_dc_cal_i = %d (0x%04X)\n",
_s9_to_s32(val&0x000001FF), val&0x000001FF));
PHY_DEBUG(("[CAL] ** adc_dc_cal_q = %d (0x%04X)\n",
- _s9_to_s32((val&0x0003FE00)>>9), (val&0x0003FE00)>>9));
+ _s9_to_s32((val&0x0003FE00)>>9),
+ (val&0x0003FE00)>>9));
#endif
hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &val);
@@ -535,7 +540,8 @@ void _txidac_dc_offset_cancellation_winbond(struct hw_data *phw_data)
}
PHY_DEBUG(("[CAL] ** fix_cancel_dc_i = %d (0x%04X)\n",
- fix_cancel_dc_i, _s32_to_s5(fix_cancel_dc_i)));
+ fix_cancel_dc_i,
+ _s32_to_s5(fix_cancel_dc_i)));
if ((abs(mag_1-mag_0)*6) > mag_0)
break;
@@ -711,7 +717,8 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data,
loop = LOOP_TIMES;
while (loop > 0) {
- PHY_DEBUG(("[CAL] [%d.] <_tx_iq_calibration_loop>\n", (LOOP_TIMES-loop+1)));
+ PHY_DEBUG(("[CAL] [%d.] <_tx_iq_calibration_loop>\n",
+ (LOOP_TIMES-loop+1)));
iqcal_tone_i_avg = 0;
iqcal_tone_q_avg = 0;
@@ -719,8 +726,8 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data,
return 0;
for (capture_time = 0; capture_time < 10; capture_time++) {
/*
- * a. Set iqcal_mode[1:0] to 0x2 and set "calib_start" to 0x1 to
- * enable "IQ calibration Mode II"
+ * a. Set iqcal_mode[1:0] to 0x2 and set "calib_start"
+ * to 0x1 to enable "IQ calibration Mode II"
*/
reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE);
reg_mode_ctrl &= ~MASK_IQCAL_MODE;
@@ -749,8 +756,8 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data,
PHY_DEBUG(("[CAL] MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
/*
- * d. Set iqcal_mode[1:0] to 0x3 and set "calib_start" to 0x1 to
- * enable "IQ calibration Mode II"
+ * d. Set iqcal_mode[1:0] to 0x3 and set "calib_start"
+ * to 0x1 to enable "IQ calibration Mode II"
*/
/* hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &val); */
hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
@@ -766,7 +773,7 @@ u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data,
iqcal_tone_i = _s13_to_s32(val & 0x00001FFF);
iqcal_tone_q = _s13_to_s32((val & 0x03FFE000) >> 13);
PHY_DEBUG(("[CAL] ** iqcal_tone_i = %d, iqcal_tone_q = %d\n",
- iqcal_tone_i, iqcal_tone_q));
+ iqcal_tone_i, iqcal_tone_q));
if (capture_time == 0)
continue;
else {
@@ -1146,7 +1153,8 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre
/* for (loop = 0; loop < LOOP_TIMES; loop++) */
loop = LOOP_TIMES;
while (loop > 0) {
- PHY_DEBUG(("[CAL] [%d.] <_rx_iq_calibration_loop>\n", (LOOP_TIMES-loop+1)));
+ PHY_DEBUG(("[CAL] [%d.] <_rx_iq_calibration_loop>\n",
+ (LOOP_TIMES-loop+1)));
iqcal_tone_i_avg = 0;
iqcal_tone_q_avg = 0;
iqcal_image_i_avg = 0;
@@ -1199,13 +1207,13 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre
/* d. */
rot_tone_i_b = (iqcal_tone_i * iqcal_tone_i +
- iqcal_tone_q * iqcal_tone_q) / 1024;
+ iqcal_tone_q * iqcal_tone_q) / 1024;
rot_tone_q_b = (iqcal_tone_i * iqcal_tone_q * (-1) +
- iqcal_tone_q * iqcal_tone_i) / 1024;
+ iqcal_tone_q * iqcal_tone_i) / 1024;
rot_image_i_b = (iqcal_image_i * iqcal_tone_i -
- iqcal_image_q * iqcal_tone_q) / 1024;
+ iqcal_image_q * iqcal_tone_q) / 1024;
rot_image_q_b = (iqcal_image_i * iqcal_tone_q +
- iqcal_image_q * iqcal_tone_i) / 1024;
+ iqcal_image_q * iqcal_tone_i) / 1024;
PHY_DEBUG(("[CAL] ** rot_tone_i_b = %d\n", rot_tone_i_b));
PHY_DEBUG(("[CAL] ** rot_tone_q_b = %d\n", rot_tone_q_b));
@@ -1225,8 +1233,10 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre
b_2 = (rot_image_q_b * 32768) / rot_tone_i_b -
phw_data->iq_rsdl_phase_tx_d2;
- PHY_DEBUG(("[CAL] ** iq_rsdl_gain_tx_d2 = %d\n", phw_data->iq_rsdl_gain_tx_d2));
- PHY_DEBUG(("[CAL] ** iq_rsdl_phase_tx_d2= %d\n", phw_data->iq_rsdl_phase_tx_d2));
+ PHY_DEBUG(("[CAL] ** iq_rsdl_gain_tx_d2 = %d\n",
+ phw_data->iq_rsdl_gain_tx_d2));
+ PHY_DEBUG(("[CAL] ** iq_rsdl_phase_tx_d2= %d\n",
+ phw_data->iq_rsdl_phase_tx_d2));
PHY_DEBUG(("[CAL] ***** EPSILON/2 = %d\n", a_2));
PHY_DEBUG(("[CAL] ***** THETA/2 = %d\n", b_2));
@@ -1272,7 +1282,8 @@ u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 fre
/* e. */
pwr_tone = (iqcal_tone_i*iqcal_tone_i + iqcal_tone_q*iqcal_tone_q);
- pwr_image = (iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q)*factor;
+ pwr_image = (iqcal_image_i*iqcal_image_i +
+ iqcal_image_q*iqcal_image_q)*factor;
PHY_DEBUG(("[CAL] ** pwr_tone = %d\n", pwr_tone));
PHY_DEBUG(("[CAL] ** pwr_image = %d\n", pwr_image));
@@ -1569,7 +1580,8 @@ unsigned char adjust_TXVGA_for_iq_mag(struct hw_data *phw_data)
sqsum = iqcal_tone_i0*iqcal_tone_i0 + iqcal_tone_q0*iqcal_tone_q0;
iq_mag_0_tx = (s32) _sqrt(sqsum);
- PHY_DEBUG(("[CAL] ** auto_adjust_txvga_for_iq_mag_0_tx=%d\n", iq_mag_0_tx));
+ PHY_DEBUG(("[CAL] ** auto_adjust_txvga_for_iq_mag_0_tx=%d\n",
+ iq_mag_0_tx));
if (iq_mag_0_tx >= 700 && iq_mag_0_tx <= 1750)
break;
diff --git a/drivers/staging/winbond/reg.c b/drivers/staging/winbond/reg.c
index 75b775252af1..80b4b343a94e 100644
--- a/drivers/staging/winbond/reg.c
+++ b/drivers/staging/winbond/reg.c
@@ -920,7 +920,7 @@ void Uxx_power_on_procedure(struct hw_data *pHwData)
Wb35Reg_WriteSync(pHwData, 0x03f8, 0x7ff);
}
-static void Set_ChanIndep_RfData_al7230_24(struct hw_data *pHwData, u32 *pltmp,
+static void Set_ChanIndep_RfData_al7230_24(struct hw_data *pHwData, u32 *pltmp,
char number)
{
u8 i;
@@ -930,7 +930,7 @@ static void Set_ChanIndep_RfData_al7230_24(struct hw_data *pHwData, u32 *pltmp,
}
}
-static void Set_ChanIndep_RfData_al7230_50(struct hw_data *pHwData, u32 *pltmp,
+static void Set_ChanIndep_RfData_al7230_50(struct hw_data *pHwData, u32 *pltmp,
char number)
{
u8 i;
@@ -1088,7 +1088,7 @@ void RFSynthesizer_initial(struct hw_data *pHwData)
msleep(5);
ltmp = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse((0x0F << 20) | 0xF01A0, 20);
- Wb35Reg_WriteSync(pHwData, 0x0864, ltmp) ;
+ Wb35Reg_WriteSync(pHwData, 0x0864, ltmp);
Wb35Reg_WriteSync(pHwData, 0x105c, pHwData->reg.BB5C);
pHwData->reg.BB50 &= ~0x13; /* (MASK_IQCAL_MODE|MASK_CALIB_START); */
@@ -1620,13 +1620,13 @@ void BBProcessor_initial(struct hw_data *pHwData)
reg->SQ3_filter[i] = 0x2f; /* half of Bit 0 ~ 6 */
}
-static inline void set_tx_power_per_channel_max2829(struct hw_data *pHwData,
+static inline void set_tx_power_per_channel_max2829(struct hw_data *pHwData,
struct chan_info Channel)
{
RFSynthesizer_SetPowerIndex(pHwData, 100);
}
-static void set_tx_power_per_channel_al2230(struct hw_data *pHwData,
+static void set_tx_power_per_channel_al2230(struct hw_data *pHwData,
struct chan_info Channel)
{
u8 index = 100;
@@ -1636,7 +1636,7 @@ static void set_tx_power_per_channel_al2230(struct hw_data *pHwData,
RFSynthesizer_SetPowerIndex(pHwData, index);
}
-static void set_tx_power_per_channel_al7230(struct hw_data *pHwData,
+static void set_tx_power_per_channel_al7230(struct hw_data *pHwData,
struct chan_info Channel)
{
u8 i, index = 100;
@@ -1660,7 +1660,7 @@ static void set_tx_power_per_channel_al7230(struct hw_data *pHwData,
RFSynthesizer_SetPowerIndex(pHwData, index);
}
-static void set_tx_power_per_channel_wb242(struct hw_data *pHwData,
+static void set_tx_power_per_channel_wb242(struct hw_data *pHwData,
struct chan_info Channel)
{
u8 index = 100;
@@ -2096,7 +2096,7 @@ void Mxx_initial(struct hw_data *pHwData)
pltmp[5] = reg->M38_MacControl;
/* M3C */
- tmp = (DEFAULT_PIFST << 26) | (DEFAULT_EIFST << 16) | (DEFAULT_DIFST << 8) | (DEFAULT_SIFST << 4) | DEFAULT_OSIFST ;
+ tmp = (DEFAULT_PIFST << 26) | (DEFAULT_EIFST << 16) | (DEFAULT_DIFST << 8) | (DEFAULT_SIFST << 4) | DEFAULT_OSIFST;
reg->M3C_MacControl = tmp;
pltmp[6] = tmp;
diff --git a/drivers/staging/winbond/wb35tx.c b/drivers/staging/winbond/wb35tx.c
index 30a77ccfe480..708c5b05f86c 100644
--- a/drivers/staging/winbond/wb35tx.c
+++ b/drivers/staging/winbond/wb35tx.c
@@ -180,7 +180,7 @@ void Wb35Tx_CurrentTime(struct wbsoft_priv *adapter, u32 TimeCount)
{
struct hw_data *pHwData = &adapter->sHwData;
struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
- unsigned char Trigger = false;
+ bool Trigger = false;
if (pWb35Tx->TxTimer > TimeCount)
Trigger = true;
diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c
index f1bce18ea828..237479acc3b4 100644
--- a/drivers/staging/wlan-ng/cfg80211.c
+++ b/drivers/staging/wlan-ng/cfg80211.c
@@ -122,7 +122,7 @@ int prism2_change_virtual_intf(struct wiphy *wiphy,
data = 1;
break;
default:
- printk(KERN_WARNING "Operation mode: %d not support\n", type);
+ netdev_warn(dev, "Operation mode: %d not support\n", type);
return -EOPNOTSUPP;
}
@@ -352,7 +352,7 @@ int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
return -EBUSY;
if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
- printk(KERN_ERR "Can't scan in AP mode\n");
+ netdev_err(dev, "Can't scan in AP mode\n");
return -EOPNOTSUPP;
}
@@ -510,7 +510,7 @@ int prism2_connect(struct wiphy *wiphy, struct net_device *dev,
((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep))
msg_join.authtype.data = P80211ENUM_authalg_sharedkey;
else
- printk(KERN_WARNING
+ netdev_warn(dev,
"Unhandled authorisation type for connect (%d)\n",
sme->auth_type);
diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c
index c1a8cb625154..5b8b094c8726 100644
--- a/drivers/staging/wlan-ng/hfa384x_usb.c
+++ b/drivers/staging/wlan-ng/hfa384x_usb.c
@@ -355,7 +355,7 @@ static int submit_rx_urb(hfa384x_t *hw, gfp_t memflags)
/* Check whether we need to reset the RX pipe */
if (result == -EPIPE) {
- printk(KERN_WARNING
+ netdev_warn(hw->wlandev->netdev,
"%s rx pipe stalled: requesting reset\n",
hw->wlandev->netdev->name);
if (!test_and_set_bit(WORK_RX_HALT, &hw->usb_flags))
@@ -405,7 +405,7 @@ static int submit_tx_urb(hfa384x_t *hw, struct urb *tx_urb, gfp_t memflags)
/* Test whether we need to reset the TX pipe */
if (result == -EPIPE) {
- printk(KERN_WARNING
+ netdev_warn(hw->wlandev->netdev,
"%s tx pipe stalled: requesting reset\n",
netdev->name);
set_bit(WORK_TX_HALT, &hw->usb_flags);
@@ -454,11 +454,11 @@ static void hfa384x_usb_defer(struct work_struct *data)
ret = usb_clear_halt(hw->usb, hw->endp_in);
if (ret != 0) {
- printk(KERN_ERR
+ netdev_err(hw->wlandev->netdev,
"Failed to clear rx pipe for %s: err=%d\n",
netdev->name, ret);
} else {
- printk(KERN_INFO "%s rx pipe reset complete.\n",
+ netdev_info(hw->wlandev->netdev, "%s rx pipe reset complete.\n",
netdev->name);
clear_bit(WORK_RX_HALT, &hw->usb_flags);
set_bit(WORK_RX_RESUME, &hw->usb_flags);
@@ -471,7 +471,7 @@ static void hfa384x_usb_defer(struct work_struct *data)
ret = submit_rx_urb(hw, GFP_KERNEL);
if (ret != 0) {
- printk(KERN_ERR
+ netdev_err(hw->wlandev->netdev,
"Failed to resume %s rx pipe.\n", netdev->name);
} else {
clear_bit(WORK_RX_RESUME, &hw->usb_flags);
@@ -485,11 +485,11 @@ static void hfa384x_usb_defer(struct work_struct *data)
usb_kill_urb(&hw->tx_urb);
ret = usb_clear_halt(hw->usb, hw->endp_out);
if (ret != 0) {
- printk(KERN_ERR
+ netdev_err(hw->wlandev->netdev,
"Failed to clear tx pipe for %s: err=%d\n",
netdev->name, ret);
} else {
- printk(KERN_INFO "%s tx pipe reset complete.\n",
+ netdev_info(hw->wlandev->netdev, "%s tx pipe reset complete.\n",
netdev->name);
clear_bit(WORK_TX_HALT, &hw->usb_flags);
set_bit(WORK_TX_RESUME, &hw->usb_flags);
@@ -1211,7 +1211,7 @@ int hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis)
result = usb_reset_device(hw->usb);
if (result < 0) {
- printk(KERN_ERR "usb_reset_device() failed, result=%d.\n",
+ netdev_err(hw->wlandev->netdev, "usb_reset_device() failed, result=%d.\n",
result);
}
@@ -1311,7 +1311,7 @@ cleanup:
if (ctlx->state == CTLX_COMPLETE) {
result = completor->complete(completor);
} else {
- printk(KERN_WARNING "CTLX[%d] error: state(%s)\n",
+ netdev_warn(hw->wlandev->netdev, "CTLX[%d] error: state(%s)\n",
le16_to_cpu(ctlx->outbuf.type),
ctlxstr(ctlx->state));
result = -EIO;
@@ -2018,7 +2018,7 @@ int hfa384x_drvr_flashdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len)
if (hw->dlstate != HFA384x_DLSTATE_FLASHENABLED)
return -EINVAL;
- printk(KERN_INFO "Download %d bytes to flash @0x%06x\n", len, daddr);
+ netdev_info(hw->wlandev->netdev, "Download %d bytes to flash @0x%06x\n", len, daddr);
/* Convert to flat address for arithmetic */
/* NOTE: dlbuffer RID stores the address in AUX format */
@@ -2028,7 +2028,7 @@ int hfa384x_drvr_flashdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len)
hw->bufinfo.page, hw->bufinfo.offset, dlbufaddr);
#if 0
- printk(KERN_WARNING "dlbuf@0x%06lx len=%d to=%d\n", dlbufaddr,
+ netdev_warn(hw->wlandev->netdev, "dlbuf@0x%06lx len=%d to=%d\n", dlbufaddr,
hw->bufinfo.len, hw->dltimeout);
#endif
/* Calculations to determine how many fills of the dlbuffer to do
@@ -2055,14 +2055,14 @@ int hfa384x_drvr_flashdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len)
burnlo = HFA384x_ADDR_CMD_MKOFF(burndaddr);
burnhi = HFA384x_ADDR_CMD_MKPAGE(burndaddr);
- printk(KERN_INFO "Writing %d bytes to flash @0x%06x\n",
+ netdev_info(hw->wlandev->netdev, "Writing %d bytes to flash @0x%06x\n",
burnlen, burndaddr);
/* Set the download mode */
result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_NV,
burnlo, burnhi, burnlen);
if (result) {
- printk(KERN_ERR "download(NV,lo=%x,hi=%x,len=%x) "
+ netdev_err(hw->wlandev->netdev, "download(NV,lo=%x,hi=%x,len=%x) "
"cmd failed, result=%d. Aborting d/l\n",
burnlo, burnhi, burnlen, result);
goto exit_proc;
@@ -2094,7 +2094,7 @@ int hfa384x_drvr_flashdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len)
HFA384x_PROGMODE_NVWRITE,
0, 0, 0);
if (result) {
- printk(KERN_ERR
+ netdev_err(hw->wlandev->netdev,
"download(NVWRITE,lo=%x,hi=%x,len=%x) "
"cmd failed, result=%d. Aborting d/l\n",
burnlo, burnhi, burnlen, result);
@@ -2279,7 +2279,7 @@ int hfa384x_drvr_ramdl_enable(hfa384x_t *hw, u32 exeaddr)
/* Check that a port isn't active */
for (i = 0; i < HFA384x_PORTID_MAX; i++) {
if (hw->port_enabled[i]) {
- printk(KERN_ERR
+ netdev_err(hw->wlandev->netdev,
"Can't download with a macport enabled.\n");
return -EINVAL;
}
@@ -2287,7 +2287,7 @@ int hfa384x_drvr_ramdl_enable(hfa384x_t *hw, u32 exeaddr)
/* Check that we're not already in a download state */
if (hw->dlstate != HFA384x_DLSTATE_DISABLED) {
- printk(KERN_ERR "Download state not disabled.\n");
+ netdev_err(hw->wlandev->netdev, "Download state not disabled.\n");
return -EINVAL;
}
@@ -2352,7 +2352,7 @@ int hfa384x_drvr_ramdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len)
if (hw->dlstate != HFA384x_DLSTATE_RAMENABLED)
return -EINVAL;
- printk(KERN_INFO "Writing %d bytes to ram @0x%06x\n", len, daddr);
+ netdev_info(hw->wlandev->netdev, "Writing %d bytes to ram @0x%06x\n", len, daddr);
/* How many dowmem calls? */
nwrites = len / HFA384x_USB_RWMEM_MAXLEN;
@@ -2449,7 +2449,7 @@ int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, unsigned int len)
len);
if (result) {
- printk(KERN_WARNING
+ netdev_warn(hw->wlandev->netdev,
"Read from index %zd failed, continuing\n", i);
continue;
}
@@ -2462,13 +2462,13 @@ int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, unsigned int len)
pdrcode = le16_to_cpu(pda[currpdr + 1]);
/* Test the record length */
if (pdrlen > HFA384x_PDR_LEN_MAX || pdrlen == 0) {
- printk(KERN_ERR "pdrlen invalid=%d\n", pdrlen);
+ netdev_err(hw->wlandev->netdev, "pdrlen invalid=%d\n", pdrlen);
pdaok = 0;
break;
}
/* Test the code */
if (!hfa384x_isgood_pdrcode(pdrcode)) {
- printk(KERN_ERR "pdrcode invalid=%d\n",
+ netdev_err(hw->wlandev->netdev, "pdrcode invalid=%d\n",
pdrcode);
pdaok = 0;
break;
@@ -2484,7 +2484,7 @@ int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, unsigned int len)
}
}
if (pdaok) {
- printk(KERN_INFO
+ netdev_info(hw->wlandev->netdev,
"PDA Read from 0x%08x in %s space.\n",
pdaloc[i].cardaddr,
pdaloc[i].auxctl == 0 ? "EXTDS" :
@@ -2564,20 +2564,20 @@ int hfa384x_drvr_start(hfa384x_t *hw)
result =
usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_in, &status);
if (result < 0) {
- printk(KERN_ERR "Cannot get bulk in endpoint status.\n");
+ netdev_err(hw->wlandev->netdev, "Cannot get bulk in endpoint status.\n");
goto done;
}
if ((status == 1) && usb_clear_halt(hw->usb, hw->endp_in))
- printk(KERN_ERR "Failed to reset bulk in endpoint.\n");
+ netdev_err(hw->wlandev->netdev, "Failed to reset bulk in endpoint.\n");
result =
usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_out, &status);
if (result < 0) {
- printk(KERN_ERR "Cannot get bulk out endpoint status.\n");
+ netdev_err(hw->wlandev->netdev, "Cannot get bulk out endpoint status.\n");
goto done;
}
if ((status == 1) && usb_clear_halt(hw->usb, hw->endp_out))
- printk(KERN_ERR "Failed to reset bulk out endpoint.\n");
+ netdev_err(hw->wlandev->netdev, "Failed to reset bulk out endpoint.\n");
/* Synchronous unlink, in case we're trying to restart the driver */
usb_kill_urb(&hw->rx_urb);
@@ -2585,7 +2585,7 @@ int hfa384x_drvr_start(hfa384x_t *hw)
/* Post the IN urb */
result = submit_rx_urb(hw, GFP_KERNEL);
if (result != 0) {
- printk(KERN_ERR
+ netdev_err(hw->wlandev->netdev,
"Fatal, failed to submit RX URB, result=%d\n", result);
goto done;
}
@@ -2605,7 +2605,7 @@ int hfa384x_drvr_start(hfa384x_t *hw)
result = result2 = hfa384x_cmd_initialize(hw);
if (result1 != 0) {
if (result2 != 0) {
- printk(KERN_ERR
+ netdev_err(hw->wlandev->netdev,
"cmd_initialize() failed on two attempts, results %d and %d\n",
result1, result2);
usb_kill_urb(&hw->rx_urb);
@@ -2616,9 +2616,9 @@ int hfa384x_drvr_start(hfa384x_t *hw)
pr_debug("but second attempt succeeded. All should be ok\n");
}
} else if (result2 != 0) {
- printk(KERN_WARNING "First cmd_initialize() succeeded, but second attempt failed (result=%d)\n",
+ netdev_warn(hw->wlandev->netdev, "First cmd_initialize() succeeded, but second attempt failed (result=%d)\n",
result2);
- printk(KERN_WARNING
+ netdev_warn(hw->wlandev->netdev,
"Most likely the card will be functional\n");
goto done;
}
@@ -2709,7 +2709,7 @@ int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb,
char *ptr;
if (hw->tx_urb.status == -EINPROGRESS) {
- printk(KERN_WARNING "TX URB already in use\n");
+ netdev_warn(hw->wlandev->netdev, "TX URB already in use\n");
result = 3;
goto exit;
}
@@ -2784,7 +2784,7 @@ int hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb,
result = 1;
ret = submit_tx_urb(hw, &hw->tx_urb, GFP_ATOMIC);
if (ret != 0) {
- printk(KERN_ERR "submit_tx_urb() failed, error=%d\n", ret);
+ netdev_err(hw->wlandev->netdev, "submit_tx_urb() failed, error=%d\n", ret);
result = 3;
}
@@ -3009,7 +3009,7 @@ static void unlocked_usbctlx_complete(hfa384x_t *hw, hfa384x_usbctlx_t *ctlx)
break;
default:
- printk(KERN_ERR "CTLX[%d] not in a terminating state(%s)\n",
+ netdev_err(hw->wlandev->netdev, "CTLX[%d] not in a terminating state(%s)\n",
le16_to_cpu(ctlx->outbuf.type), ctlxstr(ctlx->state));
break;
} /* switch */
@@ -3091,7 +3091,7 @@ static void hfa384x_usbctlxq_run(hfa384x_t *hw)
* this CTLX back in the "pending" queue
* and schedule a reset ...
*/
- printk(KERN_WARNING
+ netdev_warn(hw->wlandev->netdev,
"%s tx pipe stalled: requesting reset\n",
hw->wlandev->netdev->name);
list_move(&head->list, &hw->ctlxq.pending);
@@ -3101,12 +3101,12 @@ static void hfa384x_usbctlxq_run(hfa384x_t *hw)
}
if (result == -ESHUTDOWN) {
- printk(KERN_WARNING "%s urb shutdown!\n",
+ netdev_warn(hw->wlandev->netdev, "%s urb shutdown!\n",
hw->wlandev->netdev->name);
break;
}
- printk(KERN_ERR "Failed to submit CTLX[%d]: error=%d\n",
+ netdev_err(hw->wlandev->netdev, "Failed to submit CTLX[%d]: error=%d\n",
le16_to_cpu(head->outbuf.type), result);
unlocked_usbctlx_complete(hw, head);
} /* while */
@@ -3173,7 +3173,7 @@ static void hfa384x_usbin_callback(struct urb *urb)
break;
case -EPIPE:
- printk(KERN_WARNING "%s rx pipe stalled: requesting reset\n",
+ netdev_warn(hw->wlandev->netdev, "%s rx pipe stalled: requesting reset\n",
wlandev->netdev->name);
if (!test_and_set_bit(WORK_RX_HALT, &hw->usb_flags))
schedule_work(&hw->usb_work);
@@ -3224,7 +3224,7 @@ static void hfa384x_usbin_callback(struct urb *urb)
result = submit_rx_urb(hw, GFP_ATOMIC);
if (result != 0) {
- printk(KERN_ERR
+ netdev_err(hw->wlandev->netdev,
"Fatal, failed to resubmit rx_urb. error=%d\n",
result);
}
@@ -3360,7 +3360,7 @@ retry:
* Check that our message is what we're expecting ...
*/
if (ctlx->outbuf.type != intype) {
- printk(KERN_WARNING
+ netdev_warn(hw->wlandev->netdev,
"Expected IN[%d], received IN[%d] - ignored.\n",
le16_to_cpu(ctlx->outbuf.type),
le16_to_cpu(intype));
@@ -3396,7 +3396,7 @@ retry:
/*
* Throw this CTLX away ...
*/
- printk(KERN_ERR
+ netdev_err(hw->wlandev->netdev,
"Matched IN URB, CTLX[%d] in invalid state(%s)."
" Discarded.\n",
le16_to_cpu(ctlx->outbuf.type),
@@ -3534,7 +3534,7 @@ static void hfa384x_usbin_rx(wlandevice_t *wlandev, struct sk_buff *skb)
break;
default:
- printk(KERN_WARNING "Received frame on unsupported port=%d\n",
+ netdev_warn(hw->wlandev->netdev, "Received frame on unsupported port=%d\n",
HFA384x_RXSTATUS_MACPORT_GET(usbin->rxfrm.desc.status));
goto done;
break;
@@ -3596,7 +3596,7 @@ static void hfa384x_int_rxmonitor(wlandevice_t *wlandev,
skb = dev_alloc_skb(skblen);
if (skb == NULL) {
- printk(KERN_ERR
+ netdev_err(hw->wlandev->netdev,
"alloc_skb failed trying to allocate %d bytes\n",
skblen);
return;
@@ -3714,7 +3714,7 @@ static void hfa384x_usbout_callback(struct urb *urb)
case -EPIPE:
{
hfa384x_t *hw = wlandev->priv;
- printk(KERN_WARNING
+ netdev_warn(hw->wlandev->netdev,
"%s tx pipe stalled: requesting reset\n",
wlandev->netdev->name);
if (!test_and_set_bit
@@ -3747,7 +3747,7 @@ static void hfa384x_usbout_callback(struct urb *urb)
break;
default:
- printk(KERN_INFO "unknown urb->status=%d\n",
+ netdev_info(wlandev->netdev, "unknown urb->status=%d\n",
urb->status);
++(wlandev->linux_stats.tx_errors);
break;
@@ -3841,7 +3841,7 @@ retry:
default:
/* This is NOT a valid CTLX "success" state! */
- printk(KERN_ERR
+ netdev_err(hw->wlandev->netdev,
"Illegal CTLX[%d] success state(%s, %d) in OUT URB\n",
le16_to_cpu(ctlx->outbuf.type),
ctlxstr(ctlx->state), urb->status);
@@ -3851,7 +3851,7 @@ retry:
/* If the pipe has stalled then we need to reset it */
if ((urb->status == -EPIPE) &&
!test_and_set_bit(WORK_TX_HALT, &hw->usb_flags)) {
- printk(KERN_WARNING
+ netdev_warn(hw->wlandev->netdev,
"%s tx pipe stalled: requesting reset\n",
hw->wlandev->netdev->name);
schedule_work(&hw->usb_work);
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
index 3b3e17d3f6f5..b3ff603e6225 100644
--- a/drivers/staging/xgifb/XGI_main_26.c
+++ b/drivers/staging/xgifb/XGI_main_26.c
@@ -2070,7 +2070,6 @@ static void xgifb_remove(struct pci_dev *pdev)
release_mem_region(xgifb_info->video_base, xgifb_info->video_size);
pci_disable_device(pdev);
framebuffer_release(fb_info);
- pci_set_drvdata(pdev, NULL);
}
static struct pci_driver xgifb_driver = {
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index dbfc390330ac..57e06a9977cb 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -56,7 +56,7 @@ config THERMAL_DEFAULT_GOV_USER_SPACE
select THERMAL_GOV_USER_SPACE
help
Select this if you want to let the user space manage the
- lpatform thermals.
+ platform thermals.
endchoice
diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c
index f36950e4134f..7722cb9d5a80 100644
--- a/drivers/thermal/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/x86_pkg_temp_thermal.c
@@ -316,18 +316,19 @@ static void pkg_temp_thermal_threshold_work_fn(struct work_struct *work)
int phy_id = topology_physical_package_id(cpu);
struct phy_dev_entry *phdev = pkg_temp_thermal_get_phy_entry(cpu);
bool notify = false;
+ unsigned long flags;
if (!phdev)
return;
- spin_lock(&pkg_work_lock);
+ spin_lock_irqsave(&pkg_work_lock, flags);
++pkg_work_cnt;
if (unlikely(phy_id > max_phy_id)) {
- spin_unlock(&pkg_work_lock);
+ spin_unlock_irqrestore(&pkg_work_lock, flags);
return;
}
pkg_work_scheduled[phy_id] = 0;
- spin_unlock(&pkg_work_lock);
+ spin_unlock_irqrestore(&pkg_work_lock, flags);
enable_pkg_thres_interrupt();
rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val);
@@ -397,6 +398,7 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
int thres_count;
u32 eax, ebx, ecx, edx;
u8 *temp;
+ unsigned long flags;
cpuid(6, &eax, &ebx, &ecx, &edx);
thres_count = ebx & 0x07;
@@ -420,19 +422,19 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
goto err_ret_unlock;
}
- spin_lock(&pkg_work_lock);
+ spin_lock_irqsave(&pkg_work_lock, flags);
if (topology_physical_package_id(cpu) > max_phy_id)
max_phy_id = topology_physical_package_id(cpu);
temp = krealloc(pkg_work_scheduled,
(max_phy_id+1) * sizeof(u8), GFP_ATOMIC);
if (!temp) {
- spin_unlock(&pkg_work_lock);
+ spin_unlock_irqrestore(&pkg_work_lock, flags);
err = -ENOMEM;
goto err_ret_free;
}
pkg_work_scheduled = temp;
pkg_work_scheduled[topology_physical_package_id(cpu)] = 0;
- spin_unlock(&pkg_work_lock);
+ spin_unlock_irqrestore(&pkg_work_lock, flags);
phy_dev_entry->phys_proc_id = topology_physical_package_id(cpu);
phy_dev_entry->first_cpu = cpu;
diff --git a/drivers/tty/hvc/hvc_dcc.c b/drivers/tty/hvc/hvc_dcc.c
index 44fbebab5075..3502a7bbb69e 100644
--- a/drivers/tty/hvc/hvc_dcc.c
+++ b/drivers/tty/hvc/hvc_dcc.c
@@ -86,6 +86,21 @@ static int hvc_dcc_get_chars(uint32_t vt, char *buf, int count)
return i;
}
+static bool hvc_dcc_check(void)
+{
+ unsigned long time = jiffies + (HZ / 10);
+
+ /* Write a test character to check if it is handled */
+ __dcc_putchar('\n');
+
+ while (time_is_after_jiffies(time)) {
+ if (!(__dcc_getstatus() & DCC_STATUS_TX))
+ return true;
+ }
+
+ return false;
+}
+
static const struct hv_ops hvc_dcc_get_put_ops = {
.get_chars = hvc_dcc_get_chars,
.put_chars = hvc_dcc_put_chars,
@@ -93,6 +108,9 @@ static const struct hv_ops hvc_dcc_get_put_ops = {
static int __init hvc_dcc_console_init(void)
{
+ if (!hvc_dcc_check())
+ return -ENODEV;
+
hvc_instantiate(0, 0, &hvc_dcc_get_put_ops);
return 0;
}
@@ -100,6 +118,9 @@ console_initcall(hvc_dcc_console_init);
static int __init hvc_dcc_init(void)
{
+ if (!hvc_dcc_check())
+ return -ENODEV;
+
hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128);
return 0;
}
diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c
index c791b18cdd08..b594abfbf21e 100644
--- a/drivers/tty/hvc/hvc_vio.c
+++ b/drivers/tty/hvc/hvc_vio.c
@@ -48,6 +48,7 @@
#include <asm/prom.h>
#include <asm/hvsi.h>
#include <asm/udbg.h>
+#include <asm/machdep.h>
#include "hvc_console.h"
@@ -457,7 +458,9 @@ void __init hvc_vio_init_early(void)
if (hvterm_priv0.proto == HV_PROTOCOL_HVSI)
goto out;
#endif
- add_preferred_console("hvc", 0, NULL);
+ /* Check whether the user has requested a different console. */
+ if (!strstr(cmd_line, "console="))
+ add_preferred_console("hvc", 0, NULL);
hvc_instantiate(0, 0, ops);
out:
of_node_put(stdout_node);
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index c9a9ddd1d0bc..09505ff4fb25 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -1752,21 +1752,14 @@ int is_ignored(int sig)
static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
{
struct n_tty_data *ldata = tty->disc_data;
- int canon_change = 1;
- if (old)
- canon_change = (old->c_lflag ^ tty->termios.c_lflag) & ICANON;
- if (canon_change) {
+ if (!old || (old->c_lflag ^ tty->termios.c_lflag) & ICANON) {
bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
- ldata->line_start = 0;
- ldata->canon_head = ldata->read_tail;
+ ldata->line_start = ldata->canon_head = ldata->read_tail;
ldata->erasing = 0;
ldata->lnext = 0;
}
- if (canon_change && !L_ICANON(tty) && read_cnt(ldata))
- wake_up_interruptible(&tty->read_wait);
-
ldata->icanon = (L_ICANON(tty) != 0);
if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||
@@ -1821,9 +1814,8 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
* Fix tty hang when I_IXON(tty) is cleared, but the tty
* been stopped by STOP_CHAR(tty) before it.
*/
- if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped) {
+ if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped)
start_tty(tty);
- }
/* The termios change make the tty ready for I/O */
wake_up_interruptible(&tty->write_wait);
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 570df9d2a5d2..e33d38cb170f 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -2322,7 +2322,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
fcr = uart_config[port->type].fcr;
- if (baud < 2400 || fifo_bug) {
+ if ((baud < 2400 && !up->dma) || fifo_bug) {
fcr &= ~UART_FCR_TRIGGER_MASK;
fcr |= UART_FCR_TRIGGER_1;
}
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index daf710f5c3fc..8edf7697fdb2 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -56,11 +56,12 @@
struct dw8250_data {
- int last_lcr;
- int last_mcr;
- int line;
- struct clk *clk;
- u8 usr_reg;
+ u8 usr_reg;
+ int last_lcr;
+ int last_mcr;
+ int line;
+ struct clk *clk;
+ struct uart_8250_dma dma;
};
static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
@@ -153,6 +154,14 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
pm_runtime_put_sync_suspend(port->dev);
}
+static bool dw8250_dma_filter(struct dma_chan *chan, void *param)
+{
+ struct dw8250_data *data = param;
+
+ return chan->chan_id == data->dma.tx_chan_id ||
+ chan->chan_id == data->dma.rx_chan_id;
+}
+
static void dw8250_setup_port(struct uart_8250_port *up)
{
struct uart_port *p = &up->port;
@@ -241,7 +250,8 @@ static int dw8250_probe_of(struct uart_port *p,
}
#ifdef CONFIG_ACPI
-static int dw8250_probe_acpi(struct uart_8250_port *up)
+static int dw8250_probe_acpi(struct uart_8250_port *up,
+ struct dw8250_data *data)
{
const struct acpi_device_id *id;
struct uart_port *p = &up->port;
@@ -260,9 +270,7 @@ static int dw8250_probe_acpi(struct uart_8250_port *up)
if (!p->uartclk)
p->uartclk = (unsigned int)id->driver_data;
- up->dma = devm_kzalloc(p->dev, sizeof(*up->dma), GFP_KERNEL);
- if (!up->dma)
- return -ENOMEM;
+ up->dma = &data->dma;
up->dma->rxconf.src_maxburst = p->fifosize / 4;
up->dma->txconf.dst_maxburst = p->fifosize / 4;
@@ -314,6 +322,12 @@ static int dw8250_probe(struct platform_device *pdev)
uart.port.uartclk = clk_get_rate(data->clk);
}
+ data->dma.rx_chan_id = -1;
+ data->dma.tx_chan_id = -1;
+ data->dma.rx_param = data;
+ data->dma.tx_param = data;
+ data->dma.fn = dw8250_dma_filter;
+
uart.port.iotype = UPIO_MEM;
uart.port.serial_in = dw8250_serial_in;
uart.port.serial_out = dw8250_serial_out;
@@ -324,7 +338,7 @@ static int dw8250_probe(struct platform_device *pdev)
if (err)
return err;
} else if (ACPI_HANDLE(&pdev->dev)) {
- err = dw8250_probe_acpi(&uart);
+ err = dw8250_probe_acpi(&uart, data);
if (err)
return err;
} else {
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index c810da7c7a88..515fd0ff4e4e 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -3520,8 +3520,6 @@ static void pciserial_remove_one(struct pci_dev *dev)
{
struct serial_private *priv = pci_get_drvdata(dev);
- pci_set_drvdata(dev, NULL);
-
pciserial_remove_ports(priv);
pci_disable_device(dev);
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index febd45cd5027..701ca60076ed 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1512,6 +1512,7 @@ config SERIAL_FSL_LPUART_CONSOLE
config SERIAL_ST_ASC
tristate "ST ASC serial port support"
select SERIAL_CORE
+ depends on ARM || COMPILE_TEST
help
This driver is for the on-chip Asychronous Serial Controller on
STMicroelectronics STi SoCs.
diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index 569872f4c9b8..c9f5c9dcc15c 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -533,7 +533,7 @@ arc_uart_init_one(struct platform_device *pdev, int dev_id)
unsigned long *plat_data;
struct arc_uart_port *uart = &arc_uart_ports[dev_id];
- plat_data = (unsigned long *)dev_get_platdata(&pdev->dev);
+ plat_data = dev_get_platdata(&pdev->dev);
if (!plat_data)
return -ENODEV;
diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c
index 87636cc61a21..4f229703328b 100644
--- a/drivers/tty/serial/bfin_sport_uart.c
+++ b/drivers/tty/serial/bfin_sport_uart.c
@@ -766,9 +766,8 @@ static int sport_uart_probe(struct platform_device *pdev)
return -ENOMEM;
}
- ret = peripheral_request_list(
- (unsigned short *)dev_get_platdata(&pdev->dev),
- DRV_NAME);
+ ret = peripheral_request_list(dev_get_platdata(&pdev->dev),
+ DRV_NAME);
if (ret) {
dev_err(&pdev->dev,
"Fail to request SPORT peripherals\n");
@@ -844,8 +843,7 @@ static int sport_uart_probe(struct platform_device *pdev)
out_error_unmap:
iounmap(sport->port.membase);
out_error_free_peripherals:
- peripheral_free_list(
- (unsigned short *)dev_get_platdata(&pdev->dev));
+ peripheral_free_list(dev_get_platdata(&pdev->dev));
out_error_free_mem:
kfree(sport);
bfin_sport_uart_ports[pdev->id] = NULL;
@@ -864,8 +862,7 @@ static int sport_uart_remove(struct platform_device *pdev)
if (sport) {
uart_remove_one_port(&sport_uart_reg, &sport->port);
iounmap(sport->port.membase);
- peripheral_free_list(
- (unsigned short *)dev_get_platdata(&pdev->dev));
+ peripheral_free_list(dev_get_platdata(&pdev->dev));
kfree(sport);
bfin_sport_uart_ports[pdev->id] = NULL;
}
diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c
index 3c75e8e04028..74749a6d3565 100644
--- a/drivers/tty/serial/bfin_uart.c
+++ b/drivers/tty/serial/bfin_uart.c
@@ -1240,7 +1240,7 @@ static int bfin_serial_probe(struct platform_device *pdev)
*/
#endif
ret = peripheral_request_list(
- (unsigned short *)dev_get_platdata(&pdev->dev),
+ dev_get_platdata(&pdev->dev),
DRIVER_NAME);
if (ret) {
dev_err(&pdev->dev,
@@ -1358,8 +1358,7 @@ static int bfin_serial_probe(struct platform_device *pdev)
out_error_unmap:
iounmap(uart->port.membase);
out_error_free_peripherals:
- peripheral_free_list(
- (unsigned short *)dev_get_platdata(&pdev->dev));
+ peripheral_free_list(dev_get_platdata(&pdev->dev));
out_error_free_mem:
kfree(uart);
bfin_serial_ports[pdev->id] = NULL;
@@ -1377,8 +1376,7 @@ static int bfin_serial_remove(struct platform_device *pdev)
if (uart) {
uart_remove_one_port(&bfin_serial_reg, &uart->port);
iounmap(uart->port.membase);
- peripheral_free_list(
- (unsigned short *)dev_get_platdata(&pdev->dev));
+ peripheral_free_list(dev_get_platdata(&pdev->dev));
kfree(uart);
bfin_serial_ports[pdev->id] = NULL;
}
@@ -1432,8 +1430,8 @@ static int bfin_earlyprintk_probe(struct platform_device *pdev)
return -ENOENT;
}
- ret = peripheral_request_list(
- (unsigned short *)dev_get_platdata(&pdev->dev), DRIVER_NAME);
+ ret = peripheral_request_list(dev_get_platdata(&pdev->dev),
+ DRIVER_NAME);
if (ret) {
dev_err(&pdev->dev,
"fail to request bfin serial peripherals\n");
@@ -1463,8 +1461,7 @@ static int bfin_earlyprintk_probe(struct platform_device *pdev)
return 0;
out_error_free_peripherals:
- peripheral_free_list(
- (unsigned short *)dev_get_platdata(&pdev->dev));
+ peripheral_free_list(dev_get_platdata(&pdev->dev));
return ret;
}
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index 7e4e4088471c..8d0b994357c8 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -459,7 +459,6 @@ static int uart_clps711x_probe(struct platform_device *pdev)
ret = uart_register_driver(&s->uart);
if (ret) {
dev_err(&pdev->dev, "Registering UART driver failed\n");
- devm_clk_put(&pdev->dev, s->uart_clk);
return ret;
}
@@ -487,7 +486,6 @@ static int uart_clps711x_remove(struct platform_device *pdev)
for (i = 0; i < UART_CLPS711X_NR; i++)
uart_remove_one_port(&s->uart, &s->port[i]);
- devm_clk_put(&pdev->dev, s->uart_clk);
uart_unregister_driver(&s->uart);
return 0;
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index af286e6713eb..590390970996 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -1008,7 +1008,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
return -ENODEV;
}
- pl_data = (struct ifx_modem_platform_data *)dev_get_platdata(&spi->dev);
+ pl_data = dev_get_platdata(&spi->dev);
if (!pl_data) {
dev_err(&spi->dev, "missing platform data!");
return -ENODEV;
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index a0ebbc9ce5cd..c07d9bb39695 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -1539,7 +1539,7 @@ imx_verify_port(struct uart_port *port, struct serial_struct *ser)
ret = -EINVAL;
if (sport->port.uartclk / 16 != ser->baud_base)
ret = -EINVAL;
- if ((void *)sport->port.mapbase != ser->iomem_base)
+ if (sport->port.mapbase != (unsigned long)ser->iomem_base)
ret = -EINVAL;
if (sport->port.iobase != ser->port)
ret = -EINVAL;
@@ -1913,7 +1913,8 @@ static int serial_imx_probe_dt(struct imx_port *sport,
sport->devdata = of_id->data;
if (of_device_is_stdout_path(np))
- add_preferred_console(imx_reg.cons->name, sport->port.line, 0);
+ add_preferred_console(imx_reg.cons->name, sport->port.line,
+ NULL);
return 0;
}
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c
index d3db042f649e..503dcc77b2bd 100644
--- a/drivers/tty/serial/mfd.c
+++ b/drivers/tty/serial/mfd.c
@@ -1451,7 +1451,6 @@ static void serial_hsu_remove(struct pci_dev *pdev)
uart_remove_one_port(&serial_hsu_reg, &up->port);
}
- pci_set_drvdata(pdev, NULL);
free_irq(pdev->irq, priv);
pci_disable_device(pdev);
}
@@ -1504,4 +1503,4 @@ module_init(hsu_pci_init);
module_exit(hsu_pci_exit);
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:medfield-hsu");
+MODULE_DEVICE_TABLE(pci, pci_ids);
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 5be1df39f9f5..e05a3b1a87c7 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -1766,7 +1766,7 @@ mpc52xx_uart_of_remove(struct platform_device *op)
static int
mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state)
{
- struct uart_port *port = (struct uart_port *) platform_get_drvdata(op);
+ struct uart_port *port = platform_get_drvdata(op);
if (port)
uart_suspend_port(&mpc52xx_uart_driver, port);
@@ -1777,7 +1777,7 @@ mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state)
static int
mpc52xx_uart_of_resume(struct platform_device *op)
{
- struct uart_port *port = (struct uart_port *) platform_get_drvdata(op);
+ struct uart_port *port = platform_get_drvdata(op);
if (port)
uart_resume_port(&mpc52xx_uart_driver, port);
diff --git a/drivers/tty/serial/mpsc.c b/drivers/tty/serial/mpsc.c
index 8d702677acc5..e30a3ca3cea3 100644
--- a/drivers/tty/serial/mpsc.c
+++ b/drivers/tty/serial/mpsc.c
@@ -2030,7 +2030,7 @@ static void mpsc_drv_get_platform_data(struct mpsc_port_info *pi,
{
struct mpsc_pdata *pdata;
- pdata = (struct mpsc_pdata *)dev_get_platdata(&pd->dev);
+ pdata = dev_get_platdata(&pd->dev);
pi->port.uartclk = pdata->brg_clk_freq;
pi->port.iotype = UPIO_MEM;
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 816d1a23f9d0..7b00520624f9 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -247,7 +247,7 @@ serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud)
if(baudAbsDiff16 < 0)
baudAbsDiff16 = -baudAbsDiff16;
- return (baudAbsDiff13 > baudAbsDiff16);
+ return (baudAbsDiff13 >= baudAbsDiff16);
}
/*
@@ -258,13 +258,13 @@ serial_omap_baud_is_mode16(struct uart_port *port, unsigned int baud)
static unsigned int
serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
{
- unsigned int divisor;
+ unsigned int mode;
if (!serial_omap_baud_is_mode16(port, baud))
- divisor = 13;
+ mode = 13;
else
- divisor = 16;
- return port->uartclk/(baud * divisor);
+ mode = 16;
+ return port->uartclk/(mode * baud);
}
static void serial_omap_enable_ms(struct uart_port *port)
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 52379e56a31e..87f25def0b41 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -667,30 +667,21 @@ static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf)
static int dma_push_rx(struct eg20t_port *priv, int size)
{
- struct tty_struct *tty;
int room;
struct uart_port *port = &priv->port;
struct tty_port *tport = &port->state->port;
- port = &priv->port;
- tty = tty_port_tty_get(tport);
- if (!tty) {
- dev_dbg(priv->port.dev, "%s:tty is busy now", __func__);
- return 0;
- }
-
room = tty_buffer_request_room(tport, size);
if (room < size)
dev_warn(port->dev, "Rx overrun: dropping %u bytes\n",
size - room);
if (!room)
- return room;
+ return 0;
tty_insert_flip_string(tport, sg_virt(&priv->sg_rx), size);
port->icount.rx += room;
- tty_kref_put(tty);
return room;
}
@@ -1098,6 +1089,8 @@ static void pch_uart_err_ir(struct eg20t_port *priv, unsigned int lsr)
if (tty == NULL) {
for (i = 0; error_msg[i] != NULL; i++)
dev_err(&priv->pdev->dev, error_msg[i]);
+ } else {
+ tty_kref_put(tty);
}
}
@@ -2003,6 +1996,8 @@ module_exit(pch_uart_module_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Intel EG20T PCH UART PCI Driver");
+MODULE_DEVICE_TABLE(pci, pch_uart_pci_id);
+
module_param(default_baud, uint, S_IRUGO);
MODULE_PARM_DESC(default_baud,
"Default BAUD for initial driver state and console (default 9600)");
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index f3dfa19a1cb8..c1af04d46682 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -407,7 +407,14 @@ static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
- /* todo - possibly remove AFC and do manual CTS */
+ unsigned int umcon = rd_regl(port, S3C2410_UMCON);
+
+ if (mctrl & TIOCM_RTS)
+ umcon |= S3C2410_UMCOM_RTS_LOW;
+ else
+ umcon &= ~S3C2410_UMCOM_RTS_LOW;
+
+ wr_regl(port, S3C2410_UMCON, umcon);
}
static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
@@ -774,8 +781,6 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
if (termios->c_cflag & CSTOPB)
ulcon |= S3C2410_LCON_STOPB;
- umcon = (termios->c_cflag & CRTSCTS) ? S3C2410_UMCOM_AFC : 0;
-
if (termios->c_cflag & PARENB) {
if (termios->c_cflag & PARODD)
ulcon |= S3C2410_LCON_PODD;
@@ -792,6 +797,15 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
wr_regl(port, S3C2410_ULCON, ulcon);
wr_regl(port, S3C2410_UBRDIV, quot);
+
+ umcon = rd_regl(port, S3C2410_UMCON);
+ if (termios->c_cflag & CRTSCTS) {
+ umcon |= S3C2410_UMCOM_AFC;
+ /* Disable RTS when RX FIFO contains 63 bytes */
+ umcon &= ~S3C2412_UMCON_AFC_8;
+ } else {
+ umcon &= ~S3C2410_UMCOM_AFC;
+ }
wr_regl(port, S3C2410_UMCON, umcon);
if (ourport->info->has_divslot)
@@ -1254,7 +1268,7 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
ourport->baudclk = ERR_PTR(-EINVAL);
ourport->info = ourport->drv_data->info;
ourport->cfg = (dev_get_platdata(&pdev->dev)) ?
- (struct s3c2410_uartcfg *)dev_get_platdata(&pdev->dev) :
+ dev_get_platdata(&pdev->dev) :
ourport->drv_data->def_cfg;
ourport->port.fifosize = (ourport->info->fifosize) ?
diff --git a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h
index aaa617a6c499..8827e5424cef 100644
--- a/drivers/tty/serial/samsung.h
+++ b/drivers/tty/serial/samsung.h
@@ -63,7 +63,7 @@ struct s3c24xx_uart_port {
/* conversion functions */
-#define s3c24xx_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev)
+#define s3c24xx_dev_to_port(__dev) dev_get_drvdata(__dev)
/* register access controls */
diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c
index 49e9bbfe6cab..a447f71538ef 100644
--- a/drivers/tty/serial/sccnxp.c
+++ b/drivers/tty/serial/sccnxp.c
@@ -986,6 +986,7 @@ static int sccnxp_probe(struct platform_device *pdev)
return 0;
}
+ uart_unregister_driver(&s->uart);
err_out:
if (!IS_ERR(s->regulator))
return regulator_disable(s->regulator);
diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c
index d0d972f7e43e..0489a2bdcdf9 100644
--- a/drivers/tty/serial/serial-tegra.c
+++ b/drivers/tty/serial/serial-tegra.c
@@ -732,7 +732,7 @@ static irqreturn_t tegra_uart_isr(int irq, void *data)
static void tegra_uart_stop_rx(struct uart_port *u)
{
struct tegra_uart_port *tup = to_tegra_uport(u);
- struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port);
+ struct tty_struct *tty;
struct tty_port *port = &u->state->port;
struct dma_tx_state state;
unsigned long ier;
@@ -744,6 +744,8 @@ static void tegra_uart_stop_rx(struct uart_port *u)
if (!tup->rx_in_progress)
return;
+ tty = tty_port_tty_get(&tup->uport.state->port);
+
tegra_uart_wait_sym_time(tup, 1); /* wait a character interval */
ier = tup->ier_shadow;
diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c
index 440a962412da..90a080b1f9ee 100644
--- a/drivers/tty/serial/serial_txx9.c
+++ b/drivers/tty/serial/serial_txx9.c
@@ -1220,8 +1220,6 @@ static void pciserial_txx9_remove_one(struct pci_dev *dev)
{
struct uart_txx9_port *up = pci_get_drvdata(dev);
- pci_set_drvdata(dev, NULL);
-
if (up) {
serial_txx9_unregister_port(up->port.line);
pci_disable_device(dev);
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 537750261aaa..d262c1f4af03 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -52,6 +52,7 @@
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/gpio.h>
+#include <linux/of.h>
#ifdef CONFIG_SUPERH
#include <asm/sh_bios.h>
@@ -2437,6 +2438,112 @@ static int sci_remove(struct platform_device *dev)
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id of_sci_match[] = {
+ { .compatible = "renesas,sci-SCI-uart",
+ .data = (void *)PORT_SCI },
+ { .compatible = "renesas,sci-SCIF-uart",
+ .data = (void *)PORT_SCIF },
+ { .compatible = "renesas,sci-IRDA-uart",
+ .data = (void *)PORT_IRDA },
+ { .compatible = "renesas,sci-SCIFA-uart",
+ .data = (void *)PORT_SCIFA },
+ { .compatible = "renesas,sci-SCIFB-uart",
+ .data = (void *)PORT_SCIFB },
+ {},
+};
+MODULE_DEVICE_TABLE(of, of_sci_match);
+
+static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev,
+ int *dev_id)
+{
+ struct plat_sci_port *p;
+ struct device_node *np = pdev->dev.of_node;
+ const struct of_device_id *match;
+ struct resource *res;
+ const __be32 *prop;
+ int i, irq, val;
+
+ match = of_match_node(of_sci_match, pdev->dev.of_node);
+ if (!match || !match->data) {
+ dev_err(&pdev->dev, "OF match error\n");
+ return NULL;
+ }
+
+ p = devm_kzalloc(&pdev->dev, sizeof(struct plat_sci_port), GFP_KERNEL);
+ if (!p) {
+ dev_err(&pdev->dev, "failed to allocate DT config data\n");
+ return NULL;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "failed to get I/O memory\n");
+ return NULL;
+ }
+ p->mapbase = res->start;
+
+ for (i = 0; i < SCIx_NR_IRQS; i++) {
+ irq = platform_get_irq(pdev, i);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "failed to get irq data %d\n", i);
+ return NULL;
+ }
+ p->irqs[i] = irq;
+ }
+
+ prop = of_get_property(np, "cell-index", NULL);
+ if (!prop) {
+ dev_err(&pdev->dev, "required DT prop cell-index missing\n");
+ return NULL;
+ }
+ *dev_id = be32_to_cpup(prop);
+
+ prop = of_get_property(np, "renesas,scscr", NULL);
+ if (!prop) {
+ dev_err(&pdev->dev, "required DT prop scscr missing\n");
+ return NULL;
+ }
+ p->scscr = be32_to_cpup(prop);
+
+ prop = of_get_property(np, "renesas,scbrr-algo-id", NULL);
+ if (!prop) {
+ dev_err(&pdev->dev, "required DT prop scbrr-algo-id missing\n");
+ return NULL;
+ }
+ val = be32_to_cpup(prop);
+ if (val <= SCBRR_ALGO_INVALID || val >= SCBRR_NR_ALGOS) {
+ dev_err(&pdev->dev, "DT prop scbrr-algo-id out of range\n");
+ return NULL;
+ }
+ p->scbrr_algo_id = val;
+
+ p->flags = UPF_IOREMAP;
+ if (of_get_property(np, "renesas,autoconf", NULL))
+ p->flags |= UPF_BOOT_AUTOCONF;
+
+ prop = of_get_property(np, "renesas,regtype", NULL);
+ if (prop) {
+ val = be32_to_cpup(prop);
+ if (val < SCIx_PROBE_REGTYPE || val >= SCIx_NR_REGTYPES) {
+ dev_err(&pdev->dev, "DT prop regtype out of range\n");
+ return NULL;
+ }
+ p->regtype = val;
+ }
+
+ p->type = (unsigned int)match->data;
+
+ return p;
+}
+#else
+static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev,
+ int *dev_id)
+{
+ return NULL;
+}
+#endif /* CONFIG_OF */
+
static int sci_probe_single(struct platform_device *dev,
unsigned int index,
struct plat_sci_port *p,
@@ -2469,9 +2576,9 @@ static int sci_probe_single(struct platform_device *dev,
static int sci_probe(struct platform_device *dev)
{
- struct plat_sci_port *p = dev_get_platdata(&dev->dev);
- struct sci_port *sp = &sci_ports[dev->id];
- int ret;
+ struct plat_sci_port *p;
+ struct sci_port *sp;
+ int ret, dev_id = dev->id;
/*
* If we've come here via earlyprintk initialization, head off to
@@ -2481,9 +2588,20 @@ static int sci_probe(struct platform_device *dev)
if (is_early_platform_device(dev))
return sci_probe_earlyprintk(dev);
+ if (dev->dev.of_node)
+ p = sci_parse_dt(dev, &dev_id);
+ else
+ p = dev_get_platdata(&dev->dev);
+
+ if (!p) {
+ dev_err(&dev->dev, "no setup data supplied\n");
+ return -EINVAL;
+ }
+
+ sp = &sci_ports[dev_id];
platform_set_drvdata(dev, sp);
- ret = sci_probe_single(dev, dev->id, p, sp);
+ ret = sci_probe_single(dev, dev_id, p, sp);
if (ret)
return ret;
@@ -2535,6 +2653,7 @@ static struct platform_driver sci_driver = {
.name = "sh-sci",
.owner = THIS_MODULE,
.pm = &sci_dev_pm_ops,
+ .of_match_table = of_match_ptr(of_sci_match),
},
};
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c
index 61c1ad03db5b..f186a8fb8887 100644
--- a/drivers/tty/serial/sirfsoc_uart.c
+++ b/drivers/tty/serial/sirfsoc_uart.c
@@ -529,7 +529,7 @@ static void sirfsoc_rx_tmo_process_tl(unsigned long param)
while (sirfport->rx_completed != sirfport->rx_issued) {
sirfsoc_uart_insert_rx_buf_to_tty(sirfport,
SIRFSOC_RX_DMA_BUF_SIZE);
- sirfsoc_rx_submit_one_dma_desc(port, sirfport->rx_completed++);
+ sirfport->rx_completed++;
sirfport->rx_completed %= SIRFSOC_RX_LOOP_BUF_CNT;
}
count = CIRC_CNT(sirfport->rx_dma_items[sirfport->rx_issued].xmit.head,
@@ -706,12 +706,19 @@ static void sirfsoc_uart_rx_dma_complete_tl(unsigned long param)
{
struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)param;
struct uart_port *port = &sirfport->port;
+ struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
+ struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
unsigned long flags;
spin_lock_irqsave(&sirfport->rx_lock, flags);
while (sirfport->rx_completed != sirfport->rx_issued) {
sirfsoc_uart_insert_rx_buf_to_tty(sirfport,
SIRFSOC_RX_DMA_BUF_SIZE);
- sirfsoc_rx_submit_one_dma_desc(port, sirfport->rx_completed++);
+ if (rd_regl(port, ureg->sirfsoc_int_en_reg) &
+ uint_en->sirfsoc_rx_timeout_en)
+ sirfsoc_rx_submit_one_dma_desc(port,
+ sirfport->rx_completed++);
+ else
+ sirfport->rx_completed++;
sirfport->rx_completed %= SIRFSOC_RX_LOOP_BUF_CNT;
}
spin_unlock_irqrestore(&sirfport->rx_lock, flags);
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index 03ba081c5772..6fd60fece6b4 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -1201,6 +1201,9 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
}
return 0;
case TCFLSH:
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
return __tty_perform_flush(tty, arg);
default:
/* Try the mode commands */
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index f597e88a705d..c94d2349dd06 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -140,6 +140,10 @@ EXPORT_SYMBOL(tty_port_destroy);
static void tty_port_destructor(struct kref *kref)
{
struct tty_port *port = container_of(kref, struct tty_port, kref);
+
+ /* check if last port ref was dropped before tty release */
+ if (WARN_ON(port->itty))
+ return;
if (port->xmit_buf)
free_page((unsigned long)port->xmit_buf);
tty_port_destroy(port);
@@ -480,8 +484,6 @@ int tty_port_close_start(struct tty_port *port,
if (port->count) {
spin_unlock_irqrestore(&port->lock, flags);
- if (port->ops->drop)
- port->ops->drop(port);
return 0;
}
set_bit(ASYNCB_CLOSING, &port->flags);
@@ -500,9 +502,7 @@ int tty_port_close_start(struct tty_port *port,
/* Flush the ldisc buffering */
tty_ldisc_flush(tty);
- /* Don't call port->drop for the last reference. Callers will want
- to drop the last active reference in ->shutdown() or the tty
- shutdown path */
+ /* Report to caller this is the last port reference */
return 1;
}
EXPORT_SYMBOL(tty_port_close_start);
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 9a8e8c5a0c73..61b1137d7e56 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -1300,21 +1300,30 @@ static void csi_m(struct vc_data *vc)
case 27:
vc->vc_reverse = 0;
break;
- case 38: /* ANSI X3.64-1979 (SCO-ish?)
- * Enables underscore, white foreground
- * with white underscore (Linux - use
- * default foreground).
+ case 38:
+ case 48: /* ITU T.416
+ * Higher colour modes.
+ * They break the usual properties of SGR codes
+ * and thus need to be detected and ignored by
+ * hand. Strictly speaking, that standard also
+ * wants : rather than ; as separators, contrary
+ * to ECMA-48, but no one produces such codes
+ * and almost no one accepts them.
*/
- vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0);
- vc->vc_underline = 1;
+ i++;
+ if (i > vc->vc_npar)
+ break;
+ if (vc->vc_par[i] == 5) /* 256 colours */
+ i++; /* ubiquitous */
+ else if (vc->vc_par[i] == 2) /* 24 bit colours */
+ i += 3; /* extremely rare */
+ /* Subcommands 3 (CMY) and 4 (CMYK) are so insane
+ * that detecting them is not worth the few extra
+ * bytes of kernel's size.
+ */
break;
- case 39: /* ANSI X3.64-1979 (SCO-ish?)
- * Disable underline option.
- * Reset colour to default? It did this
- * before...
- */
+ case 39:
vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0);
- vc->vc_underline = 0;
break;
case 49:
vc->vc_color = (vc->vc_def_color & 0xf0) | (vc->vc_color & 0x0f);
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index ba475632c5fa..11d4e0a52579 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -796,10 +796,9 @@ int __uio_register_device(struct module *owner,
info->uio_dev = NULL;
- idev = kzalloc(sizeof(*idev), GFP_KERNEL);
+ idev = devm_kzalloc(parent, sizeof(*idev), GFP_KERNEL);
if (!idev) {
- ret = -ENOMEM;
- goto err_kzalloc;
+ return -ENOMEM;
}
idev->owner = owner;
@@ -809,7 +808,7 @@ int __uio_register_device(struct module *owner,
ret = uio_get_minor(idev);
if (ret)
- goto err_get_minor;
+ return ret;
idev->dev = device_create(&uio_class, parent,
MKDEV(uio_major, idev->minor), idev,
@@ -827,7 +826,7 @@ int __uio_register_device(struct module *owner,
info->uio_dev = idev;
if (info->irq && (info->irq != UIO_IRQ_CUSTOM)) {
- ret = request_irq(info->irq, uio_interrupt,
+ ret = devm_request_irq(parent, info->irq, uio_interrupt,
info->irq_flags, info->name, idev);
if (ret)
goto err_request_irq;
@@ -841,9 +840,6 @@ err_uio_dev_add_attributes:
device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
err_device_create:
uio_free_minor(idev);
-err_get_minor:
- kfree(idev);
-err_kzalloc:
return ret;
}
EXPORT_SYMBOL_GPL(__uio_register_device);
@@ -864,13 +860,9 @@ void uio_unregister_device(struct uio_info *info)
uio_free_minor(idev);
- if (info->irq && (info->irq != UIO_IRQ_CUSTOM))
- free_irq(info->irq, idev);
-
uio_dev_del_attributes(idev);
device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
- kfree(idev);
return;
}
diff --git a/drivers/uio/uio_aec.c b/drivers/uio/uio_aec.c
index f3611c2d83b6..1549fab633c6 100644
--- a/drivers/uio/uio_aec.c
+++ b/drivers/uio/uio_aec.c
@@ -147,7 +147,6 @@ static void remove(struct pci_dev *pdev)
uio_unregister_device(info);
pci_release_regions(pdev);
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
iounmap(info->priv);
kfree(info);
diff --git a/drivers/uio/uio_cif.c b/drivers/uio/uio_cif.c
index 22cdf385ab33..30f533ce3758 100644
--- a/drivers/uio/uio_cif.c
+++ b/drivers/uio/uio_cif.c
@@ -106,7 +106,6 @@ static void hilscher_pci_remove(struct pci_dev *dev)
uio_unregister_device(info);
pci_release_regions(dev);
pci_disable_device(dev);
- pci_set_drvdata(dev, NULL);
iounmap(info->mem[0].internal_addr);
kfree (info);
diff --git a/drivers/uio/uio_mf624.c b/drivers/uio/uio_mf624.c
index a1768b2f4493..f764adbfe036 100644
--- a/drivers/uio/uio_mf624.c
+++ b/drivers/uio/uio_mf624.c
@@ -42,7 +42,7 @@
enum mf624_interrupt_source {ADC, CTR4, ALL};
-void mf624_disable_interrupt(enum mf624_interrupt_source source,
+static void mf624_disable_interrupt(enum mf624_interrupt_source source,
struct uio_info *info)
{
void __iomem *INTCSR_reg = info->mem[0].internal_addr + INTCSR;
@@ -70,7 +70,7 @@ void mf624_disable_interrupt(enum mf624_interrupt_source source,
}
}
-void mf624_enable_interrupt(enum mf624_interrupt_source source,
+static void mf624_enable_interrupt(enum mf624_interrupt_source source,
struct uio_info *info)
{
void __iomem *INTCSR_reg = info->mem[0].internal_addr + INTCSR;
@@ -220,7 +220,6 @@ static void mf624_pci_remove(struct pci_dev *dev)
uio_unregister_device(info);
pci_release_regions(dev);
pci_disable_device(dev);
- pci_set_drvdata(dev, NULL);
iounmap(info->mem[0].internal_addr);
iounmap(info->mem[1].internal_addr);
diff --git a/drivers/uio/uio_netx.c b/drivers/uio/uio_netx.c
index 28a766b9e198..4c345db8b016 100644
--- a/drivers/uio/uio_netx.c
+++ b/drivers/uio/uio_netx.c
@@ -127,7 +127,6 @@ static void netx_pci_remove(struct pci_dev *dev)
uio_unregister_device(info);
pci_release_regions(dev);
pci_disable_device(dev);
- pci_set_drvdata(dev, NULL);
iounmap(info->mem[0].internal_addr);
kfree(info);
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c
index 90ff17a0202f..76669313e9a7 100644
--- a/drivers/uio/uio_pdrv_genirq.c
+++ b/drivers/uio/uio_pdrv_genirq.c
@@ -112,11 +112,11 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
if (pdev->dev.of_node) {
/* alloc uioinfo for one device */
- uioinfo = kzalloc(sizeof(*uioinfo), GFP_KERNEL);
+ uioinfo = devm_kzalloc(&pdev->dev, sizeof(*uioinfo),
+ GFP_KERNEL);
if (!uioinfo) {
- ret = -ENOMEM;
dev_err(&pdev->dev, "unable to kmalloc\n");
- return ret;
+ return -ENOMEM;
}
uioinfo->name = pdev->dev.of_node->name;
uioinfo->version = "devicetree";
@@ -125,20 +125,19 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
if (!uioinfo || !uioinfo->name || !uioinfo->version) {
dev_err(&pdev->dev, "missing platform_data\n");
- goto bad0;
+ return ret;
}
if (uioinfo->handler || uioinfo->irqcontrol ||
uioinfo->irq_flags & IRQF_SHARED) {
dev_err(&pdev->dev, "interrupt configuration error\n");
- goto bad0;
+ return ret;
}
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) {
- ret = -ENOMEM;
dev_err(&pdev->dev, "unable to kmalloc\n");
- goto bad0;
+ return -ENOMEM;
}
priv->uioinfo = uioinfo;
@@ -153,7 +152,7 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
uioinfo->irq = UIO_IRQ_NONE;
else if (ret < 0) {
dev_err(&pdev->dev, "failed to get IRQ\n");
- goto bad1;
+ return ret;
}
}
@@ -209,20 +208,12 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
ret = uio_register_device(&pdev->dev, priv->uioinfo);
if (ret) {
dev_err(&pdev->dev, "unable to register uio device\n");
- goto bad2;
+ pm_runtime_disable(&pdev->dev);
+ return ret;
}
platform_set_drvdata(pdev, priv);
return 0;
- bad2:
- pm_runtime_disable(&pdev->dev);
- bad1:
- kfree(priv);
- bad0:
- /* kfree uioinfo for OF */
- if (pdev->dev.of_node)
- kfree(uioinfo);
- return ret;
}
static int uio_pdrv_genirq_remove(struct platform_device *pdev)
@@ -235,11 +226,6 @@ static int uio_pdrv_genirq_remove(struct platform_device *pdev)
priv->uioinfo->handler = NULL;
priv->uioinfo->irqcontrol = NULL;
- /* kfree uioinfo for OF */
- if (pdev->dev.of_node)
- kfree(priv->uioinfo);
-
- kfree(priv);
return 0;
}
diff --git a/drivers/uio/uio_sercos3.c b/drivers/uio/uio_sercos3.c
index 541983217085..9cfdfcafa262 100644
--- a/drivers/uio/uio_sercos3.c
+++ b/drivers/uio/uio_sercos3.c
@@ -188,7 +188,6 @@ static void sercos3_pci_remove(struct pci_dev *dev)
uio_unregister_device(info);
pci_release_regions(dev);
pci_disable_device(dev);
- pci_set_drvdata(dev, NULL);
for (i = 0; i < 5; i++) {
if (info->mem[i].internal_addr)
iounmap(info->mem[i].internal_addr);
diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig
index 4a851e15e58c..77b47d82c9a6 100644
--- a/drivers/usb/chipidea/Kconfig
+++ b/drivers/usb/chipidea/Kconfig
@@ -1,6 +1,6 @@
config USB_CHIPIDEA
tristate "ChipIdea Highspeed Dual Role Controller"
- depends on (USB_EHCI_HCD && USB_GADGET) || (USB_EHCI_HCD && !USB_GADGET) || (!USB_EHCI_HCD && USB_GADGET)
+ depends on ((USB_EHCI_HCD && USB_GADGET) || (USB_EHCI_HCD && !USB_GADGET) || (!USB_EHCI_HCD && USB_GADGET)) && HAS_DMA
help
Say Y here if your system has a dual role high speed USB
controller based on ChipIdea silicon IP. Currently, only the
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 74d998d9b45b..be822a2c1776 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -131,7 +131,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n",
ret);
- goto err_clk;
+ goto err_phy;
}
}
@@ -143,7 +143,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"Can't register ci_hdrc platform device, err=%d\n",
ret);
- goto err_clk;
+ goto err_phy;
}
if (data->usbmisc_data) {
@@ -164,6 +164,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
disable_device:
ci_hdrc_remove_device(data->ci_pdev);
+err_phy:
+ if (data->phy)
+ usb_phy_shutdown(data->phy);
err_clk:
clk_disable_unprepare(data->clk);
return ret;
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 94626409559a..c47a6b46dea3 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -381,6 +381,15 @@ static int ci_get_platdata(struct device *dev,
return PTR_ERR(platdata->reg_vbus);
}
+ if (!platdata->phy_mode)
+ platdata->phy_mode = of_usb_get_phy_mode(dev->of_node);
+
+ if (!platdata->dr_mode)
+ platdata->dr_mode = of_usb_get_dr_mode(dev->of_node);
+
+ if (platdata->dr_mode == USB_DR_MODE_UNKNOWN)
+ platdata->dr_mode = USB_DR_MODE_OTG;
+
return 0;
}
@@ -473,7 +482,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
void __iomem *base;
int ret;
enum usb_dr_mode dr_mode;
- struct device_node *of_node = dev->of_node ?: dev->parent->of_node;
if (!dev->platform_data) {
dev_err(dev, "platform data missing\n");
@@ -514,17 +522,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
ci_get_otg_capable(ci);
- if (!ci->platdata->phy_mode)
- ci->platdata->phy_mode = of_usb_get_phy_mode(of_node);
-
hw_phymode_configure(ci);
- if (!ci->platdata->dr_mode)
- ci->platdata->dr_mode = of_usb_get_dr_mode(of_node);
-
- if (ci->platdata->dr_mode == USB_DR_MODE_UNKNOWN)
- ci->platdata->dr_mode = USB_DR_MODE_OTG;
-
dr_mode = ci->platdata->dr_mode;
/* initialize role(s) before the interrupt is requested */
if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) {
@@ -605,6 +604,7 @@ static int ci_hdrc_remove(struct platform_device *pdev)
dbg_remove_files(ci);
free_irq(ci->irq, ci);
ci_role_destroy(ci);
+ kfree(ci->hw_bank.regmap);
return 0;
}
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 6b4c2f2eb946..b157c95f7a36 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -686,9 +686,6 @@ static int _gadget_stop_activity(struct usb_gadget *gadget)
usb_ep_fifo_flush(&ci->ep0out->ep);
usb_ep_fifo_flush(&ci->ep0in->ep);
- if (ci->driver)
- ci->driver->disconnect(gadget);
-
/* make sure to disable all endpoints */
gadget_for_each_ep(ep, gadget) {
usb_ep_disable(ep);
@@ -717,6 +714,11 @@ __acquires(ci->lock)
{
int retval;
+ if (ci->gadget.speed != USB_SPEED_UNKNOWN) {
+ if (ci->driver)
+ ci->driver->disconnect(&ci->gadget);
+ }
+
spin_unlock(&ci->lock);
retval = _gadget_stop_activity(&ci->gadget);
if (retval)
@@ -1461,6 +1463,8 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
hw_device_state(ci, ci->ep0out->qh.dma);
dev_dbg(ci->dev, "Connected to host\n");
} else {
+ if (ci->driver)
+ ci->driver->disconnect(&ci->gadget);
hw_device_state(ci, 0);
if (ci->platdata->notify_event)
ci->platdata->notify_event(ci,
@@ -1600,6 +1604,8 @@ static void destroy_eps(struct ci_hdrc *ci)
for (i = 0; i < ci->hw_ep_max; i++) {
struct ci_hw_ep *hwep = &ci->ci_hw_ep[i];
+ if (hwep->pending_td)
+ free_pending_td(hwep);
dma_pool_free(ci->qh_pool, hwep->qh.ptr, hwep->qh.dma);
}
}
@@ -1667,13 +1673,13 @@ static int ci_udc_stop(struct usb_gadget *gadget,
if (ci->platdata->notify_event)
ci->platdata->notify_event(ci,
CI_HDRC_CONTROLLER_STOPPED_EVENT);
- ci->driver = NULL;
spin_unlock_irqrestore(&ci->lock, flags);
_gadget_stop_activity(&ci->gadget);
spin_lock_irqsave(&ci->lock, flags);
pm_runtime_put(&ci->gadget.dev);
}
+ ci->driver = NULL;
spin_unlock_irqrestore(&ci->lock, flags);
return 0;
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 737e3c19967b..bd429eaf6ea3 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -742,6 +742,22 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
if ((index & ~USB_DIR_IN) == 0)
return 0;
ret = findintfep(ps->dev, index);
+ if (ret < 0) {
+ /*
+ * Some not fully compliant Win apps seem to get
+ * index wrong and have the endpoint number here
+ * rather than the endpoint address (with the
+ * correct direction). Win does let this through,
+ * so we'll not reject it here but leave it to
+ * the device to not break KVM. But we warn.
+ */
+ ret = findintfep(ps->dev, index ^ 0x80);
+ if (ret >= 0)
+ dev_info(&ps->dev->dev,
+ "%s: process %i (%s) requesting ep %02x but needs %02x\n",
+ __func__, task_pid_nr(current),
+ current->comm, index, index ^ 0x80);
+ }
if (ret >= 0)
ret = checkintf(ps, ret);
break;
@@ -898,10 +914,8 @@ static int proc_control(struct dev_state *ps, void __user *arg)
snoop(&dev->dev, "control urb: bRequestType=%02x "
"bRequest=%02x wValue=%04x "
"wIndex=%04x wLength=%04x\n",
- ctrl.bRequestType, ctrl.bRequest,
- __le16_to_cpup(&ctrl.wValue),
- __le16_to_cpup(&ctrl.wIndex),
- __le16_to_cpup(&ctrl.wLength));
+ ctrl.bRequestType, ctrl.bRequest, ctrl.wValue,
+ ctrl.wIndex, ctrl.wLength);
if (ctrl.bRequestType & 0x80) {
if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data,
ctrl.wLength)) {
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index b9d3c43e3859..dfe9d0f22978 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -215,6 +215,9 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
goto disable_pci;
}
+ hcd->amd_resume_bug = (usb_hcd_amd_remote_wakeup_quirk(dev) &&
+ driver->flags & (HCD_USB11 | HCD_USB3)) ? 1 : 0;
+
if (driver->flags & HCD_MEMORY) {
/* EHCI, OHCI */
hcd->rsrc_start = pci_resource_start(dev, 0);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index d6a8d23f047b..9795a21bc612 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1033,6 +1033,7 @@ static int register_root_hub(struct usb_hcd *hcd)
dev_name(&usb_dev->dev), retval);
return retval;
}
+ usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev);
}
retval = usb_new_device (usb_dev);
@@ -1703,7 +1704,9 @@ static void usb_giveback_urb_bh(unsigned long param)
urb = list_entry(local_list.next, struct urb, urb_list);
list_del_init(&urb->urb_list);
+ bh->completing_ep = urb->ep;
__usb_hcd_giveback_urb(urb);
+ bh->completing_ep = NULL;
}
/* check if there are new URBs to giveback */
@@ -2073,8 +2076,11 @@ EXPORT_SYMBOL_GPL(usb_alloc_streams);
*
* Reverts a group of bulk endpoints back to not using stream IDs.
* Can fail if we are given bad arguments, or HCD is broken.
+ *
+ * Return: On success, the number of allocated streams. On failure, a negative
+ * error code.
*/
-void usb_free_streams(struct usb_interface *interface,
+int usb_free_streams(struct usb_interface *interface,
struct usb_host_endpoint **eps, unsigned int num_eps,
gfp_t mem_flags)
{
@@ -2085,14 +2091,14 @@ void usb_free_streams(struct usb_interface *interface,
dev = interface_to_usbdev(interface);
hcd = bus_to_hcd(dev->bus);
if (dev->speed != USB_SPEED_SUPER)
- return;
+ return -EINVAL;
/* Streams only apply to bulk endpoints. */
for (i = 0; i < num_eps; i++)
if (!eps[i] || !usb_endpoint_xfer_bulk(&eps[i]->desc))
- return;
+ return -EINVAL;
- hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags);
+ return hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags);
}
EXPORT_SYMBOL_GPL(usb_free_streams);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index dde4c83516a1..2159f820b159 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -135,7 +135,7 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev)
return usb_get_intfdata(hdev->actconfig->interface[0]);
}
-static int usb_device_supports_lpm(struct usb_device *udev)
+int usb_device_supports_lpm(struct usb_device *udev)
{
/* USB 2.1 (and greater) devices indicate LPM support through
* their USB 2.0 Extended Capabilities BOS descriptor.
@@ -156,6 +156,11 @@ static int usb_device_supports_lpm(struct usb_device *udev)
"Power management will be impacted.\n");
return 0;
}
+
+ /* udev is root hub */
+ if (!udev->parent)
+ return 1;
+
if (udev->parent->lpm_capable)
return 1;
@@ -310,9 +315,9 @@ static void usb_set_lpm_parameters(struct usb_device *udev)
return;
udev_u1_del = udev->bos->ss_cap->bU1devExitLat;
- udev_u2_del = udev->bos->ss_cap->bU2DevExitLat;
+ udev_u2_del = le16_to_cpu(udev->bos->ss_cap->bU2DevExitLat);
hub_u1_del = udev->parent->bos->ss_cap->bU1devExitLat;
- hub_u2_del = udev->parent->bos->ss_cap->bU2DevExitLat;
+ hub_u2_del = le16_to_cpu(udev->parent->bos->ss_cap->bU2DevExitLat);
usb_set_lpm_mel(udev, &udev->u1_params, udev_u1_del,
hub, &udev->parent->u1_params, hub_u1_del);
@@ -2018,8 +2023,8 @@ static void hub_free_dev(struct usb_device *udev)
* Something got disconnected. Get rid of it and all of its children.
*
* If *pdev is a normal device then the parent hub must already be locked.
- * If *pdev is a root hub then this routine will acquire the
- * usb_bus_list_lock on behalf of the caller.
+ * If *pdev is a root hub then the caller must hold the usb_bus_list_lock,
+ * which protects the set of root hubs as well as the list of buses.
*
* Only hub drivers (including virtual root hub drivers for host
* controllers) should ever call this.
@@ -3426,6 +3431,9 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state)
unsigned long long u2_pel;
int ret;
+ if (udev->state != USB_STATE_CONFIGURED)
+ return 0;
+
/* Convert SEL and PEL stored in ns to us */
u1_sel = DIV_ROUND_UP(udev->u1_params.sel, 1000);
u1_pel = DIV_ROUND_UP(udev->u1_params.pel, 1000);
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 5b44cd47da5b..d120a0887202 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -13,6 +13,7 @@
#include <linux/usb.h>
#include <linux/usb/quirks.h>
+#include <linux/usb/hcd.h>
#include "usb.h"
/* Lists of quirky USB devices, split in device quirks and interface quirks.
@@ -155,6 +156,21 @@ static const struct usb_device_id usb_interface_quirk_list[] = {
{ } /* terminating entry must be last */
};
+static const struct usb_device_id usb_amd_resume_quirk_list[] = {
+ /* Lenovo Mouse with Pixart controller */
+ { USB_DEVICE(0x17ef, 0x602e), .driver_info = USB_QUIRK_RESET_RESUME },
+
+ /* Pixart Mouse */
+ { USB_DEVICE(0x093a, 0x2500), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(0x093a, 0x2510), .driver_info = USB_QUIRK_RESET_RESUME },
+ { USB_DEVICE(0x093a, 0x2521), .driver_info = USB_QUIRK_RESET_RESUME },
+
+ /* Logitech Optical Mouse M90/M100 */
+ { USB_DEVICE(0x046d, 0xc05a), .driver_info = USB_QUIRK_RESET_RESUME },
+
+ { } /* terminating entry must be last */
+};
+
static bool usb_match_any_interface(struct usb_device *udev,
const struct usb_device_id *id)
{
@@ -181,6 +197,18 @@ static bool usb_match_any_interface(struct usb_device *udev,
return false;
}
+static int usb_amd_resume_quirk(struct usb_device *udev)
+{
+ struct usb_hcd *hcd;
+
+ hcd = bus_to_hcd(udev->bus);
+ /* The device should be attached directly to root hub */
+ if (udev->level == 1 && hcd->amd_resume_bug == 1)
+ return 1;
+
+ return 0;
+}
+
static u32 __usb_detect_quirks(struct usb_device *udev,
const struct usb_device_id *id)
{
@@ -206,6 +234,15 @@ static u32 __usb_detect_quirks(struct usb_device *udev,
void usb_detect_quirks(struct usb_device *udev)
{
udev->quirks = __usb_detect_quirks(udev, usb_quirk_list);
+
+ /*
+ * Pixart-based mice would trigger remote wakeup issue on AMD
+ * Yangtze chipset, so set them as RESET_RESUME flag.
+ */
+ if (usb_amd_resume_quirk(udev))
+ udev->quirks |= __usb_detect_quirks(udev,
+ usb_amd_resume_quirk_list);
+
if (udev->quirks)
dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
udev->quirks);
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 6d2c8edb1ffe..59cb5f99467a 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -23,14 +23,16 @@ static ssize_t field##_show(struct device *dev, \
{ \
struct usb_device *udev; \
struct usb_host_config *actconfig; \
+ ssize_t rc = 0; \
\
udev = to_usb_device(dev); \
+ usb_lock_device(udev); \
actconfig = udev->actconfig; \
if (actconfig) \
- return sprintf(buf, format_string, \
+ rc = sprintf(buf, format_string, \
actconfig->desc.field); \
- else \
- return 0; \
+ usb_unlock_device(udev); \
+ return rc; \
} \
#define usb_actconfig_attr(field, format_string) \
@@ -45,12 +47,15 @@ static ssize_t bMaxPower_show(struct device *dev,
{
struct usb_device *udev;
struct usb_host_config *actconfig;
+ ssize_t rc = 0;
udev = to_usb_device(dev);
+ usb_lock_device(udev);
actconfig = udev->actconfig;
- if (!actconfig)
- return 0;
- return sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig));
+ if (actconfig)
+ rc = sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig));
+ usb_unlock_device(udev);
+ return rc;
}
static DEVICE_ATTR_RO(bMaxPower);
@@ -59,12 +64,15 @@ static ssize_t configuration_show(struct device *dev,
{
struct usb_device *udev;
struct usb_host_config *actconfig;
+ ssize_t rc = 0;
udev = to_usb_device(dev);
+ usb_lock_device(udev);
actconfig = udev->actconfig;
- if ((!actconfig) || (!actconfig->string))
- return 0;
- return sprintf(buf, "%s\n", actconfig->string);
+ if (actconfig && actconfig->string)
+ rc = sprintf(buf, "%s\n", actconfig->string);
+ usb_unlock_device(udev);
+ return rc;
}
static DEVICE_ATTR_RO(configuration);
@@ -764,6 +772,7 @@ read_descriptors(struct file *filp, struct kobject *kobj,
* Following that are the raw descriptor entries for all the
* configurations (config plus subsidiary descriptors).
*/
+ usb_lock_device(udev);
for (cfgno = -1; cfgno < udev->descriptor.bNumConfigurations &&
nleft > 0; ++cfgno) {
if (cfgno < 0) {
@@ -784,6 +793,7 @@ read_descriptors(struct file *filp, struct kobject *kobj,
off -= srclen;
}
}
+ usb_unlock_device(udev);
return count - nleft;
}
@@ -870,9 +880,7 @@ static ssize_t interface_show(struct device *dev, struct device_attribute *attr,
char *string;
intf = to_usb_interface(dev);
- string = intf->cur_altsetting->string;
- barrier(); /* The altsetting might change! */
-
+ string = ACCESS_ONCE(intf->cur_altsetting->string);
if (!string)
return 0;
return sprintf(buf, "%s\n", string);
@@ -888,7 +896,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
intf = to_usb_interface(dev);
udev = interface_to_usbdev(intf);
- alt = intf->cur_altsetting;
+ alt = ACCESS_ONCE(intf->cur_altsetting);
return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X"
"ic%02Xisc%02Xip%02Xin%02X\n",
@@ -909,23 +917,14 @@ static ssize_t supports_autosuspend_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct usb_interface *intf;
- struct usb_device *udev;
- int ret;
+ int s;
- intf = to_usb_interface(dev);
- udev = interface_to_usbdev(intf);
-
- usb_lock_device(udev);
+ device_lock(dev);
/* Devices will be autosuspended even when an interface isn't claimed */
- if (!intf->dev.driver ||
- to_usb_driver(intf->dev.driver)->supports_autosuspend)
- ret = sprintf(buf, "%u\n", 1);
- else
- ret = sprintf(buf, "%u\n", 0);
- usb_unlock_device(udev);
+ s = (!dev->driver || to_usb_driver(dev->driver)->supports_autosuspend);
+ device_unlock(dev);
- return ret;
+ return sprintf(buf, "%u\n", s);
}
static DEVICE_ATTR_RO(supports_autosuspend);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 823857767a16..c49383669cd8 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -35,6 +35,7 @@ extern int usb_get_device_descriptor(struct usb_device *dev,
unsigned int size);
extern int usb_get_bos_descriptor(struct usb_device *dev);
extern void usb_release_bos_descriptor(struct usb_device *dev);
+extern int usb_device_supports_lpm(struct usb_device *udev);
extern char *usb_cache_string(struct usb_device *udev, int index);
extern int usb_set_configuration(struct usb_device *dev, int configuration);
extern int usb_choose_configuration(struct usb_device *udev);
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index 997ebe420bc9..31443aeedcdb 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -29,6 +29,7 @@
#define PCI_VENDOR_ID_SYNOPSYS 0x16c3
#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd
#define PCI_DEVICE_ID_INTEL_BYT 0x0f37
+#define PCI_DEVICE_ID_INTEL_MRFLD 0x119e
struct dwc3_pci {
struct device *dev;
@@ -164,7 +165,6 @@ static int dwc3_pci_probe(struct pci_dev *pci,
return 0;
err3:
- pci_set_drvdata(pci, NULL);
platform_device_put(dwc3);
err1:
pci_disable_device(pci);
@@ -179,7 +179,6 @@ static void dwc3_pci_remove(struct pci_dev *pci)
platform_device_unregister(glue->dwc3);
platform_device_unregister(glue->usb2_phy);
platform_device_unregister(glue->usb3_phy);
- pci_set_drvdata(pci, NULL);
pci_disable_device(pci);
}
@@ -189,6 +188,7 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3),
},
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c
index 5e29ddeb4d33..8cfc3191be50 100644
--- a/drivers/usb/early/ehci-dbgp.c
+++ b/drivers/usb/early/ehci-dbgp.c
@@ -568,10 +568,6 @@ try_again:
dbgp_printk("Could not find attached debug device\n");
goto err;
}
- if (ret < 0) {
- dbgp_printk("Attached device is not a debug device\n");
- goto err;
- }
dbgp_endpoint_out = dbgp_desc.bDebugOutEndpoint;
dbgp_endpoint_in = dbgp_desc.bDebugInEndpoint;
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index a9a4346c83aa..54a1e2954cea 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -3078,8 +3078,6 @@ static void udc_pci_remove(struct pci_dev *pdev)
if (dev->active)
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
-
udc_remove(dev);
}
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 1a66c5baa0d1..0658908d8968 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -1034,37 +1034,19 @@ struct ffs_sb_fill_data {
struct ffs_file_perms perms;
umode_t root_mode;
const char *dev_name;
- union {
- /* set by ffs_fs_mount(), read by ffs_sb_fill() */
- void *private_data;
- /* set by ffs_sb_fill(), read by ffs_fs_mount */
- struct ffs_data *ffs_data;
- };
+ struct ffs_data *ffs_data;
};
static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
{
struct ffs_sb_fill_data *data = _data;
struct inode *inode;
- struct ffs_data *ffs;
+ struct ffs_data *ffs = data->ffs_data;
ENTER();
- /* Initialise data */
- ffs = ffs_data_new();
- if (unlikely(!ffs))
- goto Enomem;
-
ffs->sb = sb;
- ffs->dev_name = kstrdup(data->dev_name, GFP_KERNEL);
- if (unlikely(!ffs->dev_name))
- goto Enomem;
- ffs->file_perms = data->perms;
- ffs->private_data = data->private_data;
-
- /* used by the caller of this function */
- data->ffs_data = ffs;
-
+ data->ffs_data = NULL;
sb->s_fs_info = ffs;
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
@@ -1080,17 +1062,14 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
&data->perms);
sb->s_root = d_make_root(inode);
if (unlikely(!sb->s_root))
- goto Enomem;
+ return -ENOMEM;
/* EP0 file */
if (unlikely(!ffs_sb_create_file(sb, "ep0", ffs,
&ffs_ep0_operations, NULL)))
- goto Enomem;
+ return -ENOMEM;
return 0;
-
-Enomem:
- return -ENOMEM;
}
static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts)
@@ -1193,6 +1172,7 @@ ffs_fs_mount(struct file_system_type *t, int flags,
struct dentry *rv;
int ret;
void *ffs_dev;
+ struct ffs_data *ffs;
ENTER();
@@ -1200,18 +1180,30 @@ ffs_fs_mount(struct file_system_type *t, int flags,
if (unlikely(ret < 0))
return ERR_PTR(ret);
+ ffs = ffs_data_new();
+ if (unlikely(!ffs))
+ return ERR_PTR(-ENOMEM);
+ ffs->file_perms = data.perms;
+
+ ffs->dev_name = kstrdup(dev_name, GFP_KERNEL);
+ if (unlikely(!ffs->dev_name)) {
+ ffs_data_put(ffs);
+ return ERR_PTR(-ENOMEM);
+ }
+
ffs_dev = functionfs_acquire_dev_callback(dev_name);
- if (IS_ERR(ffs_dev))
- return ffs_dev;
+ if (IS_ERR(ffs_dev)) {
+ ffs_data_put(ffs);
+ return ERR_CAST(ffs_dev);
+ }
+ ffs->private_data = ffs_dev;
+ data.ffs_data = ffs;
- data.dev_name = dev_name;
- data.private_data = ffs_dev;
rv = mount_nodev(t, flags, &data, ffs_sb_fill);
-
- /* data.ffs_data is set by ffs_sb_fill */
- if (IS_ERR(rv))
+ if (IS_ERR(rv) && data.ffs_data) {
functionfs_release_dev_callback(data.ffs_data);
-
+ ffs_data_put(data.ffs_data);
+ }
return rv;
}
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index c64deb9e3d62..74bb8df82876 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1701,7 +1701,6 @@ static void goku_remove(struct pci_dev *pdev)
if (dev->enabled)
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
dev->regs = NULL;
INFO(dev, "unbind\n");
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 0781bff70015..9fbc8fe5ecc0 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -2680,7 +2680,6 @@ static void net2280_remove (struct pci_dev *pdev)
if (dev->enabled)
pci_disable_device (pdev);
device_remove_file (&pdev->dev, &dev_attr_registers);
- pci_set_drvdata (pdev, NULL);
INFO (dev, "unbind\n");
}
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index 24174e1d1564..32d5e923750b 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -3080,7 +3080,6 @@ static void pch_udc_remove(struct pci_dev *pdev)
if (dev->active)
pci_disable_device(pdev);
kfree(dev);
- pci_set_drvdata(pdev, NULL);
}
#ifdef CONFIG_PM
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index cc9207473dbc..0ac6064aa3b8 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -2054,7 +2054,7 @@ static struct pxa25x_udc memory = {
/*
* probe - binds to the platform device
*/
-static int __init pxa25x_udc_probe(struct platform_device *pdev)
+static int pxa25x_udc_probe(struct platform_device *pdev)
{
struct pxa25x_udc *dev = &memory;
int retval, irq;
@@ -2203,7 +2203,7 @@ static void pxa25x_udc_shutdown(struct platform_device *_dev)
pullup_off();
}
-static int __exit pxa25x_udc_remove(struct platform_device *pdev)
+static int pxa25x_udc_remove(struct platform_device *pdev)
{
struct pxa25x_udc *dev = platform_get_drvdata(pdev);
@@ -2294,7 +2294,8 @@ static int pxa25x_udc_resume(struct platform_device *dev)
static struct platform_driver udc_driver = {
.shutdown = pxa25x_udc_shutdown,
- .remove = __exit_p(pxa25x_udc_remove),
+ .probe = pxa25x_udc_probe,
+ .remove = pxa25x_udc_remove,
.suspend = pxa25x_udc_suspend,
.resume = pxa25x_udc_resume,
.driver = {
@@ -2303,7 +2304,7 @@ static struct platform_driver udc_driver = {
},
};
-module_platform_driver_probe(udc_driver, pxa25x_udc_probe);
+module_platform_driver(udc_driver);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR("Frank Becker, Robert Schwebel, David Brownell");
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index 08a1a3210a21..cd1431d850c4 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -450,11 +450,11 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
* If we can't read the file, it's no good.
* If we can't write the file, use it read-only.
*/
- if (!(filp->f_op->read || filp->f_op->aio_read)) {
+ if (!file_readable(filp)) {
LINFO(curlun, "file not readable: %s\n", filename);
goto out;
}
- if (!(filp->f_op->write || filp->f_op->aio_write))
+ if (!file_writable(filp))
ro = 1;
size = i_size_read(inode->i_mapping->host);
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index b3f20d7f15de..70cb1a94beff 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -54,7 +54,7 @@ config USB_EHCI_HCD
config USB_EHCI_ROOT_HUB_TT
bool "Root Hub Transaction Translators"
- depends on USB_EHCI_HCD || USB_CHIPIDEA_HOST
+ depends on USB_EHCI_HCD
---help---
Some EHCI chips have vendor-specific extensions to integrate
transaction translators, so that no OHCI or UHCI companion
@@ -66,7 +66,7 @@ config USB_EHCI_ROOT_HUB_TT
config USB_EHCI_TT_NEWSCHED
bool "Improved Transaction Translator scheduling"
- depends on USB_EHCI_HCD || USB_CHIPIDEA_HOST
+ depends on USB_EHCI_HCD
default y
---help---
This changes the periodic scheduling code to fill more of the low
@@ -224,7 +224,7 @@ config USB_EHCI_MV
on-chip EHCI USB controller" for those.
config USB_W90X900_EHCI
- bool "W90X900(W90P910) EHCI support"
+ tristate "W90X900(W90P910) EHCI support"
depends on ARCH_W90X900
---help---
Enables support for the W90X900 USB controller
@@ -367,14 +367,62 @@ config USB_OHCI_HCD
if USB_OHCI_HCD
config USB_OHCI_HCD_OMAP1
- bool "OHCI support for OMAP1/2 chips"
+ tristate "OHCI support for OMAP1/2 chips"
depends on ARCH_OMAP1
default y
---help---
Enables support for the OHCI controller on OMAP1/2 chips.
+config USB_OHCI_HCD_SPEAR
+ tristate "Support for ST SPEAr on-chip OHCI USB controller"
+ depends on USB_OHCI_HCD && PLAT_SPEAR
+ default y
+ ---help---
+ Enables support for the on-chip OHCI controller on
+ ST SPEAr chips.
+
+config USB_OHCI_HCD_S3C2410
+ tristate "OHCI support for Samsung S3C24xx/S3C64xx SoC series"
+ depends on USB_OHCI_HCD && (ARCH_S3C24XX || ARCH_S3C64XX)
+ default y
+ ---help---
+ Enables support for the on-chip OHCI controller on
+ S3C24xx/S3C64xx chips.
+
+config USB_OHCI_HCD_LPC32XX
+ tristate "Support for LPC on-chip OHCI USB controller"
+ depends on USB_OHCI_HCD && ARCH_LPC32XX
+ default y
+ ---help---
+ Enables support for the on-chip OHCI controller on
+ NXP chips.
+
+config USB_OHCI_HCD_EP93XX
+ tristate "Support for EP93XX on-chip OHCI USB controller"
+ depends on USB_OHCI_HCD && ARCH_EP93XX
+ default y
+ ---help---
+ Enables support for the on-chip OHCI controller on
+ EP93XX chips.
+
+config USB_OHCI_HCD_PXA27X
+ tristate "Support for PXA27X/PXA3XX on-chip OHCI USB controller"
+ depends on USB_OHCI_HCD && (PXA27x || PXA3xx)
+ default y
+ ---help---
+ Enables support for the on-chip OHCI controller on
+ PXA27x/PXA3xx chips.
+
+config USB_OHCI_HCD_AT91
+ tristate "Support for Atmel on-chip OHCI USB controller"
+ depends on USB_OHCI_HCD && ARCH_AT91
+ default y
+ ---help---
+ Enables support for the on-chip OHCI controller on
+ Atmel chips.
+
config USB_OHCI_HCD_OMAP3
- bool "OHCI support for OMAP3 and later chips"
+ tristate "OHCI support for OMAP3 and later chips"
depends on (ARCH_OMAP3 || ARCH_OMAP4)
default y
---help---
@@ -454,8 +502,8 @@ config USB_OHCI_SH
If you use the PCI OHCI controller, this option is not necessary.
config USB_OHCI_EXYNOS
- boolean "OHCI support for Samsung EXYNOS SoC Series"
- depends on ARCH_EXYNOS
+ tristate "OHCI support for Samsung S5P/EXYNOS SoC Series"
+ depends on PLAT_S5P || ARCH_EXYNOS
help
Enable support for the Samsung Exynos SOC's on-chip OHCI controller.
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 50b0041c09a9..0b9fdeecf683 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_USB_EHCI_S5P) += ehci-s5p.o
obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o
obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o
+obj-$(CONFIG_USB_W90X900_EHCI) += ehci-w90x900.o
obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
@@ -46,6 +47,15 @@ obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
obj-$(CONFIG_USB_OHCI_HCD_PCI) += ohci-pci.o
obj-$(CONFIG_USB_OHCI_HCD_PLATFORM) += ohci-platform.o
+obj-$(CONFIG_USB_OHCI_EXYNOS) += ohci-exynos.o
+obj-$(CONFIG_USB_OHCI_HCD_OMAP1) += ohci-omap.o
+obj-$(CONFIG_USB_OHCI_HCD_OMAP3) += ohci-omap3.o
+obj-$(CONFIG_USB_OHCI_HCD_SPEAR) += ohci-spear.o
+obj-$(CONFIG_USB_OHCI_HCD_AT91) += ohci-at91.o
+obj-$(CONFIG_USB_OHCI_HCD_S3C2410) += ohci-s3c2410.o
+obj-$(CONFIG_USB_OHCI_HCD_LPC32XX) += ohci-nxp.o
+obj-$(CONFIG_USB_OHCI_HCD_EP93XX) += ohci-ep93xx.o
+obj-$(CONFIG_USB_OHCI_HCD_PXA27X) += ohci-pxa27x.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o
obj-$(CONFIG_USB_FHCI_HCD) += fhci.o
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 4449f565d6c6..a06d5012201f 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -57,7 +57,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
pr_debug("initializing FSL-SOC USB Controller\n");
/* Need platform data for setup */
- pdata = (struct fsl_usb2_platform_data *)dev_get_platdata(&pdev->dev);
+ pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_err(&pdev->dev,
"No platform data for %s.\n", dev_name(&pdev->dev));
@@ -130,7 +130,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
}
/* Enable USB controller, 83xx or 8536 */
- if (pdata->have_sysif_regs)
+ if (pdata->have_sysif_regs && pdata->controller_ver < FSL_USB_VER_1_6)
setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
/* Don't need to set host mode here. It will be done by tdi_reset() */
@@ -232,15 +232,9 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
case FSL_USB2_PHY_ULPI:
if (pdata->have_sysif_regs && pdata->controller_ver) {
/* controller version 1.6 or above */
+ clrbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
setbits32(non_ehci + FSL_SOC_USB_CTRL,
- ULPI_PHY_CLK_SEL);
- /*
- * Due to controller issue of PHY_CLK_VALID in ULPI
- * mode, we set USB_CTRL_USB_EN before checking
- * PHY_CLK_VALID, otherwise PHY_CLK_VALID doesn't work.
- */
- clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
- UTMI_PHY_EN, USB_CTRL_USB_EN);
+ ULPI_PHY_CLK_SEL | USB_CTRL_USB_EN);
}
portsc |= PORT_PTS_ULPI;
break;
@@ -270,8 +264,9 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
if (pdata->have_sysif_regs && pdata->controller_ver &&
(phy_mode == FSL_USB2_PHY_ULPI)) {
/* check PHY_CLK_VALID to get phy clk valid */
- if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
- PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) {
+ if (!(spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
+ PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0) ||
+ in_be32(non_ehci + FSL_SOC_USB_PRICTRL))) {
printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n");
return -EINVAL;
}
@@ -669,7 +664,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
* generic hardware linkage
*/
.irq = ehci_irq,
- .flags = HCD_USB2 | HCD_MEMORY,
+ .flags = HCD_USB2 | HCD_MEMORY | HCD_BH,
/*
* basic lifecycle operations
diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c
index 83ab51af250f..b52a66ce92e8 100644
--- a/drivers/usb/host/ehci-grlib.c
+++ b/drivers/usb/host/ehci-grlib.c
@@ -43,7 +43,7 @@ static const struct hc_driver ehci_grlib_hc_driver = {
* generic hardware linkage
*/
.irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
+ .flags = HCD_MEMORY | HCD_USB2 | HCD_BH,
/*
* basic lifecycle operations
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 86ab9fd9fe9e..3e3ca839e6ce 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1158,7 +1158,7 @@ static const struct hc_driver ehci_hc_driver = {
* generic hardware linkage
*/
.irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
+ .flags = HCD_MEMORY | HCD_USB2 | HCD_BH,
/*
* basic lifecycle operations
@@ -1238,11 +1238,6 @@ MODULE_LICENSE ("GPL");
#define XILINX_OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver
#endif
-#ifdef CONFIG_USB_W90X900_EHCI
-#include "ehci-w90x900.c"
-#define PLATFORM_DRIVER ehci_hcd_w90x900_driver
-#endif
-
#ifdef CONFIG_USB_OCTEON_EHCI
#include "ehci-octeon.c"
#define PLATFORM_DRIVER ehci_octeon_driver
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index 35cdbd88bbbe..417c10da9450 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -96,7 +96,7 @@ static const struct hc_driver mv_ehci_hc_driver = {
* generic hardware linkage
*/
.irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
+ .flags = HCD_MEMORY | HCD_USB2 | HCD_BH,
/*
* basic lifecycle operations
diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c
index 45cc00158412..ab0397e4d8f3 100644
--- a/drivers/usb/host/ehci-octeon.c
+++ b/drivers/usb/host/ehci-octeon.c
@@ -51,7 +51,7 @@ static const struct hc_driver ehci_octeon_hc_driver = {
* generic hardware linkage
*/
.irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
+ .flags = HCD_MEMORY | HCD_USB2 | HCD_BH,
/*
* basic lifecycle operations
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 6bd299e61f58..854c2ec7b699 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -361,7 +361,7 @@ static struct pci_driver ehci_pci_driver = {
.remove = usb_hcd_pci_remove,
.shutdown = usb_hcd_pci_shutdown,
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
.driver = {
.pm = &usb_hcd_pci_pm_ops
},
diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c
index 601e208bd782..893b707f0000 100644
--- a/drivers/usb/host/ehci-pmcmsp.c
+++ b/drivers/usb/host/ehci-pmcmsp.c
@@ -286,7 +286,7 @@ static const struct hc_driver ehci_msp_hc_driver = {
#else
.irq = ehci_irq,
#endif
- .flags = HCD_MEMORY | HCD_USB2,
+ .flags = HCD_MEMORY | HCD_USB2 | HCD_BH,
/*
* basic lifecycle operations
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
index 932293fa32de..6cc5567bf9c8 100644
--- a/drivers/usb/host/ehci-ppc-of.c
+++ b/drivers/usb/host/ehci-ppc-of.c
@@ -28,7 +28,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
* generic hardware linkage
*/
.irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
+ .flags = HCD_MEMORY | HCD_USB2 | HCD_BH,
/*
* basic lifecycle operations
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index fd983771b025..8188542ba17e 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -71,7 +71,7 @@ static const struct hc_driver ps3_ehci_hc_driver = {
.product_desc = "PS3 EHCI Host Controller",
.hcd_priv_size = sizeof(struct ehci_hcd),
.irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
+ .flags = HCD_MEMORY | HCD_USB2 | HCD_BH,
.reset = ps3_ehci_hc_reset,
.start = ehci_run,
.stop = ehci_stop,
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index a7f776a13eb1..e321804c3475 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -247,8 +247,6 @@ static int qtd_copy_status (
static void
ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status)
-__releases(ehci->lock)
-__acquires(ehci->lock)
{
if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
/* ... update hc-wide periodic stats */
@@ -274,11 +272,8 @@ __acquires(ehci->lock)
urb->actual_length, urb->transfer_buffer_length);
#endif
- /* complete() can reenter this HCD */
usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
- spin_unlock (&ehci->lock);
usb_hcd_giveback_urb(ehci_to_hcd(ehci), urb, status);
- spin_lock (&ehci->lock);
}
static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 85dd24ed97a6..dcbaad94d607 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1370,10 +1370,12 @@ iso_stream_schedule (
struct ehci_iso_stream *stream
)
{
- u32 now, base, next, start, period, span;
- int status;
+ u32 now, base, next, start, period, span, now2;
+ u32 wrap = 0, skip = 0;
+ int status = 0;
unsigned mod = ehci->periodic_size << 3;
struct ehci_iso_sched *sched = urb->hcpriv;
+ bool empty = list_empty(&stream->td_list);
period = urb->interval;
span = sched->span;
@@ -1384,69 +1386,31 @@ iso_stream_schedule (
now = ehci_read_frame_index(ehci) & (mod - 1);
- /* Typical case: reuse current schedule, stream is still active.
- * Hopefully there are no gaps from the host falling behind
- * (irq delays etc). If there are, the behavior depends on
- * whether URB_ISO_ASAP is set.
- */
- if (likely (!list_empty (&stream->td_list))) {
-
- /* Take the isochronous scheduling threshold into account */
- if (ehci->i_thresh)
- next = now + ehci->i_thresh; /* uframe cache */
- else
- next = (now + 2 + 7) & ~0x07; /* full frame cache */
-
- /*
- * Use ehci->last_iso_frame as the base. There can't be any
- * TDs scheduled for earlier than that.
- */
- base = ehci->last_iso_frame << 3;
- next = (next - base) & (mod - 1);
- start = (stream->next_uframe - base) & (mod - 1);
-
- /* Is the schedule already full? */
- if (unlikely(start < period)) {
- ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n",
- urb, stream->next_uframe, base,
- period, mod);
- status = -ENOSPC;
- goto fail;
- }
-
- /* Behind the scheduling threshold? */
- if (unlikely(start < next)) {
- unsigned now2 = (now - base) & (mod - 1);
-
- /* USB_ISO_ASAP: Round up to the first available slot */
- if (urb->transfer_flags & URB_ISO_ASAP)
- start += (next - start + period - 1) & -period;
-
- /*
- * Not ASAP: Use the next slot in the stream,
- * no matter what.
- */
- else if (start + span - period < now2) {
- ehci_dbg(ehci, "iso underrun %p (%u+%u < %u)\n",
- urb, start + base,
- span - period, now2 + base);
- }
- }
+ /* Take the isochronous scheduling threshold into account */
+ if (ehci->i_thresh)
+ next = now + ehci->i_thresh; /* uframe cache */
+ else
+ next = (now + 2 + 7) & ~0x07; /* full frame cache */
- start += base;
- }
+ /*
+ * Use ehci->last_iso_frame as the base. There can't be any
+ * TDs scheduled for earlier than that.
+ */
+ base = ehci->last_iso_frame << 3;
+ next = (next - base) & (mod - 1);
- /* need to schedule; when's the next (u)frame we could start?
- * this is bigger than ehci->i_thresh allows; scheduling itself
- * isn't free, the delay should handle reasonably slow cpus. it
+ /*
+ * Need to schedule; when's the next (u)frame we could start?
+ * This is bigger than ehci->i_thresh allows; scheduling itself
+ * isn't free, the delay should handle reasonably slow cpus. It
* can also help high bandwidth if the dma and irq loads don't
* jump until after the queue is primed.
*/
- else {
+ if (unlikely(empty && !hcd_periodic_completion_in_progress(
+ ehci_to_hcd(ehci), urb->ep))) {
int done = 0;
- base = now & ~0x07;
- start = base + SCHEDULING_DELAY;
+ start = (now & ~0x07) + SCHEDULING_DELAY;
/* find a uframe slot with enough bandwidth.
* Early uframes are more precious because full-speed
@@ -1477,27 +1441,96 @@ iso_stream_schedule (
status = -ENOSPC;
goto fail;
}
+
+ start = (start - base) & (mod - 1);
+ goto use_start;
}
+ /*
+ * Typical case: reuse current schedule, stream is still active.
+ * Hopefully there are no gaps from the host falling behind
+ * (irq delays etc). If there are, the behavior depends on
+ * whether URB_ISO_ASAP is set.
+ */
+ start = (stream->next_uframe - base) & (mod - 1);
+ now2 = (now - base) & (mod - 1);
+
+ /* Is the schedule already full? */
+ if (unlikely(!empty && start < period)) {
+ ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n",
+ urb, stream->next_uframe, base, period, mod);
+ status = -ENOSPC;
+ goto fail;
+ }
+
+ /* Is the next packet scheduled after the base time? */
+ if (likely(!empty || start <= now2 + period)) {
+
+ /* URB_ISO_ASAP: make sure that start >= next */
+ if (unlikely(start < next &&
+ (urb->transfer_flags & URB_ISO_ASAP)))
+ goto do_ASAP;
+
+ /* Otherwise use start, if it's not in the past */
+ if (likely(start >= now2))
+ goto use_start;
+
+ /* Otherwise we got an underrun while the queue was empty */
+ } else {
+ if (urb->transfer_flags & URB_ISO_ASAP)
+ goto do_ASAP;
+ wrap = mod;
+ now2 += mod;
+ }
+
+ /* How many uframes and packets do we need to skip? */
+ skip = (now2 - start + period - 1) & -period;
+ if (skip >= span) { /* Entirely in the past? */
+ ehci_dbg(ehci, "iso underrun %p (%u+%u < %u) [%u]\n",
+ urb, start + base, span - period, now2 + base,
+ base);
+
+ /* Try to keep the last TD intact for scanning later */
+ skip = span - period;
+
+ /* Will it come before the current scan position? */
+ if (empty) {
+ skip = span; /* Skip the entire URB */
+ status = 1; /* and give it back immediately */
+ iso_sched_free(stream, sched);
+ sched = NULL;
+ }
+ }
+ urb->error_count = skip / period;
+ if (sched)
+ sched->first_packet = urb->error_count;
+ goto use_start;
+
+ do_ASAP:
+ /* Use the first slot after "next" */
+ start = next + ((start - next) & (period - 1));
+
+ use_start:
/* Tried to schedule too far into the future? */
- if (unlikely(start - base + span - period >= mod)) {
+ if (unlikely(start + span - period >= mod + wrap)) {
ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n",
- urb, start - base, span - period, mod);
+ urb, start, span - period, mod + wrap);
status = -EFBIG;
goto fail;
}
- stream->next_uframe = start & (mod - 1);
+ start += base;
+ stream->next_uframe = (start + skip) & (mod - 1);
/* report high speed start in uframes; full speed, in frames */
- urb->start_frame = stream->next_uframe;
+ urb->start_frame = start & (mod - 1);
if (!stream->highspeed)
urb->start_frame >>= 3;
/* Make sure scan_isoc() sees these */
if (ehci->isoc_count == 0)
ehci->last_iso_frame = now >> 3;
- return 0;
+ return status;
fail:
iso_sched_free(stream, sched);
@@ -1610,7 +1643,8 @@ static void itd_link_urb(
ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
/* fill iTDs uframe by uframe */
- for (packet = 0, itd = NULL; packet < urb->number_of_packets; ) {
+ for (packet = iso_sched->first_packet, itd = NULL;
+ packet < urb->number_of_packets;) {
if (itd == NULL) {
/* ASSERT: we have all necessary itds */
// BUG_ON (list_empty (&iso_sched->td_list));
@@ -1804,10 +1838,14 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
if (unlikely(status))
goto done_not_linked;
status = iso_stream_schedule(ehci, urb, stream);
- if (likely (status == 0))
+ if (likely(status == 0)) {
itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
- else
+ } else if (status > 0) {
+ status = 0;
+ ehci_urb_done(ehci, urb, 0);
+ } else {
usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
+ }
done_not_linked:
spin_unlock_irqrestore (&ehci->lock, flags);
done:
@@ -2008,7 +2046,7 @@ static void sitd_link_urb(
ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
/* fill sITDs frame by frame */
- for (packet = 0, sitd = NULL;
+ for (packet = sched->first_packet, sitd = NULL;
packet < urb->number_of_packets;
packet++) {
@@ -2178,10 +2216,14 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
if (unlikely(status))
goto done_not_linked;
status = iso_stream_schedule(ehci, urb, stream);
- if (status == 0)
+ if (likely(status == 0)) {
sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
- else
+ } else if (status > 0) {
+ status = 0;
+ ehci_urb_done(ehci, urb, 0);
+ } else {
usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
+ }
done_not_linked:
spin_unlock_irqrestore (&ehci->lock, flags);
done:
diff --git a/drivers/usb/host/ehci-sead3.c b/drivers/usb/host/ehci-sead3.c
index b2de52d39614..8a734498079b 100644
--- a/drivers/usb/host/ehci-sead3.c
+++ b/drivers/usb/host/ehci-sead3.c
@@ -55,7 +55,7 @@ const struct hc_driver ehci_sead3_hc_driver = {
* generic hardware linkage
*/
.irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
+ .flags = HCD_MEMORY | HCD_USB2 | HCD_BH,
/*
* basic lifecycle operations
diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c
index 93e59a13bc1f..dc899eb2b861 100644
--- a/drivers/usb/host/ehci-sh.c
+++ b/drivers/usb/host/ehci-sh.c
@@ -36,7 +36,7 @@ static const struct hc_driver ehci_sh_hc_driver = {
* generic hardware linkage
*/
.irq = ehci_irq,
- .flags = HCD_USB2 | HCD_MEMORY,
+ .flags = HCD_USB2 | HCD_MEMORY | HCD_BH,
/*
* basic lifecycle operations
diff --git a/drivers/usb/host/ehci-tilegx.c b/drivers/usb/host/ehci-tilegx.c
index cca4be90a864..67026ffbf9a8 100644
--- a/drivers/usb/host/ehci-tilegx.c
+++ b/drivers/usb/host/ehci-tilegx.c
@@ -61,7 +61,7 @@ static const struct hc_driver ehci_tilegx_hc_driver = {
* Generic hardware linkage.
*/
.irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
+ .flags = HCD_MEMORY | HCD_USB2 | HCD_BH,
/*
* Basic lifecycle operations.
diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c
index 59e0e24c753f..cdad8438c02b 100644
--- a/drivers/usb/host/ehci-w90x900.c
+++ b/drivers/usb/host/ehci-w90x900.c
@@ -11,13 +11,28 @@
*
*/
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ehci.h"
/* enable phy0 and phy1 for w90p910 */
#define ENPHY (0x01<<8)
#define PHY0_CTR (0xA4)
#define PHY1_CTR (0xA8)
+#define DRIVER_DESC "EHCI w90x900 driver"
+
+static const char hcd_name[] = "ehci-w90x900 ";
+
+static struct hc_driver __read_mostly ehci_w90x900_hc_driver;
+
static int usb_w90x900_probe(const struct hc_driver *driver,
struct platform_device *pdev)
{
@@ -90,8 +105,8 @@ err1:
return retval;
}
-static
-void usb_w90x900_remove(struct usb_hcd *hcd, struct platform_device *pdev)
+static void usb_w90x900_remove(struct usb_hcd *hcd,
+ struct platform_device *pdev)
{
usb_remove_hcd(hcd);
iounmap(hcd->regs);
@@ -99,54 +114,6 @@ void usb_w90x900_remove(struct usb_hcd *hcd, struct platform_device *pdev)
usb_put_hcd(hcd);
}
-static const struct hc_driver ehci_w90x900_hc_driver = {
- .description = hcd_name,
- .product_desc = "Nuvoton w90x900 EHCI Host Controller",
- .hcd_priv_size = sizeof(struct ehci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ehci_irq,
- .flags = HCD_USB2|HCD_MEMORY,
-
- /*
- * basic lifecycle operations
- */
- .reset = ehci_setup,
- .start = ehci_run,
-
- .stop = ehci_stop,
- .shutdown = ehci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ehci_urb_enqueue,
- .urb_dequeue = ehci_urb_dequeue,
- .endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
-
- /*
- * scheduling support
- */
- .get_frame_number = ehci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ehci_hub_status_data,
- .hub_control = ehci_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
-#endif
- .relinquish_port = ehci_relinquish_port,
- .port_handed_over = ehci_port_handed_over,
-
- .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
static int ehci_w90x900_probe(struct platform_device *pdev)
{
if (usb_disabled())
@@ -173,7 +140,25 @@ static struct platform_driver ehci_hcd_w90x900_driver = {
},
};
+static int __init ehci_w90X900_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+ ehci_init_driver(&ehci_w90x900_hc_driver, NULL);
+ return platform_driver_register(&ehci_hcd_w90x900_driver);
+}
+module_init(ehci_w90X900_init);
+
+static void __exit ehci_w90X900_cleanup(void)
+{
+ platform_driver_unregister(&ehci_hcd_w90x900_driver);
+}
+module_exit(ehci_w90X900_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
-MODULE_DESCRIPTION("w90p910 usb ehci driver!");
-MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:w90p910-ehci");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
index eba962e6ebfb..95979f9f4381 100644
--- a/drivers/usb/host/ehci-xilinx-of.c
+++ b/drivers/usb/host/ehci-xilinx-of.c
@@ -79,7 +79,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = {
* generic hardware linkage
*/
.irq = ehci_irq,
- .flags = HCD_MEMORY | HCD_USB2,
+ .flags = HCD_MEMORY | HCD_USB2 | HCD_BH,
/*
* basic lifecycle operations
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 291db7d09f22..2d401927e143 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -434,6 +434,7 @@ struct ehci_iso_packet {
struct ehci_iso_sched {
struct list_head td_list;
unsigned span;
+ unsigned first_packet;
struct ehci_iso_packet packet [0];
};
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
index 60a5de505ca1..adb01d950a16 100644
--- a/drivers/usb/host/imx21-hcd.c
+++ b/drivers/usb/host/imx21-hcd.c
@@ -824,13 +824,13 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
i = DIV_ROUND_UP(wrap_frame(
cur_frame - urb->start_frame),
urb->interval);
- if (urb->transfer_flags & URB_ISO_ASAP) {
+
+ /* Treat underruns as if URB_ISO_ASAP was set */
+ if ((urb->transfer_flags & URB_ISO_ASAP) ||
+ i >= urb->number_of_packets) {
urb->start_frame = wrap_frame(urb->start_frame
+ i * urb->interval);
i = 0;
- } else if (i >= urb->number_of_packets) {
- ret = -EXDEV;
- goto alloc_dmem_failed;
}
}
}
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index caa3764a3407..476b5a5baf25 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -13,19 +13,24 @@
*/
#include <linux/clk.h>
-#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
#include <linux/platform_data/atmel.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
#include <mach/hardware.h>
#include <asm/gpio.h>
#include <mach/cpu.h>
-#ifndef CONFIG_ARCH_AT91
-#error "CONFIG_ARCH_AT91 must be defined."
-#endif
+
+#include "ohci.h"
#define valid_port(index) ((index) >= 0 && (index) < AT91_MAX_USBH_PORTS)
#define at91_for_each_port(index) \
@@ -33,7 +38,17 @@
/* interface, function and usb clocks; sometimes also an AHB clock */
static struct clk *iclk, *fclk, *uclk, *hclk;
+/* interface and function clocks; sometimes also an AHB clock */
+
+#define DRIVER_DESC "OHCI Atmel driver"
+
+static const char hcd_name[] = "ohci-atmel";
+
+static struct hc_driver __read_mostly ohci_at91_hc_driver;
static int clocked;
+static int (*orig_ohci_hub_control)(struct usb_hcd *hcd, u16 typeReq,
+ u16 wValue, u16 wIndex, char *buf, u16 wLength);
+static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf);
extern int usb_disabled(void);
@@ -117,6 +132,8 @@ static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
static int usb_hcd_at91_probe(const struct hc_driver *driver,
struct platform_device *pdev)
{
+ struct at91_usbh_data *board;
+ struct ohci_hcd *ohci;
int retval;
struct usb_hcd *hcd = NULL;
@@ -177,8 +194,10 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
}
}
+ board = hcd->self.controller->platform_data;
+ ohci = hcd_to_ohci(hcd);
+ ohci->num_ports = board->ports;
at91_start_hc(pdev);
- ohci_hcd_init(hcd_to_ohci(hcd));
retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED);
if (retval == 0)
@@ -238,36 +257,6 @@ static void usb_hcd_at91_remove(struct usb_hcd *hcd,
}
/*-------------------------------------------------------------------------*/
-
-static int
-ohci_at91_reset (struct usb_hcd *hcd)
-{
- struct at91_usbh_data *board = dev_get_platdata(hcd->self.controller);
- struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- int ret;
-
- if ((ret = ohci_init(ohci)) < 0)
- return ret;
-
- ohci->num_ports = board->ports;
- return 0;
-}
-
-static int
-ohci_at91_start (struct usb_hcd *hcd)
-{
- struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- int ret;
-
- if ((ret = ohci_run(ohci)) < 0) {
- dev_err(hcd->self.controller, "can't start %s\n",
- hcd->self.bus_name);
- ohci_stop(hcd);
- return ret;
- }
- return 0;
-}
-
static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int enable)
{
if (!valid_port(port))
@@ -297,8 +286,8 @@ static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
*/
static int ohci_at91_hub_status_data(struct usb_hcd *hcd, char *buf)
{
- struct at91_usbh_data *pdata = dev_get_platdata(hcd->self.controller);
- int length = ohci_hub_status_data(hcd, buf);
+ struct at91_usbh_data *pdata = hcd->self.controller->platform_data;
+ int length = orig_ohci_hub_status_data(hcd, buf);
int port;
at91_for_each_port(port) {
@@ -376,7 +365,8 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
break;
}
- ret = ohci_hub_control(hcd, typeReq, wValue, wIndex + 1, buf, wLength);
+ ret = orig_ohci_hub_control(hcd, typeReq, wValue, wIndex + 1,
+ buf, wLength);
if (ret)
goto out;
@@ -430,51 +420,6 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
/*-------------------------------------------------------------------------*/
-static const struct hc_driver ohci_at91_hc_driver = {
- .description = hcd_name,
- .product_desc = "AT91 OHCI",
- .hcd_priv_size = sizeof(struct ohci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ohci_irq,
- .flags = HCD_USB11 | HCD_MEMORY,
-
- /*
- * basic lifecycle operations
- */
- .reset = ohci_at91_reset,
- .start = ohci_at91_start,
- .stop = ohci_stop,
- .shutdown = ohci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ohci_urb_enqueue,
- .urb_dequeue = ohci_urb_dequeue,
- .endpoint_disable = ohci_endpoint_disable,
-
- /*
- * scheduling support
- */
- .get_frame_number = ohci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ohci_at91_hub_status_data,
- .hub_control = ohci_at91_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ohci_bus_suspend,
- .bus_resume = ohci_bus_resume,
-#endif
- .start_port_reset = ohci_start_port_reset,
-};
-
-/*-------------------------------------------------------------------------*/
-
static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
{
struct platform_device *pdev = data;
@@ -703,7 +648,11 @@ ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg)
* REVISIT: some boards will be able to turn VBUS off...
*/
if (at91_suspend_entering_slow_clock()) {
- ohci_usb_reset (ohci);
+ ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
+ ohci->hc_control &= OHCI_CTRL_RWC;
+ ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
+ ohci->rh_state = OHCI_RH_HALTED;
+
/* flush the writes */
(void) ohci_readl (ohci, &ohci->regs->control);
at91_stop_clock();
@@ -730,8 +679,6 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
#define ohci_hcd_at91_drv_resume NULL
#endif
-MODULE_ALIAS("platform:at91_ohci");
-
static struct platform_driver ohci_hcd_at91_driver = {
.probe = ohci_hcd_at91_drv_probe,
.remove = ohci_hcd_at91_drv_remove,
@@ -744,3 +691,40 @@ static struct platform_driver ohci_hcd_at91_driver = {
.of_match_table = of_match_ptr(at91_ohci_dt_ids),
},
};
+
+static int __init ohci_at91_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+ ohci_init_driver(&ohci_at91_hc_driver, NULL);
+
+ /*
+ * The Atmel HW has some unusual quirks, which require Atmel-specific
+ * workarounds. We override certain hc_driver functions here to
+ * achieve that. We explicitly do not enhance ohci_driver_overrides to
+ * allow this more easily, since this is an unusual case, and we don't
+ * want to encourage others to override these functions by making it
+ * too easy.
+ */
+
+ orig_ohci_hub_control = ohci_at91_hc_driver.hub_control;
+ orig_ohci_hub_status_data = ohci_at91_hc_driver.hub_status_data;
+
+ ohci_at91_hc_driver.hub_status_data = ohci_at91_hub_status_data;
+ ohci_at91_hc_driver.hub_control = ohci_at91_hub_control;
+
+ return platform_driver_register(&ohci_hcd_at91_driver);
+}
+module_init(ohci_at91_init);
+
+static void __exit ohci_at91_cleanup(void)
+{
+ platform_driver_unregister(&ohci_hcd_at91_driver);
+}
+module_exit(ohci_at91_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:at91_ohci");
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
index 84a20d5223b9..492f681c70f2 100644
--- a/drivers/usb/host/ohci-ep93xx.c
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -25,50 +25,23 @@
#include <linux/clk.h>
#include <linux/device.h>
-#include <linux/signal.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/signal.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
-static struct clk *usb_host_clock;
+#include "ohci.h"
-static int ohci_ep93xx_start(struct usb_hcd *hcd)
-{
- struct ohci_hcd *ohci = hcd_to_ohci(hcd);
- int ret;
+#define DRIVER_DESC "OHCI EP93xx driver"
- if ((ret = ohci_init(ohci)) < 0)
- return ret;
+static const char hcd_name[] = "ohci-ep93xx";
- if ((ret = ohci_run(ohci)) < 0) {
- dev_err(hcd->self.controller, "can't start %s\n",
- hcd->self.bus_name);
- ohci_stop(hcd);
- return ret;
- }
+static struct hc_driver __read_mostly ohci_ep93xx_hc_driver;
- return 0;
-}
-
-static struct hc_driver ohci_ep93xx_hc_driver = {
- .description = hcd_name,
- .product_desc = "EP93xx OHCI",
- .hcd_priv_size = sizeof(struct ohci_hcd),
- .irq = ohci_irq,
- .flags = HCD_USB11 | HCD_MEMORY,
- .start = ohci_ep93xx_start,
- .stop = ohci_stop,
- .shutdown = ohci_shutdown,
- .urb_enqueue = ohci_urb_enqueue,
- .urb_dequeue = ohci_urb_dequeue,
- .endpoint_disable = ohci_endpoint_disable,
- .get_frame_number = ohci_get_frame,
- .hub_status_data = ohci_hub_status_data,
- .hub_control = ohci_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ohci_bus_suspend,
- .bus_resume = ohci_bus_resume,
-#endif
- .start_port_reset = ohci_start_port_reset,
-};
+static struct clk *usb_host_clock;
static int ohci_hcd_ep93xx_drv_probe(struct platform_device *pdev)
{
@@ -109,8 +82,6 @@ static int ohci_hcd_ep93xx_drv_probe(struct platform_device *pdev)
clk_enable(usb_host_clock);
- ohci_hcd_init(hcd_to_ohci(hcd));
-
ret = usb_add_hcd(hcd, irq, 0);
if (ret)
goto err_clk_disable;
@@ -166,7 +137,6 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
}
#endif
-
static struct platform_driver ohci_hcd_ep93xx_driver = {
.probe = ohci_hcd_ep93xx_drv_probe,
.remove = ohci_hcd_ep93xx_drv_remove,
@@ -181,4 +151,24 @@ static struct platform_driver ohci_hcd_ep93xx_driver = {
},
};
+static int __init ohci_ep93xx_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+ ohci_init_driver(&ohci_ep93xx_hc_driver, NULL);
+ return platform_driver_register(&ohci_hcd_ep93xx_driver);
+}
+module_init(ohci_ep93xx_init);
+
+static void __exit ohci_ep93xx_cleanup(void)
+{
+ platform_driver_unregister(&ohci_hcd_ep93xx_driver);
+}
+module_exit(ohci_ep93xx_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:ep93xx-ohci");
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index dc6ee9adacf5..3e4bc74f76ab 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -12,24 +12,39 @@
*/
#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/platform_data/usb-ohci-exynos.h>
#include <linux/usb/phy.h>
#include <linux/usb/samsung_usb_phy.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/otg.h>
+
+#include "ohci.h"
+
+#define DRIVER_DESC "OHCI EXYNOS driver"
+
+static const char hcd_name[] = "ohci-exynos";
+static struct hc_driver __read_mostly exynos_ohci_hc_driver;
+
+#define to_exynos_ohci(hcd) (struct exynos_ohci_hcd *)(hcd_to_ohci(hcd)->priv)
struct exynos_ohci_hcd {
- struct device *dev;
- struct usb_hcd *hcd;
struct clk *clk;
struct usb_phy *phy;
struct usb_otg *otg;
struct exynos4_ohci_platdata *pdata;
};
-static void exynos_ohci_phy_enable(struct exynos_ohci_hcd *exynos_ohci)
+static void exynos_ohci_phy_enable(struct platform_device *pdev)
{
- struct platform_device *pdev = to_platform_device(exynos_ohci->dev);
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
if (exynos_ohci->phy)
usb_phy_init(exynos_ohci->phy);
@@ -37,9 +52,10 @@ static void exynos_ohci_phy_enable(struct exynos_ohci_hcd *exynos_ohci)
exynos_ohci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
}
-static void exynos_ohci_phy_disable(struct exynos_ohci_hcd *exynos_ohci)
+static void exynos_ohci_phy_disable(struct platform_device *pdev)
{
- struct platform_device *pdev = to_platform_device(exynos_ohci->dev);
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
if (exynos_ohci->phy)
usb_phy_shutdown(exynos_ohci->phy);
@@ -47,63 +63,11 @@ static void exynos_ohci_phy_disable(struct exynos_ohci_hcd *exynos_ohci)
exynos_ohci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
}
-static int ohci_exynos_reset(struct usb_hcd *hcd)
-{
- return ohci_init(hcd_to_ohci(hcd));
-}
-
-static int ohci_exynos_start(struct usb_hcd *hcd)
-{
- struct ohci_hcd *ohci = hcd_to_ohci(hcd);
- int ret;
-
- ohci_dbg(ohci, "ohci_exynos_start, ohci:%p", ohci);
-
- ret = ohci_run(ohci);
- if (ret < 0) {
- dev_err(hcd->self.controller, "can't start %s\n",
- hcd->self.bus_name);
- ohci_stop(hcd);
- return ret;
- }
-
- return 0;
-}
-
-static const struct hc_driver exynos_ohci_hc_driver = {
- .description = hcd_name,
- .product_desc = "EXYNOS OHCI Host Controller",
- .hcd_priv_size = sizeof(struct ohci_hcd),
-
- .irq = ohci_irq,
- .flags = HCD_MEMORY|HCD_USB11,
-
- .reset = ohci_exynos_reset,
- .start = ohci_exynos_start,
- .stop = ohci_stop,
- .shutdown = ohci_shutdown,
-
- .get_frame_number = ohci_get_frame,
-
- .urb_enqueue = ohci_urb_enqueue,
- .urb_dequeue = ohci_urb_dequeue,
- .endpoint_disable = ohci_endpoint_disable,
-
- .hub_status_data = ohci_hub_status_data,
- .hub_control = ohci_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ohci_bus_suspend,
- .bus_resume = ohci_bus_resume,
-#endif
- .start_port_reset = ohci_start_port_reset,
-};
-
static int exynos_ohci_probe(struct platform_device *pdev)
{
struct exynos4_ohci_platdata *pdata = dev_get_platdata(&pdev->dev);
struct exynos_ohci_hcd *exynos_ohci;
struct usb_hcd *hcd;
- struct ohci_hcd *ohci;
struct resource *res;
struct usb_phy *phy;
int irq;
@@ -119,10 +83,14 @@ static int exynos_ohci_probe(struct platform_device *pdev)
if (!pdev->dev.coherent_dma_mask)
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
- exynos_ohci = devm_kzalloc(&pdev->dev, sizeof(struct exynos_ohci_hcd),
- GFP_KERNEL);
- if (!exynos_ohci)
+ hcd = usb_create_hcd(&exynos_ohci_hc_driver,
+ &pdev->dev, dev_name(&pdev->dev));
+ if (!hcd) {
+ dev_err(&pdev->dev, "Unable to create HCD\n");
return -ENOMEM;
+ }
+
+ exynos_ohci = to_exynos_ohci(hcd);
if (of_device_is_compatible(pdev->dev.of_node,
"samsung,exynos5440-ohci"))
@@ -143,17 +111,6 @@ static int exynos_ohci_probe(struct platform_device *pdev)
}
skip_phy:
-
- exynos_ohci->dev = &pdev->dev;
-
- hcd = usb_create_hcd(&exynos_ohci_hc_driver, &pdev->dev,
- dev_name(&pdev->dev));
- if (!hcd) {
- dev_err(&pdev->dev, "Unable to create HCD\n");
- return -ENOMEM;
- }
-
- exynos_ohci->hcd = hcd;
exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost");
if (IS_ERR(exynos_ohci->clk)) {
@@ -190,26 +147,21 @@ skip_phy:
}
if (exynos_ohci->otg)
- exynos_ohci->otg->set_host(exynos_ohci->otg,
- &exynos_ohci->hcd->self);
+ exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
- exynos_ohci_phy_enable(exynos_ohci);
+ platform_set_drvdata(pdev, hcd);
- ohci = hcd_to_ohci(hcd);
- ohci_hcd_init(ohci);
+ exynos_ohci_phy_enable(pdev);
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err) {
dev_err(&pdev->dev, "Failed to add USB HCD\n");
goto fail_add_hcd;
}
-
- platform_set_drvdata(pdev, exynos_ohci);
-
return 0;
fail_add_hcd:
- exynos_ohci_phy_disable(exynos_ohci);
+ exynos_ohci_phy_disable(pdev);
fail_io:
clk_disable_unprepare(exynos_ohci->clk);
fail_clk:
@@ -219,16 +171,15 @@ fail_clk:
static int exynos_ohci_remove(struct platform_device *pdev)
{
- struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev);
- struct usb_hcd *hcd = exynos_ohci->hcd;
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
usb_remove_hcd(hcd);
if (exynos_ohci->otg)
- exynos_ohci->otg->set_host(exynos_ohci->otg,
- &exynos_ohci->hcd->self);
+ exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
- exynos_ohci_phy_disable(exynos_ohci);
+ exynos_ohci_phy_disable(pdev);
clk_disable_unprepare(exynos_ohci->clk);
@@ -239,8 +190,7 @@ static int exynos_ohci_remove(struct platform_device *pdev)
static void exynos_ohci_shutdown(struct platform_device *pdev)
{
- struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev);
- struct usb_hcd *hcd = exynos_ohci->hcd;
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
if (hcd->driver->shutdown)
hcd->driver->shutdown(hcd);
@@ -249,9 +199,10 @@ static void exynos_ohci_shutdown(struct platform_device *pdev)
#ifdef CONFIG_PM
static int exynos_ohci_suspend(struct device *dev)
{
- struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev);
- struct usb_hcd *hcd = exynos_ohci->hcd;
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ struct platform_device *pdev = to_platform_device(dev);
unsigned long flags;
int rc = 0;
@@ -271,10 +222,9 @@ static int exynos_ohci_suspend(struct device *dev)
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
if (exynos_ohci->otg)
- exynos_ohci->otg->set_host(exynos_ohci->otg,
- &exynos_ohci->hcd->self);
+ exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
- exynos_ohci_phy_disable(exynos_ohci);
+ exynos_ohci_phy_disable(pdev);
clk_disable_unprepare(exynos_ohci->clk);
@@ -286,16 +236,16 @@ fail:
static int exynos_ohci_resume(struct device *dev)
{
- struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev);
- struct usb_hcd *hcd = exynos_ohci->hcd;
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
+ struct platform_device *pdev = to_platform_device(dev);
clk_prepare_enable(exynos_ohci->clk);
if (exynos_ohci->otg)
- exynos_ohci->otg->set_host(exynos_ohci->otg,
- &exynos_ohci->hcd->self);
+ exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
- exynos_ohci_phy_enable(exynos_ohci);
+ exynos_ohci_phy_enable(pdev);
ohci_resume(hcd, false);
@@ -306,6 +256,10 @@ static int exynos_ohci_resume(struct device *dev)
#define exynos_ohci_resume NULL
#endif
+static const struct ohci_driver_overrides exynos_overrides __initconst = {
+ .extra_priv_size = sizeof(struct exynos_ohci_hcd),
+};
+
static const struct dev_pm_ops exynos_ohci_pm_ops = {
.suspend = exynos_ohci_suspend,
.resume = exynos_ohci_resume,
@@ -331,6 +285,23 @@ static struct platform_driver exynos_ohci_driver = {
.of_match_table = of_match_ptr(exynos_ohci_match),
}
};
+static int __init ohci_exynos_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+ ohci_init_driver(&exynos_ohci_hc_driver, &exynos_overrides);
+ return platform_driver_register(&exynos_ohci_driver);
+}
+module_init(ohci_exynos_init);
+
+static void __exit ohci_exynos_cleanup(void)
+{
+ platform_driver_unregister(&exynos_ohci_driver);
+}
+module_exit(ohci_exynos_cleanup);
MODULE_ALIAS("platform:exynos-ohci");
MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 8f6b695af6a4..21d937a590e8 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -216,31 +216,26 @@ static int ohci_urb_enqueue (
frame &= ~(ed->interval - 1);
frame |= ed->branch;
urb->start_frame = frame;
+ ed->last_iso = frame + ed->interval * (size - 1);
}
} else if (ed->type == PIPE_ISOCHRONOUS) {
u16 next = ohci_frame_no(ohci) + 1;
u16 frame = ed->last_iso + ed->interval;
+ u16 length = ed->interval * (size - 1);
/* Behind the scheduling threshold? */
if (unlikely(tick_before(frame, next))) {
- /* USB_ISO_ASAP: Round up to the first available slot */
+ /* URB_ISO_ASAP: Round up to the first available slot */
if (urb->transfer_flags & URB_ISO_ASAP) {
frame += (next - frame + ed->interval - 1) &
-ed->interval;
/*
- * Not ASAP: Use the next slot in the stream. If
- * the entire URB falls before the threshold, fail.
+ * Not ASAP: Use the next slot in the stream,
+ * no matter what.
*/
} else {
- if (tick_before(frame + ed->interval *
- (urb->number_of_packets - 1), next)) {
- retval = -EXDEV;
- usb_hcd_unlink_urb_from_ep(hcd, urb);
- goto fail;
- }
-
/*
* Some OHCI hardware doesn't handle late TDs
* correctly. After retiring them it proceeds
@@ -251,9 +246,16 @@ static int ohci_urb_enqueue (
urb_priv->td_cnt = DIV_ROUND_UP(
(u16) (next - frame),
ed->interval);
+ if (urb_priv->td_cnt >= urb_priv->length) {
+ ++urb_priv->td_cnt; /* Mark it */
+ ohci_dbg(ohci, "iso underrun %p (%u+%u < %u)\n",
+ urb, frame, length,
+ next);
+ }
}
}
urb->start_frame = frame;
+ ed->last_iso = frame + length;
}
/* fill the TDs and link them to the ed; and
@@ -1177,46 +1179,6 @@ MODULE_LICENSE ("GPL");
#define SA1111_DRIVER ohci_hcd_sa1111_driver
#endif
-#if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S3C64XX)
-#include "ohci-s3c2410.c"
-#define S3C2410_PLATFORM_DRIVER ohci_hcd_s3c2410_driver
-#endif
-
-#ifdef CONFIG_USB_OHCI_EXYNOS
-#include "ohci-exynos.c"
-#define EXYNOS_PLATFORM_DRIVER exynos_ohci_driver
-#endif
-
-#ifdef CONFIG_USB_OHCI_HCD_OMAP1
-#include "ohci-omap.c"
-#define OMAP1_PLATFORM_DRIVER ohci_hcd_omap_driver
-#endif
-
-#ifdef CONFIG_USB_OHCI_HCD_OMAP3
-#include "ohci-omap3.c"
-#define OMAP3_PLATFORM_DRIVER ohci_hcd_omap3_driver
-#endif
-
-#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
-#include "ohci-pxa27x.c"
-#define PLATFORM_DRIVER ohci_hcd_pxa27x_driver
-#endif
-
-#ifdef CONFIG_ARCH_EP93XX
-#include "ohci-ep93xx.c"
-#define EP93XX_PLATFORM_DRIVER ohci_hcd_ep93xx_driver
-#endif
-
-#ifdef CONFIG_ARCH_AT91
-#include "ohci-at91.c"
-#define AT91_PLATFORM_DRIVER ohci_hcd_at91_driver
-#endif
-
-#ifdef CONFIG_ARCH_LPC32XX
-#include "ohci-nxp.c"
-#define NXP_PLATFORM_DRIVER usb_hcd_nxp_driver
-#endif
-
#ifdef CONFIG_ARCH_DAVINCI_DA8XX
#include "ohci-da8xx.c"
#define DAVINCI_PLATFORM_DRIVER ohci_hcd_da8xx_driver
@@ -1227,11 +1189,6 @@ MODULE_LICENSE ("GPL");
#define OF_PLATFORM_DRIVER ohci_hcd_ppc_of_driver
#endif
-#ifdef CONFIG_PLAT_SPEAR
-#include "ohci-spear.c"
-#define SPEAR_PLATFORM_DRIVER spear_ohci_hcd_driver
-#endif
-
#ifdef CONFIG_PPC_PS3
#include "ohci-ps3.c"
#define PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver
@@ -1294,18 +1251,6 @@ static int __init ohci_hcd_mod_init(void)
goto error_platform;
#endif
-#ifdef OMAP1_PLATFORM_DRIVER
- retval = platform_driver_register(&OMAP1_PLATFORM_DRIVER);
- if (retval < 0)
- goto error_omap1_platform;
-#endif
-
-#ifdef OMAP3_PLATFORM_DRIVER
- retval = platform_driver_register(&OMAP3_PLATFORM_DRIVER);
- if (retval < 0)
- goto error_omap3_platform;
-#endif
-
#ifdef OF_PLATFORM_DRIVER
retval = platform_driver_register(&OF_PLATFORM_DRIVER);
if (retval < 0)
@@ -1330,79 +1275,19 @@ static int __init ohci_hcd_mod_init(void)
goto error_tmio;
#endif
-#ifdef S3C2410_PLATFORM_DRIVER
- retval = platform_driver_register(&S3C2410_PLATFORM_DRIVER);
- if (retval < 0)
- goto error_s3c2410;
-#endif
-
-#ifdef EXYNOS_PLATFORM_DRIVER
- retval = platform_driver_register(&EXYNOS_PLATFORM_DRIVER);
- if (retval < 0)
- goto error_exynos;
-#endif
-
-#ifdef EP93XX_PLATFORM_DRIVER
- retval = platform_driver_register(&EP93XX_PLATFORM_DRIVER);
- if (retval < 0)
- goto error_ep93xx;
-#endif
-
-#ifdef AT91_PLATFORM_DRIVER
- retval = platform_driver_register(&AT91_PLATFORM_DRIVER);
- if (retval < 0)
- goto error_at91;
-#endif
-
-#ifdef NXP_PLATFORM_DRIVER
- retval = platform_driver_register(&NXP_PLATFORM_DRIVER);
- if (retval < 0)
- goto error_nxp;
-#endif
-
#ifdef DAVINCI_PLATFORM_DRIVER
retval = platform_driver_register(&DAVINCI_PLATFORM_DRIVER);
if (retval < 0)
goto error_davinci;
#endif
-#ifdef SPEAR_PLATFORM_DRIVER
- retval = platform_driver_register(&SPEAR_PLATFORM_DRIVER);
- if (retval < 0)
- goto error_spear;
-#endif
-
return retval;
/* Error path */
-#ifdef SPEAR_PLATFORM_DRIVER
- platform_driver_unregister(&SPEAR_PLATFORM_DRIVER);
- error_spear:
-#endif
#ifdef DAVINCI_PLATFORM_DRIVER
platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER);
error_davinci:
#endif
-#ifdef NXP_PLATFORM_DRIVER
- platform_driver_unregister(&NXP_PLATFORM_DRIVER);
- error_nxp:
-#endif
-#ifdef AT91_PLATFORM_DRIVER
- platform_driver_unregister(&AT91_PLATFORM_DRIVER);
- error_at91:
-#endif
-#ifdef EP93XX_PLATFORM_DRIVER
- platform_driver_unregister(&EP93XX_PLATFORM_DRIVER);
- error_ep93xx:
-#endif
-#ifdef EXYNOS_PLATFORM_DRIVER
- platform_driver_unregister(&EXYNOS_PLATFORM_DRIVER);
- error_exynos:
-#endif
-#ifdef S3C2410_PLATFORM_DRIVER
- platform_driver_unregister(&S3C2410_PLATFORM_DRIVER);
- error_s3c2410:
-#endif
#ifdef TMIO_OHCI_DRIVER
platform_driver_unregister(&TMIO_OHCI_DRIVER);
error_tmio:
@@ -1419,14 +1304,6 @@ static int __init ohci_hcd_mod_init(void)
platform_driver_unregister(&OF_PLATFORM_DRIVER);
error_of_platform:
#endif
-#ifdef OMAP3_PLATFORM_DRIVER
- platform_driver_unregister(&OMAP3_PLATFORM_DRIVER);
- error_omap3_platform:
-#endif
-#ifdef OMAP1_PLATFORM_DRIVER
- platform_driver_unregister(&OMAP1_PLATFORM_DRIVER);
- error_omap1_platform:
-#endif
#ifdef PLATFORM_DRIVER
platform_driver_unregister(&PLATFORM_DRIVER);
error_platform:
@@ -1448,27 +1325,9 @@ module_init(ohci_hcd_mod_init);
static void __exit ohci_hcd_mod_exit(void)
{
-#ifdef SPEAR_PLATFORM_DRIVER
- platform_driver_unregister(&SPEAR_PLATFORM_DRIVER);
-#endif
#ifdef DAVINCI_PLATFORM_DRIVER
platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER);
#endif
-#ifdef NXP_PLATFORM_DRIVER
- platform_driver_unregister(&NXP_PLATFORM_DRIVER);
-#endif
-#ifdef AT91_PLATFORM_DRIVER
- platform_driver_unregister(&AT91_PLATFORM_DRIVER);
-#endif
-#ifdef EP93XX_PLATFORM_DRIVER
- platform_driver_unregister(&EP93XX_PLATFORM_DRIVER);
-#endif
-#ifdef EXYNOS_PLATFORM_DRIVER
- platform_driver_unregister(&EXYNOS_PLATFORM_DRIVER);
-#endif
-#ifdef S3C2410_PLATFORM_DRIVER
- platform_driver_unregister(&S3C2410_PLATFORM_DRIVER);
-#endif
#ifdef TMIO_OHCI_DRIVER
platform_driver_unregister(&TMIO_OHCI_DRIVER);
#endif
@@ -1481,12 +1340,6 @@ static void __exit ohci_hcd_mod_exit(void)
#ifdef OF_PLATFORM_DRIVER
platform_driver_unregister(&OF_PLATFORM_DRIVER);
#endif
-#ifdef OMAP3_PLATFORM_DRIVER
- platform_driver_unregister(&OMAP3_PLATFORM_DRIVER);
-#endif
-#ifdef OMAP1_PLATFORM_DRIVER
- platform_driver_unregister(&OMAP1_PLATFORM_DRIVER);
-#endif
#ifdef PLATFORM_DRIVER
platform_driver_unregister(&PLATFORM_DRIVER);
#endif
diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c
index 7d7d507d54e8..9ab7e24ba65d 100644
--- a/drivers/usb/host/ohci-nxp.c
+++ b/drivers/usb/host/ohci-nxp.c
@@ -19,10 +19,19 @@
* or implied.
*/
#include <linux/clk.h>
-#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/of.h>
+#include <linux/platform_device.h>
#include <linux/usb/isp1301.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ohci.h"
+
#include <mach/hardware.h>
#include <asm/mach-types.h>
@@ -57,6 +66,11 @@
#define start_int_umask(irq)
#endif
+#define DRIVER_DESC "OHCI NXP driver"
+
+static const char hcd_name[] = "ohci-nxp";
+static struct hc_driver __read_mostly ohci_nxp_hc_driver;
+
static struct i2c_client *isp1301_i2c_client;
extern int usb_disabled(void);
@@ -132,14 +146,14 @@ static inline void isp1301_vbus_off(void)
OTG1_VBUS_DRV);
}
-static void nxp_start_hc(void)
+static void ohci_nxp_start_hc(void)
{
unsigned long tmp = __raw_readl(USB_OTG_STAT_CONTROL) | HOST_EN;
__raw_writel(tmp, USB_OTG_STAT_CONTROL);
isp1301_vbus_on();
}
-static void nxp_stop_hc(void)
+static void ohci_nxp_stop_hc(void)
{
unsigned long tmp;
isp1301_vbus_off();
@@ -147,68 +161,9 @@ static void nxp_stop_hc(void)
__raw_writel(tmp, USB_OTG_STAT_CONTROL);
}
-static int ohci_nxp_start(struct usb_hcd *hcd)
-{
- struct ohci_hcd *ohci = hcd_to_ohci(hcd);
- int ret;
-
- if ((ret = ohci_init(ohci)) < 0)
- return ret;
-
- if ((ret = ohci_run(ohci)) < 0) {
- dev_err(hcd->self.controller, "can't start\n");
- ohci_stop(hcd);
- return ret;
- }
- return 0;
-}
-
-static const struct hc_driver ohci_nxp_hc_driver = {
- .description = hcd_name,
- .product_desc = "nxp OHCI",
-
- /*
- * generic hardware linkage
- */
- .irq = ohci_irq,
- .flags = HCD_USB11 | HCD_MEMORY,
-
- .hcd_priv_size = sizeof(struct ohci_hcd),
- /*
- * basic lifecycle operations
- */
- .start = ohci_nxp_start,
- .stop = ohci_stop,
- .shutdown = ohci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ohci_urb_enqueue,
- .urb_dequeue = ohci_urb_dequeue,
- .endpoint_disable = ohci_endpoint_disable,
-
- /*
- * scheduling support
- */
- .get_frame_number = ohci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ohci_hub_status_data,
- .hub_control = ohci_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ohci_bus_suspend,
- .bus_resume = ohci_bus_resume,
-#endif
- .start_port_reset = ohci_start_port_reset,
-};
-
-static int usb_hcd_nxp_probe(struct platform_device *pdev)
+static int ohci_hcd_nxp_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd = 0;
- struct ohci_hcd *ohci;
const struct hc_driver *driver = &ohci_nxp_hc_driver;
struct resource *res;
int ret = 0, irq;
@@ -313,17 +268,15 @@ static int usb_hcd_nxp_probe(struct platform_device *pdev)
goto fail_resource;
}
- nxp_start_hc();
+ ohci_nxp_start_hc();
platform_set_drvdata(pdev, hcd);
- ohci = hcd_to_ohci(hcd);
- ohci_hcd_init(ohci);
dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq);
ret = usb_add_hcd(hcd, irq, 0);
if (ret == 0)
return ret;
- nxp_stop_hc();
+ ohci_nxp_stop_hc();
fail_resource:
usb_put_hcd(hcd);
fail_hcd:
@@ -345,12 +298,12 @@ fail_disable:
return ret;
}
-static int usb_hcd_nxp_remove(struct platform_device *pdev)
+static int ohci_hcd_nxp_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
usb_remove_hcd(hcd);
- nxp_stop_hc();
+ ohci_nxp_stop_hc();
usb_put_hcd(hcd);
clk_disable(usb_pll_clk);
clk_put(usb_pll_clk);
@@ -366,20 +319,40 @@ static int usb_hcd_nxp_remove(struct platform_device *pdev)
MODULE_ALIAS("platform:usb-ohci");
#ifdef CONFIG_OF
-static const struct of_device_id usb_hcd_nxp_match[] = {
+static const struct of_device_id ohci_hcd_nxp_match[] = {
{ .compatible = "nxp,ohci-nxp" },
{},
};
-MODULE_DEVICE_TABLE(of, usb_hcd_nxp_match);
+MODULE_DEVICE_TABLE(of, ohci_hcd_nxp_match);
#endif
-static struct platform_driver usb_hcd_nxp_driver = {
+static struct platform_driver ohci_hcd_nxp_driver = {
.driver = {
.name = "usb-ohci",
.owner = THIS_MODULE,
- .of_match_table = of_match_ptr(usb_hcd_nxp_match),
+ .of_match_table = of_match_ptr(ohci_hcd_nxp_match),
},
- .probe = usb_hcd_nxp_probe,
- .remove = usb_hcd_nxp_remove,
+ .probe = ohci_hcd_nxp_probe,
+ .remove = ohci_hcd_nxp_remove,
};
+static int __init ohci_nxp_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+ ohci_init_driver(&ohci_nxp_hc_driver, NULL);
+ return platform_driver_register(&ohci_hcd_nxp_driver);
+}
+module_init(ohci_nxp_init);
+
+static void __exit ohci_nxp_cleanup(void)
+{
+ platform_driver_unregister(&ohci_hcd_nxp_driver);
+}
+module_exit(ohci_nxp_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 31d3a12eb486..18b27a27e7dc 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -14,12 +14,21 @@
* This file is licenced under the GPL.
*/
-#include <linux/signal.h>
-#include <linux/jiffies.h>
-#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb/otg.h>
+#include <linux/platform_device.h>
+#include <linux/signal.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ohci.h"
#include <asm/io.h>
#include <asm/mach-types.h>
@@ -42,10 +51,7 @@
#define OMAP1510_LB_MMU_RAM_H 0xfffec234
#define OMAP1510_LB_MMU_RAM_L 0xfffec238
-
-#ifndef CONFIG_ARCH_OMAP
-#error "This file is OMAP bus glue. CONFIG_OMAP must be defined."
-#endif
+#define DRIVER_DESC "OHCI OMAP driver"
#ifdef CONFIG_TPS65010
#include <linux/i2c/tps65010.h>
@@ -68,8 +74,9 @@ extern int ocpi_enable(void);
static struct clk *usb_host_ck;
static struct clk *usb_dc_ck;
-static int host_enabled;
-static int host_initialized;
+
+static const char hcd_name[] = "ohci-omap";
+static struct hc_driver __read_mostly ohci_omap_hc_driver;
static void omap_ohci_clock_power(int on)
{
@@ -188,7 +195,7 @@ static void start_hnp(struct ohci_hcd *ohci)
/*-------------------------------------------------------------------------*/
-static int ohci_omap_init(struct usb_hcd *hcd)
+static int ohci_omap_reset(struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
struct omap_usb_config *config = dev_get_platdata(hcd->self.controller);
@@ -198,9 +205,9 @@ static int ohci_omap_init(struct usb_hcd *hcd)
dev_dbg(hcd->self.controller, "starting USB Controller\n");
if (config->otg) {
- ohci_to_hcd(ohci)->self.otg_port = config->otg;
+ hcd->self.otg_port = config->otg;
/* default/minimum OTG power budget: 8 mA */
- ohci_to_hcd(ohci)->power_budget = 8;
+ hcd->power_budget = 8;
}
/* boards can use OTG transceivers in non-OTG modes */
@@ -238,9 +245,15 @@ static int ohci_omap_init(struct usb_hcd *hcd)
omap_1510_local_bus_init();
}
- if ((ret = ohci_init(ohci)) < 0)
+ ret = ohci_setup(hcd);
+ if (ret < 0)
return ret;
+ if (config->otg || config->rwc) {
+ ohci->hc_control = OHCI_CTRL_RWC;
+ writel(OHCI_CTRL_RWC, &ohci->regs->control);
+ }
+
/* board-specific power switching and overcurrent support */
if (machine_is_omap_osk() || machine_is_omap_innovator()) {
u32 rh = roothub_a (ohci);
@@ -281,14 +294,6 @@ static int ohci_omap_init(struct usb_hcd *hcd)
return 0;
}
-static void ohci_omap_stop(struct usb_hcd *hcd)
-{
- dev_dbg(hcd->self.controller, "stopping USB Controller\n");
- ohci_stop(hcd);
- omap_ohci_clock_power(0);
-}
-
-
/*-------------------------------------------------------------------------*/
/**
@@ -304,7 +309,6 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver,
{
int retval, irq;
struct usb_hcd *hcd = 0;
- struct ohci_hcd *ohci;
if (pdev->num_resources != 2) {
printk(KERN_ERR "hcd probe: invalid num_resources: %i\n",
@@ -354,12 +358,6 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver,
goto err2;
}
- ohci = hcd_to_ohci(hcd);
- ohci_hcd_init(ohci);
-
- host_initialized = 0;
- host_enabled = 1;
-
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
retval = -ENXIO;
@@ -369,11 +367,6 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver,
if (retval)
goto err3;
- host_initialized = 1;
-
- if (!host_enabled)
- omap_ohci_clock_power(0);
-
return 0;
err3:
iounmap(hcd->regs);
@@ -402,7 +395,9 @@ err0:
static inline void
usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
{
+ dev_dbg(hcd->self.controller, "stopping USB Controller\n");
usb_remove_hcd(hcd);
+ omap_ohci_clock_power(0);
if (!IS_ERR_OR_NULL(hcd->phy)) {
(void) otg_set_host(hcd->phy->otg, 0);
usb_put_phy(hcd->phy);
@@ -418,76 +413,6 @@ usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
/*-------------------------------------------------------------------------*/
-static int
-ohci_omap_start (struct usb_hcd *hcd)
-{
- struct omap_usb_config *config;
- struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- int ret;
-
- if (!host_enabled)
- return 0;
- config = dev_get_platdata(hcd->self.controller);
- if (config->otg || config->rwc) {
- ohci->hc_control = OHCI_CTRL_RWC;
- writel(OHCI_CTRL_RWC, &ohci->regs->control);
- }
-
- if ((ret = ohci_run (ohci)) < 0) {
- dev_err(hcd->self.controller, "can't start\n");
- ohci_stop (hcd);
- return ret;
- }
- return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static const struct hc_driver ohci_omap_hc_driver = {
- .description = hcd_name,
- .product_desc = "OMAP OHCI",
- .hcd_priv_size = sizeof(struct ohci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ohci_irq,
- .flags = HCD_USB11 | HCD_MEMORY,
-
- /*
- * basic lifecycle operations
- */
- .reset = ohci_omap_init,
- .start = ohci_omap_start,
- .stop = ohci_omap_stop,
- .shutdown = ohci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ohci_urb_enqueue,
- .urb_dequeue = ohci_urb_dequeue,
- .endpoint_disable = ohci_endpoint_disable,
-
- /*
- * scheduling support
- */
- .get_frame_number = ohci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ohci_hub_status_data,
- .hub_control = ohci_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ohci_bus_suspend,
- .bus_resume = ohci_bus_resume,
-#endif
- .start_port_reset = ohci_start_port_reset,
-};
-
-/*-------------------------------------------------------------------------*/
-
static int ohci_hcd_omap_drv_probe(struct platform_device *dev)
{
return usb_hcd_omap_probe(&ohci_omap_hc_driver, dev);
@@ -553,4 +478,29 @@ static struct platform_driver ohci_hcd_omap_driver = {
},
};
+static const struct ohci_driver_overrides omap_overrides __initconst = {
+ .product_desc = "OMAP OHCI",
+ .reset = ohci_omap_reset
+};
+
+static int __init ohci_omap_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+ ohci_init_driver(&ohci_omap_hc_driver, &omap_overrides);
+ return platform_driver_register(&ohci_hcd_omap_driver);
+}
+module_init(ohci_omap_init);
+
+static void __exit ohci_omap_cleanup(void)
+{
+ platform_driver_unregister(&ohci_hcd_omap_driver);
+}
+module_exit(ohci_omap_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_ALIAS("platform:ohci");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
index a09af26f69ed..408d06a68571 100644
--- a/drivers/usb/host/ohci-omap3.c
+++ b/drivers/usb/host/ohci-omap3.c
@@ -29,90 +29,22 @@
* - add kernel-doc
*/
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/usb/otg.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#include <linux/of.h>
-#include <linux/dma-mapping.h>
-
-/*-------------------------------------------------------------------------*/
-
-static int ohci_omap3_init(struct usb_hcd *hcd)
-{
- dev_dbg(hcd->self.controller, "starting OHCI controller\n");
-
- return ohci_init(hcd_to_ohci(hcd));
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int ohci_omap3_start(struct usb_hcd *hcd)
-{
- struct ohci_hcd *ohci = hcd_to_ohci(hcd);
- int ret;
-
- /*
- * RemoteWakeupConnected has to be set explicitly before
- * calling ohci_run. The reset value of RWC is 0.
- */
- ohci->hc_control = OHCI_CTRL_RWC;
- writel(OHCI_CTRL_RWC, &ohci->regs->control);
-
- ret = ohci_run(ohci);
-
- if (ret < 0) {
- dev_err(hcd->self.controller, "can't start\n");
- ohci_stop(hcd);
- }
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
- return ret;
-}
+#include "ohci.h"
-/*-------------------------------------------------------------------------*/
+#define DRIVER_DESC "OHCI OMAP3 driver"
-static const struct hc_driver ohci_omap3_hc_driver = {
- .description = hcd_name,
- .product_desc = "OMAP3 OHCI Host Controller",
- .hcd_priv_size = sizeof(struct ohci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ohci_irq,
- .flags = HCD_USB11 | HCD_MEMORY,
-
- /*
- * basic lifecycle operations
- */
- .reset = ohci_omap3_init,
- .start = ohci_omap3_start,
- .stop = ohci_stop,
- .shutdown = ohci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ohci_urb_enqueue,
- .urb_dequeue = ohci_urb_dequeue,
- .endpoint_disable = ohci_endpoint_disable,
-
- /*
- * scheduling support
- */
- .get_frame_number = ohci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ohci_hub_status_data,
- .hub_control = ohci_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ohci_bus_suspend,
- .bus_resume = ohci_bus_resume,
-#endif
- .start_port_reset = ohci_start_port_reset,
-};
-
-/*-------------------------------------------------------------------------*/
+static const char hcd_name[] = "ohci-omap3";
+static struct hc_driver __read_mostly ohci_omap3_hc_driver;
/*
* configure so an HC device and id are always provided
@@ -129,6 +61,7 @@ static const struct hc_driver ohci_omap3_hc_driver = {
static int ohci_hcd_omap3_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct ohci_hcd *ohci;
struct usb_hcd *hcd = NULL;
void __iomem *regs = NULL;
struct resource *res;
@@ -185,7 +118,12 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
- ohci_hcd_init(hcd_to_ohci(hcd));
+ ohci = hcd_to_ohci(hcd);
+ /*
+ * RemoteWakeupConnected has to be set explicitly before
+ * calling ohci_run. The reset value of RWC is 0.
+ */
+ ohci->hc_control = OHCI_CTRL_RWC;
ret = usb_add_hcd(hcd, irq, 0);
if (ret) {
@@ -248,5 +186,25 @@ static struct platform_driver ohci_hcd_omap3_driver = {
},
};
+static int __init ohci_omap3_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+ ohci_init_driver(&ohci_omap3_hc_driver, NULL);
+ return platform_driver_register(&ohci_hcd_omap3_driver);
+}
+module_init(ohci_omap3_init);
+
+static void __exit ohci_omap3_cleanup(void)
+{
+ platform_driver_unregister(&ohci_hcd_omap3_driver);
+}
+module_exit(ohci_omap3_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_ALIAS("platform:ohci-omap3");
MODULE_AUTHOR("Anand Gadiyar <gadiyar@ti.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index ec337c2bd5e0..eedf97c1790e 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -323,3 +323,4 @@ module_exit(ohci_pci_cleanup);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
+MODULE_SOFTDEP("pre: ehci_pci");
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 93371a235e82..c1b1fa3047be 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -19,15 +19,26 @@
* This file is licenced under the GPL.
*/
-#include <linux/device.h>
-#include <linux/signal.h>
-#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
-#include <mach/hardware.h>
#include <linux/platform_data/usb-ohci-pxa27x.h>
#include <linux/platform_data/usb-pxa3xx-ulpi.h>
+#include <linux/platform_device.h>
+#include <linux/signal.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/otg.h>
+
+#include <mach/hardware.h>
+
+#include "ohci.h"
+
+#define DRIVER_DESC "OHCI PXA27x/PXA3x driver"
/*
* UHC: USB Host Controller (OHCI-like) register definitions
@@ -101,16 +112,16 @@
#define PXA_UHC_MAX_PORTNUM 3
-struct pxa27x_ohci {
- /* must be 1st member here for hcd_to_ohci() to work */
- struct ohci_hcd ohci;
+static const char hcd_name[] = "ohci-pxa27x";
- struct device *dev;
+static struct hc_driver __read_mostly ohci_pxa27x_hc_driver;
+
+struct pxa27x_ohci {
struct clk *clk;
void __iomem *mmio_base;
};
-#define to_pxa27x_ohci(hcd) (struct pxa27x_ohci *)hcd_to_ohci(hcd)
+#define to_pxa27x_ohci(hcd) (struct pxa27x_ohci *)(hcd_to_ohci(hcd)->priv)
/*
PMM_NPS_MODE -- PMM Non-power switching mode
@@ -122,10 +133,10 @@ struct pxa27x_ohci {
PMM_PERPORT_MODE -- PMM per port switching mode
Ports are powered individually.
*/
-static int pxa27x_ohci_select_pmm(struct pxa27x_ohci *ohci, int mode)
+static int pxa27x_ohci_select_pmm(struct pxa27x_ohci *pxa_ohci, int mode)
{
- uint32_t uhcrhda = __raw_readl(ohci->mmio_base + UHCRHDA);
- uint32_t uhcrhdb = __raw_readl(ohci->mmio_base + UHCRHDB);
+ uint32_t uhcrhda = __raw_readl(pxa_ohci->mmio_base + UHCRHDA);
+ uint32_t uhcrhdb = __raw_readl(pxa_ohci->mmio_base + UHCRHDB);
switch (mode) {
case PMM_NPS_MODE:
@@ -149,20 +160,18 @@ static int pxa27x_ohci_select_pmm(struct pxa27x_ohci *ohci, int mode)
uhcrhda |= RH_A_NPS;
}
- __raw_writel(uhcrhda, ohci->mmio_base + UHCRHDA);
- __raw_writel(uhcrhdb, ohci->mmio_base + UHCRHDB);
+ __raw_writel(uhcrhda, pxa_ohci->mmio_base + UHCRHDA);
+ __raw_writel(uhcrhdb, pxa_ohci->mmio_base + UHCRHDB);
return 0;
}
-extern int usb_disabled(void);
-
/*-------------------------------------------------------------------------*/
-static inline void pxa27x_setup_hc(struct pxa27x_ohci *ohci,
+static inline void pxa27x_setup_hc(struct pxa27x_ohci *pxa_ohci,
struct pxaohci_platform_data *inf)
{
- uint32_t uhchr = __raw_readl(ohci->mmio_base + UHCHR);
- uint32_t uhcrhda = __raw_readl(ohci->mmio_base + UHCRHDA);
+ uint32_t uhchr = __raw_readl(pxa_ohci->mmio_base + UHCHR);
+ uint32_t uhcrhda = __raw_readl(pxa_ohci->mmio_base + UHCRHDA);
if (inf->flags & ENABLE_PORT1)
uhchr &= ~UHCHR_SSEP1;
@@ -194,17 +203,17 @@ static inline void pxa27x_setup_hc(struct pxa27x_ohci *ohci,
uhcrhda |= UHCRHDA_POTPGT(inf->power_on_delay / 2);
}
- __raw_writel(uhchr, ohci->mmio_base + UHCHR);
- __raw_writel(uhcrhda, ohci->mmio_base + UHCRHDA);
+ __raw_writel(uhchr, pxa_ohci->mmio_base + UHCHR);
+ __raw_writel(uhcrhda, pxa_ohci->mmio_base + UHCRHDA);
}
-static inline void pxa27x_reset_hc(struct pxa27x_ohci *ohci)
+static inline void pxa27x_reset_hc(struct pxa27x_ohci *pxa_ohci)
{
- uint32_t uhchr = __raw_readl(ohci->mmio_base + UHCHR);
+ uint32_t uhchr = __raw_readl(pxa_ohci->mmio_base + UHCHR);
- __raw_writel(uhchr | UHCHR_FHR, ohci->mmio_base + UHCHR);
+ __raw_writel(uhchr | UHCHR_FHR, pxa_ohci->mmio_base + UHCHR);
udelay(11);
- __raw_writel(uhchr & ~UHCHR_FHR, ohci->mmio_base + UHCHR);
+ __raw_writel(uhchr & ~UHCHR_FHR, pxa_ohci->mmio_base + UHCHR);
}
#ifdef CONFIG_PXA27x
@@ -213,25 +222,26 @@ extern void pxa27x_clear_otgph(void);
#define pxa27x_clear_otgph() do {} while (0)
#endif
-static int pxa27x_start_hc(struct pxa27x_ohci *ohci, struct device *dev)
+static int pxa27x_start_hc(struct pxa27x_ohci *pxa_ohci, struct device *dev)
{
int retval = 0;
struct pxaohci_platform_data *inf;
uint32_t uhchr;
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
inf = dev_get_platdata(dev);
- clk_prepare_enable(ohci->clk);
+ clk_prepare_enable(pxa_ohci->clk);
- pxa27x_reset_hc(ohci);
+ pxa27x_reset_hc(pxa_ohci);
- uhchr = __raw_readl(ohci->mmio_base + UHCHR) | UHCHR_FSBIR;
- __raw_writel(uhchr, ohci->mmio_base + UHCHR);
+ uhchr = __raw_readl(pxa_ohci->mmio_base + UHCHR) | UHCHR_FSBIR;
+ __raw_writel(uhchr, pxa_ohci->mmio_base + UHCHR);
- while (__raw_readl(ohci->mmio_base + UHCHR) & UHCHR_FSBIR)
+ while (__raw_readl(pxa_ohci->mmio_base + UHCHR) & UHCHR_FSBIR)
cpu_relax();
- pxa27x_setup_hc(ohci, inf);
+ pxa27x_setup_hc(pxa_ohci, inf);
if (inf->init)
retval = inf->init(dev);
@@ -240,38 +250,39 @@ static int pxa27x_start_hc(struct pxa27x_ohci *ohci, struct device *dev)
return retval;
if (cpu_is_pxa3xx())
- pxa3xx_u2d_start_hc(&ohci_to_hcd(&ohci->ohci)->self);
+ pxa3xx_u2d_start_hc(&hcd->self);
- uhchr = __raw_readl(ohci->mmio_base + UHCHR) & ~UHCHR_SSE;
- __raw_writel(uhchr, ohci->mmio_base + UHCHR);
- __raw_writel(UHCHIE_UPRIE | UHCHIE_RWIE, ohci->mmio_base + UHCHIE);
+ uhchr = __raw_readl(pxa_ohci->mmio_base + UHCHR) & ~UHCHR_SSE;
+ __raw_writel(uhchr, pxa_ohci->mmio_base + UHCHR);
+ __raw_writel(UHCHIE_UPRIE | UHCHIE_RWIE, pxa_ohci->mmio_base + UHCHIE);
/* Clear any OTG Pin Hold */
pxa27x_clear_otgph();
return 0;
}
-static void pxa27x_stop_hc(struct pxa27x_ohci *ohci, struct device *dev)
+static void pxa27x_stop_hc(struct pxa27x_ohci *pxa_ohci, struct device *dev)
{
struct pxaohci_platform_data *inf;
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
uint32_t uhccoms;
inf = dev_get_platdata(dev);
if (cpu_is_pxa3xx())
- pxa3xx_u2d_stop_hc(&ohci_to_hcd(&ohci->ohci)->self);
+ pxa3xx_u2d_stop_hc(&hcd->self);
if (inf->exit)
inf->exit(dev);
- pxa27x_reset_hc(ohci);
+ pxa27x_reset_hc(pxa_ohci);
/* Host Controller Reset */
- uhccoms = __raw_readl(ohci->mmio_base + UHCCOMS) | 0x01;
- __raw_writel(uhccoms, ohci->mmio_base + UHCCOMS);
+ uhccoms = __raw_readl(pxa_ohci->mmio_base + UHCCOMS) | 0x01;
+ __raw_writel(uhccoms, pxa_ohci->mmio_base + UHCCOMS);
udelay(10);
- clk_disable_unprepare(ohci->clk);
+ clk_disable_unprepare(pxa_ohci->clk);
}
#ifdef CONFIG_OF
@@ -356,7 +367,8 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
int retval, irq;
struct usb_hcd *hcd;
struct pxaohci_platform_data *inf;
- struct pxa27x_ohci *ohci;
+ struct pxa27x_ohci *pxa_ohci;
+ struct ohci_hcd *ohci;
struct resource *r;
struct clk *usb_clk;
@@ -409,29 +421,31 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
}
/* initialize "struct pxa27x_ohci" */
- ohci = (struct pxa27x_ohci *)hcd_to_ohci(hcd);
- ohci->dev = &pdev->dev;
- ohci->clk = usb_clk;
- ohci->mmio_base = (void __iomem *)hcd->regs;
+ pxa_ohci = to_pxa27x_ohci(hcd);
+ pxa_ohci->clk = usb_clk;
+ pxa_ohci->mmio_base = (void __iomem *)hcd->regs;
- if ((retval = pxa27x_start_hc(ohci, &pdev->dev)) < 0) {
+ retval = pxa27x_start_hc(pxa_ohci, &pdev->dev);
+ if (retval < 0) {
pr_debug("pxa27x_start_hc failed");
goto err3;
}
/* Select Power Management Mode */
- pxa27x_ohci_select_pmm(ohci, inf->port_mode);
+ pxa27x_ohci_select_pmm(pxa_ohci, inf->port_mode);
if (inf->power_budget)
hcd->power_budget = inf->power_budget;
- ohci_hcd_init(hcd_to_ohci(hcd));
+ /* The value of NDP in roothub_a is incorrect on this hardware */
+ ohci = hcd_to_ohci(hcd);
+ ohci->num_ports = 3;
retval = usb_add_hcd(hcd, irq, 0);
if (retval == 0)
return retval;
- pxa27x_stop_hc(ohci, &pdev->dev);
+ pxa27x_stop_hc(pxa_ohci, &pdev->dev);
err3:
iounmap(hcd->regs);
err2:
@@ -459,88 +473,18 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
*/
void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev)
{
- struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd);
+ struct pxa27x_ohci *pxa_ohci = to_pxa27x_ohci(hcd);
usb_remove_hcd(hcd);
- pxa27x_stop_hc(ohci, &pdev->dev);
+ pxa27x_stop_hc(pxa_ohci, &pdev->dev);
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ clk_put(pxa_ohci->clk);
usb_put_hcd(hcd);
- clk_put(ohci->clk);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int
-ohci_pxa27x_start (struct usb_hcd *hcd)
-{
- struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- int ret;
-
- ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci);
-
- /* The value of NDP in roothub_a is incorrect on this hardware */
- ohci->num_ports = 3;
-
- if ((ret = ohci_init(ohci)) < 0)
- return ret;
-
- if ((ret = ohci_run (ohci)) < 0) {
- dev_err(hcd->self.controller, "can't start %s",
- hcd->self.bus_name);
- ohci_stop (hcd);
- return ret;
- }
-
- return 0;
}
/*-------------------------------------------------------------------------*/
-static const struct hc_driver ohci_pxa27x_hc_driver = {
- .description = hcd_name,
- .product_desc = "PXA27x OHCI",
- .hcd_priv_size = sizeof(struct pxa27x_ohci),
-
- /*
- * generic hardware linkage
- */
- .irq = ohci_irq,
- .flags = HCD_USB11 | HCD_MEMORY,
-
- /*
- * basic lifecycle operations
- */
- .start = ohci_pxa27x_start,
- .stop = ohci_stop,
- .shutdown = ohci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ohci_urb_enqueue,
- .urb_dequeue = ohci_urb_dequeue,
- .endpoint_disable = ohci_endpoint_disable,
-
- /*
- * scheduling support
- */
- .get_frame_number = ohci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ohci_hub_status_data,
- .hub_control = ohci_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ohci_bus_suspend,
- .bus_resume = ohci_bus_resume,
-#endif
- .start_port_reset = ohci_start_port_reset,
-};
-
-/*-------------------------------------------------------------------------*/
-
static int ohci_hcd_pxa27x_drv_probe(struct platform_device *pdev)
{
pr_debug ("In ohci_hcd_pxa27x_drv_probe");
@@ -563,32 +507,35 @@ static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev)
static int ohci_hcd_pxa27x_drv_suspend(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
- struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd);
+ struct pxa27x_ohci *pxa_ohci = to_pxa27x_ohci(hcd);
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
- if (time_before(jiffies, ohci->ohci.next_statechange))
+ if (time_before(jiffies, ohci->next_statechange))
msleep(5);
- ohci->ohci.next_statechange = jiffies;
+ ohci->next_statechange = jiffies;
- pxa27x_stop_hc(ohci, dev);
+ pxa27x_stop_hc(pxa_ohci, dev);
return 0;
}
static int ohci_hcd_pxa27x_drv_resume(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
- struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd);
+ struct pxa27x_ohci *pxa_ohci = to_pxa27x_ohci(hcd);
struct pxaohci_platform_data *inf = dev_get_platdata(dev);
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
int status;
- if (time_before(jiffies, ohci->ohci.next_statechange))
+ if (time_before(jiffies, ohci->next_statechange))
msleep(5);
- ohci->ohci.next_statechange = jiffies;
+ ohci->next_statechange = jiffies;
- if ((status = pxa27x_start_hc(ohci, dev)) < 0)
+ status = pxa27x_start_hc(pxa_ohci, dev);
+ if (status < 0)
return status;
/* Select Power Management Mode */
- pxa27x_ohci_select_pmm(ohci, inf->port_mode);
+ pxa27x_ohci_select_pmm(pxa_ohci, inf->port_mode);
ohci_resume(hcd, false);
return 0;
@@ -600,9 +547,6 @@ static const struct dev_pm_ops ohci_hcd_pxa27x_pm_ops = {
};
#endif
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:pxa27x-ohci");
-
static struct platform_driver ohci_hcd_pxa27x_driver = {
.probe = ohci_hcd_pxa27x_drv_probe,
.remove = ohci_hcd_pxa27x_drv_remove,
@@ -617,3 +561,27 @@ static struct platform_driver ohci_hcd_pxa27x_driver = {
},
};
+static const struct ohci_driver_overrides pxa27x_overrides __initconst = {
+ .extra_priv_size = sizeof(struct pxa27x_ohci),
+};
+
+static int __init ohci_pxa27x_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+ ohci_init_driver(&ohci_pxa27x_hc_driver, &pxa27x_overrides);
+ return platform_driver_register(&ohci_hcd_pxa27x_driver);
+}
+module_init(ohci_pxa27x_init);
+
+static void __exit ohci_pxa27x_cleanup(void)
+{
+ platform_driver_unregister(&ohci_hcd_pxa27x_driver);
+}
+module_exit(ohci_pxa27x_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa27x-ohci");
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index df4a6707322d..e7f577e63624 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -41,9 +41,13 @@ finish_urb(struct ohci_hcd *ohci, struct urb *urb, int status)
__releases(ohci->lock)
__acquires(ohci->lock)
{
- struct device *dev = ohci_to_hcd(ohci)->self.controller;
+ struct device *dev = ohci_to_hcd(ohci)->self.controller;
+ struct usb_host_endpoint *ep = urb->ep;
+ struct urb_priv *urb_priv;
+
// ASSERT (urb->hcpriv != 0);
+ restart:
urb_free_priv (ohci, urb->hcpriv);
urb->hcpriv = NULL;
if (likely(status == -EINPROGRESS))
@@ -80,6 +84,21 @@ __acquires(ohci->lock)
ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_IE);
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
}
+
+ /*
+ * An isochronous URB that is sumitted too late won't have any TDs
+ * (marked by the fact that the td_cnt value is larger than the
+ * actual number of TDs). If the next URB on this endpoint is like
+ * that, give it back now.
+ */
+ if (!list_empty(&ep->urb_list)) {
+ urb = list_first_entry(&ep->urb_list, struct urb, urb_list);
+ urb_priv = urb->hcpriv;
+ if (urb_priv->td_cnt > urb_priv->length) {
+ status = 0;
+ goto restart;
+ }
+ }
}
@@ -546,7 +565,6 @@ td_fill (struct ohci_hcd *ohci, u32 info,
td->hwCBP = cpu_to_hc32 (ohci, data & 0xFFFFF000);
*ohci_hwPSWp(ohci, td, 0) = cpu_to_hc16 (ohci,
(data & 0x0FFF) | 0xE000);
- td->ed->last_iso = info & 0xffff;
} else {
td->hwCBP = cpu_to_hc32 (ohci, data);
}
@@ -996,7 +1014,7 @@ rescan_this:
urb_priv->td_cnt++;
/* if URB is done, clean up */
- if (urb_priv->td_cnt == urb_priv->length) {
+ if (urb_priv->td_cnt >= urb_priv->length) {
modified = completed = 1;
finish_urb(ohci, urb, 0);
}
@@ -1086,7 +1104,7 @@ static void takeback_td(struct ohci_hcd *ohci, struct td *td)
urb_priv->td_cnt++;
/* If all this urb's TDs are done, call complete() */
- if (urb_priv->td_cnt == urb_priv->length)
+ if (urb_priv->td_cnt >= urb_priv->length)
finish_urb(ohci, urb, status);
/* clean schedule: unlink EDs that are no longer busy */
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 4919afa4125e..f90101b9cdb9 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -19,19 +19,36 @@
* This file is licenced under the GPL.
*/
-#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/platform_data/usb-ohci-s3c2410.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ohci.h"
+
#define valid_port(idx) ((idx) == 1 || (idx) == 2)
/* clock device associated with the hcd */
+
+#define DRIVER_DESC "OHCI S3C2410 driver"
+
+static const char hcd_name[] = "ohci-s3c2410";
+
static struct clk *clk;
static struct clk *usb_clk;
/* forward definitions */
+static int (*orig_ohci_hub_control)(struct usb_hcd *hcd, u16 typeReq,
+ u16 wValue, u16 wIndex, char *buf, u16 wLength);
+static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf);
+
static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc);
/* conversion functions */
@@ -47,10 +64,10 @@ static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd)
dev_dbg(&dev->dev, "s3c2410_start_hc:\n");
- clk_enable(usb_clk);
+ clk_prepare_enable(usb_clk);
mdelay(2); /* let the bus clock stabilise */
- clk_enable(clk);
+ clk_prepare_enable(clk);
if (info != NULL) {
info->hcd = hcd;
@@ -75,8 +92,8 @@ static void s3c2410_stop_hc(struct platform_device *dev)
(info->enable_oc)(info, 0);
}
- clk_disable(clk);
- clk_disable(usb_clk);
+ clk_disable_unprepare(clk);
+ clk_disable_unprepare(usb_clk);
}
/* ohci_s3c2410_hub_status_data
@@ -93,7 +110,7 @@ ohci_s3c2410_hub_status_data(struct usb_hcd *hcd, char *buf)
int orig;
int portno;
- orig = ohci_hub_status_data(hcd, buf);
+ orig = orig_ohci_hub_status_data(hcd, buf);
if (info == NULL)
return orig;
@@ -164,7 +181,7 @@ static int ohci_s3c2410_hub_control(
* process the request straight away and exit */
if (info == NULL) {
- ret = ohci_hub_control(hcd, typeReq, wValue,
+ ret = orig_ohci_hub_control(hcd, typeReq, wValue,
wIndex, buf, wLength);
goto out;
}
@@ -214,7 +231,7 @@ static int ohci_s3c2410_hub_control(
break;
}
- ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
+ ret = orig_ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
if (ret)
goto out;
@@ -374,8 +391,6 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,
s3c2410_start_hc(dev, hcd);
- ohci_hcd_init(hcd_to_ohci(hcd));
-
retval = usb_add_hcd(hcd, dev->resource[1].start, 0);
if (retval != 0)
goto err_ioremap;
@@ -392,71 +407,7 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,
/*-------------------------------------------------------------------------*/
-static int
-ohci_s3c2410_start(struct usb_hcd *hcd)
-{
- struct ohci_hcd *ohci = hcd_to_ohci(hcd);
- int ret;
-
- ret = ohci_init(ohci);
- if (ret < 0)
- return ret;
-
- ret = ohci_run(ohci);
- if (ret < 0) {
- dev_err(hcd->self.controller, "can't start %s\n",
- hcd->self.bus_name);
- ohci_stop(hcd);
- return ret;
- }
-
- return 0;
-}
-
-
-static const struct hc_driver ohci_s3c2410_hc_driver = {
- .description = hcd_name,
- .product_desc = "S3C24XX OHCI",
- .hcd_priv_size = sizeof(struct ohci_hcd),
-
- /*
- * generic hardware linkage
- */
- .irq = ohci_irq,
- .flags = HCD_USB11 | HCD_MEMORY,
-
- /*
- * basic lifecycle operations
- */
- .start = ohci_s3c2410_start,
- .stop = ohci_stop,
- .shutdown = ohci_shutdown,
-
- /*
- * managing i/o requests and associated device resources
- */
- .urb_enqueue = ohci_urb_enqueue,
- .urb_dequeue = ohci_urb_dequeue,
- .endpoint_disable = ohci_endpoint_disable,
-
- /*
- * scheduling support
- */
- .get_frame_number = ohci_get_frame,
-
- /*
- * root hub support
- */
- .hub_status_data = ohci_s3c2410_hub_status_data,
- .hub_control = ohci_s3c2410_hub_control,
-#ifdef CONFIG_PM
- .bus_suspend = ohci_bus_suspend,
- .bus_resume = ohci_bus_resume,
-#endif
- .start_port_reset = ohci_start_port_reset,
-};
-
-/* device driver */
+static struct hc_driver __read_mostly ohci_s3c2410_hc_driver;
static int ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev)
{
@@ -533,4 +484,39 @@ static struct platform_driver ohci_hcd_s3c2410_driver = {
},
};
+static int __init ohci_s3c2410_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+ ohci_init_driver(&ohci_s3c2410_hc_driver, NULL);
+
+ /*
+ * The Samsung HW has some unusual quirks, which require
+ * Sumsung-specific workarounds. We override certain hc_driver
+ * functions here to achieve that. We explicitly do not enhance
+ * ohci_driver_overrides to allow this more easily, since this
+ * is an unusual case, and we don't want to encourage others to
+ * override these functions by making it too easy.
+ */
+
+ orig_ohci_hub_control = ohci_s3c2410_hc_driver.hub_control;
+ orig_ohci_hub_status_data = ohci_s3c2410_hc_driver.hub_status_data;
+
+ ohci_s3c2410_hc_driver.hub_status_data = ohci_s3c2410_hub_status_data;
+ ohci_s3c2410_hc_driver.hub_control = ohci_s3c2410_hub_control;
+
+ return platform_driver_register(&ohci_hcd_s3c2410_driver);
+}
+module_init(ohci_s3c2410_init);
+
+static void __exit ohci_s3c2410_cleanup(void)
+{
+ platform_driver_unregister(&ohci_hcd_s3c2410_driver);
+}
+module_exit(ohci_s3c2410_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:s3c2410-ohci");
diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
index cc9dd9e4f05e..31ff3fc4e26f 100644
--- a/drivers/usb/host/ohci-spear.c
+++ b/drivers/usb/host/ohci-spear.c
@@ -11,92 +11,37 @@
* warranty of any kind, whether express or implied.
*/
-#include <linux/signal.h>
-#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/signal.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ohci.h"
+#define DRIVER_DESC "OHCI SPEAr driver"
+
+static const char hcd_name[] = "SPEAr-ohci";
struct spear_ohci {
- struct ohci_hcd ohci;
struct clk *clk;
};
-#define to_spear_ohci(hcd) (struct spear_ohci *)hcd_to_ohci(hcd)
-
-static void spear_start_ohci(struct spear_ohci *ohci)
-{
- clk_prepare_enable(ohci->clk);
-}
-
-static void spear_stop_ohci(struct spear_ohci *ohci)
-{
- clk_disable_unprepare(ohci->clk);
-}
-
-static int ohci_spear_start(struct usb_hcd *hcd)
-{
- struct ohci_hcd *ohci = hcd_to_ohci(hcd);
- int ret;
-
- ret = ohci_init(ohci);
- if (ret < 0)
- return ret;
- ohci->regs = hcd->regs;
-
- ret = ohci_run(ohci);
- if (ret < 0) {
- dev_err(hcd->self.controller, "can't start\n");
- ohci_stop(hcd);
- return ret;
- }
-
- create_debug_files(ohci);
-
-#ifdef DEBUG
- ohci_dump(ohci, 1);
-#endif
- return 0;
-}
-
-static const struct hc_driver ohci_spear_hc_driver = {
- .description = hcd_name,
- .product_desc = "SPEAr OHCI",
- .hcd_priv_size = sizeof(struct spear_ohci),
-
- /* generic hardware linkage */
- .irq = ohci_irq,
- .flags = HCD_USB11 | HCD_MEMORY,
-
- /* basic lifecycle operations */
- .start = ohci_spear_start,
- .stop = ohci_stop,
- .shutdown = ohci_shutdown,
-#ifdef CONFIG_PM
- .bus_suspend = ohci_bus_suspend,
- .bus_resume = ohci_bus_resume,
-#endif
-
- /* managing i/o requests and associated device resources */
- .urb_enqueue = ohci_urb_enqueue,
- .urb_dequeue = ohci_urb_dequeue,
- .endpoint_disable = ohci_endpoint_disable,
-
- /* scheduling support */
- .get_frame_number = ohci_get_frame,
+#define to_spear_ohci(hcd) (struct spear_ohci *)(hcd_to_ohci(hcd)->priv)
- /* root hub support */
- .hub_status_data = ohci_hub_status_data,
- .hub_control = ohci_hub_control,
-
- .start_port_reset = ohci_start_port_reset,
-};
+static struct hc_driver __read_mostly ohci_spear_hc_driver;
static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
{
const struct hc_driver *driver = &ohci_spear_hc_driver;
+ struct ohci_hcd *ohci;
struct usb_hcd *hcd = NULL;
struct clk *usbh_clk;
- struct spear_ohci *ohci_p;
+ struct spear_ohci *sohci_p;
struct resource *res;
int retval, irq;
@@ -151,16 +96,18 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
goto err_put_hcd;
}
- ohci_p = (struct spear_ohci *)hcd_to_ohci(hcd);
- ohci_p->clk = usbh_clk;
- spear_start_ohci(ohci_p);
- ohci_hcd_init(hcd_to_ohci(hcd));
+ sohci_p = to_spear_ohci(hcd);
+ sohci_p->clk = usbh_clk;
+
+ clk_prepare_enable(sohci_p->clk);
+
+ ohci = hcd_to_ohci(hcd);
retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), 0);
if (retval == 0)
return retval;
- spear_stop_ohci(ohci_p);
+ clk_disable_unprepare(sohci_p->clk);
err_put_hcd:
usb_put_hcd(hcd);
fail:
@@ -172,11 +119,11 @@ fail:
static int spear_ohci_hcd_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
- struct spear_ohci *ohci_p = to_spear_ohci(hcd);
+ struct spear_ohci *sohci_p = to_spear_ohci(hcd);
usb_remove_hcd(hcd);
- if (ohci_p->clk)
- spear_stop_ohci(ohci_p);
+ if (sohci_p->clk)
+ clk_disable_unprepare(sohci_p->clk);
usb_put_hcd(hcd);
return 0;
@@ -188,13 +135,14 @@ static int spear_ohci_hcd_drv_suspend(struct platform_device *dev,
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
- struct spear_ohci *ohci_p = to_spear_ohci(hcd);
+ struct spear_ohci *sohci_p = to_spear_ohci(hcd);
if (time_before(jiffies, ohci->next_statechange))
msleep(5);
ohci->next_statechange = jiffies;
- spear_stop_ohci(ohci_p);
+ clk_disable_unprepare(sohci_p->clk);
+
return 0;
}
@@ -202,13 +150,13 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
- struct spear_ohci *ohci_p = to_spear_ohci(hcd);
+ struct spear_ohci *sohci_p = to_spear_ohci(hcd);
if (time_before(jiffies, ohci->next_statechange))
msleep(5);
ohci->next_statechange = jiffies;
- spear_start_ohci(ohci_p);
+ clk_prepare_enable(sohci_p->clk);
ohci_resume(hcd, false);
return 0;
}
@@ -234,4 +182,28 @@ static struct platform_driver spear_ohci_hcd_driver = {
},
};
+static const struct ohci_driver_overrides spear_overrides __initconst = {
+ .extra_priv_size = sizeof(struct spear_ohci),
+};
+static int __init ohci_spear_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+ ohci_init_driver(&ohci_spear_hc_driver, &spear_overrides);
+ return platform_driver_register(&spear_ohci_hcd_driver);
+}
+module_init(ohci_spear_init);
+
+static void __exit ohci_spear_cleanup(void)
+{
+ platform_driver_unregister(&spear_ohci_hcd_driver);
+}
+module_exit(ohci_spear_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Deepak Sikri");
+MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:spear-ohci");
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 2c76ef1320ea..9eec463c73c5 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -79,11 +79,30 @@
#define USB_INTEL_USB3_PSSEN 0xD8
#define USB_INTEL_USB3PRM 0xDC
+/*
+ * amd_chipset_gen values represent AMD different chipset generations
+ */
+enum amd_chipset_gen {
+ NOT_AMD_CHIPSET = 0,
+ AMD_CHIPSET_SB600,
+ AMD_CHIPSET_SB700,
+ AMD_CHIPSET_SB800,
+ AMD_CHIPSET_HUDSON2,
+ AMD_CHIPSET_BOLTON,
+ AMD_CHIPSET_YANGTZE,
+ AMD_CHIPSET_UNKNOWN,
+};
+
+struct amd_chipset_type {
+ enum amd_chipset_gen gen;
+ u8 rev;
+};
+
static struct amd_chipset_info {
struct pci_dev *nb_dev;
struct pci_dev *smbus_dev;
int nb_type;
- int sb_type;
+ struct amd_chipset_type sb_type;
int isoc_reqs;
int probe_count;
int probe_result;
@@ -91,6 +110,51 @@ static struct amd_chipset_info {
static DEFINE_SPINLOCK(amd_lock);
+/*
+ * amd_chipset_sb_type_init - initialize amd chipset southbridge type
+ *
+ * AMD FCH/SB generation and revision is identified by SMBus controller
+ * vendor, device and revision IDs.
+ *
+ * Returns: 1 if it is an AMD chipset, 0 otherwise.
+ */
+static int amd_chipset_sb_type_init(struct amd_chipset_info *pinfo)
+{
+ u8 rev = 0;
+ pinfo->sb_type.gen = AMD_CHIPSET_UNKNOWN;
+
+ pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI,
+ PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL);
+ if (pinfo->smbus_dev) {
+ rev = pinfo->smbus_dev->revision;
+ if (rev >= 0x10 && rev <= 0x1f)
+ pinfo->sb_type.gen = AMD_CHIPSET_SB600;
+ else if (rev >= 0x30 && rev <= 0x3f)
+ pinfo->sb_type.gen = AMD_CHIPSET_SB700;
+ else if (rev >= 0x40 && rev <= 0x4f)
+ pinfo->sb_type.gen = AMD_CHIPSET_SB800;
+ } else {
+ pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+ PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, NULL);
+
+ if (!pinfo->smbus_dev) {
+ pinfo->sb_type.gen = NOT_AMD_CHIPSET;
+ return 0;
+ }
+
+ rev = pinfo->smbus_dev->revision;
+ if (rev >= 0x11 && rev <= 0x14)
+ pinfo->sb_type.gen = AMD_CHIPSET_HUDSON2;
+ else if (rev >= 0x15 && rev <= 0x18)
+ pinfo->sb_type.gen = AMD_CHIPSET_BOLTON;
+ else if (rev >= 0x39 && rev <= 0x3a)
+ pinfo->sb_type.gen = AMD_CHIPSET_YANGTZE;
+ }
+
+ pinfo->sb_type.rev = rev;
+ return 1;
+}
+
void sb800_prefetch(struct device *dev, int on)
{
u16 misc;
@@ -106,7 +170,6 @@ EXPORT_SYMBOL_GPL(sb800_prefetch);
int usb_amd_find_chipset_info(void)
{
- u8 rev = 0;
unsigned long flags;
struct amd_chipset_info info;
int ret;
@@ -122,27 +185,17 @@ int usb_amd_find_chipset_info(void)
memset(&info, 0, sizeof(info));
spin_unlock_irqrestore(&amd_lock, flags);
- info.smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL);
- if (info.smbus_dev) {
- rev = info.smbus_dev->revision;
- if (rev >= 0x40)
- info.sb_type = 1;
- else if (rev >= 0x30 && rev <= 0x3b)
- info.sb_type = 3;
- } else {
- info.smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
- 0x780b, NULL);
- if (!info.smbus_dev) {
- ret = 0;
- goto commit;
- }
-
- rev = info.smbus_dev->revision;
- if (rev >= 0x11 && rev <= 0x18)
- info.sb_type = 2;
+ if (!amd_chipset_sb_type_init(&info)) {
+ ret = 0;
+ goto commit;
}
- if (info.sb_type == 0) {
+ /* Below chipset generations needn't enable AMD PLL quirk */
+ if (info.sb_type.gen == AMD_CHIPSET_UNKNOWN ||
+ info.sb_type.gen == AMD_CHIPSET_SB600 ||
+ info.sb_type.gen == AMD_CHIPSET_YANGTZE ||
+ (info.sb_type.gen == AMD_CHIPSET_SB700 &&
+ info.sb_type.rev > 0x3b)) {
if (info.smbus_dev) {
pci_dev_put(info.smbus_dev);
info.smbus_dev = NULL;
@@ -197,6 +250,18 @@ commit:
}
EXPORT_SYMBOL_GPL(usb_amd_find_chipset_info);
+int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev)
+{
+ /* Make sure amd chipset type has already been initialized */
+ usb_amd_find_chipset_info();
+ if (amd_chipset.sb_type.gen != AMD_CHIPSET_YANGTZE)
+ return 0;
+
+ dev_dbg(&pdev->dev, "QUIRK: Enable AMD remote wakeup fix\n");
+ return 1;
+}
+EXPORT_SYMBOL_GPL(usb_hcd_amd_remote_wakeup_quirk);
+
/*
* The hardware normally enables the A-link power management feature, which
* lets the system lower the power consumption in idle states.
@@ -229,7 +294,9 @@ static void usb_amd_quirk_pll(int disable)
}
}
- if (amd_chipset.sb_type == 1 || amd_chipset.sb_type == 2) {
+ if (amd_chipset.sb_type.gen == AMD_CHIPSET_SB800 ||
+ amd_chipset.sb_type.gen == AMD_CHIPSET_HUDSON2 ||
+ amd_chipset.sb_type.gen == AMD_CHIPSET_BOLTON) {
outb_p(AB_REG_BAR_LOW, 0xcd6);
addr_low = inb_p(0xcd7);
outb_p(AB_REG_BAR_HIGH, 0xcd6);
@@ -240,7 +307,8 @@ static void usb_amd_quirk_pll(int disable)
outl_p(0x40, AB_DATA(addr));
outl_p(0x34, AB_INDX(addr));
val = inl_p(AB_DATA(addr));
- } else if (amd_chipset.sb_type == 3) {
+ } else if (amd_chipset.sb_type.gen == AMD_CHIPSET_SB700 &&
+ amd_chipset.sb_type.rev <= 0x3b) {
pci_read_config_dword(amd_chipset.smbus_dev,
AB_REG_BAR_SB700, &addr);
outl(AX_INDXC, AB_INDX(addr));
@@ -353,7 +421,7 @@ void usb_amd_dev_put(void)
amd_chipset.nb_dev = NULL;
amd_chipset.smbus_dev = NULL;
amd_chipset.nb_type = 0;
- amd_chipset.sb_type = 0;
+ memset(&amd_chipset.sb_type, 0, sizeof(amd_chipset.sb_type));
amd_chipset.isoc_reqs = 0;
amd_chipset.probe_result = 0;
diff --git a/drivers/usb/host/uhci-pci.c b/drivers/usb/host/uhci-pci.c
index c300bd2f7d1c..d89c78dc70c0 100644
--- a/drivers/usb/host/uhci-pci.c
+++ b/drivers/usb/host/uhci-pci.c
@@ -293,9 +293,11 @@ static struct pci_driver uhci_pci_driver = {
.remove = usb_hcd_pci_remove,
.shutdown = uhci_shutdown,
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
.driver = {
.pm = &usb_hcd_pci_pm_ops
},
#endif
};
+
+MODULE_SOFTDEP("pre: ehci_pci");
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 041c6ddb695c..da6f56d996ce 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -1303,7 +1303,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
}
/* Fell behind? */
- if (uhci_frame_before_eq(frame, next)) {
+ if (!uhci_frame_before_eq(next, frame)) {
/* USB_ISO_ASAP: Round up to the first available slot */
if (urb->transfer_flags & URB_ISO_ASAP)
@@ -1311,13 +1311,17 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
-qh->period;
/*
- * Not ASAP: Use the next slot in the stream. If
- * the entire URB falls before the threshold, fail.
+ * Not ASAP: Use the next slot in the stream,
+ * no matter what.
*/
else if (!uhci_frame_before_eq(next,
frame + (urb->number_of_packets - 1) *
qh->period))
- return -EXDEV;
+ dev_dbg(uhci_dev(uhci), "iso underrun %p (%u+%u < %u)\n",
+ urb, frame,
+ (urb->number_of_packets - 1) *
+ qh->period,
+ next);
}
}
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index fae697ed0b70..773a6b28c4f1 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -287,7 +287,7 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue)
xhci_queue_stop_endpoint(xhci, slot_id, i, suspend);
}
- cmd->command_trb = xhci->cmd_ring->enqueue;
+ cmd->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list);
xhci_queue_stop_endpoint(xhci, slot_id, 0, suspend);
xhci_ring_cmd_db(xhci);
@@ -552,11 +552,15 @@ void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u16 wIndex)
* - Mark a port as being done with device resume,
* and ring the endpoint doorbells.
* - Stop the Synopsys redriver Compliance Mode polling.
+ * - Drop and reacquire the xHCI lock, in order to wait for port resume.
*/
static u32 xhci_get_port_status(struct usb_hcd *hcd,
struct xhci_bus_state *bus_state,
__le32 __iomem **port_array,
- u16 wIndex, u32 raw_port_status)
+ u16 wIndex, u32 raw_port_status,
+ unsigned long flags)
+ __releases(&xhci->lock)
+ __acquires(&xhci->lock)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
u32 status = 0;
@@ -591,21 +595,42 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
return 0xffffffff;
if (time_after_eq(jiffies,
bus_state->resume_done[wIndex])) {
+ int time_left;
+
xhci_dbg(xhci, "Resume USB2 port %d\n",
wIndex + 1);
bus_state->resume_done[wIndex] = 0;
clear_bit(wIndex, &bus_state->resuming_ports);
+
+ set_bit(wIndex, &bus_state->rexit_ports);
xhci_set_link_state(xhci, port_array, wIndex,
XDEV_U0);
- xhci_dbg(xhci, "set port %d resume\n",
- wIndex + 1);
- slot_id = xhci_find_slot_id_by_port(hcd, xhci,
- wIndex + 1);
- if (!slot_id) {
- xhci_dbg(xhci, "slot_id is zero\n");
- return 0xffffffff;
+
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ time_left = wait_for_completion_timeout(
+ &bus_state->rexit_done[wIndex],
+ msecs_to_jiffies(
+ XHCI_MAX_REXIT_TIMEOUT));
+ spin_lock_irqsave(&xhci->lock, flags);
+
+ if (time_left) {
+ slot_id = xhci_find_slot_id_by_port(hcd,
+ xhci, wIndex + 1);
+ if (!slot_id) {
+ xhci_dbg(xhci, "slot_id is zero\n");
+ return 0xffffffff;
+ }
+ xhci_ring_device(xhci, slot_id);
+ } else {
+ int port_status = xhci_readl(xhci,
+ port_array[wIndex]);
+ xhci_warn(xhci, "Port resume took longer than %i msec, port status = 0x%x\n",
+ XHCI_MAX_REXIT_TIMEOUT,
+ port_status);
+ status |= USB_PORT_STAT_SUSPEND;
+ clear_bit(wIndex, &bus_state->rexit_ports);
}
- xhci_ring_device(xhci, slot_id);
+
bus_state->port_c_suspend |= 1 << wIndex;
bus_state->suspended_ports &= ~(1 << wIndex);
} else {
@@ -728,7 +753,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
break;
}
status = xhci_get_port_status(hcd, bus_state, port_array,
- wIndex, temp);
+ wIndex, temp, flags);
if (status == 0xffffffff)
goto error;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 53b972c2a09f..83bcd13622c3 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2428,6 +2428,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
for (i = 0; i < USB_MAXCHILDREN; ++i) {
xhci->bus_state[0].resume_done[i] = 0;
xhci->bus_state[1].resume_done[i] = 0;
+ /* Only the USB 2.0 completions will ever be used. */
+ init_completion(&xhci->bus_state[1].rexit_done[i]);
}
if (scratchpad_alloc(xhci, flags))
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index c2d495057eb5..236c3aabe940 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -351,7 +351,7 @@ static struct pci_driver xhci_pci_driver = {
/* suspend and resume implemented later */
.shutdown = usb_hcd_pci_shutdown,
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
.driver = {
.pm = &usb_hcd_pci_pm_ops
},
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 411da1fc7ae8..6bfbd80ec2b9 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -123,6 +123,16 @@ static int enqueue_is_link_trb(struct xhci_ring *ring)
return TRB_TYPE_LINK_LE32(link->control);
}
+union xhci_trb *xhci_find_next_enqueue(struct xhci_ring *ring)
+{
+ /* Enqueue pointer can be left pointing to the link TRB,
+ * we must handle that
+ */
+ if (TRB_TYPE_LINK_LE32(ring->enqueue->link.control))
+ return ring->enq_seg->next->trbs;
+ return ring->enqueue;
+}
+
/* Updates trb to point to the next TRB in the ring, and updates seg if the next
* TRB is in a new segment. This does not skip over link TRBs, and it does not
* effect the ring dequeue or enqueue pointers.
@@ -859,8 +869,12 @@ remove_finished_td:
/* Otherwise ring the doorbell(s) to restart queued transfers */
ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
}
- ep->stopped_td = NULL;
- ep->stopped_trb = NULL;
+
+ /* Clear stopped_td and stopped_trb if endpoint is not halted */
+ if (!(ep->ep_state & EP_HALTED)) {
+ ep->stopped_td = NULL;
+ ep->stopped_trb = NULL;
+ }
/*
* Drop the lock and complete the URBs in the cancelled TD list.
@@ -1414,6 +1428,12 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
inc_deq(xhci, xhci->cmd_ring);
return;
}
+ /* There is no command to handle if we get a stop event when the
+ * command ring is empty, event->cmd_trb points to the next
+ * unset command
+ */
+ if (xhci->cmd_ring->dequeue == xhci->cmd_ring->enqueue)
+ return;
}
switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3])
@@ -1743,6 +1763,19 @@ static void handle_port_status(struct xhci_hcd *xhci,
}
}
+ /*
+ * Check to see if xhci-hub.c is waiting on RExit to U0 transition (or
+ * RExit to a disconnect state). If so, let the the driver know it's
+ * out of the RExit state.
+ */
+ if (!DEV_SUPERSPEED(temp) &&
+ test_and_clear_bit(faked_port_index,
+ &bus_state->rexit_ports)) {
+ complete(&bus_state->rexit_done[faked_port_index]);
+ bogus_port_status = true;
+ goto cleanup;
+ }
+
if (hcd->speed != HCD_USB3)
xhci_test_and_clear_bit(xhci, port_array, faked_port_index,
PORT_PLC);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 49b6edb84a79..1e36dbb48366 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -2598,15 +2598,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
if (command) {
cmd_completion = command->completion;
cmd_status = &command->status;
- command->command_trb = xhci->cmd_ring->enqueue;
-
- /* Enqueue pointer can be left pointing to the link TRB,
- * we must handle that
- */
- if (TRB_TYPE_LINK_LE32(command->command_trb->link.control))
- command->command_trb =
- xhci->cmd_ring->enq_seg->next->trbs;
-
+ command->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
list_add_tail(&command->cmd_list, &virt_dev->cmd_list);
} else {
cmd_completion = &virt_dev->cmd_completion;
@@ -2614,7 +2606,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
}
init_completion(cmd_completion);
- cmd_trb = xhci->cmd_ring->dequeue;
+ cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
if (!ctx_change)
ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma,
udev->slot_id, must_succeed);
@@ -3439,14 +3431,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
/* Attempt to submit the Reset Device command to the command ring */
spin_lock_irqsave(&xhci->lock, flags);
- reset_device_cmd->command_trb = xhci->cmd_ring->enqueue;
-
- /* Enqueue pointer can be left pointing to the link TRB,
- * we must handle that
- */
- if (TRB_TYPE_LINK_LE32(reset_device_cmd->command_trb->link.control))
- reset_device_cmd->command_trb =
- xhci->cmd_ring->enq_seg->next->trbs;
+ reset_device_cmd->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list);
ret = xhci_queue_reset_device(xhci, slot_id);
@@ -3650,7 +3635,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
union xhci_trb *cmd_trb;
spin_lock_irqsave(&xhci->lock, flags);
- cmd_trb = xhci->cmd_ring->dequeue;
+ cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
ret = xhci_queue_slot_control(xhci, TRB_ENABLE_SLOT, 0);
if (ret) {
spin_unlock_irqrestore(&xhci->lock, flags);
@@ -3785,7 +3770,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
slot_ctx->dev_info >> 27);
spin_lock_irqsave(&xhci->lock, flags);
- cmd_trb = xhci->cmd_ring->dequeue;
+ cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma,
udev->slot_id);
if (ret) {
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 46aa14894148..289fbfbae746 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1412,8 +1412,18 @@ struct xhci_bus_state {
unsigned long resume_done[USB_MAXCHILDREN];
/* which ports have started to resume */
unsigned long resuming_ports;
+ /* Which ports are waiting on RExit to U0 transition. */
+ unsigned long rexit_ports;
+ struct completion rexit_done[USB_MAXCHILDREN];
};
+
+/*
+ * It can take up to 20 ms to transition from RExit to U0 on the
+ * Intel Lynx Point LP xHCI host.
+ */
+#define XHCI_MAX_REXIT_TIMEOUT (20 * 1000)
+
static inline unsigned int hcd_index(struct usb_hcd *hcd)
{
if (hcd->speed == HCD_USB3)
@@ -1840,6 +1850,7 @@ int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command,
union xhci_trb *cmd_trb);
void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
unsigned int ep_index, unsigned int stream_id);
+union xhci_trb *xhci_find_next_enqueue(struct xhci_ring *ring);
/* xHCI roothub code */
void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array,
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index aa28ac8c7607..3e91d3e98ee8 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -120,7 +120,7 @@ get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf)
struct usb_host_endpoint *e;
e = alt->endpoint + ep;
- switch (e->desc.bmAttributes) {
+ switch (usb_endpoint_type(&e->desc)) {
case USB_ENDPOINT_XFER_BULK:
break;
case USB_ENDPOINT_XFER_ISOC:
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index d5589f9c60a9..51ffe11cf38a 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -93,6 +93,7 @@ config AM335X_CONTROL_USB
config AM335X_PHY_USB
tristate "AM335x USB PHY Driver"
+ depends on ARM || COMPILE_TEST
select USB_PHY
select AM335X_CONTROL_USB
select NOP_USB_XCEIV
diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c
index b2f29c9aebbf..02799a5efcd4 100644
--- a/drivers/usb/phy/phy-gpio-vbus-usb.c
+++ b/drivers/usb/phy/phy-gpio-vbus-usb.c
@@ -241,7 +241,7 @@ static int gpio_vbus_set_suspend(struct usb_phy *phy, int suspend)
/* platform driver interface */
-static int __init gpio_vbus_probe(struct platform_device *pdev)
+static int gpio_vbus_probe(struct platform_device *pdev)
{
struct gpio_vbus_mach_info *pdata = dev_get_platdata(&pdev->dev);
struct gpio_vbus_data *gpio_vbus;
@@ -349,7 +349,7 @@ err_gpio:
return err;
}
-static int __exit gpio_vbus_remove(struct platform_device *pdev)
+static int gpio_vbus_remove(struct platform_device *pdev)
{
struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
struct gpio_vbus_mach_info *pdata = dev_get_platdata(&pdev->dev);
@@ -398,8 +398,6 @@ static const struct dev_pm_ops gpio_vbus_dev_pm_ops = {
};
#endif
-/* NOTE: the gpio-vbus device may *NOT* be hotplugged */
-
MODULE_ALIAS("platform:gpio-vbus");
static struct platform_driver gpio_vbus_driver = {
@@ -410,10 +408,11 @@ static struct platform_driver gpio_vbus_driver = {
.pm = &gpio_vbus_dev_pm_ops,
#endif
},
- .remove = __exit_p(gpio_vbus_remove),
+ .probe = gpio_vbus_probe,
+ .remove = gpio_vbus_remove,
};
-module_platform_driver_probe(gpio_vbus_driver, gpio_vbus_probe);
+module_platform_driver(gpio_vbus_driver);
MODULE_DESCRIPTION("simple GPIO controlled OTG transceiver driver");
MODULE_AUTHOR("Philipp Zabel");
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index c45f9c0a1b34..f53298d32099 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1966,8 +1966,16 @@ static int ftdi_process_packet(struct usb_serial_port *port,
port->icount.dsr++;
if (diff_status & FTDI_RS0_RI)
port->icount.rng++;
- if (diff_status & FTDI_RS0_RLSD)
+ if (diff_status & FTDI_RS0_RLSD) {
+ struct tty_struct *tty;
+
port->icount.dcd++;
+ tty = tty_port_tty_get(&port->port);
+ if (tty)
+ usb_serial_handle_dcd_change(port, tty,
+ status & FTDI_RS0_RLSD);
+ tty_kref_put(tty);
+ }
wake_up_interruptible(&port->port.delta_msr_wait);
priv->prev_status = status;
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 1f31e6b4c251..3a5dac879094 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -570,6 +570,16 @@ void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,
dev_dbg(&usb_port->dev, "%s - status %d\n", __func__, status);
+ if (tty) {
+ struct tty_ldisc *ld = tty_ldisc_ref(tty);
+
+ if (ld) {
+ if (ld->ops->dcd_change)
+ ld->ops->dcd_change(tty, status);
+ tty_ldisc_deref(ld);
+ }
+ }
+
if (status)
wake_up_interruptible(&port->open_wait);
else if (tty && !C_CLOCAL(tty))
diff --git a/drivers/usb/wusbcore/wa-hc.c b/drivers/usb/wusbcore/wa-hc.c
index a09b65ebd9bb..6c09b0e4672b 100644
--- a/drivers/usb/wusbcore/wa-hc.c
+++ b/drivers/usb/wusbcore/wa-hc.c
@@ -44,11 +44,11 @@ int wa_create(struct wahc *wa, struct usb_interface *iface)
/* Fill up Data Transfer EP pointers */
wa->dti_epd = &iface->cur_altsetting->endpoint[1].desc;
wa->dto_epd = &iface->cur_altsetting->endpoint[2].desc;
- wa->xfer_result_size = usb_endpoint_maxp(wa->dti_epd);
- wa->xfer_result = kmalloc(wa->xfer_result_size, GFP_KERNEL);
- if (wa->xfer_result == NULL) {
+ wa->dti_buf_size = usb_endpoint_maxp(wa->dti_epd);
+ wa->dti_buf = kmalloc(wa->dti_buf_size, GFP_KERNEL);
+ if (wa->dti_buf == NULL) {
result = -ENOMEM;
- goto error_xfer_result_alloc;
+ goto error_dti_buf_alloc;
}
result = wa_nep_create(wa, iface);
if (result < 0) {
@@ -59,8 +59,8 @@ int wa_create(struct wahc *wa, struct usb_interface *iface)
return 0;
error_nep_create:
- kfree(wa->xfer_result);
-error_xfer_result_alloc:
+ kfree(wa->dti_buf);
+error_dti_buf_alloc:
wa_rpipes_destroy(wa);
error_rpipes_create:
return result;
@@ -76,7 +76,7 @@ void __wa_destroy(struct wahc *wa)
usb_kill_urb(wa->buf_in_urb);
usb_put_urb(wa->buf_in_urb);
}
- kfree(wa->xfer_result);
+ kfree(wa->dti_buf);
wa_nep_destroy(wa);
wa_rpipes_destroy(wa);
}
diff --git a/drivers/usb/wusbcore/wa-hc.h b/drivers/usb/wusbcore/wa-hc.h
index cf250c21e946..ab399343757e 100644
--- a/drivers/usb/wusbcore/wa-hc.h
+++ b/drivers/usb/wusbcore/wa-hc.h
@@ -184,8 +184,8 @@ struct wahc {
struct urb *dti_urb; /* URB for reading xfer results */
struct urb *buf_in_urb; /* URB for reading data in */
struct edc dti_edc; /* DTI error density counter */
- struct wa_xfer_result *xfer_result; /* real size = dti_ep maxpktsize */
- size_t xfer_result_size;
+ void *dti_buf;
+ size_t dti_buf_size;
s32 status; /* For reading status */
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 6ad02f57c366..0b27146b5bc1 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -114,8 +114,8 @@ static void wa_xfer_delayed_run(struct wa_rpipe *);
* struct).
*/
struct wa_seg {
- struct urb urb;
- struct urb *dto_urb; /* for data output? */
+ struct urb tr_urb; /* transfer request urb. */
+ struct urb *dto_urb; /* for data output. */
struct list_head list_node; /* for rpipe->req_list */
struct wa_xfer *xfer; /* out xfer */
u8 index; /* which segment we are */
@@ -127,11 +127,11 @@ struct wa_seg {
static inline void wa_seg_init(struct wa_seg *seg)
{
- usb_init_urb(&seg->urb);
+ usb_init_urb(&seg->tr_urb);
/* set the remaining memory to 0. */
- memset(((void *)seg) + sizeof(seg->urb), 0,
- sizeof(*seg) - sizeof(seg->urb));
+ memset(((void *)seg) + sizeof(seg->tr_urb), 0,
+ sizeof(*seg) - sizeof(seg->tr_urb));
}
/*
@@ -178,9 +178,15 @@ static void wa_xfer_destroy(struct kref *_xfer)
if (xfer->seg) {
unsigned cnt;
for (cnt = 0; cnt < xfer->segs; cnt++) {
- usb_free_urb(xfer->seg[cnt]->dto_urb);
- usb_free_urb(&xfer->seg[cnt]->urb);
+ if (xfer->seg[cnt]) {
+ if (xfer->seg[cnt]->dto_urb) {
+ kfree(xfer->seg[cnt]->dto_urb->sg);
+ usb_free_urb(xfer->seg[cnt]->dto_urb);
+ }
+ usb_free_urb(&xfer->seg[cnt]->tr_urb);
+ }
}
+ kfree(xfer->seg);
}
kfree(xfer);
}
@@ -494,12 +500,12 @@ static void __wa_xfer_setup_hdr0(struct wa_xfer *xfer,
/*
* Callback for the OUT data phase of the segment request
*
- * Check wa_seg_cb(); most comments also apply here because this
+ * Check wa_seg_tr_cb(); most comments also apply here because this
* function does almost the same thing and they work closely
* together.
*
* If the seg request has failed but this DTO phase has succeeded,
- * wa_seg_cb() has already failed the segment and moved the
+ * wa_seg_tr_cb() has already failed the segment and moved the
* status to WA_SEG_ERROR, so this will go through 'case 0' and
* effectively do nothing.
*/
@@ -514,6 +520,10 @@ static void wa_seg_dto_cb(struct urb *urb)
unsigned rpipe_ready = 0;
u8 done = 0;
+ /* free the sg if it was used. */
+ kfree(urb->sg);
+ urb->sg = NULL;
+
switch (urb->status) {
case 0:
spin_lock_irqsave(&xfer->lock, flags);
@@ -576,7 +586,7 @@ static void wa_seg_dto_cb(struct urb *urb)
* as in that case, wa_seg_dto_cb will do it when the OUT data phase
* finishes.
*/
-static void wa_seg_cb(struct urb *urb)
+static void wa_seg_tr_cb(struct urb *urb)
{
struct wa_seg *seg = urb->context;
struct wa_xfer *xfer = seg->xfer;
@@ -629,9 +639,11 @@ static void wa_seg_cb(struct urb *urb)
}
}
-/* allocate an SG list to store bytes_to_transfer bytes and copy the
+/*
+ * Allocate an SG list to store bytes_to_transfer bytes and copy the
* subset of the in_sg that matches the buffer subset
- * we are about to transfer. */
+ * we are about to transfer.
+ */
static struct scatterlist *wa_xfer_create_subset_sg(struct scatterlist *in_sg,
const unsigned int bytes_transferred,
const unsigned int bytes_to_transfer, unsigned int *out_num_sgs)
@@ -710,6 +722,55 @@ static struct scatterlist *wa_xfer_create_subset_sg(struct scatterlist *in_sg,
}
/*
+ * Populate buffer ptr and size, DMA buffer or SG list for the dto urb.
+ */
+static int __wa_populate_dto_urb(struct wa_xfer *xfer,
+ struct wa_seg *seg, size_t buf_itr_offset, size_t buf_itr_size)
+{
+ int result = 0;
+
+ if (xfer->is_dma) {
+ seg->dto_urb->transfer_dma =
+ xfer->urb->transfer_dma + buf_itr_offset;
+ seg->dto_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ seg->dto_urb->sg = NULL;
+ seg->dto_urb->num_sgs = 0;
+ } else {
+ /* do buffer or SG processing. */
+ seg->dto_urb->transfer_flags &=
+ ~URB_NO_TRANSFER_DMA_MAP;
+ /* this should always be 0 before a resubmit. */
+ seg->dto_urb->num_mapped_sgs = 0;
+
+ if (xfer->urb->transfer_buffer) {
+ seg->dto_urb->transfer_buffer =
+ xfer->urb->transfer_buffer +
+ buf_itr_offset;
+ seg->dto_urb->sg = NULL;
+ seg->dto_urb->num_sgs = 0;
+ } else {
+ seg->dto_urb->transfer_buffer = NULL;
+
+ /*
+ * allocate an SG list to store seg_size bytes
+ * and copy the subset of the xfer->urb->sg that
+ * matches the buffer subset we are about to
+ * read.
+ */
+ seg->dto_urb->sg = wa_xfer_create_subset_sg(
+ xfer->urb->sg,
+ buf_itr_offset, buf_itr_size,
+ &(seg->dto_urb->num_sgs));
+ if (!(seg->dto_urb->sg))
+ result = -ENOMEM;
+ }
+ }
+ seg->dto_urb->transfer_buffer_length = buf_itr_size;
+
+ return result;
+}
+
+/*
* Allocate the segs array and initialize each of them
*
* The segments are freed by wa_xfer_destroy() when the xfer use count
@@ -740,11 +801,11 @@ static int __wa_xfer_setup_segs(struct wa_xfer *xfer, size_t xfer_hdr_size)
wa_seg_init(seg);
seg->xfer = xfer;
seg->index = cnt;
- usb_fill_bulk_urb(&seg->urb, usb_dev,
+ usb_fill_bulk_urb(&seg->tr_urb, usb_dev,
usb_sndbulkpipe(usb_dev,
dto_epd->bEndpointAddress),
&seg->xfer_hdr, xfer_hdr_size,
- wa_seg_cb, seg);
+ wa_seg_tr_cb, seg);
buf_itr_size = min(buf_size, xfer->seg_size);
if (xfer->is_inbound == 0 && buf_size > 0) {
/* outbound data. */
@@ -756,48 +817,13 @@ static int __wa_xfer_setup_segs(struct wa_xfer *xfer, size_t xfer_hdr_size)
usb_sndbulkpipe(usb_dev,
dto_epd->bEndpointAddress),
NULL, 0, wa_seg_dto_cb, seg);
- if (xfer->is_dma) {
- seg->dto_urb->transfer_dma =
- xfer->urb->transfer_dma + buf_itr;
- seg->dto_urb->transfer_flags |=
- URB_NO_TRANSFER_DMA_MAP;
- seg->dto_urb->transfer_buffer = NULL;
- seg->dto_urb->sg = NULL;
- seg->dto_urb->num_sgs = 0;
- } else {
- /* do buffer or SG processing. */
- seg->dto_urb->transfer_flags &=
- ~URB_NO_TRANSFER_DMA_MAP;
- /* this should always be 0 before a resubmit. */
- seg->dto_urb->num_mapped_sgs = 0;
-
- if (xfer->urb->transfer_buffer) {
- seg->dto_urb->transfer_buffer =
- xfer->urb->transfer_buffer +
- buf_itr;
- seg->dto_urb->sg = NULL;
- seg->dto_urb->num_sgs = 0;
- } else {
- /* allocate an SG list to store seg_size
- bytes and copy the subset of the
- xfer->urb->sg that matches the
- buffer subset we are about to read.
- */
- seg->dto_urb->sg =
- wa_xfer_create_subset_sg(
- xfer->urb->sg,
- buf_itr, buf_itr_size,
- &(seg->dto_urb->num_sgs));
-
- if (!(seg->dto_urb->sg)) {
- seg->dto_urb->num_sgs = 0;
- goto error_sg_alloc;
- }
-
- seg->dto_urb->transfer_buffer = NULL;
- }
- }
- seg->dto_urb->transfer_buffer_length = buf_itr_size;
+
+ /* fill in the xfer buffer information. */
+ result = __wa_populate_dto_urb(xfer, seg,
+ buf_itr, buf_itr_size);
+
+ if (result < 0)
+ goto error_seg_outbound_populate;
}
seg->status = WA_SEG_READY;
buf_itr += buf_itr_size;
@@ -805,20 +831,17 @@ static int __wa_xfer_setup_segs(struct wa_xfer *xfer, size_t xfer_hdr_size)
}
return 0;
-error_sg_alloc:
+ /*
+ * Free the memory for the current segment which failed to init.
+ * Use the fact that cnt is left at were it failed. The remaining
+ * segments will be cleaned up by wa_xfer_destroy.
+ */
+error_seg_outbound_populate:
usb_free_urb(xfer->seg[cnt]->dto_urb);
error_dto_alloc:
kfree(xfer->seg[cnt]);
- cnt--;
+ xfer->seg[cnt] = NULL;
error_seg_kmalloc:
- /* use the fact that cnt is left at were it failed */
- for (; cnt >= 0; cnt--) {
- if (xfer->seg[cnt] && xfer->is_inbound == 0) {
- usb_free_urb(xfer->seg[cnt]->dto_urb);
- kfree(xfer->seg[cnt]->dto_urb->sg);
- }
- kfree(xfer->seg[cnt]);
- }
error_segs_kzalloc:
return result;
}
@@ -888,12 +911,14 @@ static int __wa_seg_submit(struct wa_rpipe *rpipe, struct wa_xfer *xfer,
struct wa_seg *seg)
{
int result;
- result = usb_submit_urb(&seg->urb, GFP_ATOMIC);
+ /* submit the transfer request. */
+ result = usb_submit_urb(&seg->tr_urb, GFP_ATOMIC);
if (result < 0) {
printk(KERN_ERR "xfer %p#%u: REQ submit failed: %d\n",
xfer, seg->index, result);
goto error_seg_submit;
}
+ /* submit the out data if this is an out request. */
if (seg->dto_urb) {
result = usb_submit_urb(seg->dto_urb, GFP_ATOMIC);
if (result < 0) {
@@ -907,7 +932,7 @@ static int __wa_seg_submit(struct wa_rpipe *rpipe, struct wa_xfer *xfer,
return 0;
error_dto_submit:
- usb_unlink_urb(&seg->urb);
+ usb_unlink_urb(&seg->tr_urb);
error_seg_submit:
seg->status = WA_SEG_ERROR;
seg->result = result;
@@ -1313,7 +1338,7 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb)
break;
case WA_SEG_SUBMITTED:
seg->status = WA_SEG_ABORTED;
- usb_unlink_urb(&seg->urb);
+ usb_unlink_urb(&seg->tr_urb);
if (xfer->is_inbound == 0)
usb_unlink_urb(seg->dto_urb);
xfer->segs_done++;
@@ -1416,7 +1441,8 @@ static int wa_xfer_status_to_errno(u8 status)
*
* FIXME: this function needs to be broken up in parts
*/
-static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer)
+static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer,
+ struct wa_xfer_result *xfer_result)
{
int result;
struct device *dev = &wa->usb_iface->dev;
@@ -1424,8 +1450,7 @@ static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer)
u8 seg_idx;
struct wa_seg *seg;
struct wa_rpipe *rpipe;
- struct wa_xfer_result *xfer_result = wa->xfer_result;
- u8 done = 0;
+ unsigned done = 0;
u8 usb_status;
unsigned rpipe_ready = 0;
@@ -1535,6 +1560,7 @@ error_submit_buf_in:
xfer, seg_idx, result);
seg->result = result;
kfree(wa->buf_in_urb->sg);
+ wa->buf_in_urb->sg = NULL;
error_sg_alloc:
__wa_xfer_abort(xfer);
error_complete:
@@ -1552,10 +1578,8 @@ error_complete:
dev_info(dev, "Control EP stall. Queue delayed work.\n");
spin_lock_irq(&wa->xfer_list_lock);
- /* remove xfer from xfer_list. */
- list_del(&xfer->list_node);
- /* add xfer to xfer_errored_list. */
- list_add_tail(&xfer->list_node, &wa->xfer_errored_list);
+ /* 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_irqrestore(&xfer->lock, flags);
queue_work(wusbd, &wa->xfer_error_work);
@@ -1687,7 +1711,7 @@ static void wa_buf_in_cb(struct urb *urb)
* We go back to OFF when we detect a ENOENT or ESHUTDOWN (or too many
* errors) in the URBs.
*/
-static void wa_xfer_result_cb(struct urb *urb)
+static void wa_dti_cb(struct urb *urb)
{
int result;
struct wahc *wa = urb->context;
@@ -1709,7 +1733,7 @@ static void wa_xfer_result_cb(struct urb *urb)
urb->actual_length, sizeof(*xfer_result));
break;
}
- xfer_result = wa->xfer_result;
+ xfer_result = (struct wa_xfer_result *)(wa->dti_buf);
if (xfer_result->hdr.bLength != sizeof(*xfer_result)) {
dev_err(dev, "DTI Error: xfer result--"
"bad header length %u\n",
@@ -1735,7 +1759,7 @@ static void wa_xfer_result_cb(struct urb *urb)
xfer_id, usb_status);
break;
}
- wa_xfer_result_chew(wa, xfer);
+ wa_xfer_result_chew(wa, xfer, xfer_result);
wa_xfer_put(xfer);
break;
case -ENOENT: /* (we killed the URB)...so, no broadcast */
@@ -1777,7 +1801,7 @@ out:
* don't really set it up and start it until the first xfer complete
* notification arrives, which is what we do here.
*
- * Follow up in wa_xfer_result_cb(), as that's where the whole state
+ * Follow up in wa_dti_cb(), as that's where the whole state
* machine starts.
*
* So here we just initialize the DTI URB for reading transfer result
@@ -1813,8 +1837,8 @@ void wa_handle_notif_xfer(struct wahc *wa, struct wa_notif_hdr *notif_hdr)
usb_fill_bulk_urb(
wa->dti_urb, wa->usb_dev,
usb_rcvbulkpipe(wa->usb_dev, 0x80 | notif_xfer->bEndpoint),
- wa->xfer_result, wa->xfer_result_size,
- wa_xfer_result_cb, wa);
+ wa->dti_buf, wa->dti_buf_size,
+ wa_dti_cb, wa);
wa->buf_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (wa->buf_in_urb == NULL) {
@@ -1836,6 +1860,7 @@ out:
error_dti_urb_submit:
usb_put_urb(wa->buf_in_urb);
+ wa->buf_in_urb = NULL;
error_buf_in_urb_alloc:
usb_put_urb(wa->dti_urb);
wa->dti_urb = NULL;
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 84b685f7ab6e..14317b70b413 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -996,6 +996,8 @@ config 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.
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index 0a2cce7285be..b7aa68b3eeff 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -544,7 +544,7 @@ static int clcdfb_register(struct clcd_fb *fb)
static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
{
- struct clcd_board *board = dev->dev.platform_data;
+ struct clcd_board *board = dev_get_platdata(&dev->dev);
struct clcd_fb *fb;
int ret;
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index a6780eecff0e..8ab304d1c855 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -3748,7 +3748,6 @@ default_chipset:
return 0;
unset_drvdata:
- dev_set_drvdata(&pdev->dev, NULL);
fb_dealloc_cmap(&info->cmap);
free_irq:
free_irq(IRQ_AMIGA_COPPER, info->par);
@@ -3768,7 +3767,6 @@ static int __exit amifb_remove(struct platform_device *pdev)
struct fb_info *info = dev_get_drvdata(&pdev->dev);
unregister_framebuffer(info);
- dev_set_drvdata(&pdev->dev, NULL);
fb_dealloc_cmap(&info->cmap);
free_irq(IRQ_AMIGA_COPPER, info->par);
custom.dmacon = DMAF_ALL | DMAF_MASTER;
diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c
index 94a51f1ef904..15dd5423d64a 100644
--- a/drivers/video/arkfb.c
+++ b/drivers/video/arkfb.c
@@ -1048,7 +1048,7 @@ static int ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
rc = register_framebuffer(info);
if (rc < 0) {
- dev_err(info->device, "cannot register framebugger\n");
+ dev_err(info->device, "cannot register framebuffer\n");
goto err_reg_fb;
}
@@ -1108,7 +1108,6 @@ static void ark_pci_remove(struct pci_dev *dev)
pci_release_regions(dev);
/* pci_disable_device(dev); */
- pci_set_drvdata(dev, NULL);
framebuffer_release(info);
}
}
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 088511a58a26..5ac636d9ccc6 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -20,12 +20,55 @@
#include <linux/gfp.h>
#include <linux/module.h>
#include <linux/platform_data/atmel.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <video/of_display_timing.h>
+#include <video/videomode.h>
#include <mach/cpu.h>
#include <asm/gpio.h>
#include <video/atmel_lcdc.h>
+struct atmel_lcdfb_config {
+ bool have_alt_pixclock;
+ bool have_hozval;
+ bool have_intensity_bit;
+};
+
+ /* LCD Controller info data structure, stored in device platform_data */
+struct atmel_lcdfb_info {
+ spinlock_t lock;
+ struct fb_info *info;
+ void __iomem *mmio;
+ int irq_base;
+ struct work_struct task;
+
+ unsigned int smem_len;
+ struct platform_device *pdev;
+ struct clk *bus_clk;
+ struct clk *lcdc_clk;
+
+ struct backlight_device *backlight;
+ u8 bl_power;
+ u8 saved_lcdcon;
+
+ u32 pseudo_palette[16];
+ bool have_intensity_bit;
+
+ struct atmel_lcdfb_pdata pdata;
+
+ struct atmel_lcdfb_config *config;
+};
+
+struct atmel_lcdfb_power_ctrl_gpio {
+ int gpio;
+ int active_low;
+
+ struct list_head list;
+};
+
#define lcdc_readl(sinfo, reg) __raw_readl((sinfo)->mmio+(reg))
#define lcdc_writel(sinfo, reg, val) __raw_writel((val), (sinfo)->mmio+(reg))
@@ -34,12 +77,6 @@
#define ATMEL_LCDC_DMA_BURST_LEN 8 /* words */
#define ATMEL_LCDC_FIFO_SIZE 512 /* words */
-struct atmel_lcdfb_config {
- bool have_alt_pixclock;
- bool have_hozval;
- bool have_intensity_bit;
-};
-
static struct atmel_lcdfb_config at91sam9261_config = {
.have_hozval = true,
.have_intensity_bit = true,
@@ -248,18 +285,27 @@ static void exit_backlight(struct atmel_lcdfb_info *sinfo)
static void init_contrast(struct atmel_lcdfb_info *sinfo)
{
+ struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+
/* contrast pwm can be 'inverted' */
- if (sinfo->lcdcon_pol_negative)
+ if (pdata->lcdcon_pol_negative)
contrast_ctr &= ~(ATMEL_LCDC_POL_POSITIVE);
/* have some default contrast/backlight settings */
lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
- if (sinfo->lcdcon_is_backlight)
+ if (pdata->lcdcon_is_backlight)
init_backlight(sinfo);
}
+static inline void atmel_lcdfb_power_control(struct atmel_lcdfb_info *sinfo, int on)
+{
+ struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+
+ if (pdata->atmel_lcdfb_power_control)
+ pdata->atmel_lcdfb_power_control(pdata, on);
+}
static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = {
.type = FB_TYPE_PACKED_PIXELS,
@@ -299,9 +345,11 @@ static unsigned long compute_hozval(struct atmel_lcdfb_info *sinfo,
static void atmel_lcdfb_stop_nowait(struct atmel_lcdfb_info *sinfo)
{
+ struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+
/* Turn off the LCD controller and the DMA controller */
lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
- sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
+ pdata->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
/* Wait for the LCDC core to become idle */
while (lcdc_readl(sinfo, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
@@ -321,9 +369,11 @@ static void atmel_lcdfb_stop(struct atmel_lcdfb_info *sinfo)
static void atmel_lcdfb_start(struct atmel_lcdfb_info *sinfo)
{
- lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
+ struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+
+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, pdata->default_dmacon);
lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
- (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET)
+ (pdata->guard_time << ATMEL_LCDC_GUARDT_OFFSET)
| ATMEL_LCDC_PWR);
}
@@ -424,6 +474,7 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
{
struct device *dev = info->device;
struct atmel_lcdfb_info *sinfo = info->par;
+ struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
unsigned long clk_value_khz;
clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
@@ -510,7 +561,7 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
else
var->green.length = 6;
- if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
+ if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
/* RGB:5X5 mode */
var->red.offset = var->green.length + 5;
var->blue.offset = 0;
@@ -527,7 +578,7 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
var->transp.length = 8;
/* fall through */
case 24:
- if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
+ if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
/* RGB:888 mode */
var->red.offset = 16;
var->blue.offset = 0;
@@ -576,6 +627,7 @@ static void atmel_lcdfb_reset(struct atmel_lcdfb_info *sinfo)
static int atmel_lcdfb_set_par(struct fb_info *info)
{
struct atmel_lcdfb_info *sinfo = info->par;
+ struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
unsigned long hozval_linesz;
unsigned long value;
unsigned long clk_value_khz;
@@ -637,7 +689,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
/* Initialize control register 2 */
- value = sinfo->default_lcdcon2;
+ value = pdata->default_lcdcon2;
if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
value |= ATMEL_LCDC_INVLINE_INVERTED;
@@ -741,6 +793,7 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
unsigned int transp, struct fb_info *info)
{
struct atmel_lcdfb_info *sinfo = info->par;
+ struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
unsigned int val;
u32 *pal;
int ret = 1;
@@ -777,8 +830,7 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
*/
} else {
/* new style BGR:565 / RGB:565 */
- if (sinfo->lcd_wiring_mode ==
- ATMEL_LCDC_WIRING_RGB) {
+ if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
val = ((blue >> 11) & 0x001f);
val |= ((red >> 0) & 0xf800);
} else {
@@ -912,16 +964,187 @@ static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo)
clk_disable_unprepare(sinfo->lcdc_clk);
}
+#ifdef CONFIG_OF
+static const struct of_device_id atmel_lcdfb_dt_ids[] = {
+ { .compatible = "atmel,at91sam9261-lcdc" , .data = &at91sam9261_config, },
+ { .compatible = "atmel,at91sam9263-lcdc" , .data = &at91sam9263_config, },
+ { .compatible = "atmel,at91sam9g10-lcdc" , .data = &at91sam9g10_config, },
+ { .compatible = "atmel,at91sam9g45-lcdc" , .data = &at91sam9g45_config, },
+ { .compatible = "atmel,at91sam9g45es-lcdc" , .data = &at91sam9g45es_config, },
+ { .compatible = "atmel,at91sam9rl-lcdc" , .data = &at91sam9rl_config, },
+ { .compatible = "atmel,at32ap-lcdc" , .data = &at32ap_config, },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, atmel_lcdfb_dt_ids);
+
+static const char *atmel_lcdfb_wiring_modes[] = {
+ [ATMEL_LCDC_WIRING_BGR] = "BRG",
+ [ATMEL_LCDC_WIRING_RGB] = "RGB",
+};
+
+const int atmel_lcdfb_get_of_wiring_modes(struct device_node *np)
+{
+ const char *mode;
+ int err, i;
+
+ err = of_property_read_string(np, "atmel,lcd-wiring-mode", &mode);
+ if (err < 0)
+ return ATMEL_LCDC_WIRING_BGR;
+
+ for (i = 0; i < ARRAY_SIZE(atmel_lcdfb_wiring_modes); i++)
+ if (!strcasecmp(mode, atmel_lcdfb_wiring_modes[i]))
+ return i;
+
+ return -ENODEV;
+}
+
+static void atmel_lcdfb_power_control_gpio(struct atmel_lcdfb_pdata *pdata, int on)
+{
+ struct atmel_lcdfb_power_ctrl_gpio *og;
+
+ list_for_each_entry(og, &pdata->pwr_gpios, list)
+ gpio_set_value(og->gpio, on);
+}
+
+static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
+{
+ struct fb_info *info = sinfo->info;
+ struct atmel_lcdfb_pdata *pdata = &sinfo->pdata;
+ struct fb_var_screeninfo *var = &info->var;
+ struct device *dev = &sinfo->pdev->dev;
+ struct device_node *np =dev->of_node;
+ struct device_node *display_np;
+ struct device_node *timings_np;
+ struct display_timings *timings;
+ enum of_gpio_flags flags;
+ struct atmel_lcdfb_power_ctrl_gpio *og;
+ bool is_gpio_power = false;
+ int ret = -ENOENT;
+ int i, gpio;
+
+ sinfo->config = (struct atmel_lcdfb_config*)
+ of_match_device(atmel_lcdfb_dt_ids, dev)->data;
+
+ display_np = of_parse_phandle(np, "display", 0);
+ if (!display_np) {
+ dev_err(dev, "failed to find display phandle\n");
+ return -ENOENT;
+ }
+
+ ret = of_property_read_u32(display_np, "bits-per-pixel", &var->bits_per_pixel);
+ if (ret < 0) {
+ dev_err(dev, "failed to get property bits-per-pixel\n");
+ goto put_display_node;
+ }
+
+ ret = of_property_read_u32(display_np, "atmel,guard-time", &pdata->guard_time);
+ if (ret < 0) {
+ dev_err(dev, "failed to get property atmel,guard-time\n");
+ goto put_display_node;
+ }
+
+ ret = of_property_read_u32(display_np, "atmel,lcdcon2", &pdata->default_lcdcon2);
+ if (ret < 0) {
+ dev_err(dev, "failed to get property atmel,lcdcon2\n");
+ goto put_display_node;
+ }
+
+ ret = of_property_read_u32(display_np, "atmel,dmacon", &pdata->default_dmacon);
+ if (ret < 0) {
+ dev_err(dev, "failed to get property bits-per-pixel\n");
+ goto put_display_node;
+ }
+
+ ret = -ENOMEM;
+ for (i = 0; i < of_gpio_named_count(display_np, "atmel,power-control-gpio"); i++) {
+ gpio = of_get_named_gpio_flags(display_np, "atmel,power-control-gpio",
+ i, &flags);
+ if (gpio < 0)
+ continue;
+
+ og = devm_kzalloc(dev, sizeof(*og), GFP_KERNEL);
+ if (!og)
+ goto put_display_node;
+
+ og->gpio = gpio;
+ og->active_low = flags & OF_GPIO_ACTIVE_LOW;
+ is_gpio_power = true;
+ ret = devm_gpio_request(dev, gpio, "lcd-power-control-gpio");
+ if (ret) {
+ dev_err(dev, "request gpio %d failed\n", gpio);
+ goto put_display_node;
+ }
+
+ ret = gpio_direction_output(gpio, og->active_low);
+ if (ret) {
+ dev_err(dev, "set direction output gpio %d failed\n", gpio);
+ goto put_display_node;
+ }
+ }
+
+ if (is_gpio_power)
+ pdata->atmel_lcdfb_power_control = atmel_lcdfb_power_control_gpio;
+
+ ret = atmel_lcdfb_get_of_wiring_modes(display_np);
+ if (ret < 0) {
+ dev_err(dev, "invalid atmel,lcd-wiring-mode\n");
+ goto put_display_node;
+ }
+ pdata->lcd_wiring_mode = ret;
+
+ pdata->lcdcon_is_backlight = of_property_read_bool(display_np, "atmel,lcdcon-backlight");
+
+ timings = of_get_display_timings(display_np);
+ if (!timings) {
+ dev_err(dev, "failed to get display timings\n");
+ goto put_display_node;
+ }
+
+ timings_np = of_find_node_by_name(display_np, "display-timings");
+ if (!timings_np) {
+ dev_err(dev, "failed to find display-timings node\n");
+ goto put_display_node;
+ }
+
+ for (i = 0; i < of_get_child_count(timings_np); i++) {
+ struct videomode vm;
+ struct fb_videomode fb_vm;
+
+ ret = videomode_from_timings(timings, &vm, i);
+ if (ret < 0)
+ goto put_timings_node;
+ ret = fb_videomode_from_videomode(&vm, &fb_vm);
+ if (ret < 0)
+ goto put_timings_node;
+
+ fb_add_videomode(&fb_vm, &info->modelist);
+ }
+
+ return 0;
+
+put_timings_node:
+ of_node_put(timings_np);
+put_display_node:
+ of_node_put(display_np);
+ return ret;
+}
+#else
+static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
+{
+ return 0;
+}
+#endif
static int __init atmel_lcdfb_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct fb_info *info;
struct atmel_lcdfb_info *sinfo;
- struct atmel_lcdfb_info *pdata_sinfo;
- struct fb_videomode fbmode;
+ struct atmel_lcdfb_pdata *pdata = NULL;
struct resource *regs = NULL;
struct resource *map = NULL;
+ struct fb_modelist *modelist;
int ret;
dev_dbg(dev, "%s BEGIN\n", __func__);
@@ -934,26 +1157,35 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
}
sinfo = info->par;
+ sinfo->pdev = pdev;
+ sinfo->info = info;
+
+ INIT_LIST_HEAD(&info->modelist);
- if (dev->platform_data) {
- pdata_sinfo = (struct atmel_lcdfb_info *)dev->platform_data;
- sinfo->default_bpp = pdata_sinfo->default_bpp;
- sinfo->default_dmacon = pdata_sinfo->default_dmacon;
- sinfo->default_lcdcon2 = pdata_sinfo->default_lcdcon2;
- sinfo->default_monspecs = pdata_sinfo->default_monspecs;
- sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control;
- sinfo->guard_time = pdata_sinfo->guard_time;
- sinfo->smem_len = pdata_sinfo->smem_len;
- sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight;
- sinfo->lcdcon_pol_negative = pdata_sinfo->lcdcon_pol_negative;
- sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode;
+ if (pdev->dev.of_node) {
+ ret = atmel_lcdfb_of_init(sinfo);
+ if (ret)
+ goto free_info;
+ } else if (dev_get_platdata(dev)) {
+ struct fb_monspecs *monspecs;
+ int i;
+
+ pdata = dev_get_platdata(dev);
+ monspecs = pdata->default_monspecs;
+ sinfo->pdata = *pdata;
+
+ for (i = 0; i < monspecs->modedb_len; i++)
+ fb_add_videomode(&monspecs->modedb[i], &info->modelist);
+
+ sinfo->config = atmel_lcdfb_get_config(pdev);
+
+ info->var.bits_per_pixel = pdata->default_bpp ? pdata->default_bpp : 16;
+ memcpy(&info->monspecs, pdata->default_monspecs, sizeof(info->monspecs));
} else {
dev_err(dev, "cannot get default configuration\n");
goto free_info;
}
- sinfo->info = info;
- sinfo->pdev = pdev;
- sinfo->config = atmel_lcdfb_get_config(pdev);
+
if (!sinfo->config)
goto free_info;
@@ -962,7 +1194,6 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
info->pseudo_palette = sinfo->pseudo_palette;
info->fbops = &atmel_lcdfb_ops;
- memcpy(&info->monspecs, sinfo->default_monspecs, sizeof(info->monspecs));
info->fix = atmel_lcdfb_fix;
/* Enable LCDC Clocks */
@@ -978,14 +1209,11 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
}
atmel_lcdfb_start_clock(sinfo);
- ret = fb_find_mode(&info->var, info, NULL, info->monspecs.modedb,
- info->monspecs.modedb_len, info->monspecs.modedb,
- sinfo->default_bpp);
- if (!ret) {
- dev_err(dev, "no suitable video mode found\n");
- goto stop_clk;
- }
+ modelist = list_first_entry(&info->modelist,
+ struct fb_modelist, list);
+ fb_videomode_to_var(&info->var, &modelist->mode);
+ atmel_lcdfb_check_var(&info->var, info);
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs) {
@@ -1069,18 +1297,6 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
goto unregister_irqs;
}
- /*
- * This makes sure that our colour bitfield
- * descriptors are correctly initialised.
- */
- atmel_lcdfb_check_var(&info->var, info);
-
- ret = fb_set_var(info, &info->var);
- if (ret) {
- dev_warn(dev, "unable to set display parameters\n");
- goto free_cmap;
- }
-
dev_set_drvdata(dev, info);
/*
@@ -1089,24 +1305,17 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
ret = register_framebuffer(info);
if (ret < 0) {
dev_err(dev, "failed to register framebuffer device: %d\n", ret);
- goto reset_drvdata;
+ goto free_cmap;
}
- /* add selected videomode to modelist */
- fb_var_to_videomode(&fbmode, &info->var);
- fb_add_videomode(&fbmode, &info->modelist);
-
/* Power up the LCDC screen */
- if (sinfo->atmel_lcdfb_power_control)
- sinfo->atmel_lcdfb_power_control(1);
+ atmel_lcdfb_power_control(sinfo, 1);
dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %d\n",
info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base);
return 0;
-reset_drvdata:
- dev_set_drvdata(dev, NULL);
free_cmap:
fb_dealloc_cmap(&info->cmap);
unregister_irqs:
@@ -1143,15 +1352,16 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct fb_info *info = dev_get_drvdata(dev);
struct atmel_lcdfb_info *sinfo;
+ struct atmel_lcdfb_pdata *pdata;
if (!info || !info->par)
return 0;
sinfo = info->par;
+ pdata = &sinfo->pdata;
cancel_work_sync(&sinfo->task);
exit_backlight(sinfo);
- if (sinfo->atmel_lcdfb_power_control)
- sinfo->atmel_lcdfb_power_control(0);
+ atmel_lcdfb_power_control(sinfo, 0);
unregister_framebuffer(info);
atmel_lcdfb_stop_clock(sinfo);
clk_put(sinfo->lcdc_clk);
@@ -1167,7 +1377,6 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
atmel_lcdfb_free_video_memory(sinfo);
}
- dev_set_drvdata(dev, NULL);
framebuffer_release(info);
return 0;
@@ -1188,9 +1397,7 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)
sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_CTR);
lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);
- if (sinfo->atmel_lcdfb_power_control)
- sinfo->atmel_lcdfb_power_control(0);
-
+ atmel_lcdfb_power_control(sinfo, 0);
atmel_lcdfb_stop(sinfo);
atmel_lcdfb_stop_clock(sinfo);
@@ -1204,8 +1411,7 @@ static int atmel_lcdfb_resume(struct platform_device *pdev)
atmel_lcdfb_start_clock(sinfo);
atmel_lcdfb_start(sinfo);
- if (sinfo->atmel_lcdfb_power_control)
- sinfo->atmel_lcdfb_power_control(1);
+ atmel_lcdfb_power_control(sinfo, 1);
lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon);
/* Enable FIFO & DMA errors */
@@ -1228,6 +1434,7 @@ static struct platform_driver atmel_lcdfb_driver = {
.driver = {
.name = "atmel_lcdfb",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(atmel_lcdfb_dt_ids),
},
};
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index a4dfe8cb0a0a..b5edb6f08b84 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -413,7 +413,6 @@ struct aty128fb_par {
int blitter_may_be_busy;
int fifo_slots; /* free slots in FIFO (64 max) */
- int pm_reg;
int crt_on, lcd_on;
struct pci_dev *pdev;
struct fb_info *next;
@@ -2016,7 +2015,6 @@ static int aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
aty128_init_engine(par);
- par->pm_reg = pdev->pm_cap;
par->pdev = pdev;
par->asleep = 0;
par->lock_blank = 0;
@@ -2397,7 +2395,7 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend)
u32 pmgt;
struct pci_dev *pdev = par->pdev;
- if (!par->pm_reg)
+ if (!par->pdev->pm_cap)
return;
/* Set the chip into the appropriate suspend mode (we use D2,
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 9b0f12c5c284..28fafbf864a5 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -1848,7 +1848,6 @@ static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
return aty_waitforvblank(par, crtc);
}
- break;
#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
case ATYIO_CLKR:
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 1e30b2b3e79f..26d80a4486fb 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -819,11 +819,6 @@ static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *in
if (v.xres_virtual < v.xres)
v.xres = v.xres_virtual;
- if (v.xoffset < 0)
- v.xoffset = 0;
- if (v.yoffset < 0)
- v.yoffset = 0;
-
if (v.xoffset > v.xres_virtual - v.xres)
v.xoffset = v.xres_virtual - v.xres - 1;
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index f7091ece580d..46a12f1a93c3 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -1427,6 +1427,8 @@ static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo)
mdelay( 15);
}
+#if defined(CONFIG_PM)
+#if defined(CONFIG_X86) || defined(CONFIG_PPC_PMAC)
static void radeon_pm_reset_pad_ctlr_strength(struct radeonfb_info *rinfo)
{
u32 tmp, tmp2;
@@ -1939,9 +1941,10 @@ static void radeon_reinitialize_M10(struct radeonfb_info *rinfo)
*/
radeon_pm_m10_enable_lvds_spread_spectrum(rinfo);
}
+#endif
#ifdef CONFIG_PPC_OF
-
+#ifdef CONFIG_PPC_PMAC
static void radeon_pm_m9p_reconfigure_mc(struct radeonfb_info *rinfo)
{
OUTREG(MC_CNTL, rinfo->save_regs[46]);
@@ -2202,6 +2205,8 @@ static void radeon_reinitialize_M9P(struct radeonfb_info *rinfo)
radeon_pm_restore_pixel_pll(rinfo);
radeon_pm_m10_enable_lvds_spread_spectrum(rinfo);
}
+#endif
+#endif
#if 0 /* Not ready yet */
static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
@@ -2515,13 +2520,13 @@ static void radeonfb_whack_power_state(struct radeonfb_info *rinfo, pci_power_t
for (;;) {
pci_read_config_word(rinfo->pdev,
- rinfo->pm_reg+PCI_PM_CTRL,
+ rinfo->pdev->pm_cap + PCI_PM_CTRL,
&pwr_cmd);
- if (pwr_cmd & 2)
+ if (pwr_cmd & state)
break;
- pwr_cmd = (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2;
+ pwr_cmd = (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | state;
pci_write_config_word(rinfo->pdev,
- rinfo->pm_reg+PCI_PM_CTRL,
+ rinfo->pdev->pm_cap + PCI_PM_CTRL,
pwr_cmd);
msleep(500);
}
@@ -2532,7 +2537,7 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
{
u32 tmp;
- if (!rinfo->pm_reg)
+ if (!rinfo->pdev->pm_cap)
return;
/* Set the chip into appropriate suspend mode (we use D2,
@@ -2804,9 +2809,6 @@ static void radeonfb_early_resume(void *data)
void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep)
{
- /* Find PM registers in config space if any*/
- rinfo->pm_reg = rinfo->pdev->pm_cap;
-
/* Enable/Disable dynamic clocks: TODO add sysfs access */
if (rinfo->family == CHIP_FAMILY_RS480)
rinfo->dynclk = -1;
@@ -2830,7 +2832,7 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlis
* reason. --BenH
*/
if (machine_is(powermac) && rinfo->of_node) {
- if (rinfo->is_mobility && rinfo->pm_reg &&
+ if (rinfo->is_mobility && rinfo->pdev->pm_cap &&
rinfo->family <= CHIP_FAMILY_RV250)
rinfo->pm_mode |= radeon_pm_d2;
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index 7351e66c7f54..cb846044f57c 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -342,7 +342,6 @@ struct radeonfb_info {
int mtrr_hdl;
- int pm_reg;
u32 save_regs[100];
int asleep;
int lock_blank;
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index a54ccdc4d661..248abd50ca25 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -588,7 +588,7 @@ int au1100fb_drv_remove(struct platform_device *dev)
if (!dev)
return -ENODEV;
- fbdev = (struct au1100fb_device *) platform_get_drvdata(dev);
+ fbdev = platform_get_drvdata(dev);
#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info);
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c
index 8993c24ce705..66885fbb8e97 100644
--- a/drivers/video/backlight/atmel-pwm-bl.c
+++ b/drivers/video/backlight/atmel-pwm-bl.c
@@ -118,7 +118,7 @@ static const struct backlight_ops atmel_pwm_bl_ops = {
.update_status = atmel_pwm_bl_set_intensity,
};
-static int __init atmel_pwm_bl_probe(struct platform_device *pdev)
+static int atmel_pwm_bl_probe(struct platform_device *pdev)
{
struct backlight_properties props;
const struct atmel_pwm_bl_platform_data *pdata;
@@ -201,7 +201,7 @@ err_free_mem:
return retval;
}
-static int __exit atmel_pwm_bl_remove(struct platform_device *pdev)
+static int atmel_pwm_bl_remove(struct platform_device *pdev)
{
struct atmel_pwm_bl *pwmbl = platform_get_drvdata(pdev);
@@ -218,10 +218,11 @@ static struct platform_driver atmel_pwm_bl_driver = {
.name = "atmel-pwm-bl",
},
/* REVISIT add suspend() and resume() */
- .remove = __exit_p(atmel_pwm_bl_remove),
+ .probe = atmel_pwm_bl_probe,
+ .remove = atmel_pwm_bl_remove,
};
-module_platform_driver_probe(atmel_pwm_bl_driver, atmel_pwm_bl_probe);
+module_platform_driver(atmel_pwm_bl_driver);
MODULE_AUTHOR("Hans-Christian egtvedt <hans-christian.egtvedt@atmel.com>");
MODULE_DESCRIPTION("Atmel PWM backlight driver");
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index 60017fc634b5..bc123d6947a4 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -363,8 +363,6 @@ static int bw2_remove(struct platform_device *op)
framebuffer_release(info);
- dev_set_drvdata(&op->dev, NULL);
-
return 0;
}
diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c
index 153dd65b0ae8..b98f709abf52 100644
--- a/drivers/video/carminefb.c
+++ b/drivers/video/carminefb.c
@@ -746,7 +746,6 @@ static void carminefb_remove(struct pci_dev *dev)
iounmap(hw->v_regs);
release_mem_region(fix.mmio_start, fix.mmio_len);
- pci_set_drvdata(dev, NULL);
pci_disable_device(dev);
kfree(hw);
}
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index ed3b8891e006..9626488a69c5 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -583,8 +583,6 @@ static int cg14_remove(struct platform_device *op)
framebuffer_release(info);
- dev_set_drvdata(&op->dev, NULL);
-
return 0;
}
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index 9f63507ded37..64a89d5747ed 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -446,8 +446,6 @@ static int cg3_remove(struct platform_device *op)
framebuffer_release(info);
- dev_set_drvdata(&op->dev, NULL);
-
return 0;
}
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
index 3545decc7485..f070ec3b0f0a 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/cg6.c
@@ -839,8 +839,6 @@ static int cg6_remove(struct platform_device *op)
framebuffer_release(info);
- dev_set_drvdata(&op->dev, NULL);
-
return 0;
}
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 97db3ba8f237..5aab9b9dc210 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -595,11 +595,6 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
return -EINVAL;
}
- if (var->xoffset < 0)
- var->xoffset = 0;
- if (var->yoffset < 0)
- var->yoffset = 0;
-
/* truncate xoffset and yoffset to maximum if too high */
if (var->xoffset > var->xres_virtual - var->xres)
var->xoffset = var->xres_virtual - var->xres - 1;
@@ -2159,7 +2154,6 @@ static int cirrusfb_pci_register(struct pci_dev *pdev,
if (!ret)
return 0;
- pci_set_drvdata(pdev, NULL);
iounmap(info->screen_base);
err_release_legacy:
if (release_io_ports)
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index 57886787ead0..b0a950f36970 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -1641,67 +1641,6 @@ static void cyberpro_common_resume(struct cfb_info *cfb)
cyber2000fb_set_par(&cfb->fb);
}
-#ifdef CONFIG_ARCH_SHARK
-
-#include <mach/framebuffer.h>
-
-static int cyberpro_vl_probe(void)
-{
- struct cfb_info *cfb;
- int err = -ENOMEM;
-
- if (!request_mem_region(FB_START, FB_SIZE, "CyberPro2010"))
- return err;
-
- cfb = cyberpro_alloc_fb_info(ID_CYBERPRO_2010, "CyberPro2010");
- if (!cfb)
- goto failed_release;
-
- cfb->irq = -1;
- cfb->region = ioremap(FB_START, FB_SIZE);
- if (!cfb->region)
- goto failed_ioremap;
-
- cfb->regs = cfb->region + MMIO_OFFSET;
- cfb->fb.device = NULL;
- cfb->fb.fix.mmio_start = FB_START + MMIO_OFFSET;
- cfb->fb.fix.smem_start = FB_START;
-
- /*
- * Bring up the hardware. This is expected to enable access
- * to the linear memory region, and allow access to the memory
- * mapped registers. Also, mem_ctl1 and mem_ctl2 must be
- * initialised.
- */
- cyber2000fb_writeb(0x18, 0x46e8, cfb);
- cyber2000fb_writeb(0x01, 0x102, cfb);
- cyber2000fb_writeb(0x08, 0x46e8, cfb);
- cyber2000fb_writeb(EXT_BIU_MISC, 0x3ce, cfb);
- cyber2000fb_writeb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf, cfb);
-
- cfb->mclk_mult = 0xdb;
- cfb->mclk_div = 0x54;
-
- err = cyberpro_common_probe(cfb);
- if (err)
- goto failed;
-
- if (int_cfb_info == NULL)
- int_cfb_info = cfb;
-
- return 0;
-
-failed:
- iounmap(cfb->region);
-failed_ioremap:
- cyberpro_free_fb_info(cfb);
-failed_release:
- release_mem_region(FB_START, FB_SIZE);
-
- return err;
-}
-#endif /* CONFIG_ARCH_SHARK */
-
/*
* PCI specific support.
*/
@@ -1871,11 +1810,6 @@ static void cyberpro_pci_remove(struct pci_dev *dev)
iounmap(cfb->region);
cyberpro_free_fb_info(cfb);
- /*
- * Ensure that the driver data is no longer
- * valid.
- */
- pci_set_drvdata(dev, NULL);
if (cfb == int_cfb_info)
int_cfb_info = NULL;
@@ -1948,28 +1882,19 @@ static int __init cyber2000fb_init(void)
cyber2000fb_setup(option);
#endif
-#ifdef CONFIG_ARCH_SHARK
- err = cyberpro_vl_probe();
- if (!err)
- ret = 0;
-#endif
-#ifdef CONFIG_PCI
err = pci_register_driver(&cyberpro_driver);
if (!err)
ret = 0;
-#endif
return ret ? err : 0;
}
module_init(cyber2000fb_init);
-#ifndef CONFIG_ARCH_SHARK
static void __exit cyberpro_exit(void)
{
pci_unregister_driver(&cyberpro_driver);
}
module_exit(cyberpro_exit);
-#endif
MODULE_AUTHOR("Russell King");
MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver");
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index e030e17a83f2..0670c85bef44 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -1314,7 +1314,7 @@ static struct fb_ops da8xx_fb_ops = {
static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev)
{
- struct da8xx_lcdc_platform_data *fb_pdata = dev->dev.platform_data;
+ struct da8xx_lcdc_platform_data *fb_pdata = dev_get_platdata(&dev->dev);
struct fb_videomode *lcdc_info;
int i;
@@ -1336,7 +1336,7 @@ static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev)
static int fb_probe(struct platform_device *device)
{
struct da8xx_lcdc_platform_data *fb_pdata =
- device->dev.platform_data;
+ dev_get_platdata(&device->dev);
static struct resource *lcdc_regs;
struct lcd_ctrl_config *lcd_cfg;
struct fb_videomode *lcdc_info;
@@ -1548,7 +1548,7 @@ err_pm_runtime_disable:
}
#ifdef CONFIG_PM
-struct lcdc_context {
+static struct lcdc_context {
u32 clk_enable;
u32 ctrl;
u32 dma_ctrl;
diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c
index 28a837dfddd1..35a0f533f1a2 100644
--- a/drivers/video/ep93xx-fb.c
+++ b/drivers/video/ep93xx-fb.c
@@ -487,7 +487,7 @@ static void ep93xxfb_dealloc_videomem(struct fb_info *info)
static int ep93xxfb_probe(struct platform_device *pdev)
{
- struct ep93xxfb_mach_info *mach_info = pdev->dev.platform_data;
+ struct ep93xxfb_mach_info *mach_info = dev_get_platdata(&pdev->dev);
struct fb_info *info;
struct ep93xx_fbi *fbi;
struct resource *res;
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index 6d2744794dd1..4c4ffa61ae26 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -1035,8 +1035,6 @@ static int ffb_remove(struct platform_device *op)
framebuffer_release(info);
- dev_set_drvdata(&op->dev, NULL);
-
return 0;
}
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c
index ebbaada7b941..7551a04f5c31 100644
--- a/drivers/video/geode/gx1fb_core.c
+++ b/drivers/video/geode/gx1fb_core.c
@@ -399,7 +399,6 @@ static void gx1fb_remove(struct pci_dev *pdev)
release_mem_region(gx1_gx_base() + 0x8300, 0x100);
fb_dealloc_cmap(&info->cmap);
- pci_set_drvdata(pdev, NULL);
framebuffer_release(info);
}
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c
index 19f0c1add747..a42d74d6eded 100644
--- a/drivers/video/geode/gxfb_core.c
+++ b/drivers/video/geode/gxfb_core.c
@@ -471,7 +471,6 @@ static void gxfb_remove(struct pci_dev *pdev)
pci_release_region(pdev, 1);
fb_dealloc_cmap(&info->cmap);
- pci_set_drvdata(pdev, NULL);
framebuffer_release(info);
}
diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c
index 4dd7b5566962..10de31b21d0a 100644
--- a/drivers/video/geode/lxfb_core.c
+++ b/drivers/video/geode/lxfb_core.c
@@ -606,7 +606,6 @@ static void lxfb_remove(struct pci_dev *pdev)
pci_release_region(pdev, 3);
fb_dealloc_cmap(&info->cmap);
- pci_set_drvdata(pdev, NULL);
framebuffer_release(info);
}
diff --git a/drivers/video/grvga.c b/drivers/video/grvga.c
index 861109e7de1b..c078701f15f6 100644
--- a/drivers/video/grvga.c
+++ b/drivers/video/grvga.c
@@ -496,7 +496,6 @@ static int grvga_probe(struct platform_device *dev)
return 0;
free_mem:
- dev_set_drvdata(&dev->dev, NULL);
if (grvga_fix_addr)
iounmap((void *)virtual_start);
else
@@ -530,7 +529,6 @@ static int grvga_remove(struct platform_device *device)
kfree((void *)info->screen_base);
framebuffer_release(info);
- dev_set_drvdata(&device->dev, NULL);
}
return 0;
@@ -557,19 +555,7 @@ static struct platform_driver grvga_driver = {
.remove = grvga_remove,
};
-
-static int __init grvga_init(void)
-{
- return platform_driver_register(&grvga_driver);
-}
-
-static void __exit grvga_exit(void)
-{
- platform_driver_unregister(&grvga_driver);
-}
-
-module_init(grvga_init);
-module_exit(grvga_exit);
+module_platform_driver(grvga_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Aeroflex Gaisler");
diff --git a/drivers/video/i740fb.c b/drivers/video/i740fb.c
index 6c4838818950..6501ac1dba0f 100644
--- a/drivers/video/i740fb.c
+++ b/drivers/video/i740fb.c
@@ -1194,7 +1194,6 @@ static void i740fb_remove(struct pci_dev *dev)
pci_iounmap(dev, info->screen_base);
pci_release_regions(dev);
/* pci_disable_device(dev); */
- pci_set_drvdata(dev, NULL);
framebuffer_release(info);
}
}
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index 4ce3438ade6f..038192ac7369 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -2129,7 +2129,6 @@ static void __exit i810fb_remove_pci(struct pci_dev *dev)
unregister_framebuffer(info);
i810fb_release_resource(info, par);
- pci_set_drvdata(dev, NULL);
printk("cleanup_module: unloaded i810 framebuffer device\n");
}
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 38733ac2b698..44ee678481d5 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -755,7 +755,7 @@ static int imxfb_resume(struct platform_device *dev)
static int imxfb_init_fbinfo(struct platform_device *pdev)
{
- struct imx_fb_platform_data *pdata = pdev->dev.platform_data;
+ struct imx_fb_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct fb_info *info = dev_get_drvdata(&pdev->dev);
struct imxfb_info *fbi = info->par;
struct device_node *np;
@@ -877,7 +877,7 @@ static int imxfb_probe(struct platform_device *pdev)
if (!res)
return -ENODEV;
- pdata = pdev->dev.platform_data;
+ pdata = dev_get_platdata(&pdev->dev);
info = framebuffer_alloc(sizeof(struct imxfb_info), &pdev->dev);
if (!info)
@@ -1066,7 +1066,7 @@ static int imxfb_remove(struct platform_device *pdev)
#endif
unregister_framebuffer(info);
- pdata = pdev->dev.platform_data;
+ pdata = dev_get_platdata(&pdev->dev);
if (pdata && pdata->exit)
pdata->exit(fbi->pdev);
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 8209e46c5d28..b847d530471a 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -931,8 +931,6 @@ static void intelfb_pci_unregister(struct pci_dev *pdev)
return;
cleanup(dinfo);
-
- pci_set_drvdata(pdev, NULL);
}
/***************************************************************
diff --git a/drivers/video/jz4740_fb.c b/drivers/video/jz4740_fb.c
index 2c49112fdd6c..3f99dcb28b09 100644
--- a/drivers/video/jz4740_fb.c
+++ b/drivers/video/jz4740_fb.c
@@ -99,9 +99,9 @@
#define JZ_LCD_CTRL_BPP_15_16 0x4
#define JZ_LCD_CTRL_BPP_18_24 0x5
-#define JZ_LCD_CMD_SOF_IRQ BIT(15)
-#define JZ_LCD_CMD_EOF_IRQ BIT(16)
-#define JZ_LCD_CMD_ENABLE_PAL BIT(12)
+#define JZ_LCD_CMD_SOF_IRQ BIT(31)
+#define JZ_LCD_CMD_EOF_IRQ BIT(30)
+#define JZ_LCD_CMD_ENABLE_PAL BIT(28)
#define JZ_LCD_SYNC_MASK 0x3ff
@@ -471,7 +471,7 @@ static int jzfb_set_par(struct fb_info *info)
writel(ctrl, jzfb->base + JZ_REG_LCD_CTRL);
if (!jzfb->is_enabled)
- clk_disable(jzfb->ldclk);
+ clk_disable_unprepare(jzfb->ldclk);
mutex_unlock(&jzfb->lock);
@@ -485,7 +485,7 @@ static void jzfb_enable(struct jzfb *jzfb)
{
uint32_t ctrl;
- clk_enable(jzfb->ldclk);
+ clk_prepare_enable(jzfb->ldclk);
jz_gpio_bulk_resume(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
jz_gpio_bulk_resume(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
@@ -514,7 +514,7 @@ static void jzfb_disable(struct jzfb *jzfb)
jz_gpio_bulk_suspend(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
jz_gpio_bulk_suspend(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
- clk_disable(jzfb->ldclk);
+ clk_disable_unprepare(jzfb->ldclk);
}
static int jzfb_blank(int blank_mode, struct fb_info *info)
@@ -693,7 +693,7 @@ static int jzfb_probe(struct platform_device *pdev)
fb_alloc_cmap(&fb->cmap, 256, 0);
- clk_enable(jzfb->ldclk);
+ clk_prepare_enable(jzfb->ldclk);
jzfb->is_enabled = 1;
writel(jzfb->framedesc->next, jzfb->base + JZ_REG_LCD_DA0);
@@ -763,7 +763,7 @@ static int jzfb_suspend(struct device *dev)
static int jzfb_resume(struct device *dev)
{
struct jzfb *jzfb = dev_get_drvdata(dev);
- clk_enable(jzfb->ldclk);
+ clk_prepare_enable(jzfb->ldclk);
mutex_lock(&jzfb->lock);
if (jzfb->is_enabled)
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
index 6157f74ac600..79bfb5c38409 100644
--- a/drivers/video/kyro/fbdev.c
+++ b/drivers/video/kyro/fbdev.c
@@ -623,7 +623,6 @@ static int kyrofb_ioctl(struct fb_info *info,
"command instead.\n");
return -EINVAL;
}
- break;
case KYRO_IOCTL_UVSTRIDE:
if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long)))
return -EFAULT;
@@ -779,7 +778,6 @@ static void kyrofb_remove(struct pci_dev *pdev)
#endif
unregister_framebuffer(info);
- pci_set_drvdata(pdev, NULL);
framebuffer_release(info);
}
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index b17f5009a436..c0f61aa37696 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -648,8 +648,6 @@ static int leo_remove(struct platform_device *op)
framebuffer_release(info);
- dev_set_drvdata(&op->dev, NULL);
-
return 0;
}
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index fd2897455696..ee41a0f276b2 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -1295,19 +1295,7 @@ static struct i2c_driver maven_driver={
.id_table = maven_id,
};
-static int __init matroxfb_maven_init(void)
-{
- return i2c_add_driver(&maven_driver);
-}
-
-static void __exit matroxfb_maven_exit(void)
-{
- i2c_del_driver(&maven_driver);
-}
-
+module_i2c_driver(maven_driver);
MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
MODULE_DESCRIPTION("Matrox G200/G400 Matrox MGA-TVO driver");
MODULE_LICENSE("GPL");
-module_init(matroxfb_maven_init);
-module_exit(matroxfb_maven_exit);
-/* we do not have __setup() yet */
diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c
index 91c59c9fb082..0cd4c3318511 100644
--- a/drivers/video/mb862xx/mb862xxfbdrv.c
+++ b/drivers/video/mb862xx/mb862xxfbdrv.c
@@ -781,7 +781,6 @@ rel_reg:
irqdisp:
irq_dispose_mapping(par->irq);
fbrel:
- dev_set_drvdata(dev, NULL);
framebuffer_release(info);
return ret;
}
@@ -814,7 +813,6 @@ static int of_platform_mb862xx_remove(struct platform_device *ofdev)
iounmap(par->mmio_base);
iounmap(par->fb_base);
- dev_set_drvdata(&ofdev->dev, NULL);
release_mem_region(par->res->start, res_size);
framebuffer_release(fbi);
return 0;
@@ -1157,7 +1155,6 @@ static void mb862xx_pci_remove(struct pci_dev *pdev)
device_remove_file(&pdev->dev, &dev_attr_dispregs);
- pci_set_drvdata(pdev, NULL);
unregister_framebuffer(fbi);
fb_dealloc_cmap(&fbi->cmap);
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c
index 0c1a874ffd2b..f87c4ef10b78 100644
--- a/drivers/video/mbx/mbxfb.c
+++ b/drivers/video/mbx/mbxfb.c
@@ -890,7 +890,7 @@ static int mbxfb_probe(struct platform_device *dev)
dev_dbg(&dev->dev, "mbxfb_probe\n");
- pdata = dev->dev.platform_data;
+ pdata = dev_get_platdata(&dev->dev);
if (!pdata) {
dev_err(&dev->dev, "platform data is required\n");
return -EINVAL;
diff --git a/drivers/video/mmp/fb/mmpfb.c b/drivers/video/mmp/fb/mmpfb.c
index 4ab95b8daed3..7ab31eb76a8c 100644
--- a/drivers/video/mmp/fb/mmpfb.c
+++ b/drivers/video/mmp/fb/mmpfb.c
@@ -392,12 +392,29 @@ static int var_update(struct fb_info *info)
return 0;
}
+static void mmpfb_set_win(struct fb_info *info)
+{
+ struct mmpfb_info *fbi = info->par;
+ struct fb_var_screeninfo *var = &info->var;
+ struct mmp_win win;
+ u32 stride;
+
+ memset(&win, 0, sizeof(win));
+ win.xsrc = win.xdst = fbi->mode.xres;
+ win.ysrc = win.ydst = fbi->mode.yres;
+ win.pix_fmt = fbi->pix_fmt;
+ stride = pixfmt_to_stride(win.pix_fmt);
+ win.pitch[0] = var->xres_virtual * stride;
+ win.pitch[1] = win.pitch[2] =
+ (stride == 1) ? (var->xres_virtual >> 1) : 0;
+ mmp_overlay_set_win(fbi->overlay, &win);
+}
+
static int mmpfb_set_par(struct fb_info *info)
{
struct mmpfb_info *fbi = info->par;
struct fb_var_screeninfo *var = &info->var;
struct mmp_addr addr;
- struct mmp_win win;
struct mmp_mode mode;
int ret;
@@ -409,11 +426,8 @@ static int mmpfb_set_par(struct fb_info *info)
fbmode_to_mmpmode(&mode, &fbi->mode, fbi->output_fmt);
mmp_path_set_mode(fbi->path, &mode);
- memset(&win, 0, sizeof(win));
- win.xsrc = win.xdst = fbi->mode.xres;
- win.ysrc = win.ydst = fbi->mode.yres;
- win.pix_fmt = fbi->pix_fmt;
- mmp_overlay_set_win(fbi->overlay, &win);
+ /* set window related info */
+ mmpfb_set_win(info);
/* set address always */
memset(&addr, 0, sizeof(addr));
@@ -427,16 +441,12 @@ static int mmpfb_set_par(struct fb_info *info)
static void mmpfb_power(struct mmpfb_info *fbi, int power)
{
struct mmp_addr addr;
- struct mmp_win win;
struct fb_var_screeninfo *var = &fbi->fb_info->var;
/* for power on, always set address/window again */
if (power) {
- memset(&win, 0, sizeof(win));
- win.xsrc = win.xdst = fbi->mode.xres;
- win.ysrc = win.ydst = fbi->mode.yres;
- win.pix_fmt = fbi->pix_fmt;
- mmp_overlay_set_win(fbi->overlay, &win);
+ /* set window related info */
+ mmpfb_set_win(fbi->fb_info);
/* set address always */
memset(&addr, 0, sizeof(addr));
diff --git a/drivers/video/mmp/hw/mmp_ctrl.c b/drivers/video/mmp/hw/mmp_ctrl.c
index 75dca19bf214..ae724aaaad47 100644
--- a/drivers/video/mmp/hw/mmp_ctrl.c
+++ b/drivers/video/mmp/hw/mmp_ctrl.c
@@ -53,15 +53,14 @@ static irqreturn_t ctrl_handle_irq(int irq, void *dev_id)
tmp = readl_relaxed(ctrl->reg_base + SPU_IRQ_ISR);
if (tmp & isr)
writel_relaxed(~isr, ctrl->reg_base + SPU_IRQ_ISR);
- } while ((isr = readl(ctrl->reg_base + SPU_IRQ_ISR)) & imask);
+ } while ((isr = readl_relaxed(ctrl->reg_base + SPU_IRQ_ISR)) & imask);
return IRQ_HANDLED;
}
static u32 fmt_to_reg(struct mmp_overlay *overlay, int pix_fmt)
{
- u32 link_config = path_to_path_plat(overlay->path)->link_config;
- u32 rbswap, uvswap = 0, yuvswap = 0,
+ u32 rbswap = 0, uvswap = 0, yuvswap = 0,
csc_en = 0, val = 0,
vid = overlay_is_vid(overlay);
@@ -71,27 +70,23 @@ static u32 fmt_to_reg(struct mmp_overlay *overlay, int pix_fmt)
case PIXFMT_RGB888PACK:
case PIXFMT_RGB888UNPACK:
case PIXFMT_RGBA888:
- rbswap = !(link_config & 0x1);
+ rbswap = 1;
break;
case PIXFMT_VYUY:
case PIXFMT_YVU422P:
case PIXFMT_YVU420P:
- rbswap = link_config & 0x1;
uvswap = 1;
break;
case PIXFMT_YUYV:
- rbswap = link_config & 0x1;
yuvswap = 1;
break;
default:
- rbswap = link_config & 0x1;
break;
}
switch (pix_fmt) {
case PIXFMT_RGB565:
case PIXFMT_BGR565:
- val = 0;
break;
case PIXFMT_RGB1555:
case PIXFMT_BGR1555:
@@ -147,17 +142,27 @@ static void dmafetch_set_fmt(struct mmp_overlay *overlay)
static void overlay_set_win(struct mmp_overlay *overlay, struct mmp_win *win)
{
struct lcd_regs *regs = path_regs(overlay->path);
- u32 pitch;
/* assert win supported */
memcpy(&overlay->win, win, sizeof(struct mmp_win));
mutex_lock(&overlay->access_ok);
- pitch = win->xsrc * pixfmt_to_stride(win->pix_fmt);
- writel_relaxed(pitch, &regs->g_pitch);
- writel_relaxed((win->ysrc << 16) | win->xsrc, &regs->g_size);
- writel_relaxed((win->ydst << 16) | win->xdst, &regs->g_size_z);
- writel_relaxed(0, &regs->g_start);
+
+ if (overlay_is_vid(overlay)) {
+ writel_relaxed(win->pitch[0], &regs->v_pitch_yc);
+ writel_relaxed(win->pitch[2] << 16 |
+ win->pitch[1], &regs->v_pitch_uv);
+
+ writel_relaxed((win->ysrc << 16) | win->xsrc, &regs->v_size);
+ writel_relaxed((win->ydst << 16) | win->xdst, &regs->v_size_z);
+ writel_relaxed(win->ypos << 16 | win->xpos, &regs->v_start);
+ } else {
+ writel_relaxed(win->pitch[0], &regs->g_pitch);
+
+ writel_relaxed((win->ysrc << 16) | win->xsrc, &regs->g_size);
+ writel_relaxed((win->ydst << 16) | win->xdst, &regs->g_size_z);
+ writel_relaxed(win->ypos << 16 | win->xpos, &regs->g_start);
+ }
dmafetch_set_fmt(overlay);
mutex_unlock(&overlay->access_ok);
@@ -239,7 +244,13 @@ static int overlay_set_addr(struct mmp_overlay *overlay, struct mmp_addr *addr)
/* FIXME: assert addr supported */
memcpy(&overlay->addr, addr, sizeof(struct mmp_addr));
- writel(addr->phys[0], &regs->g_0);
+
+ if (overlay_is_vid(overlay)) {
+ writel_relaxed(addr->phys[0], &regs->v_y0);
+ writel_relaxed(addr->phys[1], &regs->v_u0);
+ writel_relaxed(addr->phys[2], &regs->v_v0);
+ } else
+ writel_relaxed(addr->phys[0], &regs->g_0);
return overlay->addr.phys[0];
}
@@ -248,7 +259,8 @@ static void path_set_mode(struct mmp_path *path, struct mmp_mode *mode)
{
struct lcd_regs *regs = path_regs(path);
u32 total_x, total_y, vsync_ctrl, tmp, sclk_src, sclk_div,
- link_config = path_to_path_plat(path)->link_config;
+ link_config = path_to_path_plat(path)->link_config,
+ dsi_rbswap = path_to_path_plat(path)->link_config;
/* FIXME: assert videomode supported */
memcpy(&path->mode, mode, sizeof(struct mmp_mode));
@@ -263,6 +275,12 @@ static void path_set_mode(struct mmp_path *path, struct mmp_mode *mode)
tmp |= CFG_DUMB_ENA(1);
writel_relaxed(tmp, ctrl_regs(path) + intf_ctrl(path->id));
+ /* interface rb_swap setting */
+ tmp = readl_relaxed(ctrl_regs(path) + intf_rbswap_ctrl(path->id)) &
+ (~(CFG_INTFRBSWAP_MASK));
+ tmp |= dsi_rbswap & CFG_INTFRBSWAP_MASK;
+ writel_relaxed(tmp, ctrl_regs(path) + intf_rbswap_ctrl(path->id));
+
writel_relaxed((mode->yres << 16) | mode->xres, &regs->screen_active);
writel_relaxed((mode->left_margin << 16) | mode->right_margin,
&regs->screen_h_porch);
@@ -370,20 +388,12 @@ static void path_set_default(struct mmp_path *path)
* bus arbiter for faster read if not tv path;
* 2.enable horizontal smooth filter;
*/
- if (PATH_PN == path->id) {
- mask = CFG_GRA_HSMOOTH_MASK | CFG_DMA_HSMOOTH_MASK
- | CFG_ARBFAST_ENA(1);
- tmp = readl_relaxed(ctrl_regs(path) + dma_ctrl(0, path->id));
- tmp |= mask;
- writel_relaxed(tmp, ctrl_regs(path) + dma_ctrl(0, path->id));
- } else if (PATH_TV == path->id) {
- mask = CFG_GRA_HSMOOTH_MASK | CFG_DMA_HSMOOTH_MASK
- | CFG_ARBFAST_ENA(1);
- tmp = readl_relaxed(ctrl_regs(path) + dma_ctrl(0, path->id));
- tmp &= ~mask;
- tmp |= CFG_GRA_HSMOOTH_MASK | CFG_DMA_HSMOOTH_MASK;
- writel_relaxed(tmp, ctrl_regs(path) + dma_ctrl(0, path->id));
- }
+ mask = CFG_GRA_HSMOOTH_MASK | CFG_DMA_HSMOOTH_MASK | CFG_ARBFAST_ENA(1);
+ tmp = readl_relaxed(ctrl_regs(path) + dma_ctrl(0, path->id));
+ tmp |= mask;
+ if (PATH_TV == path->id)
+ tmp &= ~CFG_ARBFAST_ENA(1);
+ writel_relaxed(tmp, ctrl_regs(path) + dma_ctrl(0, path->id));
}
static int path_init(struct mmphw_path_plat *path_plat,
@@ -419,6 +429,7 @@ static int path_init(struct mmphw_path_plat *path_plat,
path_plat->path = path;
path_plat->path_config = config->path_config;
path_plat->link_config = config->link_config;
+ path_plat->dsi_rbswap = config->dsi_rbswap;
path_set_default(path);
kfree(path_info);
diff --git a/drivers/video/mmp/hw/mmp_ctrl.h b/drivers/video/mmp/hw/mmp_ctrl.h
index edd2002b0e99..53301cfdb1ae 100644
--- a/drivers/video/mmp/hw/mmp_ctrl.h
+++ b/drivers/video/mmp/hw/mmp_ctrl.h
@@ -163,6 +163,8 @@ struct lcd_regs {
#define LCD_SCLK(path) ((PATH_PN == path->id) ? LCD_CFG_SCLK_DIV :\
((PATH_TV == path->id) ? LCD_TCLK_DIV : LCD_PN2_SCLK_DIV))
+#define intf_rbswap_ctrl(id) ((id) ? (((id) & 1) ? LCD_TVIF_CTRL : \
+ PN2_IOPAD_CONTROL) : LCD_TOP_CTRL)
/* dither configure */
#ifdef CONFIG_CPU_PXA988
@@ -615,6 +617,8 @@ struct lcd_regs {
#define LCD_SPU_DUMB_CTRL 0x01B8
#define CFG_DUMBMODE(mode) ((mode)<<28)
#define CFG_DUMBMODE_MASK 0xF0000000
+#define CFG_INTFRBSWAP(mode) ((mode)<<24)
+#define CFG_INTFRBSWAP_MASK 0x0F000000
#define CFG_LCDGPIO_O(data) ((data)<<20)
#define CFG_LCDGPIO_O_MASK 0x0FF00000
#define CFG_LCDGPIO_ENA(gpio) ((gpio)<<12)
@@ -1427,6 +1431,7 @@ struct mmphw_path_plat {
struct mmp_path *path;
u32 path_config;
u32 link_config;
+ u32 dsi_rbswap;
};
/* mmp ctrl describes mmp controller related info */
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index cfdb380ec81e..804f874d32d3 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -1354,7 +1354,7 @@ static struct fb_info *mx3fb_init_fbinfo(struct device *dev, struct fb_ops *ops)
static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan)
{
struct device *dev = mx3fb->dev;
- struct mx3fb_platform_data *mx3fb_pdata = dev->platform_data;
+ struct mx3fb_platform_data *mx3fb_pdata = dev_get_platdata(dev);
const char *name = mx3fb_pdata->name;
unsigned int irq;
struct fb_info *fbi;
@@ -1462,7 +1462,7 @@ static bool chan_filter(struct dma_chan *chan, void *arg)
return false;
dev = rq->mx3fb->dev;
- mx3fb_pdata = dev->platform_data;
+ mx3fb_pdata = dev_get_platdata(dev);
return rq->id == chan->chan_id &&
mx3fb_pdata->dma_dev == chan->device->dev;
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 7ef079c146e7..891b0bf841e3 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -2146,12 +2146,6 @@ static void neofb_remove(struct pci_dev *dev)
fb_destroy_modedb(info->monspecs.modedb);
neo_unmap_mmio(info);
neo_free_fb_info(info);
-
- /*
- * Ensure that the driver data is no longer
- * valid.
- */
- pci_set_drvdata(dev, NULL);
}
}
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index 796e5112ceee..ec32f675466d 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -91,7 +91,7 @@ static int nuc900fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct nuc900fb_info *fbi = info->par;
- struct nuc900fb_mach_info *mach_info = fbi->dev->platform_data;
+ struct nuc900fb_mach_info *mach_info = dev_get_platdata(fbi->dev);
struct nuc900fb_display *display = NULL;
struct nuc900fb_display *default_display = mach_info->displays +
mach_info->default_display;
@@ -358,7 +358,7 @@ static inline void modify_gpio(void __iomem *reg,
static int nuc900fb_init_registers(struct fb_info *info)
{
struct nuc900fb_info *fbi = info->par;
- struct nuc900fb_mach_info *mach_info = fbi->dev->platform_data;
+ struct nuc900fb_mach_info *mach_info = dev_get_platdata(fbi->dev);
void __iomem *regs = fbi->io;
/*reset the display engine*/
@@ -512,7 +512,7 @@ static int nuc900fb_probe(struct platform_device *pdev)
int size;
dev_dbg(&pdev->dev, "devinit\n");
- mach_info = pdev->dev.platform_data;
+ mach_info = dev_get_platdata(&pdev->dev);
if (mach_info == NULL) {
dev_err(&pdev->dev,
"no platform data for lcd, cannot attach\n");
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
index f349ee6f0cea..a4ee65b8f918 100644
--- a/drivers/video/omap/hwa742.c
+++ b/drivers/video/omap/hwa742.c
@@ -947,7 +947,7 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
hwa742.extif = fbdev->ext_if;
hwa742.int_ctrl = fbdev->int_ctrl;
- omapfb_conf = fbdev->dev->platform_data;
+ omapfb_conf = dev_get_platdata(fbdev->dev);
hwa742.sys_ck = clk_get(NULL, "hwa_sys_ck");
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index d40612c31a98..e4fc6d9b5371 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -1602,7 +1602,7 @@ static int omapfb_find_ctrl(struct omapfb_device *fbdev)
char name[17];
int i;
- conf = fbdev->dev->platform_data;
+ conf = dev_get_platdata(fbdev->dev);
fbdev->ctrl = NULL;
@@ -1674,7 +1674,7 @@ static int omapfb_do_probe(struct platform_device *pdev,
goto cleanup;
}
- if (pdev->dev.platform_data == NULL) {
+ if (dev_get_platdata(&pdev->dev) == NULL) {
dev_err(&pdev->dev, "missing platform data\n");
r = -ENOENT;
goto cleanup;
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 02a7340111df..8fbeb299fac3 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -2352,7 +2352,7 @@ int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel,
{
enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
bool five_taps = true;
- bool fieldmode = 0;
+ bool fieldmode = false;
u16 in_height = oi->height;
u16 in_width = oi->width;
bool ilace = timings->interlace;
@@ -2365,7 +2365,7 @@ int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel,
out_height = oi->out_height == 0 ? oi->height : oi->out_height;
if (ilace && oi->height == out_height)
- fieldmode = 1;
+ fieldmode = true;
if (ilace) {
if (fieldmode)
@@ -2396,7 +2396,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
bool mem_to_mem)
{
bool five_taps = true;
- bool fieldmode = 0;
+ bool fieldmode = false;
int r, cconv = 0;
unsigned offset0, offset1;
s32 row_inc;
@@ -2417,7 +2417,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
out_height = out_height == 0 ? height : out_height;
if (ilace && height == out_height)
- fieldmode = 1;
+ fieldmode = true;
if (ilace) {
if (fieldmode)
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
index 3dfe00956a4f..fd4172b41c46 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
@@ -527,7 +527,7 @@ static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
static void hdmi_core_powerdown_disable(struct hdmi_ip_data *ip_data)
{
pr_debug("Enter hdmi_core_powerdown_disable\n");
- REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1, 0x0, 0, 0);
+ REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SYS_CTRL1, 0x0, 0, 0);
}
static void hdmi_core_swreset_release(struct hdmi_ip_data *ip_data)
@@ -550,12 +550,12 @@ static void hdmi_core_video_config(struct hdmi_ip_data *ip_data,
void __iomem *core_sys_base = hdmi_core_sys_base(ip_data);
/* sys_ctrl1 default configuration not tunable */
- r = hdmi_read_reg(core_sys_base, HDMI_CORE_CTRL1);
- r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5);
- r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4);
- r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2);
- r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1);
- hdmi_write_reg(core_sys_base, HDMI_CORE_CTRL1, r);
+ r = hdmi_read_reg(core_sys_base, HDMI_CORE_SYS_SYS_CTRL1);
+ r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_VEN_FOLLOWVSYNC, 5, 5);
+ r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_HEN_FOLLOWHSYNC, 4, 4);
+ r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_BSEL_24BITBUS, 2, 2);
+ r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_EDGE_RISINGEDGE, 1, 1);
+ hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_SYS_CTRL1, r);
REG_FLD_MOD(core_sys_base,
HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6);
@@ -859,8 +859,11 @@ void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
DUMPREG(HDMI_WP_SYSCONFIG);
DUMPREG(HDMI_WP_IRQSTATUS_RAW);
DUMPREG(HDMI_WP_IRQSTATUS);
- DUMPREG(HDMI_WP_PWR_CTRL);
DUMPREG(HDMI_WP_IRQENABLE_SET);
+ DUMPREG(HDMI_WP_IRQENABLE_CLR);
+ DUMPREG(HDMI_WP_IRQWAKEEN);
+ DUMPREG(HDMI_WP_PWR_CTRL);
+ DUMPREG(HDMI_WP_DEBOUNCE);
DUMPREG(HDMI_WP_VIDEO_CFG);
DUMPREG(HDMI_WP_VIDEO_SIZE);
DUMPREG(HDMI_WP_VIDEO_TIMING_H);
@@ -883,6 +886,8 @@ void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
DUMPPLL(PLLCTRL_CFG1);
DUMPPLL(PLLCTRL_CFG2);
DUMPPLL(PLLCTRL_CFG3);
+ DUMPPLL(PLLCTRL_SSC_CFG1);
+ DUMPPLL(PLLCTRL_SSC_CFG2);
DUMPPLL(PLLCTRL_CFG4);
}
@@ -904,8 +909,9 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
DUMPCORE(HDMI_CORE_SYS_DEV_IDH);
DUMPCORE(HDMI_CORE_SYS_DEV_REV);
DUMPCORE(HDMI_CORE_SYS_SRST);
- DUMPCORE(HDMI_CORE_CTRL1);
+ DUMPCORE(HDMI_CORE_SYS_SYS_CTRL1);
DUMPCORE(HDMI_CORE_SYS_SYS_STAT);
+ DUMPCORE(HDMI_CORE_SYS_SYS_CTRL3);
DUMPCORE(HDMI_CORE_SYS_DE_DLY);
DUMPCORE(HDMI_CORE_SYS_DE_CTRL);
DUMPCORE(HDMI_CORE_SYS_DE_TOP);
@@ -913,14 +919,58 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
DUMPCORE(HDMI_CORE_SYS_DE_CNTH);
DUMPCORE(HDMI_CORE_SYS_DE_LINL);
DUMPCORE(HDMI_CORE_SYS_DE_LINH_1);
+ DUMPCORE(HDMI_CORE_SYS_HRES_L);
+ DUMPCORE(HDMI_CORE_SYS_HRES_H);
+ DUMPCORE(HDMI_CORE_SYS_VRES_L);
+ DUMPCORE(HDMI_CORE_SYS_VRES_H);
+ DUMPCORE(HDMI_CORE_SYS_IADJUST);
+ DUMPCORE(HDMI_CORE_SYS_POLDETECT);
+ DUMPCORE(HDMI_CORE_SYS_HWIDTH1);
+ DUMPCORE(HDMI_CORE_SYS_HWIDTH2);
+ DUMPCORE(HDMI_CORE_SYS_VWIDTH);
+ DUMPCORE(HDMI_CORE_SYS_VID_CTRL);
DUMPCORE(HDMI_CORE_SYS_VID_ACEN);
DUMPCORE(HDMI_CORE_SYS_VID_MODE);
+ DUMPCORE(HDMI_CORE_SYS_VID_BLANK1);
+ DUMPCORE(HDMI_CORE_SYS_VID_BLANK3);
+ DUMPCORE(HDMI_CORE_SYS_VID_BLANK1);
+ DUMPCORE(HDMI_CORE_SYS_DC_HEADER);
+ DUMPCORE(HDMI_CORE_SYS_VID_DITHER);
+ DUMPCORE(HDMI_CORE_SYS_RGB2XVYCC_CT);
+ DUMPCORE(HDMI_CORE_SYS_R2Y_COEFF_LOW);
+ DUMPCORE(HDMI_CORE_SYS_R2Y_COEFF_UP);
+ DUMPCORE(HDMI_CORE_SYS_G2Y_COEFF_LOW);
+ DUMPCORE(HDMI_CORE_SYS_G2Y_COEFF_UP);
+ DUMPCORE(HDMI_CORE_SYS_B2Y_COEFF_LOW);
+ DUMPCORE(HDMI_CORE_SYS_B2Y_COEFF_UP);
+ DUMPCORE(HDMI_CORE_SYS_R2CB_COEFF_LOW);
+ DUMPCORE(HDMI_CORE_SYS_R2CB_COEFF_UP);
+ DUMPCORE(HDMI_CORE_SYS_G2CB_COEFF_LOW);
+ DUMPCORE(HDMI_CORE_SYS_G2CB_COEFF_UP);
+ DUMPCORE(HDMI_CORE_SYS_B2CB_COEFF_LOW);
+ DUMPCORE(HDMI_CORE_SYS_B2CB_COEFF_UP);
+ DUMPCORE(HDMI_CORE_SYS_R2CR_COEFF_LOW);
+ DUMPCORE(HDMI_CORE_SYS_R2CR_COEFF_UP);
+ DUMPCORE(HDMI_CORE_SYS_G2CR_COEFF_LOW);
+ DUMPCORE(HDMI_CORE_SYS_G2CR_COEFF_UP);
+ DUMPCORE(HDMI_CORE_SYS_B2CR_COEFF_LOW);
+ DUMPCORE(HDMI_CORE_SYS_B2CR_COEFF_UP);
+ DUMPCORE(HDMI_CORE_SYS_RGB_OFFSET_LOW);
+ DUMPCORE(HDMI_CORE_SYS_RGB_OFFSET_UP);
+ DUMPCORE(HDMI_CORE_SYS_Y_OFFSET_LOW);
+ DUMPCORE(HDMI_CORE_SYS_Y_OFFSET_UP);
+ DUMPCORE(HDMI_CORE_SYS_CBCR_OFFSET_LOW);
+ DUMPCORE(HDMI_CORE_SYS_CBCR_OFFSET_UP);
DUMPCORE(HDMI_CORE_SYS_INTR_STATE);
DUMPCORE(HDMI_CORE_SYS_INTR1);
DUMPCORE(HDMI_CORE_SYS_INTR2);
DUMPCORE(HDMI_CORE_SYS_INTR3);
DUMPCORE(HDMI_CORE_SYS_INTR4);
- DUMPCORE(HDMI_CORE_SYS_UMASK1);
+ DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK1);
+ DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK2);
+ DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK3);
+ DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK4);
+ DUMPCORE(HDMI_CORE_SYS_INTR_CTRL);
DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL);
DUMPCORE(HDMI_CORE_DDC_ADDR);
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
index 6ef2f929a76d..b25269c64123 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
@@ -31,9 +31,11 @@
#define HDMI_WP_SYSCONFIG 0x10
#define HDMI_WP_IRQSTATUS_RAW 0x24
#define HDMI_WP_IRQSTATUS 0x28
-#define HDMI_WP_PWR_CTRL 0x40
#define HDMI_WP_IRQENABLE_SET 0x2C
#define HDMI_WP_IRQENABLE_CLR 0x30
+#define HDMI_WP_IRQWAKEEN 0x34
+#define HDMI_WP_PWR_CTRL 0x40
+#define HDMI_WP_DEBOUNCE 0x44
#define HDMI_WP_VIDEO_CFG 0x50
#define HDMI_WP_VIDEO_SIZE 0x60
#define HDMI_WP_VIDEO_TIMING_H 0x68
@@ -51,8 +53,10 @@
#define HDMI_CORE_SYS_DEV_IDH 0xC
#define HDMI_CORE_SYS_DEV_REV 0x10
#define HDMI_CORE_SYS_SRST 0x14
-#define HDMI_CORE_CTRL1 0x20
+#define HDMI_CORE_SYS_SYS_CTRL1 0x20
#define HDMI_CORE_SYS_SYS_STAT 0x24
+#define HDMI_CORE_SYS_SYS_CTRL3 0x28
+#define HDMI_CORE_SYS_DCTL 0x34
#define HDMI_CORE_SYS_DE_DLY 0xC8
#define HDMI_CORE_SYS_DE_CTRL 0xCC
#define HDMI_CORE_SYS_DE_TOP 0xD0
@@ -60,20 +64,65 @@
#define HDMI_CORE_SYS_DE_CNTH 0xDC
#define HDMI_CORE_SYS_DE_LINL 0xE0
#define HDMI_CORE_SYS_DE_LINH_1 0xE4
+#define HDMI_CORE_SYS_HRES_L 0xE8
+#define HDMI_CORE_SYS_HRES_H 0xEC
+#define HDMI_CORE_SYS_VRES_L 0xF0
+#define HDMI_CORE_SYS_VRES_H 0xF4
+#define HDMI_CORE_SYS_IADJUST 0xF8
+#define HDMI_CORE_SYS_POLDETECT 0xFC
+#define HDMI_CORE_SYS_HWIDTH1 0x110
+#define HDMI_CORE_SYS_HWIDTH2 0x114
+#define HDMI_CORE_SYS_VWIDTH 0x11C
+#define HDMI_CORE_SYS_VID_CTRL 0x120
#define HDMI_CORE_SYS_VID_ACEN 0x124
#define HDMI_CORE_SYS_VID_MODE 0x128
+#define HDMI_CORE_SYS_VID_BLANK1 0x12C
+#define HDMI_CORE_SYS_VID_BLANK2 0x130
+#define HDMI_CORE_SYS_VID_BLANK3 0x134
+#define HDMI_CORE_SYS_DC_HEADER 0x138
+#define HDMI_CORE_SYS_VID_DITHER 0x13C
+#define HDMI_CORE_SYS_RGB2XVYCC_CT 0x140
+#define HDMI_CORE_SYS_R2Y_COEFF_LOW 0x144
+#define HDMI_CORE_SYS_R2Y_COEFF_UP 0x148
+#define HDMI_CORE_SYS_G2Y_COEFF_LOW 0x14C
+#define HDMI_CORE_SYS_G2Y_COEFF_UP 0x150
+#define HDMI_CORE_SYS_B2Y_COEFF_LOW 0x154
+#define HDMI_CORE_SYS_B2Y_COEFF_UP 0x158
+#define HDMI_CORE_SYS_R2CB_COEFF_LOW 0x15C
+#define HDMI_CORE_SYS_R2CB_COEFF_UP 0x160
+#define HDMI_CORE_SYS_G2CB_COEFF_LOW 0x164
+#define HDMI_CORE_SYS_G2CB_COEFF_UP 0x168
+#define HDMI_CORE_SYS_B2CB_COEFF_LOW 0x16C
+#define HDMI_CORE_SYS_B2CB_COEFF_UP 0x170
+#define HDMI_CORE_SYS_R2CR_COEFF_LOW 0x174
+#define HDMI_CORE_SYS_R2CR_COEFF_UP 0x178
+#define HDMI_CORE_SYS_G2CR_COEFF_LOW 0x17C
+#define HDMI_CORE_SYS_G2CR_COEFF_UP 0x180
+#define HDMI_CORE_SYS_B2CR_COEFF_LOW 0x184
+#define HDMI_CORE_SYS_B2CR_COEFF_UP 0x188
+#define HDMI_CORE_SYS_RGB_OFFSET_LOW 0x18C
+#define HDMI_CORE_SYS_RGB_OFFSET_UP 0x190
+#define HDMI_CORE_SYS_Y_OFFSET_LOW 0x194
+#define HDMI_CORE_SYS_Y_OFFSET_UP 0x198
+#define HDMI_CORE_SYS_CBCR_OFFSET_LOW 0x19C
+#define HDMI_CORE_SYS_CBCR_OFFSET_UP 0x1A0
#define HDMI_CORE_SYS_INTR_STATE 0x1C0
#define HDMI_CORE_SYS_INTR1 0x1C4
#define HDMI_CORE_SYS_INTR2 0x1C8
#define HDMI_CORE_SYS_INTR3 0x1CC
#define HDMI_CORE_SYS_INTR4 0x1D0
-#define HDMI_CORE_SYS_UMASK1 0x1D4
+#define HDMI_CORE_SYS_INTR_UNMASK1 0x1D4
+#define HDMI_CORE_SYS_INTR_UNMASK2 0x1D8
+#define HDMI_CORE_SYS_INTR_UNMASK3 0x1DC
+#define HDMI_CORE_SYS_INTR_UNMASK4 0x1E0
+#define HDMI_CORE_SYS_INTR_CTRL 0x1E4
#define HDMI_CORE_SYS_TMDS_CTRL 0x208
-#define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1
-#define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1
-#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1
-#define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1
+/* value definitions for HDMI_CORE_SYS_SYS_CTRL1 fields */
+#define HDMI_CORE_SYS_SYS_CTRL1_VEN_FOLLOWVSYNC 0x1
+#define HDMI_CORE_SYS_SYS_CTRL1_HEN_FOLLOWHSYNC 0x1
+#define HDMI_CORE_SYS_SYS_CTRL1_BSEL_24BITBUS 0x1
+#define HDMI_CORE_SYS_SYS_CTRL1_EDGE_RISINGEDGE 0x1
/* HDMI DDC E-DID */
#define HDMI_CORE_DDC_ADDR 0x3B4
@@ -166,6 +215,8 @@
#define PLLCTRL_CFG1 0xC
#define PLLCTRL_CFG2 0x10
#define PLLCTRL_CFG3 0x14
+#define PLLCTRL_SSC_CFG1 0x18
+#define PLLCTRL_SSC_CFG2 0x1C
#define PLLCTRL_CFG4 0x20
/* HDMI PHY */
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index 4b23af6e5c28..367cea8f43f3 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -339,8 +339,6 @@ static int p9100_remove(struct platform_device *op)
framebuffer_release(info);
- dev_set_drvdata(&op->dev, NULL);
-
return 0;
}
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index 3d86bac62d3e..b644037dd5bc 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -639,7 +639,6 @@ static int platinumfb_probe(struct platform_device* odev)
iounmap(pinfo->frame_buffer);
iounmap(pinfo->platinum_regs);
iounmap(pinfo->cmap_regs);
- dev_set_drvdata(&odev->dev, NULL);
framebuffer_release(info);
}
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 81354eeab021..45d9a3fe35e7 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -1744,7 +1744,6 @@ static void pm2fb_remove(struct pci_dev *pdev)
iounmap(par->v_regs);
release_mem_region(fix->mmio_start, fix->mmio_len);
- pci_set_drvdata(pdev, NULL);
fb_dealloc_cmap(&info->cmap);
kfree(info->pixmap.addr);
framebuffer_release(info);
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index 7718faa4a73b..9c17474340cd 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -1489,7 +1489,6 @@ static void pm3fb_remove(struct pci_dev *dev)
iounmap(par->v_regs);
release_mem_region(fix->mmio_start, fix->mmio_len);
- pci_set_drvdata(dev, NULL);
kfree(info->pixmap.addr);
framebuffer_release(info);
}
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
index aa9bd1f76d60..c95b9e46d48f 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/pxa168fb.c
@@ -364,7 +364,7 @@ static void set_graphics_start(struct fb_info *info, int xoffset, int yoffset)
static void set_dumb_panel_control(struct fb_info *info)
{
struct pxa168fb_info *fbi = info->par;
- struct pxa168fb_mach_info *mi = fbi->dev->platform_data;
+ struct pxa168fb_mach_info *mi = dev_get_platdata(fbi->dev);
u32 x;
/*
@@ -407,7 +407,7 @@ static int pxa168fb_set_par(struct fb_info *info)
u32 x;
struct pxa168fb_mach_info *mi;
- mi = fbi->dev->platform_data;
+ mi = dev_get_platdata(fbi->dev);
/*
* Set additional mode info.
@@ -609,7 +609,7 @@ static int pxa168fb_probe(struct platform_device *pdev)
struct clk *clk;
int irq, ret;
- mi = pdev->dev.platform_data;
+ mi = dev_get_platdata(&pdev->dev);
if (mi == NULL) {
dev_err(&pdev->dev, "no platform data defined\n");
return -EINVAL;
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index eca2de45f7a6..1ecd9cec2921 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -457,7 +457,7 @@ static int pxafb_adjust_timing(struct pxafb_info *fbi,
static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct pxafb_info *fbi = (struct pxafb_info *)info;
- struct pxafb_mach_info *inf = fbi->dev->platform_data;
+ struct pxafb_mach_info *inf = dev_get_platdata(fbi->dev);
int err;
if (inf->fixed_modes) {
@@ -1230,7 +1230,7 @@ static unsigned int __smart_timing(unsigned time_ns, unsigned long lcd_clk)
static void setup_smart_timing(struct pxafb_info *fbi,
struct fb_var_screeninfo *var)
{
- struct pxafb_mach_info *inf = fbi->dev->platform_data;
+ struct pxafb_mach_info *inf = dev_get_platdata(fbi->dev);
struct pxafb_mode_info *mode = &inf->modes[0];
unsigned long lclk = clk_get_rate(fbi->clk);
unsigned t1, t2, t3, t4;
@@ -1258,14 +1258,14 @@ static void setup_smart_timing(struct pxafb_info *fbi,
static int pxafb_smart_thread(void *arg)
{
struct pxafb_info *fbi = arg;
- struct pxafb_mach_info *inf = fbi->dev->platform_data;
+ struct pxafb_mach_info *inf = dev_get_platdata(fbi->dev);
if (!inf->smart_update) {
pr_err("%s: not properly initialized, thread terminated\n",
__func__);
return -EINVAL;
}
- inf = fbi->dev->platform_data;
+ inf = dev_get_platdata(fbi->dev);
pr_debug("%s(): task starting\n", __func__);
@@ -1793,7 +1793,7 @@ static struct pxafb_info *pxafb_init_fbinfo(struct device *dev)
{
struct pxafb_info *fbi;
void *addr;
- struct pxafb_mach_info *inf = dev->platform_data;
+ struct pxafb_mach_info *inf = dev_get_platdata(dev);
/* Alloc the pxafb_info and pseudo_palette in one step */
fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL);
@@ -1855,7 +1855,7 @@ static struct pxafb_info *pxafb_init_fbinfo(struct device *dev)
#ifdef CONFIG_FB_PXA_PARAMETERS
static int parse_opt_mode(struct device *dev, const char *this_opt)
{
- struct pxafb_mach_info *inf = dev->platform_data;
+ struct pxafb_mach_info *inf = dev_get_platdata(dev);
const char *name = this_opt+5;
unsigned int namelen = strlen(name);
@@ -1914,7 +1914,7 @@ done:
static int parse_opt(struct device *dev, char *this_opt)
{
- struct pxafb_mach_info *inf = dev->platform_data;
+ struct pxafb_mach_info *inf = dev_get_platdata(dev);
struct pxafb_mode_info *mode = &inf->modes[0];
char s[64];
@@ -2102,7 +2102,7 @@ static int pxafb_probe(struct platform_device *dev)
dev_dbg(&dev->dev, "pxafb_probe\n");
- inf = dev->dev.platform_data;
+ inf = dev_get_platdata(&dev->dev);
ret = -ENOMEM;
fbi = NULL;
if (!inf)
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 9536715b5a1b..a5514acd2ac6 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -1185,11 +1185,6 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
if (rivafb_do_maximize(info, var, nom, den) < 0)
return -EINVAL;
- if (var->xoffset < 0)
- var->xoffset = 0;
- if (var->yoffset < 0)
- var->yoffset = 0;
-
/* truncate xoffset and yoffset to maximum if too high */
if (var->xoffset > var->xres_virtual - var->xres)
var->xoffset = var->xres_virtual - var->xres - 1;
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index 05c2dc3d4bc0..1399a469f8b0 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -777,8 +777,8 @@ static int s1d13xxxfb_probe(struct platform_device *pdev)
printk(KERN_INFO "Epson S1D13XXX FB Driver\n");
/* enable platform-dependent hardware glue, if any */
- if (pdev->dev.platform_data)
- pdata = pdev->dev.platform_data;
+ if (dev_get_platdata(&pdev->dev))
+ pdata = dev_get_platdata(&pdev->dev);
if (pdata && pdata->platform_init_video)
pdata->platform_init_video();
@@ -923,8 +923,8 @@ static int s1d13xxxfb_suspend(struct platform_device *dev, pm_message_t state)
lcd_enable(s1dfb, 0);
crt_enable(s1dfb, 0);
- if (dev->dev.platform_data)
- pdata = dev->dev.platform_data;
+ if (dev_get_platdata(&dev->dev))
+ pdata = dev_get_platdata(&dev->dev);
#if 0
if (!s1dfb->disp_save)
@@ -973,8 +973,8 @@ static int s1d13xxxfb_resume(struct platform_device *dev)
while ((s1d13xxxfb_readreg(s1dfb, S1DREG_PS_STATUS) & 0x01))
udelay(10);
- if (dev->dev.platform_data)
- pdata = dev->dev.platform_data;
+ if (dev_get_platdata(&dev->dev))
+ pdata = dev_get_platdata(&dev->dev);
if (s1dfb->regs_save) {
/* will write RO regs, *should* get away with it :) */
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 2e7991c7ca08..62acae2694a9 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -1378,7 +1378,7 @@ static int s3c_fb_probe(struct platform_device *pdev)
return -EINVAL;
}
- pd = pdev->dev.platform_data;
+ pd = dev_get_platdata(&pdev->dev);
if (!pd) {
dev_err(dev, "no platform data specified\n");
return -EINVAL;
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index 21a32adbb8ea..81af5a63e9e1 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -123,7 +123,7 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct s3c2410fb_info *fbi = info->par;
- struct s3c2410fb_mach_info *mach_info = fbi->dev->platform_data;
+ struct s3c2410fb_mach_info *mach_info = dev_get_platdata(fbi->dev);
struct s3c2410fb_display *display = NULL;
struct s3c2410fb_display *default_display = mach_info->displays +
mach_info->default_display;
@@ -686,7 +686,7 @@ static inline void modify_gpio(void __iomem *reg,
static int s3c2410fb_init_registers(struct fb_info *info)
{
struct s3c2410fb_info *fbi = info->par;
- struct s3c2410fb_mach_info *mach_info = fbi->dev->platform_data;
+ struct s3c2410fb_mach_info *mach_info = dev_get_platdata(fbi->dev);
unsigned long flags;
void __iomem *regs = fbi->io;
void __iomem *tpal;
@@ -833,7 +833,7 @@ static int s3c24xxfb_probe(struct platform_device *pdev,
int size;
u32 lcdcon1;
- mach_info = pdev->dev.platform_data;
+ mach_info = dev_get_platdata(&pdev->dev);
if (mach_info == NULL) {
dev_err(&pdev->dev,
"no platform data for lcd, cannot attach\n");
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
index 47ca86c5c6c0..d158d2c0460f 100644
--- a/drivers/video/s3fb.c
+++ b/drivers/video/s3fb.c
@@ -1431,7 +1431,6 @@ static void s3_pci_remove(struct pci_dev *dev)
pci_release_regions(dev);
/* pci_disable_device(dev); */
- pci_set_drvdata(dev, NULL);
framebuffer_release(info);
}
}
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index de76da0c6429..580c444ec301 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -1116,7 +1116,7 @@ static struct fb_monspecs monspecs = {
static struct sa1100fb_info *sa1100fb_init_fbinfo(struct device *dev)
{
- struct sa1100fb_mach_info *inf = dev->platform_data;
+ struct sa1100fb_mach_info *inf = dev_get_platdata(dev);
struct sa1100fb_info *fbi;
unsigned i;
@@ -1201,7 +1201,7 @@ static int sa1100fb_probe(struct platform_device *pdev)
struct resource *res;
int ret, irq;
- if (!pdev->dev.platform_data) {
+ if (!dev_get_platdata(&pdev->dev)) {
dev_err(&pdev->dev, "no platform LCD data\n");
return -EINVAL;
}
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 741b2395d01e..4dbf45f3b21a 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -2362,12 +2362,6 @@ static void savagefb_remove(struct pci_dev *dev)
kfree(info->pixmap.addr);
pci_release_regions(dev);
framebuffer_release(info);
-
- /*
- * Ensure that the driver data is no longer
- * valid.
- */
- pci_set_drvdata(dev, NULL);
}
}
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index bfe4728480fd..45417fa9749b 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -498,7 +498,7 @@ static void sh_hdmi_video_config(struct sh_hdmi *hdmi)
static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
{
u8 data;
- struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
+ struct sh_mobile_hdmi_info *pdata = dev_get_platdata(hdmi->dev);
/*
* [7:4] L/R data swap control
@@ -815,7 +815,7 @@ static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
unsigned long *hdmi_rate, unsigned long *parent_rate)
{
unsigned long target = PICOS2KHZ(mode->pixclock) * 1000, rate_error;
- struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
+ struct sh_mobile_hdmi_info *pdata = dev_get_platdata(hdmi->dev);
*hdmi_rate = clk_round_rate(hdmi->hdmi_clk, target);
if ((long)*hdmi_rate < 0)
@@ -1271,7 +1271,7 @@ static void sh_hdmi_htop1_init(struct sh_hdmi *hdmi)
static int __init sh_hdmi_probe(struct platform_device *pdev)
{
- struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
+ struct sh_mobile_hdmi_info *pdata = dev_get_platdata(&pdev->dev);
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *htop1_res;
int irq = platform_get_irq(pdev, 0), ret;
diff --git a/drivers/video/simplefb.c b/drivers/video/simplefb.c
index 8d7810613058..ad46d2dd55a2 100644
--- a/drivers/video/simplefb.c
+++ b/drivers/video/simplefb.c
@@ -132,7 +132,7 @@ static int simplefb_parse_dt(struct platform_device *pdev,
static int simplefb_parse_pd(struct platform_device *pdev,
struct simplefb_params *params)
{
- struct simplefb_platform_data *pd = pdev->dev.platform_data;
+ struct simplefb_platform_data *pd = dev_get_platdata(&pdev->dev);
int i;
params->width = pd->width;
@@ -167,7 +167,7 @@ static int simplefb_probe(struct platform_device *pdev)
return -ENODEV;
ret = -ENODEV;
- if (pdev->dev.platform_data)
+ if (dev_get_platdata(&pdev->dev))
ret = simplefb_parse_pd(pdev, &params);
else if (pdev->dev.of_node)
ret = simplefb_parse_dt(pdev, &params);
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 977e27927a21..793b40238fca 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -5994,7 +5994,6 @@ static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if(!ivideo->sisvga_enabled) {
if(pci_enable_device(pdev)) {
if(ivideo->nbridge) pci_dev_put(ivideo->nbridge);
- pci_set_drvdata(pdev, NULL);
framebuffer_release(sis_fb_info);
return -EIO;
}
@@ -6211,7 +6210,6 @@ error_3: vfree(ivideo->bios_abase);
pci_dev_put(ivideo->lpcdev);
if(ivideo->nbridge)
pci_dev_put(ivideo->nbridge);
- pci_set_drvdata(pdev, NULL);
if(!ivideo->sisvga_enabled)
pci_disable_device(pdev);
framebuffer_release(sis_fb_info);
@@ -6523,8 +6521,6 @@ static void sisfb_remove(struct pci_dev *pdev)
mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
#endif
- pci_set_drvdata(pdev, NULL);
-
/* If device was disabled when starting, disable
* it when quitting.
*/
diff --git a/drivers/video/smscufx.c b/drivers/video/smscufx.c
index e188ada2ffd1..d513ed6a49f2 100644
--- a/drivers/video/smscufx.c
+++ b/drivers/video/smscufx.c
@@ -1147,7 +1147,7 @@ static void ufx_free_framebuffer_work(struct work_struct *work)
fb_destroy_modelist(&info->modelist);
- dev->info = 0;
+ dev->info = NULL;
/* Assume info structure is freed after this point */
framebuffer_release(info);
diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c
index cc6f48bba36b..58241b47a96d 100644
--- a/drivers/video/sunxvr1000.c
+++ b/drivers/video/sunxvr1000.c
@@ -186,8 +186,6 @@ static int gfb_remove(struct platform_device *op)
framebuffer_release(info);
- dev_set_drvdata(&op->dev, NULL);
-
return 0;
}
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index c000852500aa..1f3a3271f3dd 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -498,8 +498,6 @@ static int tcx_remove(struct platform_device *op)
framebuffer_release(info);
- dev_set_drvdata(&op->dev, NULL);
-
return 0;
}
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 64bc28ba4037..f761fe375f5b 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -1646,7 +1646,6 @@ static void tdfxfb_remove(struct pci_dev *pdev)
pci_resource_len(pdev, 1));
release_mem_region(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0));
- pci_set_drvdata(pdev, NULL);
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
}
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c
index deb8733f3c70..b5b69a6b9dd8 100644
--- a/drivers/video/tmiofb.c
+++ b/drivers/video/tmiofb.c
@@ -250,7 +250,7 @@ static irqreturn_t tmiofb_irq(int irq, void *__info)
*/
static int tmiofb_hw_stop(struct platform_device *dev)
{
- struct tmio_fb_data *data = dev->dev.platform_data;
+ struct tmio_fb_data *data = dev_get_platdata(&dev->dev);
struct fb_info *info = platform_get_drvdata(dev);
struct tmiofb_par *par = info->par;
@@ -311,7 +311,7 @@ static int tmiofb_hw_init(struct platform_device *dev)
*/
static void tmiofb_hw_mode(struct platform_device *dev)
{
- struct tmio_fb_data *data = dev->dev.platform_data;
+ struct tmio_fb_data *data = dev_get_platdata(&dev->dev);
struct fb_info *info = platform_get_drvdata(dev);
struct fb_videomode *mode = info->mode;
struct tmiofb_par *par = info->par;
@@ -557,7 +557,7 @@ static int tmiofb_ioctl(struct fb_info *fbi,
static struct fb_videomode *
tmiofb_find_mode(struct fb_info *info, struct fb_var_screeninfo *var)
{
- struct tmio_fb_data *data = info->device->platform_data;
+ struct tmio_fb_data *data = dev_get_platdata(info->device);
struct fb_videomode *best = NULL;
int i;
@@ -577,7 +577,7 @@ static int tmiofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct fb_videomode *mode;
- struct tmio_fb_data *data = info->device->platform_data;
+ struct tmio_fb_data *data = dev_get_platdata(info->device);
mode = tmiofb_find_mode(info, var);
if (!mode || var->bits_per_pixel > 16)
@@ -678,7 +678,7 @@ static struct fb_ops tmiofb_ops = {
static int tmiofb_probe(struct platform_device *dev)
{
const struct mfd_cell *cell = mfd_get_cell(dev);
- struct tmio_fb_data *data = dev->dev.platform_data;
+ struct tmio_fb_data *data = dev_get_platdata(&dev->dev);
struct resource *ccr = platform_get_resource(dev, IORESOURCE_MEM, 1);
struct resource *lcr = platform_get_resource(dev, IORESOURCE_MEM, 0);
struct resource *vram = platform_get_resource(dev, IORESOURCE_MEM, 2);
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index ab57d387d6b5..7ed9a227f5ea 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -1553,7 +1553,6 @@ static void trident_pci_remove(struct pci_dev *dev)
iounmap(info->screen_base);
release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
- pci_set_drvdata(dev, NULL);
kfree(info->pixmap.addr);
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
index d2e5bc3cf969..025f14e30eed 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/udlfb.c
@@ -1166,7 +1166,7 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dev, struct fb_info *info)
int new_len;
unsigned char *old_fb = info->screen_base;
unsigned char *new_fb;
- unsigned char *new_back = 0;
+ unsigned char *new_back = NULL;
pr_warn("Reallocating framebuffer. Addresses will change!\n");
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index 7aec6f39fdd5..676a4b9379d9 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -233,8 +233,7 @@ out:
static void uvesafb_free(struct uvesafb_ktask *task)
{
if (task) {
- if (task->done)
- kfree(task->done);
+ kfree(task->done);
kfree(task);
}
}
@@ -1332,8 +1331,8 @@ setmode:
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
info->fix.line_length = mode->bytes_per_scan_line;
-out: if (crtc != NULL)
- kfree(crtc);
+out:
+ kfree(crtc);
uvesafb_free(task);
return err;
@@ -1793,8 +1792,7 @@ out_mode:
fb_destroy_modedb(info->monspecs.modedb);
fb_dealloc_cmap(&info->cmap);
out:
- if (par->vbe_modes)
- kfree(par->vbe_modes);
+ kfree(par->vbe_modes);
framebuffer_release(info);
return err;
@@ -1817,12 +1815,9 @@ static int uvesafb_remove(struct platform_device *dev)
fb_dealloc_cmap(&info->cmap);
if (par) {
- if (par->vbe_modes)
- kfree(par->vbe_modes);
- if (par->vbe_state_orig)
- kfree(par->vbe_state_orig);
- if (par->vbe_state_saved)
- kfree(par->vbe_state_saved);
+ kfree(par->vbe_modes);
+ kfree(par->vbe_state_orig);
+ kfree(par->vbe_state_saved);
}
framebuffer_release(info);
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index ee5985efa15c..ea2b523f804f 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -390,9 +390,8 @@ static int vfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
if (var->vmode & FB_VMODE_YWRAP) {
- if (var->yoffset < 0
- || var->yoffset >= info->var.yres_virtual
- || var->xoffset)
+ if (var->yoffset >= info->var.yres_virtual ||
+ var->xoffset)
return -EINVAL;
} else {
if (var->xoffset + info->var.xres > info->var.xres_virtual ||
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c
index e9557fa014ee..6b424ddd6793 100644
--- a/drivers/video/vt8623fb.c
+++ b/drivers/video/vt8623fb.c
@@ -829,7 +829,6 @@ static void vt8623_pci_remove(struct pci_dev *dev)
pci_release_regions(dev);
/* pci_disable_device(dev); */
- pci_set_drvdata(dev, NULL);
framebuffer_release(info);
}
}
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index 7a299e951f75..2a0437a6d838 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -680,7 +680,7 @@ int w100fb_probe(struct platform_device *pdev)
par = info->par;
platform_set_drvdata(pdev, info);
- inf = pdev->dev.platform_data;
+ inf = dev_get_platdata(&pdev->dev);
par->chip_id = chip_id;
par->mach = inf;
par->fastpll_mode = 0;
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index 84c664ea8eb9..0e1dd3380a1e 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -369,7 +369,6 @@ err_fbmem:
err_region:
kfree(drvdata);
- dev_set_drvdata(dev, NULL);
return rc;
}
@@ -404,7 +403,6 @@ static int xilinxfb_release(struct device *dev)
#endif
kfree(drvdata);
- dev_set_drvdata(dev, NULL);
return 0;
}
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index d1d53f301de7..6df632e0bb55 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -418,8 +418,6 @@ config BFIN_WDT
# FRV Architecture
-# H8300 Architecture
-
# X86 (i386 + ia64 + x86_64) Architecture
config ACQUIRE_WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 6c5bb274d3cd..8c7b8bcbbdc5 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -66,8 +66,6 @@ obj-$(CONFIG_BFIN_WDT) += bfin_wdt.o
# FRV Architecture
-# H8300 Architecture
-
# X86 (i386 + ia64 + x86_64) Architecture
obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 5be5e3d14f79..19f3c3fc65f4 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -802,6 +802,12 @@ static int hpwdt_init_one(struct pci_dev *dev,
return -ENODEV;
}
+ /*
+ * Ignore all auxilary iLO devices with the following PCI ID
+ */
+ if (dev->subsystem_device == 0x1979)
+ return -ENODEV;
+
if (pci_enable_device(dev)) {
dev_warn(&dev->dev,
"Not possible to enable PCI Device: 0x%x:0x%x.\n",
diff --git a/fs/9p/cache.c b/fs/9p/cache.c
index a9ea73d6dcf3..2b7a032c37bc 100644
--- a/fs/9p/cache.c
+++ b/fs/9p/cache.c
@@ -90,7 +90,7 @@ void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses)
v9ses->fscache = fscache_acquire_cookie(v9fs_cache_netfs.primary_index,
&v9fs_cache_session_index_def,
- v9ses);
+ v9ses, true);
p9_debug(P9_DEBUG_FSC, "session %p get cookie %p\n",
v9ses, v9ses->fscache);
}
@@ -204,7 +204,7 @@ void v9fs_cache_inode_get_cookie(struct inode *inode)
v9ses = v9fs_inode2v9ses(inode);
v9inode->fscache = fscache_acquire_cookie(v9ses->fscache,
&v9fs_cache_inode_index_def,
- v9inode);
+ v9inode, true);
p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n",
inode, v9inode->fscache);
@@ -271,7 +271,7 @@ void v9fs_cache_inode_reset_cookie(struct inode *inode)
v9ses = v9fs_inode2v9ses(inode);
v9inode->fscache = fscache_acquire_cookie(v9ses->fscache,
&v9fs_cache_inode_index_def,
- v9inode);
+ v9inode, true);
p9_debug(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p\n",
inode, old, v9inode->fscache);
diff --git a/fs/9p/cache.h b/fs/9p/cache.h
index 40cc54ced5d9..2f9675491095 100644
--- a/fs/9p/cache.h
+++ b/fs/9p/cache.h
@@ -101,6 +101,18 @@ static inline void v9fs_fscache_wait_on_page_write(struct inode *inode,
#else /* CONFIG_9P_FSCACHE */
+static inline void v9fs_cache_inode_get_cookie(struct inode *inode)
+{
+}
+
+static inline void v9fs_cache_inode_put_cookie(struct inode *inode)
+{
+}
+
+static inline void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *file)
+{
+}
+
static inline int v9fs_fscache_release_page(struct page *page,
gfp_t gfp) {
return 1;
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index 9ff073f4090a..da0821bc05b9 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -241,9 +241,8 @@ static int v9fs_launder_page(struct page *page)
* v9fs_direct_IO - 9P address space operation for direct I/O
* @rw: direction (read or write)
* @iocb: target I/O control block
- * @iov: array of vectors that define I/O buffer
+ * @iter: array of vectors that define I/O buffer
* @pos: offset in file to begin the operation
- * @nr_segs: size of iovec array
*
* The presence of v9fs_direct_IO() in the address space ops vector
* allowes open() O_DIRECT flags which would have failed otherwise.
@@ -252,13 +251,12 @@ static int v9fs_launder_page(struct page *page)
* the VFS gets them, so this method should never be called.
*
* Direct IO is not 'yet' supported in the cached mode. Hence when
- * this routine is called through generic_file_aio_read(), the read/write fails
- * with an error.
+ * this routine is called through generic_file_read_iter(), the read/write
+ * fails with an error.
*
*/
static ssize_t
-v9fs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
- loff_t pos, unsigned long nr_segs)
+v9fs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
{
/*
* FIXME
@@ -267,7 +265,7 @@ v9fs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
*/
p9_debug(P9_DEBUG_VFS, "v9fs_direct_IO: v9fs_direct_IO (%s) off/no(%lld/%lu) EINVAL\n",
iocb->ki_filp->f_path.dentry->d_name.name,
- (long long)pos, nr_segs);
+ (long long)pos, iter->nr_segs);
return -EINVAL;
}
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index aa5ecf479a57..7de4a3d47b00 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -105,10 +105,8 @@ int v9fs_file_open(struct inode *inode, struct file *file)
v9inode->writeback_fid = (void *) fid;
}
mutex_unlock(&v9inode->v_mutex);
-#ifdef CONFIG_9P_FSCACHE
if (v9ses->cache)
v9fs_cache_inode_set_cookie(inode, file);
-#endif
return 0;
out_error:
p9_client_clunk(file->private_data);
@@ -743,8 +741,8 @@ const struct file_operations v9fs_cached_file_operations = {
.llseek = generic_file_llseek,
.read = v9fs_cached_file_read,
.write = v9fs_cached_file_write,
- .aio_read = generic_file_aio_read,
- .aio_write = generic_file_aio_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = generic_file_write_iter,
.open = v9fs_file_open,
.release = v9fs_dir_release,
.lock = v9fs_file_lock,
@@ -756,8 +754,8 @@ const struct file_operations v9fs_cached_file_operations_dotl = {
.llseek = generic_file_llseek,
.read = v9fs_cached_file_read,
.write = v9fs_cached_file_write,
- .aio_read = generic_file_aio_read,
- .aio_write = generic_file_aio_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = generic_file_write_iter,
.open = v9fs_file_open,
.release = v9fs_dir_release,
.lock = v9fs_file_lock_dotl,
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 94de6d1482e2..4e65aa903345 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -448,9 +448,7 @@ void v9fs_evict_inode(struct inode *inode)
clear_inode(inode);
filemap_fdatawrite(inode->i_mapping);
-#ifdef CONFIG_9P_FSCACHE
v9fs_cache_inode_put_cookie(inode);
-#endif
/* clunk the fid stashed in writeback_fid */
if (v9inode->writeback_fid) {
p9_client_clunk(v9inode->writeback_fid);
@@ -531,9 +529,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,
goto error;
v9fs_stat2inode(st, inode, sb);
-#ifdef CONFIG_9P_FSCACHE
v9fs_cache_inode_get_cookie(inode);
-#endif
unlock_new_inode(inode);
return inode;
error:
@@ -905,10 +901,8 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
goto error;
file->private_data = fid;
-#ifdef CONFIG_9P_FSCACHE
if (v9ses->cache)
v9fs_cache_inode_set_cookie(dentry->d_inode, file);
-#endif
*opened |= FILE_CREATED;
out:
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index a7c481402c46..4c10edec26a0 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -141,9 +141,7 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
goto error;
v9fs_stat2inode_dotl(st, inode);
-#ifdef CONFIG_9P_FSCACHE
v9fs_cache_inode_get_cookie(inode);
-#endif
retval = v9fs_get_acl(inode, fid);
if (retval)
goto error;
@@ -355,10 +353,8 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
if (err)
goto err_clunk_old_fid;
file->private_data = ofid;
-#ifdef CONFIG_9P_FSCACHE
if (v9ses->cache)
v9fs_cache_inode_set_cookie(inode, file);
-#endif
*opened |= FILE_CREATED;
out:
v9fs_put_acl(dacl, pacl);
diff --git a/fs/Makefile b/fs/Makefile
index 4fe6df3ec28f..1afa0e020082 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -11,7 +11,7 @@ obj-y := open.o read_write.o file_table.o super.o \
attr.o bad_inode.o file.o filesystems.o namespace.o \
seq_file.o xattr.o libfs.o fs-writeback.o \
pnode.o splice.o sync.o utimes.o \
- stack.o fs_struct.o statfs.o
+ stack.o fs_struct.o statfs.o iov-iter.o
ifeq ($(CONFIG_BLOCK),y)
obj-y += buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
diff --git a/fs/adfs/file.c b/fs/adfs/file.c
index a36da5382b40..da1e02161ac3 100644
--- a/fs/adfs/file.c
+++ b/fs/adfs/file.c
@@ -24,11 +24,11 @@
const struct file_operations adfs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.mmap = generic_file_mmap,
.fsync = generic_file_fsync,
.write = do_sync_write,
- .aio_write = generic_file_aio_write,
+ .write_iter = generic_file_write_iter,
.splice_read = generic_file_splice_read,
};
diff --git a/fs/affs/file.c b/fs/affs/file.c
index 8669b6ecddee..664f743c2d8d 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -28,9 +28,9 @@ static int affs_file_release(struct inode *inode, struct file *filp);
const struct file_operations affs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.write = do_sync_write,
- .aio_write = generic_file_aio_write,
+ .write_iter = generic_file_write_iter,
.mmap = generic_file_mmap,
.open = affs_file_open,
.release = affs_file_release,
diff --git a/fs/afs/cell.c b/fs/afs/cell.c
index 3c090b7555ea..ca0a3cf93791 100644
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -179,7 +179,7 @@ struct afs_cell *afs_cell_create(const char *name, unsigned namesz,
/* put it up for caching (this never returns an error) */
cell->cache = fscache_acquire_cookie(afs_cache_netfs.primary_index,
&afs_cell_cache_index_def,
- cell);
+ cell, true);
#endif
/* add to the cell lists */
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 66d50fe2ee45..3b71622e40f4 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -33,8 +33,8 @@ const struct file_operations afs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .aio_read = generic_file_aio_read,
- .aio_write = afs_file_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = afs_file_write,
.mmap = generic_file_readonly_mmap,
.splice_read = generic_file_splice_read,
.fsync = afs_fsync,
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 789bc253b5f6..ce25d755b7aa 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -259,7 +259,7 @@ struct inode *afs_iget(struct super_block *sb, struct key *key,
#ifdef CONFIG_AFS_FSCACHE
vnode->cache = fscache_acquire_cookie(vnode->volume->cache,
&afs_vnode_cache_index_def,
- vnode);
+ vnode, true);
#endif
ret = afs_inode_map_status(vnode, key);
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index a306bb6d88d9..9c048ffac900 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -747,8 +747,7 @@ extern int afs_write_end(struct file *file, struct address_space *mapping,
extern int afs_writepage(struct page *, struct writeback_control *);
extern int afs_writepages(struct address_space *, struct writeback_control *);
extern void afs_pages_written_back(struct afs_vnode *, struct afs_call *);
-extern ssize_t afs_file_write(struct kiocb *, const struct iovec *,
- unsigned long, loff_t);
+extern ssize_t afs_file_write(struct kiocb *, struct iov_iter *, loff_t);
extern int afs_writeback_all(struct afs_vnode *);
extern int afs_fsync(struct file *, loff_t, loff_t, int);
diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c
index 57bcb1596530..b6df2e83809f 100644
--- a/fs/afs/vlocation.c
+++ b/fs/afs/vlocation.c
@@ -308,7 +308,8 @@ static int afs_vlocation_fill_in_record(struct afs_vlocation *vl,
/* see if we have an in-cache copy (will set vl->valid if there is) */
#ifdef CONFIG_AFS_FSCACHE
vl->cache = fscache_acquire_cookie(vl->cell->cache,
- &afs_vlocation_cache_index_def, vl);
+ &afs_vlocation_cache_index_def, vl,
+ true);
#endif
if (vl->valid) {
diff --git a/fs/afs/volume.c b/fs/afs/volume.c
index 401eeb21869f..2b607257820c 100644
--- a/fs/afs/volume.c
+++ b/fs/afs/volume.c
@@ -131,7 +131,7 @@ struct afs_volume *afs_volume_lookup(struct afs_mount_params *params)
#ifdef CONFIG_AFS_FSCACHE
volume->cache = fscache_acquire_cookie(vlocation->cache,
&afs_volume_cache_index_def,
- volume);
+ volume, true);
#endif
afs_get_vlocation(vlocation);
volume->vlocation = vlocation;
diff --git a/fs/afs/write.c b/fs/afs/write.c
index a890db4b9898..9fa2f596430a 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -625,15 +625,14 @@ void afs_pages_written_back(struct afs_vnode *vnode, struct afs_call *call)
/*
* write to an AFS file
*/
-ssize_t afs_file_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
+ssize_t afs_file_write(struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
{
struct afs_vnode *vnode = AFS_FS_I(file_inode(iocb->ki_filp));
ssize_t result;
- size_t count = iov_length(iov, nr_segs);
+ size_t count = iov_iter_count(iter);
_enter("{%x.%u},{%zu},%lu,",
- vnode->fid.vid, vnode->fid.vnode, count, nr_segs);
+ vnode->fid.vid, vnode->fid.vnode, count, iter->nr_segs);
if (IS_SWAPFILE(&vnode->vfs_inode)) {
printk(KERN_INFO
@@ -644,7 +643,7 @@ ssize_t afs_file_write(struct kiocb *iocb, const struct iovec *iov,
if (!count)
return 0;
- result = generic_file_aio_write(iocb, iov, nr_segs, pos);
+ result = generic_file_write_iter(iocb, iter, pos);
if (IS_ERR_VALUE(result)) {
_leave(" = %zd", result);
return result;
diff --git a/fs/aio.c b/fs/aio.c
index 6b868f0e0c4c..05876b23c958 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -855,6 +855,10 @@ void aio_complete(struct kiocb *iocb, long res, long res2)
iocb->ki_ctx = ERR_PTR(-EXDEV);
wake_up_process(iocb->ki_obj.tsk);
return;
+ } else if (is_kernel_kiocb(iocb)) {
+ iocb->ki_obj.complete(iocb->ki_user_data, res);
+ aio_kernel_free(iocb);
+ return;
}
/*
@@ -1173,13 +1177,55 @@ static ssize_t aio_setup_single_vector(struct kiocb *kiocb,
return 0;
}
+static ssize_t aio_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+ struct file *file = iocb->ki_filp;
+ ssize_t ret;
+
+ if (unlikely(!is_kernel_kiocb(iocb)))
+ return -EINVAL;
+
+ if (unlikely(!(file->f_mode & FMODE_READ)))
+ return -EBADF;
+
+ ret = security_file_permission(file, MAY_READ);
+ if (unlikely(ret))
+ return ret;
+
+ if (!file->f_op->read_iter)
+ return -EINVAL;
+
+ return file->f_op->read_iter(iocb, iter, iocb->ki_pos);
+}
+
+static ssize_t aio_write_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+ struct file *file = iocb->ki_filp;
+ ssize_t ret;
+
+ if (unlikely(!is_kernel_kiocb(iocb)))
+ return -EINVAL;
+
+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
+ return -EBADF;
+
+ ret = security_file_permission(file, MAY_WRITE);
+ if (unlikely(ret))
+ return ret;
+
+ if (!file->f_op->write_iter)
+ return -EINVAL;
+
+ return file->f_op->write_iter(iocb, iter, iocb->ki_pos);
+}
+
/*
* aio_setup_iocb:
* Performs the initial checks and aio retry method
* setup for the kiocb at the time of io submission.
*/
static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
- char __user *buf, bool compat)
+ void *buf, bool compat)
{
struct file *file = req->ki_filp;
ssize_t ret;
@@ -1194,14 +1240,14 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
case IOCB_CMD_PREADV:
mode = FMODE_READ;
rw = READ;
- rw_op = file->f_op->aio_read;
+ rw_op = do_aio_read;
goto rw_common;
case IOCB_CMD_PWRITE:
case IOCB_CMD_PWRITEV:
mode = FMODE_WRITE;
rw = WRITE;
- rw_op = file->f_op->aio_write;
+ rw_op = do_aio_write;
goto rw_common;
rw_common:
if (unlikely(!(file->f_mode & mode)))
@@ -1244,6 +1290,14 @@ rw_common:
file_end_write(file);
break;
+ case IOCB_CMD_READ_ITER:
+ ret = aio_read_iter(req, buf);
+ break;
+
+ case IOCB_CMD_WRITE_ITER:
+ ret = aio_write_iter(req, buf);
+ break;
+
case IOCB_CMD_FDSYNC:
if (!file->f_op->aio_fsync)
return -EINVAL;
@@ -1281,6 +1335,80 @@ rw_common:
return 0;
}
+/*
+ * This allocates an iocb that will be used to submit and track completion of
+ * an IO that is issued from kernel space.
+ *
+ * The caller is expected to call the appropriate aio_kernel_init_() functions
+ * and then call aio_kernel_submit(). From that point forward progress is
+ * guaranteed by the file system aio method. Eventually the caller's
+ * completion callback will be called.
+ *
+ * These iocbs are special. They don't have a context, we don't limit the
+ * number pending, and they can't be canceled.
+ */
+struct kiocb *aio_kernel_alloc(gfp_t gfp)
+{
+ return kzalloc(sizeof(struct kiocb), gfp);
+}
+EXPORT_SYMBOL_GPL(aio_kernel_alloc);
+
+void aio_kernel_free(struct kiocb *iocb)
+{
+ kfree(iocb);
+}
+EXPORT_SYMBOL_GPL(aio_kernel_free);
+
+/*
+ * ptr and count can be a buff and bytes or an iov and segs.
+ */
+void aio_kernel_init_rw(struct kiocb *iocb, struct file *filp,
+ size_t nr, loff_t off)
+{
+ iocb->ki_filp = filp;
+ iocb->ki_nbytes = nr;
+ iocb->ki_pos = off;
+ iocb->ki_ctx = (void *)-1;
+}
+EXPORT_SYMBOL_GPL(aio_kernel_init_rw);
+
+void aio_kernel_init_callback(struct kiocb *iocb,
+ void (*complete)(u64 user_data, long res),
+ u64 user_data)
+{
+ iocb->ki_obj.complete = complete;
+ iocb->ki_user_data = user_data;
+}
+EXPORT_SYMBOL_GPL(aio_kernel_init_callback);
+
+/*
+ * The iocb is our responsibility once this is called. The caller must not
+ * reference it.
+ *
+ * Callers must be prepared for their iocb completion callback to be called the
+ * moment they enter this function. The completion callback may be called from
+ * any context.
+ *
+ * Returns: 0: the iocb completion callback will be called with the op result
+ * negative errno: the operation was not submitted and the iocb was freed
+ */
+int aio_kernel_submit(struct kiocb *iocb, unsigned short op, void *ptr)
+{
+ int ret;
+
+ BUG_ON(!is_kernel_kiocb(iocb));
+ BUG_ON(!iocb->ki_obj.complete);
+ BUG_ON(!iocb->ki_filp);
+
+ ret = aio_run_iocb(iocb, op, ptr, 0);
+
+ if (ret)
+ aio_kernel_free(iocb);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(aio_kernel_submit);
+
static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
struct iocb *iocb, bool compat)
{
@@ -1340,7 +1468,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
req->ki_nbytes = iocb->aio_nbytes;
ret = aio_run_iocb(req, iocb->aio_lio_opcode,
- (char __user *)(unsigned long)iocb->aio_buf,
+ (void *)(unsigned long)iocb->aio_buf,
compat);
if (ret)
goto out_put_req;
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 7c93953030fb..38651e5da183 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -39,12 +39,24 @@ static ssize_t bad_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
return -EIO;
}
+static ssize_t bad_file_read_iter(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos)
+{
+ return -EIO;
+}
+
static ssize_t bad_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
return -EIO;
}
+static ssize_t bad_file_write_iter(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos)
+{
+ return -EIO;
+}
+
static int bad_file_readdir(struct file *file, struct dir_context *ctx)
{
return -EIO;
@@ -151,7 +163,9 @@ static const struct file_operations bad_file_ops =
.read = bad_file_read,
.write = bad_file_write,
.aio_read = bad_file_aio_read,
+ .read_iter = bad_file_read_iter,
.aio_write = bad_file_aio_write,
+ .write_iter = bad_file_write_iter,
.iterate = bad_file_readdir,
.poll = bad_file_poll,
.unlocked_ioctl = bad_file_unlocked_ioctl,
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index e9c75e20db32..daa15d6ba450 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -42,7 +42,7 @@ static void befs_destroy_inode(struct inode *inode);
static int befs_init_inodecache(void);
static void befs_destroy_inodecache(void);
static void *befs_follow_link(struct dentry *, struct nameidata *);
-static void befs_put_link(struct dentry *, struct nameidata *, void *);
+static void *befs_fast_follow_link(struct dentry *, struct nameidata *);
static int befs_utf2nls(struct super_block *sb, const char *in, int in_len,
char **out, int *out_len);
static int befs_nls2utf(struct super_block *sb, const char *in, int in_len,
@@ -79,10 +79,15 @@ static const struct address_space_operations befs_aops = {
.bmap = befs_bmap,
};
+static const struct inode_operations befs_fast_symlink_inode_operations = {
+ .readlink = generic_readlink,
+ .follow_link = befs_fast_follow_link,
+};
+
static const struct inode_operations befs_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = befs_follow_link,
- .put_link = befs_put_link,
+ .put_link = kfree_put_link,
};
/*
@@ -411,7 +416,10 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
inode->i_op = &befs_dir_inode_operations;
inode->i_fop = &befs_dir_operations;
} else if (S_ISLNK(inode->i_mode)) {
- inode->i_op = &befs_symlink_inode_operations;
+ if (befs_ino->i_flags & BEFS_LONG_SYMLINK)
+ inode->i_op = &befs_symlink_inode_operations;
+ else
+ inode->i_op = &befs_fast_symlink_inode_operations;
} else {
befs_error(sb, "Inode %lu is not a regular file, "
"directory or symlink. THAT IS WRONG! BeFS has no "
@@ -477,47 +485,40 @@ befs_destroy_inodecache(void)
static void *
befs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
+ struct super_block *sb = dentry->d_sb;
befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
+ befs_data_stream *data = &befs_ino->i_data.ds;
+ befs_off_t len = data->size;
char *link;
- if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
- struct super_block *sb = dentry->d_sb;
- befs_data_stream *data = &befs_ino->i_data.ds;
- befs_off_t len = data->size;
+ if (len == 0) {
+ befs_error(sb, "Long symlink with illegal length");
+ link = ERR_PTR(-EIO);
+ } else {
+ befs_debug(sb, "Follow long symlink");
- if (len == 0) {
- befs_error(sb, "Long symlink with illegal length");
+ link = kmalloc(len, GFP_NOFS);
+ if (!link) {
+ link = ERR_PTR(-ENOMEM);
+ } else if (befs_read_lsymlink(sb, data, link, len) != len) {
+ kfree(link);
+ befs_error(sb, "Failed to read entire long symlink");
link = ERR_PTR(-EIO);
} else {
- befs_debug(sb, "Follow long symlink");
-
- link = kmalloc(len, GFP_NOFS);
- if (!link) {
- link = ERR_PTR(-ENOMEM);
- } else if (befs_read_lsymlink(sb, data, link, len) != len) {
- kfree(link);
- befs_error(sb, "Failed to read entire long symlink");
- link = ERR_PTR(-EIO);
- } else {
- link[len - 1] = '\0';
- }
+ link[len - 1] = '\0';
}
- } else {
- link = befs_ino->i_data.symlink;
}
-
nd_set_link(nd, link);
return NULL;
}
-static void befs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
+
+static void *
+befs_fast_follow_link(struct dentry *dentry, struct nameidata *nd)
{
befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
- if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
- char *link = nd_get_link(nd);
- if (!IS_ERR(link))
- kfree(link);
- }
+ nd_set_link(nd, befs_ino->i_data.symlink);
+ return NULL;
}
/*
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index ae2892218335..d150660d598b 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -24,9 +24,9 @@
const struct file_operations bfs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.write = do_sync_write,
- .aio_write = generic_file_aio_write,
+ .write_iter = generic_file_write_iter,
.mmap = generic_file_mmap,
.splice_read = generic_file_splice_read,
};
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 1e86823a9cbd..34d9da0e6b74 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -165,14 +165,14 @@ blkdev_get_block(struct inode *inode, sector_t iblock,
}
static ssize_t
-blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
- loff_t offset, unsigned long nr_segs)
+blkdev_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
+ loff_t offset)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
- return __blockdev_direct_IO(rw, iocb, inode, I_BDEV(inode), iov, offset,
- nr_segs, blkdev_get_block, NULL, NULL, 0);
+ return __blockdev_direct_IO(rw, iocb, inode, I_BDEV(inode), iter,
+ offset, blkdev_get_block, NULL, NULL, 0);
}
int __sync_blockdev(struct block_device *bdev, int wait)
@@ -1508,8 +1508,7 @@ static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
* Does not take i_mutex for the write and thus is not for general purpose
* use.
*/
-ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
+ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
{
struct file *file = iocb->ki_filp;
struct blk_plug plug;
@@ -1518,7 +1517,7 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
BUG_ON(iocb->ki_pos != pos);
blk_start_plug(&plug);
- ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
+ ret = __generic_file_write_iter(iocb, iter, &iocb->ki_pos);
if (ret > 0) {
ssize_t err;
@@ -1529,10 +1528,10 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
blk_finish_plug(&plug);
return ret;
}
-EXPORT_SYMBOL_GPL(blkdev_aio_write);
+EXPORT_SYMBOL_GPL(blkdev_write_iter);
-static ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
+static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos)
{
struct file *file = iocb->ki_filp;
struct inode *bd_inode = file->f_mapping->host;
@@ -1543,8 +1542,8 @@ static ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov,
size -= pos;
if (size < iocb->ki_nbytes)
- nr_segs = iov_shorten((struct iovec *)iov, nr_segs, size);
- return generic_file_aio_read(iocb, iov, nr_segs, pos);
+ iov_iter_shorten(iter, size);
+ return generic_file_read_iter(iocb, iter, pos);
}
/*
@@ -1578,8 +1577,8 @@ const struct file_operations def_blk_fops = {
.llseek = block_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .aio_read = blkdev_aio_read,
- .aio_write = blkdev_aio_write,
+ .read_iter = blkdev_read_iter,
+ .write_iter = blkdev_write_iter,
.mmap = generic_file_mmap,
.fsync = blkdev_fsync,
.unlocked_ioctl = block_ioctl,
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 0506f40ede83..a80a2ccb955c 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3105,11 +3105,6 @@ static inline u32 btrfs_level_size(struct btrfs_root *root, int level)
((unsigned long)(btrfs_leaf_data(leaf) + \
btrfs_item_offset_nr(leaf, slot)))
-static inline struct dentry *fdentry(struct file *file)
-{
- return file->f_path.dentry;
-}
-
static inline bool btrfs_mixed_space_info(struct btrfs_space_info *space_info)
{
return ((space_info->flags & BTRFS_BLOCK_GROUP_METADATA) &&
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 72da4df53c9a..5e70fc2cef27 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -453,7 +453,7 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages,
write_bytes -= copied;
total_copied += copied;
- /* Return to btrfs_file_aio_write to fault page */
+ /* Return to btrfs_file_write_iter to fault page */
if (unlikely(copied == 0))
break;
@@ -1557,27 +1557,23 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
}
static ssize_t __btrfs_direct_write(struct kiocb *iocb,
- const struct iovec *iov,
- unsigned long nr_segs, loff_t pos,
- loff_t *ppos, size_t count, size_t ocount)
+ struct iov_iter *iter, loff_t pos,
+ loff_t *ppos, size_t count)
{
struct file *file = iocb->ki_filp;
- struct iov_iter i;
ssize_t written;
ssize_t written_buffered;
loff_t endbyte;
int err;
- written = generic_file_direct_write(iocb, iov, &nr_segs, pos, ppos,
- count, ocount);
+ written = generic_file_direct_write_iter(iocb, iter, pos, ppos, count);
if (written < 0 || written == count)
return written;
pos += written;
count -= written;
- iov_iter_init(&i, iov, nr_segs, count, written);
- written_buffered = __btrfs_buffered_write(file, &i, pos);
+ written_buffered = __btrfs_buffered_write(file, iter, pos);
if (written_buffered < 0) {
err = written_buffered;
goto out;
@@ -1612,9 +1608,8 @@ static void update_time_for_write(struct inode *inode)
inode_inc_iversion(inode);
}
-static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
- const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
+static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
+ struct iov_iter *iter, loff_t pos)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file);
@@ -1623,17 +1618,12 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
u64 start_pos;
ssize_t num_written = 0;
ssize_t err = 0;
- size_t count, ocount;
+ size_t count;
bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host);
mutex_lock(&inode->i_mutex);
- err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
- if (err) {
- mutex_unlock(&inode->i_mutex);
- goto out;
- }
- count = ocount;
+ count = iov_iter_count(iter);
current->backing_dev_info = inode->i_mapping->backing_dev_info;
err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
@@ -1686,14 +1676,10 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
atomic_inc(&BTRFS_I(inode)->sync_writers);
if (unlikely(file->f_flags & O_DIRECT)) {
- num_written = __btrfs_direct_write(iocb, iov, nr_segs,
- pos, ppos, count, ocount);
+ num_written = __btrfs_direct_write(iocb, iter, pos, ppos,
+ count);
} else {
- struct iov_iter i;
-
- iov_iter_init(&i, iov, nr_segs, count, num_written);
-
- num_written = __btrfs_buffered_write(file, &i, pos);
+ num_written = __btrfs_buffered_write(file, iter, pos);
if (num_written > 0)
*ppos = pos + num_written;
}
@@ -2552,9 +2538,9 @@ const struct file_operations btrfs_file_operations = {
.llseek = btrfs_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .aio_read = generic_file_aio_read,
.splice_read = generic_file_splice_read,
- .aio_write = btrfs_file_aio_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = btrfs_file_write_iter,
.mmap = btrfs_file_mmap,
.open = generic_file_open,
.release = btrfs_release_file,
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 22ebc13b6c99..3f70d1c23542 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -7154,8 +7154,7 @@ free_ordered:
}
static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *iocb,
- const struct iovec *iov, loff_t offset,
- unsigned long nr_segs)
+ struct iov_iter *iter, loff_t offset)
{
int seg;
int i;
@@ -7169,35 +7168,50 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io
goto out;
/* Check the memory alignment. Blocks cannot straddle pages */
- for (seg = 0; seg < nr_segs; seg++) {
- addr = (unsigned long)iov[seg].iov_base;
- size = iov[seg].iov_len;
- end += size;
- if ((addr & blocksize_mask) || (size & blocksize_mask))
- goto out;
+ if (iov_iter_has_iovec(iter)) {
+ const struct iovec *iov = iov_iter_iovec(iter);
+
+ for (seg = 0; seg < iter->nr_segs; seg++) {
+ addr = (unsigned long)iov[seg].iov_base;
+ size = iov[seg].iov_len;
+ end += size;
+ if ((addr & blocksize_mask) || (size & blocksize_mask))
+ goto out;
- /* If this is a write we don't need to check anymore */
- if (rw & WRITE)
- continue;
+ /* If this is a write we don't need to check anymore */
+ if (rw & WRITE)
+ continue;
- /*
- * Check to make sure we don't have duplicate iov_base's in this
- * iovec, if so return EINVAL, otherwise we'll get csum errors
- * when reading back.
- */
- for (i = seg + 1; i < nr_segs; i++) {
- if (iov[seg].iov_base == iov[i].iov_base)
+ /*
+ * Check to make sure we don't have duplicate iov_base's
+ * in this iovec, if so return EINVAL, otherwise we'll
+ * get csum errors when reading back.
+ */
+ for (i = seg + 1; i < iter->nr_segs; i++) {
+ if (iov[seg].iov_base == iov[i].iov_base)
+ goto out;
+ }
+ }
+ } else if (iov_iter_has_bvec(iter)) {
+ struct bio_vec *bvec = iov_iter_bvec(iter);
+
+ for (seg = 0; seg < iter->nr_segs; seg++) {
+ addr = (unsigned long)bvec[seg].bv_offset;
+ size = bvec[seg].bv_len;
+ end += size;
+ if ((addr & blocksize_mask) || (size & blocksize_mask))
goto out;
}
- }
+ } else
+ BUG();
+
retval = 0;
out:
return retval;
}
static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
- const struct iovec *iov, loff_t offset,
- unsigned long nr_segs)
+ struct iov_iter *iter, loff_t offset)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
@@ -7207,8 +7221,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
bool relock = false;
ssize_t ret;
- if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iov,
- offset, nr_segs))
+ if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iter, offset))
return 0;
atomic_inc(&inode->i_dio_count);
@@ -7220,7 +7233,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
* call btrfs_wait_ordered_range to make absolutely sure that any
* outstanding dirty pages are on disk.
*/
- count = iov_length(iov, nr_segs);
+ count = iov_iter_count(iter);
btrfs_wait_ordered_range(inode, offset, count);
if (rw & WRITE) {
@@ -7245,7 +7258,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
ret = __blockdev_direct_IO(rw, iocb, inode,
BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev,
- iov, offset, nr_segs, btrfs_get_blocks_direct, NULL,
+ iter, offset, btrfs_get_blocks_direct, NULL,
btrfs_submit_direct, flags);
if (rw & WRITE) {
if (ret < 0 && ret != -EIOCBQUEUED)
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 9d46f60cb943..6bbf316764d7 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -321,7 +321,7 @@ static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
{
- struct btrfs_fs_info *fs_info = btrfs_sb(fdentry(file)->d_sb);
+ struct btrfs_fs_info *fs_info = btrfs_sb(file_inode(file)->i_sb);
struct btrfs_device *device;
struct request_queue *q;
struct fstrim_range range;
@@ -2098,7 +2098,7 @@ static noinline int btrfs_ioctl_ino_lookup(struct file *file,
static noinline int btrfs_ioctl_snap_destroy(struct file *file,
void __user *arg)
{
- struct dentry *parent = fdentry(file);
+ struct dentry *parent = file->f_path.dentry;
struct dentry *dentry;
struct inode *dir = parent->d_inode;
struct inode *inode;
@@ -3119,7 +3119,7 @@ out:
static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
u64 off, u64 olen, u64 destoff)
{
- struct inode *inode = fdentry(file)->d_inode;
+ struct inode *inode = file_inode(file);
struct btrfs_root *root = BTRFS_I(inode)->root;
struct fd src_file;
struct inode *src;
@@ -4317,7 +4317,7 @@ static long btrfs_ioctl_quota_rescan_status(struct file *file, void __user *arg)
static long btrfs_ioctl_quota_rescan_wait(struct file *file, void __user *arg)
{
- struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;
+ struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c
index 43eb5592cdea..00baf1419989 100644
--- a/fs/cachefiles/interface.c
+++ b/fs/cachefiles/interface.c
@@ -270,7 +270,7 @@ static void cachefiles_drop_object(struct fscache_object *_object)
#endif
/* delete retired objects */
- if (test_bit(FSCACHE_COOKIE_RETIRED, &object->fscache.cookie->flags) &&
+ if (test_bit(FSCACHE_OBJECT_RETIRED, &object->fscache.flags) &&
_object != cache->cache.fsdef
) {
_debug("- retire object OBJ%x", object->fscache.debug_id);
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 6df8bd481425..1cb39e652886 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -1179,8 +1179,7 @@ static int ceph_write_end(struct file *file, struct address_space *mapping,
* never get called.
*/
static ssize_t ceph_direct_io(int rw, struct kiocb *iocb,
- const struct iovec *iov,
- loff_t pos, unsigned long nr_segs)
+ struct iov_iter *iter, loff_t pos)
{
WARN_ON(1);
return -EINVAL;
diff --git a/fs/ceph/cache.c b/fs/ceph/cache.c
index 6bfe65e0b038..8c44fdd4e1c3 100644
--- a/fs/ceph/cache.c
+++ b/fs/ceph/cache.c
@@ -68,7 +68,7 @@ int ceph_fscache_register_fs(struct ceph_fs_client* fsc)
{
fsc->fscache = fscache_acquire_cookie(ceph_cache_netfs.primary_index,
&ceph_fscache_fsid_object_def,
- fsc);
+ fsc, true);
if (fsc->fscache == NULL) {
pr_err("Unable to resgister fsid: %p fscache cookie", fsc);
@@ -204,7 +204,7 @@ void ceph_fscache_register_inode_cookie(struct ceph_fs_client* fsc,
ci->fscache = fscache_acquire_cookie(fsc->fscache,
&ceph_fscache_inode_object_def,
- ci);
+ ci, true);
done:
mutex_unlock(&inode->i_mutex);
@@ -324,6 +324,9 @@ void ceph_invalidate_fscache_page(struct inode* inode, struct page *page)
{
struct ceph_inode_info *ci = ceph_inode(inode);
+ if (!PageFsCache(page))
+ return;
+
fscache_wait_on_page_write(ci->fscache, page);
fscache_uncache_page(ci->fscache, page);
}
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 13976c33332e..3c0a4bd74996 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -897,7 +897,7 @@ static int __ceph_is_any_caps(struct ceph_inode_info *ci)
* caller should hold i_ceph_lock.
* caller will not hold session s_mutex if called from destroy_inode.
*/
-void __ceph_remove_cap(struct ceph_cap *cap)
+void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
{
struct ceph_mds_session *session = cap->session;
struct ceph_inode_info *ci = cap->ci;
@@ -909,6 +909,16 @@ void __ceph_remove_cap(struct ceph_cap *cap)
/* remove from session list */
spin_lock(&session->s_cap_lock);
+ /*
+ * s_cap_reconnect is protected by s_cap_lock. no one changes
+ * s_cap_gen while session is in the reconnect state.
+ */
+ if (queue_release &&
+ (!session->s_cap_reconnect ||
+ cap->cap_gen == session->s_cap_gen))
+ __queue_cap_release(session, ci->i_vino.ino, cap->cap_id,
+ cap->mseq, cap->issue_seq);
+
if (session->s_cap_iterator == cap) {
/* not yet, we are iterating over this very cap */
dout("__ceph_remove_cap delaying %p removal from session %p\n",
@@ -1023,7 +1033,6 @@ void __queue_cap_release(struct ceph_mds_session *session,
struct ceph_mds_cap_release *head;
struct ceph_mds_cap_item *item;
- spin_lock(&session->s_cap_lock);
BUG_ON(!session->s_num_cap_releases);
msg = list_first_entry(&session->s_cap_releases,
struct ceph_msg, list_head);
@@ -1052,7 +1061,6 @@ void __queue_cap_release(struct ceph_mds_session *session,
(int)CEPH_CAPS_PER_RELEASE,
(int)msg->front.iov_len);
}
- spin_unlock(&session->s_cap_lock);
}
/*
@@ -1067,12 +1075,8 @@ void ceph_queue_caps_release(struct inode *inode)
p = rb_first(&ci->i_caps);
while (p) {
struct ceph_cap *cap = rb_entry(p, struct ceph_cap, ci_node);
- struct ceph_mds_session *session = cap->session;
-
- __queue_cap_release(session, ceph_ino(inode), cap->cap_id,
- cap->mseq, cap->issue_seq);
p = rb_next(p);
- __ceph_remove_cap(cap);
+ __ceph_remove_cap(cap, true);
}
}
@@ -2791,7 +2795,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
}
spin_unlock(&mdsc->cap_dirty_lock);
}
- __ceph_remove_cap(cap);
+ __ceph_remove_cap(cap, false);
}
/* else, we already released it */
@@ -2931,9 +2935,12 @@ void ceph_handle_caps(struct ceph_mds_session *session,
if (!inode) {
dout(" i don't have ino %llx\n", vino.ino);
- if (op == CEPH_CAP_OP_IMPORT)
+ if (op == CEPH_CAP_OP_IMPORT) {
+ spin_lock(&session->s_cap_lock);
__queue_cap_release(session, vino.ino, cap_id,
mseq, seq);
+ spin_unlock(&session->s_cap_lock);
+ }
goto flush_cap_releases;
}
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 868b61d56cac..2a0bcaeb189a 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -352,8 +352,18 @@ more:
}
/* note next offset and last dentry name */
+ rinfo = &req->r_reply_info;
+ if (le32_to_cpu(rinfo->dir_dir->frag) != frag) {
+ frag = le32_to_cpu(rinfo->dir_dir->frag);
+ if (ceph_frag_is_leftmost(frag))
+ fi->next_offset = 2;
+ else
+ fi->next_offset = 0;
+ off = fi->next_offset;
+ }
fi->offset = fi->next_offset;
fi->last_readdir = req;
+ fi->frag = frag;
if (req->r_reply_info.dir_end) {
kfree(fi->last_name);
@@ -363,7 +373,6 @@ more:
else
fi->next_offset = 0;
} else {
- rinfo = &req->r_reply_info;
err = note_last_dentry(fi,
rinfo->dir_dname[rinfo->dir_nr-1],
rinfo->dir_dname_len[rinfo->dir_nr-1]);
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 3de89829e2a1..12163727ca9d 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -489,83 +489,79 @@ static void ceph_sync_write_unsafe(struct ceph_osd_request *req, bool unsafe)
}
}
+
/*
- * Synchronous write, straight from __user pointer or user pages (if
- * O_DIRECT).
+ * Synchronous write, straight from __user pointer or user pages.
*
* If write spans object boundary, just do multiple writes. (For a
* correct atomic write, we should e.g. take write locks on all
* objects, rollback on failure, etc.)
*/
-static ssize_t ceph_sync_write(struct file *file, const char __user *data,
- size_t left, loff_t pos, loff_t *ppos)
+static ssize_t
+ceph_sync_direct_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, size_t count)
{
+ struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
struct ceph_snap_context *snapc;
struct ceph_vino vino;
struct ceph_osd_request *req;
- int num_ops = 1;
struct page **pages;
int num_pages;
- u64 len;
int written = 0;
int flags;
int check_caps = 0;
- int page_align, io_align;
- unsigned long buf_align;
+ int page_align;
int ret;
struct timespec mtime = CURRENT_TIME;
- bool own_pages = false;
+ loff_t pos = iocb->ki_pos;
+ struct iov_iter i;
if (ceph_snap(file_inode(file)) != CEPH_NOSNAP)
return -EROFS;
- dout("sync_write on file %p %lld~%u %s\n", file, pos,
- (unsigned)left, (file->f_flags & O_DIRECT) ? "O_DIRECT" : "");
+ dout("sync_direct_write on file %p %lld~%u\n", file, pos,
+ (unsigned)count);
- ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + left);
+ ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + count);
if (ret < 0)
return ret;
ret = invalidate_inode_pages2_range(inode->i_mapping,
pos >> PAGE_CACHE_SHIFT,
- (pos + left) >> PAGE_CACHE_SHIFT);
+ (pos + count) >> PAGE_CACHE_SHIFT);
if (ret < 0)
dout("invalidate_inode_pages2_range returned %d\n", ret);
flags = CEPH_OSD_FLAG_ORDERSNAP |
CEPH_OSD_FLAG_ONDISK |
CEPH_OSD_FLAG_WRITE;
- if ((file->f_flags & (O_SYNC|O_DIRECT)) == 0)
- flags |= CEPH_OSD_FLAG_ACK;
- else
- num_ops++; /* Also include a 'startsync' command. */
- /*
- * we may need to do multiple writes here if we span an object
- * boundary. this isn't atomic, unfortunately. :(
- */
-more:
- io_align = pos & ~PAGE_MASK;
- buf_align = (unsigned long)data & ~PAGE_MASK;
- len = left;
-
- snapc = ci->i_snap_realm->cached_context;
- vino = ceph_vino(inode);
- req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
- vino, pos, &len, num_ops,
- CEPH_OSD_OP_WRITE, flags, snapc,
- ci->i_truncate_seq, ci->i_truncate_size,
- false);
- if (IS_ERR(req))
- return PTR_ERR(req);
+ iov_iter_init(&i, iov, nr_segs, count, 0);
+
+ while (iov_iter_count(&i) > 0) {
+ void __user *data = iov_iter_iovec(&i)->iov_base + i.iov_offset;
+ u64 len = iov_iter_iovec(&i)->iov_len - i.iov_offset;
+
+ page_align = (unsigned long)data & ~PAGE_MASK;
+
+ snapc = ci->i_snap_realm->cached_context;
+ vino = ceph_vino(inode);
+ req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
+ vino, pos, &len,
+ 2,/*include a 'startsync' command*/
+ CEPH_OSD_OP_WRITE, flags, snapc,
+ ci->i_truncate_seq,
+ ci->i_truncate_size,
+ false);
+ if (IS_ERR(req)) {
+ ret = PTR_ERR(req);
+ goto out;
+ }
- /* write from beginning of first page, regardless of io alignment */
- page_align = file->f_flags & O_DIRECT ? buf_align : io_align;
- num_pages = calc_pages_for(page_align, len);
- if (file->f_flags & O_DIRECT) {
+ num_pages = calc_pages_for(page_align, len);
pages = ceph_get_direct_page_vector(data, num_pages, false);
if (IS_ERR(pages)) {
ret = PTR_ERR(pages);
@@ -577,60 +573,175 @@ more:
* may block.
*/
truncate_inode_pages_range(inode->i_mapping, pos,
- (pos+len) | (PAGE_CACHE_SIZE-1));
- } else {
+ (pos+len) | (PAGE_CACHE_SIZE-1));
+ osd_req_op_extent_osd_data_pages(req, 0, pages, len, page_align,
+ false, false);
+
+ /* BUG_ON(vino.snap != CEPH_NOSNAP); */
+ ceph_osdc_build_request(req, pos, snapc, vino.snap, &mtime);
+
+ ret = ceph_osdc_start_request(&fsc->client->osdc, req, false);
+ if (!ret)
+ ret = ceph_osdc_wait_request(&fsc->client->osdc, req);
+
+ ceph_put_page_vector(pages, num_pages, false);
+
+out:
+ ceph_osdc_put_request(req);
+ if (ret == 0) {
+ pos += len;
+ written += len;
+ iov_iter_advance(&i, (size_t)len);
+
+ if (pos > i_size_read(inode)) {
+ check_caps = ceph_inode_set_size(inode, pos);
+ if (check_caps)
+ ceph_check_caps(ceph_inode(inode),
+ CHECK_CAPS_AUTHONLY,
+ NULL);
+ }
+ } else
+ break;
+ }
+
+ if (ret != -EOLDSNAPC && written > 0) {
+ iocb->ki_pos = pos;
+ ret = written;
+ }
+ return ret;
+}
+
+
+/*
+ * Synchronous write, straight from __user pointer or user pages.
+ *
+ * If write spans object boundary, just do multiple writes. (For a
+ * correct atomic write, we should e.g. take write locks on all
+ * objects, rollback on failure, etc.)
+ */
+static ssize_t ceph_sync_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, size_t count)
+{
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file_inode(file);
+ struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_snap_context *snapc;
+ struct ceph_vino vino;
+ struct ceph_osd_request *req;
+ struct page **pages;
+ u64 len;
+ int num_pages;
+ int written = 0;
+ int flags;
+ int check_caps = 0;
+ int ret;
+ struct timespec mtime = CURRENT_TIME;
+ loff_t pos = iocb->ki_pos;
+ struct iov_iter i;
+
+ if (ceph_snap(file_inode(file)) != CEPH_NOSNAP)
+ return -EROFS;
+
+ dout("sync_write on file %p %lld~%u\n", file, pos, (unsigned)count);
+
+ ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + count);
+ if (ret < 0)
+ return ret;
+
+ ret = invalidate_inode_pages2_range(inode->i_mapping,
+ pos >> PAGE_CACHE_SHIFT,
+ (pos + count) >> PAGE_CACHE_SHIFT);
+ if (ret < 0)
+ dout("invalidate_inode_pages2_range returned %d\n", ret);
+
+ flags = CEPH_OSD_FLAG_ORDERSNAP |
+ CEPH_OSD_FLAG_ONDISK |
+ CEPH_OSD_FLAG_WRITE |
+ CEPH_OSD_FLAG_ACK;
+
+ iov_iter_init(&i, iov, nr_segs, count, 0);
+
+ while ((len = iov_iter_count(&i)) > 0) {
+ size_t left;
+ int n;
+
+ snapc = ci->i_snap_realm->cached_context;
+ vino = ceph_vino(inode);
+ req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
+ vino, pos, &len, 1,
+ CEPH_OSD_OP_WRITE, flags, snapc,
+ ci->i_truncate_seq,
+ ci->i_truncate_size,
+ false);
+ if (IS_ERR(req)) {
+ ret = PTR_ERR(req);
+ goto out;
+ }
+
+ /*
+ * write from beginning of first page,
+ * regardless of io alignment
+ */
+ num_pages = (len + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+
pages = ceph_alloc_page_vector(num_pages, GFP_NOFS);
if (IS_ERR(pages)) {
ret = PTR_ERR(pages);
goto out;
}
- ret = ceph_copy_user_to_page_vector(pages, data, pos, len);
+
+ left = len;
+ for (n = 0; n < num_pages; n++) {
+ size_t plen = min(left, PAGE_SIZE);
+ ret = iov_iter_copy_from_user(pages[n], &i, 0, plen);
+ if (ret != plen) {
+ ret = -EFAULT;
+ break;
+ }
+ left -= ret;
+ iov_iter_advance(&i, ret);
+ }
+
if (ret < 0) {
ceph_release_page_vector(pages, num_pages);
goto out;
}
- if ((file->f_flags & O_SYNC) == 0) {
- /* get a second commit callback */
- req->r_unsafe_callback = ceph_sync_write_unsafe;
- req->r_inode = inode;
- own_pages = true;
- }
- }
- osd_req_op_extent_osd_data_pages(req, 0, pages, len, page_align,
- false, own_pages);
+ /* get a second commit callback */
+ req->r_unsafe_callback = ceph_sync_write_unsafe;
+ req->r_inode = inode;
- /* BUG_ON(vino.snap != CEPH_NOSNAP); */
- ceph_osdc_build_request(req, pos, snapc, vino.snap, &mtime);
+ osd_req_op_extent_osd_data_pages(req, 0, pages, len, 0,
+ false, true);
- ret = ceph_osdc_start_request(&fsc->client->osdc, req, false);
- if (!ret)
- ret = ceph_osdc_wait_request(&fsc->client->osdc, req);
+ /* BUG_ON(vino.snap != CEPH_NOSNAP); */
+ ceph_osdc_build_request(req, pos, snapc, vino.snap, &mtime);
- if (file->f_flags & O_DIRECT)
- ceph_put_page_vector(pages, num_pages, false);
- else if (file->f_flags & O_SYNC)
- ceph_release_page_vector(pages, num_pages);
+ ret = ceph_osdc_start_request(&fsc->client->osdc, req, false);
+ if (!ret)
+ ret = ceph_osdc_wait_request(&fsc->client->osdc, req);
out:
- ceph_osdc_put_request(req);
- if (ret == 0) {
- pos += len;
- written += len;
- left -= len;
- data += len;
- if (left)
- goto more;
+ ceph_osdc_put_request(req);
+ if (ret == 0) {
+ pos += len;
+ written += len;
+
+ if (pos > i_size_read(inode)) {
+ check_caps = ceph_inode_set_size(inode, pos);
+ if (check_caps)
+ ceph_check_caps(ceph_inode(inode),
+ CHECK_CAPS_AUTHONLY,
+ NULL);
+ }
+ } else
+ break;
+ }
+ if (ret != -EOLDSNAPC && written > 0) {
ret = written;
- *ppos = pos;
- if (pos > i_size_read(inode))
- check_caps = ceph_inode_set_size(inode, pos);
- if (check_caps)
- ceph_check_caps(ceph_inode(inode), CHECK_CAPS_AUTHONLY,
- NULL);
- } else if (ret != -EOLDSNAPC && written > 0) {
- ret = written;
+ iocb->ki_pos = pos;
}
return ret;
}
@@ -772,11 +883,13 @@ retry_snap:
inode, ceph_vinop(inode), pos, count, ceph_cap_string(got));
if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 ||
- (iocb->ki_filp->f_flags & O_DIRECT) ||
- (fi->flags & CEPH_F_SYNC)) {
+ (file->f_flags & O_DIRECT) || (fi->flags & CEPH_F_SYNC)) {
mutex_unlock(&inode->i_mutex);
- written = ceph_sync_write(file, iov->iov_base, count,
- pos, &iocb->ki_pos);
+ if (file->f_flags & O_DIRECT)
+ written = ceph_sync_direct_write(iocb, iov,
+ nr_segs, count);
+ else
+ written = ceph_sync_write(iocb, iov, nr_segs, count);
if (written == -EOLDSNAPC) {
dout("aio_write %p %llx.%llx %llu~%u"
"got EOLDSNAPC, retrying\n",
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 8549a48115f7..49d4de05808f 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -436,6 +436,16 @@ void ceph_destroy_inode(struct inode *inode)
call_rcu(&inode->i_rcu, ceph_i_callback);
}
+int ceph_drop_inode(struct inode *inode)
+{
+ /*
+ * Positve dentry and corresponding inode are always accompanied
+ * in MDS reply. So no need to keep inode in the cache after
+ * dropping all its aliases.
+ */
+ return 1;
+}
+
/*
* Helpers to fill in size, ctime, mtime, and atime. We have to be
* careful because either the client or MDS may have more up to date
@@ -577,6 +587,8 @@ static int fill_inode(struct inode *inode,
int issued = 0, implemented;
struct timespec mtime, atime, ctime;
u32 nsplits;
+ struct ceph_inode_frag *frag;
+ struct rb_node *rb_node;
struct ceph_buffer *xattr_blob = NULL;
int err = 0;
int queue_trunc = 0;
@@ -751,15 +763,37 @@ no_change:
/* FIXME: move me up, if/when version reflects fragtree changes */
nsplits = le32_to_cpu(info->fragtree.nsplits);
mutex_lock(&ci->i_fragtree_mutex);
+ rb_node = rb_first(&ci->i_fragtree);
for (i = 0; i < nsplits; i++) {
u32 id = le32_to_cpu(info->fragtree.splits[i].frag);
- struct ceph_inode_frag *frag = __get_or_create_frag(ci, id);
-
- if (IS_ERR(frag))
- continue;
+ frag = NULL;
+ while (rb_node) {
+ frag = rb_entry(rb_node, struct ceph_inode_frag, node);
+ if (ceph_frag_compare(frag->frag, id) >= 0) {
+ if (frag->frag != id)
+ frag = NULL;
+ else
+ rb_node = rb_next(rb_node);
+ break;
+ }
+ rb_node = rb_next(rb_node);
+ rb_erase(&frag->node, &ci->i_fragtree);
+ kfree(frag);
+ }
+ if (!frag) {
+ frag = __get_or_create_frag(ci, id);
+ if (IS_ERR(frag))
+ continue;
+ }
frag->split_by = le32_to_cpu(info->fragtree.splits[i].by);
dout(" frag %x split by %d\n", frag->frag, frag->split_by);
}
+ while (rb_node) {
+ frag = rb_entry(rb_node, struct ceph_inode_frag, node);
+ rb_node = rb_next(rb_node);
+ rb_erase(&frag->node, &ci->i_fragtree);
+ kfree(frag);
+ }
mutex_unlock(&ci->i_fragtree_mutex);
/* were we issued a capability? */
@@ -1250,8 +1284,19 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
int err = 0, i;
struct inode *snapdir = NULL;
struct ceph_mds_request_head *rhead = req->r_request->front.iov_base;
- u64 frag = le32_to_cpu(rhead->args.readdir.frag);
struct ceph_dentry_info *di;
+ u64 r_readdir_offset = req->r_readdir_offset;
+ u32 frag = le32_to_cpu(rhead->args.readdir.frag);
+
+ if (le32_to_cpu(rinfo->dir_dir->frag) != frag) {
+ dout("readdir_prepopulate got new frag %x -> %x\n",
+ frag, le32_to_cpu(rinfo->dir_dir->frag));
+ frag = le32_to_cpu(rinfo->dir_dir->frag);
+ if (ceph_frag_is_leftmost(frag))
+ r_readdir_offset = 2;
+ else
+ r_readdir_offset = 0;
+ }
if (req->r_aborted)
return readdir_prepopulate_inodes_only(req, session);
@@ -1315,7 +1360,7 @@ retry_lookup:
}
di = dn->d_fsdata;
- di->offset = ceph_make_fpos(frag, i + req->r_readdir_offset);
+ di->offset = ceph_make_fpos(frag, i + r_readdir_offset);
/* inode */
if (dn->d_inode) {
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index b7bda5d9611d..6d953ab0ac06 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -43,6 +43,7 @@
*/
struct ceph_reconnect_state {
+ int nr_caps;
struct ceph_pagelist *pagelist;
bool flock;
};
@@ -443,6 +444,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
INIT_LIST_HEAD(&s->s_waiting);
INIT_LIST_HEAD(&s->s_unsafe);
s->s_num_cap_releases = 0;
+ s->s_cap_reconnect = 0;
s->s_cap_iterator = NULL;
INIT_LIST_HEAD(&s->s_cap_releases);
INIT_LIST_HEAD(&s->s_cap_releases_done);
@@ -986,7 +988,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
dout("removing cap %p, ci is %p, inode is %p\n",
cap, ci, &ci->vfs_inode);
spin_lock(&ci->i_ceph_lock);
- __ceph_remove_cap(cap);
+ __ceph_remove_cap(cap, false);
if (!__ceph_is_any_real_caps(ci)) {
struct ceph_mds_client *mdsc =
ceph_sb_to_client(inode->i_sb)->mdsc;
@@ -1231,9 +1233,7 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg)
session->s_trim_caps--;
if (oissued) {
/* we aren't the only cap.. just remove us */
- __queue_cap_release(session, ceph_ino(inode), cap->cap_id,
- cap->mseq, cap->issue_seq);
- __ceph_remove_cap(cap);
+ __ceph_remove_cap(cap, true);
} else {
/* try to drop referring dentries */
spin_unlock(&ci->i_ceph_lock);
@@ -1416,7 +1416,6 @@ static void discard_cap_releases(struct ceph_mds_client *mdsc,
unsigned num;
dout("discard_cap_releases mds%d\n", session->s_mds);
- spin_lock(&session->s_cap_lock);
/* zero out the in-progress message */
msg = list_first_entry(&session->s_cap_releases,
@@ -1443,8 +1442,6 @@ static void discard_cap_releases(struct ceph_mds_client *mdsc,
msg->front.iov_len = sizeof(*head);
list_add(&msg->list_head, &session->s_cap_releases);
}
-
- spin_unlock(&session->s_cap_lock);
}
/*
@@ -2238,8 +2235,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
err = ceph_fill_trace(mdsc->fsc->sb, req, req->r_session);
if (err == 0) {
if (result == 0 && (req->r_op == CEPH_MDS_OP_READDIR ||
- req->r_op == CEPH_MDS_OP_LSSNAP) &&
- rinfo->dir_nr)
+ req->r_op == CEPH_MDS_OP_LSSNAP))
ceph_readdir_prepopulate(req, req->r_session);
ceph_unreserve_caps(mdsc, &req->r_caps_reservation);
}
@@ -2490,6 +2486,7 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap,
cap->seq = 0; /* reset cap seq */
cap->issue_seq = 0; /* and issue_seq */
cap->mseq = 0; /* and migrate_seq */
+ cap->cap_gen = cap->session->s_cap_gen;
if (recon_state->flock) {
rec.v2.cap_id = cpu_to_le64(cap->cap_id);
@@ -2552,6 +2549,8 @@ encode_again:
} else {
err = ceph_pagelist_append(pagelist, &rec, reclen);
}
+
+ recon_state->nr_caps++;
out_free:
kfree(path);
out_dput:
@@ -2579,6 +2578,7 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc,
struct rb_node *p;
int mds = session->s_mds;
int err = -ENOMEM;
+ int s_nr_caps;
struct ceph_pagelist *pagelist;
struct ceph_reconnect_state recon_state;
@@ -2610,20 +2610,38 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc,
dout("session %p state %s\n", session,
session_state_name(session->s_state));
+ spin_lock(&session->s_gen_ttl_lock);
+ session->s_cap_gen++;
+ spin_unlock(&session->s_gen_ttl_lock);
+
+ spin_lock(&session->s_cap_lock);
+ /*
+ * notify __ceph_remove_cap() that we are composing cap reconnect.
+ * If a cap get released before being added to the cap reconnect,
+ * __ceph_remove_cap() should skip queuing cap release.
+ */
+ session->s_cap_reconnect = 1;
/* drop old cap expires; we're about to reestablish that state */
discard_cap_releases(mdsc, session);
+ spin_unlock(&session->s_cap_lock);
/* traverse this session's caps */
- err = ceph_pagelist_encode_32(pagelist, session->s_nr_caps);
+ s_nr_caps = session->s_nr_caps;
+ err = ceph_pagelist_encode_32(pagelist, s_nr_caps);
if (err)
goto fail;
+ recon_state.nr_caps = 0;
recon_state.pagelist = pagelist;
recon_state.flock = session->s_con.peer_features & CEPH_FEATURE_FLOCK;
err = iterate_session_caps(session, encode_caps_cb, &recon_state);
if (err < 0)
goto fail;
+ spin_lock(&session->s_cap_lock);
+ session->s_cap_reconnect = 0;
+ spin_unlock(&session->s_cap_lock);
+
/*
* snaprealms. we provide mds with the ino, seq (version), and
* parent for all of our realms. If the mds has any newer info,
@@ -2646,11 +2664,18 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc,
if (recon_state.flock)
reply->hdr.version = cpu_to_le16(2);
- if (pagelist->length) {
- /* set up outbound data if we have any */
- reply->hdr.data_len = cpu_to_le32(pagelist->length);
- ceph_msg_data_add_pagelist(reply, pagelist);
+
+ /* raced with cap release? */
+ if (s_nr_caps != recon_state.nr_caps) {
+ struct page *page = list_first_entry(&pagelist->head,
+ struct page, lru);
+ __le32 *addr = kmap_atomic(page);
+ *addr = cpu_to_le32(recon_state.nr_caps);
+ kunmap_atomic(addr);
}
+
+ reply->hdr.data_len = cpu_to_le32(pagelist->length);
+ ceph_msg_data_add_pagelist(reply, pagelist);
ceph_con_send(&session->s_con, reply);
mutex_unlock(&session->s_mutex);
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index c2a19fbbe517..4c053d099ae4 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -132,6 +132,7 @@ struct ceph_mds_session {
struct list_head s_caps; /* all caps issued by this session */
int s_nr_caps, s_trim_caps;
int s_num_cap_releases;
+ int s_cap_reconnect;
struct list_head s_cap_releases; /* waiting cap_release messages */
struct list_head s_cap_releases_done; /* ready to send */
struct ceph_cap *s_cap_iterator;
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 6a0951e43044..e58bd4a23bfb 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -686,6 +686,7 @@ static const struct super_operations ceph_super_ops = {
.alloc_inode = ceph_alloc_inode,
.destroy_inode = ceph_destroy_inode,
.write_inode = ceph_write_inode,
+ .drop_inode = ceph_drop_inode,
.sync_fs = ceph_sync_fs,
.put_super = ceph_put_super,
.show_options = ceph_show_options,
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 6014b0a3c405..8de94b564d67 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -691,6 +691,7 @@ extern const struct inode_operations ceph_file_iops;
extern struct inode *ceph_alloc_inode(struct super_block *sb);
extern void ceph_destroy_inode(struct inode *inode);
+extern int ceph_drop_inode(struct inode *inode);
extern struct inode *ceph_get_inode(struct super_block *sb,
struct ceph_vino vino);
@@ -741,13 +742,7 @@ extern int ceph_add_cap(struct inode *inode,
int fmode, unsigned issued, unsigned wanted,
unsigned cap, unsigned seq, u64 realmino, int flags,
struct ceph_cap_reservation *caps_reservation);
-extern void __ceph_remove_cap(struct ceph_cap *cap);
-static inline void ceph_remove_cap(struct ceph_cap *cap)
-{
- spin_lock(&cap->ci->i_ceph_lock);
- __ceph_remove_cap(cap);
- spin_unlock(&cap->ci->i_ceph_lock);
-}
+extern void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release);
extern void ceph_put_cap(struct ceph_mds_client *mdsc,
struct ceph_cap *cap);
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index a16b4e58bcc6..801975c34cf9 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -860,7 +860,7 @@ const struct inode_operations cifs_file_inode_ops = {
const struct inode_operations cifs_symlink_inode_ops = {
.readlink = generic_readlink,
.follow_link = cifs_follow_link,
- .put_link = cifs_put_link,
+ .put_link = kfree_put_link,
.permission = cifs_permission,
/* BB add the following two eventually */
/* revalidate: cifs_revalidate,
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index ea723a5e8226..26a754f49ba1 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -115,8 +115,6 @@ extern struct vfsmount *cifs_dfs_d_automount(struct path *path);
/* Functions related to symlinks */
extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
-extern void cifs_put_link(struct dentry *direntry,
- struct nameidata *nd, void *);
extern int cifs_readlink(struct dentry *direntry, char __user *buffer,
int buflen);
extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
@@ -132,5 +130,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */
-#define CIFS_VERSION "2.01"
+#define CIFS_VERSION "2.02"
#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index cfa14c80ef3b..52b6f6c26bfc 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -547,9 +547,6 @@ struct TCP_Server_Info {
unsigned int max_rw; /* maxRw specifies the maximum */
/* message size the server can send or receive for */
/* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
- unsigned int max_vcs; /* maximum number of smb sessions, at least
- those that can be specified uniquely with
- vcnumbers */
unsigned int capabilities; /* selective disabling of caps by smb sess */
int timeAdj; /* Adjust for difference in server time zone in sec */
__u64 CurrentMid; /* multiplex id - rotating counter */
@@ -715,7 +712,6 @@ struct cifs_ses {
enum statusEnum status;
unsigned overrideSecFlg; /* if non-zero override global sec flags */
__u16 ipc_tid; /* special tid for connection to IPC share */
- __u16 vcnum;
char *serverOS; /* name of operating system underlying server */
char *serverNOS; /* name of network operating system of server */
char *serverDomain; /* security realm of server */
@@ -1272,6 +1268,7 @@ struct dfs_info3_param {
#define CIFS_FATTR_DELETE_PENDING 0x2
#define CIFS_FATTR_NEED_REVAL 0x4
#define CIFS_FATTR_INO_COLLISION 0x8
+#define CIFS_FATTR_UNKNOWN_NLINK 0x10
struct cifs_fattr {
u32 cf_flags;
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 948676db8e2e..a630475e421c 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -2652,26 +2652,7 @@ typedef struct file_xattr_info {
} __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute info
level 0x205 */
-
-/* flags for chattr command */
-#define EXT_SECURE_DELETE 0x00000001 /* EXT3_SECRM_FL */
-#define EXT_ENABLE_UNDELETE 0x00000002 /* EXT3_UNRM_FL */
-/* Reserved for compress file 0x4 */
-#define EXT_SYNCHRONOUS 0x00000008 /* EXT3_SYNC_FL */
-#define EXT_IMMUTABLE_FL 0x00000010 /* EXT3_IMMUTABLE_FL */
-#define EXT_OPEN_APPEND_ONLY 0x00000020 /* EXT3_APPEND_FL */
-#define EXT_DO_NOT_BACKUP 0x00000040 /* EXT3_NODUMP_FL */
-#define EXT_NO_UPDATE_ATIME 0x00000080 /* EXT3_NOATIME_FL */
-/* 0x100 through 0x800 reserved for compression flags and are GET-ONLY */
-#define EXT_HASH_TREE_INDEXED_DIR 0x00001000 /* GET-ONLY EXT3_INDEX_FL */
-/* 0x2000 reserved for IMAGIC_FL */
-#define EXT_JOURNAL_THIS_FILE 0x00004000 /* GET-ONLY EXT3_JOURNAL_DATA_FL */
-/* 0x8000 reserved for EXT3_NOTAIL_FL */
-#define EXT_SYNCHRONOUS_DIR 0x00010000 /* EXT3_DIRSYNC_FL */
-#define EXT_TOPDIR 0x00020000 /* EXT3_TOPDIR_FL */
-
-#define EXT_SET_MASK 0x000300FF
-#define EXT_GET_MASK 0x0003DFFF
+/* flags for lsattr and chflags commands removed arein uapi/linux/fs.h */
typedef struct file_chattr_info {
__le64 mask; /* list of all possible attribute bits */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index a3d74fea1623..4baf35949b51 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -463,7 +463,6 @@ decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
cifs_max_pending);
set_credits(server, server->maxReq);
server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
- server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
/* even though we do not use raw we might as well set this
accurately, in case we ever find a need for it */
if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index eb955b525e55..cf6aedc59c21 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2737,8 +2737,8 @@ cifs_readdata_to_iov(struct cifs_readdata *rdata, const struct iovec *iov,
/* go while there's data to be copied and no errors */
if (copy && !rc) {
pdata = kmap(page);
- rc = memcpy_toiovecend(ii.iov, pdata, ii.iov_offset,
- (int)copy);
+ rc = memcpy_toiovecend(iov_iter_iovec(&ii), pdata,
+ ii.iov_offset, (int)copy);
kunmap(page);
if (!rc) {
*copied += copy;
@@ -3254,6 +3254,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
/*
* Reads as many pages as possible from fscache. Returns -ENOBUFS
* immediately if the cookie is negative
+ *
+ * After this point, every page in the list might have PG_fscache set,
+ * so we will need to clean that up off of every page we don't use.
*/
rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
&num_pages);
@@ -3376,6 +3379,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
kref_put(&rdata->refcount, cifs_readdata_release);
}
+ /* Any pages that have been shown to fscache but didn't get added to
+ * the pagecache must be uncached before they get returned to the
+ * allocator.
+ */
+ cifs_fscache_readpages_cancel(mapping->host, page_list);
return rc;
}
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
index 2f4bc5a58054..8d4b7bc8ae91 100644
--- a/fs/cifs/fscache.c
+++ b/fs/cifs/fscache.c
@@ -27,7 +27,7 @@ void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server)
{
server->fscache =
fscache_acquire_cookie(cifs_fscache_netfs.primary_index,
- &cifs_fscache_server_index_def, server);
+ &cifs_fscache_server_index_def, server, true);
cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
__func__, server, server->fscache);
}
@@ -46,7 +46,7 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
tcon->fscache =
fscache_acquire_cookie(server->fscache,
- &cifs_fscache_super_index_def, tcon);
+ &cifs_fscache_super_index_def, tcon, true);
cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
__func__, server->fscache, tcon->fscache);
}
@@ -69,7 +69,7 @@ static void cifs_fscache_enable_inode_cookie(struct inode *inode)
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) {
cifsi->fscache = fscache_acquire_cookie(tcon->fscache,
- &cifs_fscache_inode_object_def, cifsi);
+ &cifs_fscache_inode_object_def, cifsi, true);
cifs_dbg(FYI, "%s: got FH cookie (0x%p/0x%p)\n",
__func__, tcon->fscache, cifsi->fscache);
}
@@ -119,7 +119,7 @@ void cifs_fscache_reset_inode_cookie(struct inode *inode)
cifsi->fscache = fscache_acquire_cookie(
cifs_sb_master_tcon(cifs_sb)->fscache,
&cifs_fscache_inode_object_def,
- cifsi);
+ cifsi, true);
cifs_dbg(FYI, "%s: new cookie 0x%p oldcookie 0x%p\n",
__func__, cifsi->fscache, old);
}
@@ -223,6 +223,13 @@ void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
fscache_uncache_page(CIFS_I(inode)->fscache, page);
}
+void __cifs_fscache_readpages_cancel(struct inode *inode, struct list_head *pages)
+{
+ cifs_dbg(FYI, "%s: (fsc: %p, i: %p)\n",
+ __func__, CIFS_I(inode)->fscache, inode);
+ fscache_readpages_cancel(CIFS_I(inode)->fscache, pages);
+}
+
void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
{
struct cifsInodeInfo *cifsi = CIFS_I(inode);
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h
index 63539323e0b9..24794b6cd8ec 100644
--- a/fs/cifs/fscache.h
+++ b/fs/cifs/fscache.h
@@ -54,6 +54,7 @@ extern int __cifs_readpages_from_fscache(struct inode *,
struct address_space *,
struct list_head *,
unsigned *);
+extern void __cifs_fscache_readpages_cancel(struct inode *, struct list_head *);
extern void __cifs_readpage_to_fscache(struct inode *, struct page *);
@@ -91,6 +92,13 @@ static inline void cifs_readpage_to_fscache(struct inode *inode,
__cifs_readpage_to_fscache(inode, page);
}
+static inline void cifs_fscache_readpages_cancel(struct inode *inode,
+ struct list_head *pages)
+{
+ if (CIFS_I(inode)->fscache)
+ return __cifs_fscache_readpages_cancel(inode, pages);
+}
+
#else /* CONFIG_CIFS_FSCACHE */
static inline int cifs_fscache_register(void) { return 0; }
static inline void cifs_fscache_unregister(void) {}
@@ -131,6 +139,11 @@ static inline int cifs_readpages_from_fscache(struct inode *inode,
static inline void cifs_readpage_to_fscache(struct inode *inode,
struct page *page) {}
+static inline void cifs_fscache_readpages_cancel(struct inode *inode,
+ struct list_head *pages)
+{
+}
+
#endif /* CONFIG_CIFS_FSCACHE */
#endif /* _CIFS_FSCACHE_H */
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index f9ff9c173f78..867b7cdc794a 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -120,6 +120,33 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
cifs_i->invalid_mapping = true;
}
+/*
+ * copy nlink to the inode, unless it wasn't provided. Provide
+ * sane values if we don't have an existing one and none was provided
+ */
+static void
+cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
+{
+ /*
+ * if we're in a situation where we can't trust what we
+ * got from the server (readdir, some non-unix cases)
+ * fake reasonable values
+ */
+ if (fattr->cf_flags & CIFS_FATTR_UNKNOWN_NLINK) {
+ /* only provide fake values on a new inode */
+ if (inode->i_state & I_NEW) {
+ if (fattr->cf_cifsattrs & ATTR_DIRECTORY)
+ set_nlink(inode, 2);
+ else
+ set_nlink(inode, 1);
+ }
+ return;
+ }
+
+ /* we trust the server, so update it */
+ set_nlink(inode, fattr->cf_nlink);
+}
+
/* populate an inode with info from a cifs_fattr struct */
void
cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
@@ -134,7 +161,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
inode->i_mtime = fattr->cf_mtime;
inode->i_ctime = fattr->cf_ctime;
inode->i_rdev = fattr->cf_rdev;
- set_nlink(inode, fattr->cf_nlink);
+ cifs_nlink_fattr_to_inode(inode, fattr);
inode->i_uid = fattr->cf_uid;
inode->i_gid = fattr->cf_gid;
@@ -541,6 +568,7 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
fattr->cf_createtime = le64_to_cpu(info->CreationTime);
+ fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
fattr->cf_dtype = DT_DIR;
@@ -548,7 +576,8 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
* Server can return wrong NumberOfLinks value for directories
* when Unix extensions are disabled - fake it.
*/
- fattr->cf_nlink = 2;
+ if (!tcon->unix_ext)
+ fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
} else if (fattr->cf_cifsattrs & ATTR_REPARSE) {
fattr->cf_mode = S_IFLNK;
fattr->cf_dtype = DT_LNK;
@@ -561,11 +590,15 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
if (fattr->cf_cifsattrs & ATTR_READONLY)
fattr->cf_mode &= ~(S_IWUGO);
- fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
- if (fattr->cf_nlink < 1) {
- cifs_dbg(1, "replacing bogus file nlink value %u\n",
+ /*
+ * Don't accept zero nlink from non-unix servers unless
+ * delete is pending. Instead mark it as unknown.
+ */
+ if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
+ !info->DeletePending) {
+ cifs_dbg(1, "bogus file nlink value %u\n",
fattr->cf_nlink);
- fattr->cf_nlink = 1;
+ fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
}
}
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 7e36ceba0c7a..cc0234710ddb 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -621,10 +621,3 @@ symlink_exit:
free_xid(xid);
return rc;
}
-
-void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie)
-{
- char *p = nd_get_link(nd);
- if (!IS_ERR(p))
- kfree(p);
-}
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 42ef03be089f..53a75f3d0179 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -180,6 +180,9 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
fattr->cf_dtype = DT_REG;
}
+ /* non-unix readdir doesn't provide nlink */
+ fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
+
if (fattr->cf_cifsattrs & ATTR_READONLY)
fattr->cf_mode &= ~S_IWUGO;
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 5f99b7f19e78..352358de1d7e 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -32,88 +32,6 @@
#include <linux/slab.h>
#include "cifs_spnego.h"
-/*
- * Checks if this is the first smb session to be reconnected after
- * the socket has been reestablished (so we know whether to use vc 0).
- * Called while holding the cifs_tcp_ses_lock, so do not block
- */
-static bool is_first_ses_reconnect(struct cifs_ses *ses)
-{
- struct list_head *tmp;
- struct cifs_ses *tmp_ses;
-
- list_for_each(tmp, &ses->server->smb_ses_list) {
- tmp_ses = list_entry(tmp, struct cifs_ses,
- smb_ses_list);
- if (tmp_ses->need_reconnect == false)
- return false;
- }
- /* could not find a session that was already connected,
- this must be the first one we are reconnecting */
- return true;
-}
-
-/*
- * vc number 0 is treated specially by some servers, and should be the
- * first one we request. After that we can use vcnumbers up to maxvcs,
- * one for each smb session (some Windows versions set maxvcs incorrectly
- * so maxvc=1 can be ignored). If we have too many vcs, we can reuse
- * any vc but zero (some servers reset the connection on vcnum zero)
- *
- */
-static __le16 get_next_vcnum(struct cifs_ses *ses)
-{
- __u16 vcnum = 0;
- struct list_head *tmp;
- struct cifs_ses *tmp_ses;
- __u16 max_vcs = ses->server->max_vcs;
- __u16 i;
- int free_vc_found = 0;
-
- /* Quoting the MS-SMB specification: "Windows-based SMB servers set this
- field to one but do not enforce this limit, which allows an SMB client
- to establish more virtual circuits than allowed by this value ... but
- other server implementations can enforce this limit." */
- if (max_vcs < 2)
- max_vcs = 0xFFFF;
-
- spin_lock(&cifs_tcp_ses_lock);
- if ((ses->need_reconnect) && is_first_ses_reconnect(ses))
- goto get_vc_num_exit; /* vcnum will be zero */
- for (i = ses->server->srv_count - 1; i < max_vcs; i++) {
- if (i == 0) /* this is the only connection, use vc 0 */
- break;
-
- free_vc_found = 1;
-
- list_for_each(tmp, &ses->server->smb_ses_list) {
- tmp_ses = list_entry(tmp, struct cifs_ses,
- smb_ses_list);
- if (tmp_ses->vcnum == i) {
- free_vc_found = 0;
- break; /* found duplicate, try next vcnum */
- }
- }
- if (free_vc_found)
- break; /* we found a vcnumber that will work - use it */
- }
-
- if (i == 0)
- vcnum = 0; /* for most common case, ie if one smb session, use
- vc zero. Also for case when no free vcnum, zero
- is safest to send (some clients only send zero) */
- else if (free_vc_found == 0)
- vcnum = 1; /* we can not reuse vc=0 safely, since some servers
- reset all uids on that, but 1 is ok. */
- else
- vcnum = i;
- ses->vcnum = vcnum;
-get_vc_num_exit:
- spin_unlock(&cifs_tcp_ses_lock);
-
- return cpu_to_le16(vcnum);
-}
-
static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB)
{
__u32 capabilities = 0;
@@ -128,7 +46,7 @@ static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB)
CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4,
USHRT_MAX));
pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
- pSMB->req.VcNumber = get_next_vcnum(ses);
+ pSMB->req.VcNumber = __constant_cpu_to_le16(1);
/* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
diff --git a/fs/dcache.c b/fs/dcache.c
index 41000305d716..59c06e5b3c27 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1801,6 +1801,32 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
EXPORT_SYMBOL(d_instantiate_unique);
+/**
+ * d_instantiate_no_diralias - instantiate a non-aliased dentry
+ * @entry: dentry to complete
+ * @inode: inode to attach to this dentry
+ *
+ * Fill in inode information in the entry. If a directory alias is found, then
+ * return an error. Together with d_materialise_unique() this guarantees that a
+ * directory inode may never have more than one alias.
+ */
+int d_instantiate_no_diralias(struct dentry *entry, struct inode *inode)
+{
+ BUG_ON(!hlist_unhashed(&entry->d_alias));
+
+ spin_lock(&inode->i_lock);
+ if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry)) {
+ spin_unlock(&inode->i_lock);
+ return -EBUSY;
+ }
+ __d_instantiate(entry, inode);
+ spin_unlock(&inode->i_lock);
+ security_d_instantiate(entry, inode);
+
+ return 0;
+}
+EXPORT_SYMBOL(d_instantiate_no_diralias);
+
struct dentry *d_make_root(struct inode *root_inode)
{
struct dentry *res = NULL;
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 0e04142d5962..a142314710a3 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -127,6 +127,7 @@ struct dio {
spinlock_t bio_lock; /* protects BIO fields below */
int page_errors; /* errno from get_user_pages() */
int is_async; /* is IO async ? */
+ int should_dirty; /* should we mark read pages dirty? */
bool defer_completion; /* defer AIO completion to workqueue? */
int io_error; /* IO error in completion path */
unsigned long refcount; /* direct_io_worker() and bios */
@@ -403,7 +404,7 @@ static inline void dio_bio_submit(struct dio *dio, struct dio_submit *sdio)
dio->refcount++;
spin_unlock_irqrestore(&dio->bio_lock, flags);
- if (dio->is_async && dio->rw == READ)
+ if (dio->is_async && dio->rw == READ && dio->should_dirty)
bio_set_pages_dirty(bio);
if (sdio->submit_io)
@@ -474,13 +475,14 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio)
if (!uptodate)
dio->io_error = -EIO;
- if (dio->is_async && dio->rw == READ) {
+ if (dio->is_async && dio->rw == READ && dio->should_dirty) {
bio_check_pages_dirty(bio); /* transfers ownership */
} else {
bio_for_each_segment_all(bvec, bio, i) {
struct page *page = bvec->bv_page;
- if (dio->rw == READ && !PageCompound(page))
+ if (dio->rw == READ && !PageCompound(page) &&
+ dio->should_dirty)
set_page_dirty_lock(page);
page_cache_release(page);
}
@@ -1081,6 +1083,101 @@ static inline int drop_refcount(struct dio *dio)
return ret2;
}
+static ssize_t direct_IO_iovec(const struct iovec *iov, unsigned long nr_segs,
+ struct dio *dio, struct dio_submit *sdio,
+ unsigned blkbits, struct buffer_head *map_bh)
+{
+ size_t bytes;
+ ssize_t retval = 0;
+ int seg;
+ unsigned long user_addr;
+
+ for (seg = 0; seg < nr_segs; seg++) {
+ user_addr = (unsigned long)iov[seg].iov_base;
+ sdio->pages_in_io +=
+ ((user_addr + iov[seg].iov_len + PAGE_SIZE-1) /
+ PAGE_SIZE - user_addr / PAGE_SIZE);
+ }
+
+ dio->should_dirty = 1;
+
+ for (seg = 0; seg < nr_segs; seg++) {
+ user_addr = (unsigned long)iov[seg].iov_base;
+ sdio->size += bytes = iov[seg].iov_len;
+
+ /* Index into the first page of the first block */
+ sdio->first_block_in_page = (user_addr & ~PAGE_MASK) >> blkbits;
+ sdio->final_block_in_request = sdio->block_in_file +
+ (bytes >> blkbits);
+ /* Page fetching state */
+ sdio->head = 0;
+ sdio->tail = 0;
+ sdio->curr_page = 0;
+
+ sdio->total_pages = 0;
+ if (user_addr & (PAGE_SIZE-1)) {
+ sdio->total_pages++;
+ bytes -= PAGE_SIZE - (user_addr & (PAGE_SIZE - 1));
+ }
+ sdio->total_pages += (bytes + PAGE_SIZE - 1) / PAGE_SIZE;
+ sdio->curr_user_address = user_addr;
+
+ retval = do_direct_IO(dio, sdio, map_bh);
+
+ dio->result += iov[seg].iov_len -
+ ((sdio->final_block_in_request - sdio->block_in_file) <<
+ blkbits);
+
+ if (retval) {
+ dio_cleanup(dio, sdio);
+ break;
+ }
+ } /* end iovec loop */
+
+ return retval;
+}
+
+static ssize_t direct_IO_bvec(struct bio_vec *bvec, unsigned long nr_segs,
+ struct dio *dio, struct dio_submit *sdio,
+ unsigned blkbits, struct buffer_head *map_bh)
+{
+ ssize_t retval = 0;
+ int seg;
+
+ sdio->pages_in_io += nr_segs;
+
+ for (seg = 0; seg < nr_segs; seg++) {
+ sdio->size += bvec[seg].bv_len;
+
+ /* Index into the first page of the first block */
+ sdio->first_block_in_page = bvec[seg].bv_offset >> blkbits;
+ sdio->final_block_in_request = sdio->block_in_file +
+ (bvec[seg].bv_len >> blkbits);
+ /* Page fetching state */
+ sdio->curr_page = 0;
+ page_cache_get(bvec[seg].bv_page);
+ dio->pages[0] = bvec[seg].bv_page;
+ sdio->head = 0;
+ sdio->tail = 1;
+
+ sdio->total_pages = 1;
+ sdio->curr_user_address = 0;
+
+ retval = do_direct_IO(dio, sdio, map_bh);
+
+ dio->result += bvec[seg].bv_len -
+ ((sdio->final_block_in_request - sdio->block_in_file) <<
+ blkbits);
+
+ if (retval) {
+ dio_cleanup(dio, sdio);
+ break;
+ }
+ }
+
+ return retval;
+}
+
/*
* This is a library function for use by filesystem drivers.
*
@@ -1108,9 +1205,9 @@ static inline int drop_refcount(struct dio *dio)
*/
static inline ssize_t
do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
- struct block_device *bdev, const struct iovec *iov, loff_t offset,
- unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,
- dio_submit_t submit_io, int flags)
+ struct block_device *bdev, struct iov_iter *iter, loff_t offset,
+ get_block_t get_block, dio_iodone_t end_io, dio_submit_t submit_io,
+ int flags)
{
int seg;
size_t size;
@@ -1122,10 +1219,9 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
loff_t end = offset;
struct dio *dio;
struct dio_submit sdio = { 0, };
- unsigned long user_addr;
- size_t bytes;
struct buffer_head map_bh = { 0, };
struct blk_plug plug;
+ unsigned long nr_segs = iter->nr_segs;
if (rw & WRITE)
rw = WRITE_ODIRECT;
@@ -1144,20 +1240,49 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
}
/* Check the memory alignment. Blocks cannot straddle pages */
- for (seg = 0; seg < nr_segs; seg++) {
- addr = (unsigned long)iov[seg].iov_base;
- size = iov[seg].iov_len;
- end += size;
- if (unlikely((addr & blocksize_mask) ||
- (size & blocksize_mask))) {
- if (bdev)
- blkbits = blksize_bits(
- bdev_logical_block_size(bdev));
- blocksize_mask = (1 << blkbits) - 1;
- if ((addr & blocksize_mask) || (size & blocksize_mask))
- goto out;
+ if (iov_iter_has_iovec(iter)) {
+ const struct iovec *iov = iov_iter_iovec(iter);
+
+ for (seg = 0; seg < nr_segs; seg++) {
+ addr = (unsigned long)iov[seg].iov_base;
+ size = iov[seg].iov_len;
+ end += size;
+ if (unlikely((addr & blocksize_mask) ||
+ (size & blocksize_mask))) {
+ if (bdev)
+ blkbits = blksize_bits(
+ bdev_logical_block_size(bdev));
+ blocksize_mask = (1 << blkbits) - 1;
+ if ((addr & blocksize_mask) ||
+ (size & blocksize_mask))
+ goto out;
+ }
}
- }
+ } else if (iov_iter_has_bvec(iter)) {
+ /*
+ * Is this necessary, or can we trust the in-kernel
+ * caller? Can we replace this with
+ * end += iov_iter_count(iter); ?
+ */
+ struct bio_vec *bvec = iov_iter_bvec(iter);
+
+ for (seg = 0; seg < nr_segs; seg++) {
+ addr = bvec[seg].bv_offset;
+ size = bvec[seg].bv_len;
+ end += size;
+ if (unlikely((addr & blocksize_mask) ||
+ (size & blocksize_mask))) {
+ if (bdev)
+ blkbits = blksize_bits(
+ bdev_logical_block_size(bdev));
+ blocksize_mask = (1 << blkbits) - 1;
+ if ((addr & blocksize_mask) ||
+ (size & blocksize_mask))
+ goto out;
+ }
+ }
+ } else
+ BUG();
/* watch out for a 0 len io from a tricksy fs */
if (rw == READ && end == offset)
@@ -1251,47 +1376,14 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
if (unlikely(sdio.blkfactor))
sdio.pages_in_io = 2;
- for (seg = 0; seg < nr_segs; seg++) {
- user_addr = (unsigned long)iov[seg].iov_base;
- sdio.pages_in_io +=
- ((user_addr + iov[seg].iov_len + PAGE_SIZE-1) /
- PAGE_SIZE - user_addr / PAGE_SIZE);
- }
-
blk_start_plug(&plug);
- for (seg = 0; seg < nr_segs; seg++) {
- user_addr = (unsigned long)iov[seg].iov_base;
- sdio.size += bytes = iov[seg].iov_len;
-
- /* Index into the first page of the first block */
- sdio.first_block_in_page = (user_addr & ~PAGE_MASK) >> blkbits;
- sdio.final_block_in_request = sdio.block_in_file +
- (bytes >> blkbits);
- /* Page fetching state */
- sdio.head = 0;
- sdio.tail = 0;
- sdio.curr_page = 0;
-
- sdio.total_pages = 0;
- if (user_addr & (PAGE_SIZE-1)) {
- sdio.total_pages++;
- bytes -= PAGE_SIZE - (user_addr & (PAGE_SIZE - 1));
- }
- sdio.total_pages += (bytes + PAGE_SIZE - 1) / PAGE_SIZE;
- sdio.curr_user_address = user_addr;
-
- retval = do_direct_IO(dio, &sdio, &map_bh);
-
- dio->result += iov[seg].iov_len -
- ((sdio.final_block_in_request - sdio.block_in_file) <<
- blkbits);
-
- if (retval) {
- dio_cleanup(dio, &sdio);
- break;
- }
- } /* end iovec loop */
+ if (iov_iter_has_iovec(iter))
+ retval = direct_IO_iovec(iov_iter_iovec(iter), nr_segs, dio,
+ &sdio, blkbits, &map_bh);
+ else
+ retval = direct_IO_bvec(iov_iter_bvec(iter), nr_segs, dio,
+ &sdio, blkbits, &map_bh);
if (retval == -ENOTBLK) {
/*
@@ -1360,9 +1452,9 @@ out:
ssize_t
__blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
- struct block_device *bdev, const struct iovec *iov, loff_t offset,
- unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,
- dio_submit_t submit_io, int flags)
+ struct block_device *bdev, struct iov_iter *iter, loff_t offset,
+ get_block_t get_block, dio_iodone_t end_io, dio_submit_t submit_io,
+ int flags)
{
/*
* The block device state is needed in the end to finally
@@ -1376,9 +1468,8 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
prefetch(bdev->bd_queue);
prefetch((char *)bdev->bd_queue + SMP_CACHE_BYTES);
- return do_blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
- nr_segs, get_block, end_io,
- submit_io, flags);
+ return do_blockdev_direct_IO(rw, iocb, inode, bdev, iter, offset,
+ get_block, end_io, submit_io, flags);
}
EXPORT_SYMBOL(__blockdev_direct_IO);
diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c
index bf12ba5dd223..4000f6b3a750 100644
--- a/fs/ecryptfs/dentry.c
+++ b/fs/ecryptfs/dentry.c
@@ -44,15 +44,15 @@
*/
static int ecryptfs_d_revalidate(struct dentry *dentry, unsigned int flags)
{
- struct dentry *lower_dentry;
- int rc = 1;
+ struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
+ int rc;
+
+ if (!(lower_dentry->d_flags & DCACHE_OP_REVALIDATE))
+ return 1;
if (flags & LOOKUP_RCU)
return -ECHILD;
- lower_dentry = ecryptfs_dentry_to_lower(dentry);
- if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate)
- goto out;
rc = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
if (dentry->d_inode) {
struct inode *lower_inode =
@@ -60,12 +60,17 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, unsigned int flags)
fsstack_copy_attr_all(dentry->d_inode, lower_inode);
}
-out:
return rc;
}
struct kmem_cache *ecryptfs_dentry_info_cache;
+static void ecryptfs_dentry_free_rcu(struct rcu_head *head)
+{
+ kmem_cache_free(ecryptfs_dentry_info_cache,
+ container_of(head, struct ecryptfs_dentry_info, rcu));
+}
+
/**
* ecryptfs_d_release
* @dentry: The ecryptfs dentry
@@ -74,15 +79,11 @@ struct kmem_cache *ecryptfs_dentry_info_cache;
*/
static void ecryptfs_d_release(struct dentry *dentry)
{
- if (ecryptfs_dentry_to_private(dentry)) {
- if (ecryptfs_dentry_to_lower(dentry)) {
- dput(ecryptfs_dentry_to_lower(dentry));
- mntput(ecryptfs_dentry_to_lower_mnt(dentry));
- }
- kmem_cache_free(ecryptfs_dentry_info_cache,
- ecryptfs_dentry_to_private(dentry));
+ struct ecryptfs_dentry_info *p = dentry->d_fsdata;
+ if (p) {
+ path_put(&p->lower_path);
+ call_rcu(&p->rcu, ecryptfs_dentry_free_rcu);
}
- return;
}
const struct dentry_operations ecryptfs_dops = {
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index df19d34a033b..90d1882b306f 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -261,7 +261,10 @@ struct ecryptfs_inode_info {
* vfsmount too. */
struct ecryptfs_dentry_info {
struct path lower_path;
- struct ecryptfs_crypt_stat *crypt_stat;
+ union {
+ struct ecryptfs_crypt_stat *crypt_stat;
+ struct rcu_head rcu;
+ };
};
/**
@@ -512,13 +515,6 @@ ecryptfs_dentry_to_lower(struct dentry *dentry)
return ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.dentry;
}
-static inline void
-ecryptfs_set_dentry_lower(struct dentry *dentry, struct dentry *lower_dentry)
-{
- ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.dentry =
- lower_dentry;
-}
-
static inline struct vfsmount *
ecryptfs_dentry_to_lower_mnt(struct dentry *dentry)
{
@@ -531,13 +527,6 @@ ecryptfs_dentry_to_lower_path(struct dentry *dentry)
return &((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path;
}
-static inline void
-ecryptfs_set_dentry_lower_mnt(struct dentry *dentry, struct vfsmount *lower_mnt)
-{
- ((struct ecryptfs_dentry_info *)dentry->d_fsdata)->lower_path.mnt =
- lower_mnt;
-}
-
#define ecryptfs_printk(type, fmt, arg...) \
__ecryptfs_printk(type "%s: " fmt, __func__, ## arg);
__printf(1, 2)
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 992cf95830b5..3ed6e5f5bb4b 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -37,22 +37,21 @@
/**
* ecryptfs_read_update_atime
*
- * generic_file_read updates the atime of upper layer inode. But, it
+ * generic_file_read_iter updates the atime of upper layer inode. But, it
* doesn't give us a chance to update the atime of the lower layer
- * inode. This function is a wrapper to generic_file_read. It
- * updates the atime of the lower level inode if generic_file_read
+ * inode. This function is a wrapper to generic_file_read_iter. It
+ * updates the atime of the lower level inode if generic_file_read_iter
* returns without any errors. This is to be used only for file reads.
* The function to be used for directory reads is ecryptfs_read.
*/
static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
- const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
+ struct iov_iter *iter, loff_t pos)
{
ssize_t rc;
struct path *path;
struct file *file = iocb->ki_filp;
- rc = generic_file_aio_read(iocb, iov, nr_segs, pos);
+ rc = generic_file_read_iter(iocb, iter, pos);
/*
* Even though this is a async interface, we need to wait
* for IO to finish to update atime
@@ -357,9 +356,9 @@ const struct file_operations ecryptfs_dir_fops = {
const struct file_operations ecryptfs_main_fops = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .aio_read = ecryptfs_read_update_atime,
+ .read_iter = ecryptfs_read_update_atime,
.write = do_sync_write,
- .aio_write = generic_file_aio_write,
+ .write_iter = generic_file_write_iter,
.iterate = ecryptfs_readdir,
.unlocked_ioctl = ecryptfs_unlocked_ioctl,
#ifdef CONFIG_COMPAT
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 67e9b6339691..0f9b66eaa767 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -361,8 +361,8 @@ static int ecryptfs_lookup_interpose(struct dentry *dentry,
BUG_ON(!d_count(lower_dentry));
ecryptfs_set_dentry_private(dentry, dentry_info);
- ecryptfs_set_dentry_lower(dentry, lower_dentry);
- ecryptfs_set_dentry_lower_mnt(dentry, lower_mnt);
+ dentry_info->lower_path.mnt = lower_mnt;
+ dentry_info->lower_path.dentry = lower_dentry;
if (!lower_dentry->d_inode) {
/* We want to add because we couldn't find in lower */
@@ -703,16 +703,6 @@ out:
return NULL;
}
-static void
-ecryptfs_put_link(struct dentry *dentry, struct nameidata *nd, void *ptr)
-{
- char *buf = nd_get_link(nd);
- if (!IS_ERR(buf)) {
- /* Free the char* */
- kfree(buf);
- }
-}
-
/**
* upper_size_to_lower_size
* @crypt_stat: Crypt_stat associated with file
@@ -1121,7 +1111,7 @@ out:
const struct inode_operations ecryptfs_symlink_iops = {
.readlink = generic_readlink,
.follow_link = ecryptfs_follow_link,
- .put_link = ecryptfs_put_link,
+ .put_link = kfree_put_link,
.permission = ecryptfs_permission,
.setattr = ecryptfs_setattr,
.getattr = ecryptfs_getattr_link,
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index eb1c5979ecaf..1b119d3bf924 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -585,8 +585,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
/* ->kill_sb() will take care of root_info */
ecryptfs_set_dentry_private(s->s_root, root_info);
- ecryptfs_set_dentry_lower(s->s_root, path.dentry);
- ecryptfs_set_dentry_lower_mnt(s->s_root, path.mnt);
+ root_info->lower_path = path;
s->s_flags |= MS_ACTIVE;
return dget(s->s_root);
diff --git a/fs/exofs/file.c b/fs/exofs/file.c
index 491c6c078e7f..20564f8a358a 100644
--- a/fs/exofs/file.c
+++ b/fs/exofs/file.c
@@ -69,8 +69,8 @@ const struct file_operations exofs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .aio_read = generic_file_aio_read,
- .aio_write = generic_file_aio_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = generic_file_write_iter,
.mmap = generic_file_mmap,
.open = generic_file_open,
.release = exofs_release_file,
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index a5b3a5db3120..6af043bab460 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -64,8 +64,8 @@ const struct file_operations ext2_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .aio_read = generic_file_aio_read,
- .aio_write = generic_file_aio_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = generic_file_write_iter,
.unlocked_ioctl = ext2_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ext2_compat_ioctl,
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index c260de6d7b6d..cf91b336e3df 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -848,18 +848,16 @@ static sector_t ext2_bmap(struct address_space *mapping, sector_t block)
}
static ssize_t
-ext2_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
- loff_t offset, unsigned long nr_segs)
+ext2_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t offset)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
ssize_t ret;
- ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
- ext2_get_block);
+ ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, ext2_get_block);
if (ret < 0 && (rw & WRITE))
- ext2_write_failed(mapping, offset + iov_length(iov, nr_segs));
+ ext2_write_failed(mapping, offset + iov_iter_count(iter));
return ret;
}
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 25cb413277e9..a79677188b54 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -52,8 +52,8 @@ const struct file_operations ext3_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .aio_read = generic_file_aio_read,
- .aio_write = generic_file_aio_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = generic_file_write_iter,
.unlocked_ioctl = ext3_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ext3_compat_ioctl,
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 2bd85486b879..85bd13b8b758 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1862,8 +1862,7 @@ static int ext3_releasepage(struct page *page, gfp_t wait)
* VFS code falls back into buffered path in that case so we are safe.
*/
static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
- const struct iovec *iov, loff_t offset,
- unsigned long nr_segs)
+ struct iov_iter *iter, loff_t offset)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
@@ -1871,10 +1870,10 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
handle_t *handle;
ssize_t ret;
int orphan = 0;
- size_t count = iov_length(iov, nr_segs);
+ size_t count = iov_iter_count(iter);
int retries = 0;
- trace_ext3_direct_IO_enter(inode, offset, iov_length(iov, nr_segs), rw);
+ trace_ext3_direct_IO_enter(inode, offset, count, rw);
if (rw == WRITE) {
loff_t final_size = offset + count;
@@ -1898,15 +1897,14 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
}
retry:
- ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
- ext3_get_block);
+ ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, ext3_get_block);
/*
* In case of error extending write may have instantiated a few
* blocks outside i_size. Trim these off again.
*/
if (unlikely((rw & WRITE) && ret < 0)) {
loff_t isize = i_size_read(inode);
- loff_t end = offset + iov_length(iov, nr_segs);
+ loff_t end = offset + count;
if (end > isize)
ext3_truncate_failed_direct_write(inode);
@@ -1949,8 +1947,7 @@ retry:
ret = err;
}
out:
- trace_ext3_direct_IO_exit(inode, offset,
- iov_length(iov, nr_segs), rw, ret);
+ trace_ext3_direct_IO_exit(inode, offset, count, rw, ret);
return ret;
}
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index af815ea9d7cc..75af76400353 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2117,8 +2117,7 @@ extern void ext4_da_update_reserve_space(struct inode *inode,
extern int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
struct ext4_map_blocks *map, int flags);
extern ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
- const struct iovec *iov, loff_t offset,
- unsigned long nr_segs);
+ struct iov_iter *iter, loff_t offset);
extern int ext4_ind_calc_metadata_amount(struct inode *inode, sector_t lblock);
extern int ext4_ind_trans_blocks(struct inode *inode, int nrblocks);
extern void ext4_ind_truncate(handle_t *, struct inode *inode);
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 3da21945ff1f..2ab3dcb741df 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -74,12 +74,11 @@ void ext4_unwritten_wait(struct inode *inode)
* or one thread will zero the other's data, causing corruption.
*/
static int
-ext4_unaligned_aio(struct inode *inode, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
+ext4_unaligned_aio(struct inode *inode, struct iov_iter *iter, loff_t pos)
{
struct super_block *sb = inode->i_sb;
int blockmask = sb->s_blocksize - 1;
- size_t count = iov_length(iov, nr_segs);
+ size_t count = iov_iter_count(iter);
loff_t final_size = pos + count;
if (pos >= inode->i_size)
@@ -92,8 +91,8 @@ ext4_unaligned_aio(struct inode *inode, const struct iovec *iov,
}
static ssize_t
-ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
+ext4_file_dio_write(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
@@ -101,11 +100,11 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov,
int unaligned_aio = 0;
ssize_t ret;
int overwrite = 0;
- size_t length = iov_length(iov, nr_segs);
+ size_t length = iov_iter_count(iter);
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) &&
!is_sync_kiocb(iocb))
- unaligned_aio = ext4_unaligned_aio(inode, iov, nr_segs, pos);
+ unaligned_aio = ext4_unaligned_aio(inode, iter, pos);
/* Unaligned direct AIO must be serialized; see comment above */
if (unaligned_aio) {
@@ -146,7 +145,7 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov,
overwrite = 1;
}
- ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
+ ret = __generic_file_write_iter(iocb, iter, &iocb->ki_pos);
mutex_unlock(&inode->i_mutex);
if (ret > 0) {
@@ -165,8 +164,7 @@ ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov,
}
static ssize_t
-ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
+ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
{
struct inode *inode = file_inode(iocb->ki_filp);
ssize_t ret;
@@ -178,22 +176,24 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
- size_t length = iov_length(iov, nr_segs);
+ size_t length = iov_iter_count(iter);
if ((pos > sbi->s_bitmap_maxbytes ||
(pos == sbi->s_bitmap_maxbytes && length > 0)))
return -EFBIG;
if (pos + length > sbi->s_bitmap_maxbytes) {
- nr_segs = iov_shorten((struct iovec *)iov, nr_segs,
- sbi->s_bitmap_maxbytes - pos);
+ ret = iov_iter_shorten(iter,
+ sbi->s_bitmap_maxbytes - pos);
+ if (ret)
+ return ret;
}
}
if (unlikely(iocb->ki_filp->f_flags & O_DIRECT))
- ret = ext4_file_dio_write(iocb, iov, nr_segs, pos);
+ ret = ext4_file_dio_write(iocb, iter, pos);
else
- ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
+ ret = generic_file_write_iter(iocb, iter, pos);
return ret;
}
@@ -594,8 +594,8 @@ const struct file_operations ext4_file_operations = {
.llseek = ext4_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .aio_read = generic_file_aio_read,
- .aio_write = ext4_file_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = ext4_file_write_iter,
.unlocked_ioctl = ext4_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ext4_compat_ioctl,
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index 594009f5f523..8026469aa1fb 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -639,8 +639,7 @@ out:
* VFS code falls back into buffered path in that case so we are safe.
*/
ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
- const struct iovec *iov, loff_t offset,
- unsigned long nr_segs)
+ struct iov_iter *iter, loff_t offset)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
@@ -648,7 +647,7 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
handle_t *handle;
ssize_t ret;
int orphan = 0;
- size_t count = iov_length(iov, nr_segs);
+ size_t count = iov_iter_count(iter);
int retries = 0;
if (rw == WRITE) {
@@ -687,18 +686,17 @@ retry:
goto locked;
}
ret = __blockdev_direct_IO(rw, iocb, inode,
- inode->i_sb->s_bdev, iov,
- offset, nr_segs,
- ext4_get_block, NULL, NULL, 0);
+ inode->i_sb->s_bdev, iter,
+ offset, ext4_get_block, NULL, NULL, 0);
inode_dio_done(inode);
} else {
locked:
- ret = blockdev_direct_IO(rw, iocb, inode, iov,
- offset, nr_segs, ext4_get_block);
+ ret = blockdev_direct_IO(rw, iocb, inode, iter,
+ offset, ext4_get_block);
if (unlikely((rw & WRITE) && ret < 0)) {
loff_t isize = i_size_read(inode);
- loff_t end = offset + iov_length(iov, nr_segs);
+ loff_t end = offset + iov_iter_count(iter);
if (end > isize)
ext4_truncate_failed_write(inode);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 0d424d7ac02b..7d37d0079648 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3067,13 +3067,12 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
*
*/
static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
- const struct iovec *iov, loff_t offset,
- unsigned long nr_segs)
+ struct iov_iter *iter, loff_t offset)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
ssize_t ret;
- size_t count = iov_length(iov, nr_segs);
+ size_t count = iov_iter_count(iter);
int overwrite = 0;
get_block_t *get_block_func = NULL;
int dio_flags = 0;
@@ -3082,7 +3081,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
/* Use the old path for reads and writes beyond i_size. */
if (rw != WRITE || final_size > inode->i_size)
- return ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs);
+ return ext4_ind_direct_IO(rw, iocb, iter, offset);
BUG_ON(iocb->private == NULL);
@@ -3149,8 +3148,8 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
dio_flags = DIO_LOCKING;
}
ret = __blockdev_direct_IO(rw, iocb, inode,
- inode->i_sb->s_bdev, iov,
- offset, nr_segs,
+ inode->i_sb->s_bdev, iter,
+ offset,
get_block_func,
ext4_end_io_dio,
NULL,
@@ -3204,8 +3203,7 @@ retake_lock:
}
static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
- const struct iovec *iov, loff_t offset,
- unsigned long nr_segs)
+ struct iov_iter *iter, loff_t offset)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
@@ -3221,13 +3219,12 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
if (ext4_has_inline_data(inode))
return 0;
- trace_ext4_direct_IO_enter(inode, offset, iov_length(iov, nr_segs), rw);
+ trace_ext4_direct_IO_enter(inode, offset, iov_iter_count(iter), rw);
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
- ret = ext4_ext_direct_IO(rw, iocb, iov, offset, nr_segs);
+ ret = ext4_ext_direct_IO(rw, iocb, iter, offset);
else
- ret = ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs);
- trace_ext4_direct_IO_exit(inode, offset,
- iov_length(iov, nr_segs), rw, ret);
+ ret = ext4_ind_direct_IO(rw, iocb, iter, offset);
+ trace_ext4_direct_IO_exit(inode, offset, iov_iter_count(iter), rw, ret);
return ret;
}
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index bb312201ca95..ca3944240db5 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -206,6 +206,7 @@ int acquire_orphan_inode(struct f2fs_sb_info *sbi)
void release_orphan_inode(struct f2fs_sb_info *sbi)
{
mutex_lock(&sbi->orphan_inode_mutex);
+ BUG_ON(sbi->n_orphans == 0);
sbi->n_orphans--;
mutex_unlock(&sbi->orphan_inode_mutex);
}
@@ -253,6 +254,7 @@ void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
if (orphan->ino == ino) {
list_del(&orphan->list);
kmem_cache_free(orphan_entry_slab, orphan);
+ BUG_ON(sbi->n_orphans == 0);
sbi->n_orphans--;
break;
}
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 941f9b9ca3a5..2c02ec88f0e3 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -727,7 +727,7 @@ static int f2fs_write_end(struct file *file,
}
static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb,
- const struct iovec *iov, loff_t offset, unsigned long nr_segs)
+ struct iov_iter *iter, loff_t offset)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
@@ -736,7 +736,7 @@ static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb,
return 0;
/* Needs synchronization with the cleaner */
- return blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
+ return blockdev_direct_IO(rw, iocb, inode, iter, offset,
get_data_block_ro);
}
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 608f0df5b919..7fd99d8bd2ff 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -544,15 +544,15 @@ static inline void mutex_unlock_all(struct f2fs_sb_info *sbi)
static inline int mutex_lock_op(struct f2fs_sb_info *sbi)
{
- unsigned char next_lock = sbi->next_lock_num % NR_GLOBAL_LOCKS;
+ unsigned char next_lock;
int i = 0;
for (; i < NR_GLOBAL_LOCKS; i++)
if (mutex_trylock(&sbi->fs_lock[i]))
return i;
+ next_lock = sbi->next_lock_num++ % NR_GLOBAL_LOCKS;
mutex_lock(&sbi->fs_lock[next_lock]);
- sbi->next_lock_num++;
return next_lock;
}
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 02c906971cc6..31c2973760c0 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -685,8 +685,8 @@ const struct file_operations f2fs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .aio_read = generic_file_aio_read,
- .aio_write = generic_file_aio_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = generic_file_write_iter,
.open = generic_file_open,
.mmap = f2fs_file_mmap,
.fsync = f2fs_sync_file,
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 2f157e883687..fbad96846c7c 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -236,8 +236,8 @@ static unsigned int get_cb_cost(struct f2fs_sb_info *sbi, unsigned int segno)
return UINT_MAX - ((100 * (100 - u) * age) / (100 + u));
}
-static unsigned int get_gc_cost(struct f2fs_sb_info *sbi, unsigned int segno,
- struct victim_sel_policy *p)
+static inline unsigned int get_gc_cost(struct f2fs_sb_info *sbi,
+ unsigned int segno, struct victim_sel_policy *p)
{
if (p->alloc_mode == SSR)
return get_seg_entry(sbi, segno)->ckpt_valid_blocks;
@@ -293,7 +293,11 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
}
break;
}
- p.offset = ((segno / p.ofs_unit) * p.ofs_unit) + p.ofs_unit;
+
+ p.offset = segno + p.ofs_unit;
+ if (p.ofs_unit > 1)
+ p.offset -= segno % p.ofs_unit;
+
secno = GET_SECNO(sbi, segno);
if (sec_usage_check(sbi, secno))
@@ -306,10 +310,9 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
if (p.min_cost > cost) {
p.min_segno = segno;
p.min_cost = cost;
- }
-
- if (cost == max_cost)
+ } else if (unlikely(cost == max_cost)) {
continue;
+ }
if (nsearched++ >= p.max_search) {
sbi->last_victim[p.gc_mode] = segno;
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index 51ef5eec33d7..a15d122fdc50 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -64,24 +64,31 @@ static int recover_dentry(struct page *ipage, struct inode *inode)
name.name = raw_inode->i_name;
retry:
de = f2fs_find_entry(dir, &name, &page);
- if (de && inode->i_ino == le32_to_cpu(de->ino)) {
- kunmap(page);
- f2fs_put_page(page, 0);
- goto out;
- }
+ if (de && inode->i_ino == le32_to_cpu(de->ino))
+ goto out_unmap_put;
if (de) {
einode = f2fs_iget(inode->i_sb, le32_to_cpu(de->ino));
if (IS_ERR(einode)) {
WARN_ON(1);
if (PTR_ERR(einode) == -ENOENT)
err = -EEXIST;
- goto out;
+ goto out_unmap_put;
+ }
+ err = acquire_orphan_inode(F2FS_SB(inode->i_sb));
+ if (err) {
+ iput(einode);
+ goto out_unmap_put;
}
f2fs_delete_entry(de, page, einode);
iput(einode);
goto retry;
}
err = __f2fs_add_link(dir, &name, inode);
+ goto out;
+
+out_unmap_put:
+ kunmap(page);
+ f2fs_put_page(page, 0);
out:
f2fs_msg(inode->i_sb, KERN_NOTICE, "recover_inode and its dentry: "
"ino = %x, name = %s, dir = %lx, err = %d",
@@ -419,6 +426,7 @@ int recover_fsync_data(struct f2fs_sb_info *sbi)
{
struct list_head inode_list;
int err;
+ int need_writecp = 0;
fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry",
sizeof(struct fsync_inode_entry), NULL);
@@ -436,6 +444,8 @@ int recover_fsync_data(struct f2fs_sb_info *sbi)
if (list_empty(&inode_list))
goto out;
+ need_writecp = 1;
+
/* step #2: recover data */
err = recover_data(sbi, &inode_list, CURSEG_WARM_NODE);
BUG_ON(!list_empty(&inode_list));
@@ -443,7 +453,7 @@ out:
destroy_fsync_dnodes(&inode_list);
kmem_cache_destroy(fsync_entry_slab);
sbi->por_doing = 0;
- if (!err)
+ if (!err && need_writecp)
write_checkpoint(sbi, false);
return err;
}
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 09af9c7b0f52..bd79bbeceb1d 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -657,6 +657,7 @@ static void submit_write_page(struct f2fs_sb_info *sbi, struct page *page,
block_t blk_addr, enum page_type type)
{
struct block_device *bdev = sbi->sb->s_bdev;
+ int bio_blocks;
verify_block_addr(sbi, blk_addr);
@@ -676,7 +677,8 @@ retry:
goto retry;
}
- sbi->bio[type] = f2fs_bio_alloc(bdev, max_hw_blocks(sbi));
+ bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi));
+ sbi->bio[type] = f2fs_bio_alloc(bdev, bio_blocks);
sbi->bio[type]->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr);
sbi->bio[type]->bi_private = priv;
/*
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index bdd10eab8c40..7f94d78cda3d 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -90,6 +90,8 @@
(blk_addr << ((sbi)->log_blocksize - F2FS_LOG_SECTOR_SIZE))
#define SECTOR_TO_BLOCK(sbi, sectors) \
(sectors >> ((sbi)->log_blocksize - F2FS_LOG_SECTOR_SIZE))
+#define MAX_BIO_BLOCKS(max_hw_blocks) \
+ (min((int)max_hw_blocks, BIO_MAX_PAGES))
/* during checkpoint, bio_private is used to synchronize the last bio */
struct bio_private {
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 13d0a0fe49dd..094ccc6762cf 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -43,7 +43,9 @@ enum {
Opt_disable_roll_forward,
Opt_discard,
Opt_noheap,
+ Opt_user_xattr,
Opt_nouser_xattr,
+ Opt_acl,
Opt_noacl,
Opt_active_logs,
Opt_disable_ext_identify,
@@ -56,7 +58,9 @@ static match_table_t f2fs_tokens = {
{Opt_disable_roll_forward, "disable_roll_forward"},
{Opt_discard, "discard"},
{Opt_noheap, "no_heap"},
+ {Opt_user_xattr, "user_xattr"},
{Opt_nouser_xattr, "nouser_xattr"},
+ {Opt_acl, "acl"},
{Opt_noacl, "noacl"},
{Opt_active_logs, "active_logs=%u"},
{Opt_disable_ext_identify, "disable_ext_identify"},
@@ -237,6 +241,9 @@ static int parse_options(struct super_block *sb, char *options)
set_opt(sbi, NOHEAP);
break;
#ifdef CONFIG_F2FS_FS_XATTR
+ case Opt_user_xattr:
+ set_opt(sbi, XATTR_USER);
+ break;
case Opt_nouser_xattr:
clear_opt(sbi, XATTR_USER);
break;
@@ -244,6 +251,10 @@ static int parse_options(struct super_block *sb, char *options)
set_opt(sbi, INLINE_XATTR);
break;
#else
+ case Opt_user_xattr:
+ f2fs_msg(sb, KERN_INFO,
+ "user_xattr options not supported");
+ break;
case Opt_nouser_xattr:
f2fs_msg(sb, KERN_INFO,
"nouser_xattr options not supported");
@@ -254,10 +265,16 @@ static int parse_options(struct super_block *sb, char *options)
break;
#endif
#ifdef CONFIG_F2FS_FS_POSIX_ACL
+ case Opt_acl:
+ set_opt(sbi, POSIX_ACL);
+ break;
case Opt_noacl:
clear_opt(sbi, POSIX_ACL);
break;
#else
+ case Opt_acl:
+ f2fs_msg(sb, KERN_INFO, "acl options not supported");
+ break;
case Opt_noacl:
f2fs_msg(sb, KERN_INFO, "noacl options not supported");
break;
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index 1ac8a5f6e380..3d900ea34e47 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -154,6 +154,9 @@ static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name,
}
#ifdef CONFIG_F2FS_FS_SECURITY
+static int __f2fs_setxattr(struct inode *inode, int name_index,
+ const char *name, const void *value, size_t value_len,
+ struct page *ipage);
static int f2fs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
void *page)
{
@@ -161,7 +164,7 @@ static int f2fs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
int err = 0;
for (xattr = xattr_array; xattr->name != NULL; xattr++) {
- err = f2fs_setxattr(inode, F2FS_XATTR_INDEX_SECURITY,
+ err = __f2fs_setxattr(inode, F2FS_XATTR_INDEX_SECURITY,
xattr->name, xattr->value,
xattr->value_len, (struct page *)page);
if (err < 0)
@@ -469,16 +472,15 @@ cleanup:
return error;
}
-int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
- const void *value, size_t value_len, struct page *ipage)
+static int __f2fs_setxattr(struct inode *inode, int name_index,
+ const char *name, const void *value, size_t value_len,
+ struct page *ipage)
{
- struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
struct f2fs_inode_info *fi = F2FS_I(inode);
struct f2fs_xattr_entry *here, *last;
void *base_addr;
int found, newsize;
size_t name_len;
- int ilock;
__u32 new_hsize;
int error = -ENOMEM;
@@ -493,10 +495,6 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
if (name_len > F2FS_NAME_LEN || value_len > MAX_VALUE_LEN(inode))
return -ERANGE;
- f2fs_balance_fs(sbi);
-
- ilock = mutex_lock_op(sbi);
-
base_addr = read_all_xattrs(inode, ipage);
if (!base_addr)
goto exit;
@@ -578,7 +576,24 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
else
update_inode_page(inode);
exit:
- mutex_unlock_op(sbi, ilock);
kzfree(base_addr);
return error;
}
+
+int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
+ const void *value, size_t value_len, struct page *ipage)
+{
+ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+ int ilock;
+ int err;
+
+ f2fs_balance_fs(sbi);
+
+ ilock = mutex_lock_op(sbi);
+
+ err = __f2fs_setxattr(inode, name_index, name, value, value_len, ipage);
+
+ mutex_unlock_op(sbi, ilock);
+
+ return err;
+}
diff --git a/fs/fat/file.c b/fs/fat/file.c
index b759c57ceb18..a3abc56cd20b 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -175,8 +175,8 @@ const struct file_operations fat_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .aio_read = generic_file_aio_read,
- .aio_write = generic_file_aio_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = generic_file_write_iter,
.mmap = generic_file_mmap,
.release = fat_file_release,
.unlocked_ioctl = fat_generic_ioctl,
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index e5e553d8f384..b248abb13552 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -236,8 +236,7 @@ static int fat_write_end(struct file *file, struct address_space *mapping,
}
static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
- const struct iovec *iov,
- loff_t offset, unsigned long nr_segs)
+ struct iov_iter *iter, loff_t offset)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
@@ -254,7 +253,7 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
*
* Return 0, and fallback to normal buffered write.
*/
- loff_t size = offset + iov_length(iov, nr_segs);
+ loff_t size = offset + iov_iter_count(iter);
if (MSDOS_I(inode)->mmu_private < size)
return 0;
/*
@@ -271,10 +270,9 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
* FAT need to use the DIO_LOCKING for avoiding the race
* condition of fat_get_block() and ->truncate().
*/
- ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
- fat_get_block);
+ ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, fat_get_block);
if (ret < 0 && (rw & WRITE))
- fat_write_failed(mapping, offset + iov_length(iov, nr_segs));
+ fat_write_failed(mapping, offset + iov_iter_count(iter));
return ret;
}
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c
index b2a86e324aac..29d7feb62cf7 100644
--- a/fs/fscache/cookie.c
+++ b/fs/fscache/cookie.c
@@ -58,15 +58,16 @@ void fscache_cookie_init_once(void *_cookie)
struct fscache_cookie *__fscache_acquire_cookie(
struct fscache_cookie *parent,
const struct fscache_cookie_def *def,
- void *netfs_data)
+ void *netfs_data,
+ bool enable)
{
struct fscache_cookie *cookie;
BUG_ON(!def);
- _enter("{%s},{%s},%p",
+ _enter("{%s},{%s},%p,%u",
parent ? (char *) parent->def->name : "<no-parent>",
- def->name, netfs_data);
+ def->name, netfs_data, enable);
fscache_stat(&fscache_n_acquires);
@@ -106,7 +107,7 @@ struct fscache_cookie *__fscache_acquire_cookie(
cookie->def = def;
cookie->parent = parent;
cookie->netfs_data = netfs_data;
- cookie->flags = 0;
+ cookie->flags = (1 << FSCACHE_COOKIE_NO_DATA_YET);
/* radix tree insertion won't use the preallocation pool unless it's
* told it may not wait */
@@ -124,16 +125,22 @@ struct fscache_cookie *__fscache_acquire_cookie(
break;
}
- /* if the object is an index then we need do nothing more here - we
- * create indices on disk when we need them as an index may exist in
- * multiple caches */
- if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) {
- if (fscache_acquire_non_index_cookie(cookie) < 0) {
- atomic_dec(&parent->n_children);
- __fscache_cookie_put(cookie);
- fscache_stat(&fscache_n_acquires_nobufs);
- _leave(" = NULL");
- return NULL;
+ if (enable) {
+ /* if the object is an index then we need do nothing more here
+ * - we create indices on disk when we need them as an index
+ * may exist in multiple caches */
+ if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) {
+ if (fscache_acquire_non_index_cookie(cookie) == 0) {
+ set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
+ } else {
+ atomic_dec(&parent->n_children);
+ __fscache_cookie_put(cookie);
+ fscache_stat(&fscache_n_acquires_nobufs);
+ _leave(" = NULL");
+ return NULL;
+ }
+ } else {
+ set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
}
}
@@ -144,6 +151,39 @@ struct fscache_cookie *__fscache_acquire_cookie(
EXPORT_SYMBOL(__fscache_acquire_cookie);
/*
+ * Enable a cookie to permit it to accept new operations.
+ */
+void __fscache_enable_cookie(struct fscache_cookie *cookie,
+ bool (*can_enable)(void *data),
+ void *data)
+{
+ _enter("%p", cookie);
+
+ wait_on_bit_lock(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK,
+ fscache_wait_bit, TASK_UNINTERRUPTIBLE);
+
+ if (test_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags))
+ goto out_unlock;
+
+ if (can_enable && !can_enable(data)) {
+ /* The netfs decided it didn't want to enable after all */
+ } else if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) {
+ /* Wait for outstanding disablement to complete */
+ __fscache_wait_on_invalidate(cookie);
+
+ if (fscache_acquire_non_index_cookie(cookie) == 0)
+ set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
+ } else {
+ set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
+ }
+
+out_unlock:
+ clear_bit_unlock(FSCACHE_COOKIE_ENABLEMENT_LOCK, &cookie->flags);
+ wake_up_bit(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK);
+}
+EXPORT_SYMBOL(__fscache_enable_cookie);
+
+/*
* acquire a non-index cookie
* - this must make sure the index chain is instantiated and instantiate the
* object representation too
@@ -157,7 +197,7 @@ static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie)
_enter("");
- cookie->flags = 1 << FSCACHE_COOKIE_UNAVAILABLE;
+ set_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
/* now we need to see whether the backing objects for this cookie yet
* exist, if not there'll be nothing to search */
@@ -180,9 +220,7 @@ static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie)
_debug("cache %s", cache->tag->name);
- cookie->flags =
- (1 << FSCACHE_COOKIE_LOOKING_UP) |
- (1 << FSCACHE_COOKIE_NO_DATA_YET);
+ set_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags);
/* ask the cache to allocate objects for this cookie and its parent
* chain */
@@ -398,7 +436,8 @@ void __fscache_invalidate(struct fscache_cookie *cookie)
if (!hlist_empty(&cookie->backing_objects)) {
spin_lock(&cookie->lock);
- if (!hlist_empty(&cookie->backing_objects) &&
+ if (fscache_cookie_enabled(cookie) &&
+ !hlist_empty(&cookie->backing_objects) &&
!test_and_set_bit(FSCACHE_COOKIE_INVALIDATING,
&cookie->flags)) {
object = hlist_entry(cookie->backing_objects.first,
@@ -452,10 +491,14 @@ void __fscache_update_cookie(struct fscache_cookie *cookie)
spin_lock(&cookie->lock);
- /* update the index entry on disk in each cache backing this cookie */
- hlist_for_each_entry(object,
- &cookie->backing_objects, cookie_link) {
- fscache_raise_event(object, FSCACHE_OBJECT_EV_UPDATE);
+ if (fscache_cookie_enabled(cookie)) {
+ /* update the index entry on disk in each cache backing this
+ * cookie.
+ */
+ hlist_for_each_entry(object,
+ &cookie->backing_objects, cookie_link) {
+ fscache_raise_event(object, FSCACHE_OBJECT_EV_UPDATE);
+ }
}
spin_unlock(&cookie->lock);
@@ -464,28 +507,14 @@ void __fscache_update_cookie(struct fscache_cookie *cookie)
EXPORT_SYMBOL(__fscache_update_cookie);
/*
- * release a cookie back to the cache
- * - the object will be marked as recyclable on disk if retire is true
- * - all dependents of this cookie must have already been unregistered
- * (indices/files/pages)
+ * Disable a cookie to stop it from accepting new requests from the netfs.
*/
-void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
+void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
{
struct fscache_object *object;
+ bool awaken = false;
- fscache_stat(&fscache_n_relinquishes);
- if (retire)
- fscache_stat(&fscache_n_relinquishes_retire);
-
- if (!cookie) {
- fscache_stat(&fscache_n_relinquishes_null);
- _leave(" [no cookie]");
- return;
- }
-
- _enter("%p{%s,%p,%d},%d",
- cookie, cookie->def->name, cookie->netfs_data,
- atomic_read(&cookie->n_active), retire);
+ _enter("%p,%u", cookie, invalidate);
ASSERTCMP(atomic_read(&cookie->n_active), >, 0);
@@ -495,24 +524,82 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
BUG();
}
- /* No further netfs-accessing operations on this cookie permitted */
- set_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags);
- if (retire)
- set_bit(FSCACHE_COOKIE_RETIRED, &cookie->flags);
+ wait_on_bit_lock(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK,
+ fscache_wait_bit, TASK_UNINTERRUPTIBLE);
+ if (!test_and_clear_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags))
+ goto out_unlock_enable;
+
+ /* If the cookie is being invalidated, wait for that to complete first
+ * so that we can reuse the flag.
+ */
+ __fscache_wait_on_invalidate(cookie);
+
+ /* Dispose of the backing objects */
+ set_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags);
spin_lock(&cookie->lock);
- hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) {
- fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
+ if (!hlist_empty(&cookie->backing_objects)) {
+ hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) {
+ if (invalidate)
+ set_bit(FSCACHE_OBJECT_RETIRED, &object->flags);
+ fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
+ }
+ } else {
+ if (test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags))
+ awaken = true;
}
spin_unlock(&cookie->lock);
+ if (awaken)
+ wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
/* Wait for cessation of activity requiring access to the netfs (when
- * n_active reaches 0).
+ * n_active reaches 0). This makes sure outstanding reads and writes
+ * have completed.
*/
if (!atomic_dec_and_test(&cookie->n_active))
wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t,
TASK_UNINTERRUPTIBLE);
+ /* Reset the cookie state if it wasn't relinquished */
+ if (!test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) {
+ atomic_inc(&cookie->n_active);
+ set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
+ }
+
+out_unlock_enable:
+ clear_bit_unlock(FSCACHE_COOKIE_ENABLEMENT_LOCK, &cookie->flags);
+ wake_up_bit(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK);
+ _leave("");
+}
+EXPORT_SYMBOL(__fscache_disable_cookie);
+
+/*
+ * release a cookie back to the cache
+ * - the object will be marked as recyclable on disk if retire is true
+ * - all dependents of this cookie must have already been unregistered
+ * (indices/files/pages)
+ */
+void __fscache_relinquish_cookie(struct fscache_cookie *cookie, bool retire)
+{
+ fscache_stat(&fscache_n_relinquishes);
+ if (retire)
+ fscache_stat(&fscache_n_relinquishes_retire);
+
+ if (!cookie) {
+ fscache_stat(&fscache_n_relinquishes_null);
+ _leave(" [no cookie]");
+ return;
+ }
+
+ _enter("%p{%s,%p,%d},%d",
+ cookie, cookie->def->name, cookie->netfs_data,
+ atomic_read(&cookie->n_active), retire);
+
+ /* No further netfs-accessing operations on this cookie permitted */
+ set_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags);
+
+ __fscache_disable_cookie(cookie, retire);
+
/* Clear pointers back to the netfs */
cookie->netfs_data = NULL;
cookie->def = NULL;
@@ -568,6 +655,7 @@ int __fscache_check_consistency(struct fscache_cookie *cookie)
{
struct fscache_operation *op;
struct fscache_object *object;
+ bool wake_cookie = false;
int ret;
_enter("%p,", cookie);
@@ -591,7 +679,8 @@ int __fscache_check_consistency(struct fscache_cookie *cookie)
spin_lock(&cookie->lock);
- if (hlist_empty(&cookie->backing_objects))
+ if (!fscache_cookie_enabled(cookie) ||
+ hlist_empty(&cookie->backing_objects))
goto inconsistent;
object = hlist_entry(cookie->backing_objects.first,
struct fscache_object, cookie_link);
@@ -600,7 +689,7 @@ int __fscache_check_consistency(struct fscache_cookie *cookie)
op->debug_id = atomic_inc_return(&fscache_op_debug_id);
- atomic_inc(&cookie->n_active);
+ __fscache_use_cookie(cookie);
if (fscache_submit_op(object, op) < 0)
goto submit_failed;
@@ -622,9 +711,11 @@ int __fscache_check_consistency(struct fscache_cookie *cookie)
return ret;
submit_failed:
- atomic_dec(&cookie->n_active);
+ wake_cookie = __fscache_unuse_cookie(cookie);
inconsistent:
spin_unlock(&cookie->lock);
+ if (wake_cookie)
+ __fscache_wake_unused_cookie(cookie);
kfree(op);
_leave(" = -ESTALE");
return -ESTALE;
diff --git a/fs/fscache/fsdef.c b/fs/fscache/fsdef.c
index 10a2ade0bdf8..5a117df2a9ef 100644
--- a/fs/fscache/fsdef.c
+++ b/fs/fscache/fsdef.c
@@ -59,6 +59,7 @@ struct fscache_cookie fscache_fsdef_index = {
.lock = __SPIN_LOCK_UNLOCKED(fscache_fsdef_index.lock),
.backing_objects = HLIST_HEAD_INIT,
.def = &fscache_fsdef_index_def,
+ .flags = 1 << FSCACHE_COOKIE_ENABLED,
};
EXPORT_SYMBOL(fscache_fsdef_index);
diff --git a/fs/fscache/netfs.c b/fs/fscache/netfs.c
index b1bb6117473a..989f39401547 100644
--- a/fs/fscache/netfs.c
+++ b/fs/fscache/netfs.c
@@ -45,6 +45,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
netfs->primary_index->def = &fscache_fsdef_netfs_def;
netfs->primary_index->parent = &fscache_fsdef_index;
netfs->primary_index->netfs_data = netfs;
+ netfs->primary_index->flags = 1 << FSCACHE_COOKIE_ENABLED;
atomic_inc(&netfs->primary_index->parent->usage);
atomic_inc(&netfs->primary_index->parent->n_children);
diff --git a/fs/fscache/object.c b/fs/fscache/object.c
index 86d75a60b20c..dcb821617774 100644
--- a/fs/fscache/object.c
+++ b/fs/fscache/object.c
@@ -495,6 +495,7 @@ void fscache_object_lookup_negative(struct fscache_object *object)
* returning ENODATA.
*/
set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
+ clear_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
_debug("wake up lookup %p", &cookie->flags);
clear_bit_unlock(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags);
@@ -527,6 +528,7 @@ void fscache_obtained_object(struct fscache_object *object)
/* We do (presumably) have data */
clear_bit_unlock(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
+ clear_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
/* Allow write requests to begin stacking up and read requests
* to begin shovelling data.
@@ -679,7 +681,8 @@ static const struct fscache_state *fscache_drop_object(struct fscache_object *ob
*/
spin_lock(&cookie->lock);
hlist_del_init(&object->cookie_link);
- if (test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags))
+ if (hlist_empty(&cookie->backing_objects) &&
+ test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags))
awaken = true;
spin_unlock(&cookie->lock);
@@ -927,7 +930,7 @@ static const struct fscache_state *_fscache_invalidate_object(struct fscache_obj
*/
if (!fscache_use_cookie(object)) {
ASSERT(object->cookie->stores.rnode == NULL);
- set_bit(FSCACHE_COOKIE_RETIRED, &cookie->flags);
+ set_bit(FSCACHE_OBJECT_RETIRED, &object->flags);
_leave(" [no cookie]");
return transit_to(KILL_OBJECT);
}
diff --git a/fs/fscache/page.c b/fs/fscache/page.c
index 73899c1c3449..7f5c658af755 100644
--- a/fs/fscache/page.c
+++ b/fs/fscache/page.c
@@ -163,12 +163,10 @@ static void fscache_attr_changed_op(struct fscache_operation *op)
fscache_stat(&fscache_n_attr_changed_calls);
- if (fscache_object_is_active(object) &&
- fscache_use_cookie(object)) {
+ if (fscache_object_is_active(object)) {
fscache_stat(&fscache_n_cop_attr_changed);
ret = object->cache->ops->attr_changed(object);
fscache_stat_d(&fscache_n_cop_attr_changed);
- fscache_unuse_cookie(object);
if (ret < 0)
fscache_abort_object(object);
}
@@ -184,6 +182,7 @@ int __fscache_attr_changed(struct fscache_cookie *cookie)
{
struct fscache_operation *op;
struct fscache_object *object;
+ bool wake_cookie;
_enter("%p", cookie);
@@ -199,15 +198,19 @@ int __fscache_attr_changed(struct fscache_cookie *cookie)
}
fscache_operation_init(op, fscache_attr_changed_op, NULL);
- op->flags = FSCACHE_OP_ASYNC | (1 << FSCACHE_OP_EXCLUSIVE);
+ op->flags = FSCACHE_OP_ASYNC |
+ (1 << FSCACHE_OP_EXCLUSIVE) |
+ (1 << FSCACHE_OP_UNUSE_COOKIE);
spin_lock(&cookie->lock);
- if (hlist_empty(&cookie->backing_objects))
+ if (!fscache_cookie_enabled(cookie) ||
+ hlist_empty(&cookie->backing_objects))
goto nobufs;
object = hlist_entry(cookie->backing_objects.first,
struct fscache_object, cookie_link);
+ __fscache_use_cookie(cookie);
if (fscache_submit_exclusive_op(object, op) < 0)
goto nobufs;
spin_unlock(&cookie->lock);
@@ -217,8 +220,11 @@ int __fscache_attr_changed(struct fscache_cookie *cookie)
return 0;
nobufs:
+ wake_cookie = __fscache_unuse_cookie(cookie);
spin_unlock(&cookie->lock);
kfree(op);
+ if (wake_cookie)
+ __fscache_wake_unused_cookie(cookie);
fscache_stat(&fscache_n_attr_changed_nobufs);
_leave(" = %d", -ENOBUFS);
return -ENOBUFS;
@@ -263,7 +269,6 @@ static struct fscache_retrieval *fscache_alloc_retrieval(
}
fscache_operation_init(&op->op, NULL, fscache_release_retrieval_op);
- atomic_inc(&cookie->n_active);
op->op.flags = FSCACHE_OP_MYTHREAD |
(1UL << FSCACHE_OP_WAITING) |
(1UL << FSCACHE_OP_UNUSE_COOKIE);
@@ -384,6 +389,7 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
{
struct fscache_retrieval *op;
struct fscache_object *object;
+ bool wake_cookie = false;
int ret;
_enter("%p,%p,,,", cookie, page);
@@ -405,7 +411,7 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
return -ERESTARTSYS;
op = fscache_alloc_retrieval(cookie, page->mapping,
- end_io_func,context);
+ end_io_func, context);
if (!op) {
_leave(" = -ENOMEM");
return -ENOMEM;
@@ -414,13 +420,15 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
spin_lock(&cookie->lock);
- if (hlist_empty(&cookie->backing_objects))
+ if (!fscache_cookie_enabled(cookie) ||
+ hlist_empty(&cookie->backing_objects))
goto nobufs_unlock;
object = hlist_entry(cookie->backing_objects.first,
struct fscache_object, cookie_link);
ASSERT(test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags));
+ __fscache_use_cookie(cookie);
atomic_inc(&object->n_reads);
__set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags);
@@ -475,9 +483,11 @@ error:
nobufs_unlock_dec:
atomic_dec(&object->n_reads);
+ wake_cookie = __fscache_unuse_cookie(cookie);
nobufs_unlock:
spin_unlock(&cookie->lock);
- atomic_dec(&cookie->n_active);
+ if (wake_cookie)
+ __fscache_wake_unused_cookie(cookie);
kfree(op);
nobufs:
fscache_stat(&fscache_n_retrievals_nobufs);
@@ -514,6 +524,7 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
{
struct fscache_retrieval *op;
struct fscache_object *object;
+ bool wake_cookie = false;
int ret;
_enter("%p,,%d,,,", cookie, *nr_pages);
@@ -542,11 +553,13 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
spin_lock(&cookie->lock);
- if (hlist_empty(&cookie->backing_objects))
+ if (!fscache_cookie_enabled(cookie) ||
+ hlist_empty(&cookie->backing_objects))
goto nobufs_unlock;
object = hlist_entry(cookie->backing_objects.first,
struct fscache_object, cookie_link);
+ __fscache_use_cookie(cookie);
atomic_inc(&object->n_reads);
__set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags);
@@ -601,10 +614,12 @@ error:
nobufs_unlock_dec:
atomic_dec(&object->n_reads);
+ wake_cookie = __fscache_unuse_cookie(cookie);
nobufs_unlock:
spin_unlock(&cookie->lock);
- atomic_dec(&cookie->n_active);
kfree(op);
+ if (wake_cookie)
+ __fscache_wake_unused_cookie(cookie);
nobufs:
fscache_stat(&fscache_n_retrievals_nobufs);
_leave(" = -ENOBUFS");
@@ -626,6 +641,7 @@ int __fscache_alloc_page(struct fscache_cookie *cookie,
{
struct fscache_retrieval *op;
struct fscache_object *object;
+ bool wake_cookie = false;
int ret;
_enter("%p,%p,,,", cookie, page);
@@ -653,13 +669,15 @@ int __fscache_alloc_page(struct fscache_cookie *cookie,
spin_lock(&cookie->lock);
- if (hlist_empty(&cookie->backing_objects))
+ if (!fscache_cookie_enabled(cookie) ||
+ hlist_empty(&cookie->backing_objects))
goto nobufs_unlock;
object = hlist_entry(cookie->backing_objects.first,
struct fscache_object, cookie_link);
+ __fscache_use_cookie(cookie);
if (fscache_submit_op(object, &op->op) < 0)
- goto nobufs_unlock;
+ goto nobufs_unlock_dec;
spin_unlock(&cookie->lock);
fscache_stat(&fscache_n_alloc_ops);
@@ -689,10 +707,13 @@ error:
_leave(" = %d", ret);
return ret;
+nobufs_unlock_dec:
+ wake_cookie = __fscache_unuse_cookie(cookie);
nobufs_unlock:
spin_unlock(&cookie->lock);
- atomic_dec(&cookie->n_active);
kfree(op);
+ if (wake_cookie)
+ __fscache_wake_unused_cookie(cookie);
nobufs:
fscache_stat(&fscache_n_allocs_nobufs);
_leave(" = -ENOBUFS");
@@ -889,6 +910,7 @@ int __fscache_write_page(struct fscache_cookie *cookie,
{
struct fscache_storage *op;
struct fscache_object *object;
+ bool wake_cookie = false;
int ret;
_enter("%p,%x,", cookie, (u32) page->flags);
@@ -920,7 +942,8 @@ int __fscache_write_page(struct fscache_cookie *cookie,
ret = -ENOBUFS;
spin_lock(&cookie->lock);
- if (hlist_empty(&cookie->backing_objects))
+ if (!fscache_cookie_enabled(cookie) ||
+ hlist_empty(&cookie->backing_objects))
goto nobufs;
object = hlist_entry(cookie->backing_objects.first,
struct fscache_object, cookie_link);
@@ -957,7 +980,7 @@ int __fscache_write_page(struct fscache_cookie *cookie,
op->op.debug_id = atomic_inc_return(&fscache_op_debug_id);
op->store_limit = object->store_limit;
- atomic_inc(&cookie->n_active);
+ __fscache_use_cookie(cookie);
if (fscache_submit_op(object, &op->op) < 0)
goto submit_failed;
@@ -984,10 +1007,10 @@ already_pending:
return 0;
submit_failed:
- atomic_dec(&cookie->n_active);
spin_lock(&cookie->stores_lock);
radix_tree_delete(&cookie->stores, page->index);
spin_unlock(&cookie->stores_lock);
+ wake_cookie = __fscache_unuse_cookie(cookie);
page_cache_release(page);
ret = -ENOBUFS;
goto nobufs;
@@ -999,6 +1022,8 @@ nobufs:
spin_unlock(&cookie->lock);
radix_tree_preload_end();
kfree(op);
+ if (wake_cookie)
+ __fscache_wake_unused_cookie(cookie);
fscache_stat(&fscache_n_stores_nobufs);
_leave(" = -ENOBUFS");
return -ENOBUFS;
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index adbfd66b380f..242fe3eb1ae8 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -94,8 +94,11 @@ static ssize_t cuse_read(struct file *file, char __user *buf, size_t count,
loff_t pos = 0;
struct iovec iov = { .iov_base = buf, .iov_len = count };
struct fuse_io_priv io = { .async = 0, .file = file };
+ struct iov_iter ii;
- return fuse_direct_io(&io, &iov, 1, count, &pos, 0);
+ iov_iter_init(&ii, &iov, 1, count, 0);
+
+ return fuse_direct_io(&io, &ii, count, &pos, 0);
}
static ssize_t cuse_write(struct file *file, const char __user *buf,
@@ -104,12 +107,15 @@ static ssize_t cuse_write(struct file *file, const char __user *buf,
loff_t pos = 0;
struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count };
struct fuse_io_priv io = { .async = 0, .file = file };
+ struct iov_iter ii;
+
+ iov_iter_init(&ii, &iov, 1, count, 0);
/*
* No locking or generic_write_checks(), the server is
* responsible for locking and sanity checks.
*/
- return fuse_direct_io(&io, &iov, 1, count, &pos, 1);
+ return fuse_direct_io(&io, &ii, count, &pos, 1);
}
static int cuse_open(struct inode *inode, struct file *file)
@@ -589,11 +595,14 @@ static struct attribute *cuse_class_dev_attrs[] = {
ATTRIBUTE_GROUPS(cuse_class_dev);
static struct miscdevice cuse_miscdev = {
- .minor = MISC_DYNAMIC_MINOR,
+ .minor = CUSE_MINOR,
.name = "cuse",
.fops = &cuse_channel_fops,
};
+MODULE_ALIAS_MISCDEV(CUSE_MINOR);
+MODULE_ALIAS("devname:cuse");
+
static int __init cuse_init(void)
{
int i, rc;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 62b43b577bfc..aba9f757f47f 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -337,24 +337,6 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
return err;
}
-static struct dentry *fuse_materialise_dentry(struct dentry *dentry,
- struct inode *inode)
-{
- struct dentry *newent;
-
- if (inode && S_ISDIR(inode->i_mode)) {
- struct fuse_conn *fc = get_fuse_conn(inode);
-
- mutex_lock(&fc->inst_mutex);
- newent = d_materialise_unique(dentry, inode);
- mutex_unlock(&fc->inst_mutex);
- } else {
- newent = d_materialise_unique(dentry, inode);
- }
-
- return newent;
-}
-
static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
unsigned int flags)
{
@@ -377,7 +359,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
if (inode && get_node_id(inode) == FUSE_ROOT_ID)
goto out_iput;
- newent = fuse_materialise_dentry(entry, inode);
+ newent = d_materialise_unique(entry, inode);
err = PTR_ERR(newent);
if (IS_ERR(newent))
goto out_err;
@@ -596,21 +578,11 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
}
kfree(forget);
- if (S_ISDIR(inode->i_mode)) {
- struct dentry *alias;
- mutex_lock(&fc->inst_mutex);
- alias = d_find_alias(inode);
- if (alias) {
- /* New directory must have moved since mkdir */
- mutex_unlock(&fc->inst_mutex);
- dput(alias);
- iput(inode);
- return -EBUSY;
- }
- d_instantiate(entry, inode);
- mutex_unlock(&fc->inst_mutex);
- } else
- d_instantiate(entry, inode);
+ err = d_instantiate_no_diralias(entry, inode);
+ if (err) {
+ iput(inode);
+ return err;
+ }
fuse_change_entry_timeout(entry, &outarg);
fuse_invalidate_attr(dir);
@@ -1280,7 +1252,7 @@ static int fuse_direntplus_link(struct file *file,
if (!inode)
goto out;
- alias = fuse_materialise_dentry(dentry, inode);
+ alias = d_materialise_unique(dentry, inode);
err = PTR_ERR(alias);
if (IS_ERR(alias))
goto out;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index d409deafc67b..f700502ff6d7 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -334,7 +334,8 @@ static bool fuse_page_is_writeback(struct inode *inode, pgoff_t index)
BUG_ON(req->inode != inode);
curr_index = req->misc.write.in.offset >> PAGE_CACHE_SHIFT;
- if (curr_index == index) {
+ if (curr_index <= index &&
+ index < curr_index + req->num_pages) {
found = true;
break;
}
@@ -1178,9 +1179,10 @@ static inline void fuse_page_descs_length_init(struct fuse_req *req,
req->page_descs[i].offset;
}
-static inline unsigned long fuse_get_user_addr(const struct iov_iter *ii)
+static inline unsigned long fuse_get_user_addr(struct iov_iter *ii)
{
- return (unsigned long)ii->iov->iov_base + ii->iov_offset;
+ struct iovec *iov = iov_iter_iovec(ii);
+ return (unsigned long)iov->iov_base + ii->iov_offset;
}
static inline size_t fuse_get_frag_size(const struct iov_iter *ii,
@@ -1269,9 +1271,8 @@ static inline int fuse_iter_npages(const struct iov_iter *ii_p)
return min(npages, FUSE_MAX_PAGES_PER_REQ);
}
-ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
- unsigned long nr_segs, size_t count, loff_t *ppos,
- int write)
+ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *ii,
+ size_t count, loff_t *ppos, int write)
{
struct file *file = io->file;
struct fuse_file *ff = file->private_data;
@@ -1280,14 +1281,11 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
loff_t pos = *ppos;
ssize_t res = 0;
struct fuse_req *req;
- struct iov_iter ii;
-
- iov_iter_init(&ii, iov, nr_segs, count, 0);
if (io->async)
- req = fuse_get_req_for_background(fc, fuse_iter_npages(&ii));
+ req = fuse_get_req_for_background(fc, fuse_iter_npages(ii));
else
- req = fuse_get_req(fc, fuse_iter_npages(&ii));
+ req = fuse_get_req(fc, fuse_iter_npages(ii));
if (IS_ERR(req))
return PTR_ERR(req);
@@ -1295,7 +1293,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
size_t nres;
fl_owner_t owner = current->files;
size_t nbytes = min(count, nmax);
- int err = fuse_get_user_pages(req, &ii, &nbytes, write);
+ int err = fuse_get_user_pages(req, ii, &nbytes, write);
if (err) {
res = err;
break;
@@ -1325,9 +1323,9 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
fuse_put_request(fc, req);
if (io->async)
req = fuse_get_req_for_background(fc,
- fuse_iter_npages(&ii));
+ fuse_iter_npages(ii));
else
- req = fuse_get_req(fc, fuse_iter_npages(&ii));
+ req = fuse_get_req(fc, fuse_iter_npages(ii));
if (IS_ERR(req))
break;
}
@@ -1341,10 +1339,8 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
}
EXPORT_SYMBOL_GPL(fuse_direct_io);
-static ssize_t __fuse_direct_read(struct fuse_io_priv *io,
- const struct iovec *iov,
- unsigned long nr_segs, loff_t *ppos,
- size_t count)
+static ssize_t __fuse_direct_read(struct fuse_io_priv *io, struct iov_iter *ii,
+ loff_t *ppos, size_t count)
{
ssize_t res;
struct file *file = io->file;
@@ -1353,7 +1349,7 @@ static ssize_t __fuse_direct_read(struct fuse_io_priv *io,
if (is_bad_inode(inode))
return -EIO;
- res = fuse_direct_io(io, iov, nr_segs, count, ppos, 0);
+ res = fuse_direct_io(io, ii, count, ppos, 0);
fuse_invalidate_attr(inode);
@@ -1365,21 +1361,24 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf,
{
struct fuse_io_priv io = { .async = 0, .file = file };
struct iovec iov = { .iov_base = buf, .iov_len = count };
- return __fuse_direct_read(&io, &iov, 1, ppos, count);
+ struct iov_iter ii;
+
+ iov_iter_init(&ii, &iov, 1, count, 0);
+
+ return __fuse_direct_read(&io, &ii, ppos, count);
}
-static ssize_t __fuse_direct_write(struct fuse_io_priv *io,
- const struct iovec *iov,
- unsigned long nr_segs, loff_t *ppos)
+static ssize_t __fuse_direct_write(struct fuse_io_priv *io, struct iov_iter *ii,
+ loff_t *ppos)
{
struct file *file = io->file;
struct inode *inode = file_inode(file);
- size_t count = iov_length(iov, nr_segs);
+ size_t count = iov_iter_count(ii);
ssize_t res;
res = generic_write_checks(file, ppos, &count, 0);
if (!res)
- res = fuse_direct_io(io, iov, nr_segs, count, ppos, 1);
+ res = fuse_direct_io(io, ii, count, ppos, 1);
fuse_invalidate_attr(inode);
@@ -1390,6 +1389,7 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count };
+ struct iov_iter ii;
struct inode *inode = file_inode(file);
ssize_t res;
struct fuse_io_priv io = { .async = 0, .file = file };
@@ -1397,9 +1397,11 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
if (is_bad_inode(inode))
return -EIO;
+ iov_iter_init(&ii, &iov, 1, count, 0);
+
/* Don't allow parallel writes to the same file */
mutex_lock(&inode->i_mutex);
- res = __fuse_direct_write(&io, &iov, 1, ppos);
+ res = __fuse_direct_write(&io, &ii, ppos);
if (res > 0)
fuse_write_update_size(inode, *ppos);
mutex_unlock(&inode->i_mutex);
@@ -1409,8 +1411,13 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req)
{
- __free_page(req->pages[0]);
- fuse_file_put(req->ff, false);
+ int i;
+
+ for (i = 0; i < req->num_pages; i++)
+ __free_page(req->pages[i]);
+
+ if (req->ff)
+ fuse_file_put(req->ff, false);
}
static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req)
@@ -1418,11 +1425,14 @@ static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req)
struct inode *inode = req->inode;
struct fuse_inode *fi = get_fuse_inode(inode);
struct backing_dev_info *bdi = inode->i_mapping->backing_dev_info;
+ int i;
list_del(&req->writepages_entry);
- dec_bdi_stat(bdi, BDI_WRITEBACK);
- dec_zone_page_state(req->pages[0], NR_WRITEBACK_TEMP);
- bdi_writeout_inc(bdi);
+ for (i = 0; i < req->num_pages; i++) {
+ dec_bdi_stat(bdi, BDI_WRITEBACK);
+ dec_zone_page_state(req->pages[i], NR_WRITEBACK_TEMP);
+ bdi_writeout_inc(bdi);
+ }
wake_up(&fi->page_waitq);
}
@@ -1434,14 +1444,15 @@ __acquires(fc->lock)
struct fuse_inode *fi = get_fuse_inode(req->inode);
loff_t size = i_size_read(req->inode);
struct fuse_write_in *inarg = &req->misc.write.in;
+ __u64 data_size = req->num_pages * PAGE_CACHE_SIZE;
if (!fc->connected)
goto out_free;
- if (inarg->offset + PAGE_CACHE_SIZE <= size) {
- inarg->size = PAGE_CACHE_SIZE;
+ if (inarg->offset + data_size <= size) {
+ inarg->size = data_size;
} else if (inarg->offset < size) {
- inarg->size = size & (PAGE_CACHE_SIZE - 1);
+ inarg->size = size - inarg->offset;
} else {
/* Got truncated off completely */
goto out_free;
@@ -1488,12 +1499,36 @@ static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_req *req)
mapping_set_error(inode->i_mapping, req->out.h.error);
spin_lock(&fc->lock);
+ while (req->misc.write.next) {
+ struct fuse_req *next = req->misc.write.next;
+ req->misc.write.next = next->misc.write.next;
+ next->misc.write.next = NULL;
+ list_add(&next->writepages_entry, &fi->writepages);
+ list_add_tail(&next->list, &fi->queued_writes);
+ fuse_flush_writepages(inode);
+ }
fi->writectr--;
fuse_writepage_finish(fc, req);
spin_unlock(&fc->lock);
fuse_writepage_free(fc, req);
}
+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))) {
+ ff = list_entry(fi->write_files.next, struct fuse_file,
+ write_entry);
+ fuse_file_get(ff);
+ }
+ spin_unlock(&fc->lock);
+
+ return ff;
+}
+
static int fuse_writepage_locked(struct page *page)
{
struct address_space *mapping = page->mapping;
@@ -1501,8 +1536,8 @@ static int fuse_writepage_locked(struct page *page)
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_inode *fi = get_fuse_inode(inode);
struct fuse_req *req;
- struct fuse_file *ff;
struct page *tmp_page;
+ int error = -ENOMEM;
set_page_writeback(page);
@@ -1515,16 +1550,16 @@ static int fuse_writepage_locked(struct page *page)
if (!tmp_page)
goto err_free;
- spin_lock(&fc->lock);
- BUG_ON(list_empty(&fi->write_files));
- ff = list_entry(fi->write_files.next, struct fuse_file, write_entry);
- req->ff = fuse_file_get(ff);
- spin_unlock(&fc->lock);
+ error = -EIO;
+ req->ff = fuse_write_file_get(fc, fi);
+ if (!req->ff)
+ goto err_free;
- fuse_write_fill(req, ff, page_offset(page), 0);
+ fuse_write_fill(req, req->ff, page_offset(page), 0);
copy_highpage(tmp_page, page);
req->misc.write.in.write_flags |= FUSE_WRITE_CACHE;
+ req->misc.write.next = NULL;
req->in.argpages = 1;
req->num_pages = 1;
req->pages[0] = tmp_page;
@@ -1550,19 +1585,258 @@ err_free:
fuse_request_free(req);
err:
end_page_writeback(page);
- return -ENOMEM;
+ return error;
}
static int fuse_writepage(struct page *page, struct writeback_control *wbc)
{
int err;
+ if (fuse_page_is_writeback(page->mapping->host, page->index)) {
+ /*
+ * ->writepages() should be called for sync() and friends. We
+ * should only get here on direct reclaim and then we are
+ * allowed to skip a page which is already in flight
+ */
+ WARN_ON(wbc->sync_mode == WB_SYNC_ALL);
+
+ redirty_page_for_writepage(wbc, page);
+ return 0;
+ }
+
err = fuse_writepage_locked(page);
unlock_page(page);
return err;
}
+struct fuse_fill_wb_data {
+ struct fuse_req *req;
+ struct fuse_file *ff;
+ struct inode *inode;
+ struct page **orig_pages;
+};
+
+static void fuse_writepages_send(struct fuse_fill_wb_data *data)
+{
+ struct fuse_req *req = data->req;
+ struct inode *inode = data->inode;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_inode *fi = get_fuse_inode(inode);
+ int num_pages = req->num_pages;
+ int i;
+
+ req->ff = fuse_file_get(data->ff);
+ spin_lock(&fc->lock);
+ list_add_tail(&req->list, &fi->queued_writes);
+ fuse_flush_writepages(inode);
+ spin_unlock(&fc->lock);
+
+ for (i = 0; i < num_pages; i++)
+ end_page_writeback(data->orig_pages[i]);
+}
+
+static bool fuse_writepage_in_flight(struct fuse_req *new_req,
+ struct page *page)
+{
+ struct fuse_conn *fc = get_fuse_conn(new_req->inode);
+ struct fuse_inode *fi = get_fuse_inode(new_req->inode);
+ struct fuse_req *tmp;
+ struct fuse_req *old_req;
+ bool found = false;
+ pgoff_t curr_index;
+
+ BUG_ON(new_req->num_pages != 0);
+
+ spin_lock(&fc->lock);
+ list_del(&new_req->writepages_entry);
+ new_req->num_pages = 1;
+ list_for_each_entry(old_req, &fi->writepages, writepages_entry) {
+ BUG_ON(old_req->inode != new_req->inode);
+ curr_index = old_req->misc.write.in.offset >> PAGE_CACHE_SHIFT;
+ if (curr_index <= page->index &&
+ page->index < curr_index + old_req->num_pages) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ goto out_unlock;
+
+ for (tmp = old_req; tmp != NULL; tmp = tmp->misc.write.next) {
+ BUG_ON(tmp->inode != new_req->inode);
+ curr_index = tmp->misc.write.in.offset >> PAGE_CACHE_SHIFT;
+ if (tmp->num_pages == 1 &&
+ curr_index == page->index) {
+ old_req = tmp;
+ }
+ }
+
+ if (old_req->num_pages == 1 && (old_req->state == FUSE_REQ_INIT ||
+ old_req->state == FUSE_REQ_PENDING)) {
+ copy_highpage(old_req->pages[0], page);
+ spin_unlock(&fc->lock);
+
+ dec_bdi_stat(page->mapping->backing_dev_info, BDI_WRITEBACK);
+ dec_zone_page_state(page, NR_WRITEBACK_TEMP);
+ fuse_writepage_free(fc, new_req);
+ fuse_request_free(new_req);
+ goto out;
+ } else {
+ new_req->misc.write.next = old_req->misc.write.next;
+ old_req->misc.write.next = new_req;
+ }
+out_unlock:
+ spin_unlock(&fc->lock);
+out:
+ return found;
+}
+
+static int fuse_writepages_fill(struct page *page,
+ struct writeback_control *wbc, void *_data)
+{
+ struct fuse_fill_wb_data *data = _data;
+ struct fuse_req *req = data->req;
+ struct inode *inode = data->inode;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct page *tmp_page;
+ bool is_writeback;
+ int err;
+
+ if (!data->ff) {
+ err = -EIO;
+ data->ff = fuse_write_file_get(fc, get_fuse_inode(inode));
+ if (!data->ff)
+ goto out_unlock;
+ }
+
+ /*
+ * Being under writeback is unlikely but possible. For example direct
+ * read to an mmaped fuse file will set the page dirty twice; once when
+ * the pages are faulted with get_user_pages(), and then after the read
+ * completed.
+ */
+ is_writeback = fuse_page_is_writeback(inode, page->index);
+
+ if (req && req->num_pages &&
+ (is_writeback || req->num_pages == FUSE_MAX_PAGES_PER_REQ ||
+ (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_write ||
+ data->orig_pages[req->num_pages - 1]->index + 1 != page->index)) {
+ fuse_writepages_send(data);
+ data->req = NULL;
+ }
+ err = -ENOMEM;
+ tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
+ if (!tmp_page)
+ goto out_unlock;
+
+ /*
+ * The page must not be redirtied until the writeout is completed
+ * (i.e. userspace has sent a reply to the write request). Otherwise
+ * there could be more than one temporary page instance for each real
+ * page.
+ *
+ * This is ensured by holding the page lock in page_mkwrite() while
+ * checking fuse_page_is_writeback(). We already hold the page lock
+ * since clear_page_dirty_for_io() and keep it held until we add the
+ * request to the fi->writepages list and increment req->num_pages.
+ * After this fuse_page_is_writeback() will indicate that the page is
+ * under writeback, so we can release the page lock.
+ */
+ if (data->req == NULL) {
+ struct fuse_inode *fi = get_fuse_inode(inode);
+
+ err = -ENOMEM;
+ req = fuse_request_alloc_nofs(FUSE_MAX_PAGES_PER_REQ);
+ if (!req) {
+ __free_page(tmp_page);
+ goto out_unlock;
+ }
+
+ fuse_write_fill(req, data->ff, page_offset(page), 0);
+ req->misc.write.in.write_flags |= FUSE_WRITE_CACHE;
+ req->misc.write.next = NULL;
+ req->in.argpages = 1;
+ req->background = 1;
+ req->num_pages = 0;
+ req->end = fuse_writepage_end;
+ req->inode = inode;
+
+ spin_lock(&fc->lock);
+ list_add(&req->writepages_entry, &fi->writepages);
+ spin_unlock(&fc->lock);
+
+ data->req = req;
+ }
+ set_page_writeback(page);
+
+ copy_highpage(tmp_page, page);
+ req->pages[req->num_pages] = tmp_page;
+ req->page_descs[req->num_pages].offset = 0;
+ req->page_descs[req->num_pages].length = PAGE_SIZE;
+
+ inc_bdi_stat(page->mapping->backing_dev_info, BDI_WRITEBACK);
+ inc_zone_page_state(tmp_page, NR_WRITEBACK_TEMP);
+
+ err = 0;
+ if (is_writeback && fuse_writepage_in_flight(req, page)) {
+ end_page_writeback(page);
+ data->req = NULL;
+ goto out_unlock;
+ }
+ data->orig_pages[req->num_pages] = page;
+
+ /*
+ * Protected by fc->lock against concurrent access by
+ * fuse_page_is_writeback().
+ */
+ spin_lock(&fc->lock);
+ req->num_pages++;
+ spin_unlock(&fc->lock);
+
+out_unlock:
+ unlock_page(page);
+
+ return err;
+}
+
+static int fuse_writepages(struct address_space *mapping,
+ struct writeback_control *wbc)
+{
+ struct inode *inode = mapping->host;
+ struct fuse_fill_wb_data data;
+ int err;
+
+ err = -EIO;
+ if (is_bad_inode(inode))
+ goto out;
+
+ data.inode = inode;
+ data.req = NULL;
+ data.ff = NULL;
+
+ err = -ENOMEM;
+ data.orig_pages = kzalloc(sizeof(struct page *) *
+ FUSE_MAX_PAGES_PER_REQ,
+ GFP_NOFS);
+ if (!data.orig_pages)
+ goto out;
+
+ err = write_cache_pages(mapping, wbc, fuse_writepages_fill, &data);
+ if (data.req) {
+ /* Ignore errors if we can write at least one page */
+ BUG_ON(!data.req->num_pages);
+ fuse_writepages_send(&data);
+ err = 0;
+ }
+ if (data.ff)
+ fuse_file_put(data.ff, false);
+
+ kfree(data.orig_pages);
+out:
+ return err;
+}
+
static int fuse_launder_page(struct page *page)
{
int err = 0;
@@ -1602,14 +1876,17 @@ static void fuse_vma_close(struct vm_area_struct *vma)
static int fuse_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct page *page = vmf->page;
- /*
- * Don't use page->mapping as it may become NULL from a
- * concurrent truncate.
- */
- struct inode *inode = vma->vm_file->f_mapping->host;
+ struct inode *inode = file_inode(vma->vm_file);
+
+ file_update_time(vma->vm_file);
+ lock_page(page);
+ if (page->mapping != inode->i_mapping) {
+ unlock_page(page);
+ return VM_FAULT_NOPAGE;
+ }
fuse_wait_on_page_writeback(inode, page->index);
- return 0;
+ return VM_FAULT_LOCKED;
}
static const struct vm_operations_struct fuse_file_vm_ops = {
@@ -1868,30 +2145,17 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov,
while (iov_iter_count(&ii)) {
struct page *page = pages[page_idx++];
size_t todo = min_t(size_t, PAGE_SIZE, iov_iter_count(&ii));
- void *kaddr;
+ size_t left;
- kaddr = kmap(page);
-
- while (todo) {
- char __user *uaddr = ii.iov->iov_base + ii.iov_offset;
- size_t iov_len = ii.iov->iov_len - ii.iov_offset;
- size_t copy = min(todo, iov_len);
- size_t left;
-
- if (!to_user)
- left = copy_from_user(kaddr, uaddr, copy);
- else
- left = copy_to_user(uaddr, kaddr, copy);
+ if (!to_user)
+ left = iov_iter_copy_from_user(page, &ii, 0, todo);
+ else
+ left = iov_iter_copy_to_user(page, &ii, 0, todo);
- if (unlikely(left))
- return -EFAULT;
+ if (unlikely(left))
+ return -EFAULT;
- iov_iter_advance(&ii, copy);
- todo -= copy;
- kaddr += copy;
- }
-
- kunmap(page);
+ iov_iter_advance(&ii, todo);
}
return 0;
@@ -2385,8 +2649,8 @@ static inline loff_t fuse_round_up(loff_t off)
}
static ssize_t
-fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
- loff_t offset, unsigned long nr_segs)
+fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *ii,
+ loff_t offset)
{
ssize_t ret = 0;
struct file *file = iocb->ki_filp;
@@ -2395,7 +2659,7 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
loff_t pos = 0;
struct inode *inode;
loff_t i_size;
- size_t count = iov_length(iov, nr_segs);
+ size_t count = iov_iter_count(ii);
struct fuse_io_priv *io;
pos = offset;
@@ -2436,9 +2700,9 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
io->async = false;
if (rw == WRITE)
- ret = __fuse_direct_write(io, iov, nr_segs, &pos);
+ ret = __fuse_direct_write(io, ii, &pos);
else
- ret = __fuse_direct_read(io, iov, nr_segs, &pos, count);
+ ret = __fuse_direct_read(io, ii, &pos, count);
if (io->async) {
fuse_aio_complete(io, ret < 0 ? ret : 0, -1);
@@ -2467,6 +2731,7 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
{
struct fuse_file *ff = file->private_data;
struct inode *inode = file->f_inode;
+ struct fuse_inode *fi = get_fuse_inode(inode);
struct fuse_conn *fc = ff->fc;
struct fuse_req *req;
struct fuse_fallocate_in inarg = {
@@ -2484,10 +2749,20 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
if (lock_inode) {
mutex_lock(&inode->i_mutex);
- if (mode & FALLOC_FL_PUNCH_HOLE)
- fuse_set_nowrite(inode);
+ if (mode & FALLOC_FL_PUNCH_HOLE) {
+ loff_t endbyte = offset + length - 1;
+ err = filemap_write_and_wait_range(inode->i_mapping,
+ offset, endbyte);
+ if (err)
+ goto out;
+
+ fuse_sync_writes(inode);
+ }
}
+ if (!(mode & FALLOC_FL_KEEP_SIZE))
+ set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
+
req = fuse_get_req_nopages(fc);
if (IS_ERR(req)) {
err = PTR_ERR(req);
@@ -2520,11 +2795,11 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
fuse_invalidate_attr(inode);
out:
- if (lock_inode) {
- if (mode & FALLOC_FL_PUNCH_HOLE)
- fuse_release_nowrite(inode);
+ if (!(mode & FALLOC_FL_KEEP_SIZE))
+ clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
+
+ if (lock_inode)
mutex_unlock(&inode->i_mutex);
- }
return err;
}
@@ -2570,6 +2845,7 @@ static const struct file_operations fuse_direct_io_file_operations = {
static const struct address_space_operations fuse_file_aops = {
.readpage = fuse_readpage,
.writepage = fuse_writepage,
+ .writepages = fuse_writepages,
.launder_page = fuse_launder_page,
.readpages = fuse_readpages,
.set_page_dirty = __set_page_dirty_nobuffers,
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 5ced199b50bb..3d4796702fda 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -319,6 +319,7 @@ struct fuse_req {
struct {
struct fuse_write_in in;
struct fuse_write_out out;
+ struct fuse_req *next;
} write;
struct fuse_notify_retrieve_in retrieve_in;
struct fuse_lk_in lk_in;
@@ -372,9 +373,6 @@ struct fuse_conn {
/** Lock protecting accessess to members of this structure */
spinlock_t lock;
- /** Mutex protecting against directory alias creation */
- struct mutex inst_mutex;
-
/** Refcount */
atomic_t count;
@@ -856,9 +854,8 @@ int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
bool isdir);
-ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov,
- unsigned long nr_segs, size_t count, loff_t *ppos,
- int write);
+ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *ii,
+ size_t count, loff_t *ppos, int write);
long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
unsigned int flags);
long fuse_ioctl_common(struct file *file, unsigned int cmd,
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index a8ce6dab60a0..1c15613c64f8 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -565,7 +565,6 @@ void fuse_conn_init(struct fuse_conn *fc)
{
memset(fc, 0, sizeof(*fc));
spin_lock_init(&fc->lock);
- mutex_init(&fc->inst_mutex);
init_rwsem(&fc->killsb);
atomic_set(&fc->count, 1);
init_waitqueue_head(&fc->waitq);
@@ -596,7 +595,6 @@ void fuse_conn_put(struct fuse_conn *fc)
if (atomic_dec_and_test(&fc->count)) {
if (fc->destroy_req)
fuse_request_free(fc->destroy_req);
- mutex_destroy(&fc->inst_mutex);
fc->release(fc);
}
}
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 1f7d8057ea68..43e8eaaa0cf8 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -979,8 +979,7 @@ static int gfs2_ok_for_dio(struct gfs2_inode *ip, int rw, loff_t offset)
static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
- const struct iovec *iov, loff_t offset,
- unsigned long nr_segs)
+ struct iov_iter *iter, loff_t offset)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
@@ -1004,8 +1003,8 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
if (rv != 1)
goto out; /* dio not valid, fall back to buffered i/o */
- rv = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
- offset, nr_segs, gfs2_get_block_direct,
+ rv = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iter,
+ offset, gfs2_get_block_direct,
NULL, NULL, 0);
out:
gfs2_glock_dq(&gh);
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 0621b46d474d..28f462832e18 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -681,10 +681,9 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
}
/**
- * gfs2_file_aio_write - Perform a write to a file
+ * gfs2_file_write_iter - Perform a write to a file
* @iocb: The io context
- * @iov: The data to write
- * @nr_segs: Number of @iov segments
+ * @iter: The data to write
* @pos: The file position
*
* We have to do a lock/unlock here to refresh the inode size for
@@ -694,11 +693,11 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
*
*/
-static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
+static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos)
{
struct file *file = iocb->ki_filp;
- size_t writesize = iov_length(iov, nr_segs);
+ size_t writesize = iov_iter_count(iter);
struct gfs2_inode *ip = GFS2_I(file_inode(file));
int ret;
@@ -717,7 +716,7 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
gfs2_glock_dq_uninit(&gh);
}
- return generic_file_aio_write(iocb, iov, nr_segs, pos);
+ return generic_file_write_iter(iocb, iter, pos);
}
static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
@@ -1049,9 +1048,9 @@ static int gfs2_flock(struct file *file, int cmd, struct file_lock *fl)
const struct file_operations gfs2_file_fops = {
.llseek = gfs2_llseek,
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.write = do_sync_write,
- .aio_write = gfs2_file_aio_write,
+ .write_iter = gfs2_file_write_iter,
.unlocked_ioctl = gfs2_ioctl,
.mmap = gfs2_mmap,
.open = gfs2_open,
@@ -1081,9 +1080,9 @@ const struct file_operations gfs2_dir_fops = {
const struct file_operations gfs2_file_fops_nolock = {
.llseek = gfs2_llseek,
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.write = do_sync_write,
- .aio_write = gfs2_file_aio_write,
+ .write_iter = gfs2_file_write_iter,
.unlocked_ioctl = gfs2_ioctl,
.mmap = gfs2_mmap,
.open = gfs2_open,
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 26aabd7caba7..8c8f110d8e35 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -71,6 +71,7 @@ struct gfs2_bitmap {
u32 bi_offset;
u32 bi_start;
u32 bi_len;
+ u32 bi_blocks;
};
struct gfs2_rgrpd {
@@ -101,19 +102,25 @@ struct gfs2_rgrpd {
struct gfs2_rbm {
struct gfs2_rgrpd *rgd;
- struct gfs2_bitmap *bi; /* Bitmap must belong to the rgd */
u32 offset; /* The offset is bitmap relative */
+ int bii; /* Bitmap index */
};
+static inline struct gfs2_bitmap *rbm_bi(const struct gfs2_rbm *rbm)
+{
+ return rbm->rgd->rd_bits + rbm->bii;
+}
+
static inline u64 gfs2_rbm_to_block(const struct gfs2_rbm *rbm)
{
- return rbm->rgd->rd_data0 + (rbm->bi->bi_start * GFS2_NBBY) + rbm->offset;
+ return rbm->rgd->rd_data0 + (rbm_bi(rbm)->bi_start * GFS2_NBBY) +
+ rbm->offset;
}
static inline bool gfs2_rbm_eq(const struct gfs2_rbm *rbm1,
const struct gfs2_rbm *rbm2)
{
- return (rbm1->rgd == rbm2->rgd) && (rbm1->bi == rbm2->bi) &&
+ return (rbm1->rgd == rbm2->rgd) && (rbm1->bii == rbm2->bii) &&
(rbm1->offset == rbm2->offset);
}
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index ced3257f06e8..1f54db9aeed0 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -584,17 +584,17 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
if (!IS_ERR(inode)) {
d = d_splice_alias(inode, dentry);
error = 0;
- if (file && !IS_ERR(d)) {
- if (d == NULL)
- d = dentry;
- if (S_ISREG(inode->i_mode))
- error = finish_open(file, d, gfs2_open_common, opened);
- else
+ if (file) {
+ if (S_ISREG(inode->i_mode)) {
+ WARN_ON(d != NULL);
+ error = finish_open(file, dentry, gfs2_open_common, opened);
+ } else {
error = finish_no_open(file, d);
+ }
+ } else {
+ dput(d);
}
gfs2_glock_dq_uninit(ghs);
- if (IS_ERR(d))
- return PTR_ERR(d);
return error;
} else if (error != -ENOENT) {
goto fail_gunlock;
@@ -781,8 +781,10 @@ static struct dentry *__gfs2_lookup(struct inode *dir, struct dentry *dentry,
error = finish_open(file, dentry, gfs2_open_common, opened);
gfs2_glock_dq_uninit(&gh);
- if (error)
+ if (error) {
+ dput(d);
return ERR_PTR(error);
+ }
return d;
}
@@ -1163,14 +1165,16 @@ static int gfs2_atomic_open(struct inode *dir, struct dentry *dentry,
d = __gfs2_lookup(dir, dentry, file, opened);
if (IS_ERR(d))
return PTR_ERR(d);
- if (d == NULL)
- d = dentry;
- if (d->d_inode) {
+ if (d != NULL)
+ dentry = d;
+ if (dentry->d_inode) {
if (!(*opened & FILE_OPENED))
- return finish_no_open(file, d);
+ return finish_no_open(file, dentry);
+ dput(d);
return 0;
}
+ BUG_ON(d != NULL);
if (!(flags & O_CREAT))
return -ENOENT;
@@ -1506,13 +1510,6 @@ out:
return NULL;
}
-static void gfs2_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
-{
- char *s = nd_get_link(nd);
- if (!IS_ERR(s))
- kfree(s);
-}
-
/**
* gfs2_permission -
* @inode: The inode
@@ -1864,7 +1861,7 @@ const struct inode_operations gfs2_dir_iops = {
const struct inode_operations gfs2_symlink_iops = {
.readlink = generic_readlink,
.follow_link = gfs2_follow_link,
- .put_link = gfs2_put_link,
+ .put_link = kfree_put_link,
.permission = gfs2_permission,
.setattr = gfs2_setattr,
.getattr = gfs2_getattr,
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 69317435faa7..285dd363199a 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -81,11 +81,12 @@ static inline void gfs2_setbit(const struct gfs2_rbm *rbm, bool do_clone,
unsigned char new_state)
{
unsigned char *byte1, *byte2, *end, cur_state;
- unsigned int buflen = rbm->bi->bi_len;
+ struct gfs2_bitmap *bi = rbm_bi(rbm);
+ unsigned int buflen = bi->bi_len;
const unsigned int bit = (rbm->offset % GFS2_NBBY) * GFS2_BIT_SIZE;
- byte1 = rbm->bi->bi_bh->b_data + rbm->bi->bi_offset + (rbm->offset / GFS2_NBBY);
- end = rbm->bi->bi_bh->b_data + rbm->bi->bi_offset + buflen;
+ byte1 = bi->bi_bh->b_data + bi->bi_offset + (rbm->offset / GFS2_NBBY);
+ end = bi->bi_bh->b_data + bi->bi_offset + buflen;
BUG_ON(byte1 >= end);
@@ -95,18 +96,17 @@ static inline void gfs2_setbit(const struct gfs2_rbm *rbm, bool do_clone,
printk(KERN_WARNING "GFS2: buf_blk = 0x%x old_state=%d, "
"new_state=%d\n", rbm->offset, cur_state, new_state);
printk(KERN_WARNING "GFS2: rgrp=0x%llx bi_start=0x%x\n",
- (unsigned long long)rbm->rgd->rd_addr,
- rbm->bi->bi_start);
+ (unsigned long long)rbm->rgd->rd_addr, bi->bi_start);
printk(KERN_WARNING "GFS2: bi_offset=0x%x bi_len=0x%x\n",
- rbm->bi->bi_offset, rbm->bi->bi_len);
+ bi->bi_offset, bi->bi_len);
dump_stack();
gfs2_consist_rgrpd(rbm->rgd);
return;
}
*byte1 ^= (cur_state ^ new_state) << bit;
- if (do_clone && rbm->bi->bi_clone) {
- byte2 = rbm->bi->bi_clone + rbm->bi->bi_offset + (rbm->offset / GFS2_NBBY);
+ if (do_clone && bi->bi_clone) {
+ byte2 = bi->bi_clone + bi->bi_offset + (rbm->offset / GFS2_NBBY);
cur_state = (*byte2 >> bit) & GFS2_BIT_MASK;
*byte2 ^= (cur_state ^ new_state) << bit;
}
@@ -121,7 +121,8 @@ static inline void gfs2_setbit(const struct gfs2_rbm *rbm, bool do_clone,
static inline u8 gfs2_testbit(const struct gfs2_rbm *rbm)
{
- const u8 *buffer = rbm->bi->bi_bh->b_data + rbm->bi->bi_offset;
+ struct gfs2_bitmap *bi = rbm_bi(rbm);
+ const u8 *buffer = bi->bi_bh->b_data + bi->bi_offset;
const u8 *byte;
unsigned int bit;
@@ -252,29 +253,53 @@ static u32 gfs2_bitfit(const u8 *buf, const unsigned int len,
static int gfs2_rbm_from_block(struct gfs2_rbm *rbm, u64 block)
{
u64 rblock = block - rbm->rgd->rd_data0;
- u32 x;
if (WARN_ON_ONCE(rblock > UINT_MAX))
return -EINVAL;
if (block >= rbm->rgd->rd_data0 + rbm->rgd->rd_data)
return -E2BIG;
- rbm->bi = rbm->rgd->rd_bits;
+ rbm->bii = 0;
rbm->offset = (u32)(rblock);
/* Check if the block is within the first block */
- if (rbm->offset < (rbm->bi->bi_start + rbm->bi->bi_len) * GFS2_NBBY)
+ if (rbm->offset < rbm_bi(rbm)->bi_blocks)
return 0;
/* Adjust for the size diff between gfs2_meta_header and gfs2_rgrp */
rbm->offset += (sizeof(struct gfs2_rgrp) -
sizeof(struct gfs2_meta_header)) * GFS2_NBBY;
- x = rbm->offset / rbm->rgd->rd_sbd->sd_blocks_per_bitmap;
- rbm->offset -= x * rbm->rgd->rd_sbd->sd_blocks_per_bitmap;
- rbm->bi += x;
+ rbm->bii = rbm->offset / rbm->rgd->rd_sbd->sd_blocks_per_bitmap;
+ rbm->offset -= rbm->bii * rbm->rgd->rd_sbd->sd_blocks_per_bitmap;
return 0;
}
/**
+ * gfs2_rbm_incr - increment an rbm structure
+ * @rbm: The rbm with rgd already set correctly
+ *
+ * This function takes an existing rbm structure and increments it to the next
+ * viable block offset.
+ *
+ * Returns: If incrementing the offset would cause the rbm to go past the
+ * end of the rgrp, true is returned, otherwise false.
+ *
+ */
+
+static bool gfs2_rbm_incr(struct gfs2_rbm *rbm)
+{
+ if (rbm->offset + 1 < rbm_bi(rbm)->bi_blocks) { /* in the same bitmap */
+ rbm->offset++;
+ return false;
+ }
+ if (rbm->bii == rbm->rgd->rd_length - 1) /* at the last bitmap */
+ return true;
+
+ rbm->offset = 0;
+ rbm->bii++;
+ return false;
+}
+
+/**
* gfs2_unaligned_extlen - Look for free blocks which are not byte aligned
* @rbm: Position to search (value/result)
* @n_unaligned: Number of unaligned blocks to check
@@ -285,7 +310,6 @@ static int gfs2_rbm_from_block(struct gfs2_rbm *rbm, u64 block)
static bool gfs2_unaligned_extlen(struct gfs2_rbm *rbm, u32 n_unaligned, u32 *len)
{
- u64 block;
u32 n;
u8 res;
@@ -296,8 +320,7 @@ static bool gfs2_unaligned_extlen(struct gfs2_rbm *rbm, u32 n_unaligned, u32 *le
(*len)--;
if (*len == 0)
return true;
- block = gfs2_rbm_to_block(rbm);
- if (gfs2_rbm_from_block(rbm, block + 1))
+ if (gfs2_rbm_incr(rbm))
return true;
}
@@ -328,6 +351,7 @@ static u32 gfs2_free_extlen(const struct gfs2_rbm *rrbm, u32 len)
u32 chunk_size;
u8 *ptr, *start, *end;
u64 block;
+ struct gfs2_bitmap *bi;
if (n_unaligned &&
gfs2_unaligned_extlen(&rbm, 4 - n_unaligned, &len))
@@ -336,11 +360,12 @@ static u32 gfs2_free_extlen(const struct gfs2_rbm *rrbm, u32 len)
n_unaligned = len & 3;
/* Start is now byte aligned */
while (len > 3) {
- start = rbm.bi->bi_bh->b_data;
- if (rbm.bi->bi_clone)
- start = rbm.bi->bi_clone;
- end = start + rbm.bi->bi_bh->b_size;
- start += rbm.bi->bi_offset;
+ bi = rbm_bi(&rbm);
+ start = bi->bi_bh->b_data;
+ if (bi->bi_clone)
+ start = bi->bi_clone;
+ end = start + bi->bi_bh->b_size;
+ start += bi->bi_offset;
BUG_ON(rbm.offset & 3);
start += (rbm.offset / GFS2_NBBY);
bytes = min_t(u32, len / GFS2_NBBY, (end - start));
@@ -605,11 +630,13 @@ static void __rs_deltree(struct gfs2_blkreserv *rs)
RB_CLEAR_NODE(&rs->rs_node);
if (rs->rs_free) {
+ struct gfs2_bitmap *bi = rbm_bi(&rs->rs_rbm);
+
/* return reserved blocks to the rgrp */
BUG_ON(rs->rs_rbm.rgd->rd_reserved < rs->rs_free);
rs->rs_rbm.rgd->rd_reserved -= rs->rs_free;
rs->rs_free = 0;
- clear_bit(GBF_FULL, &rs->rs_rbm.bi->bi_flags);
+ clear_bit(GBF_FULL, &bi->bi_flags);
smp_mb__after_clear_bit();
}
}
@@ -743,18 +770,21 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd)
bi->bi_offset = sizeof(struct gfs2_rgrp);
bi->bi_start = 0;
bi->bi_len = bytes;
+ bi->bi_blocks = bytes * GFS2_NBBY;
/* header block */
} else if (x == 0) {
bytes = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_rgrp);
bi->bi_offset = sizeof(struct gfs2_rgrp);
bi->bi_start = 0;
bi->bi_len = bytes;
+ bi->bi_blocks = bytes * GFS2_NBBY;
/* last block */
} else if (x + 1 == length) {
bytes = bytes_left;
bi->bi_offset = sizeof(struct gfs2_meta_header);
bi->bi_start = rgd->rd_bitbytes - bytes_left;
bi->bi_len = bytes;
+ bi->bi_blocks = bytes * GFS2_NBBY;
/* other blocks */
} else {
bytes = sdp->sd_sb.sb_bsize -
@@ -762,6 +792,7 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd)
bi->bi_offset = sizeof(struct gfs2_meta_header);
bi->bi_start = rgd->rd_bitbytes - bytes_left;
bi->bi_len = bytes;
+ bi->bi_blocks = bytes * GFS2_NBBY;
}
bytes_left -= bytes;
@@ -1554,14 +1585,14 @@ static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 minext,
const struct gfs2_inode *ip, bool nowrap)
{
struct buffer_head *bh;
- struct gfs2_bitmap *initial_bi;
+ int initial_bii;
u32 initial_offset;
u32 offset;
u8 *buffer;
- int index;
int n = 0;
int iters = rbm->rgd->rd_length;
int ret;
+ struct gfs2_bitmap *bi;
/* If we are not starting at the beginning of a bitmap, then we
* need to add one to the bitmap count to ensure that we search
@@ -1571,52 +1602,53 @@ static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 minext,
iters++;
while(1) {
- if (test_bit(GBF_FULL, &rbm->bi->bi_flags) &&
+ bi = rbm_bi(rbm);
+ if (test_bit(GBF_FULL, &bi->bi_flags) &&
(state == GFS2_BLKST_FREE))
goto next_bitmap;
- bh = rbm->bi->bi_bh;
- buffer = bh->b_data + rbm->bi->bi_offset;
+ bh = bi->bi_bh;
+ buffer = bh->b_data + bi->bi_offset;
WARN_ON(!buffer_uptodate(bh));
- if (state != GFS2_BLKST_UNLINKED && rbm->bi->bi_clone)
- buffer = rbm->bi->bi_clone + rbm->bi->bi_offset;
+ if (state != GFS2_BLKST_UNLINKED && bi->bi_clone)
+ buffer = bi->bi_clone + bi->bi_offset;
initial_offset = rbm->offset;
- offset = gfs2_bitfit(buffer, rbm->bi->bi_len, rbm->offset, state);
+ offset = gfs2_bitfit(buffer, bi->bi_len, rbm->offset, state);
if (offset == BFITNOENT)
goto bitmap_full;
rbm->offset = offset;
if (ip == NULL)
return 0;
- initial_bi = rbm->bi;
+ initial_bii = rbm->bii;
ret = gfs2_reservation_check_and_update(rbm, ip, minext);
if (ret == 0)
return 0;
if (ret > 0) {
- n += (rbm->bi - initial_bi);
+ n += (rbm->bii - initial_bii);
goto next_iter;
}
if (ret == -E2BIG) {
- index = 0;
+ rbm->bii = 0;
rbm->offset = 0;
- n += (rbm->bi - initial_bi);
+ n += (rbm->bii - initial_bii);
goto res_covered_end_of_rgrp;
}
return ret;
bitmap_full: /* Mark bitmap as full and fall through */
- if ((state == GFS2_BLKST_FREE) && initial_offset == 0)
- set_bit(GBF_FULL, &rbm->bi->bi_flags);
+ if ((state == GFS2_BLKST_FREE) && initial_offset == 0) {
+ struct gfs2_bitmap *bi = rbm_bi(rbm);
+ set_bit(GBF_FULL, &bi->bi_flags);
+ }
next_bitmap: /* Find next bitmap in the rgrp */
rbm->offset = 0;
- index = rbm->bi - rbm->rgd->rd_bits;
- index++;
- if (index == rbm->rgd->rd_length)
- index = 0;
+ rbm->bii++;
+ if (rbm->bii == rbm->rgd->rd_length)
+ rbm->bii = 0;
res_covered_end_of_rgrp:
- rbm->bi = &rbm->rgd->rd_bits[index];
- if ((index == 0) && nowrap)
+ if ((rbm->bii == 0) && nowrap)
break;
n++;
next_iter:
@@ -1645,7 +1677,7 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip
struct gfs2_inode *ip;
int error;
int found = 0;
- struct gfs2_rbm rbm = { .rgd = rgd, .bi = rgd->rd_bits, .offset = 0 };
+ struct gfs2_rbm rbm = { .rgd = rgd, .bii = 0, .offset = 0 };
while (1) {
down_write(&sdp->sd_log_flush_lock);
@@ -1821,7 +1853,6 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested, u32 aflags)
return -EINVAL;
if (gfs2_rs_active(rs)) {
begin = rs->rs_rbm.rgd;
- flags = 0; /* Yoda: Do or do not. There is no try */
} else if (ip->i_rgd && rgrp_contains_block(ip->i_rgd, ip->i_goal)) {
rs->rs_rbm.rgd = begin = ip->i_rgd;
} else {
@@ -1973,14 +2004,14 @@ static void gfs2_alloc_extent(const struct gfs2_rbm *rbm, bool dinode,
*n = 1;
block = gfs2_rbm_to_block(rbm);
- gfs2_trans_add_meta(rbm->rgd->rd_gl, rbm->bi->bi_bh);
+ gfs2_trans_add_meta(rbm->rgd->rd_gl, rbm_bi(rbm)->bi_bh);
gfs2_setbit(rbm, true, dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED);
block++;
while (*n < elen) {
ret = gfs2_rbm_from_block(&pos, block);
if (ret || gfs2_testbit(&pos) != GFS2_BLKST_FREE)
break;
- gfs2_trans_add_meta(pos.rgd->rd_gl, pos.bi->bi_bh);
+ gfs2_trans_add_meta(pos.rgd->rd_gl, rbm_bi(&pos)->bi_bh);
gfs2_setbit(&pos, true, GFS2_BLKST_USED);
(*n)++;
block++;
@@ -2001,6 +2032,7 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
u32 blen, unsigned char new_state)
{
struct gfs2_rbm rbm;
+ struct gfs2_bitmap *bi;
rbm.rgd = gfs2_blk2rgrpd(sdp, bstart, 1);
if (!rbm.rgd) {
@@ -2011,15 +2043,15 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
while (blen--) {
gfs2_rbm_from_block(&rbm, bstart);
+ bi = rbm_bi(&rbm);
bstart++;
- if (!rbm.bi->bi_clone) {
- rbm.bi->bi_clone = kmalloc(rbm.bi->bi_bh->b_size,
- GFP_NOFS | __GFP_NOFAIL);
- memcpy(rbm.bi->bi_clone + rbm.bi->bi_offset,
- rbm.bi->bi_bh->b_data + rbm.bi->bi_offset,
- rbm.bi->bi_len);
+ if (!bi->bi_clone) {
+ bi->bi_clone = kmalloc(bi->bi_bh->b_size,
+ GFP_NOFS | __GFP_NOFAIL);
+ memcpy(bi->bi_clone + bi->bi_offset,
+ bi->bi_bh->b_data + bi->bi_offset, bi->bi_len);
}
- gfs2_trans_add_meta(rbm.rgd->rd_gl, rbm.bi->bi_bh);
+ gfs2_trans_add_meta(rbm.rgd->rd_gl, bi->bi_bh);
gfs2_setbit(&rbm, false, new_state);
}
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 380ab31b5e0f..3fe7b8e53290 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -125,15 +125,14 @@ static int hfs_releasepage(struct page *page, gfp_t mask)
}
static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb,
- const struct iovec *iov, loff_t offset, unsigned long nr_segs)
+ struct iov_iter *iter, loff_t offset)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
struct inode *inode = file_inode(file)->i_mapping->host;
ssize_t ret;
- ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
- hfs_get_block);
+ ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, hfs_get_block);
/*
* In case of error extending write may have instantiated a few
@@ -141,7 +140,7 @@ static ssize_t hfs_direct_IO(int rw, struct kiocb *iocb,
*/
if (unlikely((rw & WRITE) && ret < 0)) {
loff_t isize = i_size_read(inode);
- loff_t end = offset + iov_length(iov, nr_segs);
+ loff_t end = offset + iov_iter_count(iter);
if (end > isize)
hfs_write_failed(mapping, end);
@@ -675,9 +674,9 @@ static int hfs_file_fsync(struct file *filp, loff_t start, loff_t end,
static const struct file_operations hfs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.write = do_sync_write,
- .aio_write = generic_file_aio_write,
+ .write_iter = generic_file_write_iter,
.mmap = generic_file_mmap,
.splice_read = generic_file_splice_read,
.fsync = hfs_file_fsync,
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 37213d075f3c..96d7a2ccded2 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -123,14 +123,14 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask)
}
static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb,
- const struct iovec *iov, loff_t offset, unsigned long nr_segs)
+ struct iov_iter *iter, loff_t offset)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
struct inode *inode = file_inode(file)->i_mapping->host;
ssize_t ret;
- ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
+ ret = blockdev_direct_IO(rw, iocb, inode, iter, offset,
hfsplus_get_block);
/*
@@ -139,7 +139,7 @@ static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb,
*/
if (unlikely((rw & WRITE) && ret < 0)) {
loff_t isize = i_size_read(inode);
- loff_t end = offset + iov_length(iov, nr_segs);
+ loff_t end = offset + iov_iter_count(iter);
if (end > isize)
hfsplus_write_failed(mapping, end);
@@ -399,9 +399,9 @@ static const struct inode_operations hfsplus_file_inode_operations = {
static const struct file_operations hfsplus_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.write = do_sync_write,
- .aio_write = generic_file_aio_write,
+ .write_iter = generic_file_write_iter,
.mmap = generic_file_mmap,
.splice_read = generic_file_splice_read,
.fsync = hfsplus_file_fsync,
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 25437280a207..111a9916bcf5 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -388,8 +388,8 @@ static const struct file_operations hostfs_file_fops = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.splice_read = generic_file_splice_read,
- .aio_read = generic_file_aio_read,
- .aio_write = generic_file_aio_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = generic_file_write_iter,
.write = do_sync_write,
.mmap = generic_file_mmap,
.open = hostfs_file_open,
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index 67c1a61e0955..1ff95c19a469 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -198,9 +198,9 @@ const struct file_operations hpfs_file_ops =
{
.llseek = generic_file_llseek,
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.write = do_sync_write,
- .aio_write = generic_file_aio_write,
+ .write_iter = generic_file_write_iter,
.mmap = generic_file_mmap,
.release = hpfs_file_release,
.fsync = hpfs_file_fsync,
diff --git a/fs/internal.h b/fs/internal.h
index 513e0d859a6c..6964003cfef8 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -140,6 +140,10 @@ extern long prune_dcache_sb(struct super_block *sb, unsigned long nr_to_scan,
*/
extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
extern int rw_verify_area(int, struct file *, const loff_t *, size_t);
+extern ssize_t do_aio_read(struct kiocb *kiocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos);
+extern ssize_t do_aio_write(struct kiocb *kiocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos);
/*
* splice.c
diff --git a/fs/iov-iter.c b/fs/iov-iter.c
new file mode 100644
index 000000000000..ec461c8fea22
--- /dev/null
+++ b/fs/iov-iter.c
@@ -0,0 +1,411 @@
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/uio.h>
+#include <linux/hardirq.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/bio.h>
+
+static size_t __iovec_copy_to_user(char *vaddr, const struct iovec *iov,
+ size_t base, size_t bytes, int atomic)
+{
+ size_t copied = 0, left = 0;
+
+ while (bytes) {
+ char __user *buf = iov->iov_base + base;
+ int copy = min(bytes, iov->iov_len - base);
+
+ base = 0;
+ if (atomic)
+ left = __copy_to_user_inatomic(buf, vaddr, copy);
+ else
+ left = __copy_to_user(buf, vaddr, copy);
+ copied += copy;
+ bytes -= copy;
+ vaddr += copy;
+ iov++;
+
+ if (unlikely(left))
+ break;
+ }
+ return copied - left;
+}
+
+/*
+ * Copy as much as we can into the page and return the number of bytes which
+ * were sucessfully copied. If a fault is encountered then return the number of
+ * bytes which were copied.
+ */
+static size_t ii_iovec_copy_to_user_atomic(struct page *page,
+ struct iov_iter *i, unsigned long offset, size_t bytes)
+{
+ struct iovec *iov = (struct iovec *)i->data;
+ char *kaddr;
+ size_t copied;
+
+ BUG_ON(!in_atomic());
+ kaddr = kmap_atomic(page);
+ if (likely(i->nr_segs == 1)) {
+ int left;
+ char __user *buf = iov->iov_base + i->iov_offset;
+ left = __copy_to_user_inatomic(buf, kaddr + offset, bytes);
+ copied = bytes - left;
+ } else {
+ copied = __iovec_copy_to_user(kaddr + offset, iov,
+ i->iov_offset, bytes, 1);
+ }
+ kunmap_atomic(kaddr);
+
+ return copied;
+}
+
+/*
+ * This has the same sideeffects and return value as
+ * ii_iovec_copy_to_user_atomic().
+ * The difference is that it attempts to resolve faults.
+ * Page must not be locked.
+ */
+static size_t ii_iovec_copy_to_user(struct page *page,
+ struct iov_iter *i, unsigned long offset, size_t bytes,
+ int check_access)
+{
+ struct iovec *iov = (struct iovec *)i->data;
+ char *kaddr;
+ size_t copied;
+
+ if (check_access) {
+ might_sleep();
+ if (generic_segment_checks(iov, &i->nr_segs, &bytes,
+ VERIFY_WRITE))
+ return 0;
+ }
+
+ if (likely(i->nr_segs == 1)) {
+ int left;
+ char __user *buf = iov->iov_base + i->iov_offset;
+ /*
+ * Faults on the destination of a read are common, so do it
+ * before taking the kmap.
+ */
+ if (!fault_in_pages_writeable(buf, bytes)) {
+ kaddr = kmap_atomic(page);
+ left = __copy_to_user_inatomic(buf, kaddr + offset,
+ bytes);
+ kunmap_atomic(kaddr);
+ if (left == 0)
+ goto success;
+ }
+ kaddr = kmap(page);
+ left = copy_to_user(buf, kaddr + offset, bytes);
+ kunmap(page);
+success:
+ copied = bytes - left;
+ } else {
+ kaddr = kmap(page);
+ copied = __iovec_copy_to_user(kaddr + offset, iov,
+ i->iov_offset, bytes, 0);
+ kunmap(page);
+ }
+ return copied;
+}
+
+#ifdef CONFIG_BLOCK
+/*
+ * As an easily verifiable first pass, we implement all the methods that
+ * copy data to and from bvec pages with one function. We implement it
+ * all with kmap_atomic().
+ */
+static size_t bvec_copy_tofrom_page(struct iov_iter *iter, struct page *page,
+ unsigned long page_offset, size_t bytes,
+ int topage)
+{
+ struct bio_vec *bvec = (struct bio_vec *)iter->data;
+ size_t bvec_offset = iter->iov_offset;
+ size_t remaining = bytes;
+ void *bvec_map;
+ void *page_map;
+ size_t copy;
+
+ page_map = kmap_atomic(page);
+
+ BUG_ON(bytes > iter->count);
+ while (remaining) {
+ BUG_ON(bvec->bv_len == 0);
+ BUG_ON(bvec_offset >= bvec->bv_len);
+ copy = min(remaining, bvec->bv_len - bvec_offset);
+ bvec_map = kmap_atomic(bvec->bv_page);
+ if (topage)
+ memcpy(page_map + page_offset,
+ bvec_map + bvec->bv_offset + bvec_offset,
+ copy);
+ else
+ memcpy(bvec_map + bvec->bv_offset + bvec_offset,
+ page_map + page_offset,
+ copy);
+ kunmap_atomic(bvec_map);
+ remaining -= copy;
+ bvec_offset += copy;
+ page_offset += copy;
+ if (bvec_offset == bvec->bv_len) {
+ bvec_offset = 0;
+ bvec++;
+ }
+ }
+
+ kunmap_atomic(page_map);
+
+ return bytes;
+}
+
+static size_t ii_bvec_copy_to_user_atomic(struct page *page, struct iov_iter *i,
+ unsigned long offset, size_t bytes)
+{
+ return bvec_copy_tofrom_page(i, page, offset, bytes, 0);
+}
+static size_t ii_bvec_copy_to_user(struct page *page, struct iov_iter *i,
+ unsigned long offset, size_t bytes,
+ int check_access)
+{
+ return bvec_copy_tofrom_page(i, page, offset, bytes, 0);
+}
+static size_t ii_bvec_copy_from_user_atomic(struct page *page,
+ struct iov_iter *i,
+ unsigned long offset, size_t bytes)
+{
+ return bvec_copy_tofrom_page(i, page, offset, bytes, 1);
+}
+static size_t ii_bvec_copy_from_user(struct page *page, struct iov_iter *i,
+ unsigned long offset, size_t bytes)
+{
+ return bvec_copy_tofrom_page(i, page, offset, bytes, 1);
+}
+
+/*
+ * bio_vecs have a stricter structure than iovecs that might have
+ * come from userspace. There are no zero length bio_vec elements.
+ */
+static void ii_bvec_advance(struct iov_iter *i, size_t bytes)
+{
+ struct bio_vec *bvec = (struct bio_vec *)i->data;
+ size_t offset = i->iov_offset;
+ size_t delta;
+
+ BUG_ON(i->count < bytes);
+ while (bytes) {
+ BUG_ON(bvec->bv_len == 0);
+ BUG_ON(bvec->bv_len <= offset);
+ delta = min(bytes, bvec->bv_len - offset);
+ offset += delta;
+ i->count -= delta;
+ bytes -= delta;
+ if (offset == bvec->bv_len) {
+ bvec++;
+ offset = 0;
+ }
+ }
+
+ i->data = (unsigned long)bvec;
+ i->iov_offset = offset;
+}
+
+/*
+ * pages pointed to by bio_vecs are always pinned.
+ */
+static int ii_bvec_fault_in_readable(struct iov_iter *i, size_t bytes)
+{
+ return 0;
+}
+
+static size_t ii_bvec_single_seg_count(const struct iov_iter *i)
+{
+ const struct bio_vec *bvec = (struct bio_vec *)i->data;
+ if (i->nr_segs == 1)
+ return i->count;
+ else
+ return min(i->count, bvec->bv_len - i->iov_offset);
+}
+
+static int ii_bvec_shorten(struct iov_iter *i, size_t count)
+{
+ return -EINVAL;
+}
+
+struct iov_iter_ops ii_bvec_ops = {
+ .ii_copy_to_user_atomic = ii_bvec_copy_to_user_atomic,
+ .ii_copy_to_user = ii_bvec_copy_to_user,
+ .ii_copy_from_user_atomic = ii_bvec_copy_from_user_atomic,
+ .ii_copy_from_user = ii_bvec_copy_from_user,
+ .ii_advance = ii_bvec_advance,
+ .ii_fault_in_readable = ii_bvec_fault_in_readable,
+ .ii_single_seg_count = ii_bvec_single_seg_count,
+ .ii_shorten = ii_bvec_shorten,
+};
+EXPORT_SYMBOL(ii_bvec_ops);
+#endif /* CONFIG_BLOCK */
+
+static size_t __iovec_copy_from_user(char *vaddr, const struct iovec *iov,
+ size_t base, size_t bytes, int atomic)
+{
+ size_t copied = 0, left = 0;
+
+ while (bytes) {
+ char __user *buf = iov->iov_base + base;
+ int copy = min(bytes, iov->iov_len - base);
+
+ base = 0;
+ if (atomic)
+ left = __copy_from_user_inatomic(vaddr, buf, copy);
+ else
+ left = __copy_from_user(vaddr, buf, copy);
+ copied += copy;
+ bytes -= copy;
+ vaddr += copy;
+ iov++;
+
+ if (unlikely(left))
+ break;
+ }
+ return copied - left;
+}
+
+/*
+ * Copy as much as we can into the page and return the number of bytes which
+ * were successfully copied. If a fault is encountered then return the number
+ * of bytes which were copied.
+ */
+static size_t ii_iovec_copy_from_user_atomic(struct page *page,
+ struct iov_iter *i, unsigned long offset, size_t bytes)
+{
+ struct iovec *iov = (struct iovec *)i->data;
+ char *kaddr;
+ size_t copied;
+
+ BUG_ON(!in_atomic());
+ kaddr = kmap_atomic(page);
+ if (likely(i->nr_segs == 1)) {
+ int left;
+ char __user *buf = iov->iov_base + i->iov_offset;
+ left = __copy_from_user_inatomic(kaddr + offset, buf, bytes);
+ copied = bytes - left;
+ } else {
+ copied = __iovec_copy_from_user(kaddr + offset, iov,
+ i->iov_offset, bytes, 1);
+ }
+ kunmap_atomic(kaddr);
+
+ return copied;
+}
+EXPORT_SYMBOL(iov_iter_copy_from_user_atomic);
+
+/*
+ * This has the same sideeffects and return value as
+ * ii_iovec_copy_from_user_atomic().
+ * The difference is that it attempts to resolve faults.
+ * Page must not be locked.
+ */
+static size_t ii_iovec_copy_from_user(struct page *page,
+ struct iov_iter *i, unsigned long offset, size_t bytes)
+{
+ struct iovec *iov = (struct iovec *)i->data;
+ char *kaddr;
+ size_t copied;
+
+ kaddr = kmap(page);
+ if (likely(i->nr_segs == 1)) {
+ int left;
+ char __user *buf = iov->iov_base + i->iov_offset;
+ left = __copy_from_user(kaddr + offset, buf, bytes);
+ copied = bytes - left;
+ } else {
+ copied = __iovec_copy_from_user(kaddr + offset, iov,
+ i->iov_offset, bytes, 0);
+ }
+ kunmap(page);
+ return copied;
+}
+
+static void ii_iovec_advance(struct iov_iter *i, size_t bytes)
+{
+ BUG_ON(i->count < bytes);
+
+ if (likely(i->nr_segs == 1)) {
+ i->iov_offset += bytes;
+ i->count -= bytes;
+ } else {
+ struct iovec *iov = (struct iovec *)i->data;
+ size_t base = i->iov_offset;
+ unsigned long nr_segs = i->nr_segs;
+
+ /*
+ * The !iov->iov_len check ensures we skip over unlikely
+ * zero-length segments (without overruning the iovec).
+ */
+ while (bytes || unlikely(i->count && !iov->iov_len)) {
+ int copy;
+
+ copy = min(bytes, iov->iov_len - base);
+ BUG_ON(!i->count || i->count < copy);
+ i->count -= copy;
+ bytes -= copy;
+ base += copy;
+ if (iov->iov_len == base) {
+ iov++;
+ nr_segs--;
+ base = 0;
+ }
+ }
+ i->data = (unsigned long)iov;
+ i->iov_offset = base;
+ i->nr_segs = nr_segs;
+ }
+}
+
+/*
+ * Fault in the first iovec of the given iov_iter, to a maximum length
+ * of bytes. Returns 0 on success, or non-zero if the memory could not be
+ * accessed (ie. because it is an invalid address).
+ *
+ * writev-intensive code may want this to prefault several iovecs -- that
+ * would be possible (callers must not rely on the fact that _only_ the
+ * first iovec will be faulted with the current implementation).
+ */
+static int ii_iovec_fault_in_readable(struct iov_iter *i, size_t bytes)
+{
+ struct iovec *iov = (struct iovec *)i->data;
+ char __user *buf = iov->iov_base + i->iov_offset;
+ bytes = min(bytes, iov->iov_len - i->iov_offset);
+ return fault_in_pages_readable(buf, bytes);
+}
+
+/*
+ * Return the count of just the current iov_iter segment.
+ */
+static size_t ii_iovec_single_seg_count(const struct iov_iter *i)
+{
+ const struct iovec *iov = (struct iovec *)i->data;
+ if (i->nr_segs == 1)
+ return i->count;
+ else
+ return min(i->count, iov->iov_len - i->iov_offset);
+}
+
+static int ii_iovec_shorten(struct iov_iter *i, size_t count)
+{
+ struct iovec *iov = (struct iovec *)i->data;
+ i->nr_segs = iov_shorten(iov, i->nr_segs, count);
+ i->count = min(i->count, count);
+ return 0;
+}
+
+struct iov_iter_ops ii_iovec_ops = {
+ .ii_copy_to_user_atomic = ii_iovec_copy_to_user_atomic,
+ .ii_copy_to_user = ii_iovec_copy_to_user,
+ .ii_copy_from_user_atomic = ii_iovec_copy_from_user_atomic,
+ .ii_copy_from_user = ii_iovec_copy_from_user,
+ .ii_advance = ii_iovec_advance,
+ .ii_fault_in_readable = ii_iovec_fault_in_readable,
+ .ii_single_seg_count = ii_iovec_single_seg_count,
+ .ii_shorten = ii_iovec_shorten,
+};
+EXPORT_SYMBOL(ii_iovec_ops);
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 1506673c087e..1d7ab8b7d41e 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -51,10 +51,10 @@ const struct file_operations jffs2_file_operations =
{
.llseek = generic_file_llseek,
.open = generic_file_open,
- .read = do_sync_read,
- .aio_read = generic_file_aio_read,
- .write = do_sync_write,
- .aio_write = generic_file_aio_write,
+ .read = do_sync_read,
+ .read_iter = generic_file_read_iter,
+ .write = do_sync_write,
+ .write_iter = generic_file_write_iter,
.unlocked_ioctl=jffs2_ioctl,
.mmap = generic_file_readonly_mmap,
.fsync = jffs2_fsync,
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index dd7442c58358..040b6c7725ad 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -151,8 +151,8 @@ const struct file_operations jfs_file_operations = {
.llseek = generic_file_llseek,
.write = do_sync_write,
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
- .aio_write = generic_file_aio_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = generic_file_write_iter,
.mmap = generic_file_mmap,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index f4aab719add5..51652aaa3dc8 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -331,15 +331,14 @@ static sector_t jfs_bmap(struct address_space *mapping, sector_t block)
}
static ssize_t jfs_direct_IO(int rw, struct kiocb *iocb,
- const struct iovec *iov, loff_t offset, unsigned long nr_segs)
+ struct iov_iter *iter, loff_t offset)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
struct inode *inode = file->f_mapping->host;
ssize_t ret;
- ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
- jfs_get_block);
+ ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, jfs_get_block);
/*
* In case of error extending write may have instantiated a few
@@ -347,7 +346,7 @@ static ssize_t jfs_direct_IO(int rw, struct kiocb *iocb,
*/
if (unlikely((rw & WRITE) && ret < 0)) {
loff_t isize = i_size_read(inode);
- loff_t end = offset + iov_length(iov, nr_segs);
+ loff_t end = offset + iov_iter_count(iter);
if (end > isize)
jfs_write_failed(mapping, end);
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
index c1a3e603279c..7f464c513ba0 100644
--- a/fs/jfs/jfs_inode.c
+++ b/fs/jfs/jfs_inode.c
@@ -95,7 +95,7 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
if (insert_inode_locked(inode) < 0) {
rc = -EINVAL;
- goto fail_unlock;
+ goto fail_put;
}
inode_init_owner(inode, parent, mode);
@@ -156,7 +156,6 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
fail_drop:
dquot_drop(inode);
inode->i_flags |= S_NOQUOTA;
-fail_unlock:
clear_nlink(inode);
unlock_new_inode(inode);
fail_put:
diff --git a/fs/libfs.c b/fs/libfs.c
index 3a3a9b53bf5a..8c5018493154 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -10,6 +10,7 @@
#include <linux/vfs.h>
#include <linux/quotaops.h>
#include <linux/mutex.h>
+#include <linux/namei.h>
#include <linux/exportfs.h>
#include <linux/writeback.h>
#include <linux/buffer_head.h> /* sync_mapping_buffers */
@@ -31,6 +32,7 @@ int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
stat->blocks = inode->i_mapping->nrpages << (PAGE_CACHE_SHIFT - 9);
return 0;
}
+EXPORT_SYMBOL(simple_getattr);
int simple_statfs(struct dentry *dentry, struct kstatfs *buf)
{
@@ -39,6 +41,7 @@ int simple_statfs(struct dentry *dentry, struct kstatfs *buf)
buf->f_namelen = NAME_MAX;
return 0;
}
+EXPORT_SYMBOL(simple_statfs);
/*
* Retaining negative dentries for an in-memory filesystem just wastes
@@ -66,6 +69,7 @@ struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, unsigned
d_add(dentry, NULL);
return NULL;
}
+EXPORT_SYMBOL(simple_lookup);
int dcache_dir_open(struct inode *inode, struct file *file)
{
@@ -75,12 +79,14 @@ int dcache_dir_open(struct inode *inode, struct file *file)
return file->private_data ? 0 : -ENOMEM;
}
+EXPORT_SYMBOL(dcache_dir_open);
int dcache_dir_close(struct inode *inode, struct file *file)
{
dput(file->private_data);
return 0;
}
+EXPORT_SYMBOL(dcache_dir_close);
loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
{
@@ -123,6 +129,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
mutex_unlock(&dentry->d_inode->i_mutex);
return offset;
}
+EXPORT_SYMBOL(dcache_dir_lseek);
/* Relationship between i_mode and the DT_xxx types */
static inline unsigned char dt_type(struct inode *inode)
@@ -172,11 +179,13 @@ int dcache_readdir(struct file *file, struct dir_context *ctx)
spin_unlock(&dentry->d_lock);
return 0;
}
+EXPORT_SYMBOL(dcache_readdir);
ssize_t generic_read_dir(struct file *filp, char __user *buf, size_t siz, loff_t *ppos)
{
return -EISDIR;
}
+EXPORT_SYMBOL(generic_read_dir);
const struct file_operations simple_dir_operations = {
.open = dcache_dir_open,
@@ -186,10 +195,12 @@ const struct file_operations simple_dir_operations = {
.iterate = dcache_readdir,
.fsync = noop_fsync,
};
+EXPORT_SYMBOL(simple_dir_operations);
const struct inode_operations simple_dir_inode_operations = {
.lookup = simple_lookup,
};
+EXPORT_SYMBOL(simple_dir_inode_operations);
static const struct super_operations simple_super_operations = {
.statfs = simple_statfs,
@@ -244,6 +255,7 @@ Enomem:
deactivate_locked_super(s);
return ERR_PTR(-ENOMEM);
}
+EXPORT_SYMBOL(mount_pseudo);
int simple_open(struct inode *inode, struct file *file)
{
@@ -251,6 +263,7 @@ int simple_open(struct inode *inode, struct file *file)
file->private_data = inode->i_private;
return 0;
}
+EXPORT_SYMBOL(simple_open);
int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
{
@@ -263,6 +276,7 @@ int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *den
d_instantiate(dentry, inode);
return 0;
}
+EXPORT_SYMBOL(simple_link);
int simple_empty(struct dentry *dentry)
{
@@ -283,6 +297,7 @@ out:
spin_unlock(&dentry->d_lock);
return ret;
}
+EXPORT_SYMBOL(simple_empty);
int simple_unlink(struct inode *dir, struct dentry *dentry)
{
@@ -293,6 +308,7 @@ int simple_unlink(struct inode *dir, struct dentry *dentry)
dput(dentry);
return 0;
}
+EXPORT_SYMBOL(simple_unlink);
int simple_rmdir(struct inode *dir, struct dentry *dentry)
{
@@ -304,6 +320,7 @@ int simple_rmdir(struct inode *dir, struct dentry *dentry)
drop_nlink(dir);
return 0;
}
+EXPORT_SYMBOL(simple_rmdir);
int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
@@ -330,6 +347,7 @@ int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
return 0;
}
+EXPORT_SYMBOL(simple_rename);
/**
* simple_setattr - setattr for simple filesystem
@@ -370,6 +388,7 @@ int simple_readpage(struct file *file, struct page *page)
unlock_page(page);
return 0;
}
+EXPORT_SYMBOL(simple_readpage);
int simple_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
@@ -393,6 +412,7 @@ int simple_write_begin(struct file *file, struct address_space *mapping,
}
return 0;
}
+EXPORT_SYMBOL(simple_write_begin);
/**
* simple_write_end - .write_end helper for non-block-device FSes
@@ -444,6 +464,7 @@ int simple_write_end(struct file *file, struct address_space *mapping,
return copied;
}
+EXPORT_SYMBOL(simple_write_end);
/*
* the inodes created here are not hashed. If you use iunique to generate
@@ -512,6 +533,7 @@ out:
dput(root);
return -ENOMEM;
}
+EXPORT_SYMBOL(simple_fill_super);
static DEFINE_SPINLOCK(pin_fs_lock);
@@ -534,6 +556,7 @@ int simple_pin_fs(struct file_system_type *type, struct vfsmount **mount, int *c
mntput(mnt);
return 0;
}
+EXPORT_SYMBOL(simple_pin_fs);
void simple_release_fs(struct vfsmount **mount, int *count)
{
@@ -545,6 +568,7 @@ void simple_release_fs(struct vfsmount **mount, int *count)
spin_unlock(&pin_fs_lock);
mntput(mnt);
}
+EXPORT_SYMBOL(simple_release_fs);
/**
* simple_read_from_buffer - copy data from the buffer to user space
@@ -579,6 +603,7 @@ ssize_t simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos,
*ppos = pos + count;
return count;
}
+EXPORT_SYMBOL(simple_read_from_buffer);
/**
* simple_write_to_buffer - copy data from user space to the buffer
@@ -613,6 +638,7 @@ ssize_t simple_write_to_buffer(void *to, size_t available, loff_t *ppos,
*ppos = pos + count;
return count;
}
+EXPORT_SYMBOL(simple_write_to_buffer);
/**
* memory_read_from_buffer - copy data from the buffer
@@ -644,6 +670,7 @@ ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos,
return count;
}
+EXPORT_SYMBOL(memory_read_from_buffer);
/*
* Transaction based IO.
@@ -665,6 +692,7 @@ void simple_transaction_set(struct file *file, size_t n)
smp_mb();
ar->size = n;
}
+EXPORT_SYMBOL(simple_transaction_set);
char *simple_transaction_get(struct file *file, const char __user *buf, size_t size)
{
@@ -696,6 +724,7 @@ char *simple_transaction_get(struct file *file, const char __user *buf, size_t s
return ar->data;
}
+EXPORT_SYMBOL(simple_transaction_get);
ssize_t simple_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
{
@@ -705,12 +734,14 @@ ssize_t simple_transaction_read(struct file *file, char __user *buf, size_t size
return 0;
return simple_read_from_buffer(buf, size, pos, ar->data, ar->size);
}
+EXPORT_SYMBOL(simple_transaction_read);
int simple_transaction_release(struct inode *inode, struct file *file)
{
free_page((unsigned long)file->private_data);
return 0;
}
+EXPORT_SYMBOL(simple_transaction_release);
/* Simple attribute files */
@@ -746,12 +777,14 @@ int simple_attr_open(struct inode *inode, struct file *file,
return nonseekable_open(inode, file);
}
+EXPORT_SYMBOL_GPL(simple_attr_open);
int simple_attr_release(struct inode *inode, struct file *file)
{
kfree(file->private_data);
return 0;
}
+EXPORT_SYMBOL_GPL(simple_attr_release); /* GPL-only? This? Really? */
/* read from the buffer that is filled with the get function */
ssize_t simple_attr_read(struct file *file, char __user *buf,
@@ -787,6 +820,7 @@ out:
mutex_unlock(&attr->mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(simple_attr_read);
/* interpret the buffer as a number to call the set function with */
ssize_t simple_attr_write(struct file *file, const char __user *buf,
@@ -819,6 +853,7 @@ out:
mutex_unlock(&attr->mutex);
return ret;
}
+EXPORT_SYMBOL_GPL(simple_attr_write);
/**
* generic_fh_to_dentry - generic helper for the fh_to_dentry export operation
@@ -957,39 +992,13 @@ int noop_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{
return 0;
}
-
-EXPORT_SYMBOL(dcache_dir_close);
-EXPORT_SYMBOL(dcache_dir_lseek);
-EXPORT_SYMBOL(dcache_dir_open);
-EXPORT_SYMBOL(dcache_readdir);
-EXPORT_SYMBOL(generic_read_dir);
-EXPORT_SYMBOL(mount_pseudo);
-EXPORT_SYMBOL(simple_write_begin);
-EXPORT_SYMBOL(simple_write_end);
-EXPORT_SYMBOL(simple_dir_inode_operations);
-EXPORT_SYMBOL(simple_dir_operations);
-EXPORT_SYMBOL(simple_empty);
-EXPORT_SYMBOL(simple_fill_super);
-EXPORT_SYMBOL(simple_getattr);
-EXPORT_SYMBOL(simple_open);
-EXPORT_SYMBOL(simple_link);
-EXPORT_SYMBOL(simple_lookup);
-EXPORT_SYMBOL(simple_pin_fs);
-EXPORT_SYMBOL(simple_readpage);
-EXPORT_SYMBOL(simple_release_fs);
-EXPORT_SYMBOL(simple_rename);
-EXPORT_SYMBOL(simple_rmdir);
-EXPORT_SYMBOL(simple_statfs);
EXPORT_SYMBOL(noop_fsync);
-EXPORT_SYMBOL(simple_unlink);
-EXPORT_SYMBOL(simple_read_from_buffer);
-EXPORT_SYMBOL(simple_write_to_buffer);
-EXPORT_SYMBOL(memory_read_from_buffer);
-EXPORT_SYMBOL(simple_transaction_set);
-EXPORT_SYMBOL(simple_transaction_get);
-EXPORT_SYMBOL(simple_transaction_read);
-EXPORT_SYMBOL(simple_transaction_release);
-EXPORT_SYMBOL_GPL(simple_attr_open);
-EXPORT_SYMBOL_GPL(simple_attr_release);
-EXPORT_SYMBOL_GPL(simple_attr_read);
-EXPORT_SYMBOL_GPL(simple_attr_write);
+
+void kfree_put_link(struct dentry *dentry, struct nameidata *nd,
+ void *cookie)
+{
+ char *s = nd_get_link(nd);
+ if (!IS_ERR(s))
+ kfree(s);
+}
+EXPORT_SYMBOL(kfree_put_link);
diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c
index 9c501449450d..427bb73e298f 100644
--- a/fs/logfs/dev_mtd.c
+++ b/fs/logfs/dev_mtd.c
@@ -245,8 +245,8 @@ static int logfs_mtd_can_write_buf(struct super_block *sb, u64 ofs)
goto out;
if (memchr_inv(buf, 0xff, super->s_writesize))
err = -EIO;
- kfree(buf);
out:
+ kfree(buf);
return err;
}
diff --git a/fs/logfs/file.c b/fs/logfs/file.c
index 57914fc32b62..57f994e887b5 100644
--- a/fs/logfs/file.c
+++ b/fs/logfs/file.c
@@ -264,8 +264,8 @@ const struct inode_operations logfs_reg_iops = {
};
const struct file_operations logfs_reg_fops = {
- .aio_read = generic_file_aio_read,
- .aio_write = generic_file_aio_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = generic_file_write_iter,
.fsync = logfs_fsync,
.unlocked_ioctl = logfs_ioctl,
.llseek = generic_file_llseek,
diff --git a/fs/logfs/super.c b/fs/logfs/super.c
index 54360293bcb5..b256c0690e5b 100644
--- a/fs/logfs/super.c
+++ b/fs/logfs/super.c
@@ -287,14 +287,14 @@ static int logfs_make_writeable(struct super_block *sb)
if (err)
return err;
+ /* Do one GC pass before any data gets dirtied */
+ logfs_gc_pass(sb);
+
/* Check areas for trailing unaccounted data */
err = logfs_check_areas(sb);
if (err)
return err;
- /* Do one GC pass before any data gets dirtied */
- logfs_gc_pass(sb);
-
/* after all initializations are done, replay the journal
* for rw-mounts, if necessary */
err = logfs_replay_journal(sb);
diff --git a/fs/minix/Kconfig b/fs/minix/Kconfig
index 6624684dd5de..f2a0cfcef11d 100644
--- a/fs/minix/Kconfig
+++ b/fs/minix/Kconfig
@@ -18,7 +18,7 @@ config MINIX_FS
config MINIX_FS_NATIVE_ENDIAN
def_bool MINIX_FS
- depends on H8300 || M32R || MICROBLAZE || MIPS || S390 || SUPERH || SPARC || XTENSA || (M68K && !MMU)
+ depends on M32R || MICROBLAZE || MIPS || S390 || SUPERH || SPARC || XTENSA || (M68K && !MMU)
config MINIX_FS_BIG_ENDIAN_16BIT_INDEXED
def_bool MINIX_FS
diff --git a/fs/minix/file.c b/fs/minix/file.c
index adc6f5494231..346d8f37d342 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -15,9 +15,9 @@
const struct file_operations minix_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.write = do_sync_write,
- .aio_write = generic_file_aio_write,
+ .write_iter = generic_file_write_iter,
.mmap = generic_file_mmap,
.fsync = generic_file_fsync,
.splice_read = generic_file_splice_read,
diff --git a/fs/namespace.c b/fs/namespace.c
index da5c49483430..3ee6e59ead55 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -39,7 +39,7 @@ static int mnt_group_start = 1;
static struct list_head *mount_hashtable __read_mostly;
static struct list_head *mountpoint_hashtable __read_mostly;
static struct kmem_cache *mnt_cache __read_mostly;
-static struct rw_semaphore namespace_sem;
+static DECLARE_RWSEM(namespace_sem);
/* /sys/fs */
struct kobject *fs_kobj;
@@ -1849,14 +1849,10 @@ static int do_remount(struct path *path, int flags, int mnt_flags,
br_write_lock(&vfsmount_lock);
mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK;
mnt->mnt.mnt_flags = mnt_flags;
- br_write_unlock(&vfsmount_lock);
- }
- up_write(&sb->s_umount);
- if (!err) {
- br_write_lock(&vfsmount_lock);
touch_mnt_namespace(mnt->mnt_ns);
br_write_unlock(&vfsmount_lock);
}
+ up_write(&sb->s_umount);
return err;
}
@@ -2444,9 +2440,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
return ERR_CAST(new);
}
new_ns->root = new;
- br_write_lock(&vfsmount_lock);
list_add_tail(&new_ns->list, &new->mnt_list);
- br_write_unlock(&vfsmount_lock);
/*
* Second pass: switch the tsk->fs->* elements and mark new vfsmounts
@@ -2767,8 +2761,6 @@ void __init mnt_init(void)
unsigned u;
int err;
- init_rwsem(&namespace_sem);
-
mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct mount),
0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
@@ -2802,11 +2794,7 @@ void put_mnt_ns(struct mnt_namespace *ns)
{
if (!atomic_dec_and_test(&ns->count))
return;
- namespace_lock();
- br_write_lock(&vfsmount_lock);
- umount_tree(ns->root, 0);
- br_write_unlock(&vfsmount_lock);
- namespace_unlock();
+ drop_collected_mounts(&ns->root->mnt);
free_mnt_ns(ns);
}
@@ -2875,7 +2863,7 @@ bool fs_fully_visible(struct file_system_type *type)
if (unlikely(!ns))
return false;
- namespace_lock();
+ down_read(&namespace_sem);
list_for_each_entry(mnt, &ns->list, mnt_list) {
struct mount *child;
if (mnt->mnt.mnt_sb->s_type != type)
@@ -2896,7 +2884,7 @@ bool fs_fully_visible(struct file_system_type *type)
next: ;
}
found:
- namespace_unlock();
+ up_read(&namespace_sem);
return visible;
}
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 3be047474bfc..c320ac52353e 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -339,9 +339,8 @@ ncp_lookup_validate(struct dentry *dentry, unsigned int flags)
if (val)
goto finished;
- DDPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld, server lookup\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- NCP_GET_AGE(dentry));
+ DDPRINTK("ncp_lookup_validate: %pd2 not valid, age=%ld, server lookup\n",
+ dentry, NCP_GET_AGE(dentry));
len = sizeof(__name);
if (ncp_is_server_root(dir)) {
@@ -359,8 +358,8 @@ ncp_lookup_validate(struct dentry *dentry, unsigned int flags)
res = ncp_obtain_info(server, dir, __name, &(finfo.i));
}
finfo.volume = finfo.i.volNumber;
- DDPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
- dentry->d_parent->d_name.name, __name, res);
+ DDPRINTK("ncp_lookup_validate: looked for %pd/%s, res=%d\n",
+ dentry->d_parent, __name, res);
/*
* If we didn't find it, or if it has a different dirEntNum to
* what we remember, it's not valid any more.
@@ -454,8 +453,7 @@ static int ncp_readdir(struct file *file, struct dir_context *ctx)
ctl.page = NULL;
ctl.cache = NULL;
- DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
+ DDPRINTK("ncp_readdir: reading %pD2, pos=%d\n", file,
(int) ctx->pos);
result = -EIO;
@@ -740,12 +738,10 @@ ncp_do_readdir(struct file *file, struct dir_context *ctx,
int more;
size_t bufsize;
- DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
+ DPRINTK("ncp_do_readdir: %pD2, fpos=%ld\n", file,
(unsigned long) ctx->pos);
- PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",
- dentry->d_name.name, NCP_FINFO(dir)->volNumber,
- NCP_FINFO(dir)->dirEntNum);
+ PPRINTK("ncp_do_readdir: init %pD, volnum=%d, dirent=%u\n",
+ file, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum);
err = ncp_initialize_search(server, dir, &seq);
if (err) {
@@ -850,8 +846,7 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsig
if (!ncp_conn_valid(server))
goto finished;
- PPRINTK("ncp_lookup: server lookup for %s/%s\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ PPRINTK("ncp_lookup: server lookup for %pd2\n", dentry);
len = sizeof(__name);
if (ncp_is_server_root(dir)) {
@@ -867,8 +862,7 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsig
if (!res)
res = ncp_obtain_info(server, dir, __name, &(finfo.i));
}
- PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n",
- dentry->d_parent->d_name.name, __name, res);
+ PPRINTK("ncp_lookup: looked for %pd2, res=%d\n", dentry, res);
/*
* If we didn't find an entry, make a negative dentry.
*/
@@ -915,8 +909,7 @@ out:
return error;
out_close:
- PPRINTK("ncp_instantiate: %s/%s failed, closing file\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ PPRINTK("ncp_instantiate: %pd2 failed, closing file\n", dentry);
ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
goto out;
}
@@ -930,8 +923,7 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode,
int opmode;
__u8 __name[NCP_MAXPATHLEN + 1];
- PPRINTK("ncp_create_new: creating %s/%s, mode=%hx\n",
- dentry->d_parent->d_name.name, dentry->d_name.name, mode);
+ PPRINTK("ncp_create_new: creating %pd2, mode=%hx\n", dentry, mode);
ncp_age_dentry(server, dentry);
len = sizeof(__name);
@@ -960,8 +952,7 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode,
error = -ENAMETOOLONG;
else if (result < 0)
error = result;
- DPRINTK("ncp_create: %s/%s failed\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ DPRINTK("ncp_create: %pd2 failed\n", dentry);
goto out;
}
opmode = O_WRONLY;
@@ -994,8 +985,7 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
int error, len;
__u8 __name[NCP_MAXPATHLEN + 1];
- DPRINTK("ncp_mkdir: making %s/%s\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ DPRINTK("ncp_mkdir: making %pd2\n", dentry);
ncp_age_dentry(server, dentry);
len = sizeof(__name);
@@ -1032,8 +1022,7 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
int error, result, len;
__u8 __name[NCP_MAXPATHLEN + 1];
- DPRINTK("ncp_rmdir: removing %s/%s\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ DPRINTK("ncp_rmdir: removing %pd2\n", dentry);
len = sizeof(__name);
error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
@@ -1078,8 +1067,7 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry)
int error;
server = NCP_SERVER(dir);
- DPRINTK("ncp_unlink: unlinking %s/%s\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ DPRINTK("ncp_unlink: unlinking %pd2\n", dentry);
/*
* Check whether to close the file ...
@@ -1099,8 +1087,7 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry)
#endif
switch (error) {
case 0x00:
- DPRINTK("ncp: removed %s/%s\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ DPRINTK("ncp: removed %pd2\n", dentry);
break;
case 0x85:
case 0x8A:
@@ -1133,9 +1120,7 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
int old_len, new_len;
__u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
- DPRINTK("ncp_rename: %s/%s to %s/%s\n",
- old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
- new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
+ DPRINTK("ncp_rename: %pd2 to %pd2\n", old_dentry, new_dentry);
ncp_age_dentry(server, old_dentry);
ncp_age_dentry(server, new_dentry);
@@ -1165,8 +1150,8 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
#endif
switch (error) {
case 0x00:
- DPRINTK("ncp renamed %s -> %s.\n",
- old_dentry->d_name.name,new_dentry->d_name.name);
+ DPRINTK("ncp renamed %pd -> %pd.\n",
+ old_dentry, new_dentry);
break;
case 0x9E:
error = -ENAMETOOLONG;
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index 122e260247f5..8f5074e1ecb9 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -107,8 +107,7 @@ ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
void* freepage;
size_t freelen;
- DPRINTK("ncp_file_read: enter %s/%s\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ DPRINTK("ncp_file_read: enter %pd2\n", dentry);
pos = *ppos;
@@ -166,8 +165,7 @@ ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
file_accessed(file);
- DPRINTK("ncp_file_read: exit %s/%s\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ DPRINTK("ncp_file_read: exit %pd2\n", dentry);
outrel:
ncp_inode_close(inode);
return already_read ? already_read : error;
@@ -184,8 +182,7 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
int errno;
void* bouncebuffer;
- DPRINTK("ncp_file_write: enter %s/%s\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ DPRINTK("ncp_file_write: enter %pd2\n", dentry);
if ((ssize_t) count < 0)
return -EINVAL;
pos = *ppos;
@@ -264,8 +261,7 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
i_size_write(inode, pos);
mutex_unlock(&inode->i_mutex);
}
- DPRINTK("ncp_file_write: exit %s/%s\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ DPRINTK("ncp_file_write: exit %pd2\n", dentry);
outrel:
ncp_inode_close(inode);
return already_written ? already_written : errno;
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 854a8f05a610..006e744541b3 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -98,9 +98,7 @@ nfs_opendir(struct inode *inode, struct file *filp)
struct nfs_open_dir_context *ctx;
struct rpc_cred *cred;
- dfprintk(FILE, "NFS: open dir(%s/%s)\n",
- filp->f_path.dentry->d_parent->d_name.name,
- filp->f_path.dentry->d_name.name);
+ dfprintk(FILE, "NFS: open dir(%pD2)\n", filp);
nfs_inc_stats(inode, NFSIOS_VFSOPEN);
@@ -297,11 +295,10 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des
if (ctx->duped > 0
&& ctx->dup_cookie == *desc->dir_cookie) {
if (printk_ratelimit()) {
- pr_notice("NFS: directory %s/%s contains a readdir loop."
+ pr_notice("NFS: directory %pD2 contains a readdir loop."
"Please contact your server vendor. "
"The file: %s has duplicate cookie %llu\n",
- desc->file->f_dentry->d_parent->d_name.name,
- desc->file->f_dentry->d_name.name,
+ desc->file,
array->array[i].string.name,
*desc->dir_cookie);
}
@@ -822,9 +819,8 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx)
struct nfs_open_dir_context *dir_ctx = file->private_data;
int res = 0;
- dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- (long long)ctx->pos);
+ dfprintk(FILE, "NFS: readdir(%pD2) starting at cookie %llu\n",
+ file, (long long)ctx->pos);
nfs_inc_stats(inode, NFSIOS_VFSGETDENTS);
/*
@@ -880,22 +876,17 @@ out:
nfs_unblock_sillyrename(dentry);
if (res > 0)
res = 0;
- dfprintk(FILE, "NFS: readdir(%s/%s) returns %d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- res);
+ dfprintk(FILE, "NFS: readdir(%pD2) returns %d\n", file, res);
return res;
}
static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence)
{
- struct dentry *dentry = filp->f_path.dentry;
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = file_inode(filp);
struct nfs_open_dir_context *dir_ctx = filp->private_data;
- dfprintk(FILE, "NFS: llseek dir(%s/%s, %lld, %d)\n",
- dentry->d_parent->d_name.name,
- dentry->d_name.name,
- offset, whence);
+ dfprintk(FILE, "NFS: llseek dir(%pD2, %lld, %d)\n",
+ filp, offset, whence);
mutex_lock(&inode->i_mutex);
switch (whence) {
@@ -925,15 +916,12 @@ out:
static int nfs_fsync_dir(struct file *filp, loff_t start, loff_t end,
int datasync)
{
- struct dentry *dentry = filp->f_path.dentry;
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = file_inode(filp);
- dfprintk(FILE, "NFS: fsync dir(%s/%s) datasync %d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- datasync);
+ dfprintk(FILE, "NFS: fsync dir(%pD2) datasync %d\n", filp, datasync);
mutex_lock(&inode->i_mutex);
- nfs_inc_stats(dentry->d_inode, NFSIOS_VFSFSYNC);
+ nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
mutex_unlock(&inode->i_mutex);
return 0;
}
@@ -1073,9 +1061,8 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
}
if (is_bad_inode(inode)) {
- dfprintk(LOOKUPCACHE, "%s: %s/%s has dud inode\n",
- __func__, dentry->d_parent->d_name.name,
- dentry->d_name.name);
+ dfprintk(LOOKUPCACHE, "%s: %pd2 has dud inode\n",
+ __func__, dentry);
goto out_bad;
}
@@ -1125,9 +1112,8 @@ out_set_verifier:
nfs_advise_use_readdirplus(dir);
out_valid_noent:
dput(parent);
- dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is valid\n",
- __func__, dentry->d_parent->d_name.name,
- dentry->d_name.name);
+ dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) is valid\n",
+ __func__, dentry);
return 1;
out_zap_parent:
nfs_zap_caches(dir);
@@ -1147,18 +1133,16 @@ out_zap_parent:
goto out_valid;
dput(parent);
- dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n",
- __func__, dentry->d_parent->d_name.name,
- dentry->d_name.name);
+ dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) is invalid\n",
+ __func__, dentry);
return 0;
out_error:
nfs_free_fattr(fattr);
nfs_free_fhandle(fhandle);
nfs4_label_free(label);
dput(parent);
- dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n",
- __func__, dentry->d_parent->d_name.name,
- dentry->d_name.name, error);
+ dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) lookup returned error %d\n",
+ __func__, dentry, error);
return error;
}
@@ -1182,16 +1166,14 @@ static int nfs_weak_revalidate(struct dentry *dentry, unsigned int flags)
* eventually need to do something more here.
*/
if (!inode) {
- dfprintk(LOOKUPCACHE, "%s: %s/%s has negative inode\n",
- __func__, dentry->d_parent->d_name.name,
- dentry->d_name.name);
+ dfprintk(LOOKUPCACHE, "%s: %pd2 has negative inode\n",
+ __func__, dentry);
return 1;
}
if (is_bad_inode(inode)) {
- dfprintk(LOOKUPCACHE, "%s: %s/%s has dud inode\n",
- __func__, dentry->d_parent->d_name.name,
- dentry->d_name.name);
+ dfprintk(LOOKUPCACHE, "%s: %pd2 has dud inode\n",
+ __func__, dentry);
return 0;
}
@@ -1206,9 +1188,8 @@ static int nfs_weak_revalidate(struct dentry *dentry, unsigned int flags)
*/
static int nfs_dentry_delete(const struct dentry *dentry)
{
- dfprintk(VFS, "NFS: dentry_delete(%s/%s, %x)\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- dentry->d_flags);
+ dfprintk(VFS, "NFS: dentry_delete(%pd2, %x)\n",
+ dentry, dentry->d_flags);
/* Unhash any dentry with a stale inode */
if (dentry->d_inode != NULL && NFS_STALE(dentry->d_inode))
@@ -1286,8 +1267,7 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in
struct nfs4_label *label = NULL;
int error;
- dfprintk(VFS, "NFS: lookup(%s/%s)\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ dfprintk(VFS, "NFS: lookup(%pd2)\n", dentry);
nfs_inc_stats(dir, NFSIOS_VFSLOOKUP);
res = ERR_PTR(-ENAMETOOLONG);
@@ -1381,7 +1361,7 @@ static struct nfs_open_context *create_nfs_open_context(struct dentry *dentry, i
static int do_open(struct inode *inode, struct file *filp)
{
- nfs_fscache_set_inode_cookie(inode, filp);
+ nfs_fscache_open_file(inode, filp);
return 0;
}
@@ -1418,8 +1398,8 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
/* Expect a negative dentry */
BUG_ON(dentry->d_inode);
- dfprintk(VFS, "NFS: atomic_open(%s/%ld), %s\n",
- dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
+ dfprintk(VFS, "NFS: atomic_open(%s/%ld), %pd\n",
+ dir->i_sb->s_id, dir->i_ino, dentry);
err = nfs_check_flags(open_flags);
if (err)
@@ -1608,8 +1588,8 @@ int nfs_create(struct inode *dir, struct dentry *dentry,
int open_flags = excl ? O_CREAT | O_EXCL : O_CREAT;
int error;
- dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
- dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
+ dfprintk(VFS, "NFS: create(%s/%ld), %pd\n",
+ dir->i_sb->s_id, dir->i_ino, dentry);
attr.ia_mode = mode;
attr.ia_valid = ATTR_MODE;
@@ -1635,8 +1615,8 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
struct iattr attr;
int status;
- dfprintk(VFS, "NFS: mknod(%s/%ld), %s\n",
- dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
+ dfprintk(VFS, "NFS: mknod(%s/%ld), %pd\n",
+ dir->i_sb->s_id, dir->i_ino, dentry);
if (!new_valid_dev(rdev))
return -EINVAL;
@@ -1664,8 +1644,8 @@ int nfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
struct iattr attr;
int error;
- dfprintk(VFS, "NFS: mkdir(%s/%ld), %s\n",
- dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
+ dfprintk(VFS, "NFS: mkdir(%s/%ld), %pd\n",
+ dir->i_sb->s_id, dir->i_ino, dentry);
attr.ia_valid = ATTR_MODE;
attr.ia_mode = mode | S_IFDIR;
@@ -1692,8 +1672,8 @@ int nfs_rmdir(struct inode *dir, struct dentry *dentry)
{
int error;
- dfprintk(VFS, "NFS: rmdir(%s/%ld), %s\n",
- dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
+ dfprintk(VFS, "NFS: rmdir(%s/%ld), %pd\n",
+ dir->i_sb->s_id, dir->i_ino, dentry);
trace_nfs_rmdir_enter(dir, dentry);
if (dentry->d_inode) {
@@ -1728,8 +1708,7 @@ static int nfs_safe_remove(struct dentry *dentry)
struct inode *inode = dentry->d_inode;
int error = -EBUSY;
- dfprintk(VFS, "NFS: safe_remove(%s/%s)\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ dfprintk(VFS, "NFS: safe_remove(%pd2)\n", dentry);
/* If the dentry was sillyrenamed, we simply call d_delete() */
if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
@@ -1762,8 +1741,8 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry)
int error;
int need_rehash = 0;
- dfprintk(VFS, "NFS: unlink(%s/%ld, %s)\n", dir->i_sb->s_id,
- dir->i_ino, dentry->d_name.name);
+ dfprintk(VFS, "NFS: unlink(%s/%ld, %pd)\n", dir->i_sb->s_id,
+ dir->i_ino, dentry);
trace_nfs_unlink_enter(dir, dentry);
spin_lock(&dentry->d_lock);
@@ -1813,8 +1792,8 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
unsigned int pathlen = strlen(symname);
int error;
- dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id,
- dir->i_ino, dentry->d_name.name, symname);
+ dfprintk(VFS, "NFS: symlink(%s/%ld, %pd, %s)\n", dir->i_sb->s_id,
+ dir->i_ino, dentry, symname);
if (pathlen > PAGE_SIZE)
return -ENAMETOOLONG;
@@ -1836,9 +1815,9 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr);
trace_nfs_symlink_exit(dir, dentry, error);
if (error != 0) {
- dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n",
+ dfprintk(VFS, "NFS: symlink(%s/%ld, %pd, %s) error %d\n",
dir->i_sb->s_id, dir->i_ino,
- dentry->d_name.name, symname, error);
+ dentry, symname, error);
d_drop(dentry);
__free_page(page);
return error;
@@ -1865,9 +1844,8 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
struct inode *inode = old_dentry->d_inode;
int error;
- dfprintk(VFS, "NFS: link(%s/%s -> %s/%s)\n",
- old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ dfprintk(VFS, "NFS: link(%pd2 -> %pd2)\n",
+ old_dentry, dentry);
trace_nfs_link_enter(inode, dir, dentry);
NFS_PROTO(inode)->return_delegation(inode);
@@ -1915,9 +1893,8 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct dentry *dentry = NULL, *rehash = NULL;
int error = -EBUSY;
- dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n",
- old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
- new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
+ dfprintk(VFS, "NFS: rename(%pd2 -> %pd2, ct=%d)\n",
+ old_dentry, new_dentry,
d_count(new_dentry));
trace_nfs_rename_enter(old_dir, old_dentry, new_dir, new_dentry);
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 91ff089d3412..87a6475eb170 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -90,6 +90,7 @@ struct nfs_direct_req {
int flags;
#define NFS_ODIRECT_DO_COMMIT (1) /* an unstable reply was received */
#define NFS_ODIRECT_RESCHED_WRITES (2) /* write verification failed */
+#define NFS_ODIRECT_MARK_DIRTY (4) /* mark read pages dirty */
struct nfs_writeverf verf; /* unstable write verifier */
};
@@ -112,32 +113,22 @@ static inline int put_dreq(struct nfs_direct_req *dreq)
* nfs_direct_IO - NFS address space operation for direct I/O
* @rw: direction (read or write)
* @iocb: target I/O control block
- * @iov: array of vectors that define I/O buffer
+ * @iter: array of vectors that define I/O buffer
* @pos: offset in file to begin the operation
* @nr_segs: size of iovec array
*
* The presence of this routine in the address space ops vector means
- * the NFS client supports direct I/O. However, for most direct IO, we
- * shunt off direct read and write requests before the VFS gets them,
- * so this method is only ever called for swap.
+ * the NFS client supports direct I/O. However, we shunt off direct
+ * read and write requests before the VFS gets them, so this method
+ * should never be called.
*/
-ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs)
+ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos)
{
-#ifndef CONFIG_NFS_SWAP
- dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n",
- iocb->ki_filp->f_path.dentry->d_name.name,
- (long long) pos, nr_segs);
+ dprintk("NFS: nfs_direct_IO (%pD) off/no(%Ld/%lu) EINVAL\n",
+ iocb->ki_filp, (long long) pos, iter->nr_segs);
return -EINVAL;
-#else
- VM_BUG_ON(iocb->ki_nbytes != PAGE_SIZE);
-
- if (rw == READ || rw == KERNEL_READ)
- return nfs_file_direct_read(iocb, iov, nr_segs, pos,
- rw == READ ? true : false);
- return nfs_file_direct_write(iocb, iov, nr_segs, pos,
- rw == WRITE ? true : false);
-#endif /* CONFIG_NFS_SWAP */
}
static void nfs_direct_release_pages(struct page **pages, unsigned int npages)
@@ -265,7 +256,8 @@ static void nfs_direct_read_completion(struct nfs_pgio_header *hdr)
struct nfs_page *req = nfs_list_entry(hdr->pages.next);
struct page *page = req->wb_page;
- if (!PageCompound(page) && bytes < hdr->good_bytes)
+ if ((dreq->flags & NFS_ODIRECT_MARK_DIRTY) &&
+ !PageCompound(page) && bytes < hdr->good_bytes)
set_page_dirty(page);
bytes += req->wb_bytes;
nfs_list_remove_request(req);
@@ -308,7 +300,7 @@ static const struct nfs_pgio_completion_ops nfs_direct_read_completion_ops = {
*/
static ssize_t nfs_direct_read_schedule_segment(struct nfs_pageio_descriptor *desc,
const struct iovec *iov,
- loff_t pos, bool uio)
+ loff_t pos)
{
struct nfs_direct_req *dreq = desc->pg_dreq;
struct nfs_open_context *ctx = dreq->ctx;
@@ -336,20 +328,12 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_pageio_descriptor *de
GFP_KERNEL);
if (!pagevec)
break;
- if (uio) {
- down_read(&current->mm->mmap_sem);
- result = get_user_pages(current, current->mm, user_addr,
+ down_read(&current->mm->mmap_sem);
+ result = get_user_pages(current, current->mm, user_addr,
npages, 1, 0, pagevec, NULL);
- up_read(&current->mm->mmap_sem);
- if (result < 0)
- break;
- } else {
- WARN_ON(npages != 1);
- result = get_kernel_page(user_addr, 1, pagevec);
- if (WARN_ON(result != 1))
- break;
- }
-
+ up_read(&current->mm->mmap_sem);
+ if (result < 0)
+ break;
if ((unsigned)result < npages) {
bytes = result * PAGE_SIZE;
if (bytes <= pgbase) {
@@ -397,24 +381,17 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_pageio_descriptor *de
return result < 0 ? (ssize_t) result : -EFAULT;
}
-static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
- const struct iovec *iov,
- unsigned long nr_segs,
- loff_t pos, bool uio)
+static ssize_t nfs_direct_do_schedule_read_iovec(
+ struct nfs_pageio_descriptor *desc, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
- struct nfs_pageio_descriptor desc;
ssize_t result = -EINVAL;
size_t requested_bytes = 0;
unsigned long seg;
- NFS_PROTO(dreq->inode)->read_pageio_init(&desc, dreq->inode,
- &nfs_direct_read_completion_ops);
- get_dreq(dreq);
- desc.pg_dreq = dreq;
-
for (seg = 0; seg < nr_segs; seg++) {
const struct iovec *vec = &iov[seg];
- result = nfs_direct_read_schedule_segment(&desc, vec, pos, uio);
+ result = nfs_direct_read_schedule_segment(desc, vec, pos);
if (result < 0)
break;
requested_bytes += result;
@@ -422,6 +399,75 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
break;
pos += vec->iov_len;
}
+ if (requested_bytes)
+ return requested_bytes;
+
+ return result < 0 ? result : -EIO;
+}
+
+#ifdef CONFIG_BLOCK
+static ssize_t nfs_direct_do_schedule_read_bvec(
+ struct nfs_pageio_descriptor *desc,
+ struct bio_vec *bvec, unsigned long nr_segs, loff_t pos)
+{
+ struct nfs_direct_req *dreq = desc->pg_dreq;
+ struct nfs_open_context *ctx = dreq->ctx;
+ struct inode *inode = ctx->dentry->d_inode;
+ ssize_t result = -EINVAL;
+ size_t requested_bytes = 0;
+ unsigned long seg;
+ struct nfs_page *req;
+ unsigned int req_len;
+
+ for (seg = 0; seg < nr_segs; seg++) {
+ result = -EIO;
+ req_len = bvec[seg].bv_len;
+ req = nfs_create_request(ctx, inode,
+ bvec[seg].bv_page,
+ bvec[seg].bv_offset, req_len);
+ if (IS_ERR(req)) {
+ result = PTR_ERR(req);
+ break;
+ }
+ req->wb_index = pos >> PAGE_SHIFT;
+ req->wb_offset = pos & ~PAGE_MASK;
+ if (!nfs_pageio_add_request(desc, req)) {
+ result = desc->pg_error;
+ nfs_release_request(req);
+ break;
+ }
+ requested_bytes += req_len;
+ pos += req_len;
+ }
+
+ if (requested_bytes)
+ return requested_bytes;
+
+ return result < 0 ? result : -EIO;
+}
+#endif /* CONFIG_BLOCK */
+
+static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq,
+ struct iov_iter *iter, loff_t pos)
+{
+ struct nfs_pageio_descriptor desc;
+ ssize_t result;
+
+ NFS_PROTO(dreq->inode)->read_pageio_init(&desc, dreq->inode,
+ &nfs_direct_read_completion_ops);
+ get_dreq(dreq);
+ desc.pg_dreq = dreq;
+
+ if (iov_iter_has_iovec(iter)) {
+ result = nfs_direct_do_schedule_read_iovec(&desc,
+ iov_iter_iovec(iter), iter->nr_segs, pos);
+#ifdef CONFIG_BLOCK
+ } else if (iov_iter_has_bvec(iter)) {
+ result = nfs_direct_do_schedule_read_bvec(&desc,
+ iov_iter_bvec(iter), iter->nr_segs, pos);
+#endif
+ } else
+ BUG();
nfs_pageio_complete(&desc);
@@ -429,9 +475,9 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
* If no bytes were started, return the error, and let the
* generic layer handle the completion.
*/
- if (requested_bytes == 0) {
+ if (result < 0) {
nfs_direct_req_release(dreq);
- return result < 0 ? result : -EIO;
+ return result;
}
if (put_dreq(dreq))
@@ -439,8 +485,8 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
return 0;
}
-static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos, bool uio)
+static ssize_t nfs_direct_read(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos)
{
ssize_t result = -ENOMEM;
struct inode *inode = iocb->ki_filp->f_mapping->host;
@@ -452,7 +498,7 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov,
goto out;
dreq->inode = inode;
- dreq->bytes_left = iov_length(iov, nr_segs);
+ dreq->bytes_left = iov_iter_count(iter);
dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
l_ctx = nfs_get_lock_context(dreq->ctx);
if (IS_ERR(l_ctx)) {
@@ -463,8 +509,8 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov,
if (!is_sync_kiocb(iocb))
dreq->iocb = iocb;
- NFS_I(inode)->read_io += iov_length(iov, nr_segs);
- result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos, uio);
+ NFS_I(inode)->read_io += iov_iter_count(iter);
+ result = nfs_direct_read_schedule(dreq, iter, pos);
if (!result)
result = nfs_direct_wait(dreq);
out_release:
@@ -629,7 +675,7 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode
*/
static ssize_t nfs_direct_write_schedule_segment(struct nfs_pageio_descriptor *desc,
const struct iovec *iov,
- loff_t pos, bool uio)
+ loff_t pos)
{
struct nfs_direct_req *dreq = desc->pg_dreq;
struct nfs_open_context *ctx = dreq->ctx;
@@ -657,19 +703,12 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_pageio_descriptor *d
if (!pagevec)
break;
- if (uio) {
- down_read(&current->mm->mmap_sem);
- result = get_user_pages(current, current->mm, user_addr,
- npages, 0, 0, pagevec, NULL);
- up_read(&current->mm->mmap_sem);
- if (result < 0)
- break;
- } else {
- WARN_ON(npages != 1);
- result = get_kernel_page(user_addr, 0, pagevec);
- if (WARN_ON(result != 1))
- break;
- }
+ down_read(&current->mm->mmap_sem);
+ result = get_user_pages(current, current->mm, user_addr,
+ npages, 0, 0, pagevec, NULL);
+ up_read(&current->mm->mmap_sem);
+ if (result < 0)
+ break;
if ((unsigned)result < npages) {
bytes = result * PAGE_SIZE;
@@ -798,27 +837,18 @@ static const struct nfs_pgio_completion_ops nfs_direct_write_completion_ops = {
.completion = nfs_direct_write_completion,
};
-static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
- const struct iovec *iov,
- unsigned long nr_segs,
- loff_t pos, bool uio)
+static ssize_t nfs_direct_do_schedule_write_iovec(
+ struct nfs_pageio_descriptor *desc, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
- struct nfs_pageio_descriptor desc;
- struct inode *inode = dreq->inode;
- ssize_t result = 0;
+ ssize_t result = -EINVAL;
size_t requested_bytes = 0;
unsigned long seg;
- NFS_PROTO(inode)->write_pageio_init(&desc, inode, FLUSH_COND_STABLE,
- &nfs_direct_write_completion_ops);
- desc.pg_dreq = dreq;
- get_dreq(dreq);
- atomic_inc(&inode->i_dio_count);
-
- NFS_I(dreq->inode)->write_io += iov_length(iov, nr_segs);
for (seg = 0; seg < nr_segs; seg++) {
const struct iovec *vec = &iov[seg];
- result = nfs_direct_write_schedule_segment(&desc, vec, pos, uio);
+ result = nfs_direct_write_schedule_segment(desc, vec,
+ pos);
if (result < 0)
break;
requested_bytes += result;
@@ -826,16 +856,91 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
break;
pos += vec->iov_len;
}
+
+ if (requested_bytes)
+ return requested_bytes;
+
+ return result < 0 ? result : -EIO;
+}
+
+#ifdef CONFIG_BLOCK
+static ssize_t nfs_direct_do_schedule_write_bvec(
+ struct nfs_pageio_descriptor *desc,
+ struct bio_vec *bvec, unsigned long nr_segs, loff_t pos)
+{
+ struct nfs_direct_req *dreq = desc->pg_dreq;
+ struct nfs_open_context *ctx = dreq->ctx;
+ struct inode *inode = dreq->inode;
+ ssize_t result = 0;
+ size_t requested_bytes = 0;
+ unsigned long seg;
+ struct nfs_page *req;
+ unsigned int req_len;
+
+ for (seg = 0; seg < nr_segs; seg++) {
+ req_len = bvec[seg].bv_len;
+
+ req = nfs_create_request(ctx, inode, bvec[seg].bv_page,
+ bvec[seg].bv_offset, req_len);
+ if (IS_ERR(req)) {
+ result = PTR_ERR(req);
+ break;
+ }
+ nfs_lock_request(req);
+ req->wb_index = pos >> PAGE_SHIFT;
+ req->wb_offset = pos & ~PAGE_MASK;
+ if (!nfs_pageio_add_request(desc, req)) {
+ result = desc->pg_error;
+ nfs_unlock_and_release_request(req);
+ break;
+ }
+ requested_bytes += req_len;
+ pos += req_len;
+ }
+
+ if (requested_bytes)
+ return requested_bytes;
+
+ return result < 0 ? result : -EIO;
+}
+#endif /* CONFIG_BLOCK */
+
+static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq,
+ struct iov_iter *iter, loff_t pos)
+{
+ struct nfs_pageio_descriptor desc;
+ struct inode *inode = dreq->inode;
+ ssize_t result = 0;
+
+ NFS_PROTO(inode)->write_pageio_init(&desc, inode, FLUSH_COND_STABLE,
+ &nfs_direct_write_completion_ops);
+ desc.pg_dreq = dreq;
+ get_dreq(dreq);
+ atomic_inc(&inode->i_dio_count);
+
+ NFS_I(dreq->inode)->write_io += iov_iter_count(iter);
+
+ if (iov_iter_has_iovec(iter)) {
+ result = nfs_direct_do_schedule_write_iovec(&desc,
+ iov_iter_iovec(iter), iter->nr_segs, pos);
+#ifdef CONFIG_BLOCK
+ } else if (iov_iter_has_bvec(iter)) {
+ result = nfs_direct_do_schedule_write_bvec(&desc,
+ iov_iter_bvec(iter), iter->nr_segs, pos);
+#endif
+ } else
+ BUG();
+
nfs_pageio_complete(&desc);
/*
* If no bytes were started, return the error, and let the
* generic layer handle the completion.
*/
- if (requested_bytes == 0) {
+ if (result < 0) {
inode_dio_done(inode);
nfs_direct_req_release(dreq);
- return result < 0 ? result : -EIO;
+ return result;
}
if (put_dreq(dreq))
@@ -843,9 +948,8 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
return 0;
}
-static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos,
- size_t count, bool uio)
+static ssize_t nfs_direct_write(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos)
{
ssize_t result = -ENOMEM;
struct inode *inode = iocb->ki_filp->f_mapping->host;
@@ -857,7 +961,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov,
goto out;
dreq->inode = inode;
- dreq->bytes_left = count;
+ dreq->bytes_left = iov_iter_count(iter);
dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
l_ctx = nfs_get_lock_context(dreq->ctx);
if (IS_ERR(l_ctx)) {
@@ -868,7 +972,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov,
if (!is_sync_kiocb(iocb))
dreq->iocb = iocb;
- result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, uio);
+ result = nfs_direct_write_schedule(dreq, iter, pos);
if (!result)
result = nfs_direct_wait(dreq);
out_release:
@@ -880,12 +984,11 @@ out:
/**
* nfs_file_direct_read - file direct read operation for NFS files
* @iocb: target I/O control block
- * @iov: vector of user buffers into which to read data
- * @nr_segs: size of iov vector
+ * @iter: vector of buffers into which to read data
* @pos: byte offset in file where reading starts
*
* We use this function for direct reads instead of calling
- * generic_file_aio_read() in order to avoid gfar's check to see if
+ * generic_file_read_iter() in order to avoid gfar's check to see if
* the request starts before the end of the file. For that check
* to work, we must generate a GETATTR before each direct read, and
* even then there is a window between the GETATTR and the subsequent
@@ -898,21 +1001,19 @@ out:
* client must read the updated atime from the server back into its
* cache.
*/
-ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos, bool uio)
+ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos)
{
ssize_t retval = -EINVAL;
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
size_t count;
- count = iov_length(iov, nr_segs);
+ count = iov_iter_count(iter);
nfs_add_stats(mapping->host, NFSIOS_DIRECTREADBYTES, count);
- dfprintk(FILE, "NFS: direct read(%s/%s, %zd@%Ld)\n",
- file->f_path.dentry->d_parent->d_name.name,
- file->f_path.dentry->d_name.name,
- count, (long long) pos);
+ dfprintk(FILE, "NFS: direct read(%pD2, %zd@%Ld)\n",
+ file, count, (long long) pos);
retval = 0;
if (!count)
@@ -924,7 +1025,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
task_io_account_read(count);
- retval = nfs_direct_read(iocb, iov, nr_segs, pos, uio);
+ retval = nfs_direct_read(iocb, iter, pos);
if (retval > 0)
iocb->ki_pos = pos + retval;
@@ -935,12 +1036,11 @@ out:
/**
* nfs_file_direct_write - file direct write operation for NFS files
* @iocb: target I/O control block
- * @iov: vector of user buffers from which to write data
- * @nr_segs: size of iov vector
+ * @iter: vector of buffers from which to write data
* @pos: byte offset in file where writing starts
*
* We use this function for direct writes instead of calling
- * generic_file_aio_write() in order to avoid taking the inode
+ * generic_file_write_iter() in order to avoid taking the inode
* semaphore and updating the i_size. The NFS server will set
* the new i_size and this client must read the updated size
* back into its cache. We let the server do generic write
@@ -954,21 +1054,19 @@ out:
* Note that O_APPEND is not supported for NFS direct writes, as there
* is no atomic O_APPEND write facility in the NFS protocol.
*/
-ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos, bool uio)
+ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos)
{
ssize_t retval = -EINVAL;
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
size_t count;
- count = iov_length(iov, nr_segs);
+ count = iov_iter_count(iter);
nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count);
- dfprintk(FILE, "NFS: direct write(%s/%s, %zd@%Ld)\n",
- file->f_path.dentry->d_parent->d_name.name,
- file->f_path.dentry->d_name.name,
- count, (long long) pos);
+ dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n",
+ file, count, (long long) pos);
retval = generic_write_checks(file, &pos, &count, 0);
if (retval)
@@ -987,7 +1085,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
task_io_account_write(count);
- retval = nfs_direct_write(iocb, iov, nr_segs, pos, count, uio);
+ retval = nfs_direct_write(iocb, iter, pos);
if (retval > 0) {
struct inode *inode = mapping->host;
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 1e6bfdbc1aff..e022fe909ded 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -65,9 +65,7 @@ nfs_file_open(struct inode *inode, struct file *filp)
{
int res;
- dprintk("NFS: open file(%s/%s)\n",
- filp->f_path.dentry->d_parent->d_name.name,
- filp->f_path.dentry->d_name.name);
+ dprintk("NFS: open file(%pD2)\n", filp);
nfs_inc_stats(inode, NFSIOS_VFSOPEN);
res = nfs_check_flags(filp->f_flags);
@@ -81,9 +79,7 @@ nfs_file_open(struct inode *inode, struct file *filp)
int
nfs_file_release(struct inode *inode, struct file *filp)
{
- dprintk("NFS: release(%s/%s)\n",
- filp->f_path.dentry->d_parent->d_name.name,
- filp->f_path.dentry->d_name.name);
+ dprintk("NFS: release(%pD2)\n", filp);
nfs_inc_stats(inode, NFSIOS_VFSRELEASE);
return nfs_release(inode, filp);
@@ -123,10 +119,8 @@ force_reval:
loff_t nfs_file_llseek(struct file *filp, loff_t offset, int whence)
{
- dprintk("NFS: llseek file(%s/%s, %lld, %d)\n",
- filp->f_path.dentry->d_parent->d_name.name,
- filp->f_path.dentry->d_name.name,
- offset, whence);
+ dprintk("NFS: llseek file(%pD2, %lld, %d)\n",
+ filp, offset, whence);
/*
* whence == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate
@@ -150,12 +144,9 @@ EXPORT_SYMBOL_GPL(nfs_file_llseek);
int
nfs_file_flush(struct file *file, fl_owner_t id)
{
- struct dentry *dentry = file->f_path.dentry;
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = file_inode(file);
- dprintk("NFS: flush(%s/%s)\n",
- dentry->d_parent->d_name.name,
- dentry->d_name.name);
+ dprintk("NFS: flush(%pD2)\n", file);
nfs_inc_stats(inode, NFSIOS_VFSFLUSH);
if ((file->f_mode & FMODE_WRITE) == 0)
@@ -174,42 +165,38 @@ nfs_file_flush(struct file *file, fl_owner_t id)
EXPORT_SYMBOL_GPL(nfs_file_flush);
ssize_t
-nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
+nfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
{
- struct dentry * dentry = iocb->ki_filp->f_path.dentry;
- struct inode * inode = dentry->d_inode;
+ struct inode *inode = file_inode(iocb->ki_filp);
ssize_t result;
if (iocb->ki_filp->f_flags & O_DIRECT)
- return nfs_file_direct_read(iocb, iov, nr_segs, pos, true);
+ return nfs_file_direct_read(iocb, iter, pos);
- dprintk("NFS: read(%s/%s, %lu@%lu)\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- (unsigned long) iov_length(iov, nr_segs), (unsigned long) pos);
+ dprintk("NFS: read_iter(%pD2, %lu@%lu)\n",
+ iocb->ki_filp,
+ (unsigned long) iov_iter_count(iter), (unsigned long) pos);
result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
if (!result) {
- result = generic_file_aio_read(iocb, iov, nr_segs, pos);
+ result = generic_file_read_iter(iocb, iter, pos);
if (result > 0)
nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, result);
}
return result;
}
-EXPORT_SYMBOL_GPL(nfs_file_read);
+EXPORT_SYMBOL_GPL(nfs_file_read_iter);
ssize_t
nfs_file_splice_read(struct file *filp, loff_t *ppos,
struct pipe_inode_info *pipe, size_t count,
unsigned int flags)
{
- struct dentry *dentry = filp->f_path.dentry;
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = file_inode(filp);
ssize_t res;
- dprintk("NFS: splice_read(%s/%s, %lu@%Lu)\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- (unsigned long) count, (unsigned long long) *ppos);
+ dprintk("NFS: splice_read(%pD2, %lu@%Lu)\n",
+ filp, (unsigned long) count, (unsigned long long) *ppos);
res = nfs_revalidate_mapping(inode, filp->f_mapping);
if (!res) {
@@ -224,12 +211,10 @@ EXPORT_SYMBOL_GPL(nfs_file_splice_read);
int
nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
{
- struct dentry *dentry = file->f_path.dentry;
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = file_inode(file);
int status;
- dprintk("NFS: mmap(%s/%s)\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ dprintk("NFS: mmap(%pD2)\n", file);
/* Note: generic_file_mmap() returns ENOSYS on nommu systems
* so we call that before revalidating the mapping
@@ -252,21 +237,18 @@ EXPORT_SYMBOL_GPL(nfs_file_mmap);
* disk, but it retrieves and clears ctx->error after synching, despite
* the two being set at the same time in nfs_context_set_write_error().
* This is because the former is used to notify the _next_ call to
- * nfs_file_write() that a write error occurred, and hence cause it to
+ * nfs_file_write_iter() that a write error occurred, and hence cause it to
* fall back to doing a synchronous write.
*/
int
nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync)
{
- struct dentry *dentry = file->f_path.dentry;
struct nfs_open_context *ctx = nfs_file_open_context(file);
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = file_inode(file);
int have_error, do_resend, status;
int ret = 0;
- dprintk("NFS: fsync file(%s/%s) datasync %d\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- datasync);
+ dprintk("NFS: fsync file(%pD2) datasync %d\n", file, datasync);
nfs_inc_stats(inode, NFSIOS_VFSFSYNC);
do_resend = test_and_clear_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags);
@@ -371,10 +353,8 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping,
struct page *page;
int once_thru = 0;
- dfprintk(PAGECACHE, "NFS: write_begin(%s/%s(%ld), %u@%lld)\n",
- file->f_path.dentry->d_parent->d_name.name,
- file->f_path.dentry->d_name.name,
- mapping->host->i_ino, len, (long long) pos);
+ dfprintk(PAGECACHE, "NFS: write_begin(%pD2(%ld), %u@%lld)\n",
+ file, mapping->host->i_ino, len, (long long) pos);
start:
/*
@@ -414,10 +394,8 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,
struct nfs_open_context *ctx = nfs_file_open_context(file);
int status;
- dfprintk(PAGECACHE, "NFS: write_end(%s/%s(%ld), %u@%lld)\n",
- file->f_path.dentry->d_parent->d_name.name,
- file->f_path.dentry->d_name.name,
- mapping->host->i_ino, len, (long long) pos);
+ dfprintk(PAGECACHE, "NFS: write_end(%pD2(%ld), %u@%lld)\n",
+ file, mapping->host->i_ino, len, (long long) pos);
/*
* Zero any uninitialised parts of the page, and then mark the page
@@ -601,22 +579,21 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct page *page = vmf->page;
struct file *filp = vma->vm_file;
- struct dentry *dentry = filp->f_path.dentry;
+ struct inode *inode = file_inode(filp);
unsigned pagelen;
int ret = VM_FAULT_NOPAGE;
struct address_space *mapping;
- dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- filp->f_mapping->host->i_ino,
+ dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%pD2(%ld), offset %lld)\n",
+ filp, filp->f_mapping->host->i_ino,
(long long)page_offset(page));
/* make sure the cache has finished storing the page */
- nfs_fscache_wait_on_page_write(NFS_I(dentry->d_inode), page);
+ nfs_fscache_wait_on_page_write(NFS_I(inode), page);
lock_page(page);
mapping = page_file_mapping(page);
- if (mapping != dentry->d_inode->i_mapping)
+ if (mapping != inode->i_mapping)
goto out_unlock;
wait_on_page_writeback(page);
@@ -656,25 +633,24 @@ static int nfs_need_sync_write(struct file *filp, struct inode *inode)
return 0;
}
-ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
+ssize_t nfs_file_write_iter(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos)
{
- struct dentry * dentry = iocb->ki_filp->f_path.dentry;
- struct inode * inode = dentry->d_inode;
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file_inode(file);
unsigned long written = 0;
ssize_t result;
- size_t count = iov_length(iov, nr_segs);
+ size_t count = iov_iter_count(iter);
- result = nfs_key_timeout_notify(iocb->ki_filp, inode);
+ result = nfs_key_timeout_notify(file, inode);
if (result)
return result;
- if (iocb->ki_filp->f_flags & O_DIRECT)
- return nfs_file_direct_write(iocb, iov, nr_segs, pos, true);
+ if (file->f_flags & O_DIRECT)
+ return nfs_file_direct_write(iocb, iter, pos);
- dprintk("NFS: write(%s/%s, %lu@%Ld)\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- (unsigned long) count, (long long) pos);
+ dprintk("NFS: write_iter(%pD2, %lu@%Ld)\n",
+ file, (unsigned long) count, (long long) pos);
result = -EBUSY;
if (IS_SWAPFILE(inode))
@@ -682,8 +658,8 @@ ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
/*
* O_APPEND implies that we must revalidate the file length.
*/
- if (iocb->ki_filp->f_flags & O_APPEND) {
- result = nfs_revalidate_file_size(inode, iocb->ki_filp);
+ if (file->f_flags & O_APPEND) {
+ result = nfs_revalidate_file_size(inode, file);
if (result)
goto out;
}
@@ -692,13 +668,13 @@ ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
if (!count)
goto out;
- result = generic_file_aio_write(iocb, iov, nr_segs, pos);
+ result = generic_file_write_iter(iocb, iter, pos);
if (result > 0)
written = result;
/* Return error values for O_DSYNC and IS_SYNC() */
- if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) {
- int err = vfs_fsync(iocb->ki_filp, 0);
+ if (result >= 0 && nfs_need_sync_write(file, inode)) {
+ int err = vfs_fsync(file, 0);
if (err < 0)
result = err;
}
@@ -711,20 +687,18 @@ out_swapfile:
printk(KERN_INFO "NFS: attempt to write to active swap file!\n");
goto out;
}
-EXPORT_SYMBOL_GPL(nfs_file_write);
+EXPORT_SYMBOL_GPL(nfs_file_write_iter);
ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
struct file *filp, loff_t *ppos,
size_t count, unsigned int flags)
{
- struct dentry *dentry = filp->f_path.dentry;
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = file_inode(filp);
unsigned long written = 0;
ssize_t ret;
- dprintk("NFS splice_write(%s/%s, %lu@%llu)\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- (unsigned long) count, (unsigned long long) *ppos);
+ dprintk("NFS splice_write(%pD2, %lu@%llu)\n",
+ filp, (unsigned long) count, (unsigned long long) *ppos);
/*
* The combination of splice and an O_APPEND destination is disallowed.
@@ -883,10 +857,8 @@ int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
int ret = -ENOLCK;
int is_local = 0;
- dprintk("NFS: lock(%s/%s, t=%x, fl=%x, r=%lld:%lld)\n",
- filp->f_path.dentry->d_parent->d_name.name,
- filp->f_path.dentry->d_name.name,
- fl->fl_type, fl->fl_flags,
+ dprintk("NFS: lock(%pD2, t=%x, fl=%x, r=%lld:%lld)\n",
+ filp, fl->fl_type, fl->fl_flags,
(long long)fl->fl_start, (long long)fl->fl_end);
nfs_inc_stats(inode, NFSIOS_VFSLOCK);
@@ -923,10 +895,8 @@ int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
struct inode *inode = filp->f_mapping->host;
int is_local = 0;
- dprintk("NFS: flock(%s/%s, t=%x, fl=%x)\n",
- filp->f_path.dentry->d_parent->d_name.name,
- filp->f_path.dentry->d_name.name,
- fl->fl_type, fl->fl_flags);
+ dprintk("NFS: flock(%pD2, t=%x, fl=%x)\n",
+ filp, fl->fl_type, fl->fl_flags);
if (!(fl->fl_flags & FL_FLOCK))
return -ENOLCK;
@@ -960,9 +930,7 @@ EXPORT_SYMBOL_GPL(nfs_flock);
*/
int nfs_setlease(struct file *file, long arg, struct file_lock **fl)
{
- dprintk("NFS: setlease(%s/%s, arg=%ld)\n",
- file->f_path.dentry->d_parent->d_name.name,
- file->f_path.dentry->d_name.name, arg);
+ dprintk("NFS: setlease(%pD2, arg=%ld)\n", file, arg);
return -EINVAL;
}
EXPORT_SYMBOL_GPL(nfs_setlease);
@@ -971,8 +939,8 @@ const struct file_operations nfs_file_operations = {
.llseek = nfs_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .aio_read = nfs_file_read,
- .aio_write = nfs_file_write,
+ .read_iter = nfs_file_read_iter,
+ .write_iter = nfs_file_write_iter,
.mmap = nfs_file_mmap,
.open = nfs_file_open,
.flush = nfs_file_flush,
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index 24d1d1c5fcaf..a01af209eeee 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -39,7 +39,7 @@ void nfs_fscache_get_client_cookie(struct nfs_client *clp)
/* create a cache index for looking up filehandles */
clp->fscache = fscache_acquire_cookie(nfs_fscache_netfs.primary_index,
&nfs_fscache_server_index_def,
- clp);
+ clp, true);
dfprintk(FSCACHE, "NFS: get client cookie (0x%p/0x%p)\n",
clp, clp->fscache);
}
@@ -139,7 +139,7 @@ void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int
/* create a cache index for looking up filehandles */
nfss->fscache = fscache_acquire_cookie(nfss->nfs_client->fscache,
&nfs_fscache_super_index_def,
- nfss);
+ nfss, true);
dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n",
nfss, nfss->fscache);
return;
@@ -178,163 +178,79 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
/*
* Initialise the per-inode cache cookie pointer for an NFS inode.
*/
-void nfs_fscache_init_inode_cookie(struct inode *inode)
+void nfs_fscache_init_inode(struct inode *inode)
{
- NFS_I(inode)->fscache = NULL;
- if (S_ISREG(inode->i_mode))
- set_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags);
-}
-
-/*
- * Get the per-inode cache cookie for an NFS inode.
- */
-static void nfs_fscache_enable_inode_cookie(struct inode *inode)
-{
- struct super_block *sb = inode->i_sb;
struct nfs_inode *nfsi = NFS_I(inode);
- if (nfsi->fscache || !NFS_FSCACHE(inode))
+ nfsi->fscache = NULL;
+ if (!S_ISREG(inode->i_mode))
return;
-
- if ((NFS_SB(sb)->options & NFS_OPTION_FSCACHE)) {
- nfsi->fscache = fscache_acquire_cookie(
- NFS_SB(sb)->fscache,
- &nfs_fscache_inode_object_def,
- nfsi);
-
- dfprintk(FSCACHE, "NFS: get FH cookie (0x%p/0x%p/0x%p)\n",
- sb, nfsi, nfsi->fscache);
- }
+ nfsi->fscache = fscache_acquire_cookie(NFS_SB(inode->i_sb)->fscache,
+ &nfs_fscache_inode_object_def,
+ nfsi, false);
}
/*
* Release a per-inode cookie.
*/
-void nfs_fscache_release_inode_cookie(struct inode *inode)
-{
- struct nfs_inode *nfsi = NFS_I(inode);
-
- dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n",
- nfsi, nfsi->fscache);
-
- fscache_relinquish_cookie(nfsi->fscache, 0);
- nfsi->fscache = NULL;
-}
-
-/*
- * Retire a per-inode cookie, destroying the data attached to it.
- */
-void nfs_fscache_zap_inode_cookie(struct inode *inode)
+void nfs_fscache_clear_inode(struct inode *inode)
{
struct nfs_inode *nfsi = NFS_I(inode);
+ struct fscache_cookie *cookie = nfs_i_fscache(inode);
- dfprintk(FSCACHE, "NFS: zapping cookie (0x%p/0x%p)\n",
- nfsi, nfsi->fscache);
+ dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", nfsi, cookie);
- fscache_relinquish_cookie(nfsi->fscache, 1);
+ fscache_relinquish_cookie(cookie, false);
nfsi->fscache = NULL;
}
-/*
- * Turn off the cache with regard to a per-inode cookie if opened for writing,
- * invalidating all the pages in the page cache relating to the associated
- * inode to clear the per-page caching.
- */
-static void nfs_fscache_disable_inode_cookie(struct inode *inode)
-{
- clear_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags);
-
- if (NFS_I(inode)->fscache) {
- dfprintk(FSCACHE,
- "NFS: nfsi 0x%p turning cache off\n", NFS_I(inode));
-
- /* Need to uncache any pages attached to this inode that
- * fscache knows about before turning off the cache.
- */
- fscache_uncache_all_inode_pages(NFS_I(inode)->fscache, inode);
- nfs_fscache_zap_inode_cookie(inode);
- }
-}
-
-/*
- * wait_on_bit() sleep function for uninterruptible waiting
- */
-static int nfs_fscache_wait_bit(void *flags)
-{
- schedule();
- return 0;
-}
-
-/*
- * Lock against someone else trying to also acquire or relinquish a cookie
- */
-static inline void nfs_fscache_inode_lock(struct inode *inode)
-{
- struct nfs_inode *nfsi = NFS_I(inode);
-
- while (test_and_set_bit(NFS_INO_FSCACHE_LOCK, &nfsi->flags))
- wait_on_bit(&nfsi->flags, NFS_INO_FSCACHE_LOCK,
- nfs_fscache_wait_bit, TASK_UNINTERRUPTIBLE);
-}
-
-/*
- * Unlock cookie management lock
- */
-static inline void nfs_fscache_inode_unlock(struct inode *inode)
+static bool nfs_fscache_can_enable(void *data)
{
- struct nfs_inode *nfsi = NFS_I(inode);
+ struct inode *inode = data;
- smp_mb__before_clear_bit();
- clear_bit(NFS_INO_FSCACHE_LOCK, &nfsi->flags);
- smp_mb__after_clear_bit();
- wake_up_bit(&nfsi->flags, NFS_INO_FSCACHE_LOCK);
+ return !inode_is_open_for_write(inode);
}
/*
- * Decide if we should enable or disable local caching for this inode.
- * - For now, with NFS, only regular files that are open read-only will be able
- * to use the cache.
- * - May be invoked multiple times in parallel by parallel nfs_open() functions.
- */
-void nfs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
-{
- if (NFS_FSCACHE(inode)) {
- nfs_fscache_inode_lock(inode);
- if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
- nfs_fscache_disable_inode_cookie(inode);
- else
- nfs_fscache_enable_inode_cookie(inode);
- nfs_fscache_inode_unlock(inode);
- }
-}
-EXPORT_SYMBOL_GPL(nfs_fscache_set_inode_cookie);
-
-/*
- * Replace a per-inode cookie due to revalidation detecting a file having
- * changed on the server.
+ * Enable or disable caching for a file that is being opened as appropriate.
+ * The cookie is allocated when the inode is initialised, but is not enabled at
+ * that time. Enablement is deferred to file-open time to avoid stat() and
+ * access() thrashing the cache.
+ *
+ * For now, with NFS, only regular files that are open read-only will be able
+ * to use the cache.
+ *
+ * We enable the cache for an inode if we open it read-only and it isn't
+ * currently open for writing. We disable the cache if the inode is open
+ * write-only.
+ *
+ * The caller uses the file struct to pin i_writecount on the inode before
+ * calling us when a file is opened for writing, so we can make use of that.
+ *
+ * Note that this may be invoked multiple times in parallel by parallel
+ * nfs_open() functions.
*/
-void nfs_fscache_reset_inode_cookie(struct inode *inode)
+void nfs_fscache_open_file(struct inode *inode, struct file *filp)
{
struct nfs_inode *nfsi = NFS_I(inode);
- struct nfs_server *nfss = NFS_SERVER(inode);
- NFS_IFDEBUG(struct fscache_cookie *old = nfsi->fscache);
-
- nfs_fscache_inode_lock(inode);
- if (nfsi->fscache) {
- /* retire the current fscache cache and get a new one */
- fscache_relinquish_cookie(nfsi->fscache, 1);
+ struct fscache_cookie *cookie = nfs_i_fscache(inode);
- nfsi->fscache = fscache_acquire_cookie(
- nfss->nfs_client->fscache,
- &nfs_fscache_inode_object_def,
- nfsi);
+ if (!fscache_cookie_valid(cookie))
+ return;
- dfprintk(FSCACHE,
- "NFS: revalidation new cookie (0x%p/0x%p/0x%p/0x%p)\n",
- nfss, nfsi, old, nfsi->fscache);
+ if (inode_is_open_for_write(inode)) {
+ dfprintk(FSCACHE, "NFS: nfsi 0x%p disabling cache\n", nfsi);
+ clear_bit(NFS_INO_FSCACHE, &nfsi->flags);
+ fscache_disable_cookie(cookie, true);
+ fscache_uncache_all_inode_pages(cookie, inode);
+ } else {
+ dfprintk(FSCACHE, "NFS: nfsi 0x%p enabling cache\n", nfsi);
+ fscache_enable_cookie(cookie, nfs_fscache_can_enable, inode);
+ if (fscache_cookie_enabled(cookie))
+ set_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags);
}
- nfs_fscache_inode_unlock(inode);
}
+EXPORT_SYMBOL_GPL(nfs_fscache_open_file);
/*
* Release the caching state associated with a page, if the page isn't busy
@@ -345,7 +261,7 @@ int nfs_fscache_release_page(struct page *page, gfp_t gfp)
{
if (PageFsCache(page)) {
struct nfs_inode *nfsi = NFS_I(page->mapping->host);
- struct fscache_cookie *cookie = nfsi->fscache;
+ struct fscache_cookie *cookie = nfs_i_fscache(page->mapping->host);
BUG_ON(!cookie);
dfprintk(FSCACHE, "NFS: fscache releasepage (0x%p/0x%p/0x%p)\n",
@@ -368,7 +284,7 @@ int nfs_fscache_release_page(struct page *page, gfp_t gfp)
void __nfs_fscache_invalidate_page(struct page *page, struct inode *inode)
{
struct nfs_inode *nfsi = NFS_I(inode);
- struct fscache_cookie *cookie = nfsi->fscache;
+ struct fscache_cookie *cookie = nfs_i_fscache(inode);
BUG_ON(!cookie);
@@ -417,9 +333,9 @@ int __nfs_readpage_from_fscache(struct nfs_open_context *ctx,
dfprintk(FSCACHE,
"NFS: readpage_from_fscache(fsc:%p/p:%p(i:%lx f:%lx)/0x%p)\n",
- NFS_I(inode)->fscache, page, page->index, page->flags, inode);
+ nfs_i_fscache(inode), page, page->index, page->flags, inode);
- ret = fscache_read_or_alloc_page(NFS_I(inode)->fscache,
+ ret = fscache_read_or_alloc_page(nfs_i_fscache(inode),
page,
nfs_readpage_from_fscache_complete,
ctx,
@@ -459,9 +375,9 @@ int __nfs_readpages_from_fscache(struct nfs_open_context *ctx,
int ret;
dfprintk(FSCACHE, "NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n",
- NFS_I(inode)->fscache, npages, inode);
+ nfs_i_fscache(inode), npages, inode);
- ret = fscache_read_or_alloc_pages(NFS_I(inode)->fscache,
+ ret = fscache_read_or_alloc_pages(nfs_i_fscache(inode),
mapping, pages, nr_pages,
nfs_readpage_from_fscache_complete,
ctx,
@@ -506,15 +422,15 @@ void __nfs_readpage_to_fscache(struct inode *inode, struct page *page, int sync)
dfprintk(FSCACHE,
"NFS: readpage_to_fscache(fsc:%p/p:%p(i:%lx f:%lx)/%d)\n",
- NFS_I(inode)->fscache, page, page->index, page->flags, sync);
+ nfs_i_fscache(inode), page, page->index, page->flags, sync);
- ret = fscache_write_page(NFS_I(inode)->fscache, page, GFP_KERNEL);
+ ret = fscache_write_page(nfs_i_fscache(inode), page, GFP_KERNEL);
dfprintk(FSCACHE,
"NFS: readpage_to_fscache: p:%p(i:%lu f:%lx) ret %d\n",
page, page->index, page->flags, ret);
if (ret != 0) {
- fscache_uncache_page(NFS_I(inode)->fscache, page);
+ fscache_uncache_page(nfs_i_fscache(inode), page);
nfs_add_fscache_stats(inode,
NFSIOS_FSCACHE_PAGES_WRITTEN_FAIL, 1);
nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_UNCACHED, 1);
diff --git a/fs/nfs/fscache.h b/fs/nfs/fscache.h
index 4ecb76652eba..d7fe3e799f2f 100644
--- a/fs/nfs/fscache.h
+++ b/fs/nfs/fscache.h
@@ -76,11 +76,9 @@ extern void nfs_fscache_release_client_cookie(struct nfs_client *);
extern void nfs_fscache_get_super_cookie(struct super_block *, const char *, int);
extern void nfs_fscache_release_super_cookie(struct super_block *);
-extern void nfs_fscache_init_inode_cookie(struct inode *);
-extern void nfs_fscache_release_inode_cookie(struct inode *);
-extern void nfs_fscache_zap_inode_cookie(struct inode *);
-extern void nfs_fscache_set_inode_cookie(struct inode *, struct file *);
-extern void nfs_fscache_reset_inode_cookie(struct inode *);
+extern void nfs_fscache_init_inode(struct inode *);
+extern void nfs_fscache_clear_inode(struct inode *);
+extern void nfs_fscache_open_file(struct inode *, struct file *);
extern void __nfs_fscache_invalidate_page(struct page *, struct inode *);
extern int nfs_fscache_release_page(struct page *, gfp_t);
@@ -187,12 +185,10 @@ static inline void nfs_fscache_release_client_cookie(struct nfs_client *clp) {}
static inline void nfs_fscache_release_super_cookie(struct super_block *sb) {}
-static inline void nfs_fscache_init_inode_cookie(struct inode *inode) {}
-static inline void nfs_fscache_release_inode_cookie(struct inode *inode) {}
-static inline void nfs_fscache_zap_inode_cookie(struct inode *inode) {}
-static inline void nfs_fscache_set_inode_cookie(struct inode *inode,
- struct file *filp) {}
-static inline void nfs_fscache_reset_inode_cookie(struct inode *inode) {}
+static inline void nfs_fscache_init_inode(struct inode *inode) {}
+static inline void nfs_fscache_clear_inode(struct inode *inode) {}
+static inline void nfs_fscache_open_file(struct inode *inode,
+ struct file *filp) {}
static inline int nfs_fscache_release_page(struct page *page, gfp_t gfp)
{
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index eda8879171c4..bb90bff0cb7a 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -122,7 +122,7 @@ void nfs_clear_inode(struct inode *inode)
WARN_ON_ONCE(!list_empty(&NFS_I(inode)->open_files));
nfs_zap_acl_cache(inode);
nfs_access_zap_cache(inode);
- nfs_fscache_release_inode_cookie(inode);
+ nfs_fscache_clear_inode(inode);
}
EXPORT_SYMBOL_GPL(nfs_clear_inode);
@@ -459,7 +459,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
nfsi->attrtimeo_timestamp = now;
nfsi->access_cache = RB_ROOT;
- nfs_fscache_init_inode_cookie(inode);
+ nfs_fscache_init_inode(inode);
unlock_new_inode(inode);
} else
@@ -854,7 +854,7 @@ int nfs_open(struct inode *inode, struct file *filp)
return PTR_ERR(ctx);
nfs_file_set_open_context(filp, ctx);
put_nfs_open_context(ctx);
- nfs_fscache_set_inode_cookie(inode, filp);
+ nfs_fscache_open_file(inode, filp);
return 0;
}
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 38da8c2b81ac..32f7a4f415a1 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -291,11 +291,11 @@ int nfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *)
int nfs_file_fsync_commit(struct file *, loff_t, loff_t, int);
loff_t nfs_file_llseek(struct file *, loff_t, int);
int nfs_file_flush(struct file *, fl_owner_t);
-ssize_t nfs_file_read(struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ssize_t nfs_file_read_iter(struct kiocb *, struct iov_iter *, loff_t);
ssize_t nfs_file_splice_read(struct file *, loff_t *, struct pipe_inode_info *,
size_t, unsigned int);
int nfs_file_mmap(struct file *, struct vm_area_struct *);
-ssize_t nfs_file_write(struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ssize_t nfs_file_write_iter(struct kiocb *, struct iov_iter *, loff_t);
int nfs_file_release(struct inode *, struct file *);
int nfs_lock(struct file *, int, struct file_lock *);
int nfs_flock(struct file *, int, struct file_lock *);
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 348b535cd786..b5a0afc3ee10 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -253,9 +253,8 @@ struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh,
dprintk("--> nfs_do_submount()\n");
- dprintk("%s: submounting on %s/%s\n", __func__,
- dentry->d_parent->d_name.name,
- dentry->d_name.name);
+ dprintk("%s: submounting on %pd2\n", __func__,
+ dentry);
if (page == NULL)
goto out;
devname = nfs_devname(dentry, page, PAGE_SIZE);
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 90cb10d7b693..01b6f6a49d16 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -321,7 +321,7 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
umode_t mode = sattr->ia_mode;
int status = -ENOMEM;
- dprintk("NFS call create %s\n", dentry->d_name.name);
+ dprintk("NFS call create %pd\n", dentry);
data = nfs3_alloc_createdata();
if (data == NULL)
@@ -548,7 +548,7 @@ nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
if (len > NFS3_MAXPATHLEN)
return -ENAMETOOLONG;
- dprintk("NFS call symlink %s\n", dentry->d_name.name);
+ dprintk("NFS call symlink %pd\n", dentry);
data = nfs3_alloc_createdata();
if (data == NULL)
@@ -576,7 +576,7 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
umode_t mode = sattr->ia_mode;
int status = -ENOMEM;
- dprintk("NFS call mkdir %s\n", dentry->d_name.name);
+ dprintk("NFS call mkdir %pd\n", dentry);
sattr->ia_mode &= ~current_umask();
@@ -695,7 +695,7 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
umode_t mode = sattr->ia_mode;
int status = -ENOMEM;
- dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name,
+ dprintk("NFS call mknod %pd %u:%u\n", dentry,
MAJOR(rdev), MINOR(rdev));
sattr->ia_mode &= ~current_umask();
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
index e5b804dd944c..f59b2f26d12e 100644
--- a/fs/nfs/nfs4file.c
+++ b/fs/nfs/nfs4file.c
@@ -30,9 +30,7 @@ nfs4_file_open(struct inode *inode, struct file *filp)
* -EOPENSTALE. The VFS will retry the lookup/create/open.
*/
- dprintk("NFS: open file(%s/%s)\n",
- dentry->d_parent->d_name.name,
- dentry->d_name.name);
+ dprintk("NFS: open file(%pd2)\n", dentry);
if ((openflags & O_ACCMODE) == 3)
openflags--;
@@ -74,7 +72,7 @@ nfs4_file_open(struct inode *inode, struct file *filp)
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
nfs_file_set_open_context(filp, ctx);
- nfs_fscache_set_inode_cookie(inode, filp);
+ nfs_fscache_open_file(inode, filp);
err = 0;
out_put_ctx:
@@ -121,8 +119,8 @@ const struct file_operations nfs4_file_operations = {
.llseek = nfs_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .aio_read = nfs_file_read,
- .aio_write = nfs_file_write,
+ .read_iter = nfs_file_read_iter,
+ .write_iter = nfs_file_write_iter,
.mmap = nfs_file_mmap,
.open = nfs4_file_open,
.flush = nfs_file_flush,
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index 2288cd3c9278..049b9fb0d2c9 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -283,8 +283,7 @@ static struct vfsmount *nfs_follow_referral(struct dentry *dentry,
if (locations == NULL || locations->nlocations <= 0)
goto out;
- dprintk("%s: referral at %s/%s\n", __func__,
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ dprintk("%s: referral at %pd2\n", __func__, dentry);
page = (char *) __get_free_page(GFP_USER);
if (!page)
@@ -348,8 +347,8 @@ static struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *
mnt = ERR_PTR(-ENOENT);
parent = dget_parent(dentry);
- dprintk("%s: getting locations for %s/%s\n",
- __func__, parent->d_name.name, dentry->d_name.name);
+ dprintk("%s: getting locations for %pd2\n",
+ __func__, dentry);
err = nfs4_proc_fs_locations(client, parent->d_inode, &dentry->d_name, fs_locations, page);
dput(parent);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 989bb9d3074d..e2112780a373 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3726,9 +3726,8 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
};
int status;
- dprintk("%s: dentry = %s/%s, cookie = %Lu\n", __func__,
- dentry->d_parent->d_name.name,
- dentry->d_name.name,
+ dprintk("%s: dentry = %pd2, cookie = %Lu\n", __func__,
+ dentry,
(unsigned long long)cookie);
nfs4_setup_readdir(cookie, NFS_I(dir)->cookieverf, dentry, &args);
res.pgbase = args.pgbase;
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index a8f57c728df5..fddbba2d9eff 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -235,7 +235,7 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
};
int status = -ENOMEM;
- dprintk("NFS call create %s\n", dentry->d_name.name);
+ dprintk("NFS call create %pd\n", dentry);
data = nfs_alloc_createdata(dir, dentry, sattr);
if (data == NULL)
goto out;
@@ -265,7 +265,7 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
umode_t mode;
int status = -ENOMEM;
- dprintk("NFS call mknod %s\n", dentry->d_name.name);
+ dprintk("NFS call mknod %pd\n", dentry);
mode = sattr->ia_mode;
if (S_ISFIFO(mode)) {
@@ -423,7 +423,7 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
};
int status = -ENAMETOOLONG;
- dprintk("NFS call symlink %s\n", dentry->d_name.name);
+ dprintk("NFS call symlink %pd\n", dentry);
if (len > NFS2_MAXPATHLEN)
goto out;
@@ -462,7 +462,7 @@ nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
};
int status = -ENOMEM;
- dprintk("NFS call mkdir %s\n", dentry->d_name.name);
+ dprintk("NFS call mkdir %pd\n", dentry);
data = nfs_alloc_createdata(dir, dentry, sattr);
if (data == NULL)
goto out;
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index bb939edd4c99..8285de9eaad2 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -495,9 +495,8 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
struct rpc_task *task;
int error = -EIO;
- dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- d_count(dentry));
+ dfprintk(VFS, "NFS: silly-rename(%pd2, ct=%d)\n",
+ dentry, d_count(dentry));
nfs_inc_stats(dir, NFSIOS_SILLYRENAME);
/*
@@ -522,8 +521,8 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
SILLYNAME_FILEID_LEN, fileid,
SILLYNAME_COUNTER_LEN, sillycounter);
- dfprintk(VFS, "NFS: trying to rename %s to %s\n",
- dentry->d_name.name, silly);
+ dfprintk(VFS, "NFS: trying to rename %pd to %s\n",
+ dentry, silly);
sdentry = lookup_one_len(silly, dentry->d_parent, slen);
/*
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index ac1dc331ba31..c1d548211c31 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -954,10 +954,8 @@ int nfs_updatepage(struct file *file, struct page *page,
nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE);
- dprintk("NFS: nfs_updatepage(%s/%s %d@%lld)\n",
- file->f_path.dentry->d_parent->d_name.name,
- file->f_path.dentry->d_name.name, count,
- (long long)(page_file_offset(page) + offset));
+ dprintk("NFS: nfs_updatepage(%pD2 %d@%lld)\n",
+ file, count, (long long)(page_file_offset(page) + offset));
if (nfs_can_extend_write(file, page, inode)) {
count = max(count + offset, nfs_page_length(page));
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index e0a65a9e37e9..9c271f42604a 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -385,8 +385,8 @@ purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
status = vfs_rmdir(parent->d_inode, child);
if (status)
- printk("failed to remove client recovery directory %s\n",
- child->d_name.name);
+ printk("failed to remove client recovery directory %pd\n",
+ child);
/* Keep trying, success or failure: */
return 0;
}
@@ -410,15 +410,15 @@ out:
nfs4_release_reclaim(nn);
if (status)
printk("nfsd4: failed to purge old clients from recovery"
- " directory %s\n", nn->rec_file->f_path.dentry->d_name.name);
+ " directory %pD\n", nn->rec_file);
}
static int
load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
{
if (child->d_name.len != HEXDIR_LEN - 1) {
- printk("nfsd4: illegal name %s in recovery directory\n",
- child->d_name.name);
+ printk("nfsd4: illegal name %pd in recovery directory\n",
+ child);
/* Keep trying; maybe the others are OK: */
return 0;
}
@@ -437,7 +437,7 @@ nfsd4_recdir_load(struct net *net) {
status = nfsd4_list_rec_dir(load_recdir, nn);
if (status)
printk("nfsd4: failed loading clients from recovery"
- " directory %s\n", nn->rec_file->f_path.dentry->d_name.name);
+ " directory %pD\n", nn->rec_file);
return status;
}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 0874998a49cd..a601fd49f997 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -3843,9 +3843,8 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfs4_ol_stateid *stp;
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
- dprintk("NFSD: nfsd4_open_confirm on file %.*s\n",
- (int)cstate->current_fh.fh_dentry->d_name.len,
- cstate->current_fh.fh_dentry->d_name.name);
+ dprintk("NFSD: nfsd4_open_confirm on file %pd\n",
+ cstate->current_fh.fh_dentry);
status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0);
if (status)
@@ -3922,9 +3921,8 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
struct nfs4_ol_stateid *stp;
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
- dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n",
- (int)cstate->current_fh.fh_dentry->d_name.len,
- cstate->current_fh.fh_dentry->d_name.name);
+ dprintk("NFSD: nfsd4_open_downgrade on file %pd\n",
+ cstate->current_fh.fh_dentry);
/* We don't yet support WANT bits: */
if (od->od_deleg_want)
@@ -3980,9 +3978,8 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct net *net = SVC_NET(rqstp);
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
- dprintk("NFSD: nfsd4_close on file %.*s\n",
- (int)cstate->current_fh.fh_dentry->d_name.len,
- cstate->current_fh.fh_dentry->d_name.name);
+ dprintk("NFSD: nfsd4_close on file %pd\n",
+ cstate->current_fh.fh_dentry);
nfs4_lock_state();
status = nfs4_preprocess_seqid_op(cstate, close->cl_seqid,
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 814afaa4458a..3d0e15ae6f72 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -47,7 +47,7 @@ static int nfsd_acceptable(void *expv, struct dentry *dentry)
tdentry = parent;
}
if (tdentry != exp->ex_path.dentry)
- dprintk("nfsd_acceptable failed at %p %s\n", tdentry, tdentry->d_name.name);
+ dprintk("nfsd_acceptable failed at %p %pd\n", tdentry, tdentry);
rv = (tdentry == exp->ex_path.dentry);
dput(tdentry);
return rv;
@@ -253,8 +253,8 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
if (S_ISDIR(dentry->d_inode->i_mode) &&
(dentry->d_flags & DCACHE_DISCONNECTED)) {
- printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %pd2\n",
+ dentry);
}
fhp->fh_dentry = dentry;
@@ -361,10 +361,9 @@ skip_pseudoflavor_check:
error = nfsd_permission(rqstp, exp, dentry, access);
if (error) {
- dprintk("fh_verify: %s/%s permission failure, "
+ dprintk("fh_verify: %pd2 permission failure, "
"acc=%x, error=%d\n",
- dentry->d_parent->d_name.name,
- dentry->d_name.name,
+ dentry,
access, ntohl(error));
}
out:
@@ -514,14 +513,13 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
*/
struct inode * inode = dentry->d_inode;
- struct dentry *parent = dentry->d_parent;
__u32 *datap;
dev_t ex_dev = exp_sb(exp)->s_dev;
- dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n",
+ dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %pd2, ino=%ld)\n",
MAJOR(ex_dev), MINOR(ex_dev),
(long) exp->ex_path.dentry->d_inode->i_ino,
- parent->d_name.name, dentry->d_name.name,
+ dentry,
(inode ? inode->i_ino : 0));
/* Choose filehandle version and fsid type based on
@@ -534,13 +532,13 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
fh_put(ref_fh);
if (fhp->fh_locked || fhp->fh_dentry) {
- printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n",
- parent->d_name.name, dentry->d_name.name);
+ printk(KERN_ERR "fh_compose: fh %pd2 not initialized!\n",
+ dentry);
}
if (fhp->fh_maxsize < NFS_FHSIZE)
- printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n",
+ printk(KERN_ERR "fh_compose: called with maxsize %d! %pd2\n",
fhp->fh_maxsize,
- parent->d_name.name, dentry->d_name.name);
+ dentry);
fhp->fh_dentry = dget(dentry); /* our internal copy */
fhp->fh_export = exp;
@@ -613,8 +611,8 @@ out_bad:
printk(KERN_ERR "fh_update: fh not verified!\n");
goto out;
out_negative:
- printk(KERN_ERR "fh_update: %s/%s still negative!\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ printk(KERN_ERR "fh_update: %pd2 still negative!\n",
+ dentry);
goto out;
}
diff --git a/fs/nfsd/nfsfh.h b/fs/nfsd/nfsfh.h
index e5e6707ba687..4775bc4896c8 100644
--- a/fs/nfsd/nfsfh.h
+++ b/fs/nfsd/nfsfh.h
@@ -173,8 +173,8 @@ fh_lock_nested(struct svc_fh *fhp, unsigned int subclass)
BUG_ON(!dentry);
if (fhp->fh_locked) {
- printk(KERN_WARNING "fh_lock: %s/%s already locked!\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
+ printk(KERN_WARNING "fh_lock: %pd2 already locked!\n",
+ dentry);
return;
}
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index c827acb0e943..13886f7f40d5 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1317,9 +1317,8 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
if (!fhp->fh_locked) {
/* not actually possible */
printk(KERN_ERR
- "nfsd_create: parent %s/%s not locked!\n",
- dentry->d_parent->d_name.name,
- dentry->d_name.name);
+ "nfsd_create: parent %pd2 not locked!\n",
+ dentry);
err = nfserr_io;
goto out;
}
@@ -1329,8 +1328,8 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
*/
err = nfserr_exist;
if (dchild->d_inode) {
- dprintk("nfsd_create: dentry %s/%s not negative!\n",
- dentry->d_name.name, dchild->d_name.name);
+ dprintk("nfsd_create: dentry %pd/%pd not negative!\n",
+ dentry, dchild);
goto out;
}
diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c
index 08fdb77852ac..7aeb8ee01305 100644
--- a/fs/nilfs2/file.c
+++ b/fs/nilfs2/file.c
@@ -153,8 +153,8 @@ const struct file_operations nilfs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .aio_read = generic_file_aio_read,
- .aio_write = generic_file_aio_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = generic_file_write_iter,
.unlocked_ioctl = nilfs_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = nilfs_compat_ioctl,
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 7e350c562e0e..4a99a24b54a2 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -298,8 +298,8 @@ static int nilfs_write_end(struct file *file, struct address_space *mapping,
}
static ssize_t
-nilfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
- loff_t offset, unsigned long nr_segs)
+nilfs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
+ loff_t offset)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
@@ -310,7 +310,7 @@ nilfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
return 0;
/* Needs synchronization with the cleaner */
- size = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
+ size = blockdev_direct_IO(rw, iocb, inode, iter, offset,
nilfs_get_block);
/*
@@ -319,7 +319,7 @@ nilfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
*/
if (unlikely((rw & WRITE) && size < 0)) {
loff_t isize = i_size_read(inode);
- loff_t end = offset + iov_length(iov, nr_segs);
+ loff_t end = offset + iov_iter_count(iter);
if (end > isize)
nilfs_write_failed(mapping, end);
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index c20360002f29..2cd76d2a2f99 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -618,9 +618,8 @@ static int ocfs2_releasepage(struct page *page, gfp_t wait)
static ssize_t ocfs2_direct_IO(int rw,
struct kiocb *iocb,
- const struct iovec *iov,
- loff_t offset,
- unsigned long nr_segs)
+ struct iov_iter *iter,
+ loff_t offset)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file)->i_mapping->host;
@@ -637,8 +636,7 @@ static ssize_t ocfs2_direct_IO(int rw,
return 0;
return __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev,
- iov, offset, nr_segs,
- ocfs2_direct_IO_get_blocks,
+ iter, offset, ocfs2_direct_IO_get_blocks,
ocfs2_dio_end_io, NULL, 0);
}
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h
index f671e49beb34..573f41d1e459 100644
--- a/fs/ocfs2/aops.h
+++ b/fs/ocfs2/aops.h
@@ -74,7 +74,7 @@ static inline void ocfs2_iocb_set_rw_locked(struct kiocb *iocb, int level)
/*
* Using a named enum representing lock types in terms of #N bit stored in
* iocb->private, which is going to be used for communication between
- * ocfs2_dio_end_io() and ocfs2_file_aio_write/read().
+ * ocfs2_dio_end_io() and ocfs2_file_write/read_iter().
*/
enum ocfs2_iocb_lock_bits {
OCFS2_IOCB_RW_LOCK = 0,
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index d54d1bffe3da..f116c099835b 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -2235,15 +2235,13 @@ out:
return ret;
}
-static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
- const struct iovec *iov,
- unsigned long nr_segs,
- loff_t pos)
+static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
+ struct iov_iter *iter,
+ loff_t pos)
{
int ret, direct_io, appending, rw_level, have_alloc_sem = 0;
int can_do_direct, has_refcount = 0;
ssize_t written = 0;
- size_t ocount; /* original count */
size_t count; /* after file limit checks */
loff_t old_size, *ppos = &iocb->ki_pos;
u32 old_clusters;
@@ -2254,11 +2252,11 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
OCFS2_MOUNT_COHERENCY_BUFFERED);
int unaligned_dio = 0;
- trace_ocfs2_file_aio_write(inode, file, file->f_path.dentry,
+ trace_ocfs2_file_write_iter(inode, file, file->f_path.dentry,
(unsigned long long)OCFS2_I(inode)->ip_blkno,
file->f_path.dentry->d_name.len,
file->f_path.dentry->d_name.name,
- (unsigned int)nr_segs);
+ (unsigned long)pos);
if (iocb->ki_nbytes == 0)
return 0;
@@ -2358,28 +2356,24 @@ relock:
/* communicate with ocfs2_dio_end_io */
ocfs2_iocb_set_rw_locked(iocb, rw_level);
- ret = generic_segment_checks(iov, &nr_segs, &ocount,
- VERIFY_READ);
- if (ret)
- goto out_dio;
- count = ocount;
+ count = iov_iter_count(iter);
ret = generic_write_checks(file, ppos, &count,
S_ISBLK(inode->i_mode));
if (ret)
goto out_dio;
if (direct_io) {
- written = generic_file_direct_write(iocb, iov, &nr_segs, *ppos,
- ppos, count, ocount);
+ written = generic_file_direct_write_iter(iocb, iter, *ppos,
+ ppos, count);
if (written < 0) {
ret = written;
goto out_dio;
}
} else {
current->backing_dev_info = file->f_mapping->backing_dev_info;
- written = generic_file_buffered_write(iocb, iov, nr_segs, *ppos,
- ppos, count, 0);
+ written = generic_file_buffered_write_iter(iocb, iter, *ppos,
+ ppos, count, 0);
current->backing_dev_info = NULL;
}
@@ -2535,7 +2529,7 @@ static ssize_t ocfs2_file_splice_read(struct file *in,
in->f_path.dentry->d_name.name, len);
/*
- * See the comment in ocfs2_file_aio_read()
+ * See the comment in ocfs2_file_read_iter()
*/
ret = ocfs2_inode_lock_atime(inode, in->f_path.mnt, &lock_level);
if (ret < 0) {
@@ -2550,19 +2544,18 @@ bail:
return ret;
}
-static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
- const struct iovec *iov,
- unsigned long nr_segs,
- loff_t pos)
+static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
+ struct iov_iter *iter,
+ loff_t pos)
{
int ret = 0, rw_level = -1, have_alloc_sem = 0, lock_level = 0;
struct file *filp = iocb->ki_filp;
struct inode *inode = file_inode(filp);
- trace_ocfs2_file_aio_read(inode, filp, filp->f_path.dentry,
+ trace_ocfs2_file_read_iter(inode, filp, filp->f_path.dentry,
(unsigned long long)OCFS2_I(inode)->ip_blkno,
filp->f_path.dentry->d_name.len,
- filp->f_path.dentry->d_name.name, nr_segs);
+ filp->f_path.dentry->d_name.name, pos);
if (!inode) {
@@ -2598,7 +2591,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
*
* Take and drop the meta data lock to update inode fields
* like i_size. This allows the checks down below
- * generic_file_aio_read() a chance of actually working.
+ * generic_file_read_iter() a chance of actually working.
*/
ret = ocfs2_inode_lock_atime(inode, filp->f_path.mnt, &lock_level);
if (ret < 0) {
@@ -2607,13 +2600,13 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
}
ocfs2_inode_unlock(inode, lock_level);
- ret = generic_file_aio_read(iocb, iov, nr_segs, iocb->ki_pos);
- trace_generic_file_aio_read_ret(ret);
+ ret = generic_file_read_iter(iocb, iter, iocb->ki_pos);
+ trace_generic_file_read_iter_ret(ret);
/* buffered aio wouldn't have proper lock coverage today */
BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT));
- /* see ocfs2_file_aio_write */
+ /* see ocfs2_file_write_iter */
if (ret == -EIOCBQUEUED || !ocfs2_iocb_is_rw_locked(iocb)) {
rw_level = -1;
have_alloc_sem = 0;
@@ -2710,8 +2703,8 @@ const struct file_operations ocfs2_fops = {
.fsync = ocfs2_sync_file,
.release = ocfs2_file_release,
.open = ocfs2_file_open,
- .aio_read = ocfs2_file_aio_read,
- .aio_write = ocfs2_file_aio_write,
+ .read_iter = ocfs2_file_read_iter,
+ .write_iter = ocfs2_file_write_iter,
.unlocked_ioctl = ocfs2_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ocfs2_compat_ioctl,
@@ -2758,8 +2751,8 @@ const struct file_operations ocfs2_fops_no_plocks = {
.fsync = ocfs2_sync_file,
.release = ocfs2_file_release,
.open = ocfs2_file_open,
- .aio_read = ocfs2_file_aio_read,
- .aio_write = ocfs2_file_aio_write,
+ .read_iter = ocfs2_file_read_iter,
+ .write_iter = ocfs2_file_write_iter,
.unlocked_ioctl = ocfs2_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ocfs2_compat_ioctl,
diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h
index 1b60c62aa9d6..67f08ba77260 100644
--- a/fs/ocfs2/ocfs2_trace.h
+++ b/fs/ocfs2/ocfs2_trace.h
@@ -1310,13 +1310,13 @@ DEFINE_OCFS2_FILE_OPS(ocfs2_file_release);
DEFINE_OCFS2_FILE_OPS(ocfs2_sync_file);
-DEFINE_OCFS2_FILE_OPS(ocfs2_file_aio_write);
+DEFINE_OCFS2_FILE_OPS(ocfs2_file_write_iter);
DEFINE_OCFS2_FILE_OPS(ocfs2_file_splice_write);
DEFINE_OCFS2_FILE_OPS(ocfs2_file_splice_read);
-DEFINE_OCFS2_FILE_OPS(ocfs2_file_aio_read);
+DEFINE_OCFS2_FILE_OPS(ocfs2_file_read_iter);
DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_truncate_file);
@@ -1474,7 +1474,7 @@ TRACE_EVENT(ocfs2_prepare_inode_for_write,
__entry->direct_io, __entry->has_refcount)
);
-DEFINE_OCFS2_INT_EVENT(generic_file_aio_read_ret);
+DEFINE_OCFS2_INT_EVENT(generic_file_read_iter_ret);
/* End of trace events for fs/ocfs2/file.c. */
diff --git a/fs/omfs/file.c b/fs/omfs/file.c
index 54d57d6ba68d..0fe505b2cded 100644
--- a/fs/omfs/file.c
+++ b/fs/omfs/file.c
@@ -339,8 +339,8 @@ const struct file_operations omfs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .aio_read = generic_file_aio_read,
- .aio_write = generic_file_aio_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = generic_file_write_iter,
.mmap = generic_file_mmap,
.fsync = generic_file_fsync,
.splice_read = generic_file_splice_read,
diff --git a/fs/proc/self.c b/fs/proc/self.c
index 6b6a993b5c25..ffeb202ec942 100644
--- a/fs/proc/self.c
+++ b/fs/proc/self.c
@@ -36,18 +36,10 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
return NULL;
}
-static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd,
- void *cookie)
-{
- char *s = nd_get_link(nd);
- if (!IS_ERR(s))
- kfree(s);
-}
-
static const struct inode_operations proc_self_inode_operations = {
.readlink = proc_self_readlink,
.follow_link = proc_self_follow_link,
- .put_link = proc_self_put_link,
+ .put_link = kfree_put_link,
};
static unsigned self_inum;
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c
index 4884ac5ae9be..c4d8572a37df 100644
--- a/fs/ramfs/file-mmu.c
+++ b/fs/ramfs/file-mmu.c
@@ -39,9 +39,9 @@ const struct address_space_operations ramfs_aops = {
const struct file_operations ramfs_file_operations = {
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.write = do_sync_write,
- .aio_write = generic_file_aio_write,
+ .write_iter = generic_file_write_iter,
.mmap = generic_file_mmap,
.fsync = noop_fsync,
.splice_read = generic_file_splice_read,
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index 8d5b438cc188..f2487c3cc3f3 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -39,9 +39,9 @@ const struct file_operations ramfs_file_operations = {
.mmap = ramfs_nommu_mmap,
.get_unmapped_area = ramfs_nommu_get_unmapped_area,
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.write = do_sync_write,
- .aio_write = generic_file_aio_write,
+ .write_iter = generic_file_write_iter,
.fsync = noop_fsync,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
diff --git a/fs/read_write.c b/fs/read_write.c
index e3cd280b158c..296b5711a78b 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -29,7 +29,7 @@ typedef ssize_t (*iov_fn_t)(struct kiocb *, const struct iovec *,
const struct file_operations generic_ro_fops = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.mmap = generic_file_readonly_mmap,
.splice_read = generic_file_splice_read,
};
@@ -359,6 +359,29 @@ int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t
return count > MAX_RW_COUNT ? MAX_RW_COUNT : count;
}
+ssize_t do_aio_read(struct kiocb *kiocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
+{
+ struct file *file = kiocb->ki_filp;
+
+ if (file->f_op->read_iter) {
+ size_t count;
+ struct iov_iter iter;
+ int ret;
+
+ count = 0;
+ ret = generic_segment_checks(iov, &nr_segs, &count,
+ VERIFY_WRITE);
+ if (ret)
+ return ret;
+
+ iov_iter_init(&iter, iov, nr_segs, count, 0);
+ return file->f_op->read_iter(kiocb, &iter, pos);
+ }
+
+ return file->f_op->aio_read(kiocb, iov, nr_segs, pos);
+}
+
ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
{
struct iovec iov = { .iov_base = buf, .iov_len = len };
@@ -369,7 +392,7 @@ ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *pp
kiocb.ki_pos = *ppos;
kiocb.ki_nbytes = len;
- ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
+ ret = do_aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos;
@@ -384,7 +407,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
if (!(file->f_mode & FMODE_READ))
return -EBADF;
- if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read))
+ if (!file_readable(file))
return -EINVAL;
if (unlikely(!access_ok(VERIFY_WRITE, buf, count)))
return -EFAULT;
@@ -408,6 +431,29 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
EXPORT_SYMBOL(vfs_read);
+ssize_t do_aio_write(struct kiocb *kiocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
+{
+ struct file *file = kiocb->ki_filp;
+
+ if (file->f_op->write_iter) {
+ size_t count;
+ struct iov_iter iter;
+ int ret;
+
+ count = 0;
+ ret = generic_segment_checks(iov, &nr_segs, &count,
+ VERIFY_READ);
+ if (ret)
+ return ret;
+
+ iov_iter_init(&iter, iov, nr_segs, count, 0);
+ return file->f_op->write_iter(kiocb, &iter, pos);
+ }
+
+ return file->f_op->aio_write(kiocb, iov, nr_segs, pos);
+}
+
ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
{
struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };
@@ -418,7 +464,7 @@ ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, lof
kiocb.ki_pos = *ppos;
kiocb.ki_nbytes = len;
- ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
+ ret = do_aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos;
@@ -433,7 +479,7 @@ ssize_t __kernel_write(struct file *file, const char *buf, size_t count, loff_t
const char __user *p;
ssize_t ret;
- if (!file->f_op || (!file->f_op->write && !file->f_op->aio_write))
+ if (!file_writable(file))
return -EINVAL;
old_fs = get_fs();
@@ -460,7 +506,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
if (!(file->f_mode & FMODE_WRITE))
return -EBADF;
- if (!file->f_op || (!file->f_op->write && !file->f_op->aio_write))
+ if (!file_writable(file))
return -EINVAL;
if (unlikely(!access_ok(VERIFY_READ, buf, count)))
return -EFAULT;
@@ -745,10 +791,12 @@ static ssize_t do_readv_writev(int type, struct file *file,
fnv = NULL;
if (type == READ) {
fn = file->f_op->read;
- fnv = file->f_op->aio_read;
+ if (file->f_op->aio_read || file->f_op->read_iter)
+ fnv = do_aio_read;
} else {
fn = (io_fn_t)file->f_op->write;
- fnv = file->f_op->aio_write;
+ if (file->f_op->aio_write || file->f_op->write_iter)
+ fnv = do_aio_write;
file_start_write(file);
}
@@ -778,7 +826,7 @@ ssize_t vfs_readv(struct file *file, const struct iovec __user *vec,
{
if (!(file->f_mode & FMODE_READ))
return -EBADF;
- if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
+ if (!file_readable(file))
return -EINVAL;
return do_readv_writev(READ, file, vec, vlen, pos);
@@ -791,7 +839,7 @@ ssize_t vfs_writev(struct file *file, const struct iovec __user *vec,
{
if (!(file->f_mode & FMODE_WRITE))
return -EBADF;
- if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write))
+ if (!file_writable(file))
return -EINVAL;
return do_readv_writev(WRITE, file, vec, vlen, pos);
@@ -927,10 +975,12 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
fnv = NULL;
if (type == READ) {
fn = file->f_op->read;
- fnv = file->f_op->aio_read;
+ if (file->f_op->aio_read || file->f_op->read_iter)
+ fnv = do_aio_read;
} else {
fn = (io_fn_t)file->f_op->write;
- fnv = file->f_op->aio_write;
+ if (file->f_op->aio_write || file->f_op->write_iter)
+ fnv = do_aio_write;
file_start_write(file);
}
@@ -965,7 +1015,7 @@ static size_t compat_readv(struct file *file,
goto out;
ret = -EINVAL;
- if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
+ if (!file_readable(file))
goto out;
ret = compat_do_readv_writev(READ, file, vec, vlen, pos);
@@ -1032,7 +1082,7 @@ static size_t compat_writev(struct file *file,
goto out;
ret = -EINVAL;
- if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write))
+ if (!file_writable(file))
goto out;
ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos);
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index dcaafcfc23b0..f98feb229ec4 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -245,8 +245,8 @@ const struct file_operations reiserfs_file_operations = {
.open = reiserfs_file_open,
.release = reiserfs_file_release,
.fsync = reiserfs_sync_file,
- .aio_read = generic_file_aio_read,
- .aio_write = generic_file_aio_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = generic_file_write_iter,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
.llseek = generic_file_llseek,
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index ad62bdbb451e..6d652af02c5b 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -3083,14 +3083,13 @@ static int reiserfs_releasepage(struct page *page, gfp_t unused_gfp_flags)
/* We thank Mingming Cao for helping us understand in great detail what
to do in this section of the code. */
static ssize_t reiserfs_direct_IO(int rw, struct kiocb *iocb,
- const struct iovec *iov, loff_t offset,
- unsigned long nr_segs)
+ struct iov_iter *iter, loff_t offset)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
ssize_t ret;
- ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
+ ret = blockdev_direct_IO(rw, iocb, inode, iter, offset,
reiserfs_get_blocks_direct_io);
/*
@@ -3099,7 +3098,7 @@ static ssize_t reiserfs_direct_IO(int rw, struct kiocb *iocb,
*/
if (unlikely((rw & WRITE) && ret < 0)) {
loff_t isize = i_size_read(inode);
- loff_t end = offset + iov_length(iov, nr_segs);
+ loff_t end = offset + iov_iter_count(iter);
if ((end > isize) && inode_newsize_ok(inode, isize) == 0) {
truncate_setsize(inode, isize);
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 73feacc49b2e..fd777032c2ba 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -1163,21 +1163,6 @@ static struct reiserfs_journal_list *find_newer_jl_for_cn(struct
return NULL;
}
-static int newer_jl_done(struct reiserfs_journal_cnode *cn)
-{
- struct super_block *sb = cn->sb;
- b_blocknr_t blocknr = cn->blocknr;
-
- cn = cn->hprev;
- while (cn) {
- if (cn->sb == sb && cn->blocknr == blocknr && cn->jlist &&
- atomic_read(&cn->jlist->j_commit_left) != 0)
- return 0;
- cn = cn->hprev;
- }
- return 1;
-}
-
static void remove_journal_hash(struct super_block *,
struct reiserfs_journal_cnode **,
struct reiserfs_journal_list *, unsigned long,
@@ -1353,7 +1338,6 @@ static int flush_journal_list(struct super_block *s,
reiserfs_warning(s, "clm-2048", "called with wcount %d",
atomic_read(&journal->j_wcount));
}
- BUG_ON(jl->j_trans_id == 0);
/* if flushall == 0, the lock is already held */
if (flushall) {
@@ -1593,31 +1577,6 @@ static int flush_journal_list(struct super_block *s,
return err;
}
-static int test_transaction(struct super_block *s,
- struct reiserfs_journal_list *jl)
-{
- struct reiserfs_journal_cnode *cn;
-
- if (jl->j_len == 0 || atomic_read(&jl->j_nonzerolen) == 0)
- return 1;
-
- cn = jl->j_realblock;
- while (cn) {
- /* if the blocknr == 0, this has been cleared from the hash,
- ** skip it
- */
- if (cn->blocknr == 0) {
- goto next;
- }
- if (cn->bh && !newer_jl_done(cn))
- return 0;
- next:
- cn = cn->next;
- cond_resched();
- }
- return 0;
-}
-
static int write_one_transaction(struct super_block *s,
struct reiserfs_journal_list *jl,
struct buffer_chunk *chunk)
@@ -1805,6 +1764,8 @@ static int flush_used_journal_lists(struct super_block *s,
break;
tjl = JOURNAL_LIST_ENTRY(tjl->j_list.next);
}
+ get_journal_list(jl);
+ get_journal_list(flush_jl);
/* try to find a group of blocks we can flush across all the
** transactions, but only bother if we've actually spanned
** across multiple lists
@@ -1813,6 +1774,8 @@ static int flush_used_journal_lists(struct super_block *s,
ret = kupdate_transactions(s, jl, &tjl, &trans_id, len, i);
}
flush_journal_list(s, flush_jl, 1);
+ put_journal_list(s, flush_jl);
+ put_journal_list(s, jl);
return 0;
}
@@ -3868,27 +3831,6 @@ int reiserfs_prepare_for_journal(struct super_block *sb,
return 1;
}
-static void flush_old_journal_lists(struct super_block *s)
-{
- struct reiserfs_journal *journal = SB_JOURNAL(s);
- struct reiserfs_journal_list *jl;
- struct list_head *entry;
- time_t now = get_seconds();
-
- while (!list_empty(&journal->j_journal_list)) {
- entry = journal->j_journal_list.next;
- jl = JOURNAL_LIST_ENTRY(entry);
- /* this check should always be run, to send old lists to disk */
- if (jl->j_timestamp < (now - (JOURNAL_MAX_TRANS_AGE * 4)) &&
- atomic_read(&jl->j_commit_left) == 0 &&
- test_transaction(s, jl)) {
- flush_used_journal_lists(s, jl);
- } else {
- break;
- }
- }
-}
-
/*
** long and ugly. If flush, will not return until all commit
** blocks and all real buffers in the trans are on disk.
@@ -4232,7 +4174,6 @@ static int do_journal_end(struct reiserfs_transaction_handle *th,
}
}
}
- flush_old_journal_lists(sb);
journal->j_current_jl->j_list_bitmap =
get_list_bitmap(sb, journal->j_current_jl);
diff --git a/fs/romfs/mmap-nommu.c b/fs/romfs/mmap-nommu.c
index f373bde8f545..f8a9e2bf8d8b 100644
--- a/fs/romfs/mmap-nommu.c
+++ b/fs/romfs/mmap-nommu.c
@@ -73,7 +73,7 @@ static int romfs_mmap(struct file *file, struct vm_area_struct *vma)
const struct file_operations romfs_ro_fops = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.splice_read = generic_file_splice_read,
.mmap = romfs_mmap,
.get_unmapped_area = romfs_get_unmapped_area,
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index c590cabd57bb..d49e6ca3345b 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -497,6 +497,6 @@ EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
void sysfs_remove_bin_file(struct kobject *kobj,
const struct bin_attribute *attr)
{
- sysfs_hash_and_remove(kobj->sd, NULL, attr->attr.name);
+ sysfs_hash_and_remove(kobj->sd, attr->attr.name, NULL);
}
EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 4d83cedb9fcb..d23e66dfba74 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -28,19 +28,19 @@
DEFINE_MUTEX(sysfs_mutex);
DEFINE_SPINLOCK(sysfs_assoc_lock);
-#define to_sysfs_dirent(X) rb_entry((X), struct sysfs_dirent, s_rb);
+#define to_sysfs_dirent(X) rb_entry((X), struct sysfs_dirent, s_rb)
static DEFINE_SPINLOCK(sysfs_ino_lock);
static DEFINE_IDA(sysfs_ino_ida);
/**
* sysfs_name_hash
- * @ns: Namespace tag to hash
* @name: Null terminated string to hash
+ * @ns: Namespace tag to hash
*
* Returns 31 bit hash of ns + name (so it fits in an off_t )
*/
-static unsigned int sysfs_name_hash(const void *ns, const char *name)
+static unsigned int sysfs_name_hash(const char *name, const void *ns)
{
unsigned long hash = init_name_hash();
unsigned int len = strlen(name);
@@ -56,8 +56,8 @@ static unsigned int sysfs_name_hash(const void *ns, const char *name)
return hash;
}
-static int sysfs_name_compare(unsigned int hash, const void *ns,
- const char *name, const struct sysfs_dirent *sd)
+static int sysfs_name_compare(unsigned int hash, const char *name,
+ const void *ns, const struct sysfs_dirent *sd)
{
if (hash != sd->s_hash)
return hash - sd->s_hash;
@@ -69,7 +69,7 @@ static int sysfs_name_compare(unsigned int hash, const void *ns,
static int sysfs_sd_compare(const struct sysfs_dirent *left,
const struct sysfs_dirent *right)
{
- return sysfs_name_compare(left->s_hash, left->s_ns, left->s_name,
+ return sysfs_name_compare(left->s_hash, left->s_name, left->s_ns,
right);
}
@@ -111,6 +111,11 @@ static int sysfs_link_sibling(struct sysfs_dirent *sd)
/* add new node and rebalance the tree */
rb_link_node(&sd->s_rb, parent, node);
rb_insert_color(&sd->s_rb, &sd->s_parent->s_dir.children);
+
+ /* if @sd has ns tag, mark the parent to enable ns filtering */
+ if (sd->s_ns)
+ sd->s_parent->s_flags |= SYSFS_FLAG_HAS_NS;
+
return 0;
}
@@ -130,6 +135,13 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd)
sd->s_parent->s_dir.subdirs--;
rb_erase(&sd->s_rb, &sd->s_parent->s_dir.children);
+
+ /*
+ * Either all or none of the children have tags. Clearing HAS_NS
+ * when there's no child left is enough to keep the flag synced.
+ */
+ if (RB_EMPTY_ROOT(&sd->s_parent->s_dir.children))
+ sd->s_parent->s_flags &= ~SYSFS_FLAG_HAS_NS;
}
#ifdef CONFIG_DEBUG_LOCK_ALLOC
@@ -297,7 +309,6 @@ static int sysfs_dentry_delete(const struct dentry *dentry)
static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags)
{
struct sysfs_dirent *sd;
- int type;
if (flags & LOOKUP_RCU)
return -ECHILD;
@@ -318,13 +329,8 @@ static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags)
goto out_bad;
/* The sysfs dirent has been moved to a different namespace */
- type = KOBJ_NS_TYPE_NONE;
- if (sd->s_parent) {
- type = sysfs_ns_type(sd->s_parent);
- if (type != KOBJ_NS_TYPE_NONE &&
- sysfs_info(dentry->d_sb)->ns[type] != sd->s_ns)
- goto out_bad;
- }
+ if (sd->s_ns && sd->s_ns != sysfs_info(dentry->d_sb)->ns)
+ goto out_bad;
mutex_unlock(&sysfs_mutex);
out_valid:
@@ -445,14 +451,7 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
struct sysfs_inode_attrs *ps_iattr;
int ret;
- if (!!sysfs_ns_type(acxt->parent_sd) != !!sd->s_ns) {
- WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n",
- sysfs_ns_type(acxt->parent_sd) ? "required" : "invalid",
- acxt->parent_sd->s_name, sd->s_name);
- return -EINVAL;
- }
-
- sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name);
+ sd->s_hash = sysfs_name_hash(sd->s_name, sd->s_ns);
sd->s_parent = sysfs_get(acxt->parent_sd);
ret = sysfs_link_sibling(sd);
@@ -597,6 +596,7 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
* sysfs_find_dirent - find sysfs_dirent with the given name
* @parent_sd: sysfs_dirent to search under
* @name: name to look for
+ * @ns: the namespace tag to use
*
* Look for sysfs_dirent with name @name under @parent_sd.
*
@@ -607,26 +607,19 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
* Pointer to sysfs_dirent if found, NULL if not.
*/
struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
- const void *ns,
- const unsigned char *name)
+ const unsigned char *name,
+ const void *ns)
{
struct rb_node *node = parent_sd->s_dir.children.rb_node;
unsigned int hash;
- if (!!sysfs_ns_type(parent_sd) != !!ns) {
- WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n",
- sysfs_ns_type(parent_sd) ? "required" : "invalid",
- parent_sd->s_name, name);
- return NULL;
- }
-
- hash = sysfs_name_hash(ns, name);
+ hash = sysfs_name_hash(name, ns);
while (node) {
struct sysfs_dirent *sd;
int result;
sd = to_sysfs_dirent(node);
- result = sysfs_name_compare(hash, ns, name, sd);
+ result = sysfs_name_compare(hash, name, ns, sd);
if (result < 0)
node = node->rb_left;
else if (result > 0)
@@ -638,9 +631,10 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
}
/**
- * sysfs_get_dirent - find and get sysfs_dirent with the given name
+ * sysfs_get_dirent_ns - find and get sysfs_dirent with the given name
* @parent_sd: sysfs_dirent to search under
* @name: name to look for
+ * @ns: the namespace tag to use
*
* Look for sysfs_dirent with name @name under @parent_sd and get
* it if found.
@@ -651,24 +645,24 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
* RETURNS:
* Pointer to sysfs_dirent if found, NULL if not.
*/
-struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
- const void *ns,
- const unsigned char *name)
+struct sysfs_dirent *sysfs_get_dirent_ns(struct sysfs_dirent *parent_sd,
+ const unsigned char *name,
+ const void *ns)
{
struct sysfs_dirent *sd;
mutex_lock(&sysfs_mutex);
- sd = sysfs_find_dirent(parent_sd, ns, name);
+ sd = sysfs_find_dirent(parent_sd, name, ns);
sysfs_get(sd);
mutex_unlock(&sysfs_mutex);
return sd;
}
-EXPORT_SYMBOL_GPL(sysfs_get_dirent);
+EXPORT_SYMBOL_GPL(sysfs_get_dirent_ns);
static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
- enum kobj_ns_type type, const void *ns, const char *name,
- struct sysfs_dirent **p_sd)
+ const char *name, const void *ns,
+ struct sysfs_dirent **p_sd)
{
umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
struct sysfs_addrm_cxt acxt;
@@ -680,7 +674,6 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
if (!sd)
return -ENOMEM;
- sd->s_flags |= (type << SYSFS_NS_TYPE_SHIFT);
sd->s_ns = ns;
sd->s_dir.kobj = kobj;
@@ -700,44 +693,17 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
int sysfs_create_subdir(struct kobject *kobj, const char *name,
struct sysfs_dirent **p_sd)
{
- return create_dir(kobj, kobj->sd,
- KOBJ_NS_TYPE_NONE, NULL, name, p_sd);
-}
-
-/**
- * sysfs_read_ns_type: return associated ns_type
- * @kobj: the kobject being queried
- *
- * Each kobject can be tagged with exactly one namespace type
- * (i.e. network or user). Return the ns_type associated with
- * this object if any
- */
-static enum kobj_ns_type sysfs_read_ns_type(struct kobject *kobj)
-{
- const struct kobj_ns_type_operations *ops;
- enum kobj_ns_type type;
-
- ops = kobj_child_ns_ops(kobj);
- if (!ops)
- return KOBJ_NS_TYPE_NONE;
-
- type = ops->type;
- BUG_ON(type <= KOBJ_NS_TYPE_NONE);
- BUG_ON(type >= KOBJ_NS_TYPES);
- BUG_ON(!kobj_ns_type_registered(type));
-
- return type;
+ return create_dir(kobj, kobj->sd, name, NULL, p_sd);
}
/**
- * sysfs_create_dir - create a directory for an object.
- * @kobj: object we're creating directory for.
+ * sysfs_create_dir_ns - create a directory for an object with a namespace tag
+ * @kobj: object we're creating directory for
+ * @ns: the namespace tag to use
*/
-int sysfs_create_dir(struct kobject *kobj)
+int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
{
- enum kobj_ns_type type;
struct sysfs_dirent *parent_sd, *sd;
- const void *ns = NULL;
int error = 0;
BUG_ON(!kobj);
@@ -750,11 +716,7 @@ int sysfs_create_dir(struct kobject *kobj)
if (!parent_sd)
return -ENOENT;
- if (sysfs_ns_type(parent_sd))
- ns = kobj->ktype->namespace(kobj);
- type = sysfs_read_ns_type(kobj);
-
- error = create_dir(kobj, parent_sd, type, ns, kobject_name(kobj), &sd);
+ error = create_dir(kobj, parent_sd, kobject_name(kobj), ns, &sd);
if (!error)
kobj->sd = sd;
return error;
@@ -768,15 +730,14 @@ static struct dentry *sysfs_lookup(struct inode *dir, struct dentry *dentry,
struct sysfs_dirent *parent_sd = parent->d_fsdata;
struct sysfs_dirent *sd;
struct inode *inode;
- enum kobj_ns_type type;
- const void *ns;
+ const void *ns = NULL;
mutex_lock(&sysfs_mutex);
- type = sysfs_ns_type(parent_sd);
- ns = sysfs_info(dir->i_sb)->ns[type];
+ if (parent_sd->s_flags & SYSFS_FLAG_HAS_NS)
+ ns = sysfs_info(dir->i_sb)->ns;
- sd = sysfs_find_dirent(parent_sd, ns, dentry->d_name.name);
+ sd = sysfs_find_dirent(parent_sd, dentry->d_name.name, ns);
/* no such entry */
if (!sd) {
@@ -864,9 +825,8 @@ void sysfs_remove_dir(struct kobject *kobj)
__sysfs_remove_dir(sd);
}
-int sysfs_rename(struct sysfs_dirent *sd,
- struct sysfs_dirent *new_parent_sd, const void *new_ns,
- const char *new_name)
+int sysfs_rename(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent_sd,
+ const char *new_name, const void *new_ns)
{
int error;
@@ -878,7 +838,7 @@ int sysfs_rename(struct sysfs_dirent *sd,
goto out; /* nothing to rename */
error = -EEXIST;
- if (sysfs_find_dirent(new_parent_sd, new_ns, new_name))
+ if (sysfs_find_dirent(new_parent_sd, new_name, new_ns))
goto out;
/* rename sysfs_dirent */
@@ -899,7 +859,7 @@ int sysfs_rename(struct sysfs_dirent *sd,
sysfs_get(new_parent_sd);
sysfs_put(sd->s_parent);
sd->s_ns = new_ns;
- sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name);
+ sd->s_hash = sysfs_name_hash(sd->s_name, sd->s_ns);
sd->s_parent = new_parent_sd;
sysfs_link_sibling(sd);
@@ -909,30 +869,25 @@ int sysfs_rename(struct sysfs_dirent *sd,
return error;
}
-int sysfs_rename_dir(struct kobject *kobj, const char *new_name)
+int sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
+ const void *new_ns)
{
struct sysfs_dirent *parent_sd = kobj->sd->s_parent;
- const void *new_ns = NULL;
-
- if (sysfs_ns_type(parent_sd))
- new_ns = kobj->ktype->namespace(kobj);
- return sysfs_rename(kobj->sd, parent_sd, new_ns, new_name);
+ return sysfs_rename(kobj->sd, parent_sd, new_name, new_ns);
}
-int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
+int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj,
+ const void *new_ns)
{
struct sysfs_dirent *sd = kobj->sd;
struct sysfs_dirent *new_parent_sd;
- const void *new_ns = NULL;
BUG_ON(!sd->s_parent);
- if (sysfs_ns_type(sd->s_parent))
- new_ns = kobj->ktype->namespace(kobj);
new_parent_sd = new_parent_kobj && new_parent_kobj->sd ?
new_parent_kobj->sd : &sysfs_root;
- return sysfs_rename(sd, new_parent_sd, new_ns, sd->s_name);
+ return sysfs_rename(sd, new_parent_sd, sd->s_name, new_ns);
}
/* Relationship between s_mode and the DT_xxx types */
@@ -1002,15 +957,15 @@ static int sysfs_readdir(struct file *file, struct dir_context *ctx)
struct dentry *dentry = file->f_path.dentry;
struct sysfs_dirent *parent_sd = dentry->d_fsdata;
struct sysfs_dirent *pos = file->private_data;
- enum kobj_ns_type type;
- const void *ns;
-
- type = sysfs_ns_type(parent_sd);
- ns = sysfs_info(dentry->d_sb)->ns[type];
+ const void *ns = NULL;
if (!dir_emit_dots(file, ctx))
return 0;
mutex_lock(&sysfs_mutex);
+
+ if (parent_sd->s_flags & SYSFS_FLAG_HAS_NS)
+ ns = sysfs_info(dentry->d_sb)->ns;
+
for (pos = sysfs_dir_pos(ns, parent_sd, ctx->pos, pos);
pos;
pos = sysfs_dir_next_pos(ns, parent_sd, ctx->pos, pos)) {
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 15ef5eb13663..4697019fafa3 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -466,9 +466,9 @@ void sysfs_notify(struct kobject *k, const char *dir, const char *attr)
mutex_lock(&sysfs_mutex);
if (sd && dir)
- sd = sysfs_find_dirent(sd, NULL, dir);
+ sd = sysfs_find_dirent(sd, dir, NULL);
if (sd && attr)
- sd = sysfs_find_dirent(sd, NULL, attr);
+ sd = sysfs_find_dirent(sd, attr, NULL);
if (sd)
sysfs_notify_dirent(sd);
@@ -485,58 +485,15 @@ const struct file_operations sysfs_file_operations = {
.poll = sysfs_poll,
};
-static int sysfs_attr_ns(struct kobject *kobj, const struct attribute *attr,
- const void **pns)
-{
- struct sysfs_dirent *dir_sd = kobj->sd;
- const struct sysfs_ops *ops;
- const void *ns = NULL;
- int err;
-
- if (!dir_sd) {
- WARN(1, KERN_ERR "sysfs: kobject %s without dirent\n",
- kobject_name(kobj));
- return -ENOENT;
- }
-
- err = 0;
- if (!sysfs_ns_type(dir_sd))
- goto out;
-
- err = -EINVAL;
- if (!kobj->ktype)
- goto out;
- ops = kobj->ktype->sysfs_ops;
- if (!ops)
- goto out;
- if (!ops->namespace)
- goto out;
-
- err = 0;
- ns = ops->namespace(kobj, attr);
-out:
- if (err) {
- WARN(1, KERN_ERR
- "missing sysfs namespace attribute operation for kobject: %s\n",
- kobject_name(kobj));
- }
- *pns = ns;
- return err;
-}
-
-int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,
- const struct attribute *attr, int type, umode_t amode)
+int sysfs_add_file_mode_ns(struct sysfs_dirent *dir_sd,
+ const struct attribute *attr, int type,
+ umode_t amode, const void *ns)
{
umode_t mode = (amode & S_IALLUGO) | S_IFREG;
struct sysfs_addrm_cxt acxt;
struct sysfs_dirent *sd;
- const void *ns;
int rc;
- rc = sysfs_attr_ns(dir_sd->s_dir.kobj, attr, &ns);
- if (rc)
- return rc;
-
sd = sysfs_new_dirent(attr->name, mode, type);
if (!sd)
return -ENOMEM;
@@ -559,23 +516,25 @@ int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,
int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
int type)
{
- return sysfs_add_file_mode(dir_sd, attr, type, attr->mode);
+ return sysfs_add_file_mode_ns(dir_sd, attr, type, attr->mode, NULL);
}
-
/**
- * sysfs_create_file - create an attribute file for an object.
- * @kobj: object we're creating for.
- * @attr: attribute descriptor.
+ * sysfs_create_file_ns - create an attribute file for an object with custom ns
+ * @kobj: object we're creating for
+ * @attr: attribute descriptor
+ * @ns: namespace the new file should belong to
*/
-int sysfs_create_file(struct kobject *kobj, const struct attribute *attr)
+int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr,
+ const void *ns)
{
BUG_ON(!kobj || !kobj->sd || !attr);
- return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR);
+ return sysfs_add_file_mode_ns(kobj->sd, attr, SYSFS_KOBJ_ATTR,
+ attr->mode, ns);
}
-EXPORT_SYMBOL_GPL(sysfs_create_file);
+EXPORT_SYMBOL_GPL(sysfs_create_file_ns);
int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr)
{
@@ -604,7 +563,7 @@ int sysfs_add_file_to_group(struct kobject *kobj,
int error;
if (group)
- dir_sd = sysfs_get_dirent(kobj->sd, NULL, group);
+ dir_sd = sysfs_get_dirent(kobj->sd, group);
else
dir_sd = sysfs_get(kobj->sd);
@@ -630,17 +589,12 @@ int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr,
{
struct sysfs_dirent *sd;
struct iattr newattrs;
- const void *ns;
int rc;
- rc = sysfs_attr_ns(kobj, attr, &ns);
- if (rc)
- return rc;
-
mutex_lock(&sysfs_mutex);
rc = -ENOENT;
- sd = sysfs_find_dirent(kobj->sd, ns, attr->name);
+ sd = sysfs_find_dirent(kobj->sd, attr->name, NULL);
if (!sd)
goto out;
@@ -655,22 +609,21 @@ int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr,
EXPORT_SYMBOL_GPL(sysfs_chmod_file);
/**
- * sysfs_remove_file - remove an object attribute.
- * @kobj: object we're acting for.
- * @attr: attribute descriptor.
+ * sysfs_remove_file_ns - remove an object attribute with a custom ns tag
+ * @kobj: object we're acting for
+ * @attr: attribute descriptor
+ * @ns: namespace tag of the file to remove
*
- * Hash the attribute name and kill the victim.
+ * Hash the attribute name and namespace tag and kill the victim.
*/
-void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr)
+void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr,
+ const void *ns)
{
- const void *ns;
-
- if (sysfs_attr_ns(kobj, attr, &ns))
- return;
+ struct sysfs_dirent *dir_sd = kobj->sd;
- sysfs_hash_and_remove(kobj->sd, ns, attr->name);
+ sysfs_hash_and_remove(dir_sd, attr->name, ns);
}
-EXPORT_SYMBOL_GPL(sysfs_remove_file);
+EXPORT_SYMBOL_GPL(sysfs_remove_file_ns);
void sysfs_remove_files(struct kobject *kobj, const struct attribute **ptr)
{
@@ -692,11 +645,11 @@ void sysfs_remove_file_from_group(struct kobject *kobj,
struct sysfs_dirent *dir_sd;
if (group)
- dir_sd = sysfs_get_dirent(kobj->sd, NULL, group);
+ dir_sd = sysfs_get_dirent(kobj->sd, group);
else
dir_sd = sysfs_get(kobj->sd);
if (dir_sd) {
- sysfs_hash_and_remove(dir_sd, NULL, attr->name);
+ sysfs_hash_and_remove(dir_sd, attr->name, NULL);
sysfs_put(dir_sd);
}
}
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 5f92cd2f61c1..2dae55c4f7dc 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -26,7 +26,7 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
if (grp->attrs)
for (attr = grp->attrs; *attr; attr++)
- sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name);
+ sysfs_hash_and_remove(dir_sd, (*attr)->name, NULL);
if (grp->bin_attrs)
for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++)
sysfs_remove_bin_file(kobj, *bin_attr);
@@ -49,16 +49,17 @@ static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
* re-adding (if required) the file.
*/
if (update)
- sysfs_hash_and_remove(dir_sd, NULL,
- (*attr)->name);
+ sysfs_hash_and_remove(dir_sd, (*attr)->name,
+ NULL);
if (grp->is_visible) {
mode = grp->is_visible(kobj, *attr, i);
if (!mode)
continue;
}
- error = sysfs_add_file_mode(dir_sd, *attr,
- SYSFS_KOBJ_ATTR,
- (*attr)->mode | mode);
+ error = sysfs_add_file_mode_ns(dir_sd, *attr,
+ SYSFS_KOBJ_ATTR,
+ (*attr)->mode | mode,
+ NULL);
if (unlikely(error))
break;
}
@@ -206,7 +207,7 @@ void sysfs_remove_group(struct kobject *kobj,
struct sysfs_dirent *sd;
if (grp->name) {
- sd = sysfs_get_dirent(dir_sd, NULL, grp->name);
+ sd = sysfs_get_dirent(dir_sd, grp->name);
if (!sd) {
WARN(!sd, KERN_WARNING
"sysfs group %p not found for kobject '%s'\n",
@@ -261,7 +262,7 @@ int sysfs_merge_group(struct kobject *kobj,
struct attribute *const *attr;
int i;
- dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name);
+ dir_sd = sysfs_get_dirent(kobj->sd, grp->name);
if (!dir_sd)
return -ENOENT;
@@ -269,7 +270,7 @@ int sysfs_merge_group(struct kobject *kobj,
error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
if (error) {
while (--i >= 0)
- sysfs_hash_and_remove(dir_sd, NULL, (*--attr)->name);
+ sysfs_hash_and_remove(dir_sd, (*--attr)->name, NULL);
}
sysfs_put(dir_sd);
@@ -288,10 +289,10 @@ void sysfs_unmerge_group(struct kobject *kobj,
struct sysfs_dirent *dir_sd;
struct attribute *const *attr;
- dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name);
+ dir_sd = sysfs_get_dirent(kobj->sd, grp->name);
if (dir_sd) {
for (attr = grp->attrs; *attr; ++attr)
- sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name);
+ sysfs_hash_and_remove(dir_sd, (*attr)->name, NULL);
sysfs_put(dir_sd);
}
}
@@ -310,7 +311,7 @@ int sysfs_add_link_to_group(struct kobject *kobj, const char *group_name,
struct sysfs_dirent *dir_sd;
int error = 0;
- dir_sd = sysfs_get_dirent(kobj->sd, NULL, group_name);
+ dir_sd = sysfs_get_dirent(kobj->sd, group_name);
if (!dir_sd)
return -ENOENT;
@@ -332,9 +333,9 @@ void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name,
{
struct sysfs_dirent *dir_sd;
- dir_sd = sysfs_get_dirent(kobj->sd, NULL, group_name);
+ dir_sd = sysfs_get_dirent(kobj->sd, group_name);
if (dir_sd) {
- sysfs_hash_and_remove(dir_sd, NULL, link_name);
+ sysfs_hash_and_remove(dir_sd, link_name, NULL);
sysfs_put(dir_sd);
}
}
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 963f910c8034..07193d720d92 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -314,8 +314,8 @@ void sysfs_evict_inode(struct inode *inode)
sysfs_put(sd);
}
-int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns,
- const char *name)
+int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name,
+ const void *ns)
{
struct sysfs_addrm_cxt acxt;
struct sysfs_dirent *sd;
@@ -328,7 +328,7 @@ int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns,
sysfs_addrm_start(&acxt, dir_sd);
- sd = sysfs_find_dirent(dir_sd, ns, name);
+ sd = sysfs_find_dirent(dir_sd, name, ns);
if (sd)
sysfs_remove_one(&acxt, sd);
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 834ec2cdb7a3..8c24bce2f4ae 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -36,7 +36,7 @@ static const struct super_operations sysfs_ops = {
struct sysfs_dirent sysfs_root = {
.s_name = "",
.s_count = ATOMIC_INIT(1),
- .s_flags = SYSFS_DIR | (KOBJ_NS_TYPE_NONE << SYSFS_NS_TYPE_SHIFT),
+ .s_flags = SYSFS_DIR,
.s_mode = S_IFDIR | S_IRUGO | S_IXUGO,
.s_ino = 1,
};
@@ -77,14 +77,8 @@ static int sysfs_test_super(struct super_block *sb, void *data)
{
struct sysfs_super_info *sb_info = sysfs_info(sb);
struct sysfs_super_info *info = data;
- enum kobj_ns_type type;
- int found = 1;
- for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) {
- if (sb_info->ns[type] != info->ns[type])
- found = 0;
- }
- return found;
+ return sb_info->ns == info->ns;
}
static int sysfs_set_super(struct super_block *sb, void *data)
@@ -98,9 +92,7 @@ static int sysfs_set_super(struct super_block *sb, void *data)
static void free_sysfs_super_info(struct sysfs_super_info *info)
{
- int type;
- for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++)
- kobj_ns_drop(type, info->ns[type]);
+ kobj_ns_drop(KOBJ_NS_TYPE_NET, info->ns);
kfree(info);
}
@@ -108,7 +100,6 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
struct sysfs_super_info *info;
- enum kobj_ns_type type;
struct super_block *sb;
int error;
@@ -116,18 +107,15 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
if (!capable(CAP_SYS_ADMIN) && !fs_fully_visible(fs_type))
return ERR_PTR(-EPERM);
- for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) {
- if (!kobj_ns_current_may_mount(type))
- return ERR_PTR(-EPERM);
- }
+ if (!kobj_ns_current_may_mount(KOBJ_NS_TYPE_NET))
+ return ERR_PTR(-EPERM);
}
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return ERR_PTR(-ENOMEM);
- for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++)
- info->ns[type] = kobj_ns_grab_current(type);
+ info->ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
sb = sget(fs_type, sysfs_test_super, sysfs_set_super, flags, info);
if (IS_ERR(sb) || sb->s_fs_info != info)
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 2dd4507d9edd..88c8bc5e8911 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -28,7 +28,6 @@ static int sysfs_do_create_link_sd(struct sysfs_dirent *parent_sd,
struct sysfs_dirent *target_sd = NULL;
struct sysfs_dirent *sd = NULL;
struct sysfs_addrm_cxt acxt;
- enum kobj_ns_type ns_type;
int error;
BUG_ON(!name || !parent_sd);
@@ -50,29 +49,15 @@ static int sysfs_do_create_link_sd(struct sysfs_dirent *parent_sd,
if (!sd)
goto out_put;
- ns_type = sysfs_ns_type(parent_sd);
- if (ns_type)
- sd->s_ns = target->ktype->namespace(target);
+ sd->s_ns = target_sd->s_ns;
sd->s_symlink.target_sd = target_sd;
target_sd = NULL; /* reference is now owned by the symlink */
sysfs_addrm_start(&acxt, parent_sd);
- /* Symlinks must be between directories with the same ns_type */
- if (!ns_type ||
- (ns_type == sysfs_ns_type(sd->s_symlink.target_sd->s_parent))) {
- if (warn)
- error = sysfs_add_one(&acxt, sd);
- else
- error = __sysfs_add_one(&acxt, sd);
- } else {
- error = -EINVAL;
- WARN(1, KERN_WARNING
- "sysfs: symlink across ns_types %s/%s -> %s/%s\n",
- parent_sd->s_name,
- sd->s_name,
- sd->s_symlink.target_sd->s_parent->s_name,
- sd->s_symlink.target_sd->s_name);
- }
+ if (warn)
+ error = sysfs_add_one(&acxt, sd);
+ else
+ error = __sysfs_add_one(&acxt, sd);
sysfs_addrm_finish(&acxt);
if (error)
@@ -156,10 +141,10 @@ void sysfs_delete_link(struct kobject *kobj, struct kobject *targ,
{
const void *ns = NULL;
spin_lock(&sysfs_assoc_lock);
- if (targ->sd && sysfs_ns_type(kobj->sd))
+ if (targ->sd)
ns = targ->sd->s_ns;
spin_unlock(&sysfs_assoc_lock);
- sysfs_hash_and_remove(kobj->sd, ns, name);
+ sysfs_hash_and_remove(kobj->sd, name, ns);
}
/**
@@ -176,24 +161,25 @@ void sysfs_remove_link(struct kobject *kobj, const char *name)
else
parent_sd = kobj->sd;
- sysfs_hash_and_remove(parent_sd, NULL, name);
+ sysfs_hash_and_remove(parent_sd, name, NULL);
}
EXPORT_SYMBOL_GPL(sysfs_remove_link);
/**
- * sysfs_rename_link - rename symlink in object's directory.
+ * sysfs_rename_link_ns - rename symlink in object's directory.
* @kobj: object we're acting for.
* @targ: object we're pointing to.
* @old: previous name of the symlink.
* @new: new name of the symlink.
+ * @new_ns: new namespace of the symlink.
*
* A helper function for the common rename symlink idiom.
*/
-int sysfs_rename_link(struct kobject *kobj, struct kobject *targ,
- const char *old, const char *new)
+int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *targ,
+ const char *old, const char *new, const void *new_ns)
{
struct sysfs_dirent *parent_sd, *sd = NULL;
- const void *old_ns = NULL, *new_ns = NULL;
+ const void *old_ns = NULL;
int result;
if (!kobj)
@@ -205,7 +191,7 @@ int sysfs_rename_link(struct kobject *kobj, struct kobject *targ,
old_ns = targ->sd->s_ns;
result = -ENOENT;
- sd = sysfs_get_dirent(parent_sd, old_ns, old);
+ sd = sysfs_get_dirent_ns(parent_sd, old, old_ns);
if (!sd)
goto out;
@@ -215,16 +201,13 @@ int sysfs_rename_link(struct kobject *kobj, struct kobject *targ,
if (sd->s_symlink.target_sd->s_dir.kobj != targ)
goto out;
- if (sysfs_ns_type(parent_sd))
- new_ns = targ->ktype->namespace(targ);
-
- result = sysfs_rename(sd, parent_sd, new_ns, new);
+ result = sysfs_rename(sd, parent_sd, new, new_ns);
out:
sysfs_put(sd);
return result;
}
-EXPORT_SYMBOL_GPL(sysfs_rename_link);
+EXPORT_SYMBOL_GPL(sysfs_rename_link_ns);
static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
struct sysfs_dirent *target_sd, char *path)
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index b6deca3e301d..ee44fde199d0 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -93,11 +93,8 @@ struct sysfs_dirent {
#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK)
#define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR)
-/* identify any namespace tag on sysfs_dirents */
-#define SYSFS_NS_TYPE_MASK 0xf00
-#define SYSFS_NS_TYPE_SHIFT 8
-
-#define SYSFS_FLAG_MASK ~(SYSFS_NS_TYPE_MASK|SYSFS_TYPE_MASK)
+#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK
+#define SYSFS_FLAG_HAS_NS 0x01000
#define SYSFS_FLAG_REMOVED 0x02000
static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
@@ -105,15 +102,6 @@ static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
return sd->s_flags & SYSFS_TYPE_MASK;
}
-/*
- * Return any namespace tags on this dirent.
- * enum kobj_ns_type is defined in linux/kobject.h
- */
-static inline enum kobj_ns_type sysfs_ns_type(struct sysfs_dirent *sd)
-{
- return (sd->s_flags & SYSFS_NS_TYPE_MASK) >> SYSFS_NS_TYPE_SHIFT;
-}
-
#ifdef CONFIG_DEBUG_LOCK_ALLOC
#define sysfs_dirent_init_lockdep(sd) \
do { \
@@ -141,12 +129,13 @@ struct sysfs_addrm_cxt {
*/
/*
- * Each sb is associated with a set of namespace tags (i.e.
- * the network namespace of the task which mounted this sysfs
- * instance).
+ * Each sb is associated with one namespace tag, currently the network
+ * namespace of the task which mounted this sysfs instance. If multiple
+ * tags become necessary, make the following an array and compare
+ * sysfs_dirent tag against every entry.
*/
struct sysfs_super_info {
- void *ns[KOBJ_NS_TYPES];
+ void *ns;
};
#define sysfs_info(SB) ((struct sysfs_super_info *)(SB->s_fs_info))
extern struct sysfs_dirent sysfs_root;
@@ -173,11 +162,8 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
- const void *ns,
- const unsigned char *name);
-struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
- const void *ns,
- const unsigned char *name);
+ const unsigned char *name,
+ const void *ns);
struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type);
void release_sysfs_dirent(struct sysfs_dirent *sd);
@@ -187,7 +173,7 @@ int sysfs_create_subdir(struct kobject *kobj, const char *name,
void sysfs_remove_subdir(struct sysfs_dirent *sd);
int sysfs_rename(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent_sd,
- const void *ns, const char *new_name);
+ const char *new_name, const void *new_ns);
static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd)
{
@@ -218,8 +204,8 @@ int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat);
int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
size_t size, int flags);
-int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns,
- const char *name);
+int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name,
+ const void *ns);
int sysfs_inode_init(void);
/*
@@ -230,8 +216,9 @@ extern const struct file_operations sysfs_file_operations;
int sysfs_add_file(struct sysfs_dirent *dir_sd,
const struct attribute *attr, int type);
-int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,
- const struct attribute *attr, int type, umode_t amode);
+int sysfs_add_file_mode_ns(struct sysfs_dirent *dir_sd,
+ const struct attribute *attr, int type,
+ umode_t amode, const void *ns);
/*
* bin.c
*/
diff --git a/fs/sysv/file.c b/fs/sysv/file.c
index 9d4dc6831792..ff4b363ba5c9 100644
--- a/fs/sysv/file.c
+++ b/fs/sysv/file.c
@@ -22,9 +22,9 @@
const struct file_operations sysv_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.write = do_sync_write,
- .aio_write = generic_file_aio_write,
+ .write_iter = generic_file_write_iter,
.mmap = generic_file_mmap,
.fsync = generic_file_fsync,
.splice_read = generic_file_splice_read,
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 6b4947f75af7..ea41649e4ca5 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -192,8 +192,7 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
struct ubifs_dent_node *dent;
struct ubifs_info *c = dir->i_sb->s_fs_info;
- dbg_gen("'%.*s' in dir ino %lu",
- dentry->d_name.len, dentry->d_name.name, dir->i_ino);
+ dbg_gen("'%pd' in dir ino %lu", dentry, dir->i_ino);
if (dentry->d_name.len > UBIFS_MAX_NLEN)
return ERR_PTR(-ENAMETOOLONG);
@@ -225,8 +224,8 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
* checking.
*/
err = PTR_ERR(inode);
- ubifs_err("dead directory entry '%.*s', error %d",
- dentry->d_name.len, dentry->d_name.name, err);
+ ubifs_err("dead directory entry '%pd', error %d",
+ dentry, err);
ubifs_ro_mode(c, err);
goto out;
}
@@ -260,8 +259,8 @@ static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
* parent directory inode.
*/
- dbg_gen("dent '%.*s', mode %#hx in dir ino %lu",
- dentry->d_name.len, dentry->d_name.name, mode, dir->i_ino);
+ dbg_gen("dent '%pd', mode %#hx in dir ino %lu",
+ dentry, mode, dir->i_ino);
err = ubifs_budget_space(c, &req);
if (err)
@@ -509,8 +508,8 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
* changing the parent inode.
*/
- dbg_gen("dent '%.*s' to ino %lu (nlink %d) in dir ino %lu",
- dentry->d_name.len, dentry->d_name.name, inode->i_ino,
+ dbg_gen("dent '%pd' to ino %lu (nlink %d) in dir ino %lu",
+ dentry, inode->i_ino,
inode->i_nlink, dir->i_ino);
ubifs_assert(mutex_is_locked(&dir->i_mutex));
ubifs_assert(mutex_is_locked(&inode->i_mutex));
@@ -566,8 +565,8 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
* deletions.
*/
- dbg_gen("dent '%.*s' from ino %lu (nlink %d) in dir ino %lu",
- dentry->d_name.len, dentry->d_name.name, inode->i_ino,
+ dbg_gen("dent '%pd' from ino %lu (nlink %d) in dir ino %lu",
+ dentry, inode->i_ino,
inode->i_nlink, dir->i_ino);
ubifs_assert(mutex_is_locked(&dir->i_mutex));
ubifs_assert(mutex_is_locked(&inode->i_mutex));
@@ -656,8 +655,8 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
* because we have extra space reserved for deletions.
*/
- dbg_gen("directory '%.*s', ino %lu in dir ino %lu", dentry->d_name.len,
- dentry->d_name.name, inode->i_ino, dir->i_ino);
+ dbg_gen("directory '%pd', ino %lu in dir ino %lu", dentry,
+ inode->i_ino, dir->i_ino);
ubifs_assert(mutex_is_locked(&dir->i_mutex));
ubifs_assert(mutex_is_locked(&inode->i_mutex));
err = check_dir_empty(c, dentry->d_inode);
@@ -716,8 +715,8 @@ static int ubifs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
* directory inode.
*/
- dbg_gen("dent '%.*s', mode %#hx in dir ino %lu",
- dentry->d_name.len, dentry->d_name.name, mode, dir->i_ino);
+ dbg_gen("dent '%pd', mode %#hx in dir ino %lu",
+ dentry, mode, dir->i_ino);
err = ubifs_budget_space(c, &req);
if (err)
@@ -778,8 +777,7 @@ static int ubifs_mknod(struct inode *dir, struct dentry *dentry,
* directory inode.
*/
- dbg_gen("dent '%.*s' in dir ino %lu",
- dentry->d_name.len, dentry->d_name.name, dir->i_ino);
+ dbg_gen("dent '%pd' in dir ino %lu", dentry, dir->i_ino);
if (!new_valid_dev(rdev))
return -EINVAL;
@@ -853,8 +851,8 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
* directory inode.
*/
- dbg_gen("dent '%.*s', target '%s' in dir ino %lu", dentry->d_name.len,
- dentry->d_name.name, symname, dir->i_ino);
+ dbg_gen("dent '%pd', target '%s' in dir ino %lu", dentry,
+ symname, dir->i_ino);
if (len > UBIFS_MAX_INO_DATA)
return -ENAMETOOLONG;
@@ -979,10 +977,9 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
* separately.
*/
- dbg_gen("dent '%.*s' ino %lu in dir ino %lu to dent '%.*s' in dir ino %lu",
- old_dentry->d_name.len, old_dentry->d_name.name,
- old_inode->i_ino, old_dir->i_ino, new_dentry->d_name.len,
- new_dentry->d_name.name, new_dir->i_ino);
+ dbg_gen("dent '%pd' ino %lu in dir ino %lu to dent '%pd' in dir ino %lu",
+ old_dentry, old_inode->i_ino, old_dir->i_ino,
+ new_dentry, new_dir->i_ino);
ubifs_assert(mutex_is_locked(&old_dir->i_mutex));
ubifs_assert(mutex_is_locked(&new_dir->i_mutex));
if (unlink)
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 123c79b7261e..22924e048ac0 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -44,7 +44,7 @@
* 'ubifs_writepage()' we are only guaranteed that the page is locked.
*
* Similarly, @i_mutex is not always locked in 'ubifs_readpage()', e.g., the
- * read-ahead path does not lock it ("sys_read -> generic_file_aio_read ->
+ * read-ahead path does not lock it ("sys_read -> generic_file_read_iter ->
* ondemand_readahead -> readpage"). In case of readahead, @I_SYNC flag is not
* set as well. However, UBIFS disables readahead.
*/
@@ -1396,8 +1396,8 @@ static int update_mctime(struct ubifs_info *c, struct inode *inode)
return 0;
}
-static ssize_t ubifs_aio_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
+static ssize_t ubifs_write_iter(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos)
{
int err;
struct inode *inode = iocb->ki_filp->f_mapping->host;
@@ -1407,7 +1407,7 @@ static ssize_t ubifs_aio_write(struct kiocb *iocb, const struct iovec *iov,
if (err)
return err;
- return generic_file_aio_write(iocb, iov, nr_segs, pos);
+ return generic_file_write_iter(iocb, iter, pos);
}
static int ubifs_set_page_dirty(struct page *page)
@@ -1583,8 +1583,8 @@ const struct file_operations ubifs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .aio_read = generic_file_aio_read,
- .aio_write = ubifs_aio_write,
+ .read_iter = generic_file_read_iter,
+ .write_iter = ubifs_write_iter,
.mmap = ubifs_file_mmap,
.fsync = ubifs_fsync,
.unlocked_ioctl = ubifs_ioctl,
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index afaad07f3b29..0e045e75abd8 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -933,10 +933,8 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
int move = (old_dir != new_dir);
struct ubifs_inode *uninitialized_var(new_ui);
- dbg_jnl("dent '%.*s' in dir ino %lu to dent '%.*s' in dir ino %lu",
- old_dentry->d_name.len, old_dentry->d_name.name,
- old_dir->i_ino, new_dentry->d_name.len,
- new_dentry->d_name.name, new_dir->i_ino);
+ dbg_jnl("dent '%pd' in dir ino %lu to dent '%pd' in dir ino %lu",
+ old_dentry, old_dir->i_ino, new_dentry, new_dir->i_ino);
ubifs_assert(ubifs_inode(old_dir)->data_len == 0);
ubifs_assert(ubifs_inode(new_dir)->data_len == 0);
ubifs_assert(mutex_is_locked(&ubifs_inode(old_dir)->ui_mutex));
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index 0f7139bdb2c2..5e0a63b1b0d5 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -303,8 +303,8 @@ int ubifs_setxattr(struct dentry *dentry, const char *name,
union ubifs_key key;
int err, type;
- dbg_gen("xattr '%s', host ino %lu ('%.*s'), size %zd", name,
- host->i_ino, dentry->d_name.len, dentry->d_name.name, size);
+ dbg_gen("xattr '%s', host ino %lu ('%pd'), size %zd", name,
+ host->i_ino, dentry, size);
ubifs_assert(mutex_is_locked(&host->i_mutex));
if (size > UBIFS_MAX_INO_DATA)
@@ -367,8 +367,8 @@ ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf,
union ubifs_key key;
int err;
- dbg_gen("xattr '%s', ino %lu ('%.*s'), buf size %zd", name,
- host->i_ino, dentry->d_name.len, dentry->d_name.name, size);
+ dbg_gen("xattr '%s', ino %lu ('%pd'), buf size %zd", name,
+ host->i_ino, dentry, size);
err = check_namespace(&nm);
if (err < 0)
@@ -426,8 +426,8 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size)
int err, len, written = 0;
struct qstr nm = { .name = NULL };
- dbg_gen("ino %lu ('%.*s'), buffer size %zd", host->i_ino,
- dentry->d_name.len, dentry->d_name.name, size);
+ dbg_gen("ino %lu ('%pd'), buffer size %zd", host->i_ino,
+ dentry, size);
len = host_ui->xattr_names + host_ui->xattr_cnt;
if (!buffer)
@@ -529,8 +529,8 @@ int ubifs_removexattr(struct dentry *dentry, const char *name)
union ubifs_key key;
int err;
- dbg_gen("xattr '%s', ino %lu ('%.*s')", name,
- host->i_ino, dentry->d_name.len, dentry->d_name.name);
+ dbg_gen("xattr '%s', ino %lu ('%pd')", name,
+ host->i_ino, dentry);
ubifs_assert(mutex_is_locked(&host->i_mutex));
err = check_namespace(&nm);
diff --git a/fs/udf/file.c b/fs/udf/file.c
index c02a27a19c6d..9985beecffca 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -119,8 +119,7 @@ static int udf_adinicb_write_end(struct file *file,
}
static ssize_t udf_adinicb_direct_IO(int rw, struct kiocb *iocb,
- const struct iovec *iov,
- loff_t offset, unsigned long nr_segs)
+ struct iov_iter *iter, loff_t offset)
{
/* Fallback to buffered I/O. */
return 0;
@@ -134,8 +133,8 @@ const struct address_space_operations udf_adinicb_aops = {
.direct_IO = udf_adinicb_direct_IO,
};
-static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t ppos)
+static ssize_t udf_file_write_iter(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t ppos)
{
ssize_t retval;
struct file *file = iocb->ki_filp;
@@ -169,7 +168,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
} else
up_write(&iinfo->i_data_sem);
- retval = generic_file_aio_write(iocb, iov, nr_segs, ppos);
+ retval = generic_file_write_iter(iocb, iter, ppos);
if (retval > 0)
mark_inode_dirty(inode);
@@ -243,12 +242,12 @@ static int udf_release_file(struct inode *inode, struct file *filp)
const struct file_operations udf_file_operations = {
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.unlocked_ioctl = udf_ioctl,
.open = generic_file_open,
.mmap = generic_file_mmap,
.write = do_sync_write,
- .aio_write = udf_file_aio_write,
+ .write_iter = udf_file_write_iter,
.release = udf_release_file,
.fsync = generic_file_fsync,
.splice_read = generic_file_splice_read,
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
index 7e5aae4bf46f..6eaf5edf1ea1 100644
--- a/fs/udf/ialloc.c
+++ b/fs/udf/ialloc.c
@@ -30,18 +30,17 @@ void udf_free_inode(struct inode *inode)
{
struct super_block *sb = inode->i_sb;
struct udf_sb_info *sbi = UDF_SB(sb);
+ struct logicalVolIntegrityDescImpUse *lvidiu = udf_sb_lvidiu(sb);
- mutex_lock(&sbi->s_alloc_mutex);
- if (sbi->s_lvid_bh) {
- struct logicalVolIntegrityDescImpUse *lvidiu =
- udf_sb_lvidiu(sbi);
+ if (lvidiu) {
+ mutex_lock(&sbi->s_alloc_mutex);
if (S_ISDIR(inode->i_mode))
le32_add_cpu(&lvidiu->numDirs, -1);
else
le32_add_cpu(&lvidiu->numFiles, -1);
udf_updated_lvid(sb);
+ mutex_unlock(&sbi->s_alloc_mutex);
}
- mutex_unlock(&sbi->s_alloc_mutex);
udf_free_blocks(sb, NULL, &UDF_I(inode)->i_location, 0, 1);
}
@@ -55,6 +54,7 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err)
uint32_t start = UDF_I(dir)->i_location.logicalBlockNum;
struct udf_inode_info *iinfo;
struct udf_inode_info *dinfo = UDF_I(dir);
+ struct logicalVolIntegrityDescImpUse *lvidiu;
inode = new_inode(sb);
@@ -92,12 +92,10 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err)
return NULL;
}
- if (sbi->s_lvid_bh) {
- struct logicalVolIntegrityDescImpUse *lvidiu;
-
+ lvidiu = udf_sb_lvidiu(sb);
+ if (lvidiu) {
iinfo->i_unique = lvid_get_unique_id(sb);
mutex_lock(&sbi->s_alloc_mutex);
- lvidiu = udf_sb_lvidiu(sbi);
if (S_ISDIR(mode))
le32_add_cpu(&lvidiu->numDirs, 1);
else
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 062b7925bca0..986e11ad176b 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -216,19 +216,17 @@ static int udf_write_begin(struct file *file, struct address_space *mapping,
return ret;
}
-static ssize_t udf_direct_IO(int rw, struct kiocb *iocb,
- const struct iovec *iov,
- loff_t offset, unsigned long nr_segs)
+static ssize_t udf_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
+ loff_t offset)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
ssize_t ret;
- ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
- udf_get_block);
+ ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, udf_get_block);
if (unlikely(ret < 0 && (rw & WRITE)))
- udf_write_failed(mapping, offset + iov_length(iov, nr_segs));
+ udf_write_failed(mapping, offset + iov_iter_count(iter));
return ret;
}
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 839a2bad7f45..91219385691d 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -94,13 +94,25 @@ static unsigned int udf_count_free(struct super_block *);
static int udf_statfs(struct dentry *, struct kstatfs *);
static int udf_show_options(struct seq_file *, struct dentry *);
-struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi)
+struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct super_block *sb)
{
- struct logicalVolIntegrityDesc *lvid =
- (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data;
- __u32 number_of_partitions = le32_to_cpu(lvid->numOfPartitions);
- __u32 offset = number_of_partitions * 2 *
- sizeof(uint32_t)/sizeof(uint8_t);
+ struct logicalVolIntegrityDesc *lvid;
+ unsigned int partnum;
+ unsigned int offset;
+
+ if (!UDF_SB(sb)->s_lvid_bh)
+ return NULL;
+ lvid = (struct logicalVolIntegrityDesc *)UDF_SB(sb)->s_lvid_bh->b_data;
+ partnum = le32_to_cpu(lvid->numOfPartitions);
+ if ((sb->s_blocksize - sizeof(struct logicalVolIntegrityDescImpUse) -
+ offsetof(struct logicalVolIntegrityDesc, impUse)) /
+ (2 * sizeof(uint32_t)) < partnum) {
+ udf_err(sb, "Logical volume integrity descriptor corrupted "
+ "(numOfPartitions = %u)!\n", partnum);
+ return NULL;
+ }
+ /* The offset is to skip freeSpaceTable and sizeTable arrays */
+ offset = partnum * 2 * sizeof(uint32_t);
return (struct logicalVolIntegrityDescImpUse *)&(lvid->impUse[offset]);
}
@@ -629,9 +641,10 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
struct udf_options uopt;
struct udf_sb_info *sbi = UDF_SB(sb);
int error = 0;
+ struct logicalVolIntegrityDescImpUse *lvidiu = udf_sb_lvidiu(sb);
- if (sbi->s_lvid_bh) {
- int write_rev = le16_to_cpu(udf_sb_lvidiu(sbi)->minUDFWriteRev);
+ if (lvidiu) {
+ int write_rev = le16_to_cpu(lvidiu->minUDFWriteRev);
if (write_rev > UDF_MAX_WRITE_VERSION && !(*flags & MS_RDONLY))
return -EACCES;
}
@@ -1905,11 +1918,12 @@ static void udf_open_lvid(struct super_block *sb)
if (!bh)
return;
-
- mutex_lock(&sbi->s_alloc_mutex);
lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
- lvidiu = udf_sb_lvidiu(sbi);
+ lvidiu = udf_sb_lvidiu(sb);
+ if (!lvidiu)
+ return;
+ mutex_lock(&sbi->s_alloc_mutex);
lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
udf_time_to_disk_stamp(&lvid->recordingDateAndTime,
@@ -1937,10 +1951,12 @@ static void udf_close_lvid(struct super_block *sb)
if (!bh)
return;
+ lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
+ lvidiu = udf_sb_lvidiu(sb);
+ if (!lvidiu)
+ return;
mutex_lock(&sbi->s_alloc_mutex);
- lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
- lvidiu = udf_sb_lvidiu(sbi);
lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
udf_time_to_disk_stamp(&lvid->recordingDateAndTime, CURRENT_TIME);
@@ -2093,15 +2109,19 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
if (sbi->s_lvid_bh) {
struct logicalVolIntegrityDescImpUse *lvidiu =
- udf_sb_lvidiu(sbi);
- uint16_t minUDFReadRev = le16_to_cpu(lvidiu->minUDFReadRev);
- uint16_t minUDFWriteRev = le16_to_cpu(lvidiu->minUDFWriteRev);
- /* uint16_t maxUDFWriteRev =
- le16_to_cpu(lvidiu->maxUDFWriteRev); */
+ udf_sb_lvidiu(sb);
+ uint16_t minUDFReadRev;
+ uint16_t minUDFWriteRev;
+ if (!lvidiu) {
+ ret = -EINVAL;
+ goto error_out;
+ }
+ minUDFReadRev = le16_to_cpu(lvidiu->minUDFReadRev);
+ minUDFWriteRev = le16_to_cpu(lvidiu->minUDFWriteRev);
if (minUDFReadRev > UDF_MAX_READ_VERSION) {
udf_err(sb, "minUDFReadRev=%x (max is %x)\n",
- le16_to_cpu(lvidiu->minUDFReadRev),
+ minUDFReadRev,
UDF_MAX_READ_VERSION);
ret = -EINVAL;
goto error_out;
@@ -2265,11 +2285,7 @@ static int udf_statfs(struct dentry *dentry, struct kstatfs *buf)
struct logicalVolIntegrityDescImpUse *lvidiu;
u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
- if (sbi->s_lvid_bh != NULL)
- lvidiu = udf_sb_lvidiu(sbi);
- else
- lvidiu = NULL;
-
+ lvidiu = udf_sb_lvidiu(sb);
buf->f_type = UDF_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize;
buf->f_blocks = sbi->s_partmaps[sbi->s_partition].s_partition_len;
diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h
index ed401e94aa8c..1f32c7bd9f57 100644
--- a/fs/udf/udf_sb.h
+++ b/fs/udf/udf_sb.h
@@ -162,7 +162,7 @@ static inline struct udf_sb_info *UDF_SB(struct super_block *sb)
return sb->s_fs_info;
}
-struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi);
+struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct super_block *sb);
int udf_compute_nr_groups(struct super_block *sb, u32 partition);
diff --git a/fs/ufs/file.c b/fs/ufs/file.c
index 33afa20d4509..e155e4c4af87 100644
--- a/fs/ufs/file.c
+++ b/fs/ufs/file.c
@@ -36,9 +36,9 @@
const struct file_operations ufs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .aio_read = generic_file_aio_read,
+ .read_iter = generic_file_read_iter,
.write = do_sync_write,
- .aio_write = generic_file_aio_write,
+ .write_iter = generic_file_write_iter,
.mmap = generic_file_mmap,
.open = generic_file_open,
.fsync = generic_file_fsync,
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index e51e581454e9..6fad7b559538 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -1413,9 +1413,8 @@ STATIC ssize_t
xfs_vm_direct_IO(
int rw,
struct kiocb *iocb,
- const struct iovec *iov,
- loff_t offset,
- unsigned long nr_segs)
+ struct iov_iter *iter,
+ loff_t offset)
{
struct inode *inode = iocb->ki_filp->f_mapping->host;
struct block_device *bdev = xfs_find_bdev_for_inode(inode);
@@ -1423,7 +1422,7 @@ xfs_vm_direct_IO(
ssize_t ret;
if (rw & WRITE) {
- size_t size = iov_length(iov, nr_segs);
+ size_t size = iov_iter_count(iter);
/*
* We cannot preallocate a size update transaction here as we
@@ -1435,15 +1434,13 @@ xfs_vm_direct_IO(
if (offset + size > XFS_I(inode)->i_d.di_size)
ioend->io_isdirect = 1;
- ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iov,
- offset, nr_segs,
+ ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iter, offset,
xfs_get_blocks_direct,
xfs_end_io_direct_write, NULL, 0);
if (ret != -EIOCBQUEUED && iocb->private)
goto out_destroy_ioend;
} else {
- ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iov,
- offset, nr_segs,
+ ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iter, offset,
xfs_get_blocks_direct,
NULL, NULL, 0);
}
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 88c5ea75ebf6..f1d85cfc0a54 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -628,6 +628,7 @@ xfs_buf_item_unlock(
else if (aborted) {
ASSERT(XFS_FORCED_SHUTDOWN(lip->li_mountp));
if (lip->li_flags & XFS_LI_IN_AIL) {
+ spin_lock(&lip->li_ailp->xa_lock);
xfs_trans_ail_delete(lip->li_ailp, lip,
SHUTDOWN_LOG_IO_ERROR);
}
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 4c749ab543d0..818c6230bb35 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -227,10 +227,9 @@ xfs_file_fsync(
}
STATIC ssize_t
-xfs_file_aio_read(
+xfs_file_read_iter(
struct kiocb *iocb,
- const struct iovec *iovp,
- unsigned long nr_segs,
+ struct iov_iter *iter,
loff_t pos)
{
struct file *file = iocb->ki_filp;
@@ -251,9 +250,7 @@ xfs_file_aio_read(
if (file->f_mode & FMODE_NOCMTIME)
ioflags |= IO_INVIS;
- ret = generic_segment_checks(iovp, &nr_segs, &size, VERIFY_WRITE);
- if (ret < 0)
- return ret;
+ size = iov_iter_count(iter);
if (unlikely(ioflags & IO_ISDIRECT)) {
xfs_buftarg_t *target =
@@ -306,7 +303,7 @@ xfs_file_aio_read(
trace_xfs_file_read(ip, size, pos, ioflags);
- ret = generic_file_aio_read(iocb, iovp, nr_segs, pos);
+ ret = generic_file_read_iter(iocb, iter, pos);
if (ret > 0)
XFS_STATS_ADD(xs_read_bytes, ret);
@@ -622,10 +619,9 @@ restart:
STATIC ssize_t
xfs_file_dio_aio_write(
struct kiocb *iocb,
- const struct iovec *iovp,
- unsigned long nr_segs,
+ struct iov_iter *iter,
loff_t pos,
- size_t ocount)
+ size_t count)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
@@ -633,7 +629,6 @@ xfs_file_dio_aio_write(
struct xfs_inode *ip = XFS_I(inode);
struct xfs_mount *mp = ip->i_mount;
ssize_t ret = 0;
- size_t count = ocount;
int unaligned_io = 0;
int iolock;
struct xfs_buftarg *target = XFS_IS_REALTIME_INODE(ip) ?
@@ -693,8 +688,8 @@ xfs_file_dio_aio_write(
}
trace_xfs_file_direct_write(ip, count, iocb->ki_pos, 0);
- ret = generic_file_direct_write(iocb, iovp,
- &nr_segs, pos, &iocb->ki_pos, count, ocount);
+ ret = generic_file_direct_write_iter(iocb, iter,
+ pos, &iocb->ki_pos, count);
out:
xfs_rw_iunlock(ip, iolock);
@@ -707,10 +702,9 @@ out:
STATIC ssize_t
xfs_file_buffered_aio_write(
struct kiocb *iocb,
- const struct iovec *iovp,
- unsigned long nr_segs,
+ struct iov_iter *iter,
loff_t pos,
- size_t ocount)
+ size_t count)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
@@ -719,7 +713,6 @@ xfs_file_buffered_aio_write(
ssize_t ret;
int enospc = 0;
int iolock = XFS_IOLOCK_EXCL;
- size_t count = ocount;
xfs_rw_ilock(ip, iolock);
@@ -732,7 +725,7 @@ xfs_file_buffered_aio_write(
write_retry:
trace_xfs_file_buffered_write(ip, count, iocb->ki_pos, 0);
- ret = generic_file_buffered_write(iocb, iovp, nr_segs,
+ ret = generic_file_buffered_write_iter(iocb, iter,
pos, &iocb->ki_pos, count, 0);
/*
@@ -753,10 +746,9 @@ out:
}
STATIC ssize_t
-xfs_file_aio_write(
+xfs_file_write_iter(
struct kiocb *iocb,
- const struct iovec *iovp,
- unsigned long nr_segs,
+ struct iov_iter *iter,
loff_t pos)
{
struct file *file = iocb->ki_filp;
@@ -764,17 +756,15 @@ xfs_file_aio_write(
struct inode *inode = mapping->host;
struct xfs_inode *ip = XFS_I(inode);
ssize_t ret;
- size_t ocount = 0;
+ size_t count = 0;
XFS_STATS_INC(xs_write_calls);
BUG_ON(iocb->ki_pos != pos);
- ret = generic_segment_checks(iovp, &nr_segs, &ocount, VERIFY_READ);
- if (ret)
- return ret;
+ count = iov_iter_count(iter);
- if (ocount == 0)
+ if (count == 0)
return 0;
if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
@@ -783,10 +773,9 @@ xfs_file_aio_write(
}
if (unlikely(file->f_flags & O_DIRECT))
- ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos, ocount);
+ ret = xfs_file_dio_aio_write(iocb, iter, pos, count);
else
- ret = xfs_file_buffered_aio_write(iocb, iovp, nr_segs, pos,
- ocount);
+ ret = xfs_file_buffered_aio_write(iocb, iter, pos, count);
if (ret > 0) {
ssize_t err;
@@ -1411,8 +1400,8 @@ const struct file_operations xfs_file_operations = {
.llseek = xfs_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .aio_read = xfs_file_aio_read,
- .aio_write = xfs_file_aio_write,
+ .read_iter = xfs_file_read_iter,
+ .write_iter = xfs_file_write_iter,
.splice_read = xfs_file_splice_read,
.splice_write = xfs_file_splice_write,
.unlocked_ioctl = xfs_file_ioctl,
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index 1edb5cc3e5f4..18272c766a50 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -515,7 +515,7 @@ typedef struct xfs_swapext
/* XFS_IOC_GETBIOSIZE ---- deprecated 47 */
#define XFS_IOC_GETBMAPX _IOWR('X', 56, struct getbmap)
#define XFS_IOC_ZERO_RANGE _IOW ('X', 57, struct xfs_flock64)
-#define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_eofblocks)
+#define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_fs_eofblocks)
/*
* ioctl commands that replace IRIX syssgi()'s
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 193206ba4358..474807a401c8 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -119,11 +119,6 @@ xfs_inode_free(
ip->i_itemp = NULL;
}
- /* asserts to verify all state is correct here */
- ASSERT(atomic_read(&ip->i_pincount) == 0);
- ASSERT(!spin_is_locked(&ip->i_flags_lock));
- ASSERT(!xfs_isiflocked(ip));
-
/*
* Because we use RCU freeing we need to ensure the inode always
* appears to be reclaimed with an invalid inode number when in the
@@ -135,6 +130,10 @@ xfs_inode_free(
ip->i_ino = 0;
spin_unlock(&ip->i_flags_lock);
+ /* asserts to verify all state is correct here */
+ ASSERT(atomic_read(&ip->i_pincount) == 0);
+ ASSERT(!xfs_isiflocked(ip));
+
call_rcu(&VFS_I(ip)->i_rcu, xfs_inode_free_callback);
}
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index dabda9521b4b..cc179878fe41 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -1970,6 +1970,13 @@ xlog_recover_do_inode_buffer(
* magic number. If we don't recognise the magic number in the buffer, then
* return a LSN of -1 so that the caller knows it was an unrecognised block and
* so can recover the buffer.
+ *
+ * Note: we cannot rely solely on magic number matches to determine that the
+ * buffer has a valid LSN - we also need to verify that it belongs to this
+ * filesystem, so we need to extract the object's LSN and compare it to that
+ * which we read from the superblock. If the UUIDs don't match, then we've got a
+ * stale metadata block from an old filesystem instance that we need to recover
+ * over the top of.
*/
static xfs_lsn_t
xlog_recover_get_buf_lsn(
@@ -1980,6 +1987,8 @@ xlog_recover_get_buf_lsn(
__uint16_t magic16;
__uint16_t magicda;
void *blk = bp->b_addr;
+ uuid_t *uuid;
+ xfs_lsn_t lsn = -1;
/* v4 filesystems always recover immediately */
if (!xfs_sb_version_hascrc(&mp->m_sb))
@@ -1992,43 +2001,79 @@ xlog_recover_get_buf_lsn(
case XFS_ABTB_MAGIC:
case XFS_ABTC_MAGIC:
case XFS_IBT_CRC_MAGIC:
- case XFS_IBT_MAGIC:
- return be64_to_cpu(
- ((struct xfs_btree_block *)blk)->bb_u.s.bb_lsn);
+ case XFS_IBT_MAGIC: {
+ struct xfs_btree_block *btb = blk;
+
+ lsn = be64_to_cpu(btb->bb_u.s.bb_lsn);
+ uuid = &btb->bb_u.s.bb_uuid;
+ break;
+ }
case XFS_BMAP_CRC_MAGIC:
- case XFS_BMAP_MAGIC:
- return be64_to_cpu(
- ((struct xfs_btree_block *)blk)->bb_u.l.bb_lsn);
+ case XFS_BMAP_MAGIC: {
+ struct xfs_btree_block *btb = blk;
+
+ lsn = be64_to_cpu(btb->bb_u.l.bb_lsn);
+ uuid = &btb->bb_u.l.bb_uuid;
+ break;
+ }
case XFS_AGF_MAGIC:
- return be64_to_cpu(((struct xfs_agf *)blk)->agf_lsn);
+ lsn = be64_to_cpu(((struct xfs_agf *)blk)->agf_lsn);
+ uuid = &((struct xfs_agf *)blk)->agf_uuid;
+ break;
case XFS_AGFL_MAGIC:
- return be64_to_cpu(((struct xfs_agfl *)blk)->agfl_lsn);
+ lsn = be64_to_cpu(((struct xfs_agfl *)blk)->agfl_lsn);
+ uuid = &((struct xfs_agfl *)blk)->agfl_uuid;
+ break;
case XFS_AGI_MAGIC:
- return be64_to_cpu(((struct xfs_agi *)blk)->agi_lsn);
+ lsn = be64_to_cpu(((struct xfs_agi *)blk)->agi_lsn);
+ uuid = &((struct xfs_agi *)blk)->agi_uuid;
+ break;
case XFS_SYMLINK_MAGIC:
- return be64_to_cpu(((struct xfs_dsymlink_hdr *)blk)->sl_lsn);
+ lsn = be64_to_cpu(((struct xfs_dsymlink_hdr *)blk)->sl_lsn);
+ uuid = &((struct xfs_dsymlink_hdr *)blk)->sl_uuid;
+ break;
case XFS_DIR3_BLOCK_MAGIC:
case XFS_DIR3_DATA_MAGIC:
case XFS_DIR3_FREE_MAGIC:
- return be64_to_cpu(((struct xfs_dir3_blk_hdr *)blk)->lsn);
+ lsn = be64_to_cpu(((struct xfs_dir3_blk_hdr *)blk)->lsn);
+ uuid = &((struct xfs_dir3_blk_hdr *)blk)->uuid;
+ break;
case XFS_ATTR3_RMT_MAGIC:
- return be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn);
+ lsn = be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn);
+ uuid = &((struct xfs_attr3_rmt_hdr *)blk)->rm_uuid;
+ break;
case XFS_SB_MAGIC:
- return be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn);
+ lsn = be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn);
+ uuid = &((struct xfs_dsb *)blk)->sb_uuid;
+ break;
default:
break;
}
+ if (lsn != (xfs_lsn_t)-1) {
+ if (!uuid_equal(&mp->m_sb.sb_uuid, uuid))
+ goto recover_immediately;
+ return lsn;
+ }
+
magicda = be16_to_cpu(((struct xfs_da_blkinfo *)blk)->magic);
switch (magicda) {
case XFS_DIR3_LEAF1_MAGIC:
case XFS_DIR3_LEAFN_MAGIC:
case XFS_DA3_NODE_MAGIC:
- return be64_to_cpu(((struct xfs_da3_blkinfo *)blk)->lsn);
+ lsn = be64_to_cpu(((struct xfs_da3_blkinfo *)blk)->lsn);
+ uuid = &((struct xfs_da3_blkinfo *)blk)->uuid;
+ break;
default:
break;
}
+ if (lsn != (xfs_lsn_t)-1) {
+ if (!uuid_equal(&mp->m_sb.sb_uuid, uuid))
+ goto recover_immediately;
+ return lsn;
+ }
+
/*
* We do individual object checks on dquot and inode buffers as they
* have their own individual LSN records. Also, we could have a stale
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h
index cf051e05a8fe..4e280bd226dd 100644
--- a/include/acpi/acexcep.h
+++ b/include/acpi/acexcep.h
@@ -125,8 +125,9 @@ struct acpi_exception_info {
#define AE_NO_HANDLER EXCEP_ENV (0x001A)
#define AE_OWNER_ID_LIMIT EXCEP_ENV (0x001B)
#define AE_NOT_CONFIGURED EXCEP_ENV (0x001C)
+#define AE_ACCESS EXCEP_ENV (0x001D)
-#define AE_CODE_ENV_MAX 0x001C
+#define AE_CODE_ENV_MAX 0x001D
/*
* Programmer exceptions
@@ -227,7 +228,7 @@ static const struct acpi_exception_info acpi_gbl_exception_names_env[] = {
EXCEP_TXT("AE_NO_ACPI_TABLES", "ACPI tables could not be found"),
EXCEP_TXT("AE_NO_NAMESPACE", "A namespace has not been loaded"),
EXCEP_TXT("AE_NO_MEMORY", "Insufficient dynamic memory"),
- EXCEP_TXT("AE_NOT_FOUND", "The name was not found in the namespace"),
+ EXCEP_TXT("AE_NOT_FOUND", "A requested entity is not found"),
EXCEP_TXT("AE_NOT_EXIST", "A required entity does not exist"),
EXCEP_TXT("AE_ALREADY_EXISTS", "An entity already exists"),
EXCEP_TXT("AE_TYPE", "The object type is incorrect"),
@@ -259,7 +260,8 @@ static const struct acpi_exception_info acpi_gbl_exception_names_env[] = {
EXCEP_TXT("AE_OWNER_ID_LIMIT",
"There are no more Owner IDs available for ACPI tables or control methods"),
EXCEP_TXT("AE_NOT_CONFIGURED",
- "The interface is not part of the current subsystem configuration")
+ "The interface is not part of the current subsystem configuration"),
+ EXCEP_TXT("AE_ACCESS", "Permission denied for the requested operation")
};
static const struct acpi_exception_info acpi_gbl_exception_names_pgm[] = {
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 85bfdbe17805..c7b1475422b3 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -46,7 +46,7 @@
/* Current ACPICA subsystem version in YYYYMMDD format */
-#define ACPI_CA_VERSION 0x20130725
+#define ACPI_CA_VERSION 0x20130823
#include <acpi/acconfig.h>
#include <acpi/actypes.h>
@@ -280,9 +280,16 @@ acpi_status
acpi_install_initialization_handler(acpi_init_handler handler, u32 function);
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
- acpi_install_global_event_handler
- (acpi_gbl_event_handler handler, void *context))
-
+ acpi_install_sci_handler(acpi_sci_handler
+ address,
+ void *context))
+ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+ acpi_remove_sci_handler(acpi_sci_handler
+ address))
+ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+ acpi_install_global_event_handler
+ (acpi_gbl_event_handler handler,
+ void *context))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
acpi_install_fixed_event_handler(u32
acpi_event,
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index b748aefce929..f6abf23ad0a7 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -474,6 +474,11 @@ typedef u64 acpi_integer;
#define ACPI_MOVE_NAME(dest,src) (ACPI_STRNCPY (ACPI_CAST_PTR (char, (dest)), ACPI_CAST_PTR (char, (src)), ACPI_NAME_SIZE))
#endif
+/* Support for the special RSDP signature (8 characters) */
+
+#define ACPI_VALIDATE_RSDP_SIG(a) (!ACPI_STRNCMP (ACPI_CAST_PTR (char, (a)), ACPI_SIG_RSDP, 8))
+#define ACPI_MAKE_RSDP_SIG(dest) (ACPI_MEMCPY (ACPI_CAST_PTR (char, (dest)), ACPI_SIG_RSDP, 8))
+
/*******************************************************************************
*
* Miscellaneous constants
@@ -946,6 +951,9 @@ typedef void
* Various handlers and callback procedures
*/
typedef
+u32 (*acpi_sci_handler) (void *context);
+
+typedef
void (*acpi_gbl_event_handler) (u32 event_type,
acpi_handle device,
u32 event_number, void *context);
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
index 68534ef86ec8..fda0f3e35c03 100644
--- a/include/acpi/platform/aclinux.h
+++ b/include/acpi/platform/aclinux.h
@@ -87,7 +87,7 @@
#define ACPI_FLUSH_CPU_CACHE()
#define ACPI_CAST_PTHREAD_T(pthread) ((acpi_thread_id) (pthread))
-#if defined(__ia64__) || defined(__x86_64__)
+#if defined(__ia64__) || defined(__x86_64__) || defined(__aarch64__)
#define ACPI_MACHINE_WIDTH 64
#define COMPILER_DEPENDENT_INT64 long
#define COMPILER_DEPENDENT_UINT64 unsigned long
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 66096d06925e..7816e45f5d5a 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -199,6 +199,7 @@ struct acpi_processor_flags {
struct acpi_processor {
acpi_handle handle;
u32 acpi_id;
+ u32 apic_id;
u32 id;
u32 pblk;
int performance_platform_limit;
@@ -314,6 +315,8 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
/* in processor_core.c */
void acpi_processor_set_pdc(acpi_handle handle);
+int acpi_get_apicid(acpi_handle, int type, u32 acpi_id);
+int acpi_map_cpuid(int apic_id, u32 acpi_id);
int acpi_get_cpuid(acpi_handle, int type, u32 acpi_id);
/* in processor_throttling.c */
diff --git a/include/asm-generic/preempt.h b/include/asm-generic/preempt.h
new file mode 100644
index 000000000000..5dc14ed3791c
--- /dev/null
+++ b/include/asm-generic/preempt.h
@@ -0,0 +1,113 @@
+#ifndef __ASM_PREEMPT_H
+#define __ASM_PREEMPT_H
+
+#include <linux/thread_info.h>
+
+/*
+ * We mask the PREEMPT_NEED_RESCHED bit so as not to confuse all current users
+ * that think a non-zero value indicates we cannot preempt.
+ */
+static __always_inline int preempt_count(void)
+{
+ return current_thread_info()->preempt_count & ~PREEMPT_NEED_RESCHED;
+}
+
+static __always_inline int *preempt_count_ptr(void)
+{
+ return &current_thread_info()->preempt_count;
+}
+
+/*
+ * We now loose PREEMPT_NEED_RESCHED and cause an extra reschedule; however the
+ * alternative is loosing a reschedule. Better schedule too often -- also this
+ * should be a very rare operation.
+ */
+static __always_inline void preempt_count_set(int pc)
+{
+ *preempt_count_ptr() = pc;
+}
+
+/*
+ * must be macros to avoid header recursion hell
+ */
+#define task_preempt_count(p) \
+ (task_thread_info(p)->preempt_count & ~PREEMPT_NEED_RESCHED)
+
+#define init_task_preempt_count(p) do { \
+ task_thread_info(p)->preempt_count = PREEMPT_DISABLED; \
+} while (0)
+
+#define init_idle_preempt_count(p, cpu) do { \
+ task_thread_info(p)->preempt_count = PREEMPT_ENABLED; \
+} while (0)
+
+/*
+ * We fold the NEED_RESCHED bit into the preempt count such that
+ * preempt_enable() can decrement and test for needing to reschedule with a
+ * single instruction.
+ *
+ * We invert the actual bit, so that when the decrement hits 0 we know we both
+ * need to resched (the bit is cleared) and can resched (no preempt count).
+ */
+
+static __always_inline void set_preempt_need_resched(void)
+{
+ *preempt_count_ptr() &= ~PREEMPT_NEED_RESCHED;
+}
+
+static __always_inline void clear_preempt_need_resched(void)
+{
+ *preempt_count_ptr() |= PREEMPT_NEED_RESCHED;
+}
+
+static __always_inline bool test_preempt_need_resched(void)
+{
+ return !(*preempt_count_ptr() & PREEMPT_NEED_RESCHED);
+}
+
+/*
+ * The various preempt_count add/sub methods
+ */
+
+static __always_inline void __preempt_count_add(int val)
+{
+ *preempt_count_ptr() += val;
+}
+
+static __always_inline void __preempt_count_sub(int val)
+{
+ *preempt_count_ptr() -= val;
+}
+
+static __always_inline bool __preempt_count_dec_and_test(void)
+{
+ return !--*preempt_count_ptr();
+}
+
+/*
+ * Returns true when we need to resched -- even if we can not.
+ */
+static __always_inline bool need_resched(void)
+{
+ return unlikely(test_preempt_need_resched());
+}
+
+/*
+ * Returns true when we need to resched and can (barring IRQ state).
+ */
+static __always_inline bool should_resched(void)
+{
+ return unlikely(!*preempt_count_ptr());
+}
+
+#ifdef CONFIG_PREEMPT
+extern asmlinkage void preempt_schedule(void);
+#define __preempt_schedule() preempt_schedule()
+
+#ifdef CONFIG_CONTEXT_TRACKING
+extern asmlinkage void preempt_schedule_context(void);
+#define __preempt_schedule_context() preempt_schedule_context()
+#endif
+#endif /* CONFIG_PREEMPT */
+
+#endif /* __ASM_PREEMPT_H */
diff --git a/include/asm-generic/simd.h b/include/asm-generic/simd.h
new file mode 100644
index 000000000000..f57eb7b5c23b
--- /dev/null
+++ b/include/asm-generic/simd.h
@@ -0,0 +1,14 @@
+
+#include <linux/hardirq.h>
+
+/*
+ * may_use_simd - whether it is allowable at this time to issue SIMD
+ * instructions or access the SIMD register file
+ *
+ * As architectures typically don't preserve the SIMD register file when
+ * taking an interrupt, !in_interrupt() should be a reasonable default.
+ */
+static __must_check inline bool may_use_simd(void)
+{
+ return !in_interrupt();
+}
diff --git a/arch/x86/include/asm/crypto/ablk_helper.h b/include/crypto/ablk_helper.h
index 4f93df50c23e..4f93df50c23e 100644
--- a/arch/x86/include/asm/crypto/ablk_helper.h
+++ b/include/crypto/ablk_helper.h
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index b46fb45f2cca..c65f496ad6b6 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -433,6 +433,9 @@ struct drm_file {
struct drm_master *master; /* master this node is currently associated with
N.B. not always minor->master */
+ /* true when the client has asked us to expose stereo 3D mode flags */
+ bool stereo_allowed;
+
/**
* fbs - List of framebuffers associated with this file.
*
@@ -1303,6 +1306,8 @@ extern int drm_getstats(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int drm_getcap(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+extern int drm_setclientcap(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
extern int drm_setversion(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int drm_noop(struct drm_device *dev, void *data,
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 24f499569a2f..b2d08ca68ee7 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -108,6 +108,7 @@ enum drm_mode_status {
MODE_ONE_HEIGHT, /* only one height is supported */
MODE_ONE_SIZE, /* only one resolution is supported */
MODE_NO_REDUCED, /* monitor doesn't accept reduced blanking */
+ MODE_NO_STEREO, /* stereo modes not supported */
MODE_UNVERIFIED = -3, /* mode needs to reverified */
MODE_BAD = -2, /* unspecified reason */
MODE_ERROR = -1 /* error condition */
@@ -124,7 +125,8 @@ enum drm_mode_status {
.vscan = (vs), .flags = (f), \
.base.type = DRM_MODE_OBJECT_MODE
-#define CRTC_INTERLACE_HALVE_V 0x1 /* halve V values for interlacing */
+#define CRTC_INTERLACE_HALVE_V (1 << 0) /* halve V values for interlacing */
+#define CRTC_STEREO_DOUBLE (1 << 1) /* adjust timings for stereo modes */
struct drm_display_mode {
/* Header */
@@ -155,8 +157,7 @@ struct drm_display_mode {
int height_mm;
/* Actual mode we give to hw */
- int clock_index;
- int synth_clock;
+ int crtc_clock; /* in KHz */
int crtc_hdisplay;
int crtc_hblank_start;
int crtc_hblank_end;
@@ -180,6 +181,20 @@ struct drm_display_mode {
int hsync; /* in kHz */
};
+#define DRM_MODE_FLAG_3D_MASK (DRM_MODE_FLAG_3D_FRAME_PACKING | \
+ DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE | \
+ DRM_MODE_FLAG_3D_LINE_ALTERNATIVE | \
+ DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL | \
+ DRM_MODE_FLAG_3D_L_DEPTH | \
+ DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH | \
+ DRM_MODE_FLAG_3D_TOP_AND_BOTTOM | \
+ DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF)
+
+static inline bool drm_mode_is_stereo(const struct drm_display_mode *mode)
+{
+ return mode->flags & DRM_MODE_FLAG_3D_MASK;
+}
+
enum drm_connector_status {
connector_status_connected = 1,
connector_status_disconnected = 2,
@@ -597,6 +612,7 @@ struct drm_connector {
int connector_type_id;
bool interlace_allowed;
bool doublescan_allowed;
+ bool stereo_allowed;
struct list_head modes; /* list of modes on this connector */
enum drm_connector_status status;
@@ -975,7 +991,7 @@ extern void drm_mode_config_reset(struct drm_device *dev);
extern void drm_mode_config_cleanup(struct drm_device *dev);
extern void drm_mode_set_name(struct drm_display_mode *mode);
extern bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2);
-extern bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2);
+extern bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2);
extern int drm_mode_width(const struct drm_display_mode *mode);
extern int drm_mode_height(const struct drm_display_mode *mode);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index a5db4aeefa36..35e68358ad06 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -116,7 +116,7 @@ void acpi_numa_arch_fixup(void);
#ifdef CONFIG_ACPI_HOTPLUG_CPU
/* Arch dependent functions for cpu hotplug support */
-int acpi_map_lsapic(acpi_handle handle, int *pcpu);
+int acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu);
int acpi_unmap_lsapic(int cpu);
#endif /* CONFIG_ACPI_HOTPLUG_CPU */
@@ -294,58 +294,51 @@ void __init acpi_nvs_nosave_s3(void);
#endif /* CONFIG_PM_SLEEP */
struct acpi_osc_context {
- char *uuid_str; /* uuid string */
+ char *uuid_str; /* UUID string */
int rev;
- struct acpi_buffer cap; /* arg2/arg3 */
- struct acpi_buffer ret; /* free by caller if success */
+ struct acpi_buffer cap; /* list of DWORD capabilities */
+ struct acpi_buffer ret; /* free by caller if success */
};
-#define OSC_QUERY_TYPE 0
-#define OSC_SUPPORT_TYPE 1
-#define OSC_CONTROL_TYPE 2
-
-/* _OSC DW0 Definition */
-#define OSC_QUERY_ENABLE 1
-#define OSC_REQUEST_ERROR 2
-#define OSC_INVALID_UUID_ERROR 4
-#define OSC_INVALID_REVISION_ERROR 8
-#define OSC_CAPABILITIES_MASK_ERROR 16
-
acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context);
-/* platform-wide _OSC bits */
-#define OSC_SB_PAD_SUPPORT 1
-#define OSC_SB_PPC_OST_SUPPORT 2
-#define OSC_SB_PR3_SUPPORT 4
-#define OSC_SB_HOTPLUG_OST_SUPPORT 8
-#define OSC_SB_APEI_SUPPORT 16
+/* Indexes into _OSC Capabilities Buffer (DWORDs 2 & 3 are device-specific) */
+#define OSC_QUERY_DWORD 0 /* DWORD 1 */
+#define OSC_SUPPORT_DWORD 1 /* DWORD 2 */
+#define OSC_CONTROL_DWORD 2 /* DWORD 3 */
+
+/* _OSC Capabilities DWORD 1: Query/Control and Error Returns (generic) */
+#define OSC_QUERY_ENABLE 0x00000001 /* input */
+#define OSC_REQUEST_ERROR 0x00000002 /* return */
+#define OSC_INVALID_UUID_ERROR 0x00000004 /* return */
+#define OSC_INVALID_REVISION_ERROR 0x00000008 /* return */
+#define OSC_CAPABILITIES_MASK_ERROR 0x00000010 /* return */
+
+/* Platform-Wide Capabilities _OSC: Capabilities DWORD 2: Support Field */
+#define OSC_SB_PAD_SUPPORT 0x00000001
+#define OSC_SB_PPC_OST_SUPPORT 0x00000002
+#define OSC_SB_PR3_SUPPORT 0x00000004
+#define OSC_SB_HOTPLUG_OST_SUPPORT 0x00000008
+#define OSC_SB_APEI_SUPPORT 0x00000010
+#define OSC_SB_CPC_SUPPORT 0x00000020
extern bool osc_sb_apei_support_acked;
-/* PCI defined _OSC bits */
-/* _OSC DW1 Definition (OS Support Fields) */
-#define OSC_EXT_PCI_CONFIG_SUPPORT 1
-#define OSC_ACTIVE_STATE_PWR_SUPPORT 2
-#define OSC_CLOCK_PWR_CAPABILITY_SUPPORT 4
-#define OSC_PCI_SEGMENT_GROUPS_SUPPORT 8
-#define OSC_MSI_SUPPORT 16
-#define OSC_PCI_SUPPORT_MASKS 0x1f
-
-/* _OSC DW1 Definition (OS Control Fields) */
-#define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL 1
-#define OSC_SHPC_NATIVE_HP_CONTROL 2
-#define OSC_PCI_EXPRESS_PME_CONTROL 4
-#define OSC_PCI_EXPRESS_AER_CONTROL 8
-#define OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL 16
-
-#define OSC_PCI_CONTROL_MASKS (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | \
- OSC_SHPC_NATIVE_HP_CONTROL | \
- OSC_PCI_EXPRESS_PME_CONTROL | \
- OSC_PCI_EXPRESS_AER_CONTROL | \
- OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL)
-
-#define OSC_PCI_NATIVE_HOTPLUG (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | \
- OSC_SHPC_NATIVE_HP_CONTROL)
+/* PCI Host Bridge _OSC: Capabilities DWORD 2: Support Field */
+#define OSC_PCI_EXT_CONFIG_SUPPORT 0x00000001
+#define OSC_PCI_ASPM_SUPPORT 0x00000002
+#define OSC_PCI_CLOCK_PM_SUPPORT 0x00000004
+#define OSC_PCI_SEGMENT_GROUPS_SUPPORT 0x00000008
+#define OSC_PCI_MSI_SUPPORT 0x00000010
+#define OSC_PCI_SUPPORT_MASKS 0x0000001f
+
+/* PCI Host Bridge _OSC: Capabilities DWORD 3: Control Field */
+#define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL 0x00000001
+#define OSC_PCI_SHPC_NATIVE_HP_CONTROL 0x00000002
+#define OSC_PCI_EXPRESS_PME_CONTROL 0x00000004
+#define OSC_PCI_EXPRESS_AER_CONTROL 0x00000008
+#define OSC_PCI_EXPRESS_CAPABILITY_CONTROL 0x00000010
+#define OSC_PCI_CONTROL_MASKS 0x0000001f
extern acpi_status acpi_pci_osc_control_set(acpi_handle handle,
u32 *mask, u32 req);
diff --git a/include/linux/aio.h b/include/linux/aio.h
index d9c92daa3944..9f4b10a81f8a 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -31,13 +31,15 @@ typedef int (kiocb_cancel_fn)(struct kiocb *);
struct kiocb {
struct file *ki_filp;
- struct kioctx *ki_ctx; /* NULL for sync ops */
+ struct kioctx *ki_ctx; /* NULL for sync ops,
+ * -1 for kernel caller */
kiocb_cancel_fn *ki_cancel;
void *private;
union {
void __user *user;
struct task_struct *tsk;
+ void (*complete)(u64 user_data, long res);
} ki_obj;
__u64 ki_user_data; /* user's data for completion */
@@ -59,6 +61,11 @@ static inline bool is_sync_kiocb(struct kiocb *kiocb)
return kiocb->ki_ctx == NULL;
}
+static inline bool is_kernel_kiocb(struct kiocb *kiocb)
+{
+ return kiocb->ki_ctx == (void *)-1;
+}
+
static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
{
*kiocb = (struct kiocb) {
@@ -77,6 +84,14 @@ extern void exit_aio(struct mm_struct *mm);
extern long do_io_submit(aio_context_t ctx_id, long nr,
struct iocb __user *__user *iocbpp, bool compat);
void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel);
+struct kiocb *aio_kernel_alloc(gfp_t gfp);
+void aio_kernel_free(struct kiocb *iocb);
+void aio_kernel_init_rw(struct kiocb *iocb, struct file *filp, size_t nr,
+ loff_t off);
+void aio_kernel_init_callback(struct kiocb *iocb,
+ void (*complete)(u64 user_data, long res),
+ u64 user_data);
+int aio_kernel_submit(struct kiocb *iocb, unsigned short op, void *ptr);
#else
static inline ssize_t wait_on_sync_kiocb(struct kiocb *iocb) { return 0; }
static inline void aio_complete(struct kiocb *iocb, long res, long res2) { }
diff --git a/include/linux/bcma/bcma_driver_pci.h b/include/linux/bcma/bcma_driver_pci.h
index d66033f418c9..0333e605ea0d 100644
--- a/include/linux/bcma/bcma_driver_pci.h
+++ b/include/linux/bcma/bcma_driver_pci.h
@@ -242,6 +242,7 @@ extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
struct bcma_device *core, bool enable);
extern void bcma_core_pci_up(struct bcma_bus *bus);
extern void bcma_core_pci_down(struct bcma_bus *bus);
+extern void bcma_core_pci_power_save(struct bcma_bus *bus, bool up);
extern int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev);
extern int bcma_core_pci_plat_dev_init(struct pci_dev *dev);
diff --git a/include/linux/bio.h b/include/linux/bio.h
index ec48bac5b039..4fd525342596 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -307,6 +307,14 @@ extern struct bio_vec *bvec_alloc(gfp_t, int, unsigned long *, mempool_t *);
extern void bvec_free(mempool_t *, struct bio_vec *, unsigned int);
extern unsigned int bvec_nr_vecs(unsigned short idx);
+static inline ssize_t bvec_length(const struct bio_vec *bvec, unsigned long nr)
+{
+ ssize_t bytes = 0;
+ while (nr--)
+ bytes += (bvec++)->bv_len;
+ return bytes;
+}
+
#ifdef CONFIG_BLK_CGROUP
int bio_associate_current(struct bio *bio);
void bio_disassociate_task(struct bio *bio);
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index fa1abeb45b76..1bea25f14796 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -176,7 +176,6 @@ enum rq_flag_bits {
__REQ_FLUSH_SEQ, /* request for flush sequence */
__REQ_IO_STAT, /* account I/O stat */
__REQ_MIXED_MERGE, /* merge of different types, fail separately */
- __REQ_KERNEL, /* direct IO to kernel pages */
__REQ_PM, /* runtime pm request */
__REQ_NR_BITS, /* stops here */
};
@@ -227,7 +226,6 @@ enum rq_flag_bits {
#define REQ_IO_STAT (1 << __REQ_IO_STAT)
#define REQ_MIXED_MERGE (1 << __REQ_MIXED_MERGE)
#define REQ_SECURE (1 << __REQ_SECURE)
-#define REQ_KERNEL (1 << __REQ_KERNEL)
#define REQ_PM (1 << __REQ_PM)
#endif /* __LINUX_BLK_TYPES_H */
diff --git a/include/linux/blockconsole.h b/include/linux/blockconsole.h
new file mode 100644
index 000000000000..114f7c50d333
--- /dev/null
+++ b/include/linux/blockconsole.h
@@ -0,0 +1,7 @@
+#ifndef LINUX_BLOCKCONSOLE_H
+#define LINUX_BLOCKCONSOLE_H
+
+int bcon_magic_present(const void *data);
+void bcon_add(const char *name);
+
+#endif
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 3561d305b1e0..39c1d9469677 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -612,11 +612,6 @@ struct cgroup_subsys {
int subsys_id;
int disabled;
int early_init;
- /*
- * True if this subsys uses ID. ID is not available before cgroup_init()
- * (not available in early_init time.)
- */
- bool use_id;
/*
* If %false, this subsystem is properly hierarchical -
@@ -642,9 +637,6 @@ struct cgroup_subsys {
*/
struct cgroupfs_root *root;
struct list_head sibling;
- /* used when use_id == true */
- struct idr idr;
- spinlock_t id_lock;
/* list of cftype_sets */
struct list_head cftsets;
@@ -875,35 +867,6 @@ int css_scan_tasks(struct cgroup_subsys_state *css,
int cgroup_attach_task_all(struct task_struct *from, struct task_struct *);
int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from);
-/*
- * CSS ID is ID for cgroup_subsys_state structs under subsys. This only works
- * if cgroup_subsys.use_id == true. It can be used for looking up and scanning.
- * CSS ID is assigned at cgroup allocation (create) automatically
- * and removed when subsys calls free_css_id() function. This is because
- * the lifetime of cgroup_subsys_state is subsys's matter.
- *
- * Looking up and scanning function should be called under rcu_read_lock().
- * Taking cgroup_mutex is not necessary for following calls.
- * But the css returned by this routine can be "not populated yet" or "being
- * destroyed". The caller should check css and cgroup's status.
- */
-
-/*
- * Typically Called at ->destroy(), or somewhere the subsys frees
- * cgroup_subsys_state.
- */
-void free_css_id(struct cgroup_subsys *ss, struct cgroup_subsys_state *css);
-
-/* Find a cgroup_subsys_state which has given ID */
-
-struct cgroup_subsys_state *css_lookup(struct cgroup_subsys *ss, int id);
-
-/* Returns true if root is ancestor of cg */
-bool css_is_ancestor(struct cgroup_subsys_state *cg,
- const struct cgroup_subsys_state *root);
-
-/* Get id and depth of css */
-unsigned short css_id(struct cgroup_subsys_state *css);
struct cgroup_subsys_state *css_from_dir(struct dentry *dentry,
struct cgroup_subsys *ss);
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index dbbf8aa7731b..67301a405712 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -292,6 +292,8 @@ extern void clocksource_resume(void);
extern struct clocksource * __init __weak clocksource_default_clock(void);
extern void clocksource_mark_unstable(struct clocksource *cs);
+extern u64
+clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask);
extern void
clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 minsec);
diff --git a/include/linux/console.h b/include/linux/console.h
index 7571a16bd653..fdfcb703d7f5 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -115,6 +115,7 @@ static inline int con_debug_leave(void)
#define CON_BOOT (8)
#define CON_ANYTIME (16) /* Safe to call when cpu is offline */
#define CON_BRL (32) /* Used for a braille device */
+#define CON_ALLDATA (64) /* per-console ignore_loglevel */
struct console {
char name[16];
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 59066e0b4ff1..716c3760ee39 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -224,6 +224,7 @@ static inline int dname_external(const struct dentry *dentry)
extern void d_instantiate(struct dentry *, struct inode *);
extern struct dentry * d_instantiate_unique(struct dentry *, struct inode *);
extern struct dentry * d_materialise_unique(struct dentry *, struct inode *);
+extern int d_instantiate_no_diralias(struct dentry *, struct inode *);
extern void __d_drop(struct dentry *dentry);
extern void d_drop(struct dentry *dentry);
extern void d_delete(struct dentry *);
diff --git a/include/linux/device.h b/include/linux/device.h
index 2a9d6ed59579..ce690ea34547 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -427,8 +427,6 @@ struct class_attribute {
char *buf);
ssize_t (*store)(struct class *class, struct class_attribute *attr,
const char *buf, size_t count);
- const void *(*namespace)(struct class *class,
- const struct class_attribute *attr);
};
#define CLASS_ATTR(_name, _mode, _show, _store) \
@@ -438,10 +436,24 @@ struct class_attribute {
#define CLASS_ATTR_RO(_name) \
struct class_attribute class_attr_##_name = __ATTR_RO(_name)
-extern int __must_check class_create_file(struct class *class,
- const struct class_attribute *attr);
-extern void class_remove_file(struct class *class,
- const struct class_attribute *attr);
+extern int __must_check class_create_file_ns(struct class *class,
+ const struct class_attribute *attr,
+ const void *ns);
+extern void class_remove_file_ns(struct class *class,
+ const struct class_attribute *attr,
+ const void *ns);
+
+static inline int __must_check class_create_file(struct class *class,
+ const struct class_attribute *attr)
+{
+ return class_create_file_ns(class, attr, NULL);
+}
+
+static inline void class_remove_file(struct class *class,
+ const struct class_attribute *attr)
+{
+ return class_remove_file_ns(class, attr, NULL);
+}
/* Simple class attribute that is just a static string */
struct class_attribute_string {
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 3f40547ba191..4c743ed2e46e 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -182,8 +182,6 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
#define READ 0
#define WRITE RW_MASK
#define READA RWA_MASK
-#define KERNEL_READ (READ|REQ_KERNEL)
-#define KERNEL_WRITE (WRITE|REQ_KERNEL)
#define READ_SYNC (READ | REQ_SYNC)
#define WRITE_SYNC (WRITE | REQ_SYNC | REQ_NOIDLE)
@@ -291,25 +289,108 @@ struct address_space;
struct writeback_control;
struct iov_iter {
- const struct iovec *iov;
+ struct iov_iter_ops *ops;
+ unsigned long data;
unsigned long nr_segs;
size_t iov_offset;
size_t count;
};
-size_t iov_iter_copy_from_user_atomic(struct page *page,
- struct iov_iter *i, unsigned long offset, size_t bytes);
-size_t iov_iter_copy_from_user(struct page *page,
- struct iov_iter *i, unsigned long offset, size_t bytes);
-void iov_iter_advance(struct iov_iter *i, size_t bytes);
-int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes);
-size_t iov_iter_single_seg_count(const struct iov_iter *i);
+struct iov_iter_ops {
+ size_t (*ii_copy_to_user_atomic)(struct page *, struct iov_iter *,
+ unsigned long, size_t);
+ size_t (*ii_copy_to_user)(struct page *, struct iov_iter *,
+ unsigned long, size_t, int);
+ size_t (*ii_copy_from_user_atomic)(struct page *, struct iov_iter *,
+ unsigned long, size_t);
+ size_t (*ii_copy_from_user)(struct page *, struct iov_iter *,
+ unsigned long, size_t);
+ void (*ii_advance)(struct iov_iter *, size_t);
+ int (*ii_fault_in_readable)(struct iov_iter *, size_t);
+ size_t (*ii_single_seg_count)(const struct iov_iter *);
+ int (*ii_shorten)(struct iov_iter *, size_t);
+};
+
+static inline size_t iov_iter_copy_to_user_atomic(struct page *page,
+ struct iov_iter *i, unsigned long offset, size_t bytes)
+{
+ return i->ops->ii_copy_to_user_atomic(page, i, offset, bytes);
+}
+static inline size_t __iov_iter_copy_to_user(struct page *page,
+ struct iov_iter *i, unsigned long offset, size_t bytes)
+{
+ return i->ops->ii_copy_to_user(page, i, offset, bytes, 0);
+}
+static inline size_t iov_iter_copy_to_user(struct page *page,
+ struct iov_iter *i, unsigned long offset, size_t bytes)
+{
+ return i->ops->ii_copy_to_user(page, i, offset, bytes, 1);
+}
+static inline size_t iov_iter_copy_from_user_atomic(struct page *page,
+ struct iov_iter *i, unsigned long offset, size_t bytes)
+{
+ return i->ops->ii_copy_from_user_atomic(page, i, offset, bytes);
+}
+static inline size_t iov_iter_copy_from_user(struct page *page,
+ struct iov_iter *i, unsigned long offset, size_t bytes)
+{
+ return i->ops->ii_copy_from_user(page, i, offset, bytes);
+}
+static inline void iov_iter_advance(struct iov_iter *i, size_t bytes)
+{
+ return i->ops->ii_advance(i, bytes);
+}
+static inline int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes)
+{
+ return i->ops->ii_fault_in_readable(i, bytes);
+}
+static inline size_t iov_iter_single_seg_count(const struct iov_iter *i)
+{
+ return i->ops->ii_single_seg_count(i);
+}
+static inline int iov_iter_shorten(struct iov_iter *i, size_t count)
+{
+ return i->ops->ii_shorten(i, count);
+}
+
+#ifdef CONFIG_BLOCK
+extern struct iov_iter_ops ii_bvec_ops;
+
+struct bio_vec;
+static inline void iov_iter_init_bvec(struct iov_iter *i,
+ struct bio_vec *bvec,
+ unsigned long nr_segs,
+ size_t count, size_t written)
+{
+ i->ops = &ii_bvec_ops;
+ i->data = (unsigned long)bvec;
+ i->nr_segs = nr_segs;
+ i->iov_offset = 0;
+ i->count = count + written;
+
+ iov_iter_advance(i, written);
+}
+
+static inline int iov_iter_has_bvec(struct iov_iter *i)
+{
+ return i->ops == &ii_bvec_ops;
+}
+
+static inline struct bio_vec *iov_iter_bvec(struct iov_iter *i)
+{
+ BUG_ON(!iov_iter_has_bvec(i));
+ return (struct bio_vec *)i->data;
+}
+#endif
+
+extern struct iov_iter_ops ii_iovec_ops;
static inline void iov_iter_init(struct iov_iter *i,
const struct iovec *iov, unsigned long nr_segs,
size_t count, size_t written)
{
- i->iov = iov;
+ i->ops = &ii_iovec_ops;
+ i->data = (unsigned long)iov;
i->nr_segs = nr_segs;
i->iov_offset = 0;
i->count = count + written;
@@ -317,6 +398,17 @@ static inline void iov_iter_init(struct iov_iter *i,
iov_iter_advance(i, written);
}
+static inline int iov_iter_has_iovec(struct iov_iter *i)
+{
+ return i->ops == &ii_iovec_ops;
+}
+
+static inline struct iovec *iov_iter_iovec(struct iov_iter *i)
+{
+ BUG_ON(!iov_iter_has_iovec(i));
+ return (struct iovec *)i->data;
+}
+
static inline size_t iov_iter_count(struct iov_iter *i)
{
return i->count;
@@ -369,8 +461,8 @@ struct address_space_operations {
void (*invalidatepage) (struct page *, unsigned int, unsigned int);
int (*releasepage) (struct page *, gfp_t);
void (*freepage)(struct page *);
- ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
- loff_t offset, unsigned long nr_segs);
+ ssize_t (*direct_IO)(int, struct kiocb *, struct iov_iter *iter,
+ loff_t offset);
int (*get_xip_mem)(struct address_space *, pgoff_t, int,
void **, unsigned long *);
/*
@@ -1529,7 +1621,9 @@ struct file_operations {
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ ssize_t (*read_iter) (struct kiocb *, struct iov_iter *, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
+ ssize_t (*write_iter) (struct kiocb *, struct iov_iter *, loff_t);
int (*iterate) (struct file *, struct dir_context *);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
@@ -1554,6 +1648,18 @@ struct file_operations {
int (*show_fdinfo)(struct seq_file *m, struct file *f);
};
+static inline int file_readable(struct file *filp)
+{
+ return filp && (filp->f_op->read || filp->f_op->aio_read ||
+ filp->f_op->read_iter);
+}
+
+static inline int file_writable(struct file *filp)
+{
+ return filp && (filp->f_op->write || filp->f_op->aio_write ||
+ filp->f_op->write_iter);
+}
+
struct inode_operations {
struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
void * (*follow_link) (struct dentry *, struct nameidata *);
@@ -2292,6 +2398,11 @@ static inline void allow_write_access(struct file *file)
if (file)
atomic_inc(&file_inode(file)->i_writecount);
}
+static inline bool inode_is_open_for_write(const struct inode *inode)
+{
+ return atomic_read(&inode->i_writecount) > 0;
+}
+
#ifdef CONFIG_IMA
static inline void i_readcount_dec(struct inode *inode)
{
@@ -2398,25 +2509,36 @@ extern int sb_min_blocksize(struct super_block *, int);
extern int generic_file_mmap(struct file *, struct vm_area_struct *);
extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *);
extern int generic_file_remap_pages(struct vm_area_struct *, unsigned long addr,
- unsigned long size, pgoff_t pgoff);
-extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
+ unsigned long size, pgoff_t pgoff);
+extern int file_read_iter_actor(read_descriptor_t *desc, struct page *page,
+ unsigned long offset, unsigned long size);
int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk);
extern ssize_t generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t);
+extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *,
+ loff_t);
extern ssize_t __generic_file_aio_write(struct kiocb *, const struct iovec *, unsigned long,
loff_t *);
+extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *,
+ loff_t *);
extern ssize_t generic_file_aio_write(struct kiocb *, const struct iovec *, unsigned long, loff_t);
+extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *,
+ loff_t);
extern ssize_t generic_file_direct_write(struct kiocb *, const struct iovec *,
unsigned long *, loff_t, loff_t *, size_t, size_t);
+extern ssize_t generic_file_direct_write_iter(struct kiocb *, struct iov_iter *,
+ loff_t, loff_t *, size_t);
extern ssize_t generic_file_buffered_write(struct kiocb *, const struct iovec *,
unsigned long, loff_t, loff_t *, size_t, ssize_t);
+extern ssize_t generic_file_buffered_write_iter(struct kiocb *,
+ struct iov_iter *, loff_t, loff_t *, size_t, ssize_t);
extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos);
extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos);
extern int generic_segment_checks(const struct iovec *iov,
unsigned long *nr_segs, size_t *count, int access_flags);
/* fs/block_dev.c */
-extern ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos);
+extern ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos);
extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end,
int datasync);
extern void block_sync_page(struct page *page);
@@ -2473,16 +2595,16 @@ enum {
void dio_end_io(struct bio *bio, int error);
ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
- struct block_device *bdev, const struct iovec *iov, loff_t offset,
- unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,
- dio_submit_t submit_io, int flags);
+ struct block_device *bdev, struct iov_iter *iter, loff_t offset,
+ get_block_t get_block, dio_iodone_t end_io, dio_submit_t submit_io,
+ int flags);
static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb,
- struct inode *inode, const struct iovec *iov, loff_t offset,
- unsigned long nr_segs, get_block_t get_block)
+ struct inode *inode, struct iov_iter *iter, loff_t offset,
+ get_block_t get_block)
{
- return __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
- offset, nr_segs, get_block, NULL, NULL,
+ return __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iter,
+ offset, get_block, NULL, NULL,
DIO_LOCKING | DIO_SKIP_HOLES);
}
#endif
@@ -2502,6 +2624,7 @@ extern int __page_symlink(struct inode *inode, const char *symname, int len,
int nofs);
extern int page_symlink(struct inode *inode, const char *symname, int len);
extern const struct inode_operations page_symlink_inode_operations;
+extern void kfree_put_link(struct dentry *, struct nameidata *, void *);
extern int generic_readlink(struct dentry *, char __user *, int);
extern void generic_fillattr(struct inode *, struct kstat *);
extern int vfs_getattr(struct path *, struct kstat *);
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index 7823e9ef995e..771484993ca7 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -308,36 +308,6 @@ struct fscache_cache_ops {
void (*dissociate_pages)(struct fscache_cache *cache);
};
-/*
- * data file or index object cookie
- * - a file will only appear in one cache
- * - a request to cache a file may or may not be honoured, subject to
- * constraints such as disk space
- * - indices are created on disk just-in-time
- */
-struct fscache_cookie {
- atomic_t usage; /* number of users of this cookie */
- atomic_t n_children; /* number of children of this cookie */
- atomic_t n_active; /* number of active users of netfs ptrs */
- spinlock_t lock;
- spinlock_t stores_lock; /* lock on page store tree */
- struct hlist_head backing_objects; /* object(s) backing this file/index */
- const struct fscache_cookie_def *def; /* definition */
- struct fscache_cookie *parent; /* parent of this entry */
- void *netfs_data; /* back pointer to netfs */
- struct radix_tree_root stores; /* pages to be stored on this cookie */
-#define FSCACHE_COOKIE_PENDING_TAG 0 /* pages tag: pending write to cache */
-#define FSCACHE_COOKIE_STORING_TAG 1 /* pages tag: writing to cache */
-
- unsigned long flags;
-#define FSCACHE_COOKIE_LOOKING_UP 0 /* T if non-index cookie being looked up still */
-#define FSCACHE_COOKIE_NO_DATA_YET 1 /* T if new object with no cached data yet */
-#define FSCACHE_COOKIE_UNAVAILABLE 2 /* T if cookie is unavailable (error, etc) */
-#define FSCACHE_COOKIE_INVALIDATING 3 /* T if cookie is being invalidated */
-#define FSCACHE_COOKIE_RELINQUISHED 4 /* T if cookie has been relinquished */
-#define FSCACHE_COOKIE_RETIRED 5 /* T if cookie was retired */
-};
-
extern struct fscache_cookie fscache_fsdef_index;
/*
@@ -400,6 +370,7 @@ struct fscache_object {
#define FSCACHE_OBJECT_IS_LIVE 3 /* T if object is not withdrawn or relinquished */
#define FSCACHE_OBJECT_IS_LOOKED_UP 4 /* T if object has been looked up */
#define FSCACHE_OBJECT_IS_AVAILABLE 5 /* T if object has become active */
+#define FSCACHE_OBJECT_RETIRED 6 /* T if object was retired on relinquishment */
struct list_head cache_link; /* link in cache->object_list */
struct hlist_node cookie_link; /* link in cookie->backing_objects */
@@ -511,6 +482,11 @@ static inline void fscache_end_io(struct fscache_retrieval *op,
op->end_io_func(page, op->context, error);
}
+static inline void __fscache_use_cookie(struct fscache_cookie *cookie)
+{
+ atomic_inc(&cookie->n_active);
+}
+
/**
* fscache_use_cookie - Request usage of cookie attached to an object
* @object: Object description
@@ -524,6 +500,16 @@ static inline bool fscache_use_cookie(struct fscache_object *object)
return atomic_inc_not_zero(&cookie->n_active) != 0;
}
+static inline bool __fscache_unuse_cookie(struct fscache_cookie *cookie)
+{
+ return atomic_dec_and_test(&cookie->n_active);
+}
+
+static inline void __fscache_wake_unused_cookie(struct fscache_cookie *cookie)
+{
+ wake_up_atomic_t(&cookie->n_active);
+}
+
/**
* fscache_unuse_cookie - Cease usage of cookie attached to an object
* @object: Object description
@@ -534,8 +520,8 @@ static inline bool fscache_use_cookie(struct fscache_object *object)
static inline void fscache_unuse_cookie(struct fscache_object *object)
{
struct fscache_cookie *cookie = object->cookie;
- if (atomic_dec_and_test(&cookie->n_active))
- wake_up_atomic_t(&cookie->n_active);
+ if (__fscache_unuse_cookie(cookie))
+ __fscache_wake_unused_cookie(cookie);
}
/*
diff --git a/include/linux/fscache.h b/include/linux/fscache.h
index 19b46458e4e8..115bb81912cc 100644
--- a/include/linux/fscache.h
+++ b/include/linux/fscache.h
@@ -167,6 +167,42 @@ struct fscache_netfs {
};
/*
+ * data file or index object cookie
+ * - a file will only appear in one cache
+ * - a request to cache a file may or may not be honoured, subject to
+ * constraints such as disk space
+ * - indices are created on disk just-in-time
+ */
+struct fscache_cookie {
+ atomic_t usage; /* number of users of this cookie */
+ atomic_t n_children; /* number of children of this cookie */
+ atomic_t n_active; /* number of active users of netfs ptrs */
+ spinlock_t lock;
+ spinlock_t stores_lock; /* lock on page store tree */
+ struct hlist_head backing_objects; /* object(s) backing this file/index */
+ const struct fscache_cookie_def *def; /* definition */
+ struct fscache_cookie *parent; /* parent of this entry */
+ void *netfs_data; /* back pointer to netfs */
+ struct radix_tree_root stores; /* pages to be stored on this cookie */
+#define FSCACHE_COOKIE_PENDING_TAG 0 /* pages tag: pending write to cache */
+#define FSCACHE_COOKIE_STORING_TAG 1 /* pages tag: writing to cache */
+
+ unsigned long flags;
+#define FSCACHE_COOKIE_LOOKING_UP 0 /* T if non-index cookie being looked up still */
+#define FSCACHE_COOKIE_NO_DATA_YET 1 /* T if new object with no cached data yet */
+#define FSCACHE_COOKIE_UNAVAILABLE 2 /* T if cookie is unavailable (error, etc) */
+#define FSCACHE_COOKIE_INVALIDATING 3 /* T if cookie is being invalidated */
+#define FSCACHE_COOKIE_RELINQUISHED 4 /* T if cookie has been relinquished */
+#define FSCACHE_COOKIE_ENABLED 5 /* T if cookie is enabled */
+#define FSCACHE_COOKIE_ENABLEMENT_LOCK 6 /* T if cookie is being en/disabled */
+};
+
+static inline bool fscache_cookie_enabled(struct fscache_cookie *cookie)
+{
+ return test_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
+}
+
+/*
* slow-path functions for when there is actually caching available, and the
* netfs does actually have a valid token
* - these are not to be called directly
@@ -181,8 +217,8 @@ extern void __fscache_release_cache_tag(struct fscache_cache_tag *);
extern struct fscache_cookie *__fscache_acquire_cookie(
struct fscache_cookie *,
const struct fscache_cookie_def *,
- void *);
-extern void __fscache_relinquish_cookie(struct fscache_cookie *, int);
+ void *, bool);
+extern void __fscache_relinquish_cookie(struct fscache_cookie *, bool);
extern int __fscache_check_consistency(struct fscache_cookie *);
extern void __fscache_update_cookie(struct fscache_cookie *);
extern int __fscache_attr_changed(struct fscache_cookie *);
@@ -211,6 +247,9 @@ extern void __fscache_uncache_all_inode_pages(struct fscache_cookie *,
struct inode *);
extern void __fscache_readpages_cancel(struct fscache_cookie *cookie,
struct list_head *pages);
+extern void __fscache_disable_cookie(struct fscache_cookie *, bool);
+extern void __fscache_enable_cookie(struct fscache_cookie *,
+ bool (*)(void *), void *);
/**
* fscache_register_netfs - Register a filesystem as desiring caching services
@@ -289,6 +328,7 @@ void fscache_release_cache_tag(struct fscache_cache_tag *tag)
* @def: A description of the cache object, including callback operations
* @netfs_data: An arbitrary piece of data to be kept in the cookie to
* represent the cache object to the netfs
+ * @enable: Whether or not to enable a data cookie immediately
*
* This function is used to inform FS-Cache about part of an index hierarchy
* that can be used to locate files. This is done by requesting a cookie for
@@ -301,10 +341,12 @@ static inline
struct fscache_cookie *fscache_acquire_cookie(
struct fscache_cookie *parent,
const struct fscache_cookie_def *def,
- void *netfs_data)
+ void *netfs_data,
+ bool enable)
{
- if (fscache_cookie_valid(parent))
- return __fscache_acquire_cookie(parent, def, netfs_data);
+ if (fscache_cookie_valid(parent) && fscache_cookie_enabled(parent))
+ return __fscache_acquire_cookie(parent, def, netfs_data,
+ enable);
else
return NULL;
}
@@ -322,7 +364,7 @@ struct fscache_cookie *fscache_acquire_cookie(
* description.
*/
static inline
-void fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
+void fscache_relinquish_cookie(struct fscache_cookie *cookie, bool retire)
{
if (fscache_cookie_valid(cookie))
__fscache_relinquish_cookie(cookie, retire);
@@ -341,7 +383,7 @@ void fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
static inline
int fscache_check_consistency(struct fscache_cookie *cookie)
{
- if (fscache_cookie_valid(cookie))
+ if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
return __fscache_check_consistency(cookie);
else
return 0;
@@ -360,7 +402,7 @@ int fscache_check_consistency(struct fscache_cookie *cookie)
static inline
void fscache_update_cookie(struct fscache_cookie *cookie)
{
- if (fscache_cookie_valid(cookie))
+ if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
__fscache_update_cookie(cookie);
}
@@ -407,7 +449,7 @@ void fscache_unpin_cookie(struct fscache_cookie *cookie)
static inline
int fscache_attr_changed(struct fscache_cookie *cookie)
{
- if (fscache_cookie_valid(cookie))
+ if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
return __fscache_attr_changed(cookie);
else
return -ENOBUFS;
@@ -429,7 +471,7 @@ int fscache_attr_changed(struct fscache_cookie *cookie)
static inline
void fscache_invalidate(struct fscache_cookie *cookie)
{
- if (fscache_cookie_valid(cookie))
+ if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
__fscache_invalidate(cookie);
}
@@ -503,7 +545,7 @@ int fscache_read_or_alloc_page(struct fscache_cookie *cookie,
void *context,
gfp_t gfp)
{
- if (fscache_cookie_valid(cookie))
+ if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
return __fscache_read_or_alloc_page(cookie, page, end_io_func,
context, gfp);
else
@@ -554,7 +596,7 @@ int fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
void *context,
gfp_t gfp)
{
- if (fscache_cookie_valid(cookie))
+ if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
return __fscache_read_or_alloc_pages(cookie, mapping, pages,
nr_pages, end_io_func,
context, gfp);
@@ -585,7 +627,7 @@ int fscache_alloc_page(struct fscache_cookie *cookie,
struct page *page,
gfp_t gfp)
{
- if (fscache_cookie_valid(cookie))
+ if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
return __fscache_alloc_page(cookie, page, gfp);
else
return -ENOBUFS;
@@ -634,7 +676,7 @@ int fscache_write_page(struct fscache_cookie *cookie,
struct page *page,
gfp_t gfp)
{
- if (fscache_cookie_valid(cookie))
+ if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
return __fscache_write_page(cookie, page, gfp);
else
return -ENOBUFS;
@@ -744,4 +786,47 @@ void fscache_uncache_all_inode_pages(struct fscache_cookie *cookie,
__fscache_uncache_all_inode_pages(cookie, inode);
}
+/**
+ * fscache_disable_cookie - Disable a cookie
+ * @cookie: The cookie representing the cache object
+ * @invalidate: Invalidate the backing object
+ *
+ * Disable a cookie from accepting further alloc, read, write, invalidate,
+ * update or acquire operations. Outstanding operations can still be waited
+ * upon and pages can still be uncached and the cookie relinquished.
+ *
+ * This will not return until all outstanding operations have completed.
+ *
+ * If @invalidate is set, then the backing object will be invalidated and
+ * detached, otherwise it will just be detached.
+ */
+static inline
+void fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
+{
+ if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
+ __fscache_disable_cookie(cookie, invalidate);
+}
+
+/**
+ * fscache_enable_cookie - Reenable a cookie
+ * @cookie: The cookie representing the cache object
+ * @can_enable: A function to permit enablement once lock is held
+ * @data: Data for can_enable()
+ *
+ * Reenable a previously disabled cookie, allowing it to accept further alloc,
+ * read, write, invalidate, update or acquire operations. An attempt will be
+ * made to immediately reattach the cookie to a backing object.
+ *
+ * The can_enable() function is called (if not NULL) once the enablement lock
+ * is held to rule on whether enablement is still permitted to go ahead.
+ */
+static inline
+void fscache_enable_cookie(struct fscache_cookie *cookie,
+ bool (*can_enable)(void *data),
+ void *data)
+{
+ if (fscache_cookie_valid(cookie) && !fscache_cookie_enabled(cookie))
+ __fscache_enable_cookie(cookie, can_enable, data);
+}
+
#endif /* _LINUX_FSCACHE_H */
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index 1e041063b226..d9cf963ac832 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -33,7 +33,7 @@ extern void rcu_nmi_exit(void);
#define __irq_enter() \
do { \
account_irq_enter_time(current); \
- add_preempt_count(HARDIRQ_OFFSET); \
+ preempt_count_add(HARDIRQ_OFFSET); \
trace_hardirq_enter(); \
} while (0)
@@ -49,7 +49,7 @@ extern void irq_enter(void);
do { \
trace_hardirq_exit(); \
account_irq_exit_time(current); \
- sub_preempt_count(HARDIRQ_OFFSET); \
+ preempt_count_sub(HARDIRQ_OFFSET); \
} while (0)
/*
@@ -62,7 +62,7 @@ extern void irq_exit(void);
lockdep_off(); \
ftrace_nmi_enter(); \
BUG_ON(in_nmi()); \
- add_preempt_count(NMI_OFFSET + HARDIRQ_OFFSET); \
+ preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET); \
rcu_nmi_enter(); \
trace_hardirq_enter(); \
} while (0)
@@ -72,7 +72,7 @@ extern void irq_exit(void);
trace_hardirq_exit(); \
rcu_nmi_exit(); \
BUG_ON(!in_nmi()); \
- sub_preempt_count(NMI_OFFSET + HARDIRQ_OFFSET); \
+ preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET); \
ftrace_nmi_exit(); \
lockdep_on(); \
} while (0)
diff --git a/include/linux/hwmon-vid.h b/include/linux/hwmon-vid.h
index f346e4d5381c..da0a680e2f6d 100644
--- a/include/linux/hwmon-vid.h
+++ b/include/linux/hwmon-vid.h
@@ -38,7 +38,7 @@ static inline int vid_to_reg(int val, u8 vrm)
return ((val >= 1100) && (val <= 1850) ?
((18499 - val * 10) / 25 + 5) / 10 : -1);
default:
- return -1;
+ return -EINVAL;
}
}
diff --git a/include/linux/hwmon.h b/include/linux/hwmon.h
index b2514f70d591..09354f6c1d63 100644
--- a/include/linux/hwmon.h
+++ b/include/linux/hwmon.h
@@ -15,9 +15,19 @@
#define _HWMON_H_
struct device;
+struct attribute_group;
struct device *hwmon_device_register(struct device *dev);
+struct device *
+hwmon_device_register_with_groups(struct device *dev, const char *name,
+ void *drvdata,
+ const struct attribute_group **groups);
+struct device *
+devm_hwmon_device_register_with_groups(struct device *dev, const char *name,
+ void *drvdata,
+ const struct attribute_group **groups);
void hwmon_device_unregister(struct device *dev);
+void devm_hwmon_device_unregister(struct device *dev);
#endif
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index a3b8b2e2d244..15da677478dd 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -30,10 +30,13 @@
/*
* Framework version for util services.
*/
+#define UTIL_FW_MINOR 0
+
+#define UTIL_WS2K8_FW_MAJOR 1
+#define UTIL_WS2K8_FW_VERSION (UTIL_WS2K8_FW_MAJOR << 16 | UTIL_FW_MINOR)
#define UTIL_FW_MAJOR 3
-#define UTIL_FW_MINOR 0
-#define UTIL_FW_MAJOR_MINOR (UTIL_FW_MAJOR << 16 | UTIL_FW_MINOR)
+#define UTIL_FW_VERSION (UTIL_FW_MAJOR << 16 | UTIL_FW_MINOR)
/*
@@ -429,15 +432,6 @@ struct hv_ring_buffer_info {
u32 ring_data_startoffset;
};
-struct hv_ring_buffer_debug_info {
- u32 current_interrupt_mask;
- u32 current_read_index;
- u32 current_write_index;
- u32 bytes_avail_toread;
- u32 bytes_avail_towrite;
-};
-
-
/*
*
* hv_get_ringbuffer_availbytes()
@@ -899,23 +893,6 @@ enum vmbus_channel_state {
CHANNEL_OPENED_STATE,
};
-struct vmbus_channel_debug_info {
- u32 relid;
- enum vmbus_channel_state state;
- uuid_le interfacetype;
- uuid_le interface_instance;
- u32 monitorid;
- u32 servermonitor_pending;
- u32 servermonitor_latency;
- u32 servermonitor_connectionid;
- u32 clientmonitor_pending;
- u32 clientmonitor_latency;
- u32 clientmonitor_connectionid;
-
- struct hv_ring_buffer_debug_info inbound;
- struct hv_ring_buffer_debug_info outbound;
-};
-
/*
* Represents each channel msg on the vmbus connection This is a
* variable-size data structure depending on the msg type itself
@@ -1181,19 +1158,8 @@ extern int vmbus_recvpacket_raw(struct vmbus_channel *channel,
u64 *requestid);
-extern void vmbus_get_debug_info(struct vmbus_channel *channel,
- struct vmbus_channel_debug_info *debug);
-
extern void vmbus_ontimer(unsigned long data);
-struct hv_dev_port_info {
- u32 int_mask;
- u32 read_idx;
- u32 write_idx;
- u32 bytes_avail_toread;
- u32 bytes_avail_towrite;
-};
-
/* Base driver object */
struct hv_driver {
const char *name;
diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h
index 2bac0eb8948d..a1124bdc4cac 100644
--- a/include/linux/iio/buffer.h
+++ b/include/linux/iio/buffer.h
@@ -36,7 +36,7 @@ struct iio_buffer;
* any of them not existing.
**/
struct iio_buffer_access_funcs {
- int (*store_to)(struct iio_buffer *buffer, u8 *data);
+ int (*store_to)(struct iio_buffer *buffer, const void *data);
int (*read_first_n)(struct iio_buffer *buffer,
size_t n,
char __user *buf);
@@ -81,7 +81,7 @@ struct iio_buffer {
bool stufftoread;
const struct attribute_group *attrs;
struct list_head demux_list;
- unsigned char *demux_bounce;
+ void *demux_bounce;
struct list_head buffer_list;
};
@@ -120,7 +120,32 @@ int iio_scan_mask_set(struct iio_dev *indio_dev,
* @indio_dev: iio_dev structure for device.
* @data: Full scan.
*/
-int iio_push_to_buffers(struct iio_dev *indio_dev, unsigned char *data);
+int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data);
+
+/*
+ * iio_push_to_buffers_with_timestamp() - push data and timestamp to buffers
+ * @indio_dev: iio_dev structure for device.
+ * @data: sample data
+ * @timestamp: timestamp for the sample data
+ *
+ * Pushes data to the IIO device's buffers. If timestamps are enabled for the
+ * device the function will store the supplied timestamp as the last element in
+ * the sample data buffer before pushing it to the device buffers. The sample
+ * data buffer needs to be large enough to hold the additional timestamp
+ * (usually the buffer should be indio->scan_bytes bytes large).
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+static inline int iio_push_to_buffers_with_timestamp(struct iio_dev *indio_dev,
+ void *data, int64_t timestamp)
+{
+ if (indio_dev->scan_timestamp) {
+ size_t ts_offset = indio_dev->scan_bytes / sizeof(int64_t) - 1;
+ ((int64_t *)data)[ts_offset] = timestamp;
+ }
+
+ return iio_push_to_buffers(indio_dev, data);
+}
int iio_update_demux(struct iio_dev *indio_dev);
diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h
index e51f65480ea5..e732fda6c8e6 100644
--- a/include/linux/iio/common/st_sensors.h
+++ b/include/linux/iio/common/st_sensors.h
@@ -184,6 +184,7 @@ struct st_sensors {
u8 wai;
char sensors_supported[ST_SENSORS_MAX_4WAI][ST_SENSORS_MAX_NAME];
struct iio_chan_spec *ch;
+ int num_ch;
struct st_sensor_odr odr;
struct st_sensor_power pw;
struct st_sensor_axis enable_axis;
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
index 833926c91aa8..2752b1fd12be 100644
--- a/include/linux/iio/consumer.h
+++ b/include/linux/iio/consumer.h
@@ -77,7 +77,7 @@ struct iio_cb_buffer;
* fail.
*/
struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
- int (*cb)(u8 *data,
+ int (*cb)(const void *data,
void *private),
void *private);
/**
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index 2103cc32a5fb..ac1cb8f1858c 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -36,6 +36,14 @@ enum iio_chan_info_enum {
IIO_CHAN_INFO_PHASE,
IIO_CHAN_INFO_HARDWAREGAIN,
IIO_CHAN_INFO_HYSTERESIS,
+ IIO_CHAN_INFO_INT_TIME,
+};
+
+enum iio_shared_by {
+ IIO_SEPARATE,
+ IIO_SHARED_BY_TYPE,
+ IIO_SHARED_BY_DIR,
+ IIO_SHARED_BY_ALL
};
enum iio_endian {
@@ -57,7 +65,7 @@ struct iio_dev;
*/
struct iio_chan_spec_ext_info {
const char *name;
- bool shared;
+ enum iio_shared_by shared;
ssize_t (*read)(struct iio_dev *, uintptr_t private,
struct iio_chan_spec const *, char *buf);
ssize_t (*write)(struct iio_dev *, uintptr_t private,
@@ -125,7 +133,7 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev,
#define IIO_ENUM_AVAILABLE(_name, _e) \
{ \
.name = (_name "_available"), \
- .shared = true, \
+ .shared = IIO_SHARED_BY_TYPE, \
.read = iio_enum_available_read, \
.private = (uintptr_t)(_e), \
}
@@ -146,12 +154,14 @@ ssize_t iio_enum_write(struct iio_dev *indio_dev,
* shift: Shift right by this before masking out
* realbits.
* endianness: little or big endian
- * @info_mask: What information is to be exported about this channel.
- * This includes calibbias, scale etc.
* @info_mask_separate: What information is to be exported that is specific to
* this channel.
* @info_mask_shared_by_type: What information is to be exported that is shared
-* by all channels of the same type.
+ * by all channels of the same type.
+ * @info_mask_shared_by_dir: What information is to be exported that is shared
+ * by all channels of the same direction.
+ * @info_mask_shared_by_all: What information is to be exported that is shared
+ * by all channels.
* @event_mask: What events can this channel produce.
* @ext_info: Array of extended info attributes for this channel.
* The array is NULL terminated, the last element should
@@ -186,9 +196,10 @@ struct iio_chan_spec {
u8 shift;
enum iio_endian endianness;
} scan_type;
- long info_mask;
long info_mask_separate;
long info_mask_shared_by_type;
+ long info_mask_shared_by_dir;
+ long info_mask_shared_by_all;
long event_mask;
const struct iio_chan_spec_ext_info *ext_info;
const char *extend_name;
@@ -212,7 +223,9 @@ static inline bool iio_channel_has_info(const struct iio_chan_spec *chan,
enum iio_chan_info_enum type)
{
return (chan->info_mask_separate & BIT(type)) |
- (chan->info_mask_shared_by_type & BIT(type));
+ (chan->info_mask_shared_by_type & BIT(type)) |
+ (chan->info_mask_shared_by_dir & BIT(type)) |
+ (chan->info_mask_shared_by_all & BIT(type));
}
#define IIO_ST(si, rb, sb, sh) \
@@ -457,7 +470,7 @@ static inline void iio_device_put(struct iio_dev *indio_dev)
{
if (indio_dev)
put_device(&indio_dev->dev);
-};
+}
/**
* dev_to_iio_dev() - Get IIO device struct from a device struct
@@ -593,7 +606,7 @@ static inline bool iio_buffer_enabled(struct iio_dev *indio_dev)
{
return indio_dev->currentmode
& (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE);
-};
+}
/**
* iio_get_debugfs_dentry() - helper function to get the debugfs_dentry
@@ -603,12 +616,12 @@ static inline bool iio_buffer_enabled(struct iio_dev *indio_dev)
static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev)
{
return indio_dev->debugfs_dentry;
-};
+}
#else
static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev)
{
return NULL;
-};
+}
#endif
int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer,
diff --git a/include/linux/iio/sysfs.h b/include/linux/iio/sysfs.h
index 2958c960003a..8a1d18640ab9 100644
--- a/include/linux/iio/sysfs.h
+++ b/include/linux/iio/sysfs.h
@@ -100,6 +100,21 @@ struct iio_const_attr {
#define IIO_CONST_ATTR_SAMP_FREQ_AVAIL(_string) \
IIO_CONST_ATTR(sampling_frequency_available, _string)
+/**
+ * IIO_DEV_ATTR_INT_TIME_AVAIL - list available integration times
+ * @_show: output method for the attribute
+ **/
+#define IIO_DEV_ATTR_INT_TIME_AVAIL(_show) \
+ IIO_DEVICE_ATTR(integration_time_available, S_IRUGO, _show, NULL, 0)
+/**
+ * IIO_CONST_ATTR_INT_TIME_AVAIL - list available integration times
+ * @_string: frequency string for the attribute
+ *
+ * Constant version
+ **/
+#define IIO_CONST_ATTR_INT_TIME_AVAIL(_string) \
+ IIO_CONST_ATTR(integration_time_available, _string)
+
#define IIO_DEV_ATTR_TEMP_RAW(_show) \
IIO_DEVICE_ATTR(in_temp_raw, S_IRUGO, _show, NULL, 0)
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 78e2ada50cd5..d380c5e68008 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -55,7 +55,7 @@
#define DMAR_IQT_REG 0x88 /* Invalidation queue tail register */
#define DMAR_IQ_SHIFT 4 /* Invalidation queue head/tail shift */
#define DMAR_IQA_REG 0x90 /* Invalidation queue addr register */
-#define DMAR_ICS_REG 0x98 /* Invalidation complete status register */
+#define DMAR_ICS_REG 0x9c /* Invalidation complete status register */
#define DMAR_IRTA_REG 0xb8 /* Interrupt remapping table addr register */
#define OFFSET_STRIDE (9)
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 7ea319e95b47..a444c790fa72 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -22,6 +22,7 @@
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/types.h>
+#include <trace/events/iommu.h>
#define IOMMU_READ (1)
#define IOMMU_WRITE (2)
@@ -227,6 +228,7 @@ static inline int report_iommu_fault(struct iommu_domain *domain,
ret = domain->handler(domain, dev, iova, flags,
domain->handler_token);
+ trace_io_page_fault(dev, iova, flags);
return ret;
}
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 0e5d9ecdb2b6..46544e381bf9 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -31,6 +31,8 @@
#define GIC_DIST_TARGET 0x800
#define GIC_DIST_CONFIG 0xc00
#define GIC_DIST_SOFTINT 0xf00
+#define GIC_DIST_SGI_PENDING_CLEAR 0xf10
+#define GIC_DIST_SGI_PENDING_SET 0xf20
#define GICH_HCR 0x0
#define GICH_VTR 0x4
@@ -74,6 +76,9 @@ static inline void gic_init(unsigned int nr, int start,
gic_init_bases(nr, start, dist, cpu, 0, NULL);
}
+int gic_get_cpu_id(unsigned int cpu);
+void gic_migrate_target(unsigned int new_cpu_id);
+
#endif /* __ASSEMBLY */
#endif
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 482ad2d84a32..672ddc4de4af 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -439,6 +439,17 @@ static inline char *hex_byte_pack(char *buf, u8 byte)
return buf;
}
+extern const char hex_asc_upper[];
+#define hex_asc_upper_lo(x) hex_asc_upper[((x) & 0x0f)]
+#define hex_asc_upper_hi(x) hex_asc_upper[((x) & 0xf0) >> 4]
+
+static inline char *hex_byte_pack_upper(char *buf, u8 byte)
+{
+ *buf++ = hex_asc_upper_hi(byte);
+ *buf++ = hex_asc_upper_lo(byte);
+ return buf;
+}
+
static inline char * __deprecated pack_hex_byte(char *buf, u8 byte)
{
return hex_byte_pack(buf, byte);
diff --git a/include/linux/kobj_completion.h b/include/linux/kobj_completion.h
new file mode 100644
index 000000000000..a428f6436063
--- /dev/null
+++ b/include/linux/kobj_completion.h
@@ -0,0 +1,18 @@
+#ifndef _KOBJ_COMPLETION_H_
+#define _KOBJ_COMPLETION_H_
+
+#include <linux/kobject.h>
+#include <linux/completion.h>
+
+struct kobj_completion {
+ struct kobject kc_kobj;
+ struct completion kc_unregister;
+};
+
+#define kobj_to_kobj_completion(kobj) \
+ container_of(kobj, struct kobj_completion, kc_kobj)
+
+void kobj_completion_init(struct kobj_completion *kc, struct kobj_type *ktype);
+void kobj_completion_release(struct kobject *kobj);
+void kobj_completion_del_and_wait(struct kobj_completion *kc);
+#endif /* _KOBJ_COMPLETION_H_ */
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index de6dcbcc6ef7..e7ba650086ce 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -107,6 +107,7 @@ extern int __must_check kobject_move(struct kobject *, struct kobject *);
extern struct kobject *kobject_get(struct kobject *kobj);
extern void kobject_put(struct kobject *kobj);
+extern const void *kobject_namespace(struct kobject *kobj);
extern char *kobject_get_path(struct kobject *kobj, gfp_t flag);
struct kobj_type {
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 0fbbc7aa02cb..749bdb12cd15 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -190,7 +190,6 @@ struct kvm_async_pf {
unsigned long addr;
struct kvm_arch_async_pf arch;
struct page *page;
- bool done;
};
void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu);
diff --git a/include/linux/mfd/arizona/registers.h b/include/linux/mfd/arizona/registers.h
index 4706d3d46e56..cb49417f8ba9 100644
--- a/include/linux/mfd/arizona/registers.h
+++ b/include/linux/mfd/arizona/registers.h
@@ -1908,7 +1908,7 @@
#define ARIZONA_FLL2_SYNC_GAIN_MASK 0x003c /* FLL2_SYNC_GAIN */
#define ARIZONA_FLL2_SYNC_GAIN_SHIFT 2 /* FLL2_SYNC_GAIN */
#define ARIZONA_FLL2_SYNC_GAIN_WIDTH 4 /* FLL2_SYNC_GAIN */
-#define ARIZONA_FLL2_SYNC_BW_MASK 0x0001 /* FLL2_SYNC_BW */
+#define ARIZONA_FLL2_SYNC_BW 0x0001 /* FLL2_SYNC_BW */
#define ARIZONA_FLL2_SYNC_BW_MASK 0x0001 /* FLL2_SYNC_BW */
#define ARIZONA_FLL2_SYNC_BW_SHIFT 0 /* FLL2_SYNC_BW */
#define ARIZONA_FLL2_SYNC_BW_WIDTH 1 /* FLL2_SYNC_BW */
diff --git a/include/linux/mfd/da9052/da9052.h b/include/linux/mfd/da9052/da9052.h
index 786d02eb79d2..21e21b81cc75 100644
--- a/include/linux/mfd/da9052/da9052.h
+++ b/include/linux/mfd/da9052/da9052.h
@@ -148,10 +148,15 @@ static inline int da9052_group_read(struct da9052 *da9052, unsigned char reg,
unsigned reg_cnt, unsigned char *val)
{
int ret;
+ unsigned int tmp;
+ int i;
- ret = regmap_bulk_read(da9052->regmap, reg, val, reg_cnt);
- if (ret < 0)
- return ret;
+ for (i = 0; i < reg_cnt; i++) {
+ ret = regmap_read(da9052->regmap, reg + i, &tmp);
+ val[i] = (unsigned char)tmp;
+ if (ret < 0)
+ return ret;
+ }
if (da9052->fix_io) {
ret = da9052->fix_io(da9052, reg);
@@ -166,10 +171,13 @@ static inline int da9052_group_write(struct da9052 *da9052, unsigned char reg,
unsigned reg_cnt, unsigned char *val)
{
int ret;
+ int i;
- ret = regmap_raw_write(da9052->regmap, reg, val, reg_cnt);
- if (ret < 0)
- return ret;
+ for (i = 0; i < reg_cnt; i++) {
+ ret = regmap_write(da9052->regmap, reg + i, val[i]);
+ if (ret < 0)
+ return ret;
+ }
if (da9052->fix_io) {
ret = da9052->fix_io(da9052, reg);
diff --git a/include/linux/mfd/mc13xxx.h b/include/linux/mfd/mc13xxx.h
index 41ed59276c00..67c17b5a6f44 100644
--- a/include/linux/mfd/mc13xxx.h
+++ b/include/linux/mfd/mc13xxx.h
@@ -41,6 +41,13 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx,
unsigned int mode, unsigned int channel,
u8 ato, bool atox, unsigned int *sample);
+#define MC13783_AUDIO_RX0 36
+#define MC13783_AUDIO_RX1 37
+#define MC13783_AUDIO_TX 38
+#define MC13783_SSI_NETWORK 39
+#define MC13783_AUDIO_CODEC 40
+#define MC13783_AUDIO_DAC 41
+
#define MC13XXX_IRQ_ADCDONE 0
#define MC13XXX_IRQ_ADCBISDONE 1
#define MC13XXX_IRQ_TS 2
diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h
index d1382dfbeff0..0ce772105508 100644
--- a/include/linux/mfd/rtsx_pci.h
+++ b/include/linux/mfd/rtsx_pci.h
@@ -756,6 +756,59 @@
#define PCR_SETTING_REG2 0x814
#define PCR_SETTING_REG3 0x747
+/* Phy bits */
+#define PHY_PCR_FORCE_CODE 0xB000
+#define PHY_PCR_OOBS_CALI_50 0x0800
+#define PHY_PCR_OOBS_VCM_08 0x0200
+#define PHY_PCR_OOBS_SEN_90 0x0040
+#define PHY_PCR_RSSI_EN 0x0002
+
+#define PHY_RCR1_ADP_TIME 0x0100
+#define PHY_RCR1_VCO_COARSE 0x001F
+
+#define PHY_RCR2_EMPHASE_EN 0x8000
+#define PHY_RCR2_NADJR 0x4000
+#define PHY_RCR2_CDR_CP_10 0x0400
+#define PHY_RCR2_CDR_SR_2 0x0100
+#define PHY_RCR2_FREQSEL_12 0x0040
+#define PHY_RCR2_CPADJEN 0x0020
+#define PHY_RCR2_CDR_SC_8 0x0008
+#define PHY_RCR2_CALIB_LATE 0x0002
+
+#define PHY_RDR_RXDSEL_1_9 0x4000
+
+#define PHY_TUNE_TUNEREF_1_0 0x4000
+#define PHY_TUNE_VBGSEL_1252 0x0C00
+#define PHY_TUNE_SDBUS_33 0x0200
+#define PHY_TUNE_TUNED18 0x01C0
+#define PHY_TUNE_TUNED12 0X0020
+
+#define PHY_BPCR_IBRXSEL 0x0400
+#define PHY_BPCR_IBTXSEL 0x0100
+#define PHY_BPCR_IB_FILTER 0x0080
+#define PHY_BPCR_CMIRROR_EN 0x0040
+
+#define PHY_REG_REV_RESV 0xE000
+#define PHY_REG_REV_RXIDLE_LATCHED 0x1000
+#define PHY_REG_REV_P1_EN 0x0800
+#define PHY_REG_REV_RXIDLE_EN 0x0400
+#define PHY_REG_REV_CLKREQ_DLY_TIMER_1_0 0x0040
+#define PHY_REG_REV_STOP_CLKRD 0x0020
+#define PHY_REG_REV_RX_PWST 0x0008
+#define PHY_REG_REV_STOP_CLKWR 0x0004
+
+#define PHY_FLD3_TIMER_4 0x7800
+#define PHY_FLD3_TIMER_6 0x00E0
+#define PHY_FLD3_RXDELINK 0x0004
+
+#define PHY_FLD4_FLDEN_SEL 0x4000
+#define PHY_FLD4_REQ_REF 0x2000
+#define PHY_FLD4_RXAMP_OFF 0x1000
+#define PHY_FLD4_REQ_ADDA 0x0800
+#define PHY_FLD4_BER_COUNT 0x00E0
+#define PHY_FLD4_BER_TIMER 0x000A
+#define PHY_FLD4_BER_CHK_EN 0x0001
+
#define rtsx_pci_init_cmd(pcr) ((pcr)->ci = 0)
struct rtsx_pcr;
diff --git a/include/linux/mfd/stw481x.h b/include/linux/mfd/stw481x.h
new file mode 100644
index 000000000000..eda121556e5d
--- /dev/null
+++ b/include/linux/mfd/stw481x.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ *
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#ifndef MFD_STW481X_H
+#define MFD_STW481X_H
+
+#include <linux/i2c.h>
+#include <linux/regulator/machine.h>
+#include <linux/regmap.h>
+#include <linux/bitops.h>
+
+/* These registers are accessed from more than one driver */
+#define STW_CONF1 0x11U
+#define STW_CONF1_PDN_VMMC 0x01U
+#define STW_CONF1_VMMC_MASK 0x0eU
+#define STW_CONF1_VMMC_1_8V 0x02U
+#define STW_CONF1_VMMC_2_85V 0x04U
+#define STW_CONF1_VMMC_3V 0x06U
+#define STW_CONF1_VMMC_1_85V 0x08U
+#define STW_CONF1_VMMC_2_6V 0x0aU
+#define STW_CONF1_VMMC_2_7V 0x0cU
+#define STW_CONF1_VMMC_3_3V 0x0eU
+#define STW_CONF1_MMC_LS_STATUS 0x10U
+#define STW_PCTL_REG_LO 0x1eU
+#define STW_PCTL_REG_HI 0x1fU
+#define STW_CONF1_V_MONITORING 0x20U
+#define STW_CONF1_IT_WARN 0x40U
+#define STW_CONF1_PDN_VAUX 0x80U
+#define STW_CONF2 0x20U
+#define STW_CONF2_MASK_TWARN 0x01U
+#define STW_CONF2_VMMC_EXT 0x02U
+#define STW_CONF2_MASK_IT_WAKE_UP 0x04U
+#define STW_CONF2_GPO1 0x08U
+#define STW_CONF2_GPO2 0x10U
+#define STW_VCORE_SLEEP 0x21U
+
+/**
+ * struct stw481x - state holder for the Stw481x drivers
+ * @mutex: mutex to serialize I2C accesses
+ * @i2c_client: corresponding I2C client
+ * @regulator: regulator device for regulator children
+ * @map: regmap handle to access device registers
+ */
+struct stw481x {
+ struct mutex lock;
+ struct i2c_client *client;
+ struct regulator_dev *vmmc_regulator;
+ struct regmap *map;
+};
+
+#endif
diff --git a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
index b6bdcd66c07d..7086b2248c8f 100644
--- a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
+++ b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
@@ -363,4 +363,9 @@
#define IMX6Q_GPR13_SATA_TX_LVL_1_240_V (0x1f << 2)
#define IMX6Q_GPR13_SATA_MPLL_CLK_EN BIT(1)
#define IMX6Q_GPR13_SATA_TX_EDGE_RATE BIT(0)
+
+/* For imx6sl iomux gpr register field define */
+#define IMX6SL_GPR1_FEC_CLOCK_MUX1_SEL_MASK (0x3 << 17)
+#define IMX6SL_GPR1_FEC_CLOCK_MUX2_SEL_MASK (0x1 << 14)
+
#endif /* __LINUX_IMX6Q_IOMUXC_GPR_H */
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index 25f2c611ab01..d498d98f0c2c 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -46,16 +46,24 @@
/* Step Enable */
#define STEPENB_MASK (0x1FFFF << 0)
#define STEPENB(val) ((val) << 0)
+#define ENB(val) (1 << (val))
+#define STPENB_STEPENB STEPENB(0x1FFFF)
+#define STPENB_STEPENB_TC STEPENB(0x1FFF)
/* IRQ enable */
#define IRQENB_HW_PEN BIT(0)
#define IRQENB_FIFO0THRES BIT(2)
+#define IRQENB_FIFO0OVRRUN BIT(3)
+#define IRQENB_FIFO0UNDRFLW BIT(4)
#define IRQENB_FIFO1THRES BIT(5)
+#define IRQENB_FIFO1OVRRUN BIT(6)
+#define IRQENB_FIFO1UNDRFLW BIT(7)
#define IRQENB_PENUP BIT(9)
/* Step Configuration */
#define STEPCONFIG_MODE_MASK (3 << 0)
#define STEPCONFIG_MODE(val) ((val) << 0)
+#define STEPCONFIG_MODE_SWCNT STEPCONFIG_MODE(1)
#define STEPCONFIG_MODE_HWSYNC STEPCONFIG_MODE(2)
#define STEPCONFIG_AVG_MASK (7 << 2)
#define STEPCONFIG_AVG(val) ((val) << 2)
@@ -123,15 +131,21 @@
#define ADC_CLK 3000000
#define TOTAL_STEPS 16
#define TOTAL_CHANNELS 8
+#define FIFO1_THRESHOLD 19
/*
-* ADC runs at 3MHz, and it takes
-* 15 cycles to latch one data output.
-* Hence the idle time for ADC to
-* process one sample data would be
-* around 5 micro seconds.
-*/
-#define IDLE_TIMEOUT 5 /* microsec */
+ * time in us for processing a single channel, calculated as follows:
+ *
+ * num cycles = open delay + (sample delay + conv time) * averaging
+ *
+ * num cycles: 152 + (1 + 13) * 16 = 376
+ *
+ * clock frequency: 26MHz / 8 = 3.25MHz
+ * clock period: 1 / 3.25MHz = 308ns
+ *
+ * processing time: 376 * 308ns = 116us
+ */
+#define IDLE_TIMEOUT 116 /* microsec */
#define TSCADC_CELLS 2
@@ -146,6 +160,7 @@ struct ti_tscadc_dev {
struct mfd_cell cells[TSCADC_CELLS];
u32 reg_se_cache;
spinlock_t reg_lock;
+ unsigned int clk_div;
/* tsc device */
struct titsc *tsc;
diff --git a/include/linux/mfd/wm8994/core.h b/include/linux/mfd/wm8994/core.h
index 40854ac0ba3d..eefafa62d304 100644
--- a/include/linux/mfd/wm8994/core.h
+++ b/include/linux/mfd/wm8994/core.h
@@ -56,8 +56,6 @@ struct irq_domain;
#define WM8994_IRQ_GPIO(x) (x + WM8994_IRQ_TEMP_WARN)
struct wm8994 {
- struct mutex irq_lock;
-
struct wm8994_pdata pdata;
enum wm8994_type type;
@@ -85,16 +83,43 @@ struct wm8994 {
};
/* Device I/O API */
-int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg);
-int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg,
- unsigned short val);
-int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
- unsigned short mask, unsigned short val);
-int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
- int count, u16 *buf);
-int wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg,
- int count, const u16 *buf);
+static inline int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(wm8994->regmap, reg, &val);
+
+ if (ret < 0)
+ return ret;
+ else
+ return val;
+}
+
+static inline int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg,
+ unsigned short val)
+{
+ return regmap_write(wm8994->regmap, reg, val);
+}
+
+static inline int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
+ int count, u16 *buf)
+{
+ return regmap_bulk_read(wm8994->regmap, reg, buf, count);
+}
+
+static inline int wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg,
+ int count, const u16 *buf)
+{
+ return regmap_raw_write(wm8994->regmap, reg, buf, count * sizeof(u16));
+}
+
+static inline int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
+ unsigned short mask, unsigned short val)
+{
+ return regmap_update_bits(wm8994->regmap, reg, mask, val);
+}
/* Helper to save on boilerplate */
static inline int wm8994_request_irq(struct wm8994 *wm8994, int irq,
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index 09c2300ddb37..c8cf093d8b71 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -31,6 +31,7 @@
#define I2O_MINOR 166
#define MICROCODE_MINOR 184
#define TUN_MINOR 200
+#define CUSE_MINOR 203
#define MWAVE_MINOR 219 /* ACP/Mwave Modem */
#define MPT_MINOR 220
#define MPT2SAS_MINOR 221
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 842de3e21e70..f42cdbd8ac21 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -420,7 +420,6 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
#define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR)
#define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR)
#define mmc_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED)
-#define mmc_sd_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED)
#define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
#define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED))
#define mmc_card_doing_bkops(c) ((c)->state & MMC_STATE_DOING_BKOPS)
@@ -432,7 +431,6 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
#define mmc_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
-#define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
#define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
#define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
#define mmc_card_set_doing_bkops(c) ((c)->state |= MMC_STATE_DOING_BKOPS)
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index da51bec578c3..a00fc49c8434 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -188,7 +188,6 @@ extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int);
extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort);
extern void mmc_release_host(struct mmc_host *host);
-extern int mmc_try_claim_host(struct mmc_host *host);
extern void mmc_get_card(struct mmc_card *card);
extern void mmc_put_card(struct mmc_card *card);
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index 198f0fa44e9f..6ce7d2cd3c7a 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -15,6 +15,7 @@
#define LINUX_MMC_DW_MMC_H
#include <linux/scatterlist.h>
+#include <linux/mmc/core.h>
#define MAX_MCI_SLOTS 2
@@ -129,6 +130,9 @@ struct dw_mci {
struct mmc_request *mrq;
struct mmc_command *cmd;
struct mmc_data *data;
+ struct mmc_command stop_abort;
+ unsigned int prev_blksz;
+ unsigned char timing;
struct workqueue_struct *card_workqueue;
/* DMA interface members*/
diff --git a/include/linux/mount.h b/include/linux/mount.h
index 38cd98f112a0..fdbb3e6aba65 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -77,6 +77,6 @@ extern struct vfsmount *vfs_kern_mount(struct file_system_type *type,
extern void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list);
extern void mark_mounts_for_expiry(struct list_head *mounts);
-extern dev_t name_to_dev_t(char *name);
+extern dev_t name_to_dev_t(const char *name);
#endif /* _LINUX_MOUNT_H */
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index ac8e89d5a792..129548169400 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -498,7 +498,6 @@ struct nand_buffers {
* supported, 0 otherwise.
* @onfi_set_features: [REPLACEABLE] set the features for ONFI nand
* @onfi_get_features: [REPLACEABLE] get the features for ONFI nand
- * @ecclayout: [REPLACEABLE] the default ECC placement scheme
* @bbt: [INTERN] bad block table pointer
* @bbt_td: [REPLACEABLE] bad block table descriptor for flash
* lookup.
@@ -572,7 +571,6 @@ struct nand_chip {
uint8_t *oob_poi;
struct nand_hw_control *controller;
- struct nand_ecclayout *ecclayout;
struct nand_ecc_ctrl ecc;
struct nand_buffers *buffers;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3de49aca4519..0ea606ffa7cd 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1143,8 +1143,18 @@ struct net_device {
struct list_head dev_list;
struct list_head napi_list;
struct list_head unreg_list;
- struct list_head upper_dev_list; /* List of upper devices */
- struct list_head lower_dev_list;
+
+ /* directly linked devices, like slaves for bonding */
+ struct {
+ struct list_head upper;
+ struct list_head lower;
+ } adj_list;
+
+ /* all linked devices, *including* neighbours */
+ struct {
+ struct list_head upper;
+ struct list_head lower;
+ } all_adj_list;
/* currently active device features */
@@ -2813,24 +2823,49 @@ extern int bpf_jit_enable;
extern bool netdev_has_upper_dev(struct net_device *dev,
struct net_device *upper_dev);
extern bool netdev_has_any_upper_dev(struct net_device *dev);
-extern struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
- struct list_head **iter);
+extern 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, upper, iter) \
- for (iter = &(dev)->upper_dev_list, \
- upper = netdev_upper_get_next_dev_rcu(dev, &(iter)); \
- upper; \
- upper = netdev_upper_get_next_dev_rcu(dev, &(iter)))
-
+#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)); \
+ updev; \
+ updev = netdev_all_upper_get_next_dev_rcu(dev, &(iter)))
+
+extern void *netdev_lower_get_next_private(struct net_device *dev,
+ struct list_head **iter);
+extern void *netdev_lower_get_next_private_rcu(struct net_device *dev,
+ struct list_head **iter);
+
+#define netdev_for_each_lower_private(dev, priv, iter) \
+ for (iter = (dev)->adj_list.lower.next, \
+ priv = netdev_lower_get_next_private(dev, &(iter)); \
+ priv; \
+ priv = netdev_lower_get_next_private(dev, &(iter)))
+
+#define netdev_for_each_lower_private_rcu(dev, priv, iter) \
+ for (iter = &(dev)->adj_list.lower, \
+ priv = netdev_lower_get_next_private_rcu(dev, &(iter)); \
+ priv; \
+ priv = netdev_lower_get_next_private_rcu(dev, &(iter)))
+
+extern void *netdev_adjacent_get_private(struct list_head *adj_list);
extern struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
extern struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev);
extern int netdev_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev);
extern int netdev_master_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev);
+extern int netdev_master_upper_dev_link_private(struct net_device *dev,
+ struct net_device *upper_dev,
+ void *private);
extern void netdev_upper_dev_unlink(struct net_device *dev,
struct net_device *upper_dev);
+extern void *netdev_lower_dev_get_private_rcu(struct net_device *dev,
+ struct net_device *lower_dev);
+extern void *netdev_lower_dev_get_private(struct net_device *dev,
+ struct net_device *lower_dev);
extern int skb_checksum_help(struct sk_buff *skb);
extern struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
netdev_features_t features, bool tx_path);
@@ -2873,8 +2908,20 @@ extern int __init dev_proc_init(void);
#define dev_proc_init() 0
#endif
-extern int netdev_class_create_file(struct class_attribute *class_attr);
-extern void netdev_class_remove_file(struct class_attribute *class_attr);
+extern int netdev_class_create_file_ns(struct class_attribute *class_attr,
+ const void *ns);
+extern void netdev_class_remove_file_ns(struct class_attribute *class_attr,
+ const void *ns);
+
+static inline int netdev_class_create_file(struct class_attribute *class_attr)
+{
+ return netdev_class_create_file_ns(class_attr, NULL);
+}
+
+static inline void netdev_class_remove_file(struct class_attribute *class_attr)
+{
+ netdev_class_remove_file_ns(class_attr, NULL);
+}
extern struct kobj_ns_type_operations net_ns_type_operations;
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 3ea4cde8701c..96235b53a3fd 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -269,9 +269,13 @@ static inline int NFS_STALE(const struct inode *inode)
return test_bit(NFS_INO_STALE, &NFS_I(inode)->flags);
}
-static inline int NFS_FSCACHE(const struct inode *inode)
+static inline struct fscache_cookie *nfs_i_fscache(struct inode *inode)
{
- return test_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags);
+#ifdef CONFIG_NFS_FSCACHE
+ return NFS_I(inode)->fscache;
+#else
+ return NULL;
+#endif
}
static inline __u64 NFS_FILEID(const struct inode *inode)
@@ -457,14 +461,11 @@ extern int nfs3_removexattr (struct dentry *, const char *name);
/*
* linux/fs/nfs/direct.c
*/
-extern ssize_t nfs_direct_IO(int, struct kiocb *, const struct iovec *, loff_t,
- unsigned long);
-extern ssize_t nfs_file_direct_read(struct kiocb *iocb,
- const struct iovec *iov, unsigned long nr_segs,
- loff_t pos, bool uio);
-extern ssize_t nfs_file_direct_write(struct kiocb *iocb,
- const struct iovec *iov, unsigned long nr_segs,
- loff_t pos, bool uio);
+extern ssize_t nfs_direct_IO(int, struct kiocb *, struct iov_iter *, loff_t);
+extern ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos);
+extern ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos);
/*
* linux/fs/nfs/dir.c
diff --git a/include/linux/of_mtd.h b/include/linux/of_mtd.h
index ed7f267e6389..6f10e938ff7e 100644
--- a/include/linux/of_mtd.h
+++ b/include/linux/of_mtd.h
@@ -10,10 +10,29 @@
#define __LINUX_OF_NET_H
#ifdef CONFIG_OF_MTD
+
#include <linux/of.h>
int of_get_nand_ecc_mode(struct device_node *np);
int of_get_nand_bus_width(struct device_node *np);
bool of_get_nand_on_flash_bbt(struct device_node *np);
-#endif
+
+#else /* CONFIG_OF_MTD */
+
+static inline int of_get_nand_ecc_mode(struct device_node *np)
+{
+ return -ENOSYS;
+}
+
+static inline int of_get_nand_bus_width(struct device_node *np)
+{
+ return -ENOSYS;
+}
+
+static inline bool of_get_nand_on_flash_bbt(struct device_node *np)
+{
+ return false;
+}
+
+#endif /* CONFIG_OF_MTD */
#endif /* __LINUX_OF_MTD_H */
diff --git a/include/linux/platform_data/leds-lp55xx.h b/include/linux/platform_data/leds-lp55xx.h
index 51a2ff579d60..c32de4dcec54 100644
--- a/include/linux/platform_data/leds-lp55xx.h
+++ b/include/linux/platform_data/leds-lp55xx.h
@@ -22,6 +22,7 @@
struct lp55xx_led_config {
const char *name;
+ const char *default_trigger;
u8 chan_nr;
u8 led_current; /* mA x10, 0 if led is not connected */
u8 max_current;
diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h
index d44912d81578..a0f5a8f9b3bc 100644
--- a/include/linux/platform_data/mmc-esdhc-imx.h
+++ b/include/linux/platform_data/mmc-esdhc-imx.h
@@ -10,6 +10,8 @@
#ifndef __ASM_ARCH_IMX_ESDHC_H
#define __ASM_ARCH_IMX_ESDHC_H
+#include <linux/types.h>
+
enum wp_types {
ESDHC_WP_NONE, /* no WP, neither controller nor gpio */
ESDHC_WP_CONTROLLER, /* mmc controller internal WP */
@@ -32,6 +34,7 @@ enum cd_types {
* @cd_gpio: gpio for card_detect interrupt
* @wp_type: type of write_protect method (see wp_types enum above)
* @cd_type: type of card_detect method (see cd_types enum above)
+ * @support_vsel: indicate it supports 1.8v switching
*/
struct esdhc_platform_data {
@@ -41,5 +44,6 @@ struct esdhc_platform_data {
enum cd_types cd_type;
int max_bus_width;
unsigned int f_max;
+ bool support_vsel;
};
#endif /* __ASM_ARCH_IMX_ESDHC_H */
diff --git a/include/linux/platform_data/pinctrl-adi2.h b/include/linux/platform_data/pinctrl-adi2.h
new file mode 100644
index 000000000000..8f91300617ec
--- /dev/null
+++ b/include/linux/platform_data/pinctrl-adi2.h
@@ -0,0 +1,40 @@
+/*
+ * Pinctrl Driver for ADI GPIO2 controller
+ *
+ * Copyright 2007-2013 Analog Devices Inc.
+ *
+ * Licensed under the GPLv2 or later
+ */
+
+
+#ifndef PINCTRL_ADI2_H
+#define PINCTRL_ADI2_H
+
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+/**
+ * struct adi_pinctrl_gpio_platform_data - Pinctrl gpio platform data
+ * for ADI GPIO2 device.
+ *
+ * @port_gpio_base: Optional global GPIO index of the GPIO bank.
+ * 0 means driver decides.
+ * @port_pin_base: Pin index of the pin controller device.
+ * @port_width: PIN number of the GPIO bank device
+ * @pint_id: GPIO PINT device id that this GPIO bank should map to.
+ * @pint_assign: The 32-bit GPIO PINT registers can be divided into 2 parts. A
+ * GPIO bank can be mapped into either low 16 bits[0] or high 16
+ * bits[1] of each PINT register.
+ * @pint_map: GIOP bank mapping code in PINT device
+ */
+struct adi_pinctrl_gpio_platform_data {
+ unsigned int port_gpio_base;
+ unsigned int port_pin_base;
+ unsigned int port_width;
+ u8 pinctrl_id;
+ u8 pint_id;
+ bool pint_assign;
+ u8 pint_map;
+};
+
+#endif
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index ce8e4ffd78c7..16f6654082dd 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -178,6 +178,7 @@ struct platform_driver {
int (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
+ bool prevent_deferred_probe;
};
#define to_platform_driver(drv) (container_of((drv), struct platform_driver, \
diff --git a/include/linux/preempt.h b/include/linux/preempt.h
index f5d4723cdb3d..a3d9dc8c2c00 100644
--- a/include/linux/preempt.h
+++ b/include/linux/preempt.h
@@ -6,106 +6,95 @@
* preempt_count (used for kernel preemption, interrupt count, etc.)
*/
-#include <linux/thread_info.h>
#include <linux/linkage.h>
#include <linux/list.h>
-#if defined(CONFIG_DEBUG_PREEMPT) || defined(CONFIG_PREEMPT_TRACER)
- extern void add_preempt_count(int val);
- extern void sub_preempt_count(int val);
-#else
-# define add_preempt_count(val) do { preempt_count() += (val); } while (0)
-# define sub_preempt_count(val) do { preempt_count() -= (val); } while (0)
-#endif
-
-#define inc_preempt_count() add_preempt_count(1)
-#define dec_preempt_count() sub_preempt_count(1)
-
-#define preempt_count() (current_thread_info()->preempt_count)
-
-#ifdef CONFIG_PREEMPT
-
-asmlinkage void preempt_schedule(void);
-
-#define preempt_check_resched() \
-do { \
- if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
- preempt_schedule(); \
-} while (0)
-
-#ifdef CONFIG_CONTEXT_TRACKING
+/*
+ * We use the MSB mostly because its available; see <linux/preempt_mask.h> for
+ * the other bits -- can't include that header due to inclusion hell.
+ */
+#define PREEMPT_NEED_RESCHED 0x80000000
-void preempt_schedule_context(void);
+#include <asm/preempt.h>
-#define preempt_check_resched_context() \
-do { \
- if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
- preempt_schedule_context(); \
-} while (0)
+#if defined(CONFIG_DEBUG_PREEMPT) || defined(CONFIG_PREEMPT_TRACER)
+extern void preempt_count_add(int val);
+extern void preempt_count_sub(int val);
+#define preempt_count_dec_and_test() ({ preempt_count_sub(1); should_resched(); })
#else
+#define preempt_count_add(val) __preempt_count_add(val)
+#define preempt_count_sub(val) __preempt_count_sub(val)
+#define preempt_count_dec_and_test() __preempt_count_dec_and_test()
+#endif
-#define preempt_check_resched_context() preempt_check_resched()
-
-#endif /* CONFIG_CONTEXT_TRACKING */
-
-#else /* !CONFIG_PREEMPT */
-
-#define preempt_check_resched() do { } while (0)
-#define preempt_check_resched_context() do { } while (0)
-
-#endif /* CONFIG_PREEMPT */
+#define __preempt_count_inc() __preempt_count_add(1)
+#define __preempt_count_dec() __preempt_count_sub(1)
+#define preempt_count_inc() preempt_count_add(1)
+#define preempt_count_dec() preempt_count_sub(1)
#ifdef CONFIG_PREEMPT_COUNT
#define preempt_disable() \
do { \
- inc_preempt_count(); \
+ preempt_count_inc(); \
barrier(); \
} while (0)
#define sched_preempt_enable_no_resched() \
do { \
barrier(); \
- dec_preempt_count(); \
+ preempt_count_dec(); \
} while (0)
-#define preempt_enable_no_resched() sched_preempt_enable_no_resched()
+#define preempt_enable_no_resched() sched_preempt_enable_no_resched()
+#ifdef CONFIG_PREEMPT
#define preempt_enable() \
do { \
- preempt_enable_no_resched(); \
barrier(); \
- preempt_check_resched(); \
+ if (unlikely(preempt_count_dec_and_test())) \
+ __preempt_schedule(); \
+} while (0)
+
+#define preempt_check_resched() \
+do { \
+ if (should_resched()) \
+ __preempt_schedule(); \
} while (0)
-/* For debugging and tracer internals only! */
-#define add_preempt_count_notrace(val) \
- do { preempt_count() += (val); } while (0)
-#define sub_preempt_count_notrace(val) \
- do { preempt_count() -= (val); } while (0)
-#define inc_preempt_count_notrace() add_preempt_count_notrace(1)
-#define dec_preempt_count_notrace() sub_preempt_count_notrace(1)
+#else
+#define preempt_enable() preempt_enable_no_resched()
+#define preempt_check_resched() do { } while (0)
+#endif
#define preempt_disable_notrace() \
do { \
- inc_preempt_count_notrace(); \
+ __preempt_count_inc(); \
barrier(); \
} while (0)
#define preempt_enable_no_resched_notrace() \
do { \
barrier(); \
- dec_preempt_count_notrace(); \
+ __preempt_count_dec(); \
} while (0)
-/* preempt_check_resched is OK to trace */
+#ifdef CONFIG_PREEMPT
+
+#ifndef CONFIG_CONTEXT_TRACKING
+#define __preempt_schedule_context() __preempt_schedule()
+#endif
+
#define preempt_enable_notrace() \
do { \
- preempt_enable_no_resched_notrace(); \
barrier(); \
- preempt_check_resched_context(); \
+ if (unlikely(__preempt_count_dec_and_test())) \
+ __preempt_schedule_context(); \
} while (0)
+#else
+#define preempt_enable_notrace() preempt_enable_no_resched_notrace()
+#endif
#else /* !CONFIG_PREEMPT_COUNT */
@@ -115,10 +104,11 @@ do { \
* that can cause faults and scheduling migrate into our preempt-protected
* region.
*/
-#define preempt_disable() barrier()
+#define preempt_disable() barrier()
#define sched_preempt_enable_no_resched() barrier()
-#define preempt_enable_no_resched() barrier()
-#define preempt_enable() barrier()
+#define preempt_enable_no_resched() barrier()
+#define preempt_enable() barrier()
+#define preempt_check_resched() do { } while (0)
#define preempt_disable_notrace() barrier()
#define preempt_enable_no_resched_notrace() barrier()
diff --git a/include/linux/random.h b/include/linux/random.h
index 3b9377d6b7a5..6312dd9ba449 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -17,6 +17,7 @@ extern void add_interrupt_randomness(int irq, int irq_flags);
extern void get_random_bytes(void *buf, int nbytes);
extern void get_random_bytes_arch(void *buf, int nbytes);
void generate_random_uuid(unsigned char uuid_out[16]);
+extern int random_int_secret_init(void);
#ifndef MODULE
extern const struct file_operations random_fops, urandom_fops;
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index 4106721c4e5e..45a0a9e81478 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -19,6 +19,21 @@
*/
/*
+ * INIT_LIST_HEAD_RCU - Initialize a list_head visible to RCU readers
+ * @list: list to be initialized
+ *
+ * You should instead use INIT_LIST_HEAD() for normal initialization and
+ * cleanup tasks, when readers have no access to the list being initialized.
+ * However, if the list being initialized is visible to readers, you
+ * need to keep the compiler from being too mischievous.
+ */
+static inline void INIT_LIST_HEAD_RCU(struct list_head *list)
+{
+ ACCESS_ONCE(list->next) = list;
+ ACCESS_ONCE(list->prev) = list;
+}
+
+/*
* return the ->next pointer of a list_head in an rcu safe
* way, we must not access it directly
*/
@@ -191,9 +206,13 @@ static inline void list_splice_init_rcu(struct list_head *list,
if (list_empty(list))
return;
- /* "first" and "last" tracking list, so initialize it. */
+ /*
+ * "first" and "last" tracking list, so initialize it. RCU readers
+ * have access to this list, so we must use INIT_LIST_HEAD_RCU()
+ * instead of INIT_LIST_HEAD().
+ */
- INIT_LIST_HEAD(list);
+ INIT_LIST_HEAD_RCU(list);
/*
* At this point, the list body still points to the source list.
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index f1f1bc39346b..69d8d7211de8 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -261,6 +261,10 @@ static inline void rcu_user_hooks_switch(struct task_struct *prev,
rcu_irq_exit(); \
} while (0)
+#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP)
+extern bool __rcu_is_watching(void);
+#endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) */
+
/*
* Infrastructure to implement the synchronize_() primitives in
* TREE_RCU and rcu_barrier_() primitives in TINY_RCU.
@@ -297,10 +301,6 @@ static inline void destroy_rcu_head_on_stack(struct rcu_head *head)
}
#endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
-#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_SMP)
-extern int rcu_is_cpu_idle(void);
-#endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_SMP) */
-
#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU)
bool rcu_lockdep_current_cpu_online(void);
#else /* #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU) */
@@ -351,7 +351,7 @@ static inline int rcu_read_lock_held(void)
{
if (!debug_lockdep_rcu_enabled())
return 1;
- if (rcu_is_cpu_idle())
+ if (!rcu_is_watching())
return 0;
if (!rcu_lockdep_current_cpu_online())
return 0;
@@ -402,7 +402,7 @@ static inline int rcu_read_lock_sched_held(void)
if (!debug_lockdep_rcu_enabled())
return 1;
- if (rcu_is_cpu_idle())
+ if (!rcu_is_watching())
return 0;
if (!rcu_lockdep_current_cpu_online())
return 0;
@@ -506,8 +506,17 @@ static inline void rcu_preempt_sleep_check(void)
#ifdef __CHECKER__
#define rcu_dereference_sparse(p, space) \
((void)(((typeof(*p) space *)p) == p))
+/* The dummy first argument in __rcu_assign_pointer_typecheck makes the
+ * typechecked pointer the second argument, matching rcu_assign_pointer itself;
+ * this avoids confusion about argument numbers in warning messages. */
+#define __rcu_assign_pointer_check_kernel(v) \
+ do { \
+ extern void __rcu_assign_pointer_typecheck(int, typeof(*(v)) __kernel *); \
+ __rcu_assign_pointer_typecheck(0, v); \
+ } while (0)
#else /* #ifdef __CHECKER__ */
#define rcu_dereference_sparse(p, space)
+#define __rcu_assign_pointer_check_kernel(v) do { } while (0)
#endif /* #else #ifdef __CHECKER__ */
#define __rcu_access_pointer(p, space) \
@@ -551,7 +560,8 @@ static inline void rcu_preempt_sleep_check(void)
#define __rcu_assign_pointer(p, v, space) \
do { \
smp_wmb(); \
- (p) = (typeof(*v) __force space *)(v); \
+ __rcu_assign_pointer_check_kernel(v); \
+ ACCESS_ONCE(p) = (typeof(*(v)) __force space *)(v); \
} while (0)
@@ -771,7 +781,7 @@ static inline void rcu_read_lock(void)
__rcu_read_lock();
__acquire(RCU);
rcu_lock_acquire(&rcu_lock_map);
- rcu_lockdep_assert(!rcu_is_cpu_idle(),
+ rcu_lockdep_assert(rcu_is_watching(),
"rcu_read_lock() used illegally while idle");
}
@@ -792,7 +802,7 @@ static inline void rcu_read_lock(void)
*/
static inline void rcu_read_unlock(void)
{
- rcu_lockdep_assert(!rcu_is_cpu_idle(),
+ rcu_lockdep_assert(rcu_is_watching(),
"rcu_read_unlock() used illegally while idle");
rcu_lock_release(&rcu_lock_map);
__release(RCU);
@@ -821,7 +831,7 @@ static inline void rcu_read_lock_bh(void)
local_bh_disable();
__acquire(RCU_BH);
rcu_lock_acquire(&rcu_bh_lock_map);
- rcu_lockdep_assert(!rcu_is_cpu_idle(),
+ rcu_lockdep_assert(rcu_is_watching(),
"rcu_read_lock_bh() used illegally while idle");
}
@@ -832,7 +842,7 @@ static inline void rcu_read_lock_bh(void)
*/
static inline void rcu_read_unlock_bh(void)
{
- rcu_lockdep_assert(!rcu_is_cpu_idle(),
+ rcu_lockdep_assert(rcu_is_watching(),
"rcu_read_unlock_bh() used illegally while idle");
rcu_lock_release(&rcu_bh_lock_map);
__release(RCU_BH);
@@ -857,7 +867,7 @@ static inline void rcu_read_lock_sched(void)
preempt_disable();
__acquire(RCU_SCHED);
rcu_lock_acquire(&rcu_sched_lock_map);
- rcu_lockdep_assert(!rcu_is_cpu_idle(),
+ rcu_lockdep_assert(rcu_is_watching(),
"rcu_read_lock_sched() used illegally while idle");
}
@@ -875,7 +885,7 @@ static inline notrace void rcu_read_lock_sched_notrace(void)
*/
static inline void rcu_read_unlock_sched(void)
{
- rcu_lockdep_assert(!rcu_is_cpu_idle(),
+ rcu_lockdep_assert(rcu_is_watching(),
"rcu_read_unlock_sched() used illegally while idle");
rcu_lock_release(&rcu_sched_lock_map);
__release(RCU_SCHED);
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h
index e31005ee339e..09ebcbe9fd78 100644
--- a/include/linux/rcutiny.h
+++ b/include/linux/rcutiny.h
@@ -132,4 +132,21 @@ static inline void rcu_scheduler_starting(void)
}
#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE)
+
+static inline bool rcu_is_watching(void)
+{
+ return __rcu_is_watching();
+}
+
+#else /* defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) */
+
+static inline bool rcu_is_watching(void)
+{
+ return true;
+}
+
+
+#endif /* #else defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) */
+
#endif /* __LINUX_RCUTINY_H */
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
index 226169d1bd2b..4b9c81548742 100644
--- a/include/linux/rcutree.h
+++ b/include/linux/rcutree.h
@@ -90,4 +90,6 @@ extern void exit_rcu(void);
extern void rcu_scheduler_starting(void);
extern int rcu_scheduler_active __read_mostly;
+extern bool rcu_is_watching(void);
+
#endif /* __LINUX_RCUTREE_H */
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index a10380bfbeac..24e993636db0 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -70,6 +70,8 @@ struct regmap_range {
unsigned int range_max;
};
+#define regmap_reg_range(low, high) { .range_min = low, .range_max = high, }
+
/*
* A table of ranges including some yes ranges and some no ranges.
* If a register belongs to a no_range, the corresponding check function
@@ -425,11 +427,15 @@ bool regmap_reg_in_ranges(unsigned int reg,
* @reg: Offset of the register within the regmap bank
* @lsb: lsb of the register field.
* @reg: msb of the register field.
+ * @id_size: port size if it has some ports
+ * @id_offset: address offset for each ports
*/
struct reg_field {
unsigned int reg;
unsigned int lsb;
unsigned int msb;
+ unsigned int id_size;
+ unsigned int id_offset;
};
#define REG_FIELD(_reg, _lsb, _msb) { \
@@ -448,6 +454,15 @@ void devm_regmap_field_free(struct device *dev, struct regmap_field *field);
int regmap_field_read(struct regmap_field *field, unsigned int *val);
int regmap_field_write(struct regmap_field *field, unsigned int val);
+int regmap_field_update_bits(struct regmap_field *field,
+ unsigned int mask, unsigned int val);
+
+int regmap_fields_write(struct regmap_field *field, unsigned int id,
+ unsigned int val);
+int regmap_fields_read(struct regmap_field *field, unsigned int id,
+ unsigned int *val);
+int regmap_fields_update_bits(struct regmap_field *field, unsigned int id,
+ unsigned int mask, unsigned int val);
/**
* Description of an IRQ for the generic regmap irq_chip.
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 67e13aa5a478..c8b492c6b6a8 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -40,6 +40,8 @@ enum regulator_status {
};
/**
+ * struct regulator_linear_range - specify linear voltage ranges
+ *
* Specify a range of voltages for regulator_map_linar_range() and
* regulator_list_linear_range().
*
@@ -207,6 +209,7 @@ enum regulator_type {
* @min_uV: Voltage given by the lowest selector (if linear mapping)
* @uV_step: Voltage increase with each selector (if linear mapping)
* @linear_min_sel: Minimal selector for starting linear mapping
+ * @fixed_uV: Fixed voltage of rails.
* @ramp_delay: Time to settle down after voltage change (unit: uV/us)
* @volt_table: Voltage mapping table (if table based mapping)
*
@@ -239,6 +242,7 @@ struct regulator_desc {
unsigned int min_uV;
unsigned int uV_step;
unsigned int linear_min_sel;
+ int fixed_uV;
unsigned int ramp_delay;
const struct regulator_linear_range *linear_ranges;
@@ -334,7 +338,12 @@ struct regulator_dev {
struct regulator_dev *
regulator_register(const struct regulator_desc *regulator_desc,
const struct regulator_config *config);
+struct regulator_dev *
+devm_regulator_register(struct device *dev,
+ const struct regulator_desc *regulator_desc,
+ const struct regulator_config *config);
void regulator_unregister(struct regulator_dev *rdev);
+void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev);
int regulator_notifier_call_chain(struct regulator_dev *rdev,
unsigned long event, void *data);
diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h
index 999b20ce06cf..730e638c5589 100644
--- a/include/linux/regulator/machine.h
+++ b/include/linux/regulator/machine.h
@@ -95,6 +95,7 @@ struct regulator_state {
* @initial_state: Suspend state to set by default.
* @initial_mode: Mode to set at startup.
* @ramp_delay: Time to settle down after voltage change (unit: uV/us)
+ * @enable_time: Turn-on time of the rails (unit: microseconds)
*/
struct regulation_constraints {
@@ -129,6 +130,7 @@ struct regulation_constraints {
unsigned int initial_mode;
unsigned int ramp_delay;
+ unsigned int enable_time;
/* constraint flags */
unsigned always_on:1; /* regulator never off when system is on */
@@ -193,15 +195,10 @@ int regulator_suspend_finish(void);
#ifdef CONFIG_REGULATOR
void regulator_has_full_constraints(void);
-void regulator_use_dummy_regulator(void);
#else
static inline void regulator_has_full_constraints(void)
{
}
-
-static inline void regulator_use_dummy_regulator(void)
-{
-}
#endif
#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 6682da36b293..b09798b672f3 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -22,6 +22,7 @@ struct sched_param {
#include <linux/errno.h>
#include <linux/nodemask.h>
#include <linux/mm_types.h>
+#include <linux/preempt.h>
#include <asm/page.h>
#include <asm/ptrace.h>
@@ -427,6 +428,14 @@ struct task_cputime {
.sum_exec_runtime = 0, \
}
+#define PREEMPT_ENABLED (PREEMPT_NEED_RESCHED)
+
+#ifdef CONFIG_PREEMPT_COUNT
+#define PREEMPT_DISABLED (1 + PREEMPT_ENABLED)
+#else
+#define PREEMPT_DISABLED PREEMPT_ENABLED
+#endif
+
/*
* Disable preemption until the scheduler is running.
* Reset by start_kernel()->sched_init()->init_idle().
@@ -434,7 +443,7 @@ struct task_cputime {
* We include PREEMPT_ACTIVE to avoid cond_resched() from working
* before the scheduler is active -- see should_resched().
*/
-#define INIT_PREEMPT_COUNT (1 + PREEMPT_ACTIVE)
+#define INIT_PREEMPT_COUNT (PREEMPT_DISABLED + PREEMPT_ACTIVE)
/**
* struct thread_group_cputimer - thread group interval timer counts
@@ -811,6 +820,10 @@ struct sched_domain {
u64 last_update;
+ /* idle_balance() stats */
+ u64 max_newidle_lb_cost;
+ unsigned long next_decay_max_lb_cost;
+
#ifdef CONFIG_SCHEDSTATS
/* load_balance() stats */
unsigned int lb_count[CPU_MAX_IDLE_TYPES];
@@ -2402,11 +2415,6 @@ static inline int signal_pending_state(long state, struct task_struct *p)
return (state & TASK_INTERRUPTIBLE) || __fatal_signal_pending(p);
}
-static inline int need_resched(void)
-{
- return unlikely(test_thread_flag(TIF_NEED_RESCHED));
-}
-
/*
* cond_resched() and cond_resched_lock(): latency reduction via
* explicit rescheduling in places that are safe. The return
@@ -2475,34 +2483,98 @@ static inline int tsk_is_polling(struct task_struct *p)
{
return task_thread_info(p)->status & TS_POLLING;
}
-static inline void current_set_polling(void)
+static inline void __current_set_polling(void)
{
current_thread_info()->status |= TS_POLLING;
}
-static inline void current_clr_polling(void)
+static inline bool __must_check current_set_polling_and_test(void)
+{
+ __current_set_polling();
+
+ /*
+ * Polling state must be visible before we test NEED_RESCHED,
+ * paired by resched_task()
+ */
+ smp_mb();
+
+ return unlikely(tif_need_resched());
+}
+
+static inline void __current_clr_polling(void)
{
current_thread_info()->status &= ~TS_POLLING;
- smp_mb__after_clear_bit();
+}
+
+static inline bool __must_check current_clr_polling_and_test(void)
+{
+ __current_clr_polling();
+
+ /*
+ * Polling state must be visible before we test NEED_RESCHED,
+ * paired by resched_task()
+ */
+ smp_mb();
+
+ return unlikely(tif_need_resched());
}
#elif defined(TIF_POLLING_NRFLAG)
static inline int tsk_is_polling(struct task_struct *p)
{
return test_tsk_thread_flag(p, TIF_POLLING_NRFLAG);
}
-static inline void current_set_polling(void)
+
+static inline void __current_set_polling(void)
{
set_thread_flag(TIF_POLLING_NRFLAG);
}
-static inline void current_clr_polling(void)
+static inline bool __must_check current_set_polling_and_test(void)
+{
+ __current_set_polling();
+
+ /*
+ * Polling state must be visible before we test NEED_RESCHED,
+ * paired by resched_task()
+ *
+ * XXX: assumes set/clear bit are identical barrier wise.
+ */
+ smp_mb__after_clear_bit();
+
+ return unlikely(tif_need_resched());
+}
+
+static inline void __current_clr_polling(void)
{
clear_thread_flag(TIF_POLLING_NRFLAG);
}
+
+static inline bool __must_check current_clr_polling_and_test(void)
+{
+ __current_clr_polling();
+
+ /*
+ * Polling state must be visible before we test NEED_RESCHED,
+ * paired by resched_task()
+ */
+ smp_mb__after_clear_bit();
+
+ return unlikely(tif_need_resched());
+}
+
#else
static inline int tsk_is_polling(struct task_struct *p) { return 0; }
-static inline void current_set_polling(void) { }
-static inline void current_clr_polling(void) { }
+static inline void __current_set_polling(void) { }
+static inline void __current_clr_polling(void) { }
+
+static inline bool __must_check current_set_polling_and_test(void)
+{
+ return unlikely(tif_need_resched());
+}
+static inline bool __must_check current_clr_polling_and_test(void)
+{
+ return unlikely(tif_need_resched());
+}
#endif
/*
diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h
index bf8086b2506e..9552afa733d8 100644
--- a/include/linux/sched/sysctl.h
+++ b/include/linux/sched/sysctl.h
@@ -2,8 +2,8 @@
#define _SCHED_SYSCTL_H
#ifdef CONFIG_DETECT_HUNG_TASK
+extern int sysctl_hung_task_check_count;
extern unsigned int sysctl_hung_task_panic;
-extern unsigned long sysctl_hung_task_check_count;
extern unsigned long sysctl_hung_task_timeout_secs;
extern unsigned long sysctl_hung_task_warnings;
extern int proc_dohung_task_timeout_secs(struct ctl_table *table, int write,
diff --git a/include/linux/sched_clock.h b/include/linux/sched_clock.h
index fa7922c80a41..eca7abeb86fc 100644
--- a/include/linux/sched_clock.h
+++ b/include/linux/sched_clock.h
@@ -15,6 +15,8 @@ static inline void sched_clock_postinit(void) { }
#endif
extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate);
+extern void sched_clock_register(u64 (*read)(void), int bits,
+ unsigned long rate);
extern unsigned long long (*sched_clock_func)(void);
diff --git a/include/linux/security.h b/include/linux/security.h
index 9d37e2b9d3ec..5623a7f965b7 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1052,17 +1052,25 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* @xfrm_policy_delete_security:
* @ctx contains the xfrm_sec_ctx.
* Authorize deletion of xp->security.
- * @xfrm_state_alloc_security:
+ * @xfrm_state_alloc:
* @x contains the xfrm_state being added to the Security Association
* Database by the XFRM system.
* @sec_ctx contains the security context information being provided by
* the user-level SA generation program (e.g., setkey or racoon).
- * @secid contains the secid from which to take the mls portion of the context.
* Allocate a security structure to the x->security field; the security
* field is initialized to NULL when the xfrm_state is allocated. Set the
- * context to correspond to either sec_ctx or polsec, with the mls portion
- * taken from secid in the latter case.
- * Return 0 if operation was successful (memory to allocate, legal context).
+ * context to correspond to sec_ctx. Return 0 if operation was successful
+ * (memory to allocate, legal context).
+ * @xfrm_state_alloc_acquire:
+ * @x contains the xfrm_state being added to the Security Association
+ * Database by the XFRM system.
+ * @polsec contains the policy's security context.
+ * @secid contains the secid from which to take the mls portion of the
+ * context.
+ * Allocate a security structure to the x->security field; the security
+ * field is initialized to NULL when the xfrm_state is allocated. Set the
+ * context to correspond to secid. Return 0 if operation was successful
+ * (memory to allocate, legal context).
* @xfrm_state_free_security:
* @x contains the xfrm_state.
* Deallocate x->security.
@@ -1679,9 +1687,11 @@ struct security_operations {
int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx);
void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx);
int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx);
- int (*xfrm_state_alloc_security) (struct xfrm_state *x,
- struct xfrm_user_sec_ctx *sec_ctx,
- u32 secid);
+ int (*xfrm_state_alloc) (struct xfrm_state *x,
+ struct xfrm_user_sec_ctx *sec_ctx);
+ int (*xfrm_state_alloc_acquire) (struct xfrm_state *x,
+ struct xfrm_sec_ctx *polsec,
+ u32 secid);
void (*xfrm_state_free_security) (struct xfrm_state *x);
int (*xfrm_state_delete_security) (struct xfrm_state *x);
int (*xfrm_policy_lookup) (struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h
index d34049712a4d..3dbdf7e53dcc 100644
--- a/include/linux/serial_sci.h
+++ b/include/linux/serial_sci.h
@@ -5,18 +5,22 @@
#include <linux/sh_dma.h>
/*
- * Generic header for SuperH (H)SCI(F) (used by sh/sh64/h8300 and related parts)
+ * Generic header for SuperH (H)SCI(F) (used by sh/sh64 and related parts)
*/
#define SCIx_NOT_SUPPORTED (-1)
enum {
+ SCBRR_ALGO_INVALID,
+
SCBRR_ALGO_1, /* ((clk + 16 * bps) / (16 * bps) - 1) */
SCBRR_ALGO_2, /* ((clk + 16 * bps) / (32 * bps) - 1) */
SCBRR_ALGO_3, /* (((clk * 2) + 16 * bps) / (16 * bps) - 1) */
SCBRR_ALGO_4, /* (((clk * 2) + 16 * bps) / (32 * bps) - 1) */
SCBRR_ALGO_5, /* (((clk * 1000 / 32) / bps) - 1) */
SCBRR_ALGO_6, /* HSCIF variable sample rate algorithm */
+
+ SCBRR_NR_ALGOS,
};
#define SCSCR_TIE (1 << 7)
diff --git a/include/linux/spi/rspi.h b/include/linux/spi/rspi.h
index 900f0e328235..a25bd6f65e7f 100644
--- a/include/linux/spi/rspi.h
+++ b/include/linux/spi/rspi.h
@@ -26,6 +26,8 @@ struct rspi_plat_data {
unsigned int dma_rx_id;
unsigned dma_width_16bit:1; /* DMAC read/write width = 16-bit */
+
+ u16 num_chipselect;
};
#endif
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 887116dbce2c..4d634d66ba0b 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -434,6 +434,8 @@ extern struct spi_master *
spi_alloc_master(struct device *host, unsigned size);
extern int spi_register_master(struct spi_master *master);
+extern int devm_spi_register_master(struct device *dev,
+ struct spi_master *master);
extern void spi_unregister_master(struct spi_master *master);
extern struct spi_master *spi_busnum_to_master(u16 busnum);
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 11baec7c9b26..6695040a0317 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -173,7 +173,6 @@ struct bin_attribute bin_attr_##_name = __BIN_ATTR_RW(_name, _size)
struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *, char *);
ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
- const void *(*namespace)(struct kobject *, const struct attribute *);
};
struct sysfs_dirent;
@@ -183,19 +182,23 @@ struct sysfs_dirent;
int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
void *data, struct module *owner);
-int __must_check sysfs_create_dir(struct kobject *kobj);
+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(struct kobject *kobj, const char *new_name);
-int __must_check sysfs_move_dir(struct kobject *kobj,
- struct kobject *new_parent_kobj);
-
-int __must_check sysfs_create_file(struct kobject *kobj,
- const struct attribute *attr);
+int __must_check sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
+ const void *new_ns);
+int __must_check sysfs_move_dir_ns(struct kobject *kobj,
+ struct kobject *new_parent_kobj,
+ const void *new_ns);
+
+int __must_check sysfs_create_file_ns(struct kobject *kobj,
+ const struct attribute *attr,
+ const void *ns);
int __must_check sysfs_create_files(struct kobject *kobj,
const struct attribute **attr);
int __must_check sysfs_chmod_file(struct kobject *kobj,
const struct attribute *attr, umode_t mode);
-void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr);
+void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr,
+ const void *ns);
void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr);
int __must_check sysfs_create_bin_file(struct kobject *kobj,
@@ -210,8 +213,9 @@ int __must_check sysfs_create_link_nowarn(struct kobject *kobj,
const char *name);
void sysfs_remove_link(struct kobject *kobj, const char *name);
-int sysfs_rename_link(struct kobject *kobj, struct kobject *target,
- const char *old_name, const char *new_name);
+int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *target,
+ const char *old_name, const char *new_name,
+ const void *new_ns);
void sysfs_delete_link(struct kobject *dir, struct kobject *targ,
const char *name);
@@ -241,9 +245,9 @@ void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name,
void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr);
void sysfs_notify_dirent(struct sysfs_dirent *sd);
-struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
- const void *ns,
- const unsigned char *name);
+struct sysfs_dirent *sysfs_get_dirent_ns(struct sysfs_dirent *parent_sd,
+ const unsigned char *name,
+ const void *ns);
struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd);
void sysfs_put(struct sysfs_dirent *sd);
@@ -257,7 +261,7 @@ static inline int sysfs_schedule_callback(struct kobject *kobj,
return -ENOSYS;
}
-static inline int sysfs_create_dir(struct kobject *kobj)
+static inline int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
{
return 0;
}
@@ -266,19 +270,22 @@ static inline void sysfs_remove_dir(struct kobject *kobj)
{
}
-static inline int sysfs_rename_dir(struct kobject *kobj, const char *new_name)
+static inline int sysfs_rename_dir_ns(struct kobject *kobj,
+ const char *new_name, const void *new_ns)
{
return 0;
}
-static inline int sysfs_move_dir(struct kobject *kobj,
- struct kobject *new_parent_kobj)
+static inline int sysfs_move_dir_ns(struct kobject *kobj,
+ struct kobject *new_parent_kobj,
+ const void *new_ns)
{
return 0;
}
-static inline int sysfs_create_file(struct kobject *kobj,
- const struct attribute *attr)
+static inline int sysfs_create_file_ns(struct kobject *kobj,
+ const struct attribute *attr,
+ const void *ns)
{
return 0;
}
@@ -295,8 +302,9 @@ static inline int sysfs_chmod_file(struct kobject *kobj,
return 0;
}
-static inline void sysfs_remove_file(struct kobject *kobj,
- const struct attribute *attr)
+static inline void sysfs_remove_file_ns(struct kobject *kobj,
+ const struct attribute *attr,
+ const void *ns)
{
}
@@ -333,8 +341,9 @@ static inline void sysfs_remove_link(struct kobject *kobj, const char *name)
{
}
-static inline int sysfs_rename_link(struct kobject *k, struct kobject *t,
- const char *old_name, const char *new_name)
+static inline int sysfs_rename_link_ns(struct kobject *k, struct kobject *t,
+ const char *old_name,
+ const char *new_name, const void *ns)
{
return 0;
}
@@ -413,10 +422,9 @@ static inline void sysfs_notify(struct kobject *kobj, const char *dir,
static inline void sysfs_notify_dirent(struct sysfs_dirent *sd)
{
}
-static inline
-struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
- const void *ns,
- const unsigned char *name)
+static inline struct sysfs_dirent *
+sysfs_get_dirent_ns(struct sysfs_dirent *parent_sd, const unsigned char *name,
+ const void *ns)
{
return NULL;
}
@@ -435,4 +443,28 @@ static inline int __must_check sysfs_init(void)
#endif /* CONFIG_SYSFS */
+static inline int __must_check sysfs_create_file(struct kobject *kobj,
+ const struct attribute *attr)
+{
+ return sysfs_create_file_ns(kobj, attr, NULL);
+}
+
+static inline void sysfs_remove_file(struct kobject *kobj,
+ const struct attribute *attr)
+{
+ return sysfs_remove_file_ns(kobj, attr, NULL);
+}
+
+static inline int sysfs_rename_link(struct kobject *kobj, struct kobject *target,
+ const char *old_name, const char *new_name)
+{
+ return sysfs_rename_link_ns(kobj, target, old_name, new_name, NULL);
+}
+
+static inline struct sysfs_dirent *
+sysfs_get_dirent(struct sysfs_dirent *parent_sd, const unsigned char *name)
+{
+ return sysfs_get_dirent_ns(parent_sd, name, NULL);
+}
+
#endif /* _SYSFS_H_ */
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index e7e04736802f..fddbe2023a5d 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -104,8 +104,21 @@ static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
#define test_thread_flag(flag) \
test_ti_thread_flag(current_thread_info(), flag)
-#define set_need_resched() set_thread_flag(TIF_NEED_RESCHED)
-#define clear_need_resched() clear_thread_flag(TIF_NEED_RESCHED)
+static inline __deprecated void set_need_resched(void)
+{
+ /*
+ * Use of this function in deprecated.
+ *
+ * As of this writing there are only a few users in the DRM tree left
+ * all of which are wrong and can be removed without causing too much
+ * grief.
+ *
+ * The DRM people are aware and are working on removing the last few
+ * instances.
+ */
+}
+
+#define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED)
#if defined TIF_RESTORE_SIGMASK && !defined HAVE_SET_RESTORE_SIGMASK
/*
diff --git a/include/linux/timex.h b/include/linux/timex.h
index dd3edd7dfc94..9d3f1a5b6178 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -64,6 +64,20 @@
#include <asm/timex.h>
+#ifndef random_get_entropy
+/*
+ * The random_get_entropy() function is used by the /dev/random driver
+ * in order to extract entropy via the relative unpredictability of
+ * when an interrupt takes places versus a high speed, fine-grained
+ * timing source or cycle counter. Since it will be occurred on every
+ * single interrupt, it must have a very low cost/overhead.
+ *
+ * By default we use get_cycles() for this purpose, but individual
+ * architectures may override this in their asm/timex.h header file.
+ */
+#define random_get_entropy() get_cycles()
+#endif
+
/*
* SHIFT_PLL is used as a dampening factor to define how much we
* adjust the frequency correction for a given offset in PLL mode.
diff --git a/include/linux/topology.h b/include/linux/topology.h
index d3cf0d6e7712..12ae6ce997d6 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -106,6 +106,8 @@ int arch_update_cpu_topology(void);
.last_balance = jiffies, \
.balance_interval = 1, \
.smt_gain = 1178, /* 15% */ \
+ .max_newidle_lb_cost = 0, \
+ .next_decay_max_lb_cost = jiffies, \
}
#endif
#endif /* CONFIG_SCHED_SMT */
@@ -135,6 +137,8 @@ int arch_update_cpu_topology(void);
, \
.last_balance = jiffies, \
.balance_interval = 1, \
+ .max_newidle_lb_cost = 0, \
+ .next_decay_max_lb_cost = jiffies, \
}
#endif
#endif /* CONFIG_SCHED_MC */
@@ -166,6 +170,8 @@ int arch_update_cpu_topology(void);
, \
.last_balance = jiffies, \
.balance_interval = 1, \
+ .max_newidle_lb_cost = 0, \
+ .next_decay_max_lb_cost = jiffies, \
}
#endif
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 64f864651d86..2f47989d8288 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -180,7 +180,6 @@ struct tty_port_operations {
IFF the port was initialized. Do not use to free resources. Called
under the port mutex to serialize against activate/shutdowns */
void (*shutdown)(struct tty_port *port);
- void (*drop)(struct tty_port *port);
/* Called under the port mutex from tty_port_open, serialized using
the port mutex */
/* FIXME: long term getting the tty argument *out* of this would be
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 5ca0951e1855..9d8cf056e661 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -15,7 +15,7 @@
*/
static inline void pagefault_disable(void)
{
- inc_preempt_count();
+ preempt_count_inc();
/*
* make sure to have issued the store before a pagefault
* can hit.
@@ -30,11 +30,7 @@ static inline void pagefault_enable(void)
* the pagefault handler again.
*/
barrier();
- dec_preempt_count();
- /*
- * make sure we do..
- */
- barrier();
+ preempt_count_dec();
preempt_check_resched();
}
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 001629cd1a97..f726c39097e0 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -702,7 +702,7 @@ extern int usb_alloc_streams(struct usb_interface *interface,
unsigned int num_streams, gfp_t mem_flags);
/* Reverts a group of bulk endpoints back to not using stream IDs. */
-extern void usb_free_streams(struct usb_interface *interface,
+extern int usb_free_streams(struct usb_interface *interface,
struct usb_host_endpoint **eps, unsigned int num_eps,
gfp_t mem_flags);
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 75efc45eaa2f..fc64b6825f5e 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -73,6 +73,7 @@ struct giveback_urb_bh {
spinlock_t lock;
struct list_head head;
struct tasklet_struct bh;
+ struct usb_host_endpoint *completing_ep;
};
struct usb_hcd {
@@ -140,6 +141,7 @@ struct usb_hcd {
unsigned wireless:1; /* Wireless USB HCD */
unsigned authorized_default:1;
unsigned has_tt:1; /* Integrated TT in root hub */
+ unsigned amd_resume_bug:1; /* AMD remote wakeup quirk */
unsigned int irq; /* irq allocated */
void __iomem *regs; /* device memory/io */
@@ -378,6 +380,12 @@ static inline int hcd_giveback_urb_in_bh(struct usb_hcd *hcd)
return hcd->driver->flags & HCD_BH;
}
+static inline bool hcd_periodic_completion_in_progress(struct usb_hcd *hcd,
+ struct usb_host_endpoint *ep)
+{
+ return hcd->high_prio_bh.completing_ep == ep;
+}
+
extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
int status);
@@ -428,6 +436,8 @@ extern int usb_hcd_pci_probe(struct pci_dev *dev,
extern void usb_hcd_pci_remove(struct pci_dev *dev);
extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
+extern int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev);
+
#ifdef CONFIG_PM
extern const struct dev_pm_ops usb_hcd_pci_pm_ops;
#endif
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 6781258d0b67..bd8218b15009 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -391,7 +391,7 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
loff_t *ppos, int nonblock);
-size_t vb2_write(struct vb2_queue *q, char __user *data, size_t count,
+size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
loff_t *ppos, int nonblock);
/**
@@ -491,7 +491,7 @@ int vb2_ioctl_expbuf(struct file *file, void *priv,
int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma);
int vb2_fop_release(struct file *file);
-ssize_t vb2_fop_write(struct file *file, char __user *buf,
+ssize_t vb2_fop_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos);
ssize_t vb2_fop_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos);
diff --git a/include/media/videobuf2-dma-sg.h b/include/media/videobuf2-dma-sg.h
index 0038526b8ef7..7b89852779af 100644
--- a/include/media/videobuf2-dma-sg.h
+++ b/include/media/videobuf2-dma-sg.h
@@ -15,16 +15,10 @@
#include <media/videobuf2-core.h>
-struct vb2_dma_sg_desc {
- unsigned long size;
- unsigned int num_pages;
- struct scatterlist *sglist;
-};
-
-static inline struct vb2_dma_sg_desc *vb2_dma_sg_plane_desc(
+static inline struct sg_table *vb2_dma_sg_plane_desc(
struct vb2_buffer *vb, unsigned int plane_no)
{
- return (struct vb2_dma_sg_desc *)vb2_plane_cookie(vb, plane_no);
+ return (struct sg_table *)vb2_plane_cookie(vb, plane_no);
}
extern const struct vb2_mem_ops vb2_dma_sg_memops;
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 10d43d8c7037..f5ad918ace14 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -249,6 +249,7 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
uint bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait);
int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo);
+int bt_sock_wait_ready(struct sock *sk, unsigned long flags);
void bt_accept_enqueue(struct sock *parent, struct sock *sk);
void bt_accept_unlink(struct sock *sk);
@@ -331,16 +332,16 @@ out:
int bt_to_errno(__u16 code);
-extern int hci_sock_init(void);
-extern void hci_sock_cleanup(void);
+int hci_sock_init(void);
+void hci_sock_cleanup(void);
-extern int bt_sysfs_init(void);
-extern void bt_sysfs_cleanup(void);
+int bt_sysfs_init(void);
+void bt_sysfs_cleanup(void);
-extern int bt_procfs_init(struct net *net, const char *name,
- struct bt_sock_list* sk_list,
- int (* seq_show)(struct seq_file *, void *));
-extern void bt_procfs_cleanup(struct net *net, const char *name);
+int bt_procfs_init(struct net *net, const char *name,
+ struct bt_sock_list *sk_list,
+ int (*seq_show)(struct seq_file *, void *));
+void bt_procfs_cleanup(struct net *net, const char *name);
extern struct dentry *bt_debugfs;
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index aaeaf0938ec0..7ede2666dc75 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -104,11 +104,13 @@ enum {
enum {
HCI_SETUP,
HCI_AUTO_OFF,
+ HCI_RFKILLED,
HCI_MGMT,
HCI_PAIRABLE,
HCI_SERVICE_CACHE,
HCI_DEBUG_KEYS,
HCI_UNREGISTER,
+ HCI_USER_CHANNEL,
HCI_LE_SCAN,
HCI_SSP_ENABLED,
@@ -693,9 +695,6 @@ struct hci_cp_sniff_subrate {
} __packed;
#define HCI_OP_SET_EVENT_MASK 0x0c01
-struct hci_cp_set_event_mask {
- __u8 mask[8];
-} __packed;
#define HCI_OP_RESET 0x0c03
@@ -825,6 +824,8 @@ struct hci_rp_read_inq_rsp_tx_power {
__s8 tx_power;
} __packed;
+#define HCI_OP_SET_EVENT_MASK_PAGE_2 0x0c63
+
#define HCI_OP_READ_FLOW_CONTROL_MODE 0x0c66
struct hci_rp_read_flow_control_mode {
__u8 status;
@@ -837,6 +838,8 @@ struct hci_cp_write_le_host_supported {
__u8 simul;
} __packed;
+#define HCI_OP_READ_SYNC_TRAIN_PARAMS 0x0c77
+
#define HCI_OP_READ_LOCAL_VERSION 0x1001
struct hci_rp_read_local_version {
__u8 status;
@@ -1570,6 +1573,7 @@ struct sockaddr_hci {
#define HCI_DEV_NONE 0xffff
#define HCI_CHANNEL_RAW 0
+#define HCI_CHANNEL_USER 1
#define HCI_CHANNEL_MONITOR 2
#define HCI_CHANNEL_CONTROL 3
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 3ede820d328f..6d056395538f 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -367,18 +367,17 @@ extern rwlock_t hci_dev_list_lock;
extern rwlock_t hci_cb_list_lock;
/* ----- HCI interface to upper protocols ----- */
-extern int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
-extern void l2cap_connect_cfm(struct hci_conn *hcon, u8 status);
-extern int l2cap_disconn_ind(struct hci_conn *hcon);
-extern void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason);
-extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
-extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb,
- u16 flags);
-
-extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags);
-extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status);
-extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
-extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
+int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
+void l2cap_connect_cfm(struct hci_conn *hcon, u8 status);
+int l2cap_disconn_ind(struct hci_conn *hcon);
+void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason);
+int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
+int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags);
+
+int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags);
+void sco_connect_cfm(struct hci_conn *hcon, __u8 status);
+void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
+int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
/* ----- Inquiry cache ----- */
#define INQUIRY_CACHE_AGE_MAX (HZ*30) /* 30 seconds */
@@ -1168,7 +1167,6 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
u8 *randomizer, u8 status);
-int mgmt_le_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
u8 ssp, u8 *eir, u16 eir_len);
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 9944c3e68c5d..421d7633a91f 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -93,6 +93,7 @@ struct mgmt_rp_read_index_list {
#define MGMT_SETTING_BREDR 0x00000080
#define MGMT_SETTING_HS 0x00000100
#define MGMT_SETTING_LE 0x00000200
+#define MGMT_SETTING_ADVERTISING 0x00000400
#define MGMT_OP_READ_INFO 0x0004
#define MGMT_READ_INFO_SIZE 0
@@ -351,6 +352,8 @@ struct mgmt_cp_set_device_id {
} __packed;
#define MGMT_SET_DEVICE_ID_SIZE 8
+#define MGMT_OP_SET_ADVERTISING 0x0029
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 7afd4199d6b6..b7f43e76a5c5 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -256,8 +256,8 @@ static inline void rfcomm_dlc_put(struct rfcomm_dlc *d)
rfcomm_dlc_free(d);
}
-extern void __rfcomm_dlc_throttle(struct rfcomm_dlc *d);
-extern void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d);
+void __rfcomm_dlc_throttle(struct rfcomm_dlc *d);
+void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d);
static inline void rfcomm_dlc_throttle(struct rfcomm_dlc *d)
{
diff --git a/include/net/caif/caif_hsi.h b/include/net/caif/caif_hsi.h
index 4795e817afe5..097f69cfaa75 100644
--- a/include/net/caif/caif_hsi.h
+++ b/include/net/caif/caif_hsi.h
@@ -195,6 +195,6 @@ enum ifla_caif_hsi {
__IFLA_CAIF_HSI_MAX
};
-extern struct cfhsi_ops *cfhsi_get_ops(void);
+struct cfhsi_ops *cfhsi_get_ops(void);
#endif /* CAIF_HSI_H_ */
diff --git a/include/net/compat.h b/include/net/compat.h
index 6e9565324989..3b603b199c01 100644
--- a/include/net/compat.h
+++ b/include/net/compat.h
@@ -29,8 +29,8 @@ struct compat_cmsghdr {
compat_int_t cmsg_type;
};
-extern int compat_sock_get_timestamp(struct sock *, struct timeval __user *);
-extern int compat_sock_get_timestampns(struct sock *, struct timespec __user *);
+int compat_sock_get_timestamp(struct sock *, struct timeval __user *);
+int compat_sock_get_timestampns(struct sock *, struct timespec __user *);
#else /* defined(CONFIG_COMPAT) */
/*
@@ -40,24 +40,30 @@ extern int compat_sock_get_timestampns(struct sock *, struct timespec __user *);
#define compat_mmsghdr mmsghdr
#endif /* defined(CONFIG_COMPAT) */
-extern int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *);
-extern int verify_compat_iovec(struct msghdr *, struct iovec *, struct sockaddr_storage *, int);
-extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr __user *,unsigned int);
-extern asmlinkage long compat_sys_sendmmsg(int, struct compat_mmsghdr __user *,
- unsigned int, unsigned int);
-extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned int);
-extern asmlinkage long compat_sys_recvmmsg(int, struct compat_mmsghdr __user *,
- unsigned int, unsigned int,
- struct compat_timespec __user *);
-extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *);
-extern int put_cmsg_compat(struct msghdr*, int, int, int, void *);
-
-extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *, unsigned char *, int);
-
-extern int compat_mc_setsockopt(struct sock *, int, int, char __user *, unsigned int,
- int (*)(struct sock *, int, int, char __user *, unsigned int));
-extern int compat_mc_getsockopt(struct sock *, int, int, char __user *,
- int __user *, int (*)(struct sock *, int, int, char __user *,
- int __user *));
+int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *);
+int verify_compat_iovec(struct msghdr *, struct iovec *,
+ struct sockaddr_storage *, int);
+asmlinkage long compat_sys_sendmsg(int, struct compat_msghdr __user *,
+ unsigned int);
+asmlinkage long compat_sys_sendmmsg(int, struct compat_mmsghdr __user *,
+ unsigned int, unsigned int);
+asmlinkage long compat_sys_recvmsg(int, struct compat_msghdr __user *,
+ unsigned int);
+asmlinkage long compat_sys_recvmmsg(int, struct compat_mmsghdr __user *,
+ unsigned int, unsigned int,
+ struct compat_timespec __user *);
+asmlinkage long compat_sys_getsockopt(int, int, int, char __user *,
+ int __user *);
+int put_cmsg_compat(struct msghdr*, int, int, int, void *);
+
+int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *,
+ unsigned char *, int);
+
+int compat_mc_setsockopt(struct sock *, int, int, char __user *, unsigned int,
+ int (*)(struct sock *, int, int, char __user *,
+ unsigned int));
+int compat_mc_getsockopt(struct sock *, int, int, char __user *, int __user *,
+ int (*)(struct sock *, int, int, char __user *,
+ int __user *));
#endif /* NET_COMPAT_H */
diff --git a/include/net/dcbevent.h b/include/net/dcbevent.h
index 443626ed4cbc..d2f3041c0dfa 100644
--- a/include/net/dcbevent.h
+++ b/include/net/dcbevent.h
@@ -25,9 +25,9 @@ enum dcbevent_notif_type {
};
#ifdef CONFIG_DCB
-extern int register_dcbevent_notifier(struct notifier_block *nb);
-extern int unregister_dcbevent_notifier(struct notifier_block *nb);
-extern int call_dcbevent_notifiers(unsigned long val, void *v);
+int register_dcbevent_notifier(struct notifier_block *nb);
+int unregister_dcbevent_notifier(struct notifier_block *nb);
+int call_dcbevent_notifiers(unsigned long val, void *v);
#else
static inline int
register_dcbevent_notifier(struct notifier_block *nb)
diff --git a/include/net/dn.h b/include/net/dn.h
index c88bf4ebd330..ccc15588d108 100644
--- a/include/net/dn.h
+++ b/include/net/dn.h
@@ -199,24 +199,26 @@ static inline void dn_sk_ports_copy(struct flowidn *fld, struct dn_scp *scp)
fld->fld_dport = scp->addrrem;
}
-extern unsigned int dn_mss_from_pmtu(struct net_device *dev, int mtu);
+unsigned int dn_mss_from_pmtu(struct net_device *dev, int mtu);
#define DN_MENUVER_ACC 0x01
#define DN_MENUVER_USR 0x02
#define DN_MENUVER_PRX 0x04
#define DN_MENUVER_UIC 0x08
-extern struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr);
-extern struct sock *dn_find_by_skb(struct sk_buff *skb);
+struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr);
+struct sock *dn_find_by_skb(struct sk_buff *skb);
#define DN_ASCBUF_LEN 9
-extern char *dn_addr2asc(__u16, char *);
-extern int dn_destroy_timer(struct sock *sk);
+char *dn_addr2asc(__u16, char *);
+int dn_destroy_timer(struct sock *sk);
-extern int dn_sockaddr2username(struct sockaddr_dn *addr, unsigned char *buf, unsigned char type);
-extern int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn *addr, unsigned char *type);
+int dn_sockaddr2username(struct sockaddr_dn *addr, unsigned char *buf,
+ unsigned char type);
+int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn *addr,
+ unsigned char *type);
-extern void dn_start_slow_timer(struct sock *sk);
-extern void dn_stop_slow_timer(struct sock *sk);
+void dn_start_slow_timer(struct sock *sk);
+void dn_stop_slow_timer(struct sock *sk);
extern __le16 decnet_address;
extern int decnet_debug_level;
diff --git a/include/net/dn_dev.h b/include/net/dn_dev.h
index b9e32db03f20..20b5ab06032d 100644
--- a/include/net/dn_dev.h
+++ b/include/net/dn_dev.h
@@ -148,27 +148,27 @@ struct rtnode_hello_message {
} __packed;
-extern void dn_dev_init(void);
-extern void dn_dev_cleanup(void);
+void dn_dev_init(void);
+void dn_dev_cleanup(void);
-extern int dn_dev_ioctl(unsigned int cmd, void __user *arg);
+int dn_dev_ioctl(unsigned int cmd, void __user *arg);
-extern void dn_dev_devices_off(void);
-extern void dn_dev_devices_on(void);
+void dn_dev_devices_off(void);
+void dn_dev_devices_on(void);
-extern void dn_dev_init_pkt(struct sk_buff *skb);
-extern void dn_dev_veri_pkt(struct sk_buff *skb);
-extern void dn_dev_hello(struct sk_buff *skb);
+void dn_dev_init_pkt(struct sk_buff *skb);
+void dn_dev_veri_pkt(struct sk_buff *skb);
+void dn_dev_hello(struct sk_buff *skb);
-extern void dn_dev_up(struct net_device *);
-extern void dn_dev_down(struct net_device *);
+void dn_dev_up(struct net_device *);
+void dn_dev_down(struct net_device *);
-extern int dn_dev_set_default(struct net_device *dev, int force);
-extern struct net_device *dn_dev_get_default(void);
-extern int dn_dev_bind_default(__le16 *addr);
+int dn_dev_set_default(struct net_device *dev, int force);
+struct net_device *dn_dev_get_default(void);
+int dn_dev_bind_default(__le16 *addr);
-extern int register_dnaddr_notifier(struct notifier_block *nb);
-extern int unregister_dnaddr_notifier(struct notifier_block *nb);
+int register_dnaddr_notifier(struct notifier_block *nb);
+int unregister_dnaddr_notifier(struct notifier_block *nb);
static inline int dn_dev_islocal(struct net_device *dev, __le16 addr)
{
diff --git a/include/net/dn_fib.h b/include/net/dn_fib.h
index 74004af31c48..f2ca135ddcc9 100644
--- a/include/net/dn_fib.h
+++ b/include/net/dn_fib.h
@@ -95,41 +95,38 @@ struct dn_fib_table {
/*
* dn_fib.c
*/
-extern void dn_fib_init(void);
-extern void dn_fib_cleanup(void);
-
-extern int dn_fib_ioctl(struct socket *sock, unsigned int cmd,
- unsigned long arg);
-extern struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r,
- struct nlattr *attrs[],
- const struct nlmsghdr *nlh, int *errp);
-extern int dn_fib_semantic_match(int type, struct dn_fib_info *fi,
- const struct flowidn *fld,
- struct dn_fib_res *res);
-extern void dn_fib_release_info(struct dn_fib_info *fi);
-extern void dn_fib_flush(void);
-extern void dn_fib_select_multipath(const struct flowidn *fld,
- struct dn_fib_res *res);
+void dn_fib_init(void);
+void dn_fib_cleanup(void);
+
+int dn_fib_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
+struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r,
+ struct nlattr *attrs[],
+ const struct nlmsghdr *nlh, int *errp);
+int dn_fib_semantic_match(int type, struct dn_fib_info *fi,
+ const struct flowidn *fld, struct dn_fib_res *res);
+void dn_fib_release_info(struct dn_fib_info *fi);
+void dn_fib_flush(void);
+void dn_fib_select_multipath(const struct flowidn *fld, struct dn_fib_res *res);
/*
* dn_tables.c
*/
-extern struct dn_fib_table *dn_fib_get_table(u32 n, int creat);
-extern struct dn_fib_table *dn_fib_empty_table(void);
-extern void dn_fib_table_init(void);
-extern void dn_fib_table_cleanup(void);
+struct dn_fib_table *dn_fib_get_table(u32 n, int creat);
+struct dn_fib_table *dn_fib_empty_table(void);
+void dn_fib_table_init(void);
+void dn_fib_table_cleanup(void);
/*
* dn_rules.c
*/
-extern void dn_fib_rules_init(void);
-extern void dn_fib_rules_cleanup(void);
-extern unsigned int dnet_addr_type(__le16 addr);
-extern int dn_fib_lookup(struct flowidn *fld, struct dn_fib_res *res);
+void dn_fib_rules_init(void);
+void dn_fib_rules_cleanup(void);
+unsigned int dnet_addr_type(__le16 addr);
+int dn_fib_lookup(struct flowidn *fld, struct dn_fib_res *res);
-extern int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb);
+int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb);
-extern void dn_fib_free_info(struct dn_fib_info *fi);
+void dn_fib_free_info(struct dn_fib_info *fi);
static inline void dn_fib_info_put(struct dn_fib_info *fi)
{
diff --git a/include/net/dn_neigh.h b/include/net/dn_neigh.h
index 4cb4ae7fb81f..fac4e3f4a6d3 100644
--- a/include/net/dn_neigh.h
+++ b/include/net/dn_neigh.h
@@ -16,12 +16,12 @@ struct dn_neigh {
__u8 priority;
};
-extern void dn_neigh_init(void);
-extern void dn_neigh_cleanup(void);
-extern int dn_neigh_router_hello(struct sk_buff *skb);
-extern int dn_neigh_endnode_hello(struct sk_buff *skb);
-extern void dn_neigh_pointopoint_hello(struct sk_buff *skb);
-extern int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n);
+void dn_neigh_init(void);
+void dn_neigh_cleanup(void);
+int dn_neigh_router_hello(struct sk_buff *skb);
+int dn_neigh_endnode_hello(struct sk_buff *skb);
+void dn_neigh_pointopoint_hello(struct sk_buff *skb);
+int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n);
extern struct neigh_table dn_neigh_table;
diff --git a/include/net/dn_nsp.h b/include/net/dn_nsp.h
index e43a2893f132..3a3e33d18456 100644
--- a/include/net/dn_nsp.h
+++ b/include/net/dn_nsp.h
@@ -15,29 +15,32 @@
*******************************************************************************/
/* dn_nsp.c functions prototyping */
-extern void dn_nsp_send_data_ack(struct sock *sk);
-extern void dn_nsp_send_oth_ack(struct sock *sk);
-extern void dn_nsp_delayed_ack(struct sock *sk);
-extern void dn_send_conn_ack(struct sock *sk);
-extern void dn_send_conn_conf(struct sock *sk, gfp_t gfp);
-extern void dn_nsp_send_disc(struct sock *sk, unsigned char type,
- unsigned short reason, gfp_t gfp);
-extern void dn_nsp_return_disc(struct sk_buff *skb, unsigned char type,
- unsigned short reason);
-extern void dn_nsp_send_link(struct sock *sk, unsigned char lsflags, char fcval);
-extern void dn_nsp_send_conninit(struct sock *sk, unsigned char flags);
-
-extern void dn_nsp_output(struct sock *sk);
-extern int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff_head *q, unsigned short acknum);
-extern void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, gfp_t gfp, int oob);
-extern unsigned long dn_nsp_persist(struct sock *sk);
-extern int dn_nsp_xmit_timeout(struct sock *sk);
-
-extern int dn_nsp_rx(struct sk_buff *);
-extern int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb);
-
-extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri);
-extern struct sk_buff *dn_alloc_send_skb(struct sock *sk, size_t *size, int noblock, long timeo, int *err);
+void dn_nsp_send_data_ack(struct sock *sk);
+void dn_nsp_send_oth_ack(struct sock *sk);
+void dn_nsp_delayed_ack(struct sock *sk);
+void dn_send_conn_ack(struct sock *sk);
+void dn_send_conn_conf(struct sock *sk, gfp_t gfp);
+void dn_nsp_send_disc(struct sock *sk, unsigned char type,
+ unsigned short reason, gfp_t gfp);
+void dn_nsp_return_disc(struct sk_buff *skb, unsigned char type,
+ unsigned short reason);
+void dn_nsp_send_link(struct sock *sk, unsigned char lsflags, char fcval);
+void dn_nsp_send_conninit(struct sock *sk, unsigned char flags);
+
+void dn_nsp_output(struct sock *sk);
+int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb,
+ struct sk_buff_head *q, unsigned short acknum);
+void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, gfp_t gfp,
+ int oob);
+unsigned long dn_nsp_persist(struct sock *sk);
+int dn_nsp_xmit_timeout(struct sock *sk);
+
+int dn_nsp_rx(struct sk_buff *);
+int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb);
+
+struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri);
+struct sk_buff *dn_alloc_send_skb(struct sock *sk, size_t *size, int noblock,
+ long timeo, int *err);
#define NSP_REASON_OK 0 /* No error */
#define NSP_REASON_NR 1 /* No resources */
diff --git a/include/net/dn_route.h b/include/net/dn_route.h
index 2e9d317c82dc..b409ad6b8d7a 100644
--- a/include/net/dn_route.h
+++ b/include/net/dn_route.h
@@ -15,10 +15,11 @@
GNU General Public License for more details.
*******************************************************************************/
-extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri);
-extern int dn_route_output_sock(struct dst_entry __rcu **pprt, struct flowidn *, struct sock *sk, int flags);
-extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
-extern void dn_rt_cache_flush(int delay);
+struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri);
+int dn_route_output_sock(struct dst_entry __rcu **pprt, struct flowidn *,
+ struct sock *sk, int flags);
+int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
+void dn_rt_cache_flush(int delay);
/* Masks for flags field */
#define DN_RT_F_PID 0x07 /* Mask for packet type */
@@ -92,8 +93,8 @@ static inline bool dn_is_output_route(struct dn_route *rt)
return rt->fld.flowidn_iif == 0;
}
-extern void dn_route_init(void);
-extern void dn_route_cleanup(void);
+void dn_route_init(void);
+void dn_route_cleanup(void);
#include <net/sock.h>
#include <linux/if_arp.h>
diff --git a/include/net/dst.h b/include/net/dst.h
index 3bc4865f8267..211dcf1e758e 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -106,7 +106,7 @@ struct dst_entry {
};
};
-extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
+u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
extern const u32 dst_default_metrics[];
#define DST_METRICS_READ_ONLY 0x1UL
@@ -119,7 +119,7 @@ static inline bool dst_metrics_read_only(const struct dst_entry *dst)
return dst->_metrics & DST_METRICS_READ_ONLY;
}
-extern void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old);
+void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old);
static inline void dst_destroy_metrics_generic(struct dst_entry *dst)
{
@@ -262,7 +262,7 @@ static inline struct dst_entry *dst_clone(struct dst_entry *dst)
return dst;
}
-extern void dst_release(struct dst_entry *dst);
+void dst_release(struct dst_entry *dst);
static inline void refdst_drop(unsigned long refdst)
{
@@ -362,12 +362,11 @@ static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb)
return child;
}
-extern int dst_discard(struct sk_buff *skb);
-extern void *dst_alloc(struct dst_ops *ops, struct net_device *dev,
- int initial_ref, int initial_obsolete,
- unsigned short flags);
-extern void __dst_free(struct dst_entry *dst);
-extern struct dst_entry *dst_destroy(struct dst_entry *dst);
+int dst_discard(struct sk_buff *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);
+struct dst_entry *dst_destroy(struct dst_entry *dst);
static inline void dst_free(struct dst_entry *dst)
{
@@ -463,7 +462,7 @@ static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie)
return dst;
}
-extern void dst_init(void);
+void dst_init(void);
/* Flags for xfrm_lookup flags argument. */
enum {
@@ -480,9 +479,9 @@ static inline struct dst_entry *xfrm_lookup(struct net *net,
return dst_orig;
}
#else
-extern struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
- const struct flowi *fl, struct sock *sk,
- int flags);
+struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
+ const struct flowi *fl, struct sock *sk,
+ int flags);
#endif
#endif /* _NET_DST_H */
diff --git a/include/net/esp.h b/include/net/esp.h
index d58451331dbd..1356dda00d22 100644
--- a/include/net/esp.h
+++ b/include/net/esp.h
@@ -13,7 +13,7 @@ struct esp_data {
struct crypto_aead *aead;
};
-extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len);
+void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len);
struct ip_esp_hdr;
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index 4b2b557fb0e8..e584de16e4c3 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -115,14 +115,13 @@ static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla)
return frh->table;
}
-extern struct fib_rules_ops *fib_rules_register(const struct fib_rules_ops *, struct net *);
-extern void fib_rules_unregister(struct fib_rules_ops *);
+struct fib_rules_ops *fib_rules_register(const struct fib_rules_ops *,
+ struct net *);
+void fib_rules_unregister(struct fib_rules_ops *);
-extern int fib_rules_lookup(struct fib_rules_ops *,
- struct flowi *, int flags,
- struct fib_lookup_arg *);
-extern int fib_default_rule_add(struct fib_rules_ops *,
- u32 pref, u32 table,
- u32 flags);
-extern u32 fib_default_rule_pref(struct fib_rules_ops *ops);
+int fib_rules_lookup(struct fib_rules_ops *, struct flowi *, int flags,
+ struct fib_lookup_arg *);
+int fib_default_rule_add(struct fib_rules_ops *, u32 pref, u32 table,
+ u32 flags);
+u32 fib_default_rule_pref(struct fib_rules_ops *ops);
#endif
diff --git a/include/net/flow.h b/include/net/flow.h
index 628e11b98c58..65ce471d2ab5 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -215,12 +215,13 @@ typedef struct flow_cache_object *(*flow_resolve_t)(
struct net *net, const struct flowi *key, u16 family,
u8 dir, struct flow_cache_object *oldobj, void *ctx);
-extern struct flow_cache_object *flow_cache_lookup(
- struct net *net, const struct flowi *key, u16 family,
- u8 dir, flow_resolve_t resolver, void *ctx);
+struct flow_cache_object *flow_cache_lookup(struct net *net,
+ const struct flowi *key, u16 family,
+ u8 dir, flow_resolve_t resolver,
+ void *ctx);
-extern void flow_cache_flush(void);
-extern void flow_cache_flush_deferred(void);
+void flow_cache_flush(void);
+void flow_cache_flush_deferred(void);
extern atomic_t flow_cache_genid;
#endif
diff --git a/include/net/flow_keys.h b/include/net/flow_keys.h
index bb8271d487b7..ac2439d02f54 100644
--- a/include/net/flow_keys.h
+++ b/include/net/flow_keys.h
@@ -13,5 +13,5 @@ struct flow_keys {
u8 ip_proto;
};
-extern bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow);
+bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow);
#endif
diff --git a/include/net/garp.h b/include/net/garp.h
index 834d8add9e5f..abf33bbd2e6a 100644
--- a/include/net/garp.h
+++ b/include/net/garp.h
@@ -112,19 +112,18 @@ struct garp_port {
struct rcu_head rcu;
};
-extern int garp_register_application(struct garp_application *app);
-extern void garp_unregister_application(struct garp_application *app);
-
-extern int garp_init_applicant(struct net_device *dev,
- struct garp_application *app);
-extern void garp_uninit_applicant(struct net_device *dev,
- struct garp_application *app);
-
-extern int garp_request_join(const struct net_device *dev,
- const struct garp_application *app,
- const void *data, u8 len, u8 type);
-extern void garp_request_leave(const struct net_device *dev,
- const struct garp_application *app,
- const void *data, u8 len, u8 type);
+int garp_register_application(struct garp_application *app);
+void garp_unregister_application(struct garp_application *app);
+
+int garp_init_applicant(struct net_device *dev, struct garp_application *app);
+void garp_uninit_applicant(struct net_device *dev,
+ struct garp_application *app);
+
+int garp_request_join(const struct net_device *dev,
+ const struct garp_application *app, const void *data,
+ u8 len, u8 type);
+void garp_request_leave(const struct net_device *dev,
+ const struct garp_application *app,
+ const void *data, u8 len, u8 type);
#endif /* _NET_GARP_H */
diff --git a/include/net/gen_stats.h b/include/net/gen_stats.h
index cf8439ba4d11..ea4271dceff0 100644
--- a/include/net/gen_stats.h
+++ b/include/net/gen_stats.h
@@ -19,32 +19,31 @@ struct gnet_dump {
struct tc_stats tc_stats;
};
-extern int gnet_stats_start_copy(struct sk_buff *skb, int type,
+int gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock,
+ struct gnet_dump *d);
+
+int gnet_stats_start_copy_compat(struct sk_buff *skb, int type,
+ int tc_stats_type, int xstats_type,
spinlock_t *lock, struct gnet_dump *d);
-extern int gnet_stats_start_copy_compat(struct sk_buff *skb, int type,
- int tc_stats_type,int xstats_type,
- spinlock_t *lock, struct gnet_dump *d);
-
-extern int gnet_stats_copy_basic(struct gnet_dump *d,
- struct gnet_stats_basic_packed *b);
-extern int gnet_stats_copy_rate_est(struct gnet_dump *d,
- const struct gnet_stats_basic_packed *b,
- struct gnet_stats_rate_est64 *r);
-extern int gnet_stats_copy_queue(struct gnet_dump *d,
- struct gnet_stats_queue *q);
-extern int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len);
-
-extern int gnet_stats_finish_copy(struct gnet_dump *d);
-
-extern int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
- struct gnet_stats_rate_est64 *rate_est,
- spinlock_t *stats_lock, struct nlattr *opt);
-extern void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
- struct gnet_stats_rate_est64 *rate_est);
-extern int gen_replace_estimator(struct gnet_stats_basic_packed *bstats,
- struct gnet_stats_rate_est64 *rate_est,
- spinlock_t *stats_lock, struct nlattr *opt);
-extern bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats,
- const struct gnet_stats_rate_est64 *rate_est);
+int gnet_stats_copy_basic(struct gnet_dump *d,
+ struct gnet_stats_basic_packed *b);
+int gnet_stats_copy_rate_est(struct gnet_dump *d,
+ const struct gnet_stats_basic_packed *b,
+ struct gnet_stats_rate_est64 *r);
+int gnet_stats_copy_queue(struct gnet_dump *d, struct gnet_stats_queue *q);
+int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len);
+
+int gnet_stats_finish_copy(struct gnet_dump *d);
+
+int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
+ struct gnet_stats_rate_est64 *rate_est,
+ spinlock_t *stats_lock, struct nlattr *opt);
+void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
+ struct gnet_stats_rate_est64 *rate_est);
+int gen_replace_estimator(struct gnet_stats_basic_packed *bstats,
+ struct gnet_stats_rate_est64 *rate_est,
+ spinlock_t *stats_lock, struct nlattr *opt);
+bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats,
+ const struct gnet_stats_rate_est64 *rate_est);
#endif
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 8e0b6c856a13..9b787b62cf16 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -122,7 +122,7 @@ struct genl_ops {
struct list_head ops_list;
};
-extern int __genl_register_family(struct genl_family *family);
+int __genl_register_family(struct genl_family *family);
static inline int genl_register_family(struct genl_family *family)
{
@@ -130,8 +130,8 @@ static inline int genl_register_family(struct genl_family *family)
return __genl_register_family(family);
}
-extern int __genl_register_family_with_ops(struct genl_family *family,
- struct genl_ops *ops, size_t n_ops);
+int __genl_register_family_with_ops(struct genl_family *family,
+ struct genl_ops *ops, size_t n_ops);
static inline int genl_register_family_with_ops(struct genl_family *family,
struct genl_ops *ops, size_t n_ops)
@@ -140,18 +140,18 @@ static inline int genl_register_family_with_ops(struct genl_family *family,
return __genl_register_family_with_ops(family, ops, n_ops);
}
-extern int genl_unregister_family(struct genl_family *family);
-extern int genl_register_ops(struct genl_family *, struct genl_ops *ops);
-extern int genl_unregister_ops(struct genl_family *, struct genl_ops *ops);
-extern int genl_register_mc_group(struct genl_family *family,
- struct genl_multicast_group *grp);
-extern void genl_unregister_mc_group(struct genl_family *family,
- struct genl_multicast_group *grp);
-extern void genl_notify(struct sk_buff *skb, struct net *net, u32 portid,
- u32 group, struct nlmsghdr *nlh, gfp_t flags);
+int genl_unregister_family(struct genl_family *family);
+int genl_register_ops(struct genl_family *, struct genl_ops *ops);
+int genl_unregister_ops(struct genl_family *, struct genl_ops *ops);
+int genl_register_mc_group(struct genl_family *family,
+ struct genl_multicast_group *grp);
+void genl_unregister_mc_group(struct genl_family *family,
+ struct genl_multicast_group *grp);
+void genl_notify(struct sk_buff *skb, struct net *net, u32 portid,
+ u32 group, struct nlmsghdr *nlh, gfp_t flags);
void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
- struct genl_family *family, int flags, u8 cmd);
+ struct genl_family *family, int flags, u8 cmd);
/**
* genlmsg_nlhdr - Obtain netlink header from user specified header
diff --git a/include/net/icmp.h b/include/net/icmp.h
index 081439fd070e..970028e13382 100644
--- a/include/net/icmp.h
+++ b/include/net/icmp.h
@@ -39,10 +39,10 @@ struct net_proto_family;
struct sk_buff;
struct net;
-extern void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info);
-extern int icmp_rcv(struct sk_buff *skb);
-extern void icmp_err(struct sk_buff *, u32 info);
-extern int icmp_init(void);
-extern void icmp_out_count(struct net *net, unsigned char type);
+void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info);
+int icmp_rcv(struct sk_buff *skb);
+void icmp_err(struct sk_buff *skb, u32 info);
+int icmp_init(void);
+void icmp_out_count(struct net *net, unsigned char type);
#endif /* _ICMP_H */
diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h
index 04642c920431..f981ba7adeed 100644
--- a/include/net/inet6_connection_sock.h
+++ b/include/net/inet6_connection_sock.h
@@ -22,27 +22,25 @@ struct sk_buff;
struct sock;
struct sockaddr;
-extern int inet6_csk_bind_conflict(const struct sock *sk,
- const struct inet_bind_bucket *tb, bool relax);
+int inet6_csk_bind_conflict(const struct sock *sk,
+ const struct inet_bind_bucket *tb, bool relax);
-extern struct dst_entry* inet6_csk_route_req(struct sock *sk,
- struct flowi6 *fl6,
- const struct request_sock *req);
+struct dst_entry *inet6_csk_route_req(struct sock *sk, struct flowi6 *fl6,
+ const struct request_sock *req);
-extern struct request_sock *inet6_csk_search_req(const struct sock *sk,
- struct request_sock ***prevp,
- const __be16 rport,
- const struct in6_addr *raddr,
- const struct in6_addr *laddr,
- const int iif);
+struct request_sock *inet6_csk_search_req(const struct sock *sk,
+ struct request_sock ***prevp,
+ const __be16 rport,
+ const struct in6_addr *raddr,
+ const struct in6_addr *laddr,
+ const int iif);
-extern void inet6_csk_reqsk_queue_hash_add(struct sock *sk,
- struct request_sock *req,
- const unsigned long timeout);
+void inet6_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
+ const unsigned long timeout);
-extern void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
+void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
-extern int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl);
+int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl);
-extern struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu);
+struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu);
#endif /* _INET6_CONNECTION_SOCK_H */
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index fd4ee016ba5c..f52fa88feb64 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -53,7 +53,7 @@ static inline int inet6_sk_ehashfn(const struct sock *sk)
return inet6_ehashfn(net, laddr, lport, faddr, fport);
}
-extern int __inet6_hash(struct sock *sk, struct inet_timewait_sock *twp);
+int __inet6_hash(struct sock *sk, struct inet_timewait_sock *twp);
/*
* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
@@ -61,21 +61,19 @@ extern int __inet6_hash(struct sock *sk, struct inet_timewait_sock *twp);
*
* The sockhash lock must be held as a reader here.
*/
-extern struct sock *__inet6_lookup_established(struct net *net,
- struct inet_hashinfo *hashinfo,
- const struct in6_addr *saddr,
- const __be16 sport,
- const struct in6_addr *daddr,
- const u16 hnum,
- const int dif);
-
-extern struct sock *inet6_lookup_listener(struct net *net,
- struct inet_hashinfo *hashinfo,
- const struct in6_addr *saddr,
- const __be16 sport,
- const struct in6_addr *daddr,
- const unsigned short hnum,
- const int dif);
+struct sock *__inet6_lookup_established(struct net *net,
+ struct inet_hashinfo *hashinfo,
+ const struct in6_addr *saddr,
+ const __be16 sport,
+ const struct in6_addr *daddr,
+ const u16 hnum, const int dif);
+
+struct sock *inet6_lookup_listener(struct net *net,
+ struct inet_hashinfo *hashinfo,
+ const struct in6_addr *saddr,
+ const __be16 sport,
+ const struct in6_addr *daddr,
+ const unsigned short hnum, const int dif);
static inline struct sock *__inet6_lookup(struct net *net,
struct inet_hashinfo *hashinfo,
@@ -110,9 +108,9 @@ static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo,
inet6_iif(skb));
}
-extern struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
- const struct in6_addr *saddr, const __be16 sport,
- const struct in6_addr *daddr, const __be16 dport,
- const int dif);
+struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
+ const struct in6_addr *saddr, const __be16 sport,
+ const struct in6_addr *daddr, const __be16 dport,
+ const int dif);
#endif /* IS_ENABLED(CONFIG_IPV6) */
#endif /* _INET6_HASHTABLES_H */
diff --git a/include/net/inet_common.h b/include/net/inet_common.h
index 234008782c8c..fe7994c48b75 100644
--- a/include/net/inet_common.h
+++ b/include/net/inet_common.h
@@ -13,30 +13,30 @@ struct sock;
struct sockaddr;
struct socket;
-extern int inet_release(struct socket *sock);
-extern int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
- int addr_len, int flags);
-extern int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
- int addr_len, int flags);
-extern int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr,
- int addr_len, int flags);
-extern int inet_accept(struct socket *sock, struct socket *newsock, int flags);
-extern int inet_sendmsg(struct kiocb *iocb, struct socket *sock,
- struct msghdr *msg, size_t size);
-extern ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset,
- size_t size, int flags);
-extern int inet_recvmsg(struct kiocb *iocb, struct socket *sock,
- struct msghdr *msg, size_t size, int flags);
-extern int inet_shutdown(struct socket *sock, int how);
-extern int inet_listen(struct socket *sock, int backlog);
-extern void inet_sock_destruct(struct sock *sk);
-extern int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len);
-extern int inet_getname(struct socket *sock, struct sockaddr *uaddr,
- int *uaddr_len, int peer);
-extern int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
-extern int inet_ctl_sock_create(struct sock **sk, unsigned short family,
- unsigned short type, unsigned char protocol,
- struct net *net);
+int inet_release(struct socket *sock);
+int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
+ int addr_len, int flags);
+int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
+ int addr_len, int flags);
+int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr,
+ int addr_len, int flags);
+int inet_accept(struct socket *sock, struct socket *newsock, int flags);
+int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
+ size_t size);
+ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset,
+ size_t size, int flags);
+int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
+ size_t size, int flags);
+int inet_shutdown(struct socket *sock, int how);
+int inet_listen(struct socket *sock, int backlog);
+void inet_sock_destruct(struct sock *sk);
+int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len);
+int inet_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len,
+ int peer);
+int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
+int inet_ctl_sock_create(struct sock **sk, unsigned short family,
+ unsigned short type, unsigned char protocol,
+ struct net *net);
static inline void inet_ctl_sock_destroy(struct sock *sk)
{
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index de2c78529afa..c55aeed41ace 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -146,9 +146,9 @@ static inline void *inet_csk_ca(const struct sock *sk)
return (void *)inet_csk(sk)->icsk_ca_priv;
}
-extern struct sock *inet_csk_clone_lock(const struct sock *sk,
- const struct request_sock *req,
- const gfp_t priority);
+struct sock *inet_csk_clone_lock(const struct sock *sk,
+ const struct request_sock *req,
+ const gfp_t priority);
enum inet_csk_ack_state_t {
ICSK_ACK_SCHED = 1,
@@ -157,11 +157,11 @@ enum inet_csk_ack_state_t {
ICSK_ACK_PUSHED2 = 8
};
-extern void inet_csk_init_xmit_timers(struct sock *sk,
- void (*retransmit_handler)(unsigned long),
- void (*delack_handler)(unsigned long),
- void (*keepalive_handler)(unsigned long));
-extern void inet_csk_clear_xmit_timers(struct sock *sk);
+void inet_csk_init_xmit_timers(struct sock *sk,
+ void (*retransmit_handler)(unsigned long),
+ void (*delack_handler)(unsigned long),
+ void (*keepalive_handler)(unsigned long));
+void inet_csk_clear_xmit_timers(struct sock *sk);
static inline void inet_csk_schedule_ack(struct sock *sk)
{
@@ -178,8 +178,8 @@ static inline void inet_csk_delack_init(struct sock *sk)
memset(&inet_csk(sk)->icsk_ack, 0, sizeof(inet_csk(sk)->icsk_ack));
}
-extern void inet_csk_delete_keepalive_timer(struct sock *sk);
-extern void inet_csk_reset_keepalive_timer(struct sock *sk, unsigned long timeout);
+void inet_csk_delete_keepalive_timer(struct sock *sk);
+void inet_csk_reset_keepalive_timer(struct sock *sk, unsigned long timeout);
#ifdef INET_CSK_DEBUG
extern const char inet_csk_timer_bug_msg[];
@@ -241,23 +241,21 @@ static inline void inet_csk_reset_xmit_timer(struct sock *sk, const int what,
#endif
}
-extern struct sock *inet_csk_accept(struct sock *sk, int flags, int *err);
+struct sock *inet_csk_accept(struct sock *sk, int flags, int *err);
-extern struct request_sock *inet_csk_search_req(const struct sock *sk,
- struct request_sock ***prevp,
- const __be16 rport,
- const __be32 raddr,
- const __be32 laddr);
-extern int inet_csk_bind_conflict(const struct sock *sk,
- const struct inet_bind_bucket *tb, bool relax);
-extern int inet_csk_get_port(struct sock *sk, unsigned short snum);
+struct request_sock *inet_csk_search_req(const struct sock *sk,
+ struct request_sock ***prevp,
+ const __be16 rport,
+ const __be32 raddr,
+ const __be32 laddr);
+int inet_csk_bind_conflict(const struct sock *sk,
+ const struct inet_bind_bucket *tb, bool relax);
+int inet_csk_get_port(struct sock *sk, unsigned short snum);
-extern struct dst_entry* inet_csk_route_req(struct sock *sk,
- struct flowi4 *fl4,
+struct dst_entry *inet_csk_route_req(struct sock *sk, struct flowi4 *fl4,
+ const struct request_sock *req);
+struct dst_entry *inet_csk_route_child_sock(struct sock *sk, struct sock *newsk,
const struct request_sock *req);
-extern struct dst_entry* inet_csk_route_child_sock(struct sock *sk,
- struct sock *newsk,
- const struct request_sock *req);
static inline void inet_csk_reqsk_queue_add(struct sock *sk,
struct request_sock *req,
@@ -266,9 +264,8 @@ static inline void inet_csk_reqsk_queue_add(struct sock *sk,
reqsk_queue_add(&inet_csk(sk)->icsk_accept_queue, req, sk, child);
}
-extern void inet_csk_reqsk_queue_hash_add(struct sock *sk,
- struct request_sock *req,
- unsigned long timeout);
+void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
+ unsigned long timeout);
static inline void inet_csk_reqsk_queue_removed(struct sock *sk,
struct request_sock *req)
@@ -315,13 +312,13 @@ static inline void inet_csk_reqsk_queue_drop(struct sock *sk,
reqsk_free(req);
}
-extern void inet_csk_reqsk_queue_prune(struct sock *parent,
- const unsigned long interval,
- const unsigned long timeout,
- const unsigned long max_rto);
+void inet_csk_reqsk_queue_prune(struct sock *parent,
+ const unsigned long interval,
+ const unsigned long timeout,
+ const unsigned long max_rto);
-extern void inet_csk_destroy_sock(struct sock *sk);
-extern void inet_csk_prepare_forced_close(struct sock *sk);
+void inet_csk_destroy_sock(struct sock *sk);
+void inet_csk_prepare_forced_close(struct sock *sk);
/*
* LISTEN is a special case for poll..
@@ -332,15 +329,15 @@ static inline unsigned int inet_csk_listen_poll(const struct sock *sk)
(POLLIN | POLLRDNORM) : 0;
}
-extern int inet_csk_listen_start(struct sock *sk, const int nr_table_entries);
-extern void inet_csk_listen_stop(struct sock *sk);
+int inet_csk_listen_start(struct sock *sk, const int nr_table_entries);
+void inet_csk_listen_stop(struct sock *sk);
-extern void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
+void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
-extern int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int __user *optlen);
-extern int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, unsigned int optlen);
+int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, unsigned int optlen);
-extern struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu);
+struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu);
#endif /* _INET_CONNECTION_SOCK_H */
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index ef83d9e844b5..594dfeead70f 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -218,22 +218,21 @@ static inline void inet_ehash_locks_free(struct inet_hashinfo *hashinfo)
}
}
-extern struct inet_bind_bucket *
- inet_bind_bucket_create(struct kmem_cache *cachep,
- struct net *net,
- struct inet_bind_hashbucket *head,
- const unsigned short snum);
-extern void inet_bind_bucket_destroy(struct kmem_cache *cachep,
- struct inet_bind_bucket *tb);
-
-static inline int inet_bhashfn(struct net *net,
- const __u16 lport, const int bhash_size)
+struct inet_bind_bucket *
+inet_bind_bucket_create(struct kmem_cache *cachep, struct net *net,
+ struct inet_bind_hashbucket *head,
+ const unsigned short snum);
+void inet_bind_bucket_destroy(struct kmem_cache *cachep,
+ struct inet_bind_bucket *tb);
+
+static inline int inet_bhashfn(struct net *net, const __u16 lport,
+ const int bhash_size)
{
return (lport + net_hash_mix(net)) & (bhash_size - 1);
}
-extern void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
- const unsigned short snum);
+void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
+ const unsigned short snum);
/* These can have wildcards, don't try too hard. */
static inline int inet_lhashfn(struct net *net, const unsigned short num)
@@ -247,23 +246,22 @@ static inline int inet_sk_listen_hashfn(const struct sock *sk)
}
/* Caller must disable local BH processing. */
-extern int __inet_inherit_port(struct sock *sk, struct sock *child);
+int __inet_inherit_port(struct sock *sk, struct sock *child);
-extern void inet_put_port(struct sock *sk);
+void inet_put_port(struct sock *sk);
void inet_hashinfo_init(struct inet_hashinfo *h);
-extern int __inet_hash_nolisten(struct sock *sk, struct inet_timewait_sock *tw);
-extern void inet_hash(struct sock *sk);
-extern void inet_unhash(struct sock *sk);
+int __inet_hash_nolisten(struct sock *sk, struct inet_timewait_sock *tw);
+void inet_hash(struct sock *sk);
+void inet_unhash(struct sock *sk);
-extern struct sock *__inet_lookup_listener(struct net *net,
- struct inet_hashinfo *hashinfo,
- const __be32 saddr,
- const __be16 sport,
- const __be32 daddr,
- const unsigned short hnum,
- const int dif);
+struct sock *__inet_lookup_listener(struct net *net,
+ struct inet_hashinfo *hashinfo,
+ const __be32 saddr, const __be16 sport,
+ const __be32 daddr,
+ const unsigned short hnum,
+ const int dif);
static inline struct sock *inet_lookup_listener(struct net *net,
struct inet_hashinfo *hashinfo,
@@ -339,10 +337,11 @@ static inline struct sock *inet_lookup_listener(struct net *net,
*
* Local BH must be disabled here.
*/
-extern struct sock * __inet_lookup_established(struct net *net,
- struct inet_hashinfo *hashinfo,
- const __be32 saddr, const __be16 sport,
- const __be32 daddr, const u16 hnum, const int dif);
+struct sock *__inet_lookup_established(struct net *net,
+ struct inet_hashinfo *hashinfo,
+ const __be32 saddr, const __be16 sport,
+ const __be32 daddr, const u16 hnum,
+ const int dif);
static inline struct sock *
inet_lookup_established(struct net *net, struct inet_hashinfo *hashinfo,
@@ -399,13 +398,14 @@ static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo,
iph->daddr, dport, inet_iif(skb));
}
-extern int __inet_hash_connect(struct inet_timewait_death_row *death_row,
- struct sock *sk,
- u32 port_offset,
- int (*check_established)(struct inet_timewait_death_row *,
- struct sock *, __u16, struct inet_timewait_sock **),
- int (*hash)(struct sock *sk, struct inet_timewait_sock *twp));
+int __inet_hash_connect(struct inet_timewait_death_row *death_row,
+ struct sock *sk, u32 port_offset,
+ int (*check_established)(struct inet_timewait_death_row *,
+ struct sock *, __u16,
+ struct inet_timewait_sock **),
+ int (*hash)(struct sock *sk,
+ struct inet_timewait_sock *twp));
-extern int inet_hash_connect(struct inet_timewait_death_row *death_row,
- struct sock *sk);
+int inet_hash_connect(struct inet_timewait_death_row *death_row,
+ struct sock *sk);
#endif /* _INET_HASHTABLES_H */
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index b21a7f06d6a4..636d203727a2 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -199,11 +199,11 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to,
}
#endif
-extern int inet_sk_rebuild_header(struct sock *sk);
+int inet_sk_rebuild_header(struct sock *sk);
extern u32 inet_ehash_secret;
extern u32 ipv6_hash_secret;
-extern void build_ehash_secret(void);
+void build_ehash_secret(void);
static inline unsigned int inet_ehashfn(struct net *net,
const __be32 laddr, const __u16 lport,
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index f908dfc06505..828200ab1125 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -83,9 +83,9 @@ struct inet_timewait_death_row {
int sysctl_max_tw_buckets;
};
-extern void inet_twdr_hangman(unsigned long data);
-extern void inet_twdr_twkill_work(struct work_struct *work);
-extern void inet_twdr_twcal_tick(unsigned long data);
+void inet_twdr_hangman(unsigned long data);
+void inet_twdr_twkill_work(struct work_struct *work);
+void inet_twdr_twcal_tick(unsigned long data);
struct inet_bind_bucket;
@@ -195,28 +195,27 @@ static inline __be32 sk_rcv_saddr(const struct sock *sk)
return sk->__sk_common.skc_rcv_saddr;
}
-extern void inet_twsk_put(struct inet_timewait_sock *tw);
+void inet_twsk_put(struct inet_timewait_sock *tw);
-extern int inet_twsk_unhash(struct inet_timewait_sock *tw);
+int inet_twsk_unhash(struct inet_timewait_sock *tw);
-extern int inet_twsk_bind_unhash(struct inet_timewait_sock *tw,
- struct inet_hashinfo *hashinfo);
+int inet_twsk_bind_unhash(struct inet_timewait_sock *tw,
+ struct inet_hashinfo *hashinfo);
-extern struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk,
- const int state);
+struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk,
+ const int state);
-extern void __inet_twsk_hashdance(struct inet_timewait_sock *tw,
- struct sock *sk,
- struct inet_hashinfo *hashinfo);
+void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
+ struct inet_hashinfo *hashinfo);
-extern void inet_twsk_schedule(struct inet_timewait_sock *tw,
- struct inet_timewait_death_row *twdr,
- const int timeo, const int timewait_len);
-extern void inet_twsk_deschedule(struct inet_timewait_sock *tw,
- struct inet_timewait_death_row *twdr);
+void inet_twsk_schedule(struct inet_timewait_sock *tw,
+ struct inet_timewait_death_row *twdr,
+ const int timeo, const int timewait_len);
+void inet_twsk_deschedule(struct inet_timewait_sock *tw,
+ struct inet_timewait_death_row *twdr);
-extern void inet_twsk_purge(struct inet_hashinfo *hashinfo,
- struct inet_timewait_death_row *twdr, int family);
+void inet_twsk_purge(struct inet_hashinfo *hashinfo,
+ struct inet_timewait_death_row *twdr, int family);
static inline
struct net *twsk_net(const struct inet_timewait_sock *twsk)
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index 53f464d7cddc..f4e127af4e17 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -120,9 +120,9 @@ static inline void inetpeer_transfer_peer(unsigned long *to, unsigned long *from
}
}
-extern void inet_peer_base_init(struct inet_peer_base *);
+void inet_peer_base_init(struct inet_peer_base *);
-void inet_initpeers(void) __init;
+void inet_initpeers(void) __init;
#define INETPEER_METRICS_NEW (~(u32) 0)
@@ -159,11 +159,11 @@ static inline struct inet_peer *inet_getpeer_v6(struct inet_peer_base *base,
}
/* can be called from BH context or outside */
-extern void inet_putpeer(struct inet_peer *p);
-extern bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout);
+void inet_putpeer(struct inet_peer *p);
+bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout);
-extern void inetpeer_invalidate_tree(struct inet_peer_base *);
-extern void inetpeer_invalidate_family(int family);
+void inetpeer_invalidate_tree(struct inet_peer_base *);
+void inetpeer_invalidate_family(int family);
/*
* temporary check to make sure we dont access rid, ip_id_count, tcp_ts,
diff --git a/include/net/ip.h b/include/net/ip.h
index 5e5268807a1c..c1f192b8cd0e 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -86,53 +86,51 @@ struct packet_type;
struct rtable;
struct sockaddr;
-extern int igmp_mc_proc_init(void);
+int igmp_mc_proc_init(void);
/*
* Functions provided by ip.c
*/
-extern int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
- __be32 saddr, __be32 daddr,
- struct ip_options_rcu *opt);
-extern int ip_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt, struct net_device *orig_dev);
-extern int ip_local_deliver(struct sk_buff *skb);
-extern int ip_mr_input(struct sk_buff *skb);
-extern int ip_output(struct sk_buff *skb);
-extern int ip_mc_output(struct sk_buff *skb);
-extern int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
-extern int ip_do_nat(struct sk_buff *skb);
-extern void ip_send_check(struct iphdr *ip);
-extern int __ip_local_out(struct sk_buff *skb);
-extern int ip_local_out(struct sk_buff *skb);
-extern int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl);
-extern void ip_init(void);
-extern int ip_append_data(struct sock *sk, struct flowi4 *fl4,
- int getfrag(void *from, char *to, int offset, int len,
- int odd, struct sk_buff *skb),
- void *from, int len, int protolen,
- struct ipcm_cookie *ipc,
- struct rtable **rt,
- unsigned int flags);
-extern int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb);
-extern ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
- int offset, size_t size, int flags);
-extern struct sk_buff *__ip_make_skb(struct sock *sk,
- struct flowi4 *fl4,
- struct sk_buff_head *queue,
- struct inet_cork *cork);
-extern int ip_send_skb(struct net *net, struct sk_buff *skb);
-extern int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4);
-extern void ip_flush_pending_frames(struct sock *sk);
-extern struct sk_buff *ip_make_skb(struct sock *sk,
- struct flowi4 *fl4,
- int getfrag(void *from, char *to, int offset, int len,
- int odd, struct sk_buff *skb),
- void *from, int length, int transhdrlen,
- struct ipcm_cookie *ipc,
- struct rtable **rtp,
- unsigned int flags);
+int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
+ __be32 saddr, __be32 daddr,
+ struct ip_options_rcu *opt);
+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_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);
+void ip_init(void);
+int ip_append_data(struct sock *sk, struct flowi4 *fl4,
+ int getfrag(void *from, char *to, int offset, int len,
+ int odd, struct sk_buff *skb),
+ void *from, int len, int protolen,
+ struct ipcm_cookie *ipc,
+ struct rtable **rt,
+ unsigned int flags);
+int ip_generic_getfrag(void *from, char *to, int offset, int len, int odd,
+ struct sk_buff *skb);
+ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
+ int offset, size_t size, int flags);
+struct sk_buff *__ip_make_skb(struct sock *sk, struct flowi4 *fl4,
+ struct sk_buff_head *queue,
+ struct inet_cork *cork);
+int ip_send_skb(struct net *net, struct sk_buff *skb);
+int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4);
+void ip_flush_pending_frames(struct sock *sk);
+struct sk_buff *ip_make_skb(struct sock *sk, struct flowi4 *fl4,
+ int getfrag(void *from, char *to, int offset,
+ int len, int odd, struct sk_buff *skb),
+ void *from, int length, int transhdrlen,
+ struct ipcm_cookie *ipc, struct rtable **rtp,
+ unsigned int flags);
static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4)
{
@@ -140,10 +138,9 @@ static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4)
}
/* datagram.c */
-extern int ip4_datagram_connect(struct sock *sk,
- struct sockaddr *uaddr, int addr_len);
+int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
-extern void ip4_datagram_release_cb(struct sock *sk);
+void ip4_datagram_release_cb(struct sock *sk);
struct ip_reply_arg {
struct kvec iov[1];
@@ -184,16 +181,16 @@ extern struct ipv4_config ipv4_config;
#define NET_ADD_STATS_BH(net, field, adnd) SNMP_ADD_STATS_BH((net)->mib.net_statistics, field, adnd)
#define NET_ADD_STATS_USER(net, field, adnd) SNMP_ADD_STATS_USER((net)->mib.net_statistics, field, adnd)
-extern unsigned long snmp_fold_field(void __percpu *mib[], int offt);
+unsigned long snmp_fold_field(void __percpu *mib[], int offt);
#if BITS_PER_LONG==32
-extern u64 snmp_fold_field64(void __percpu *mib[], int offt, size_t sync_off);
+u64 snmp_fold_field64(void __percpu *mib[], int offt, size_t sync_off);
#else
static inline u64 snmp_fold_field64(void __percpu *mib[], int offt, size_t syncp_off)
{
return snmp_fold_field(mib, offt);
}
#endif
-extern int snmp_mib_init(void __percpu *ptr[2], size_t mibsize, size_t align);
+int snmp_mib_init(void __percpu *ptr[2], size_t mibsize, size_t align);
static inline void snmp_mib_free(void __percpu *ptr[SNMP_ARRAY_SZ])
{
@@ -210,7 +207,7 @@ extern struct local_ports {
seqlock_t lock;
int range[2];
} sysctl_local_ports;
-extern void inet_get_local_port_range(int *low, int *high);
+void inet_get_local_port_range(int *low, int *high);
extern unsigned long *sysctl_local_reserved_ports;
static inline int inet_is_reserved_local_port(int port)
@@ -231,9 +228,9 @@ extern int sysctl_ip_early_demux;
/* From ip_output.c */
extern int sysctl_ip_dynaddr;
-extern void ipfrag_init(void);
+void ipfrag_init(void);
-extern void ip_static_sysctl_init(void);
+void ip_static_sysctl_init(void);
static inline bool ip_is_fragment(const struct iphdr *iph)
{
@@ -262,7 +259,7 @@ int ip_dont_fragment(struct sock *sk, struct dst_entry *dst)
!(dst_metric_locked(dst, RTAX_MTU)));
}
-extern void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more);
+void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more);
static inline void ip_select_ident(struct sk_buff *skb, struct dst_entry *dst, struct sock *sk)
{
@@ -390,7 +387,7 @@ static inline int sk_mc_loop(struct sock *sk)
return 1;
}
-extern bool ip_call_ra_chain(struct sk_buff *skb);
+bool ip_call_ra_chain(struct sk_buff *skb);
/*
* Functions provided by ip_fragment.c
@@ -428,50 +425,52 @@ int ip_frag_nqueues(struct net *net);
* Functions provided by ip_forward.c
*/
-extern int ip_forward(struct sk_buff *skb);
+int ip_forward(struct sk_buff *skb);
/*
* Functions provided by ip_options.c
*/
-extern void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
- __be32 daddr, struct rtable *rt, int is_frag);
-extern int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb);
-extern void ip_options_fragment(struct sk_buff *skb);
-extern int ip_options_compile(struct net *net,
- struct ip_options *opt, struct sk_buff *skb);
-extern int ip_options_get(struct net *net, struct ip_options_rcu **optp,
- unsigned char *data, int optlen);
-extern int ip_options_get_from_user(struct net *net, struct ip_options_rcu **optp,
- unsigned char __user *data, int optlen);
-extern void ip_options_undo(struct ip_options * opt);
-extern void ip_forward_options(struct sk_buff *skb);
-extern int ip_options_rcv_srr(struct sk_buff *skb);
+void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
+ __be32 daddr, struct rtable *rt, int is_frag);
+int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb);
+void ip_options_fragment(struct sk_buff *skb);
+int ip_options_compile(struct net *net, struct ip_options *opt,
+ struct sk_buff *skb);
+int ip_options_get(struct net *net, struct ip_options_rcu **optp,
+ unsigned char *data, int optlen);
+int ip_options_get_from_user(struct net *net, struct ip_options_rcu **optp,
+ unsigned char __user *data, int optlen);
+void ip_options_undo(struct ip_options *opt);
+void ip_forward_options(struct sk_buff *skb);
+int ip_options_rcv_srr(struct sk_buff *skb);
/*
* Functions provided by ip_sockglue.c
*/
-extern void ipv4_pktinfo_prepare(struct sk_buff *skb);
-extern void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb);
-extern int ip_cmsg_send(struct net *net,
- struct msghdr *msg, struct ipcm_cookie *ipc);
-extern int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, unsigned int optlen);
-extern int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen);
-extern int compat_ip_setsockopt(struct sock *sk, int level,
- int optname, char __user *optval, unsigned int optlen);
-extern int compat_ip_getsockopt(struct sock *sk, int level,
- int optname, char __user *optval, int __user *optlen);
-extern int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *));
-
-extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len);
-extern void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
- __be16 port, u32 info, u8 *payload);
-extern void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
- u32 info);
+void ipv4_pktinfo_prepare(struct sk_buff *skb);
+void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb);
+int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc);
+int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
+ unsigned int optlen);
+int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
+ int __user *optlen);
+int compat_ip_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, unsigned int optlen);
+int compat_ip_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+int ip_ra_control(struct sock *sk, unsigned char on,
+ void (*destructor)(struct sock *));
+
+int ip_recv_error(struct sock *sk, struct msghdr *msg, int len);
+void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
+ u32 info, u8 *payload);
+void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
+ u32 info);
#ifdef CONFIG_PROC_FS
-extern int ip_misc_proc_init(void);
+int ip_misc_proc_init(void);
#endif
#endif /* _IP_H */
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 48ec25a7fcb6..eab88f0e2088 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -267,48 +267,41 @@ typedef struct rt6_info *(*pol_lookup_t)(struct net *,
* exported functions
*/
-extern struct fib6_table *fib6_get_table(struct net *net, u32 id);
-extern struct fib6_table *fib6_new_table(struct net *net, u32 id);
-extern struct dst_entry *fib6_rule_lookup(struct net *net,
- struct flowi6 *fl6, int flags,
- pol_lookup_t lookup);
+struct fib6_table *fib6_get_table(struct net *net, u32 id);
+struct fib6_table *fib6_new_table(struct net *net, u32 id);
+struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
+ int flags, pol_lookup_t lookup);
-extern struct fib6_node *fib6_lookup(struct fib6_node *root,
- const struct in6_addr *daddr,
- const struct in6_addr *saddr);
+struct fib6_node *fib6_lookup(struct fib6_node *root,
+ const struct in6_addr *daddr,
+ const struct in6_addr *saddr);
-struct fib6_node *fib6_locate(struct fib6_node *root,
- const struct in6_addr *daddr, int dst_len,
- const struct in6_addr *saddr, int src_len);
+struct fib6_node *fib6_locate(struct fib6_node *root,
+ const struct in6_addr *daddr, int dst_len,
+ const struct in6_addr *saddr, int src_len);
-extern void fib6_clean_all_ro(struct net *net,
- int (*func)(struct rt6_info *, void *arg),
- int prune, void *arg);
+void fib6_clean_all_ro(struct net *net,
+ int (*func)(struct rt6_info *, void *arg),
+ int prune, void *arg);
-extern void fib6_clean_all(struct net *net,
- int (*func)(struct rt6_info *, void *arg),
- int prune, void *arg);
+void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg),
+ int prune, void *arg);
-extern int fib6_add(struct fib6_node *root,
- struct rt6_info *rt,
- struct nl_info *info);
+int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info);
-extern int fib6_del(struct rt6_info *rt,
- struct nl_info *info);
+int fib6_del(struct rt6_info *rt, struct nl_info *info);
-extern void inet6_rt_notify(int event, struct rt6_info *rt,
- struct nl_info *info);
+void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info);
-extern void fib6_run_gc(unsigned long expires,
- struct net *net, bool force);
+void fib6_run_gc(unsigned long expires, struct net *net, bool force);
-extern void fib6_gc_cleanup(void);
+void fib6_gc_cleanup(void);
-extern int fib6_init(void);
+int fib6_init(void);
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
-extern int fib6_rules_init(void);
-extern void fib6_rules_cleanup(void);
+int fib6_rules_init(void);
+void fib6_rules_cleanup(void);
#else
static inline int fib6_rules_init(void)
{
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index f525e7038cca..02e220dc4cf5 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -51,7 +51,7 @@ static inline unsigned int rt6_flags2srcprefs(int flags)
return (flags >> 3) & 7;
}
-extern void rt6_bind_peer(struct rt6_info *rt, int create);
+void rt6_bind_peer(struct rt6_info *rt, int create);
static inline struct inet_peer *__rt6_get_peer(struct rt6_info *rt, int create)
{
@@ -72,70 +72,58 @@ static inline struct inet_peer *rt6_get_peer_create(struct rt6_info *rt)
return __rt6_get_peer(rt, 1);
}
-extern void ip6_route_input(struct sk_buff *skb);
+void ip6_route_input(struct sk_buff *skb);
-extern struct dst_entry * ip6_route_output(struct net *net,
- const struct sock *sk,
- struct flowi6 *fl6);
-extern struct dst_entry * ip6_route_lookup(struct net *net,
- struct flowi6 *fl6, int flags);
+struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk,
+ struct flowi6 *fl6);
+struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
+ int flags);
-extern int ip6_route_init(void);
-extern void ip6_route_cleanup(void);
+int ip6_route_init(void);
+void ip6_route_cleanup(void);
-extern int ipv6_route_ioctl(struct net *net,
- unsigned int cmd,
- void __user *arg);
+int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg);
-extern int ip6_route_add(struct fib6_config *cfg);
-extern int ip6_ins_rt(struct rt6_info *);
-extern int ip6_del_rt(struct rt6_info *);
+int ip6_route_add(struct fib6_config *cfg);
+int ip6_ins_rt(struct rt6_info *);
+int ip6_del_rt(struct rt6_info *);
-extern int ip6_route_get_saddr(struct net *net,
- struct rt6_info *rt,
- const struct in6_addr *daddr,
- unsigned int prefs,
- struct in6_addr *saddr);
+int ip6_route_get_saddr(struct net *net, struct rt6_info *rt,
+ const struct in6_addr *daddr, unsigned int prefs,
+ struct in6_addr *saddr);
-extern struct rt6_info *rt6_lookup(struct net *net,
- const struct in6_addr *daddr,
- const struct in6_addr *saddr,
- int oif, int flags);
+struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr,
+ const struct in6_addr *saddr, int oif, int flags);
-extern struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
- struct flowi6 *fl6);
-extern int icmp6_dst_gc(void);
+struct dst_entry *icmp6_dst_alloc(struct net_device *dev, struct flowi6 *fl6);
+int icmp6_dst_gc(void);
-extern void fib6_force_start_gc(struct net *net);
+void fib6_force_start_gc(struct net *net);
-extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
- const struct in6_addr *addr,
- bool anycast);
+struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
+ const struct in6_addr *addr, bool anycast);
/*
* support functions for ND
*
*/
-extern struct rt6_info * rt6_get_dflt_router(const struct in6_addr *addr,
- struct net_device *dev);
-extern struct rt6_info * rt6_add_dflt_router(const struct in6_addr *gwaddr,
- struct net_device *dev,
- unsigned int pref);
-
-extern void rt6_purge_dflt_routers(struct net *net);
-
-extern int rt6_route_rcv(struct net_device *dev,
- u8 *opt, int len,
- const struct in6_addr *gwaddr);
-
-extern void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
- int oif, u32 mark);
-extern void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk,
- __be32 mtu);
-extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark);
-extern void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
- u32 mark);
-extern void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk);
+struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr,
+ struct net_device *dev);
+struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr,
+ struct net_device *dev, unsigned int pref);
+
+void rt6_purge_dflt_routers(struct net *net);
+
+int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
+ const struct in6_addr *gwaddr);
+
+void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, int oif,
+ u32 mark);
+void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu);
+void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark);
+void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
+ u32 mark);
+void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk);
struct netlink_callback;
@@ -145,10 +133,10 @@ struct rt6_rtnl_dump_arg {
struct net *net;
};
-extern int rt6_dump_route(struct rt6_info *rt, void *p_arg);
-extern void rt6_ifdown(struct net *net, struct net_device *dev);
-extern void rt6_mtu_change(struct net_device *dev, unsigned int mtu);
-extern void rt6_remove_prefsrc(struct inet6_ifaddr *ifp);
+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);
/*
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index cbf2be37c91a..9922093f575e 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -165,7 +165,7 @@ struct fib_result_nl {
#define FIB_TABLE_HASHSZ 2
#endif
-extern __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
+__be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
#define FIB_RES_SADDR(net, res) \
((FIB_RES_NH(res).nh_saddr_genid == \
@@ -187,14 +187,14 @@ struct fib_table {
unsigned long tb_data[0];
};
-extern int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
- struct fib_result *res, int fib_flags);
-extern int fib_table_insert(struct fib_table *, struct fib_config *);
-extern int fib_table_delete(struct fib_table *, struct fib_config *);
-extern int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
- struct netlink_callback *cb);
-extern int fib_table_flush(struct fib_table *table);
-extern void fib_free_table(struct fib_table *tb);
+int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
+ struct fib_result *res, int fib_flags);
+int fib_table_insert(struct fib_table *, struct fib_config *);
+int fib_table_delete(struct fib_table *, struct fib_config *);
+int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
+ struct netlink_callback *cb);
+int fib_table_flush(struct fib_table *table);
+void fib_free_table(struct fib_table *tb);
@@ -234,14 +234,13 @@ static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
}
#else /* CONFIG_IP_MULTIPLE_TABLES */
-extern int __net_init fib4_rules_init(struct net *net);
-extern void __net_exit fib4_rules_exit(struct net *net);
+int __net_init fib4_rules_init(struct net *net);
+void __net_exit fib4_rules_exit(struct net *net);
-extern struct fib_table *fib_new_table(struct net *net, u32 id);
-extern struct fib_table *fib_get_table(struct net *net, u32 id);
+struct fib_table *fib_new_table(struct net *net, u32 id);
+struct fib_table *fib_get_table(struct net *net, u32 id);
-extern int __fib_lookup(struct net *net, struct flowi4 *flp,
- struct fib_result *res);
+int __fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res);
static inline int fib_lookup(struct net *net, struct flowi4 *flp,
struct fib_result *res)
@@ -269,12 +268,12 @@ static inline int fib_lookup(struct net *net, struct flowi4 *flp,
/* Exported by fib_frontend.c */
extern const struct nla_policy rtm_ipv4_policy[];
-extern void ip_fib_init(void);
-extern __be32 fib_compute_spec_dst(struct sk_buff *skb);
-extern int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
- u8 tos, int oif, struct net_device *dev,
- struct in_device *idev, u32 *itag);
-extern void fib_select_default(struct fib_result *res);
+void ip_fib_init(void);
+__be32 fib_compute_spec_dst(struct sk_buff *skb);
+int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
+ u8 tos, int oif, struct net_device *dev,
+ struct in_device *idev, u32 *itag);
+void fib_select_default(struct fib_result *res);
#ifdef CONFIG_IP_ROUTE_CLASSID
static inline int fib_num_tclassid_users(struct net *net)
{
@@ -288,15 +287,15 @@ static inline int fib_num_tclassid_users(struct net *net)
#endif
/* Exported by fib_semantics.c */
-extern int ip_fib_check_default(__be32 gw, struct net_device *dev);
-extern int fib_sync_down_dev(struct net_device *dev, int force);
-extern int fib_sync_down_addr(struct net *net, __be32 local);
-extern int fib_sync_up(struct net_device *dev);
-extern void fib_select_multipath(struct fib_result *res);
+int ip_fib_check_default(__be32 gw, struct net_device *dev);
+int fib_sync_down_dev(struct net_device *dev, int force);
+int fib_sync_down_addr(struct net *net, __be32 local);
+int fib_sync_up(struct net_device *dev);
+void fib_select_multipath(struct fib_result *res);
/* Exported by fib_trie.c */
-extern void fib_trie_init(void);
-extern struct fib_table *fib_trie_table(u32 id);
+void fib_trie_init(void);
+struct fib_table *fib_trie_table(u32 id);
static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
{
@@ -314,7 +313,7 @@ static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
#endif
}
-extern void free_fib_info(struct fib_info *fi);
+void free_fib_info(struct fib_info *fi);
static inline void fib_info_put(struct fib_info *fi)
{
@@ -323,8 +322,8 @@ static inline void fib_info_put(struct fib_info *fi)
}
#ifdef CONFIG_PROC_FS
-extern int __net_init fib_proc_init(struct net *net);
-extern void __net_exit fib_proc_exit(struct net *net);
+int __net_init fib_proc_init(struct net *net);
+void __net_exit fib_proc_exit(struct net *net);
#else
static inline int fib_proc_init(struct net *net)
{
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index f0d70f066f3d..b6fd378c09c8 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -236,7 +236,7 @@ static inline int ip_vs_addr_equal(int af, const union nf_inet_addr *a,
#ifdef CONFIG_IP_VS_DEBUG
#include <linux/net.h>
-extern int ip_vs_get_debug_level(void);
+int ip_vs_get_debug_level(void);
static inline const char *ip_vs_dbg_addr(int af, char *buf, size_t buf_len,
const union nf_inet_addr *addr,
@@ -532,9 +532,9 @@ struct ip_vs_proto_data {
struct tcp_states_t *tcp_state_table;
};
-extern struct ip_vs_protocol *ip_vs_proto_get(unsigned short proto);
-extern struct ip_vs_proto_data *ip_vs_proto_data_get(struct net *net,
- unsigned short proto);
+struct ip_vs_protocol *ip_vs_proto_get(unsigned short proto);
+struct ip_vs_proto_data *ip_vs_proto_data_get(struct net *net,
+ unsigned short proto);
struct ip_vs_conn_param {
struct net *net;
@@ -1176,8 +1176,8 @@ static inline int sysctl_backup_only(struct netns_ipvs *ipvs)
* IPVS core functions
* (from ip_vs_core.c)
*/
-extern const char *ip_vs_proto_name(unsigned int proto);
-extern void ip_vs_init_hash_table(struct list_head *table, int rows);
+const char *ip_vs_proto_name(unsigned int proto);
+void ip_vs_init_hash_table(struct list_head *table, int rows);
#define IP_VS_INIT_HASH_TABLE(t) ip_vs_init_hash_table((t), ARRAY_SIZE((t)))
#define IP_VS_APP_TYPE_FTP 1
@@ -1240,22 +1240,22 @@ static inline void __ip_vs_conn_put(struct ip_vs_conn *cp)
smp_mb__before_atomic_dec();
atomic_dec(&cp->refcnt);
}
-extern void ip_vs_conn_put(struct ip_vs_conn *cp);
-extern void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport);
+void ip_vs_conn_put(struct ip_vs_conn *cp);
+void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport);
struct ip_vs_conn *ip_vs_conn_new(const struct ip_vs_conn_param *p,
const union nf_inet_addr *daddr,
__be16 dport, unsigned int flags,
struct ip_vs_dest *dest, __u32 fwmark);
-extern void ip_vs_conn_expire_now(struct ip_vs_conn *cp);
+void ip_vs_conn_expire_now(struct ip_vs_conn *cp);
-extern const char * ip_vs_state_name(__u16 proto, int state);
+const char *ip_vs_state_name(__u16 proto, int state);
-extern void ip_vs_tcp_conn_listen(struct net *net, struct ip_vs_conn *cp);
-extern int ip_vs_check_template(struct ip_vs_conn *ct);
-extern void ip_vs_random_dropentry(struct net *net);
-extern int ip_vs_conn_init(void);
-extern void ip_vs_conn_cleanup(void);
+void ip_vs_tcp_conn_listen(struct net *net, struct ip_vs_conn *cp);
+int ip_vs_check_template(struct ip_vs_conn *ct);
+void ip_vs_random_dropentry(struct net *net);
+int ip_vs_conn_init(void);
+void ip_vs_conn_cleanup(void);
static inline void ip_vs_control_del(struct ip_vs_conn *cp)
{
@@ -1320,37 +1320,36 @@ ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp)
/*
* IPVS netns init & cleanup functions
*/
-extern int ip_vs_estimator_net_init(struct net *net);
-extern int ip_vs_control_net_init(struct net *net);
-extern int ip_vs_protocol_net_init(struct net *net);
-extern int ip_vs_app_net_init(struct net *net);
-extern int ip_vs_conn_net_init(struct net *net);
-extern int ip_vs_sync_net_init(struct net *net);
-extern void ip_vs_conn_net_cleanup(struct net *net);
-extern void ip_vs_app_net_cleanup(struct net *net);
-extern void ip_vs_protocol_net_cleanup(struct net *net);
-extern void ip_vs_control_net_cleanup(struct net *net);
-extern void ip_vs_estimator_net_cleanup(struct net *net);
-extern void ip_vs_sync_net_cleanup(struct net *net);
-extern void ip_vs_service_net_cleanup(struct net *net);
+int ip_vs_estimator_net_init(struct net *net);
+int ip_vs_control_net_init(struct net *net);
+int ip_vs_protocol_net_init(struct net *net);
+int ip_vs_app_net_init(struct net *net);
+int ip_vs_conn_net_init(struct net *net);
+int ip_vs_sync_net_init(struct net *net);
+void ip_vs_conn_net_cleanup(struct net *net);
+void ip_vs_app_net_cleanup(struct net *net);
+void ip_vs_protocol_net_cleanup(struct net *net);
+void ip_vs_control_net_cleanup(struct net *net);
+void ip_vs_estimator_net_cleanup(struct net *net);
+void ip_vs_sync_net_cleanup(struct net *net);
+void ip_vs_service_net_cleanup(struct net *net);
/*
* IPVS application functions
* (from ip_vs_app.c)
*/
#define IP_VS_APP_MAX_PORTS 8
-extern struct ip_vs_app *register_ip_vs_app(struct net *net,
- struct ip_vs_app *app);
-extern void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app);
-extern int ip_vs_bind_app(struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern void ip_vs_unbind_app(struct ip_vs_conn *cp);
-extern int register_ip_vs_app_inc(struct net *net, struct ip_vs_app *app,
- __u16 proto, __u16 port);
-extern int ip_vs_app_inc_get(struct ip_vs_app *inc);
-extern void ip_vs_app_inc_put(struct ip_vs_app *inc);
-
-extern int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff *skb);
-extern int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff *skb);
+struct ip_vs_app *register_ip_vs_app(struct net *net, struct ip_vs_app *app);
+void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app);
+int ip_vs_bind_app(struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
+void ip_vs_unbind_app(struct ip_vs_conn *cp);
+int register_ip_vs_app_inc(struct net *net, struct ip_vs_app *app, __u16 proto,
+ __u16 port);
+int ip_vs_app_inc_get(struct ip_vs_app *inc);
+void ip_vs_app_inc_put(struct ip_vs_app *inc);
+
+int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff *skb);
+int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff *skb);
int register_ip_vs_pe(struct ip_vs_pe *pe);
int unregister_ip_vs_pe(struct ip_vs_pe *pe);
@@ -1371,17 +1370,15 @@ struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name);
/*
* IPVS protocol functions (from ip_vs_proto.c)
*/
-extern int ip_vs_protocol_init(void);
-extern void ip_vs_protocol_cleanup(void);
-extern void ip_vs_protocol_timeout_change(struct netns_ipvs *ipvs, int flags);
-extern int *ip_vs_create_timeout_table(int *table, int size);
-extern int
-ip_vs_set_state_timeout(int *table, int num, const char *const *names,
- const char *name, int to);
-extern void
-ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp,
- const struct sk_buff *skb,
- int offset, const char *msg);
+int ip_vs_protocol_init(void);
+void ip_vs_protocol_cleanup(void);
+void ip_vs_protocol_timeout_change(struct netns_ipvs *ipvs, int flags);
+int *ip_vs_create_timeout_table(int *table, int size);
+int ip_vs_set_state_timeout(int *table, int num, const char *const *names,
+ const char *name, int to);
+void ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp,
+ const struct sk_buff *skb, int offset,
+ const char *msg);
extern struct ip_vs_protocol ip_vs_protocol_tcp;
extern struct ip_vs_protocol ip_vs_protocol_udp;
@@ -1394,22 +1391,22 @@ extern struct ip_vs_protocol ip_vs_protocol_sctp;
* Registering/unregistering scheduler functions
* (from ip_vs_sched.c)
*/
-extern int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
-extern int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
-extern int ip_vs_bind_scheduler(struct ip_vs_service *svc,
- struct ip_vs_scheduler *scheduler);
-extern void ip_vs_unbind_scheduler(struct ip_vs_service *svc,
- struct ip_vs_scheduler *sched);
-extern struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
-extern void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
-extern struct ip_vs_conn *
+int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+int unregister_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);
+int ip_vs_bind_scheduler(struct ip_vs_service *svc,
+ struct ip_vs_scheduler *scheduler);
+void ip_vs_unbind_scheduler(struct ip_vs_service *svc,
+ struct ip_vs_scheduler *sched);
+struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
+void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
+struct ip_vs_conn *
ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
struct ip_vs_proto_data *pd, int *ignored,
struct ip_vs_iphdr *iph);
-extern int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
- struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph);
+int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
+ struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph);
-extern void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg);
+void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg);
/*
@@ -1418,25 +1415,24 @@ extern void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg);
extern struct ip_vs_stats ip_vs_stats;
extern int sysctl_ip_vs_sync_ver;
-extern struct ip_vs_service *
+struct ip_vs_service *
ip_vs_service_find(struct net *net, int af, __u32 fwmark, __u16 protocol,
const union nf_inet_addr *vaddr, __be16 vport);
-extern bool
-ip_vs_has_real_service(struct net *net, int af, __u16 protocol,
- const union nf_inet_addr *daddr, __be16 dport);
-
-extern int ip_vs_use_count_inc(void);
-extern void ip_vs_use_count_dec(void);
-extern int ip_vs_register_nl_ioctl(void);
-extern void ip_vs_unregister_nl_ioctl(void);
-extern int ip_vs_control_init(void);
-extern void ip_vs_control_cleanup(void);
-extern struct ip_vs_dest *
+bool ip_vs_has_real_service(struct net *net, int af, __u16 protocol,
+ const union nf_inet_addr *daddr, __be16 dport);
+
+int ip_vs_use_count_inc(void);
+void ip_vs_use_count_dec(void);
+int ip_vs_register_nl_ioctl(void);
+void ip_vs_unregister_nl_ioctl(void);
+int ip_vs_control_init(void);
+void ip_vs_control_cleanup(void);
+struct ip_vs_dest *
ip_vs_find_dest(struct net *net, int af, const union nf_inet_addr *daddr,
__be16 dport, const union nf_inet_addr *vaddr, __be16 vport,
__u16 protocol, __u32 fwmark, __u32 flags);
-extern void ip_vs_try_bind_dest(struct ip_vs_conn *cp);
+void ip_vs_try_bind_dest(struct ip_vs_conn *cp);
static inline void ip_vs_dest_hold(struct ip_vs_dest *dest)
{
@@ -1453,56 +1449,49 @@ static inline void ip_vs_dest_put(struct ip_vs_dest *dest)
* IPVS sync daemon data and function prototypes
* (from ip_vs_sync.c)
*/
-extern int start_sync_thread(struct net *net, int state, char *mcast_ifn,
- __u8 syncid);
-extern int stop_sync_thread(struct net *net, int state);
-extern void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp, int pkts);
-
+int start_sync_thread(struct net *net, int state, char *mcast_ifn, __u8 syncid);
+int stop_sync_thread(struct net *net, int state);
+void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp, int pkts);
/*
* IPVS rate estimator prototypes (from ip_vs_est.c)
*/
-extern void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats);
-extern void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats);
-extern void ip_vs_zero_estimator(struct ip_vs_stats *stats);
-extern void ip_vs_read_estimator(struct ip_vs_stats_user *dst,
- struct ip_vs_stats *stats);
+void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats);
+void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats);
+void ip_vs_zero_estimator(struct ip_vs_stats *stats);
+void ip_vs_read_estimator(struct ip_vs_stats_user *dst,
+ struct ip_vs_stats *stats);
/*
* Various IPVS packet transmitters (from ip_vs_xmit.c)
*/
-extern int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
-extern int ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp,
- struct ip_vs_iphdr *iph);
-extern int ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
-extern int ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp,
- struct ip_vs_iphdr *iph);
-extern int ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
-extern int ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp, int offset,
- unsigned int hooknum, struct ip_vs_iphdr *iph);
-extern void ip_vs_dest_dst_rcu_free(struct rcu_head *head);
+int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+int ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+int ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+int ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+int ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+int ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, int offset,
+ unsigned int hooknum, struct ip_vs_iphdr *iph);
+void ip_vs_dest_dst_rcu_free(struct rcu_head *head);
#ifdef CONFIG_IP_VS_IPV6
-extern int ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp,
- struct ip_vs_iphdr *iph);
-extern int ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp,
- struct ip_vs_iphdr *iph);
-extern int ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp,
- struct ip_vs_iphdr *iph);
-extern int ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
-extern int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp, int offset,
- unsigned int hooknum, struct ip_vs_iphdr *iph);
+int ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+int ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+int ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+int ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, int offset,
+ unsigned int hooknum, struct ip_vs_iphdr *iph);
#endif
#ifdef CONFIG_SYSCTL
@@ -1551,15 +1540,15 @@ static inline char ip_vs_fwd_tag(struct ip_vs_conn *cp)
return fwd;
}
-extern void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
- struct ip_vs_conn *cp, int dir);
+void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp,
+ struct ip_vs_conn *cp, int dir);
#ifdef CONFIG_IP_VS_IPV6
-extern void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
- struct ip_vs_conn *cp, int dir);
+void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
+ struct ip_vs_conn *cp, int dir);
#endif
-extern __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset);
+__sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset);
static inline __wsum ip_vs_check_diff4(__be32 old, __be32 new, __wsum oldsum)
{
@@ -1618,13 +1607,13 @@ static inline int ip_vs_conntrack_enabled(struct netns_ipvs *ipvs)
#endif
}
-extern void ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp,
- int outin);
-extern int ip_vs_confirm_conntrack(struct sk_buff *skb);
-extern void ip_vs_nfct_expect_related(struct sk_buff *skb, struct nf_conn *ct,
- struct ip_vs_conn *cp, u_int8_t proto,
- const __be16 port, int from_rs);
-extern void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp);
+void ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp,
+ int outin);
+int ip_vs_confirm_conntrack(struct sk_buff *skb);
+void ip_vs_nfct_expect_related(struct sk_buff *skb, struct nf_conn *ct,
+ struct ip_vs_conn *cp, u_int8_t proto,
+ const __be16 port, int from_rs);
+void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp);
#else
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index bbf1c8fb8511..fe1c7f6c9217 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -244,14 +244,14 @@ struct ipv6_fl_socklist {
struct rcu_head rcu;
};
-extern struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label);
-extern struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space,
- struct ip6_flowlabel * fl,
- struct ipv6_txoptions * fopt);
-extern void fl6_free_socklist(struct sock *sk);
-extern int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen);
-extern int ip6_flowlabel_init(void);
-extern void ip6_flowlabel_cleanup(void);
+struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label);
+struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions *opt_space,
+ struct ip6_flowlabel *fl,
+ struct ipv6_txoptions *fopt);
+void fl6_free_socklist(struct sock *sk);
+int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen);
+int ip6_flowlabel_init(void);
+void ip6_flowlabel_cleanup(void);
static inline void fl6_sock_release(struct ip6_flowlabel *fl)
{
@@ -259,7 +259,7 @@ static inline void fl6_sock_release(struct ip6_flowlabel *fl)
atomic_dec(&fl->users);
}
-extern void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info);
+void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info);
int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
struct icmp6hdr *thdr, int len);
@@ -267,19 +267,21 @@ int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb,
struct sock *sk, struct flowi6 *fl6);
-extern int ip6_ra_control(struct sock *sk, int sel);
+int ip6_ra_control(struct sock *sk, int sel);
-extern int ipv6_parse_hopopts(struct sk_buff *skb);
+int ipv6_parse_hopopts(struct sk_buff *skb);
-extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
-extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
- int newtype,
- struct ipv6_opt_hdr __user *newopt,
- int newoptlen);
+struct ipv6_txoptions *ipv6_dup_options(struct sock *sk,
+ struct ipv6_txoptions *opt);
+struct ipv6_txoptions *ipv6_renew_options(struct sock *sk,
+ struct ipv6_txoptions *opt,
+ int newtype,
+ struct ipv6_opt_hdr __user *newopt,
+ int newoptlen);
struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
struct ipv6_txoptions *opt);
-extern bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb);
+bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb);
static inline bool ipv6_accept_ra(struct inet6_dev *idev)
{
@@ -306,7 +308,7 @@ static inline int ip6_frag_mem(struct net *net)
#define IPV6_FRAG_LOW_THRESH (3 * 1024*1024) /* 3145728 */
#define IPV6_FRAG_TIMEOUT (60 * HZ) /* 60 seconds */
-extern int __ipv6_addr_type(const struct in6_addr *addr);
+int __ipv6_addr_type(const struct in6_addr *addr);
static inline int ipv6_addr_type(const struct in6_addr *addr)
{
return __ipv6_addr_type(addr) & 0xffff;
@@ -656,9 +658,9 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add
return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
}
-extern void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt);
+void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt);
-extern int ip6_dst_hoplimit(struct dst_entry *dst);
+int ip6_dst_hoplimit(struct dst_entry *dst);
/*
* Header manipulation
@@ -682,83 +684,65 @@ static inline __be32 ip6_flowinfo(const struct ipv6hdr *hdr)
* rcv function (called from netdevice level)
*/
-extern int ipv6_rcv(struct sk_buff *skb,
- struct net_device *dev,
- struct packet_type *pt,
- struct net_device *orig_dev);
+int ipv6_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev);
-extern int ip6_rcv_finish(struct sk_buff *skb);
+int ip6_rcv_finish(struct sk_buff *skb);
/*
* upper-layer output functions
*/
-extern int ip6_xmit(struct sock *sk,
- struct sk_buff *skb,
- struct flowi6 *fl6,
- struct ipv6_txoptions *opt,
- int tclass);
-
-extern int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr);
-
-extern int ip6_append_data(struct sock *sk,
- int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb),
- void *from,
- int length,
- int transhdrlen,
- int hlimit,
- int tclass,
- struct ipv6_txoptions *opt,
- struct flowi6 *fl6,
- struct rt6_info *rt,
- unsigned int flags,
- int dontfrag);
-
-extern int ip6_push_pending_frames(struct sock *sk);
-
-extern void ip6_flush_pending_frames(struct sock *sk);
-
-extern int ip6_dst_lookup(struct sock *sk,
- struct dst_entry **dst,
- struct flowi6 *fl6);
-extern struct dst_entry * ip6_dst_lookup_flow(struct sock *sk,
- struct flowi6 *fl6,
- const struct in6_addr *final_dst,
- bool can_sleep);
-extern struct dst_entry * ip6_sk_dst_lookup_flow(struct sock *sk,
- struct flowi6 *fl6,
- const struct in6_addr *final_dst,
- bool can_sleep);
-extern struct dst_entry * ip6_blackhole_route(struct net *net,
- struct dst_entry *orig_dst);
+int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
+ struct ipv6_txoptions *opt, int tclass);
+
+int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr);
+
+int ip6_append_data(struct sock *sk,
+ int getfrag(void *from, char *to, int offset, int len,
+ int odd, struct sk_buff *skb),
+ void *from, int length, int transhdrlen, int hlimit,
+ int tclass, struct ipv6_txoptions *opt, struct flowi6 *fl6,
+ struct rt6_info *rt, unsigned int flags, int dontfrag);
+
+int ip6_push_pending_frames(struct sock *sk);
+
+void ip6_flush_pending_frames(struct sock *sk);
+
+int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi6 *fl6);
+struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
+ const struct in6_addr *final_dst,
+ bool can_sleep);
+struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
+ const struct in6_addr *final_dst,
+ bool can_sleep);
+struct dst_entry *ip6_blackhole_route(struct net *net,
+ struct dst_entry *orig_dst);
/*
* skb processing functions
*/
-extern int ip6_output(struct sk_buff *skb);
-extern int ip6_forward(struct sk_buff *skb);
-extern int ip6_input(struct sk_buff *skb);
-extern int ip6_mc_input(struct sk_buff *skb);
+int ip6_output(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);
-extern int __ip6_local_out(struct sk_buff *skb);
-extern int ip6_local_out(struct sk_buff *skb);
+int __ip6_local_out(struct sk_buff *skb);
+int ip6_local_out(struct sk_buff *skb);
/*
* Extension header (options) processing
*/
-extern void ipv6_push_nfrag_opts(struct sk_buff *skb,
- struct ipv6_txoptions *opt,
- u8 *proto,
- struct in6_addr **daddr_p);
-extern void ipv6_push_frag_opts(struct sk_buff *skb,
- struct ipv6_txoptions *opt,
- u8 *proto);
+void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
+ u8 *proto, struct in6_addr **daddr_p);
+void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
+ u8 *proto);
-extern int ipv6_skip_exthdr(const struct sk_buff *, int start,
- u8 *nexthdrp, __be16 *frag_offp);
+int ipv6_skip_exthdr(const struct sk_buff *, int start, u8 *nexthdrp,
+ __be16 *frag_offp);
-extern bool ipv6_ext_hdr(u8 nexthdr);
+bool ipv6_ext_hdr(u8 nexthdr);
enum {
IP6_FH_F_FRAG = (1 << 0),
@@ -767,57 +751,44 @@ enum {
};
/* find specified header and get offset to it */
-extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
- int target, unsigned short *fragoff, int *fragflg);
+int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, int target,
+ unsigned short *fragoff, int *fragflg);
-extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
+int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
-extern struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
- const struct ipv6_txoptions *opt,
- struct in6_addr *orig);
+struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
+ const struct ipv6_txoptions *opt,
+ struct in6_addr *orig);
/*
* socket options (ipv6_sockglue.c)
*/
-extern int ipv6_setsockopt(struct sock *sk, int level,
- int optname,
- char __user *optval,
- unsigned int optlen);
-extern int ipv6_getsockopt(struct sock *sk, int level,
- int optname,
- char __user *optval,
- int __user *optlen);
-extern int compat_ipv6_setsockopt(struct sock *sk,
- int level,
- int optname,
- char __user *optval,
- unsigned int optlen);
-extern int compat_ipv6_getsockopt(struct sock *sk,
- int level,
- int optname,
- char __user *optval,
- int __user *optlen);
-
-extern int ip6_datagram_connect(struct sock *sk,
- struct sockaddr *addr, int addr_len);
-
-extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len);
-extern int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len);
-extern void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
- u32 info, u8 *payload);
-extern void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info);
-extern void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu);
-
-extern int inet6_release(struct socket *sock);
-extern int inet6_bind(struct socket *sock, struct sockaddr *uaddr,
- int addr_len);
-extern int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
- int *uaddr_len, int peer);
-extern int inet6_ioctl(struct socket *sock, unsigned int cmd,
- unsigned long arg);
-
-extern int inet6_hash_connect(struct inet_timewait_death_row *death_row,
+int ipv6_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, unsigned int optlen);
+int ipv6_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+int compat_ipv6_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, unsigned int optlen);
+int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+
+int ip6_datagram_connect(struct sock *sk, struct sockaddr *addr, int addr_len);
+
+int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len);
+int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len);
+void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
+ u32 info, u8 *payload);
+void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info);
+void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu);
+
+int inet6_release(struct socket *sock);
+int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len);
+int inet6_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len,
+ int peer);
+int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
+
+int inet6_hash_connect(struct inet_timewait_death_row *death_row,
struct sock *sk);
/*
@@ -829,30 +800,29 @@ extern const struct proto_ops inet6_dgram_ops;
struct group_source_req;
struct group_filter;
-extern int ip6_mc_source(int add, int omode, struct sock *sk,
- struct group_source_req *pgsr);
-extern int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf);
-extern int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
- struct group_filter __user *optval,
- int __user *optlen);
-extern unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr,
- const struct in6_addr *daddr, u32 rnd);
+int ip6_mc_source(int add, int omode, struct sock *sk,
+ struct group_source_req *pgsr);
+int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf);
+int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
+ struct group_filter __user *optval, int __user *optlen);
+unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr,
+ const struct in6_addr *daddr, u32 rnd);
#ifdef CONFIG_PROC_FS
-extern int ac6_proc_init(struct net *net);
-extern void ac6_proc_exit(struct net *net);
-extern int raw6_proc_init(void);
-extern void raw6_proc_exit(void);
-extern int tcp6_proc_init(struct net *net);
-extern void tcp6_proc_exit(struct net *net);
-extern int udp6_proc_init(struct net *net);
-extern void udp6_proc_exit(struct net *net);
-extern int udplite6_proc_init(void);
-extern void udplite6_proc_exit(void);
-extern int ipv6_misc_proc_init(void);
-extern void ipv6_misc_proc_exit(void);
-extern int snmp6_register_dev(struct inet6_dev *idev);
-extern int snmp6_unregister_dev(struct inet6_dev *idev);
+int ac6_proc_init(struct net *net);
+void ac6_proc_exit(struct net *net);
+int raw6_proc_init(void);
+void raw6_proc_exit(void);
+int tcp6_proc_init(struct net *net);
+void tcp6_proc_exit(struct net *net);
+int udp6_proc_init(struct net *net);
+void udp6_proc_exit(struct net *net);
+int udplite6_proc_init(void);
+void udplite6_proc_exit(void);
+int ipv6_misc_proc_init(void);
+void ipv6_misc_proc_exit(void);
+int snmp6_register_dev(struct inet6_dev *idev);
+int snmp6_unregister_dev(struct inet6_dev *idev);
#else
static inline int ac6_proc_init(struct net *net) { return 0; }
@@ -865,10 +835,10 @@ static inline int snmp6_unregister_dev(struct inet6_dev *idev) { return 0; }
extern struct ctl_table ipv6_route_table_template[];
extern struct ctl_table ipv6_icmp_table_template[];
-extern struct ctl_table *ipv6_icmp_sysctl_init(struct net *net);
-extern struct ctl_table *ipv6_route_sysctl_init(struct net *net);
-extern int ipv6_sysctl_register(void);
-extern void ipv6_sysctl_unregister(void);
+struct ctl_table *ipv6_icmp_sysctl_init(struct net *net);
+struct ctl_table *ipv6_route_sysctl_init(struct net *net);
+int ipv6_sysctl_register(void);
+void ipv6_sysctl_unregister(void);
#endif
#endif /* _NET_IPV6_H */
diff --git a/include/net/ipx.h b/include/net/ipx.h
index c1fec6b464cc..9e9e35465baf 100644
--- a/include/net/ipx.h
+++ b/include/net/ipx.h
@@ -123,23 +123,23 @@ extern struct list_head ipx_routes;
extern rwlock_t ipx_routes_lock;
extern struct list_head ipx_interfaces;
-extern struct ipx_interface *ipx_interfaces_head(void);
+struct ipx_interface *ipx_interfaces_head(void);
extern spinlock_t ipx_interfaces_lock;
extern struct ipx_interface *ipx_primary_net;
-extern int ipx_proc_init(void);
-extern void ipx_proc_exit(void);
+int ipx_proc_init(void);
+void ipx_proc_exit(void);
-extern const char *ipx_frame_name(__be16);
-extern const char *ipx_device_name(struct ipx_interface *intrfc);
+const char *ipx_frame_name(__be16);
+const char *ipx_device_name(struct ipx_interface *intrfc);
static __inline__ void ipxitf_hold(struct ipx_interface *intrfc)
{
atomic_inc(&intrfc->refcnt);
}
-extern void ipxitf_down(struct ipx_interface *intrfc);
+void ipxitf_down(struct ipx_interface *intrfc);
static __inline__ void ipxitf_put(struct ipx_interface *intrfc)
{
diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h
index 80ffde3bb164..0224402260a7 100644
--- a/include/net/irda/ircomm_tty.h
+++ b/include/net/irda/ircomm_tty.h
@@ -105,13 +105,13 @@ struct ircomm_tty_cb {
void ircomm_tty_start(struct tty_struct *tty);
void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self);
-extern int ircomm_tty_tiocmget(struct tty_struct *tty);
-extern int ircomm_tty_tiocmset(struct tty_struct *tty,
- unsigned int set, unsigned int clear);
-extern int ircomm_tty_ioctl(struct tty_struct *tty,
- unsigned int cmd, unsigned long arg);
-extern void ircomm_tty_set_termios(struct tty_struct *tty,
- struct ktermios *old_termios);
+int ircomm_tty_tiocmget(struct tty_struct *tty);
+int ircomm_tty_tiocmset(struct tty_struct *tty, unsigned int set,
+ unsigned int clear);
+int ircomm_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
+ unsigned long arg);
+void ircomm_tty_set_termios(struct tty_struct *tty,
+ struct ktermios *old_termios);
#endif
diff --git a/include/net/irda/irda.h b/include/net/irda/irda.h
index 3bed61d379a8..a059465101ff 100644
--- a/include/net/irda/irda.h
+++ b/include/net/irda/irda.h
@@ -112,20 +112,19 @@ do { if(!(expr)) { \
struct net_device;
struct packet_type;
-extern void irda_proc_register(void);
-extern void irda_proc_unregister(void);
+void irda_proc_register(void);
+void irda_proc_unregister(void);
-extern int irda_sysctl_register(void);
-extern void irda_sysctl_unregister(void);
+int irda_sysctl_register(void);
+void irda_sysctl_unregister(void);
-extern int irsock_init(void);
-extern void irsock_cleanup(void);
+int irsock_init(void);
+void irsock_cleanup(void);
-extern int irda_nl_register(void);
-extern void irda_nl_unregister(void);
+int irda_nl_register(void);
+void irda_nl_unregister(void);
-extern int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *ptype,
- struct net_device *orig_dev);
+int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *ptype, struct net_device *orig_dev);
#endif /* NET_IRDA_H */
diff --git a/include/net/irda/irlap_event.h b/include/net/irda/irlap_event.h
index 4c90824c50fb..f9d88da97af2 100644
--- a/include/net/irda/irlap_event.h
+++ b/include/net/irda/irlap_event.h
@@ -126,6 +126,6 @@ void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event,
struct sk_buff *skb, struct irlap_info *info);
void irlap_print_event(IRLAP_EVENT event);
-extern int irlap_qos_negotiate(struct irlap_cb *self, struct sk_buff *skb);
+int irlap_qos_negotiate(struct irlap_cb *self, struct sk_buff *skb);
#endif
diff --git a/include/net/irda/irlap_frame.h b/include/net/irda/irlap_frame.h
index 6b1dc4f8eca5..57173ae398ae 100644
--- a/include/net/irda/irlap_frame.h
+++ b/include/net/irda/irlap_frame.h
@@ -163,7 +163,7 @@ void irlap_resend_rejected_frame(struct irlap_cb *self, int command);
void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
__u8 caddr, int command);
-extern int irlap_insert_qos_negotiation_params(struct irlap_cb *self,
- struct sk_buff *skb);
+int irlap_insert_qos_negotiation_params(struct irlap_cb *self,
+ struct sk_buff *skb);
#endif
diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h
index 5d5a6a4732ef..a830b01baba4 100644
--- a/include/net/iw_handler.h
+++ b/include/net/iw_handler.h
@@ -432,44 +432,32 @@ struct iw_public_data {
/* First : function strictly used inside the kernel */
/* Handle /proc/net/wireless, called in net/code/dev.c */
-extern int dev_get_wireless_info(char * buffer, char **start, off_t offset,
- int length);
+int dev_get_wireless_info(char *buffer, char **start, off_t offset, int length);
/* Second : functions that may be called by driver modules */
/* Send a single event to user space */
-extern void wireless_send_event(struct net_device * dev,
- unsigned int cmd,
- union iwreq_data * wrqu,
- const char * extra);
+void wireless_send_event(struct net_device *dev, unsigned int cmd,
+ union iwreq_data *wrqu, const char *extra);
/* We may need a function to send a stream of events to user space.
* More on that later... */
/* Standard handler for SIOCSIWSPY */
-extern int iw_handler_set_spy(struct net_device * dev,
- struct iw_request_info * info,
- union iwreq_data * wrqu,
- char * extra);
+int iw_handler_set_spy(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
/* Standard handler for SIOCGIWSPY */
-extern int iw_handler_get_spy(struct net_device * dev,
- struct iw_request_info * info,
- union iwreq_data * wrqu,
- char * extra);
+int iw_handler_get_spy(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
/* Standard handler for SIOCSIWTHRSPY */
-extern int iw_handler_set_thrspy(struct net_device * dev,
- struct iw_request_info *info,
- union iwreq_data * wrqu,
- char * extra);
+int iw_handler_set_thrspy(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
/* Standard handler for SIOCGIWTHRSPY */
-extern int iw_handler_get_thrspy(struct net_device * dev,
- struct iw_request_info *info,
- union iwreq_data * wrqu,
- char * extra);
+int iw_handler_get_thrspy(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
/* Driver call to update spy records */
-extern void wireless_spy_update(struct net_device * dev,
- unsigned char * address,
- struct iw_quality * wstats);
+void wireless_spy_update(struct net_device *dev, unsigned char *address,
+ struct iw_quality *wstats);
/************************* INLINE FUNTIONS *************************/
/*
diff --git a/include/net/lapb.h b/include/net/lapb.h
index df892a94f2c6..9510f8725f03 100644
--- a/include/net/lapb.h
+++ b/include/net/lapb.h
@@ -105,40 +105,40 @@ struct lapb_cb {
};
/* lapb_iface.c */
-extern void lapb_connect_confirmation(struct lapb_cb *lapb, int);
-extern void lapb_connect_indication(struct lapb_cb *lapb, int);
-extern void lapb_disconnect_confirmation(struct lapb_cb *lapb, int);
-extern void lapb_disconnect_indication(struct lapb_cb *lapb, int);
-extern int lapb_data_indication(struct lapb_cb *lapb, struct sk_buff *);
-extern int lapb_data_transmit(struct lapb_cb *lapb, struct sk_buff *);
+void lapb_connect_confirmation(struct lapb_cb *lapb, int);
+void lapb_connect_indication(struct lapb_cb *lapb, int);
+void lapb_disconnect_confirmation(struct lapb_cb *lapb, int);
+void lapb_disconnect_indication(struct lapb_cb *lapb, int);
+int lapb_data_indication(struct lapb_cb *lapb, struct sk_buff *);
+int lapb_data_transmit(struct lapb_cb *lapb, struct sk_buff *);
/* lapb_in.c */
-extern void lapb_data_input(struct lapb_cb *lapb, struct sk_buff *);
+void lapb_data_input(struct lapb_cb *lapb, struct sk_buff *);
/* lapb_out.c */
-extern void lapb_kick(struct lapb_cb *lapb);
-extern void lapb_transmit_buffer(struct lapb_cb *lapb, struct sk_buff *, int);
-extern void lapb_establish_data_link(struct lapb_cb *lapb);
-extern void lapb_enquiry_response(struct lapb_cb *lapb);
-extern void lapb_timeout_response(struct lapb_cb *lapb);
-extern void lapb_check_iframes_acked(struct lapb_cb *lapb, unsigned short);
-extern void lapb_check_need_response(struct lapb_cb *lapb, int, int);
+void lapb_kick(struct lapb_cb *lapb);
+void lapb_transmit_buffer(struct lapb_cb *lapb, struct sk_buff *, int);
+void lapb_establish_data_link(struct lapb_cb *lapb);
+void lapb_enquiry_response(struct lapb_cb *lapb);
+void lapb_timeout_response(struct lapb_cb *lapb);
+void lapb_check_iframes_acked(struct lapb_cb *lapb, unsigned short);
+void lapb_check_need_response(struct lapb_cb *lapb, int, int);
/* lapb_subr.c */
-extern void lapb_clear_queues(struct lapb_cb *lapb);
-extern void lapb_frames_acked(struct lapb_cb *lapb, unsigned short);
-extern void lapb_requeue_frames(struct lapb_cb *lapb);
-extern int lapb_validate_nr(struct lapb_cb *lapb, unsigned short);
-extern int lapb_decode(struct lapb_cb *lapb, struct sk_buff *, struct lapb_frame *);
-extern void lapb_send_control(struct lapb_cb *lapb, int, int, int);
-extern void lapb_transmit_frmr(struct lapb_cb *lapb);
+void lapb_clear_queues(struct lapb_cb *lapb);
+void lapb_frames_acked(struct lapb_cb *lapb, unsigned short);
+void lapb_requeue_frames(struct lapb_cb *lapb);
+int lapb_validate_nr(struct lapb_cb *lapb, unsigned short);
+int lapb_decode(struct lapb_cb *lapb, struct sk_buff *, struct lapb_frame *);
+void lapb_send_control(struct lapb_cb *lapb, int, int, int);
+void lapb_transmit_frmr(struct lapb_cb *lapb);
/* lapb_timer.c */
-extern void lapb_start_t1timer(struct lapb_cb *lapb);
-extern void lapb_start_t2timer(struct lapb_cb *lapb);
-extern void lapb_stop_t1timer(struct lapb_cb *lapb);
-extern void lapb_stop_t2timer(struct lapb_cb *lapb);
-extern int lapb_t1timer_running(struct lapb_cb *lapb);
+void lapb_start_t1timer(struct lapb_cb *lapb);
+void lapb_start_t2timer(struct lapb_cb *lapb);
+void lapb_stop_t1timer(struct lapb_cb *lapb);
+void lapb_stop_t2timer(struct lapb_cb *lapb);
+int lapb_t1timer_running(struct lapb_cb *lapb);
/*
* Debug levels.
diff --git a/include/net/llc.h b/include/net/llc.h
index 9e7d7f08ef77..68490cbc8a65 100644
--- a/include/net/llc.h
+++ b/include/net/llc.h
@@ -95,29 +95,29 @@ struct hlist_nulls_head *llc_sk_laddr_hash(struct llc_sap *sap,
extern struct list_head llc_sap_list;
extern spinlock_t llc_sap_list_lock;
-extern int llc_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt, struct net_device *orig_dev);
+int llc_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
+ struct net_device *orig_dev);
-extern int llc_mac_hdr_init(struct sk_buff *skb,
- const unsigned char *sa, const unsigned char *da);
+int llc_mac_hdr_init(struct sk_buff *skb, const unsigned char *sa,
+ const unsigned char *da);
-extern void llc_add_pack(int type, void (*handler)(struct llc_sap *sap,
- struct sk_buff *skb));
-extern void llc_remove_pack(int type);
+void llc_add_pack(int type,
+ void (*handler)(struct llc_sap *sap, struct sk_buff *skb));
+void llc_remove_pack(int type);
-extern void llc_set_station_handler(void (*handler)(struct sk_buff *skb));
+void llc_set_station_handler(void (*handler)(struct sk_buff *skb));
-extern struct llc_sap *llc_sap_open(unsigned char lsap,
- int (*rcv)(struct sk_buff *skb,
- struct net_device *dev,
- struct packet_type *pt,
- struct net_device *orig_dev));
+struct llc_sap *llc_sap_open(unsigned char lsap,
+ int (*rcv)(struct sk_buff *skb,
+ struct net_device *dev,
+ struct packet_type *pt,
+ struct net_device *orig_dev));
static inline void llc_sap_hold(struct llc_sap *sap)
{
atomic_inc(&sap->refcnt);
}
-extern void llc_sap_close(struct llc_sap *sap);
+void llc_sap_close(struct llc_sap *sap);
static inline void llc_sap_put(struct llc_sap *sap)
{
@@ -125,27 +125,27 @@ static inline void llc_sap_put(struct llc_sap *sap)
llc_sap_close(sap);
}
-extern struct llc_sap *llc_sap_find(unsigned char sap_value);
+struct llc_sap *llc_sap_find(unsigned char sap_value);
-extern int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
- unsigned char *dmac, unsigned char dsap);
+int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
+ unsigned char *dmac, unsigned char dsap);
-extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb);
-extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb);
+void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb);
+void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb);
-extern void llc_station_init(void);
-extern void llc_station_exit(void);
+void llc_station_init(void);
+void llc_station_exit(void);
#ifdef CONFIG_PROC_FS
-extern int llc_proc_init(void);
-extern void llc_proc_exit(void);
+int llc_proc_init(void);
+void llc_proc_exit(void);
#else
#define llc_proc_init() (0)
#define llc_proc_exit() do { } while(0)
#endif /* CONFIG_PROC_FS */
#ifdef CONFIG_SYSCTL
-extern int llc_sysctl_init(void);
-extern void llc_sysctl_exit(void);
+int llc_sysctl_init(void);
+void llc_sysctl_exit(void);
extern int sysctl_llc2_ack_timeout;
extern int sysctl_llc2_busy_timeout;
diff --git a/include/net/llc_c_ac.h b/include/net/llc_c_ac.h
index df83f69d2de4..f3be818e73c1 100644
--- a/include/net/llc_c_ac.h
+++ b/include/net/llc_c_ac.h
@@ -89,114 +89,92 @@
typedef int (*llc_conn_action_t)(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ac_clear_remote_busy(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ac_conn_confirm(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_data_ind(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_disc_ind(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_rst_ind(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_rst_confirm(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_clear_remote_busy_if_f_eq_1(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_send_disc_cmd_p_set_x(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_send_dm_rsp_f_set_p(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_send_dm_rsp_f_set_1(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_send_i_cmd_p_set_1(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_send_i_xxx_x_set_0(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_resend_i_xxx_x_set_0(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_resend_i_rsp_f_set_1(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_send_rej_cmd_p_set_1(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_send_rej_rsp_f_set_1(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_send_rej_xxx_x_set_0(struct sock* sk,
+int llc_conn_ac_clear_remote_busy(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_conn_confirm(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_data_ind(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_rst_confirm(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_clear_remote_busy_if_f_eq_1(struct sock *sk,
struct sk_buff *skb);
-extern int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_set_remote_busy(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock* sk,
+int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock *sk,
+ struct sk_buff *skb);
+int llc_conn_ac_send_disc_cmd_p_set_x(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_dm_rsp_f_set_p(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_dm_rsp_f_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_i_cmd_p_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_resend_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk,
struct sk_buff *skb);
-extern int llc_conn_ac_send_rr_cmd_p_set_1(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_send_rr_rsp_f_set_1(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_send_ack_rsp_f_set_1(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_send_rr_xxx_x_set_0(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_send_ack_xxx_x_set_0(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_send_ua_rsp_f_set_p(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_set_s_flag_0(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_set_s_flag_1(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_start_p_timer(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_start_ack_timer(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_start_rej_timer(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_start_ack_tmr_if_not_running(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_stop_ack_timer(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_stop_p_timer(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_stop_rej_timer(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_stop_all_timers(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_stop_other_timers(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_upd_nr_received(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_inc_tx_win_size(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_dec_tx_win_size(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_upd_p_flag(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_set_data_flag_2(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_set_data_flag_0(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_set_data_flag_1(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_set_data_flag_1_if_data_flag_eq_0(struct sock* sk,
- struct sk_buff *skb);
-extern int llc_conn_ac_set_p_flag_0(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_set_remote_busy_0(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_set_retry_cnt_0(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_set_cause_flag_0(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_set_cause_flag_1(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_inc_retry_cnt_by_1(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_set_vr_0(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_inc_vr_by_1(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_set_vs_0(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_set_vs_nr(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_rst_vs(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_upd_vs(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_disc(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_reset(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_disc_confirm(struct sock* sk, struct sk_buff *skb);
-extern u8 llc_circular_between(u8 a, u8 b, u8 c);
-extern int llc_conn_ac_send_ack_if_needed(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_adjust_npta_by_rr(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_adjust_npta_by_rnr(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_rst_sendack_flag(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_send_i_rsp_as_ack(struct sock* sk, struct sk_buff *skb);
-extern int llc_conn_ac_send_i_as_ack(struct sock* sk, struct sk_buff *skb);
+int llc_conn_ac_resend_i_rsp_f_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_rej_cmd_p_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_rej_rsp_f_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_rej_xxx_x_set_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_rr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_rr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_ack_rsp_f_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_rr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_set_s_flag_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_set_s_flag_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_start_p_timer(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_start_ack_timer(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_start_rej_timer(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk,
+ struct sk_buff *skb);
+int llc_conn_ac_stop_ack_timer(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_stop_p_timer(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_stop_rej_timer(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_stop_all_timers(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_stop_other_timers(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_upd_nr_received(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_inc_tx_win_size(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_dec_tx_win_size(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_upd_p_flag(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_set_data_flag_2(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_set_data_flag_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_set_data_flag_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_set_data_flag_1_if_data_flag_eq_0(struct sock *sk,
+ struct sk_buff *skb);
+int llc_conn_ac_set_p_flag_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_set_remote_busy_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_set_retry_cnt_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_set_cause_flag_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_set_cause_flag_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_inc_retry_cnt_by_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_set_vr_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_inc_vr_by_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_set_vs_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_set_vs_nr(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_rst_vs(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_upd_vs(struct sock *sk, struct sk_buff *skb);
+int llc_conn_disc(struct sock *sk, struct sk_buff *skb);
+int llc_conn_reset(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_disc_confirm(struct sock *sk, struct sk_buff *skb);
+u8 llc_circular_between(u8 a, u8 b, u8 c);
+int llc_conn_ac_send_ack_if_needed(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_adjust_npta_by_rr(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_adjust_npta_by_rnr(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_rst_sendack_flag(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_i_rsp_as_ack(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ac_send_i_as_ack(struct sock *sk, struct sk_buff *skb);
-extern void llc_conn_busy_tmr_cb(unsigned long timeout_data);
-extern void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data);
-extern void llc_conn_ack_tmr_cb(unsigned long timeout_data);
-extern void llc_conn_rej_tmr_cb(unsigned long timeout_data);
+void llc_conn_busy_tmr_cb(unsigned long timeout_data);
+void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data);
+void llc_conn_ack_tmr_cb(unsigned long timeout_data);
+void llc_conn_rej_tmr_cb(unsigned long timeout_data);
-extern void llc_conn_set_p_flag(struct sock *sk, u8 value);
+void llc_conn_set_p_flag(struct sock *sk, u8 value);
#endif /* LLC_C_AC_H */
diff --git a/include/net/llc_c_ev.h b/include/net/llc_c_ev.h
index 6ca3113df39e..3948cf111dd0 100644
--- a/include/net/llc_c_ev.h
+++ b/include/net/llc_c_ev.h
@@ -128,138 +128,93 @@ static __inline__ struct llc_conn_state_ev *llc_conn_ev(struct sk_buff *skb)
typedef int (*llc_conn_ev_t)(struct sock *sk, struct sk_buff *skb);
typedef int (*llc_conn_ev_qfyr_t)(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_local_busy_detected(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_local_busy_cleared(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk,
+int llc_conn_ev_conn_req(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_local_busy_cleared(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk,
+ struct sk_buff *skb);
+int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk,
struct sk_buff *skb);
-extern int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk,
+int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk,
+ struct sk_buff *skb);
+int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_ua_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk,
struct sk_buff *skb);
-extern int llc_conn_ev_rx_ua_rsp_fbit_set_x(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_p_tmr_exp(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_ack_tmr_exp(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_rej_tmr_exp(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_busy_tmr_exp(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_sendack_tmr_exp(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk,
+ struct sk_buff *skb);
+int llc_conn_ev_p_tmr_exp(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_ack_tmr_exp(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rej_tmr_exp(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_busy_tmr_exp(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_sendack_tmr_exp(struct sock *sk, struct sk_buff *skb);
/* NOT_USED functions and their variations */
-extern int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_xxx_rsp_fbit_set_1(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_rx_any_frame(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_tx_buffer_full(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_init_p_f_cycle(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_xxx_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk,
+ struct sk_buff *skb);
+int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk,
+ struct sk_buff *skb);
+int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk,
+ struct sk_buff *skb);
+int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk,
+ struct sk_buff *skb);
+int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_rx_any_frame(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_tx_buffer_full(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_init_p_f_cycle(struct sock *sk, struct sk_buff *skb);
/* Available connection action qualifiers */
-extern int llc_conn_ev_qlfy_data_flag_eq_1(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_data_flag_eq_0(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_data_flag_eq_2(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_p_flag_eq_1(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_last_frame_eq_1(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_last_frame_eq_0(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_p_flag_eq_0(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_p_flag_eq_f(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_remote_busy_eq_0(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_remote_busy_eq_1(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_retry_cnt_lt_n2(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_retry_cnt_gte_n2(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_s_flag_eq_1(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_s_flag_eq_0(struct sock *sk, struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_cause_flag_eq_1(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_cause_flag_eq_0(struct sock *sk,
+int llc_conn_ev_qlfy_data_flag_eq_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_data_flag_eq_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_data_flag_eq_2(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_p_flag_eq_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_last_frame_eq_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_last_frame_eq_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_p_flag_eq_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_p_flag_eq_f(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_remote_busy_eq_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_remote_busy_eq_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_retry_cnt_lt_n2(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_retry_cnt_gte_n2(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_s_flag_eq_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_s_flag_eq_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_cause_flag_eq_1(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_cause_flag_eq_0(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_set_status_conn(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_set_status_disc(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_set_status_failed(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_set_status_remote_busy(struct sock *sk,
struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_set_status_conn(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_set_status_disc(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_set_status_failed(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_set_status_remote_busy(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_set_status_refuse(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_set_status_conflict(struct sock *sk,
- struct sk_buff *skb);
-extern int llc_conn_ev_qlfy_set_status_rst_done(struct sock *sk,
- struct sk_buff *skb);
+int llc_conn_ev_qlfy_set_status_refuse(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_set_status_conflict(struct sock *sk, struct sk_buff *skb);
+int llc_conn_ev_qlfy_set_status_rst_done(struct sock *sk, struct sk_buff *skb);
static __inline__ int llc_conn_space(struct sock *sk, struct sk_buff *skb)
{
diff --git a/include/net/llc_conn.h b/include/net/llc_conn.h
index 2f97d8ddce92..0134681acc4c 100644
--- a/include/net/llc_conn.h
+++ b/include/net/llc_conn.h
@@ -95,28 +95,24 @@ static __inline__ char llc_backlog_type(struct sk_buff *skb)
return skb->cb[sizeof(skb->cb) - 1];
}
-extern struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority,
- struct proto *prot);
-extern void llc_sk_free(struct sock *sk);
+struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority,
+ struct proto *prot);
+void llc_sk_free(struct sock *sk);
-extern void llc_sk_reset(struct sock *sk);
+void llc_sk_reset(struct sock *sk);
/* Access to a connection */
-extern int llc_conn_state_process(struct sock *sk, struct sk_buff *skb);
-extern void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb);
-extern void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb);
-extern void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr,
- u8 first_p_bit);
-extern void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr,
- u8 first_f_bit);
-extern int llc_conn_remove_acked_pdus(struct sock *conn, u8 nr,
- u16 *how_many_unacked);
-extern struct sock *llc_lookup_established(struct llc_sap *sap,
- struct llc_addr *daddr,
- struct llc_addr *laddr);
-extern void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk);
-extern void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk);
+int llc_conn_state_process(struct sock *sk, struct sk_buff *skb);
+void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb);
+void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb);
+void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit);
+void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit);
+int llc_conn_remove_acked_pdus(struct sock *conn, u8 nr, u16 *how_many_unacked);
+struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,
+ struct llc_addr *laddr);
+void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk);
+void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk);
-extern u8 llc_data_accept_state(u8 state);
-extern void llc_build_offset_table(void);
+u8 llc_data_accept_state(u8 state);
+void llc_build_offset_table(void);
#endif /* LLC_CONN_H */
diff --git a/include/net/llc_if.h b/include/net/llc_if.h
index f0cb909b60eb..8d5c543cd620 100644
--- a/include/net/llc_if.h
+++ b/include/net/llc_if.h
@@ -62,8 +62,7 @@
#define LLC_STATUS_CONFLICT 7 /* disconnect conn */
#define LLC_STATUS_RESET_DONE 8 /* */
-extern int llc_establish_connection(struct sock *sk, u8 *lmac,
- u8 *dmac, u8 dsap);
-extern int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb);
-extern int llc_send_disc(struct sock *sk);
+int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap);
+int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb);
+int llc_send_disc(struct sock *sk);
#endif /* LLC_IF_H */
diff --git a/include/net/llc_pdu.h b/include/net/llc_pdu.h
index 5a93d13ac95c..31e2de7d57c5 100644
--- a/include/net/llc_pdu.h
+++ b/include/net/llc_pdu.h
@@ -410,21 +410,20 @@ struct llc_frmr_info {
u8 ind_bits; /* indicator bits set with macro */
} __packed;
-extern void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 type);
-extern void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value);
-extern void llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit);
-extern void llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit);
-extern void llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr);
-extern void llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr);
-extern void llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr);
-extern void llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr);
-extern void llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit);
-extern void llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit);
-extern void llc_pdu_init_as_frmr_rsp(struct sk_buff *skb,
- struct llc_pdu_sn *prev_pdu,
- u8 f_bit, u8 vs, u8 vr, u8 vzyxw);
-extern void llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr);
-extern void llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr);
-extern void llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr);
-extern void llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit);
+void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 type);
+void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value);
+void llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit);
+void llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit);
+void llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr);
+void llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr);
+void llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr);
+void llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr);
+void llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit);
+void llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit);
+void llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, struct llc_pdu_sn *prev_pdu,
+ u8 f_bit, u8 vs, u8 vr, u8 vzyxw);
+void llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr);
+void llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr);
+void llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr);
+void llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit);
#endif /* LLC_PDU_H */
diff --git a/include/net/llc_s_ac.h b/include/net/llc_s_ac.h
index 37a3bbd02394..a61b98c108ee 100644
--- a/include/net/llc_s_ac.h
+++ b/include/net/llc_s_ac.h
@@ -25,15 +25,13 @@
/* All action functions must look like this */
typedef int (*llc_sap_action_t)(struct llc_sap *sap, struct sk_buff *skb);
-extern int llc_sap_action_unitdata_ind(struct llc_sap *sap,
- struct sk_buff *skb);
-extern int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb);
-extern int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb);
-extern int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb);
-extern int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb);
-extern int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb);
-extern int llc_sap_action_report_status(struct llc_sap *sap,
- struct sk_buff *skb);
-extern int llc_sap_action_xid_ind(struct llc_sap *sap, struct sk_buff *skb);
-extern int llc_sap_action_test_ind(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_action_unitdata_ind(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_action_report_status(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_action_xid_ind(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_action_test_ind(struct llc_sap *sap, struct sk_buff *skb);
#endif /* LLC_S_AC_H */
diff --git a/include/net/llc_s_ev.h b/include/net/llc_s_ev.h
index e3acb9329e4a..84db3a59ed28 100644
--- a/include/net/llc_s_ev.h
+++ b/include/net/llc_s_ev.h
@@ -53,15 +53,14 @@ struct llc_sap;
typedef int (*llc_sap_ev_t)(struct llc_sap *sap, struct sk_buff *skb);
-extern int llc_sap_ev_activation_req(struct llc_sap *sap, struct sk_buff *skb);
-extern int llc_sap_ev_rx_ui(struct llc_sap *sap, struct sk_buff *skb);
-extern int llc_sap_ev_unitdata_req(struct llc_sap *sap, struct sk_buff *skb);
-extern int llc_sap_ev_xid_req(struct llc_sap *sap, struct sk_buff *skb);
-extern int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct sk_buff *skb);
-extern int llc_sap_ev_rx_xid_r(struct llc_sap *sap, struct sk_buff *skb);
-extern int llc_sap_ev_test_req(struct llc_sap *sap, struct sk_buff *skb);
-extern int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct sk_buff *skb);
-extern int llc_sap_ev_rx_test_r(struct llc_sap *sap, struct sk_buff *skb);
-extern int llc_sap_ev_deactivation_req(struct llc_sap *sap,
- struct sk_buff *skb);
+int llc_sap_ev_activation_req(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_ev_rx_ui(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_ev_unitdata_req(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_ev_xid_req(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_ev_rx_xid_r(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_ev_test_req(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_ev_rx_test_r(struct llc_sap *sap, struct sk_buff *skb);
+int llc_sap_ev_deactivation_req(struct llc_sap *sap, struct sk_buff *skb);
#endif /* LLC_S_EV_H */
diff --git a/include/net/llc_sap.h b/include/net/llc_sap.h
index ed25bec2f648..1e4df9fd9fb2 100644
--- a/include/net/llc_sap.h
+++ b/include/net/llc_sap.h
@@ -19,18 +19,14 @@ struct net_device;
struct sk_buff;
struct sock;
-extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb);
-extern void llc_save_primitive(struct sock *sk, struct sk_buff* skb,
- unsigned char prim);
-extern struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev,
- u8 type, u32 data_size);
+void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb);
+void llc_save_primitive(struct sock *sk, struct sk_buff *skb,
+ unsigned char prim);
+struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev,
+ u8 type, u32 data_size);
-extern void llc_build_and_send_test_pkt(struct llc_sap *sap,
- struct sk_buff *skb,
- unsigned char *dmac,
- unsigned char dsap);
-extern void llc_build_and_send_xid_pkt(struct llc_sap *sap,
- struct sk_buff *skb,
- unsigned char *dmac,
- unsigned char dsap);
+void llc_build_and_send_test_pkt(struct llc_sap *sap, struct sk_buff *skb,
+ unsigned char *dmac, unsigned char dsap);
+void llc_build_and_send_xid_pkt(struct llc_sap *sap, struct sk_buff *skb,
+ unsigned char *dmac, unsigned char dsap);
#endif /* LLC_SAP_H */
diff --git a/include/net/mrp.h b/include/net/mrp.h
index 4fbf02aa2ec1..31912c3be772 100644
--- a/include/net/mrp.h
+++ b/include/net/mrp.h
@@ -112,6 +112,7 @@ struct mrp_applicant {
struct mrp_application *app;
struct net_device *dev;
struct timer_list join_timer;
+ struct timer_list periodic_timer;
spinlock_t lock;
struct sk_buff_head queue;
@@ -125,19 +126,17 @@ struct mrp_port {
struct rcu_head rcu;
};
-extern int mrp_register_application(struct mrp_application *app);
-extern void mrp_unregister_application(struct mrp_application *app);
+int mrp_register_application(struct mrp_application *app);
+void mrp_unregister_application(struct mrp_application *app);
-extern int mrp_init_applicant(struct net_device *dev,
- struct mrp_application *app);
-extern void mrp_uninit_applicant(struct net_device *dev,
- struct mrp_application *app);
+int mrp_init_applicant(struct net_device *dev, struct mrp_application *app);
+void mrp_uninit_applicant(struct net_device *dev, struct mrp_application *app);
-extern int mrp_request_join(const struct net_device *dev,
- const struct mrp_application *app,
- const void *value, u8 len, u8 type);
-extern void mrp_request_leave(const struct net_device *dev,
- const struct mrp_application *app,
- const void *value, u8 len, u8 type);
+int mrp_request_join(const struct net_device *dev,
+ const struct mrp_application *app,
+ const void *value, u8 len, u8 type);
+void mrp_request_leave(const struct net_device *dev,
+ const struct mrp_application *app,
+ const void *value, u8 len, u8 type);
#endif /* _NET_MRP_H */
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index ea0cc26ab70e..6bbda34d5e59 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -110,8 +110,8 @@ struct ndisc_options {
#define NDISC_OPT_SPACE(len) (((len)+2+7)&~7)
-extern struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
- struct ndisc_options *ndopts);
+struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
+ struct ndisc_options *ndopts);
/*
* Return the padding between the option length and the start of the
@@ -189,60 +189,51 @@ static inline struct neighbour *__ipv6_neigh_lookup(struct net_device *dev, cons
return n;
}
-extern int ndisc_init(void);
-extern int ndisc_late_init(void);
+int ndisc_init(void);
+int ndisc_late_init(void);
-extern void ndisc_late_cleanup(void);
-extern void ndisc_cleanup(void);
+void ndisc_late_cleanup(void);
+void ndisc_cleanup(void);
-extern int ndisc_rcv(struct sk_buff *skb);
+int ndisc_rcv(struct sk_buff *skb);
-extern void ndisc_send_ns(struct net_device *dev,
- struct neighbour *neigh,
- const struct in6_addr *solicit,
- const struct in6_addr *daddr,
- const struct in6_addr *saddr);
+void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
+ const struct in6_addr *solicit,
+ const struct in6_addr *daddr, const struct in6_addr *saddr);
-extern void ndisc_send_rs(struct net_device *dev,
- const struct in6_addr *saddr,
- const struct in6_addr *daddr);
-extern void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
- const struct in6_addr *daddr,
- const struct in6_addr *solicited_addr,
- bool router, bool solicited, bool override,
- bool inc_opt);
+void ndisc_send_rs(struct net_device *dev,
+ const struct in6_addr *saddr, const struct in6_addr *daddr);
+void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
+ const struct in6_addr *daddr,
+ const struct in6_addr *solicited_addr,
+ bool router, bool solicited, bool override, bool inc_opt);
-extern void ndisc_send_redirect(struct sk_buff *skb,
- const struct in6_addr *target);
+void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target);
-extern int ndisc_mc_map(const struct in6_addr *addr, char *buf,
- struct net_device *dev, int dir);
+int ndisc_mc_map(const struct in6_addr *addr, char *buf, struct net_device *dev,
+ int dir);
/*
* IGMP
*/
-extern int igmp6_init(void);
+int igmp6_init(void);
-extern void igmp6_cleanup(void);
+void igmp6_cleanup(void);
-extern int igmp6_event_query(struct sk_buff *skb);
+int igmp6_event_query(struct sk_buff *skb);
-extern int igmp6_event_report(struct sk_buff *skb);
+int igmp6_event_report(struct sk_buff *skb);
#ifdef CONFIG_SYSCTL
-extern int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl,
- int write,
- void __user *buffer,
- size_t *lenp,
- loff_t *ppos);
+int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos);
int ndisc_ifinfo_sysctl_strategy(struct ctl_table *ctl,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen);
#endif
-extern void inet6_ifinfo_notify(int event,
- struct inet6_dev *idev);
+void inet6_ifinfo_notify(int event, struct inet6_dev *idev);
#endif
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 1313456a0994..38c2afb585de 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -136,8 +136,8 @@ struct net {
extern struct net init_net;
#ifdef CONFIG_NET_NS
-extern struct net *copy_net_ns(unsigned long flags,
- struct user_namespace *user_ns, struct net *old_net);
+struct net *copy_net_ns(unsigned long flags, struct user_namespace *user_ns,
+ struct net *old_net);
#else /* CONFIG_NET_NS */
#include <linux/sched.h>
@@ -154,11 +154,11 @@ static inline struct net *copy_net_ns(unsigned long flags,
extern struct list_head net_namespace_list;
-extern struct net *get_net_ns_by_pid(pid_t pid);
-extern struct net *get_net_ns_by_fd(int pid);
+struct net *get_net_ns_by_pid(pid_t pid);
+struct net *get_net_ns_by_fd(int pid);
#ifdef CONFIG_NET_NS
-extern void __put_net(struct net *net);
+void __put_net(struct net *net);
static inline struct net *get_net(struct net *net)
{
@@ -190,7 +190,7 @@ int net_eq(const struct net *net1, const struct net *net2)
return net1 == net2;
}
-extern void net_drop_ns(void *);
+void net_drop_ns(void *);
#else
@@ -307,19 +307,19 @@ struct pernet_operations {
* device which caused kernel oops, and panics during network
* namespace cleanup. So please don't get this wrong.
*/
-extern int register_pernet_subsys(struct pernet_operations *);
-extern void unregister_pernet_subsys(struct pernet_operations *);
-extern int register_pernet_device(struct pernet_operations *);
-extern void unregister_pernet_device(struct pernet_operations *);
+int register_pernet_subsys(struct pernet_operations *);
+void unregister_pernet_subsys(struct pernet_operations *);
+int register_pernet_device(struct pernet_operations *);
+void unregister_pernet_device(struct pernet_operations *);
struct ctl_table;
struct ctl_table_header;
#ifdef CONFIG_SYSCTL
-extern int net_sysctl_init(void);
-extern struct ctl_table_header *register_net_sysctl(struct net *net,
- const char *path, struct ctl_table *table);
-extern void unregister_net_sysctl_table(struct ctl_table_header *header);
+int net_sysctl_init(void);
+struct ctl_table_header *register_net_sysctl(struct net *net, const char *path,
+ struct ctl_table *table);
+void unregister_net_sysctl_table(struct ctl_table_header *header);
#else
static inline int net_sysctl_init(void) { return 0; }
static inline struct ctl_table_header *register_net_sysctl(struct net *net,
diff --git a/include/net/netevent.h b/include/net/netevent.h
index fe630dde35c3..d8bbb38584b6 100644
--- a/include/net/netevent.h
+++ b/include/net/netevent.h
@@ -26,8 +26,8 @@ enum netevent_notif_type {
NETEVENT_REDIRECT, /* arg is struct netevent_redirect ptr */
};
-extern int register_netevent_notifier(struct notifier_block *nb);
-extern int unregister_netevent_notifier(struct notifier_block *nb);
-extern int call_netevent_notifiers(unsigned long val, void *v);
+int register_netevent_notifier(struct notifier_block *nb);
+int unregister_netevent_notifier(struct notifier_block *nb);
+int call_netevent_notifiers(unsigned long val, void *v);
#endif
diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
index 7573d52a4346..6c3d12e2949f 100644
--- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
+++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
@@ -16,9 +16,9 @@ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4;
extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp;
-extern int nf_conntrack_ipv4_compat_init(void);
-extern void nf_conntrack_ipv4_compat_fini(void);
+int nf_conntrack_ipv4_compat_init(void);
+void nf_conntrack_ipv4_compat_fini(void);
-extern void need_ipv4_conntrack(void);
+void need_ipv4_conntrack(void);
#endif /*_NF_CONNTRACK_IPV4_H*/
diff --git a/include/net/netfilter/ipv4/nf_defrag_ipv4.h b/include/net/netfilter/ipv4/nf_defrag_ipv4.h
index 6b00ea38546b..f01ef208dff6 100644
--- a/include/net/netfilter/ipv4/nf_defrag_ipv4.h
+++ b/include/net/netfilter/ipv4/nf_defrag_ipv4.h
@@ -1,6 +1,6 @@
#ifndef _NF_DEFRAG_IPV4_H
#define _NF_DEFRAG_IPV4_H
-extern void nf_defrag_ipv4_enable(void);
+void nf_defrag_ipv4_enable(void);
#endif /* _NF_DEFRAG_IPV4_H */
diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
index fd79c9a1779d..5613412e7dc2 100644
--- a/include/net/netfilter/ipv6/nf_defrag_ipv6.h
+++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
@@ -1,15 +1,14 @@
#ifndef _NF_DEFRAG_IPV6_H
#define _NF_DEFRAG_IPV6_H
-extern void nf_defrag_ipv6_enable(void);
-
-extern int nf_ct_frag6_init(void);
-extern void nf_ct_frag6_cleanup(void);
-extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
-extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
- struct net_device *in,
- struct net_device *out,
- int (*okfn)(struct sk_buff *));
+void nf_defrag_ipv6_enable(void);
+
+int nf_ct_frag6_init(void);
+void nf_ct_frag6_cleanup(void);
+struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
+void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
+ struct net_device *in, struct net_device *out,
+ int (*okfn)(struct sk_buff *));
struct inet_frags_ctl;
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 0c1288a50e8b..01ea6eed1bb1 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -139,15 +139,13 @@ static inline struct net *nf_ct_net(const struct nf_conn *ct)
}
/* Alter reply tuple (maybe alter helper). */
-extern void
-nf_conntrack_alter_reply(struct nf_conn *ct,
- const struct nf_conntrack_tuple *newreply);
+void nf_conntrack_alter_reply(struct nf_conn *ct,
+ const struct nf_conntrack_tuple *newreply);
/* Is this tuple taken? (ignoring any belonging to the given
conntrack). */
-extern int
-nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
- const struct nf_conn *ignored_conntrack);
+int nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
+ const struct nf_conn *ignored_conntrack);
/* Return conntrack_info and tuple hash for given skb. */
static inline struct nf_conn *
@@ -165,37 +163,34 @@ static inline void nf_ct_put(struct nf_conn *ct)
}
/* Protocol module loading */
-extern int nf_ct_l3proto_try_module_get(unsigned short l3proto);
-extern void nf_ct_l3proto_module_put(unsigned short l3proto);
+int nf_ct_l3proto_try_module_get(unsigned short l3proto);
+void nf_ct_l3proto_module_put(unsigned short l3proto);
/*
* Allocate a hashtable of hlist_head (if nulls == 0),
* or hlist_nulls_head (if nulls == 1)
*/
-extern void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls);
+void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls);
-extern void nf_ct_free_hashtable(void *hash, unsigned int size);
+void nf_ct_free_hashtable(void *hash, unsigned int size);
-extern struct nf_conntrack_tuple_hash *
+struct nf_conntrack_tuple_hash *
__nf_conntrack_find(struct net *net, u16 zone,
const struct nf_conntrack_tuple *tuple);
-extern int nf_conntrack_hash_check_insert(struct nf_conn *ct);
+int nf_conntrack_hash_check_insert(struct nf_conn *ct);
bool nf_ct_delete(struct nf_conn *ct, u32 pid, int report);
-extern void nf_conntrack_flush_report(struct net *net, u32 portid, int report);
+void nf_conntrack_flush_report(struct net *net, u32 portid, int report);
-extern bool nf_ct_get_tuplepr(const struct sk_buff *skb,
- unsigned int nhoff, u_int16_t l3num,
- struct nf_conntrack_tuple *tuple);
-extern bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
- const struct nf_conntrack_tuple *orig);
+bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff,
+ u_int16_t l3num, struct nf_conntrack_tuple *tuple);
+bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
+ const struct nf_conntrack_tuple *orig);
-extern void __nf_ct_refresh_acct(struct nf_conn *ct,
- enum ip_conntrack_info ctinfo,
- const struct sk_buff *skb,
- unsigned long extra_jiffies,
- int do_acct);
+void __nf_ct_refresh_acct(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
+ const struct sk_buff *skb,
+ unsigned long extra_jiffies, int do_acct);
/* Refresh conntrack for this many jiffies and do accounting */
static inline void nf_ct_refresh_acct(struct nf_conn *ct,
@@ -214,10 +209,8 @@ static inline void nf_ct_refresh(struct nf_conn *ct,
__nf_ct_refresh_acct(ct, 0, skb, extra_jiffies, 0);
}
-extern bool __nf_ct_kill_acct(struct nf_conn *ct,
- enum ip_conntrack_info ctinfo,
- const struct sk_buff *skb,
- int do_acct);
+bool __nf_ct_kill_acct(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
+ const struct sk_buff *skb, int do_acct);
/* kill conntrack and do accounting */
static inline bool nf_ct_kill_acct(struct nf_conn *ct,
@@ -244,19 +237,17 @@ static inline struct nf_conn *nf_ct_untracked_get(void)
{
return &__raw_get_cpu_var(nf_conntrack_untracked);
}
-extern void nf_ct_untracked_status_or(unsigned long bits);
+void nf_ct_untracked_status_or(unsigned long bits);
/* Iterate over all conntracks: if iter returns true, it's deleted. */
-extern void
-nf_ct_iterate_cleanup(struct net *net,
- int (*iter)(struct nf_conn *i, void *data),
- void *data, u32 portid, int report);
-extern void nf_conntrack_free(struct nf_conn *ct);
-extern struct nf_conn *
-nf_conntrack_alloc(struct net *net, u16 zone,
- const struct nf_conntrack_tuple *orig,
- const struct nf_conntrack_tuple *repl,
- gfp_t gfp);
+void nf_ct_iterate_cleanup(struct net *net,
+ int (*iter)(struct nf_conn *i, void *data),
+ void *data, u32 portid, int report);
+void nf_conntrack_free(struct nf_conn *ct);
+struct nf_conn *nf_conntrack_alloc(struct net *net, u16 zone,
+ const struct nf_conntrack_tuple *orig,
+ const struct nf_conntrack_tuple *repl,
+ gfp_t gfp);
static inline int nf_ct_is_template(const struct nf_conn *ct)
{
@@ -287,7 +278,7 @@ static inline bool nf_is_loopback_packet(const struct sk_buff *skb)
struct kernel_param;
-extern int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp);
+int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp);
extern unsigned int nf_conntrack_htable_size;
extern unsigned int nf_conntrack_max;
extern unsigned int nf_conntrack_hash_rnd;
diff --git a/include/net/netfilter/nf_conntrack_acct.h b/include/net/netfilter/nf_conntrack_acct.h
index 2bdb7a15fe06..fef44edf49c1 100644
--- a/include/net/netfilter/nf_conntrack_acct.h
+++ b/include/net/netfilter/nf_conntrack_acct.h
@@ -42,8 +42,8 @@ struct nf_conn_counter *nf_ct_acct_ext_add(struct nf_conn *ct, gfp_t gfp)
return acct;
};
-extern unsigned int
-seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir);
+unsigned int seq_print_acct(struct seq_file *s, const struct nf_conn *ct,
+ int dir);
/* Check if connection tracking accounting is enabled */
static inline bool nf_ct_acct_enabled(struct net *net)
@@ -57,9 +57,9 @@ static inline void nf_ct_set_acct(struct net *net, bool enable)
net->ct.sysctl_acct = enable;
}
-extern int nf_conntrack_acct_pernet_init(struct net *net);
-extern void nf_conntrack_acct_pernet_fini(struct net *net);
+int nf_conntrack_acct_pernet_init(struct net *net);
+void nf_conntrack_acct_pernet_fini(struct net *net);
-extern int nf_conntrack_acct_init(void);
-extern void nf_conntrack_acct_fini(void);
+int nf_conntrack_acct_init(void);
+void nf_conntrack_acct_fini(void);
#endif /* _NF_CONNTRACK_ACCT_H */
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index fb2b6234e937..15308b8eb5b5 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -20,49 +20,42 @@
/* This header is used to share core functionality between the
standalone connection tracking module, and the compatibility layer's use
of connection tracking. */
-extern unsigned int nf_conntrack_in(struct net *net,
- u_int8_t pf,
- unsigned int hooknum,
- struct sk_buff *skb);
-
-extern int nf_conntrack_init_net(struct net *net);
-extern void nf_conntrack_cleanup_net(struct net *net);
-extern void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list);
-
-extern int nf_conntrack_proto_pernet_init(struct net *net);
-extern void nf_conntrack_proto_pernet_fini(struct net *net);
-
-extern int nf_conntrack_proto_init(void);
-extern void nf_conntrack_proto_fini(void);
-
-extern int nf_conntrack_init_start(void);
-extern void nf_conntrack_cleanup_start(void);
-
-extern void nf_conntrack_init_end(void);
-extern void nf_conntrack_cleanup_end(void);
-
-extern bool
-nf_ct_get_tuple(const struct sk_buff *skb,
- unsigned int nhoff,
- unsigned int dataoff,
- u_int16_t l3num,
- u_int8_t protonum,
- struct nf_conntrack_tuple *tuple,
- const struct nf_conntrack_l3proto *l3proto,
- const struct nf_conntrack_l4proto *l4proto);
-
-extern bool
-nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
- const struct nf_conntrack_tuple *orig,
- const struct nf_conntrack_l3proto *l3proto,
- const struct nf_conntrack_l4proto *l4proto);
+unsigned int nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
+ struct sk_buff *skb);
+
+int nf_conntrack_init_net(struct net *net);
+void nf_conntrack_cleanup_net(struct net *net);
+void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list);
+
+int nf_conntrack_proto_pernet_init(struct net *net);
+void nf_conntrack_proto_pernet_fini(struct net *net);
+
+int nf_conntrack_proto_init(void);
+void nf_conntrack_proto_fini(void);
+
+int nf_conntrack_init_start(void);
+void nf_conntrack_cleanup_start(void);
+
+void nf_conntrack_init_end(void);
+void nf_conntrack_cleanup_end(void);
+
+bool nf_ct_get_tuple(const struct sk_buff *skb, unsigned int nhoff,
+ unsigned int dataoff, u_int16_t l3num, u_int8_t protonum,
+ struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_l3proto *l3proto,
+ const struct nf_conntrack_l4proto *l4proto);
+
+bool nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
+ const struct nf_conntrack_tuple *orig,
+ const struct nf_conntrack_l3proto *l3proto,
+ const struct nf_conntrack_l4proto *l4proto);
/* Find a connection corresponding to a tuple. */
-extern struct nf_conntrack_tuple_hash *
+struct nf_conntrack_tuple_hash *
nf_conntrack_find_get(struct net *net, u16 zone,
const struct nf_conntrack_tuple *tuple);
-extern int __nf_conntrack_confirm(struct sk_buff *skb);
+int __nf_conntrack_confirm(struct sk_buff *skb);
/* Confirm a connection: returns NF_DROP if packet must be dropped. */
static inline int nf_conntrack_confirm(struct sk_buff *skb)
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 092dc651689f..0e3d08e4b1d3 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -68,10 +68,12 @@ struct nf_ct_event_notifier {
int (*fcn)(unsigned int events, struct nf_ct_event *item);
};
-extern int nf_conntrack_register_notifier(struct net *net, struct nf_ct_event_notifier *nb);
-extern void nf_conntrack_unregister_notifier(struct net *net, struct nf_ct_event_notifier *nb);
+int nf_conntrack_register_notifier(struct net *net,
+ struct nf_ct_event_notifier *nb);
+void nf_conntrack_unregister_notifier(struct net *net,
+ struct nf_ct_event_notifier *nb);
-extern void nf_ct_deliver_cached_events(struct nf_conn *ct);
+void nf_ct_deliver_cached_events(struct nf_conn *ct);
static inline void
nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
@@ -166,8 +168,10 @@ struct nf_exp_event_notifier {
int (*fcn)(unsigned int events, struct nf_exp_event *item);
};
-extern int nf_ct_expect_register_notifier(struct net *net, struct nf_exp_event_notifier *nb);
-extern void nf_ct_expect_unregister_notifier(struct net *net, struct nf_exp_event_notifier *nb);
+int nf_ct_expect_register_notifier(struct net *net,
+ struct nf_exp_event_notifier *nb);
+void nf_ct_expect_unregister_notifier(struct net *net,
+ struct nf_exp_event_notifier *nb);
static inline void
nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
@@ -207,11 +211,11 @@ nf_ct_expect_event(enum ip_conntrack_expect_events event,
nf_ct_expect_event_report(event, exp, 0, 0);
}
-extern int nf_conntrack_ecache_pernet_init(struct net *net);
-extern void nf_conntrack_ecache_pernet_fini(struct net *net);
+int nf_conntrack_ecache_pernet_init(struct net *net);
+void nf_conntrack_ecache_pernet_fini(struct net *net);
-extern int nf_conntrack_ecache_init(void);
-extern void nf_conntrack_ecache_fini(void);
+int nf_conntrack_ecache_init(void);
+void nf_conntrack_ecache_fini(void);
#else /* CONFIG_NF_CONNTRACK_EVENTS */
static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h
index 88a1d4060d52..86372ae0ee84 100644
--- a/include/net/netfilter/nf_conntrack_extend.h
+++ b/include/net/netfilter/nf_conntrack_extend.h
@@ -73,7 +73,7 @@ static inline void *__nf_ct_ext_find(const struct nf_conn *ct, u8 id)
((id##_TYPE *)__nf_ct_ext_find((ext), (id)))
/* Destroy all relationships */
-extern void __nf_ct_ext_destroy(struct nf_conn *ct);
+void __nf_ct_ext_destroy(struct nf_conn *ct);
static inline void nf_ct_ext_destroy(struct nf_conn *ct)
{
if (ct->ext)
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index 26c4ae5bfbb8..6cf614bc0029 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -52,21 +52,24 @@ struct nf_conntrack_helper {
unsigned int queue_num; /* For user-space helpers. */
};
-extern struct nf_conntrack_helper *
-__nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum);
+struct nf_conntrack_helper *__nf_conntrack_helper_find(const char *name,
+ u16 l3num, u8 protonum);
-extern struct nf_conntrack_helper *
-nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum);
+struct nf_conntrack_helper *nf_conntrack_helper_try_module_get(const char *name,
+ u16 l3num,
+ u8 protonum);
-extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
-extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
+int nf_conntrack_helper_register(struct nf_conntrack_helper *);
+void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
-extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, struct nf_conntrack_helper *helper, gfp_t gfp);
+struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct,
+ struct nf_conntrack_helper *helper,
+ gfp_t gfp);
-extern int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
- gfp_t flags);
+int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
+ gfp_t flags);
-extern void nf_ct_helper_destroy(struct nf_conn *ct);
+void nf_ct_helper_destroy(struct nf_conn *ct);
static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
{
@@ -82,17 +85,16 @@ static inline void *nfct_help_data(const struct nf_conn *ct)
return (void *)help->data;
}
-extern int nf_conntrack_helper_pernet_init(struct net *net);
-extern void nf_conntrack_helper_pernet_fini(struct net *net);
+int nf_conntrack_helper_pernet_init(struct net *net);
+void nf_conntrack_helper_pernet_fini(struct net *net);
-extern int nf_conntrack_helper_init(void);
-extern void nf_conntrack_helper_fini(void);
+int nf_conntrack_helper_init(void);
+void nf_conntrack_helper_fini(void);
-extern int nf_conntrack_broadcast_help(struct sk_buff *skb,
- unsigned int protoff,
- struct nf_conn *ct,
- enum ip_conntrack_info ctinfo,
- unsigned int timeout);
+int nf_conntrack_broadcast_help(struct sk_buff *skb, unsigned int protoff,
+ struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int timeout);
struct nf_ct_helper_expectfn {
struct list_head head;
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index 3bb89eac3fa1..3efab704b7eb 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -77,17 +77,17 @@ struct nf_conntrack_l3proto {
extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX];
/* Protocol pernet registration. */
-extern int nf_ct_l3proto_pernet_register(struct net *net,
- struct nf_conntrack_l3proto *proto);
-extern void nf_ct_l3proto_pernet_unregister(struct net *net,
- struct nf_conntrack_l3proto *proto);
+int nf_ct_l3proto_pernet_register(struct net *net,
+ struct nf_conntrack_l3proto *proto);
+void nf_ct_l3proto_pernet_unregister(struct net *net,
+ struct nf_conntrack_l3proto *proto);
/* Protocol global registration. */
-extern int nf_ct_l3proto_register(struct nf_conntrack_l3proto *proto);
-extern void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto);
+int nf_ct_l3proto_register(struct nf_conntrack_l3proto *proto);
+void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto);
-extern struct nf_conntrack_l3proto *nf_ct_l3proto_find_get(u_int16_t l3proto);
-extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p);
+struct nf_conntrack_l3proto *nf_ct_l3proto_find_get(u_int16_t l3proto);
+void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p);
/* Existing built-in protocols */
extern struct nf_conntrack_l3proto nf_conntrack_l3proto_generic;
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
index b411d7b17dec..4c8d573830b7 100644
--- a/include/net/netfilter/nf_conntrack_l4proto.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -114,22 +114,22 @@ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_generic;
#define MAX_NF_CT_PROTO 256
-extern struct nf_conntrack_l4proto *
-__nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto);
+struct nf_conntrack_l4proto *__nf_ct_l4proto_find(u_int16_t l3proto,
+ u_int8_t l4proto);
-extern struct nf_conntrack_l4proto *
-nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t l4proto);
-extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p);
+struct nf_conntrack_l4proto *nf_ct_l4proto_find_get(u_int16_t l3proto,
+ u_int8_t l4proto);
+void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p);
/* Protocol pernet registration. */
-extern int nf_ct_l4proto_pernet_register(struct net *net,
- struct nf_conntrack_l4proto *proto);
-extern void nf_ct_l4proto_pernet_unregister(struct net *net,
- struct nf_conntrack_l4proto *proto);
+int nf_ct_l4proto_pernet_register(struct net *net,
+ struct nf_conntrack_l4proto *proto);
+void nf_ct_l4proto_pernet_unregister(struct net *net,
+ struct nf_conntrack_l4proto *proto);
/* Protocol global registration. */
-extern int nf_ct_l4proto_register(struct nf_conntrack_l4proto *proto);
-extern void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *proto);
+int nf_ct_l4proto_register(struct nf_conntrack_l4proto *proto);
+void nf_ct_l4proto_unregister(struct nf_conntrack_l4proto *proto);
static inline void nf_ct_kfree_compat_sysctl_table(struct nf_proto_net *pn)
{
@@ -140,11 +140,11 @@ static inline void nf_ct_kfree_compat_sysctl_table(struct nf_proto_net *pn)
}
/* Generic netlink helpers */
-extern int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
- const struct nf_conntrack_tuple *tuple);
-extern int nf_ct_port_nlattr_to_tuple(struct nlattr *tb[],
- struct nf_conntrack_tuple *t);
-extern int nf_ct_port_nlattr_tuple_size(void);
+int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *tuple);
+int nf_ct_port_nlattr_to_tuple(struct nlattr *tb[],
+ struct nf_conntrack_tuple *t);
+int nf_ct_port_nlattr_tuple_size(void);
extern const struct nla_policy nf_ct_port_nla_policy[];
#ifdef CONFIG_SYSCTL
diff --git a/include/net/netfilter/nf_conntrack_seqadj.h b/include/net/netfilter/nf_conntrack_seqadj.h
index f6177a5fe0ca..4b3362991a25 100644
--- a/include/net/netfilter/nf_conntrack_seqadj.h
+++ b/include/net/netfilter/nf_conntrack_seqadj.h
@@ -30,22 +30,18 @@ static inline struct nf_conn_seqadj *nfct_seqadj_ext_add(struct nf_conn *ct)
return nf_ct_ext_add(ct, NF_CT_EXT_SEQADJ, GFP_ATOMIC);
}
-extern int nf_ct_seqadj_init(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
- s32 off);
-extern int nf_ct_seqadj_set(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
- __be32 seq, s32 off);
-extern void nf_ct_tcp_seqadj_set(struct sk_buff *skb,
- struct nf_conn *ct,
- enum ip_conntrack_info ctinfo,
- s32 off);
-
-extern int nf_ct_seq_adjust(struct sk_buff *skb,
- struct nf_conn *ct, enum ip_conntrack_info ctinfo,
- unsigned int protoff);
-extern s32 nf_ct_seq_offset(const struct nf_conn *ct, enum ip_conntrack_dir,
- u32 seq);
-
-extern int nf_conntrack_seqadj_init(void);
-extern void nf_conntrack_seqadj_fini(void);
+int nf_ct_seqadj_init(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
+ s32 off);
+int nf_ct_seqadj_set(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
+ __be32 seq, s32 off);
+void nf_ct_tcp_seqadj_set(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo, s32 off);
+
+int nf_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo, unsigned int protoff);
+s32 nf_ct_seq_offset(const struct nf_conn *ct, enum ip_conntrack_dir, u32 seq);
+
+int nf_conntrack_seqadj_init(void);
+void nf_conntrack_seqadj_fini(void);
#endif /* _NF_CONNTRACK_SEQADJ_H */
diff --git a/include/net/netfilter/nf_conntrack_synproxy.h b/include/net/netfilter/nf_conntrack_synproxy.h
index 806f54a290d6..968186642bb1 100644
--- a/include/net/netfilter/nf_conntrack_synproxy.h
+++ b/include/net/netfilter/nf_conntrack_synproxy.h
@@ -56,22 +56,20 @@ struct synproxy_options {
struct tcphdr;
struct xt_synproxy_info;
-extern void synproxy_parse_options(const struct sk_buff *skb, unsigned int doff,
- const struct tcphdr *th,
- struct synproxy_options *opts);
-extern unsigned int synproxy_options_size(const struct synproxy_options *opts);
-extern void synproxy_build_options(struct tcphdr *th,
- const struct synproxy_options *opts);
+void synproxy_parse_options(const struct sk_buff *skb, unsigned int doff,
+ const struct tcphdr *th,
+ struct synproxy_options *opts);
+unsigned int synproxy_options_size(const struct synproxy_options *opts);
+void synproxy_build_options(struct tcphdr *th,
+ const struct synproxy_options *opts);
-extern void synproxy_init_timestamp_cookie(const struct xt_synproxy_info *info,
- struct synproxy_options *opts);
-extern void synproxy_check_timestamp_cookie(struct synproxy_options *opts);
+void synproxy_init_timestamp_cookie(const struct xt_synproxy_info *info,
+ struct synproxy_options *opts);
+void synproxy_check_timestamp_cookie(struct synproxy_options *opts);
-extern unsigned int synproxy_tstamp_adjust(struct sk_buff *skb,
- unsigned int protoff,
- struct tcphdr *th,
- struct nf_conn *ct,
- enum ip_conntrack_info ctinfo,
- const struct nf_conn_synproxy *synproxy);
+unsigned int synproxy_tstamp_adjust(struct sk_buff *skb, unsigned int protoff,
+ struct tcphdr *th, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ const struct nf_conn_synproxy *synproxy);
#endif /* _NF_CONNTRACK_SYNPROXY_H */
diff --git a/include/net/netfilter/nf_conntrack_timeout.h b/include/net/netfilter/nf_conntrack_timeout.h
index d23aceb16d94..62308713dd7f 100644
--- a/include/net/netfilter/nf_conntrack_timeout.h
+++ b/include/net/netfilter/nf_conntrack_timeout.h
@@ -76,8 +76,8 @@ nf_ct_timeout_lookup(struct net *net, struct nf_conn *ct,
}
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
-extern int nf_conntrack_timeout_init(void);
-extern void nf_conntrack_timeout_fini(void);
+int nf_conntrack_timeout_init(void);
+void nf_conntrack_timeout_fini(void);
#else
static inline int nf_conntrack_timeout_init(void)
{
diff --git a/include/net/netfilter/nf_conntrack_timestamp.h b/include/net/netfilter/nf_conntrack_timestamp.h
index b00461413efd..300ae2209f25 100644
--- a/include/net/netfilter/nf_conntrack_timestamp.h
+++ b/include/net/netfilter/nf_conntrack_timestamp.h
@@ -48,11 +48,11 @@ static inline void nf_ct_set_tstamp(struct net *net, bool enable)
}
#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
-extern int nf_conntrack_tstamp_pernet_init(struct net *net);
-extern void nf_conntrack_tstamp_pernet_fini(struct net *net);
+int nf_conntrack_tstamp_pernet_init(struct net *net);
+void nf_conntrack_tstamp_pernet_fini(struct net *net);
-extern int nf_conntrack_tstamp_init(void);
-extern void nf_conntrack_tstamp_fini(void);
+int nf_conntrack_tstamp_init(void);
+void nf_conntrack_tstamp_fini(void);
#else
static inline int nf_conntrack_tstamp_pernet_init(struct net *net)
{
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
index 59a192420053..c29b4e545f87 100644
--- a/include/net/netfilter/nf_nat.h
+++ b/include/net/netfilter/nf_nat.h
@@ -41,13 +41,13 @@ struct nf_conn_nat {
};
/* Set up the info structure to map into this range. */
-extern unsigned int nf_nat_setup_info(struct nf_conn *ct,
- const struct nf_nat_range *range,
- enum nf_nat_manip_type maniptype);
+unsigned int nf_nat_setup_info(struct nf_conn *ct,
+ const struct nf_nat_range *range,
+ enum nf_nat_manip_type maniptype);
/* Is this tuple already taken? (not by us)*/
-extern int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
- const struct nf_conn *ignored_conntrack);
+int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
+ const struct nf_conn *ignored_conntrack);
static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
{
diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h
index 972e1e47ec79..fbfd1ba4254e 100644
--- a/include/net/netfilter/nf_nat_core.h
+++ b/include/net/netfilter/nf_nat_core.h
@@ -7,12 +7,10 @@
/* This header used to share core functionality between the standalone
NAT module, and the compatibility layer's use of NAT for masquerading. */
-extern unsigned int nf_nat_packet(struct nf_conn *ct,
- enum ip_conntrack_info ctinfo,
- unsigned int hooknum,
- struct sk_buff *skb);
+unsigned int nf_nat_packet(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
+ unsigned int hooknum, struct sk_buff *skb);
-extern int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family);
+int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family);
static inline int nf_nat_initialized(struct nf_conn *ct,
enum nf_nat_manip_type manip)
diff --git a/include/net/netfilter/nf_nat_helper.h b/include/net/netfilter/nf_nat_helper.h
index 404324d1d0c4..01bcc6bfbcc9 100644
--- a/include/net/netfilter/nf_nat_helper.h
+++ b/include/net/netfilter/nf_nat_helper.h
@@ -7,14 +7,11 @@
struct sk_buff;
/* These return true or false. */
-extern int __nf_nat_mangle_tcp_packet(struct sk_buff *skb,
- struct nf_conn *ct,
- enum ip_conntrack_info ctinfo,
- unsigned int protoff,
- unsigned int match_offset,
- unsigned int match_len,
- const char *rep_buffer,
- unsigned int rep_len, bool adjust);
+int __nf_nat_mangle_tcp_packet(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int protoff, unsigned int match_offset,
+ unsigned int match_len, const char *rep_buffer,
+ unsigned int rep_len, bool adjust);
static inline int nf_nat_mangle_tcp_packet(struct sk_buff *skb,
struct nf_conn *ct,
@@ -30,18 +27,14 @@ static inline int nf_nat_mangle_tcp_packet(struct sk_buff *skb,
rep_buffer, rep_len, true);
}
-extern int nf_nat_mangle_udp_packet(struct sk_buff *skb,
- struct nf_conn *ct,
- enum ip_conntrack_info ctinfo,
- unsigned int protoff,
- unsigned int match_offset,
- unsigned int match_len,
- const char *rep_buffer,
- unsigned int rep_len);
+int nf_nat_mangle_udp_packet(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int protoff, unsigned int match_offset,
+ unsigned int match_len, const char *rep_buffer,
+ unsigned int rep_len);
/* Setup NAT on this expected conntrack so it follows master, but goes
* to port ct->master->saved_proto. */
-extern void nf_nat_follow_master(struct nf_conn *ct,
- struct nf_conntrack_expect *this);
+void nf_nat_follow_master(struct nf_conn *ct, struct nf_conntrack_expect *this);
#endif
diff --git a/include/net/netfilter/nf_nat_l3proto.h b/include/net/netfilter/nf_nat_l3proto.h
index bd3b97e02c82..5a2919b2e09a 100644
--- a/include/net/netfilter/nf_nat_l3proto.h
+++ b/include/net/netfilter/nf_nat_l3proto.h
@@ -35,18 +35,15 @@ struct nf_nat_l3proto {
struct nf_nat_range *range);
};
-extern int nf_nat_l3proto_register(const struct nf_nat_l3proto *);
-extern void nf_nat_l3proto_unregister(const struct nf_nat_l3proto *);
-extern const struct nf_nat_l3proto *__nf_nat_l3proto_find(u8 l3proto);
-
-extern int nf_nat_icmp_reply_translation(struct sk_buff *skb,
- struct nf_conn *ct,
- enum ip_conntrack_info ctinfo,
- unsigned int hooknum);
-extern int nf_nat_icmpv6_reply_translation(struct sk_buff *skb,
- struct nf_conn *ct,
- enum ip_conntrack_info ctinfo,
- unsigned int hooknum,
- unsigned int hdrlen);
+int nf_nat_l3proto_register(const struct nf_nat_l3proto *);
+void nf_nat_l3proto_unregister(const struct nf_nat_l3proto *);
+const struct nf_nat_l3proto *__nf_nat_l3proto_find(u8 l3proto);
+
+int nf_nat_icmp_reply_translation(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int hooknum);
+int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int hooknum, unsigned int hdrlen);
#endif /* _NF_NAT_L3PROTO_H */
diff --git a/include/net/netfilter/nf_nat_l4proto.h b/include/net/netfilter/nf_nat_l4proto.h
index 24feb68d1bcc..12f4cc841b6e 100644
--- a/include/net/netfilter/nf_nat_l4proto.h
+++ b/include/net/netfilter/nf_nat_l4proto.h
@@ -42,10 +42,11 @@ struct nf_nat_l4proto {
};
/* Protocol registration. */
-extern int nf_nat_l4proto_register(u8 l3proto, const struct nf_nat_l4proto *l4proto);
-extern void nf_nat_l4proto_unregister(u8 l3proto, const struct nf_nat_l4proto *l4proto);
+int nf_nat_l4proto_register(u8 l3proto, const struct nf_nat_l4proto *l4proto);
+void nf_nat_l4proto_unregister(u8 l3proto,
+ const struct nf_nat_l4proto *l4proto);
-extern const struct nf_nat_l4proto *__nf_nat_l4proto_find(u8 l3proto, u8 l4proto);
+const struct nf_nat_l4proto *__nf_nat_l4proto_find(u8 l3proto, u8 l4proto);
/* Built-in protocols. */
extern const struct nf_nat_l4proto nf_nat_l4proto_tcp;
@@ -54,19 +55,18 @@ extern const struct nf_nat_l4proto nf_nat_l4proto_icmp;
extern const struct nf_nat_l4proto nf_nat_l4proto_icmpv6;
extern const struct nf_nat_l4proto nf_nat_l4proto_unknown;
-extern bool nf_nat_l4proto_in_range(const struct nf_conntrack_tuple *tuple,
- enum nf_nat_manip_type maniptype,
- const union nf_conntrack_man_proto *min,
- const union nf_conntrack_man_proto *max);
+bool nf_nat_l4proto_in_range(const struct nf_conntrack_tuple *tuple,
+ enum nf_nat_manip_type maniptype,
+ const union nf_conntrack_man_proto *min,
+ const union nf_conntrack_man_proto *max);
-extern void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto,
- struct nf_conntrack_tuple *tuple,
- const struct nf_nat_range *range,
- enum nf_nat_manip_type maniptype,
- const struct nf_conn *ct,
- u16 *rover);
+void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto,
+ struct nf_conntrack_tuple *tuple,
+ const struct nf_nat_range *range,
+ enum nf_nat_manip_type maniptype,
+ const struct nf_conn *ct, u16 *rover);
-extern int nf_nat_l4proto_nlattr_to_range(struct nlattr *tb[],
- struct nf_nat_range *range);
+int nf_nat_l4proto_nlattr_to_range(struct nlattr *tb[],
+ struct nf_nat_range *range);
#endif /*_NF_NAT_L4PROTO_H*/
diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h
index aaba4bbcdda0..c1d5b3e34a21 100644
--- a/include/net/netfilter/nf_queue.h
+++ b/include/net/netfilter/nf_queue.h
@@ -28,7 +28,7 @@ struct nf_queue_handler {
void nf_register_queue_handler(const struct nf_queue_handler *qh);
void nf_unregister_queue_handler(void);
-extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
+void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
bool nf_queue_entry_get_refs(struct nf_queue_entry *entry);
void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
diff --git a/include/net/netfilter/xt_rateest.h b/include/net/netfilter/xt_rateest.h
index 495c71f66e7e..79f45e19f31e 100644
--- a/include/net/netfilter/xt_rateest.h
+++ b/include/net/netfilter/xt_rateest.h
@@ -16,7 +16,7 @@ struct xt_rateest {
struct rcu_head rcu;
};
-extern struct xt_rateest *xt_rateest_lookup(const char *name);
-extern void xt_rateest_put(struct xt_rateest *est);
+struct xt_rateest *xt_rateest_lookup(const char *name);
+void xt_rateest_put(struct xt_rateest *est);
#endif /* _XT_RATEEST_H */
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 9690b0f6698a..2b47eaadba8f 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -225,44 +225,31 @@ struct nl_info {
u32 portid;
};
-extern int netlink_rcv_skb(struct sk_buff *skb,
- int (*cb)(struct sk_buff *,
- struct nlmsghdr *));
-extern int nlmsg_notify(struct sock *sk, struct sk_buff *skb,
- u32 portid, unsigned int group, int report,
- gfp_t flags);
-
-extern int nla_validate(const struct nlattr *head,
- int len, int maxtype,
- const struct nla_policy *policy);
-extern int nla_parse(struct nlattr **tb, int maxtype,
- const struct nlattr *head, int len,
- const struct nla_policy *policy);
-extern int nla_policy_len(const struct nla_policy *, int);
-extern struct nlattr * nla_find(const struct nlattr *head,
- int len, int attrtype);
-extern size_t nla_strlcpy(char *dst, const struct nlattr *nla,
- size_t dstsize);
-extern int nla_memcpy(void *dest, const struct nlattr *src, int count);
-extern int nla_memcmp(const struct nlattr *nla, const void *data,
- size_t size);
-extern int nla_strcmp(const struct nlattr *nla, const char *str);
-extern struct nlattr * __nla_reserve(struct sk_buff *skb, int attrtype,
- int attrlen);
-extern void * __nla_reserve_nohdr(struct sk_buff *skb, int attrlen);
-extern struct nlattr * nla_reserve(struct sk_buff *skb, int attrtype,
- int attrlen);
-extern void * nla_reserve_nohdr(struct sk_buff *skb, int attrlen);
-extern void __nla_put(struct sk_buff *skb, int attrtype,
- int attrlen, const void *data);
-extern void __nla_put_nohdr(struct sk_buff *skb, int attrlen,
- const void *data);
-extern int nla_put(struct sk_buff *skb, int attrtype,
- int attrlen, const void *data);
-extern int nla_put_nohdr(struct sk_buff *skb, int attrlen,
- const void *data);
-extern int nla_append(struct sk_buff *skb, int attrlen,
- const void *data);
+int netlink_rcv_skb(struct sk_buff *skb,
+ int (*cb)(struct sk_buff *, struct nlmsghdr *));
+int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 portid,
+ unsigned int group, int report, gfp_t flags);
+
+int nla_validate(const struct nlattr *head, int len, int maxtype,
+ const struct nla_policy *policy);
+int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
+ int len, const struct nla_policy *policy);
+int nla_policy_len(const struct nla_policy *, int);
+struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype);
+size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize);
+int nla_memcpy(void *dest, const struct nlattr *src, int count);
+int nla_memcmp(const struct nlattr *nla, const void *data, size_t size);
+int nla_strcmp(const struct nlattr *nla, const char *str);
+struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen);
+void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen);
+struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen);
+void *nla_reserve_nohdr(struct sk_buff *skb, int attrlen);
+void __nla_put(struct sk_buff *skb, int attrtype, int attrlen,
+ const void *data);
+void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data);
+int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data);
+int nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data);
+int nla_append(struct sk_buff *skb, int attrlen, const void *data);
/**************************************************************************
* Netlink Messages
diff --git a/include/net/netrom.h b/include/net/netrom.h
index 121dcf854db5..110350aca3df 100644
--- a/include/net/netrom.h
+++ b/include/net/netrom.h
@@ -183,51 +183,50 @@ extern int sysctl_netrom_routing_control;
extern int sysctl_netrom_link_fails_count;
extern int sysctl_netrom_reset_circuit;
-extern int nr_rx_frame(struct sk_buff *, struct net_device *);
-extern void nr_destroy_socket(struct sock *);
+int nr_rx_frame(struct sk_buff *, struct net_device *);
+void nr_destroy_socket(struct sock *);
/* nr_dev.c */
-extern int nr_rx_ip(struct sk_buff *, struct net_device *);
-extern void nr_setup(struct net_device *);
+int nr_rx_ip(struct sk_buff *, struct net_device *);
+void nr_setup(struct net_device *);
/* nr_in.c */
-extern int nr_process_rx_frame(struct sock *, struct sk_buff *);
+int nr_process_rx_frame(struct sock *, struct sk_buff *);
/* nr_loopback.c */
-extern void nr_loopback_init(void);
-extern void nr_loopback_clear(void);
-extern int nr_loopback_queue(struct sk_buff *);
+void nr_loopback_init(void);
+void nr_loopback_clear(void);
+int nr_loopback_queue(struct sk_buff *);
/* nr_out.c */
-extern void nr_output(struct sock *, struct sk_buff *);
-extern void nr_send_nak_frame(struct sock *);
-extern void nr_kick(struct sock *);
-extern void nr_transmit_buffer(struct sock *, struct sk_buff *);
-extern void nr_establish_data_link(struct sock *);
-extern void nr_enquiry_response(struct sock *);
-extern void nr_check_iframes_acked(struct sock *, unsigned short);
+void nr_output(struct sock *, struct sk_buff *);
+void nr_send_nak_frame(struct sock *);
+void nr_kick(struct sock *);
+void nr_transmit_buffer(struct sock *, struct sk_buff *);
+void nr_establish_data_link(struct sock *);
+void nr_enquiry_response(struct sock *);
+void nr_check_iframes_acked(struct sock *, unsigned short);
/* nr_route.c */
-extern void nr_rt_device_down(struct net_device *);
-extern struct net_device *nr_dev_first(void);
-extern struct net_device *nr_dev_get(ax25_address *);
-extern int nr_rt_ioctl(unsigned int, void __user *);
-extern void nr_link_failed(ax25_cb *, int);
-extern int nr_route_frame(struct sk_buff *, ax25_cb *);
+void nr_rt_device_down(struct net_device *);
+struct net_device *nr_dev_first(void);
+struct net_device *nr_dev_get(ax25_address *);
+int nr_rt_ioctl(unsigned int, void __user *);
+void nr_link_failed(ax25_cb *, int);
+int nr_route_frame(struct sk_buff *, ax25_cb *);
extern const struct file_operations nr_nodes_fops;
extern const struct file_operations nr_neigh_fops;
-extern void nr_rt_free(void);
+void nr_rt_free(void);
/* nr_subr.c */
-extern void nr_clear_queues(struct sock *);
-extern void nr_frames_acked(struct sock *, unsigned short);
-extern void nr_requeue_frames(struct sock *);
-extern int nr_validate_nr(struct sock *, unsigned short);
-extern int nr_in_rx_window(struct sock *, unsigned short);
-extern void nr_write_internal(struct sock *, int);
+void nr_clear_queues(struct sock *);
+void nr_frames_acked(struct sock *, unsigned short);
+void nr_requeue_frames(struct sock *);
+int nr_validate_nr(struct sock *, unsigned short);
+int nr_in_rx_window(struct sock *, unsigned short);
+void nr_write_internal(struct sock *, int);
-extern void __nr_transmit_reply(struct sk_buff *skb, int mine,
- unsigned char cmdflags);
+void __nr_transmit_reply(struct sk_buff *skb, int mine, unsigned char cmdflags);
/*
* This routine is called when a Connect Acknowledge with the Choke Flag
@@ -247,24 +246,24 @@ do { \
__nr_transmit_reply((skb), (mine), NR_RESET); \
} while (0)
-extern void nr_disconnect(struct sock *, int);
+void nr_disconnect(struct sock *, int);
/* nr_timer.c */
-extern void nr_init_timers(struct sock *sk);
-extern void nr_start_heartbeat(struct sock *);
-extern void nr_start_t1timer(struct sock *);
-extern void nr_start_t2timer(struct sock *);
-extern void nr_start_t4timer(struct sock *);
-extern void nr_start_idletimer(struct sock *);
-extern void nr_stop_heartbeat(struct sock *);
-extern void nr_stop_t1timer(struct sock *);
-extern void nr_stop_t2timer(struct sock *);
-extern void nr_stop_t4timer(struct sock *);
-extern void nr_stop_idletimer(struct sock *);
-extern int nr_t1timer_running(struct sock *);
+void nr_init_timers(struct sock *sk);
+void nr_start_heartbeat(struct sock *);
+void nr_start_t1timer(struct sock *);
+void nr_start_t2timer(struct sock *);
+void nr_start_t4timer(struct sock *);
+void nr_start_idletimer(struct sock *);
+void nr_stop_heartbeat(struct sock *);
+void nr_stop_t1timer(struct sock *);
+void nr_stop_t2timer(struct sock *);
+void nr_stop_t4timer(struct sock *);
+void nr_stop_idletimer(struct sock *);
+int nr_t1timer_running(struct sock *);
/* sysctl_net_netrom.c */
-extern void nr_register_sysctl(void);
-extern void nr_unregister_sysctl(void);
+void nr_register_sysctl(void);
+void nr_unregister_sysctl(void);
#endif
diff --git a/include/net/p8022.h b/include/net/p8022.h
index 42e9fac51b31..05e41383856b 100644
--- a/include/net/p8022.h
+++ b/include/net/p8022.h
@@ -1,13 +1,13 @@
#ifndef _NET_P8022_H
#define _NET_P8022_H
-extern struct datalink_proto *
- register_8022_client(unsigned char type,
- int (*func)(struct sk_buff *skb,
- struct net_device *dev,
- struct packet_type *pt,
- struct net_device *orig_dev));
-extern void unregister_8022_client(struct datalink_proto *proto);
+struct datalink_proto *
+register_8022_client(unsigned char type,
+ int (*func)(struct sk_buff *skb,
+ struct net_device *dev,
+ struct packet_type *pt,
+ struct net_device *orig_dev));
+void unregister_8022_client(struct datalink_proto *proto);
-extern struct datalink_proto *make_8023_client(void);
-extern void destroy_8023_client(struct datalink_proto *dl);
+struct datalink_proto *make_8023_client(void);
+void destroy_8023_client(struct datalink_proto *dl);
#endif
diff --git a/include/net/ping.h b/include/net/ping.h
index 5db0224b73ac..3f67704f3747 100644
--- a/include/net/ping.h
+++ b/include/net/ping.h
@@ -103,8 +103,8 @@ void ping_seq_stop(struct seq_file *seq, void *v);
int ping_proc_register(struct net *net, struct ping_seq_afinfo *afinfo);
void ping_proc_unregister(struct net *net, struct ping_seq_afinfo *afinfo);
-extern int __init ping_proc_init(void);
-extern void ping_proc_exit(void);
+int __init ping_proc_init(void);
+void ping_proc_exit(void);
#endif
void __init ping_init(void);
diff --git a/include/net/protocol.h b/include/net/protocol.h
index 047c0476c0a0..fbf7676c9a02 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -96,20 +96,20 @@ extern const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS];
extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS];
#endif
-extern int inet_add_protocol(const struct net_protocol *prot, unsigned char num);
-extern int inet_del_protocol(const struct net_protocol *prot, unsigned char num);
-extern int inet_add_offload(const struct net_offload *prot, unsigned char num);
-extern int inet_del_offload(const struct net_offload *prot, unsigned char num);
-extern void inet_register_protosw(struct inet_protosw *p);
-extern void inet_unregister_protosw(struct inet_protosw *p);
+int inet_add_protocol(const struct net_protocol *prot, unsigned char num);
+int inet_del_protocol(const struct net_protocol *prot, unsigned char num);
+int inet_add_offload(const struct net_offload *prot, unsigned char num);
+int inet_del_offload(const struct net_offload *prot, unsigned char num);
+void inet_register_protosw(struct inet_protosw *p);
+void inet_unregister_protosw(struct inet_protosw *p);
#if IS_ENABLED(CONFIG_IPV6)
-extern int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char num);
-extern int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char num);
-extern int inet6_register_protosw(struct inet_protosw *p);
-extern void inet6_unregister_protosw(struct inet_protosw *p);
+int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char num);
+int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char num);
+int inet6_register_protosw(struct inet_protosw *p);
+void inet6_unregister_protosw(struct inet_protosw *p);
#endif
-extern int inet6_add_offload(const struct net_offload *prot, unsigned char num);
-extern int inet6_del_offload(const struct net_offload *prot, unsigned char num);
+int inet6_add_offload(const struct net_offload *prot, unsigned char num);
+int inet6_del_offload(const struct net_offload *prot, unsigned char num);
#endif /* _PROTOCOL_H */
diff --git a/include/net/psnap.h b/include/net/psnap.h
index fe456c295b04..78db4cc1306a 100644
--- a/include/net/psnap.h
+++ b/include/net/psnap.h
@@ -1,11 +1,11 @@
#ifndef _NET_PSNAP_H
#define _NET_PSNAP_H
-extern struct datalink_proto *
+struct datalink_proto *
register_snap_client(const unsigned char *desc,
int (*rcvfunc)(struct sk_buff *, struct net_device *,
struct packet_type *,
struct net_device *orig_dev));
-extern void unregister_snap_client(struct datalink_proto *proto);
+void unregister_snap_client(struct datalink_proto *proto);
#endif
diff --git a/include/net/raw.h b/include/net/raw.h
index 42ce6fe7a2d5..6a40c6562dd2 100644
--- a/include/net/raw.h
+++ b/include/net/raw.h
@@ -26,7 +26,7 @@ extern struct proto raw_prot;
void raw_icmp_error(struct sk_buff *, int, u32);
int raw_local_deliver(struct sk_buff *, int);
-extern int raw_rcv(struct sock *, struct sk_buff *);
+int raw_rcv(struct sock *, struct sk_buff *);
#define RAW_HTABLE_SIZE MAX_INET_PROTOS
@@ -36,8 +36,8 @@ struct raw_hashinfo {
};
#ifdef CONFIG_PROC_FS
-extern int raw_proc_init(void);
-extern void raw_proc_exit(void);
+int raw_proc_init(void);
+void raw_proc_exit(void);
struct raw_iter_state {
struct seq_net_private p;
diff --git a/include/net/rawv6.h b/include/net/rawv6.h
index e7ea660e4db6..87783dea0791 100644
--- a/include/net/rawv6.h
+++ b/include/net/rawv6.h
@@ -7,8 +7,7 @@ void raw6_icmp_error(struct sk_buff *, int nexthdr,
u8 type, u8 code, int inner_offset, __be32);
bool raw6_local_deliver(struct sk_buff *, int);
-extern int rawv6_rcv(struct sock *sk,
- struct sk_buff *skb);
+int rawv6_rcv(struct sock *sk, struct sk_buff *skb);
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
int rawv6_mh_filter_register(int (*filter)(struct sock *sock,
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index 59795e42c8b6..65c3e5164a5c 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -43,7 +43,7 @@ struct request_sock_ops {
struct request_sock *req);
};
-extern int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req);
+int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req);
/* struct request_sock - mini sock to represent a connection request
*/
@@ -162,13 +162,13 @@ struct request_sock_queue {
*/
};
-extern int reqsk_queue_alloc(struct request_sock_queue *queue,
- unsigned int nr_table_entries);
+int reqsk_queue_alloc(struct request_sock_queue *queue,
+ unsigned int nr_table_entries);
-extern void __reqsk_queue_destroy(struct request_sock_queue *queue);
-extern void reqsk_queue_destroy(struct request_sock_queue *queue);
-extern void reqsk_fastopen_remove(struct sock *sk,
- struct request_sock *req, bool reset);
+void __reqsk_queue_destroy(struct request_sock_queue *queue);
+void reqsk_queue_destroy(struct request_sock_queue *queue);
+void reqsk_fastopen_remove(struct sock *sk, struct request_sock *req,
+ bool reset);
static inline struct request_sock *
reqsk_queue_yank_acceptq(struct request_sock_queue *queue)
diff --git a/include/net/rose.h b/include/net/rose.h
index 555dd198aab7..50811fe2c585 100644
--- a/include/net/rose.h
+++ b/include/net/rose.h
@@ -160,38 +160,42 @@ extern int sysctl_rose_routing_control;
extern int sysctl_rose_link_fail_timeout;
extern int sysctl_rose_maximum_vcs;
extern int sysctl_rose_window_size;
-extern int rosecmp(rose_address *, rose_address *);
-extern int rosecmpm(rose_address *, rose_address *, unsigned short);
-extern char *rose2asc(char *buf, const rose_address *);
-extern struct sock *rose_find_socket(unsigned int, struct rose_neigh *);
-extern void rose_kill_by_neigh(struct rose_neigh *);
-extern unsigned int rose_new_lci(struct rose_neigh *);
-extern int rose_rx_call_request(struct sk_buff *, struct net_device *, struct rose_neigh *, unsigned int);
-extern void rose_destroy_socket(struct sock *);
+
+int rosecmp(rose_address *, rose_address *);
+int rosecmpm(rose_address *, rose_address *, unsigned short);
+char *rose2asc(char *buf, const rose_address *);
+struct sock *rose_find_socket(unsigned int, struct rose_neigh *);
+void rose_kill_by_neigh(struct rose_neigh *);
+unsigned int rose_new_lci(struct rose_neigh *);
+int rose_rx_call_request(struct sk_buff *, struct net_device *,
+ struct rose_neigh *, unsigned int);
+void rose_destroy_socket(struct sock *);
/* rose_dev.c */
-extern void rose_setup(struct net_device *);
+void rose_setup(struct net_device *);
/* rose_in.c */
-extern int rose_process_rx_frame(struct sock *, struct sk_buff *);
+int rose_process_rx_frame(struct sock *, struct sk_buff *);
/* rose_link.c */
-extern void rose_start_ftimer(struct rose_neigh *);
-extern void rose_stop_ftimer(struct rose_neigh *);
-extern void rose_stop_t0timer(struct rose_neigh *);
-extern int rose_ftimer_running(struct rose_neigh *);
-extern void rose_link_rx_restart(struct sk_buff *, struct rose_neigh *, unsigned short);
-extern void rose_transmit_clear_request(struct rose_neigh *, unsigned int, unsigned char, unsigned char);
-extern void rose_transmit_link(struct sk_buff *, struct rose_neigh *);
+void rose_start_ftimer(struct rose_neigh *);
+void rose_stop_ftimer(struct rose_neigh *);
+void rose_stop_t0timer(struct rose_neigh *);
+int rose_ftimer_running(struct rose_neigh *);
+void rose_link_rx_restart(struct sk_buff *, struct rose_neigh *,
+ unsigned short);
+void rose_transmit_clear_request(struct rose_neigh *, unsigned int,
+ unsigned char, unsigned char);
+void rose_transmit_link(struct sk_buff *, struct rose_neigh *);
/* rose_loopback.c */
-extern void rose_loopback_init(void);
-extern void rose_loopback_clear(void);
-extern int rose_loopback_queue(struct sk_buff *, struct rose_neigh *);
+void rose_loopback_init(void);
+void rose_loopback_clear(void);
+int rose_loopback_queue(struct sk_buff *, struct rose_neigh *);
/* rose_out.c */
-extern void rose_kick(struct sock *);
-extern void rose_enquiry_response(struct sock *);
+void rose_kick(struct sock *);
+void rose_enquiry_response(struct sock *);
/* rose_route.c */
extern struct rose_neigh *rose_loopback_neigh;
@@ -199,43 +203,45 @@ extern const struct file_operations rose_neigh_fops;
extern const struct file_operations rose_nodes_fops;
extern const struct file_operations rose_routes_fops;
-extern void rose_add_loopback_neigh(void);
-extern int __must_check rose_add_loopback_node(rose_address *);
-extern void rose_del_loopback_node(rose_address *);
-extern void rose_rt_device_down(struct net_device *);
-extern void rose_link_device_down(struct net_device *);
-extern struct net_device *rose_dev_first(void);
-extern struct net_device *rose_dev_get(rose_address *);
-extern struct rose_route *rose_route_free_lci(unsigned int, struct rose_neigh *);
-extern struct rose_neigh *rose_get_neigh(rose_address *, unsigned char *, unsigned char *, int);
-extern int rose_rt_ioctl(unsigned int, void __user *);
-extern void rose_link_failed(ax25_cb *, int);
-extern int rose_route_frame(struct sk_buff *, ax25_cb *);
-extern void rose_rt_free(void);
+void rose_add_loopback_neigh(void);
+int __must_check rose_add_loopback_node(rose_address *);
+void rose_del_loopback_node(rose_address *);
+void rose_rt_device_down(struct net_device *);
+void rose_link_device_down(struct net_device *);
+struct net_device *rose_dev_first(void);
+struct net_device *rose_dev_get(rose_address *);
+struct rose_route *rose_route_free_lci(unsigned int, struct rose_neigh *);
+struct rose_neigh *rose_get_neigh(rose_address *, unsigned char *,
+ unsigned char *, int);
+int rose_rt_ioctl(unsigned int, void __user *);
+void rose_link_failed(ax25_cb *, int);
+int rose_route_frame(struct sk_buff *, ax25_cb *);
+void rose_rt_free(void);
/* rose_subr.c */
-extern void rose_clear_queues(struct sock *);
-extern void rose_frames_acked(struct sock *, unsigned short);
-extern void rose_requeue_frames(struct sock *);
-extern int rose_validate_nr(struct sock *, unsigned short);
-extern void rose_write_internal(struct sock *, int);
-extern int rose_decode(struct sk_buff *, int *, int *, int *, int *, int *);
-extern int rose_parse_facilities(unsigned char *, unsigned int, struct rose_facilities_struct *);
-extern void rose_disconnect(struct sock *, int, int, int);
+void rose_clear_queues(struct sock *);
+void rose_frames_acked(struct sock *, unsigned short);
+void rose_requeue_frames(struct sock *);
+int rose_validate_nr(struct sock *, unsigned short);
+void rose_write_internal(struct sock *, int);
+int rose_decode(struct sk_buff *, int *, int *, int *, int *, int *);
+int rose_parse_facilities(unsigned char *, unsigned int,
+ struct rose_facilities_struct *);
+void rose_disconnect(struct sock *, int, int, int);
/* rose_timer.c */
-extern void rose_start_heartbeat(struct sock *);
-extern void rose_start_t1timer(struct sock *);
-extern void rose_start_t2timer(struct sock *);
-extern void rose_start_t3timer(struct sock *);
-extern void rose_start_hbtimer(struct sock *);
-extern void rose_start_idletimer(struct sock *);
-extern void rose_stop_heartbeat(struct sock *);
-extern void rose_stop_timer(struct sock *);
-extern void rose_stop_idletimer(struct sock *);
+void rose_start_heartbeat(struct sock *);
+void rose_start_t1timer(struct sock *);
+void rose_start_t2timer(struct sock *);
+void rose_start_t3timer(struct sock *);
+void rose_start_hbtimer(struct sock *);
+void rose_start_idletimer(struct sock *);
+void rose_stop_heartbeat(struct sock *);
+void rose_stop_timer(struct sock *);
+void rose_stop_idletimer(struct sock *);
/* sysctl_net_rose.c */
-extern void rose_register_sysctl(void);
-extern void rose_unregister_sysctl(void);
+void rose_register_sysctl(void);
+void rose_unregister_sysctl(void);
#endif
diff --git a/include/net/route.h b/include/net/route.h
index afdeeb5bec25..6f572ca66d25 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -108,13 +108,15 @@ struct rt_cache_stat {
extern struct ip_rt_acct __percpu *ip_rt_acct;
struct in_device;
-extern int ip_rt_init(void);
-extern void rt_cache_flush(struct net *net);
-extern void rt_flush_dev(struct net_device *dev);
-extern struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp);
-extern struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp,
- struct sock *sk);
-extern struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig);
+
+int ip_rt_init(void);
+void rt_cache_flush(struct net *net);
+void rt_flush_dev(struct net_device *dev);
+struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp);
+struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp,
+ struct sock *sk);
+struct dst_entry *ipv4_blackhole_route(struct net *net,
+ struct dst_entry *dst_orig);
static inline struct rtable *ip_route_output_key(struct net *net, struct flowi4 *flp)
{
@@ -162,8 +164,8 @@ static inline struct rtable *ip_route_output_gre(struct net *net, struct flowi4
return ip_route_output_key(net, fl4);
}
-extern int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 src,
- u8 tos, struct net_device *devin);
+int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 src,
+ u8 tos, struct net_device *devin);
static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src,
u8 tos, struct net_device *devin)
@@ -179,24 +181,25 @@ static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src,
return err;
}
-extern void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,
- int oif, u32 mark, u8 protocol, int flow_flags);
-extern void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu);
-extern void ipv4_redirect(struct sk_buff *skb, struct net *net,
- int oif, u32 mark, u8 protocol, int flow_flags);
-extern void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk);
-extern void ip_rt_send_redirect(struct sk_buff *skb);
-
-extern unsigned int inet_addr_type(struct net *net, __be32 addr);
-extern unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev, __be32 addr);
-extern void ip_rt_multicast_event(struct in_device *);
-extern int ip_rt_ioctl(struct net *, unsigned int cmd, void __user *arg);
-extern void ip_rt_get_source(u8 *src, struct sk_buff *skb, struct rtable *rt);
-extern int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb);
+void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, int oif,
+ u32 mark, u8 protocol, int flow_flags);
+void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu);
+void ipv4_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark,
+ u8 protocol, int flow_flags);
+void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk);
+void ip_rt_send_redirect(struct sk_buff *skb);
+
+unsigned int inet_addr_type(struct net *net, __be32 addr);
+unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev,
+ __be32 addr);
+void ip_rt_multicast_event(struct in_device *);
+int ip_rt_ioctl(struct net *, unsigned int cmd, void __user *arg);
+void ip_rt_get_source(u8 *src, struct sk_buff *skb, struct rtable *rt);
+int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb);
struct in_ifaddr;
-extern void fib_add_ifaddr(struct in_ifaddr *);
-extern void fib_del_ifaddr(struct in_ifaddr *, struct in_ifaddr *);
+void fib_add_ifaddr(struct in_ifaddr *);
+void fib_del_ifaddr(struct in_ifaddr *, struct in_ifaddr *);
static inline void ip_rt_put(struct rtable *rt)
{
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 702664833a53..bb13a182fba6 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -8,14 +8,12 @@ typedef int (*rtnl_doit_func)(struct sk_buff *, struct nlmsghdr *);
typedef int (*rtnl_dumpit_func)(struct sk_buff *, struct netlink_callback *);
typedef u16 (*rtnl_calcit_func)(struct sk_buff *, struct nlmsghdr *);
-extern int __rtnl_register(int protocol, int msgtype,
- rtnl_doit_func, rtnl_dumpit_func,
- rtnl_calcit_func);
-extern void rtnl_register(int protocol, int msgtype,
- rtnl_doit_func, rtnl_dumpit_func,
- rtnl_calcit_func);
-extern int rtnl_unregister(int protocol, int msgtype);
-extern void rtnl_unregister_all(int protocol);
+int __rtnl_register(int protocol, int msgtype,
+ rtnl_doit_func, rtnl_dumpit_func, rtnl_calcit_func);
+void rtnl_register(int protocol, int msgtype,
+ rtnl_doit_func, rtnl_dumpit_func, rtnl_calcit_func);
+int rtnl_unregister(int protocol, int msgtype);
+void rtnl_unregister_all(int protocol);
static inline int rtnl_msg_family(const struct nlmsghdr *nlh)
{
@@ -83,11 +81,11 @@ struct rtnl_link_ops {
unsigned int (*get_num_rx_queues)(void);
};
-extern int __rtnl_link_register(struct rtnl_link_ops *ops);
-extern void __rtnl_link_unregister(struct rtnl_link_ops *ops);
+int __rtnl_link_register(struct rtnl_link_ops *ops);
+void __rtnl_link_unregister(struct rtnl_link_ops *ops);
-extern int rtnl_link_register(struct rtnl_link_ops *ops);
-extern void rtnl_link_unregister(struct rtnl_link_ops *ops);
+int rtnl_link_register(struct rtnl_link_ops *ops);
+void rtnl_link_unregister(struct rtnl_link_ops *ops);
/**
* struct rtnl_af_ops - rtnetlink address family operations
@@ -117,18 +115,18 @@ struct rtnl_af_ops {
const struct nlattr *attr);
};
-extern int __rtnl_af_register(struct rtnl_af_ops *ops);
-extern void __rtnl_af_unregister(struct rtnl_af_ops *ops);
+int __rtnl_af_register(struct rtnl_af_ops *ops);
+void __rtnl_af_unregister(struct rtnl_af_ops *ops);
-extern int rtnl_af_register(struct rtnl_af_ops *ops);
-extern void rtnl_af_unregister(struct rtnl_af_ops *ops);
+int rtnl_af_register(struct rtnl_af_ops *ops);
+void rtnl_af_unregister(struct rtnl_af_ops *ops);
+struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]);
+struct net_device *rtnl_create_link(struct net *net, char *ifname,
+ const struct rtnl_link_ops *ops,
+ struct nlattr *tb[]);
+int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm);
-extern struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]);
-extern struct net_device *rtnl_create_link(struct net *net,
- char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]);
-extern int rtnl_configure_link(struct net_device *dev,
- const struct ifinfomsg *ifm);
extern const struct nla_policy ifla_policy[IFLA_MAX+1];
#define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index f4eb365f7dcd..d0a6321c302e 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -702,13 +702,20 @@ static inline u64 psched_l2t_ns(const struct psched_ratecfg *r,
}
void psched_ratecfg_precompute(struct psched_ratecfg *r,
- const struct tc_ratespec *conf);
+ const struct tc_ratespec *conf,
+ u64 rate64);
static inline void psched_ratecfg_getrate(struct tc_ratespec *res,
const struct psched_ratecfg *r)
{
memset(res, 0, sizeof(*res));
- res->rate = r->rate_bytes_ps;
+
+ /* legacy struct tc_ratespec has a 32bit @rate field
+ * Qdisc using 64bit rate should add new attributes
+ * in order to maintain compatibility.
+ */
+ res->rate = min_t(u64, r->rate_bytes_ps, ~0U);
+
res->overhead = r->overhead;
res->linklayer = (r->linklayer & TC_LINKLAYER_MASK);
}
diff --git a/include/net/scm.h b/include/net/scm.h
index 8de2d37d2077..262532d111f5 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -33,11 +33,11 @@ struct scm_cookie {
#endif
};
-extern void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm);
-extern void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm);
-extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm);
-extern void __scm_destroy(struct scm_cookie *scm);
-extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl);
+void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm);
+void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm);
+int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm);
+void __scm_destroy(struct scm_cookie *scm);
+struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl);
#ifdef CONFIG_SECURITY_NETWORK
static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 3794c5ad20fe..c5fe80697f8d 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -90,12 +90,11 @@
/*
* sctp/protocol.c
*/
-extern int sctp_copy_local_addr_list(struct net *, struct sctp_bind_addr *,
- sctp_scope_t, gfp_t gfp,
- int flags);
-extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
-extern int sctp_register_pf(struct sctp_pf *, sa_family_t);
-extern void sctp_addr_wq_mgmt(struct net *, struct sctp_sockaddr_entry *, int);
+int sctp_copy_local_addr_list(struct net *, struct sctp_bind_addr *,
+ sctp_scope_t, gfp_t gfp, int flags);
+struct sctp_pf *sctp_get_pf_specific(sa_family_t family);
+int sctp_register_pf(struct sctp_pf *, sa_family_t);
+void sctp_addr_wq_mgmt(struct net *, struct sctp_sockaddr_entry *, int);
/*
* sctp/socket.c
@@ -110,7 +109,7 @@ void sctp_sock_rfree(struct sk_buff *skb);
void sctp_copy_sock(struct sock *newsk, struct sock *sk,
struct sctp_association *asoc);
extern struct percpu_counter sctp_sockets_allocated;
-extern int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *);
+int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *);
/*
* sctp/primitive.c
diff --git a/include/net/secure_seq.h b/include/net/secure_seq.h
index 6ca975bebd37..52c1a906f288 100644
--- a/include/net/secure_seq.h
+++ b/include/net/secure_seq.h
@@ -3,19 +3,19 @@
#include <linux/types.h>
-extern void net_secret_init(void);
-extern __u32 secure_ip_id(__be32 daddr);
-extern __u32 secure_ipv6_id(const __be32 daddr[4]);
-extern u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
-extern u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
- __be16 dport);
-extern __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
- __be16 sport, __be16 dport);
-extern __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
- __be16 sport, __be16 dport);
-extern u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
- __be16 sport, __be16 dport);
-extern u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
- __be16 sport, __be16 dport);
+void net_secret_init(void);
+__u32 secure_ip_id(__be32 daddr);
+__u32 secure_ipv6_id(const __be32 daddr[4]);
+u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
+u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
+ __be16 dport);
+__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
+ __be16 sport, __be16 dport);
+__u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
+ __be16 sport, __be16 dport);
+u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
+ __be16 sport, __be16 dport);
+u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
+ __be16 sport, __be16 dport);
#endif /* _NET_SECURE_SEQ */
diff --git a/include/net/sock.h b/include/net/sock.h
index 6ba2e7b0e2b1..4625d2eff461 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -746,7 +746,7 @@ static inline int sk_stream_wspace(const struct sock *sk)
return sk->sk_sndbuf - sk->sk_wmem_queued;
}
-extern void sk_stream_write_space(struct sock *sk);
+void sk_stream_write_space(struct sock *sk);
/* OOB backlog add */
static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb)
@@ -788,7 +788,7 @@ static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *s
return 0;
}
-extern int __sk_backlog_rcv(struct sock *sk, struct sk_buff *skb);
+int __sk_backlog_rcv(struct sock *sk, struct sk_buff *skb);
static inline int sk_backlog_rcv(struct sock *sk, struct sk_buff *skb)
{
@@ -853,15 +853,15 @@ static inline void sock_rps_reset_rxhash(struct sock *sk)
__rc; \
})
-extern int sk_stream_wait_connect(struct sock *sk, long *timeo_p);
-extern int sk_stream_wait_memory(struct sock *sk, long *timeo_p);
-extern void sk_stream_wait_close(struct sock *sk, long timeo_p);
-extern int sk_stream_error(struct sock *sk, int flags, int err);
-extern void sk_stream_kill_queues(struct sock *sk);
-extern void sk_set_memalloc(struct sock *sk);
-extern void sk_clear_memalloc(struct sock *sk);
+int sk_stream_wait_connect(struct sock *sk, long *timeo_p);
+int sk_stream_wait_memory(struct sock *sk, long *timeo_p);
+void sk_stream_wait_close(struct sock *sk, long timeo_p);
+int sk_stream_error(struct sock *sk, int flags, int err);
+void sk_stream_kill_queues(struct sock *sk);
+void sk_set_memalloc(struct sock *sk);
+void sk_clear_memalloc(struct sock *sk);
-extern int sk_wait_data(struct sock *sk, long *timeo);
+int sk_wait_data(struct sock *sk, long *timeo);
struct request_sock_ops;
struct timewait_sock_ops;
@@ -1031,8 +1031,8 @@ struct cg_proto {
struct mem_cgroup *memcg;
};
-extern int proto_register(struct proto *prot, int alloc_slab);
-extern void proto_unregister(struct proto *prot);
+int proto_register(struct proto *prot, int alloc_slab);
+void proto_unregister(struct proto *prot);
static inline bool memcg_proto_active(struct cg_proto *cg_proto)
{
@@ -1287,8 +1287,8 @@ proto_memory_pressure(struct proto *prot)
#ifdef CONFIG_PROC_FS
/* Called with local bh disabled */
-extern void sock_prot_inuse_add(struct net *net, struct proto *prot, int inc);
-extern int sock_prot_inuse_get(struct net *net, struct proto *proto);
+void sock_prot_inuse_add(struct net *net, struct proto *prot, int inc);
+int sock_prot_inuse_get(struct net *net, struct proto *proto);
#else
static inline void sock_prot_inuse_add(struct net *net, struct proto *prot,
int inc)
@@ -1364,8 +1364,8 @@ static inline struct inode *SOCK_INODE(struct socket *socket)
/*
* Functions for memory accounting
*/
-extern int __sk_mem_schedule(struct sock *sk, int size, int kind);
-extern void __sk_mem_reclaim(struct sock *sk);
+int __sk_mem_schedule(struct sock *sk, int size, int kind);
+void __sk_mem_reclaim(struct sock *sk);
#define SK_MEM_QUANTUM ((int)PAGE_SIZE)
#define SK_MEM_QUANTUM_SHIFT ilog2(SK_MEM_QUANTUM)
@@ -1473,14 +1473,14 @@ do { \
lockdep_init_map(&(sk)->sk_lock.dep_map, (name), (key), 0); \
} while (0)
-extern void lock_sock_nested(struct sock *sk, int subclass);
+void lock_sock_nested(struct sock *sk, int subclass);
static inline void lock_sock(struct sock *sk)
{
lock_sock_nested(sk, 0);
}
-extern void release_sock(struct sock *sk);
+void release_sock(struct sock *sk);
/* BH context may only use the following locking interface. */
#define bh_lock_sock(__sk) spin_lock(&((__sk)->sk_lock.slock))
@@ -1489,7 +1489,7 @@ extern void release_sock(struct sock *sk);
SINGLE_DEPTH_NESTING)
#define bh_unlock_sock(__sk) spin_unlock(&((__sk)->sk_lock.slock))
-extern bool lock_sock_fast(struct sock *sk);
+bool lock_sock_fast(struct sock *sk);
/**
* unlock_sock_fast - complement of lock_sock_fast
* @sk: socket
@@ -1507,108 +1507,84 @@ static inline void unlock_sock_fast(struct sock *sk, bool slow)
}
-extern struct sock *sk_alloc(struct net *net, int family,
- gfp_t priority,
- struct proto *prot);
-extern void sk_free(struct sock *sk);
-extern void sk_release_kernel(struct sock *sk);
-extern struct sock *sk_clone_lock(const struct sock *sk,
- const gfp_t priority);
-
-extern struct sk_buff *sock_wmalloc(struct sock *sk,
- unsigned long size, int force,
- gfp_t priority);
-extern struct sk_buff *sock_rmalloc(struct sock *sk,
- unsigned long size, int force,
- gfp_t priority);
-extern void sock_wfree(struct sk_buff *skb);
-extern void skb_orphan_partial(struct sk_buff *skb);
-extern void sock_rfree(struct sk_buff *skb);
-extern void sock_edemux(struct sk_buff *skb);
-
-extern int sock_setsockopt(struct socket *sock, int level,
- int op, char __user *optval,
- unsigned int optlen);
-
-extern int sock_getsockopt(struct socket *sock, int level,
- int op, char __user *optval,
- int __user *optlen);
-extern struct sk_buff *sock_alloc_send_skb(struct sock *sk,
- unsigned long size,
- int noblock,
- int *errcode);
-extern struct sk_buff *sock_alloc_send_pskb(struct sock *sk,
- unsigned long header_len,
- unsigned long data_len,
- int noblock,
- int *errcode,
- int max_page_order);
-extern void *sock_kmalloc(struct sock *sk, int size,
- gfp_t priority);
-extern void sock_kfree_s(struct sock *sk, void *mem, int size);
-extern void sk_send_sigurg(struct sock *sk);
+struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
+ struct proto *prot);
+void sk_free(struct sock *sk);
+void sk_release_kernel(struct sock *sk);
+struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority);
+
+struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force,
+ gfp_t priority);
+struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force,
+ gfp_t priority);
+void sock_wfree(struct sk_buff *skb);
+void skb_orphan_partial(struct sk_buff *skb);
+void sock_rfree(struct sk_buff *skb);
+void sock_edemux(struct sk_buff *skb);
+
+int sock_setsockopt(struct socket *sock, int level, int op,
+ char __user *optval, unsigned int optlen);
+
+int sock_getsockopt(struct socket *sock, int level, int op,
+ char __user *optval, int __user *optlen);
+struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size,
+ int noblock, int *errcode);
+struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
+ unsigned long data_len, int noblock,
+ int *errcode, int max_page_order);
+void *sock_kmalloc(struct sock *sk, int size, gfp_t priority);
+void sock_kfree_s(struct sock *sk, void *mem, int size);
+void sk_send_sigurg(struct sock *sk);
/*
* Functions to fill in entries in struct proto_ops when a protocol
* does not implement a particular function.
*/
-extern int sock_no_bind(struct socket *,
- struct sockaddr *, int);
-extern int sock_no_connect(struct socket *,
- struct sockaddr *, int, int);
-extern int sock_no_socketpair(struct socket *,
- struct socket *);
-extern int sock_no_accept(struct socket *,
- struct socket *, int);
-extern int sock_no_getname(struct socket *,
- struct sockaddr *, int *, int);
-extern unsigned int sock_no_poll(struct file *, struct socket *,
- struct poll_table_struct *);
-extern int sock_no_ioctl(struct socket *, unsigned int,
- unsigned long);
-extern int sock_no_listen(struct socket *, int);
-extern int sock_no_shutdown(struct socket *, int);
-extern int sock_no_getsockopt(struct socket *, int , int,
- char __user *, int __user *);
-extern int sock_no_setsockopt(struct socket *, int, int,
- char __user *, unsigned int);
-extern int sock_no_sendmsg(struct kiocb *, struct socket *,
- struct msghdr *, size_t);
-extern int sock_no_recvmsg(struct kiocb *, struct socket *,
- struct msghdr *, size_t, int);
-extern int sock_no_mmap(struct file *file,
- struct socket *sock,
- struct vm_area_struct *vma);
-extern ssize_t sock_no_sendpage(struct socket *sock,
- struct page *page,
- int offset, size_t size,
- int flags);
+int sock_no_bind(struct socket *, struct sockaddr *, int);
+int sock_no_connect(struct socket *, struct sockaddr *, int, int);
+int sock_no_socketpair(struct socket *, struct socket *);
+int sock_no_accept(struct socket *, struct socket *, int);
+int sock_no_getname(struct socket *, struct sockaddr *, int *, int);
+unsigned int sock_no_poll(struct file *, struct socket *,
+ struct poll_table_struct *);
+int sock_no_ioctl(struct socket *, unsigned int, unsigned long);
+int sock_no_listen(struct socket *, int);
+int sock_no_shutdown(struct socket *, int);
+int sock_no_getsockopt(struct socket *, int , int, char __user *, int __user *);
+int sock_no_setsockopt(struct socket *, int, int, char __user *, unsigned int);
+int sock_no_sendmsg(struct kiocb *, struct socket *, struct msghdr *, size_t);
+int sock_no_recvmsg(struct kiocb *, struct socket *, struct msghdr *, size_t,
+ int);
+int sock_no_mmap(struct file *file, struct socket *sock,
+ struct vm_area_struct *vma);
+ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset,
+ size_t size, int flags);
/*
* Functions to fill in entries in struct proto_ops when a protocol
* uses the inet style.
*/
-extern int sock_common_getsockopt(struct socket *sock, int level, int optname,
+int sock_common_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen);
-extern int sock_common_recvmsg(struct kiocb *iocb, struct socket *sock,
+int sock_common_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size, int flags);
-extern int sock_common_setsockopt(struct socket *sock, int level, int optname,
+int sock_common_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, unsigned int optlen);
-extern int compat_sock_common_getsockopt(struct socket *sock, int level,
+int compat_sock_common_getsockopt(struct socket *sock, int level,
int optname, char __user *optval, int __user *optlen);
-extern int compat_sock_common_setsockopt(struct socket *sock, int level,
+int compat_sock_common_setsockopt(struct socket *sock, int level,
int optname, char __user *optval, unsigned int optlen);
-extern void sk_common_release(struct sock *sk);
+void sk_common_release(struct sock *sk);
/*
* Default socket callbacks and setup code
*/
/* Initialise core socket variables */
-extern void sock_init_data(struct socket *sock, struct sock *sk);
+void sock_init_data(struct socket *sock, struct sock *sk);
-extern void sk_filter_release_rcu(struct rcu_head *rcu);
+void sk_filter_release_rcu(struct rcu_head *rcu);
/**
* sk_filter_release - release a socket filter
@@ -1669,8 +1645,7 @@ static inline void sock_put(struct sock *sk)
sk_free(sk);
}
-extern int sk_receive_skb(struct sock *sk, struct sk_buff *skb,
- const int nested);
+int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested);
static inline void sk_tx_queue_set(struct sock *sk, int tx_queue)
{
@@ -1724,8 +1699,8 @@ static inline void sock_graft(struct sock *sk, struct socket *parent)
write_unlock_bh(&sk->sk_callback_lock);
}
-extern kuid_t sock_i_uid(struct sock *sk);
-extern unsigned long sock_i_ino(struct sock *sk);
+kuid_t sock_i_uid(struct sock *sk);
+unsigned long sock_i_ino(struct sock *sk);
static inline struct dst_entry *
__sk_dst_get(struct sock *sk)
@@ -1747,7 +1722,7 @@ sk_dst_get(struct sock *sk)
return dst;
}
-extern void sk_reset_txq(struct sock *sk);
+void sk_reset_txq(struct sock *sk);
static inline void dst_negative_advice(struct sock *sk)
{
@@ -1800,16 +1775,16 @@ sk_dst_reset(struct sock *sk)
spin_unlock(&sk->sk_dst_lock);
}
-extern struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie);
+struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie);
-extern struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie);
+struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie);
static inline bool sk_can_gso(const struct sock *sk)
{
return net_gso_ok(sk->sk_route_caps, sk->sk_gso_type);
}
-extern void sk_setup_caps(struct sock *sk, struct dst_entry *dst);
+void sk_setup_caps(struct sock *sk, struct dst_entry *dst);
static inline void sk_nocaps_add(struct sock *sk, netdev_features_t flags)
{
@@ -2022,14 +1997,14 @@ static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
sk_mem_charge(sk, skb->truesize);
}
-extern void sk_reset_timer(struct sock *sk, struct timer_list *timer,
- unsigned long expires);
+void sk_reset_timer(struct sock *sk, struct timer_list *timer,
+ unsigned long expires);
-extern void sk_stop_timer(struct sock *sk, struct timer_list *timer);
+void sk_stop_timer(struct sock *sk, struct timer_list *timer);
-extern int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
+int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
-extern int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb);
+int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb);
/*
* Recover an error report and clear atomically
@@ -2097,7 +2072,7 @@ static inline struct page_frag *sk_page_frag(struct sock *sk)
return &sk->sk_frag;
}
-extern bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag);
+bool sk_page_frag_refill(struct sock *sk, struct page_frag *pfrag);
/*
* Default write policy as shown to user space via poll/select/SIGIO
@@ -2135,10 +2110,10 @@ static inline int sock_intr_errno(long timeo)
return timeo == MAX_SCHEDULE_TIMEOUT ? -ERESTARTSYS : -EINTR;
}
-extern void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
- struct sk_buff *skb);
-extern void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
- struct sk_buff *skb);
+void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
+ struct sk_buff *skb);
+void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
+ struct sk_buff *skb);
static inline void
sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
@@ -2171,8 +2146,8 @@ sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
__sock_recv_wifi_status(msg, sk, skb);
}
-extern void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
- struct sk_buff *skb);
+void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
+ struct sk_buff *skb);
static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
struct sk_buff *skb)
@@ -2197,7 +2172,7 @@ static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
*
* Currently only depends on SOCK_TIMESTAMPING* flags.
*/
-extern void sock_tx_timestamp(struct sock *sk, __u8 *tx_flags);
+void sock_tx_timestamp(struct sock *sk, __u8 *tx_flags);
/**
* sk_eat_skb - Release a skb if it is no longer needed
@@ -2261,11 +2236,11 @@ static inline struct sock *skb_steal_sock(struct sk_buff *skb)
return NULL;
}
-extern void sock_enable_timestamp(struct sock *sk, int flag);
-extern int sock_get_timestamp(struct sock *, struct timeval __user *);
-extern int sock_get_timestampns(struct sock *, struct timespec __user *);
-extern int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len,
- int level, int type);
+void sock_enable_timestamp(struct sock *sk, int flag);
+int sock_get_timestamp(struct sock *, struct timeval __user *);
+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);
/*
* Enable debug/info messages
diff --git a/include/net/stp.h b/include/net/stp.h
index ad447f105417..3af174d70d9e 100644
--- a/include/net/stp.h
+++ b/include/net/stp.h
@@ -8,7 +8,7 @@ struct stp_proto {
void *data;
};
-extern int stp_proto_register(const struct stp_proto *proto);
-extern void stp_proto_unregister(const struct stp_proto *proto);
+int stp_proto_register(const struct stp_proto *proto);
+void stp_proto_unregister(const struct stp_proto *proto);
#endif /* _NET_STP_H */
diff --git a/include/net/tcp.h b/include/net/tcp.h
index b1aa324c5e65..de870ee5582d 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -50,7 +50,7 @@
extern struct inet_hashinfo tcp_hashinfo;
extern struct percpu_counter tcp_orphan_count;
-extern void tcp_time_wait(struct sock *sk, int state, int timeo);
+void tcp_time_wait(struct sock *sk, int state, int timeo);
#define MAX_TCP_HEADER (128 + MAX_HEADER)
#define MAX_TCP_OPTION_SPACE 40
@@ -325,7 +325,7 @@ static inline bool tcp_too_many_orphans(struct sock *sk, int shift)
return false;
}
-extern bool tcp_check_oom(struct sock *sk, int shift);
+bool tcp_check_oom(struct sock *sk, int shift);
/* syncookies: remember time of last synqueue overflow */
static inline void tcp_synq_overflow(struct sock *sk)
@@ -348,38 +348,38 @@ extern struct proto tcp_prot;
#define TCP_ADD_STATS_USER(net, field, val) SNMP_ADD_STATS_USER((net)->mib.tcp_statistics, field, val)
#define TCP_ADD_STATS(net, field, val) SNMP_ADD_STATS((net)->mib.tcp_statistics, field, val)
-extern void tcp_init_mem(struct net *net);
-
-extern void tcp_tasklet_init(void);
-
-extern void tcp_v4_err(struct sk_buff *skb, u32);
-
-extern void tcp_shutdown (struct sock *sk, int how);
-
-extern void tcp_v4_early_demux(struct sk_buff *skb);
-extern int tcp_v4_rcv(struct sk_buff *skb);
-
-extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
-extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
- size_t size);
-extern int tcp_sendpage(struct sock *sk, struct page *page, int offset,
- size_t size, int flags);
-extern void tcp_release_cb(struct sock *sk);
-extern void tcp_wfree(struct sk_buff *skb);
-extern void tcp_write_timer_handler(struct sock *sk);
-extern void tcp_delack_timer_handler(struct sock *sk);
-extern int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg);
-extern int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
- const struct tcphdr *th, unsigned int len);
-extern void tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
- const struct tcphdr *th, unsigned int len);
-extern void tcp_rcv_space_adjust(struct sock *sk);
-extern void tcp_cleanup_rbuf(struct sock *sk, int copied);
-extern int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp);
-extern void tcp_twsk_destructor(struct sock *sk);
-extern ssize_t tcp_splice_read(struct socket *sk, loff_t *ppos,
- struct pipe_inode_info *pipe, size_t len,
- unsigned int flags);
+void tcp_init_mem(struct net *net);
+
+void tcp_tasklet_init(void);
+
+void tcp_v4_err(struct sk_buff *skb, u32);
+
+void tcp_shutdown(struct sock *sk, int how);
+
+void tcp_v4_early_demux(struct sk_buff *skb);
+int tcp_v4_rcv(struct sk_buff *skb);
+
+int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
+int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ size_t size);
+int tcp_sendpage(struct sock *sk, struct page *page, int offset, size_t size,
+ int flags);
+void tcp_release_cb(struct sock *sk);
+void tcp_wfree(struct sk_buff *skb);
+void tcp_write_timer_handler(struct sock *sk);
+void tcp_delack_timer_handler(struct sock *sk);
+int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg);
+int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
+ const struct tcphdr *th, unsigned int len);
+void tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
+ const struct tcphdr *th, unsigned int len);
+void tcp_rcv_space_adjust(struct sock *sk);
+void tcp_cleanup_rbuf(struct sock *sk, int copied);
+int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp);
+void tcp_twsk_destructor(struct sock *sk);
+ssize_t tcp_splice_read(struct socket *sk, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t len,
+ unsigned int flags);
static inline void tcp_dec_quickack_mode(struct sock *sk,
const unsigned int pkts)
@@ -409,66 +409,65 @@ enum tcp_tw_status {
};
-extern enum tcp_tw_status tcp_timewait_state_process(struct inet_timewait_sock *tw,
- struct sk_buff *skb,
- const struct tcphdr *th);
-extern struct sock * tcp_check_req(struct sock *sk,struct sk_buff *skb,
- struct request_sock *req,
- struct request_sock **prev,
- bool fastopen);
-extern int tcp_child_process(struct sock *parent, struct sock *child,
- struct sk_buff *skb);
-extern void tcp_enter_loss(struct sock *sk, int how);
-extern void tcp_clear_retrans(struct tcp_sock *tp);
-extern void tcp_update_metrics(struct sock *sk);
-extern void tcp_init_metrics(struct sock *sk);
-extern void tcp_metrics_init(void);
-extern bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst, bool paws_check);
-extern bool tcp_remember_stamp(struct sock *sk);
-extern bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw);
-extern void tcp_fetch_timewait_stamp(struct sock *sk, struct dst_entry *dst);
-extern void tcp_disable_fack(struct tcp_sock *tp);
-extern void tcp_close(struct sock *sk, long timeout);
-extern void tcp_init_sock(struct sock *sk);
-extern unsigned int tcp_poll(struct file * file, struct socket *sock,
- struct poll_table_struct *wait);
-extern int tcp_getsockopt(struct sock *sk, int level, int optname,
+enum tcp_tw_status tcp_timewait_state_process(struct inet_timewait_sock *tw,
+ struct sk_buff *skb,
+ const struct tcphdr *th);
+struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
+ struct request_sock *req, struct request_sock **prev,
+ bool fastopen);
+int tcp_child_process(struct sock *parent, struct sock *child,
+ struct sk_buff *skb);
+void tcp_enter_loss(struct sock *sk, int how);
+void tcp_clear_retrans(struct tcp_sock *tp);
+void tcp_update_metrics(struct sock *sk);
+void tcp_init_metrics(struct sock *sk);
+void tcp_metrics_init(void);
+bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst,
+ bool paws_check);
+bool tcp_remember_stamp(struct sock *sk);
+bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw);
+void tcp_fetch_timewait_stamp(struct sock *sk, struct dst_entry *dst);
+void tcp_disable_fack(struct tcp_sock *tp);
+void tcp_close(struct sock *sk, long timeout);
+void tcp_init_sock(struct sock *sk);
+unsigned int tcp_poll(struct file *file, struct socket *sock,
+ struct poll_table_struct *wait);
+int tcp_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+int tcp_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, unsigned int optlen);
+int compat_tcp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
-extern int tcp_setsockopt(struct sock *sk, int level, int optname,
+int compat_tcp_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, unsigned int optlen);
-extern int compat_tcp_getsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int __user *optlen);
-extern int compat_tcp_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, unsigned int optlen);
-extern void tcp_set_keepalive(struct sock *sk, int val);
-extern void tcp_syn_ack_timeout(struct sock *sk, struct request_sock *req);
-extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
- size_t len, int nonblock, int flags, int *addr_len);
-extern void tcp_parse_options(const struct sk_buff *skb,
- struct tcp_options_received *opt_rx,
- int estab, struct tcp_fastopen_cookie *foc);
-extern const u8 *tcp_parse_md5sig_option(const struct tcphdr *th);
+void tcp_set_keepalive(struct sock *sk, int val);
+void tcp_syn_ack_timeout(struct sock *sk, struct request_sock *req);
+int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ size_t len, int nonblock, int flags, int *addr_len);
+void tcp_parse_options(const struct sk_buff *skb,
+ struct tcp_options_received *opt_rx,
+ int estab, struct tcp_fastopen_cookie *foc);
+const u8 *tcp_parse_md5sig_option(const struct tcphdr *th);
/*
* TCP v4 functions exported for the inet6 API
*/
-extern void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb);
-extern int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb);
-extern struct sock * tcp_create_openreq_child(struct sock *sk,
- struct request_sock *req,
- struct sk_buff *skb);
-extern struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
- struct request_sock *req,
- struct dst_entry *dst);
-extern int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb);
-extern int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
- int addr_len);
-extern int tcp_connect(struct sock *sk);
-extern struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
- struct request_sock *req,
- struct tcp_fastopen_cookie *foc);
-extern int tcp_disconnect(struct sock *sk, int flags);
+void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb);
+int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb);
+struct sock *tcp_create_openreq_child(struct sock *sk,
+ struct request_sock *req,
+ struct sk_buff *skb);
+struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
+ struct request_sock *req,
+ struct dst_entry *dst);
+int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb);
+int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
+int tcp_connect(struct sock *sk);
+struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
+ struct request_sock *req,
+ struct tcp_fastopen_cookie *foc);
+int tcp_disconnect(struct sock *sk, int flags);
void tcp_connect_init(struct sock *sk);
void tcp_finish_connect(struct sock *sk, struct sk_buff *skb);
@@ -477,15 +476,32 @@ void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb);
/* From syncookies.c */
extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS];
-extern int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th,
- u32 cookie);
-extern struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
- struct ip_options *opt);
+int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th,
+ u32 cookie);
+struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+ struct ip_options *opt);
#ifdef CONFIG_SYN_COOKIES
-extern u32 __cookie_v4_init_sequence(const struct iphdr *iph,
- const struct tcphdr *th, u16 *mssp);
-extern __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb,
- __u16 *mss);
+#include <linux/ktime.h>
+
+/* Syncookies use a monotonic timer which increments every 64 seconds.
+ * This counter is used both as a hash input and partially encoded into
+ * the cookie value. A cookie is only validated further if the delta
+ * between the current counter value and the encoded one is less than this,
+ * i.e. a sent cookie is valid only at most for 128 seconds (or less if
+ * the counter advances immediately after a cookie is generated).
+ */
+#define MAX_SYNCOOKIE_AGE 2
+
+static inline u32 tcp_cookie_time(void)
+{
+ struct timespec now;
+ getnstimeofday(&now);
+ return now.tv_sec >> 6; /* 64 seconds granularity */
+}
+
+u32 __cookie_v4_init_sequence(const struct iphdr *iph, const struct tcphdr *th,
+ u16 *mssp);
+__u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mss);
#else
static inline __u32 cookie_v4_init_sequence(struct sock *sk,
struct sk_buff *skb,
@@ -495,19 +511,19 @@ static inline __u32 cookie_v4_init_sequence(struct sock *sk,
}
#endif
-extern __u32 cookie_init_timestamp(struct request_sock *req);
-extern bool cookie_check_timestamp(struct tcp_options_received *opt,
- struct net *net, bool *ecn_ok);
+__u32 cookie_init_timestamp(struct request_sock *req);
+bool cookie_check_timestamp(struct tcp_options_received *opt, struct net *net,
+ bool *ecn_ok);
/* From net/ipv6/syncookies.c */
-extern int __cookie_v6_check(const struct ipv6hdr *iph, const struct tcphdr *th,
- u32 cookie);
-extern struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb);
+int __cookie_v6_check(const struct ipv6hdr *iph, const struct tcphdr *th,
+ u32 cookie);
+struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb);
#ifdef CONFIG_SYN_COOKIES
-extern u32 __cookie_v6_init_sequence(const struct ipv6hdr *iph,
- const struct tcphdr *th, u16 *mssp);
-extern __u32 cookie_v6_init_sequence(struct sock *sk, const struct sk_buff *skb,
- __u16 *mss);
+u32 __cookie_v6_init_sequence(const struct ipv6hdr *iph,
+ const struct tcphdr *th, u16 *mssp);
+__u32 cookie_v6_init_sequence(struct sock *sk, const struct sk_buff *skb,
+ __u16 *mss);
#else
static inline __u32 cookie_v6_init_sequence(struct sock *sk,
struct sk_buff *skb,
@@ -518,47 +534,46 @@ static inline __u32 cookie_v6_init_sequence(struct sock *sk,
#endif
/* tcp_output.c */
-extern void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
- int nonagle);
-extern bool tcp_may_send_now(struct sock *sk);
-extern int __tcp_retransmit_skb(struct sock *, struct sk_buff *);
-extern int tcp_retransmit_skb(struct sock *, struct sk_buff *);
-extern void tcp_retransmit_timer(struct sock *sk);
-extern void tcp_xmit_retransmit_queue(struct sock *);
-extern void tcp_simple_retransmit(struct sock *);
-extern int tcp_trim_head(struct sock *, struct sk_buff *, u32);
-extern int tcp_fragment(struct sock *, struct sk_buff *, u32, unsigned int);
-
-extern void tcp_send_probe0(struct sock *);
-extern void tcp_send_partial(struct sock *);
-extern int tcp_write_wakeup(struct sock *);
-extern void tcp_send_fin(struct sock *sk);
-extern void tcp_send_active_reset(struct sock *sk, gfp_t priority);
-extern int tcp_send_synack(struct sock *);
-extern bool tcp_syn_flood_action(struct sock *sk,
- const struct sk_buff *skb,
- const char *proto);
-extern void tcp_push_one(struct sock *, unsigned int mss_now);
-extern void tcp_send_ack(struct sock *sk);
-extern void tcp_send_delayed_ack(struct sock *sk);
-extern void tcp_send_loss_probe(struct sock *sk);
-extern bool tcp_schedule_loss_probe(struct sock *sk);
+void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
+ int nonagle);
+bool tcp_may_send_now(struct sock *sk);
+int __tcp_retransmit_skb(struct sock *, struct sk_buff *);
+int tcp_retransmit_skb(struct sock *, struct sk_buff *);
+void tcp_retransmit_timer(struct sock *sk);
+void tcp_xmit_retransmit_queue(struct sock *);
+void tcp_simple_retransmit(struct sock *);
+int tcp_trim_head(struct sock *, struct sk_buff *, u32);
+int tcp_fragment(struct sock *, struct sk_buff *, u32, unsigned int);
+
+void tcp_send_probe0(struct sock *);
+void tcp_send_partial(struct sock *);
+int tcp_write_wakeup(struct sock *);
+void tcp_send_fin(struct sock *sk);
+void tcp_send_active_reset(struct sock *sk, gfp_t priority);
+int tcp_send_synack(struct sock *);
+bool tcp_syn_flood_action(struct sock *sk, const struct sk_buff *skb,
+ const char *proto);
+void tcp_push_one(struct sock *, unsigned int mss_now);
+void tcp_send_ack(struct sock *sk);
+void tcp_send_delayed_ack(struct sock *sk);
+void tcp_send_loss_probe(struct sock *sk);
+bool tcp_schedule_loss_probe(struct sock *sk);
/* tcp_input.c */
-extern void tcp_cwnd_application_limited(struct sock *sk);
-extern void tcp_resume_early_retransmit(struct sock *sk);
-extern void tcp_rearm_rto(struct sock *sk);
-extern void tcp_reset(struct sock *sk);
+void tcp_cwnd_application_limited(struct sock *sk);
+void tcp_resume_early_retransmit(struct sock *sk);
+void tcp_rearm_rto(struct sock *sk);
+void tcp_reset(struct sock *sk);
/* tcp_timer.c */
-extern void tcp_init_xmit_timers(struct sock *);
+void tcp_init_xmit_timers(struct sock *);
static inline void tcp_clear_xmit_timers(struct sock *sk)
{
inet_csk_clear_xmit_timers(sk);
}
-extern unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu);
-extern unsigned int tcp_current_mss(struct sock *sk);
+unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu);
+unsigned int tcp_current_mss(struct sock *sk);
/* Bound MSS / TSO packet size with the half of the window */
static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize)
@@ -584,20 +599,20 @@ static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize)
}
/* tcp.c */
-extern void tcp_get_info(const struct sock *, struct tcp_info *);
+void tcp_get_info(const struct sock *, struct tcp_info *);
/* Read 'sendfile()'-style from a TCP socket */
typedef int (*sk_read_actor_t)(read_descriptor_t *, struct sk_buff *,
unsigned int, size_t);
-extern int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
- sk_read_actor_t recv_actor);
+int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
+ sk_read_actor_t recv_actor);
-extern void tcp_initialize_rcv_mss(struct sock *sk);
+void tcp_initialize_rcv_mss(struct sock *sk);
-extern int tcp_mtu_to_mss(struct sock *sk, int pmtu);
-extern int tcp_mss_to_mtu(struct sock *sk, int mss);
-extern void tcp_mtup_init(struct sock *sk);
-extern void tcp_init_buffer_space(struct sock *sk);
+int tcp_mtu_to_mss(struct sock *sk, int pmtu);
+int tcp_mss_to_mtu(struct sock *sk, int mss);
+void tcp_mtup_init(struct sock *sk);
+void tcp_init_buffer_space(struct sock *sk);
static inline void tcp_bound_rto(const struct sock *sk)
{
@@ -610,7 +625,7 @@ static inline u32 __tcp_set_rto(const struct tcp_sock *tp)
return (tp->srtt >> 3) + tp->rttvar;
}
-extern void tcp_set_rto(struct sock *sk);
+void tcp_set_rto(struct sock *sk);
static inline void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd)
{
@@ -663,7 +678,7 @@ static inline u32 tcp_receive_window(const struct tcp_sock *tp)
* scaling applied to the result. The caller does these things
* if necessary. This is a "raw" window selection.
*/
-extern u32 __tcp_select_window(struct sock *sk);
+u32 __tcp_select_window(struct sock *sk);
void tcp_send_window_probe(struct sock *sk);
@@ -800,24 +815,24 @@ struct tcp_congestion_ops {
struct module *owner;
};
-extern int tcp_register_congestion_control(struct tcp_congestion_ops *type);
-extern void tcp_unregister_congestion_control(struct tcp_congestion_ops *type);
+int tcp_register_congestion_control(struct tcp_congestion_ops *type);
+void tcp_unregister_congestion_control(struct tcp_congestion_ops *type);
-extern void tcp_init_congestion_control(struct sock *sk);
-extern void tcp_cleanup_congestion_control(struct sock *sk);
-extern int tcp_set_default_congestion_control(const char *name);
-extern void tcp_get_default_congestion_control(char *name);
-extern void tcp_get_available_congestion_control(char *buf, size_t len);
-extern void tcp_get_allowed_congestion_control(char *buf, size_t len);
-extern int tcp_set_allowed_congestion_control(char *allowed);
-extern int tcp_set_congestion_control(struct sock *sk, const char *name);
-extern void tcp_slow_start(struct tcp_sock *tp);
-extern void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w);
+void tcp_init_congestion_control(struct sock *sk);
+void tcp_cleanup_congestion_control(struct sock *sk);
+int tcp_set_default_congestion_control(const char *name);
+void tcp_get_default_congestion_control(char *name);
+void tcp_get_available_congestion_control(char *buf, size_t len);
+void tcp_get_allowed_congestion_control(char *buf, size_t len);
+int tcp_set_allowed_congestion_control(char *allowed);
+int tcp_set_congestion_control(struct sock *sk, const char *name);
+void tcp_slow_start(struct tcp_sock *tp);
+void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w);
extern struct tcp_congestion_ops tcp_init_congestion_ops;
-extern u32 tcp_reno_ssthresh(struct sock *sk);
-extern void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 in_flight);
-extern u32 tcp_reno_min_cwnd(const struct sock *sk);
+u32 tcp_reno_ssthresh(struct sock *sk);
+void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 in_flight);
+u32 tcp_reno_min_cwnd(const struct sock *sk);
extern struct tcp_congestion_ops tcp_reno;
static inline void tcp_set_ca_state(struct sock *sk, const u8 ca_state)
@@ -936,8 +951,8 @@ static inline __u32 tcp_current_ssthresh(const struct sock *sk)
/* Use define here intentionally to get WARN_ON location shown at the caller */
#define tcp_verify_left_out(tp) WARN_ON(tcp_left_out(tp) > tp->packets_out)
-extern void tcp_enter_cwr(struct sock *sk, const int set_ssthresh);
-extern __u32 tcp_init_cwnd(const struct tcp_sock *tp, const struct dst_entry *dst);
+void tcp_enter_cwr(struct sock *sk, const int set_ssthresh);
+__u32 tcp_init_cwnd(const struct tcp_sock *tp, const struct dst_entry *dst);
/* The maximum number of MSS of available cwnd for which TSO defers
* sending if not using sysctl_tcp_tso_win_divisor.
@@ -963,7 +978,7 @@ static inline u32 tcp_wnd_end(const struct tcp_sock *tp)
{
return tp->snd_una + tp->snd_wnd;
}
-extern bool tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight);
+bool tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight);
static inline void tcp_minshall_update(struct tcp_sock *tp, unsigned int mss,
const struct sk_buff *skb)
@@ -1028,7 +1043,7 @@ static inline void tcp_prequeue_init(struct tcp_sock *tp)
#endif
}
-extern bool tcp_prequeue(struct sock *sk, struct sk_buff *skb);
+bool tcp_prequeue(struct sock *sk, struct sk_buff *skb);
#undef STATE_TRACE
@@ -1039,9 +1054,9 @@ static const char *statename[]={
"Close Wait","Last ACK","Listen","Closing"
};
#endif
-extern void tcp_set_state(struct sock *sk, int state);
+void tcp_set_state(struct sock *sk, int state);
-extern void tcp_done(struct sock *sk);
+void tcp_done(struct sock *sk);
static inline void tcp_sack_reset(struct tcp_options_received *rx_opt)
{
@@ -1049,13 +1064,12 @@ static inline void tcp_sack_reset(struct tcp_options_received *rx_opt)
rx_opt->num_sacks = 0;
}
-extern u32 tcp_default_init_rwnd(u32 mss);
+u32 tcp_default_init_rwnd(u32 mss);
/* Determine a window scaling and initial window to offer. */
-extern void tcp_select_initial_window(int __space, __u32 mss,
- __u32 *rcv_wnd, __u32 *window_clamp,
- int wscale_ok, __u8 *rcv_wscale,
- __u32 init_rcv_wnd);
+void tcp_select_initial_window(int __space, __u32 mss, __u32 *rcv_wnd,
+ __u32 *window_clamp, int wscale_ok,
+ __u8 *rcv_wscale, __u32 init_rcv_wnd);
static inline int tcp_win_from_space(int space)
{
@@ -1099,7 +1113,7 @@ static inline void tcp_openreq_init(struct request_sock *req,
ireq->loc_port = tcp_hdr(skb)->dest;
}
-extern void tcp_enter_memory_pressure(struct sock *sk);
+void tcp_enter_memory_pressure(struct sock *sk);
static inline int keepalive_intvl_when(const struct tcp_sock *tp)
{
@@ -1252,21 +1266,20 @@ struct tcp_md5sig_pool {
};
/* - functions */
-extern int tcp_v4_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key,
- const struct sock *sk,
- const struct request_sock *req,
- const struct sk_buff *skb);
-extern int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
- int family, const u8 *newkey,
- u8 newkeylen, gfp_t gfp);
-extern int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr,
- int family);
-extern struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk,
+int tcp_v4_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key,
+ const struct sock *sk, const struct request_sock *req,
+ const struct sk_buff *skb);
+int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
+ int family, const u8 *newkey, u8 newkeylen, gfp_t gfp);
+int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr,
+ int family);
+struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk,
struct sock *addr_sk);
#ifdef CONFIG_TCP_MD5SIG
-extern struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk,
- const union tcp_md5_addr *addr, int family);
+struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk,
+ const union tcp_md5_addr *addr,
+ int family);
#define tcp_twsk_md5_key(twsk) ((twsk)->tw_md5_key)
#else
static inline struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk,
@@ -1278,27 +1291,26 @@ static inline struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk,
#define tcp_twsk_md5_key(twsk) NULL
#endif
-extern bool tcp_alloc_md5sig_pool(void);
+bool tcp_alloc_md5sig_pool(void);
-extern struct tcp_md5sig_pool *tcp_get_md5sig_pool(void);
+struct tcp_md5sig_pool *tcp_get_md5sig_pool(void);
static inline void tcp_put_md5sig_pool(void)
{
local_bh_enable();
}
-extern int tcp_md5_hash_header(struct tcp_md5sig_pool *, const struct tcphdr *);
-extern int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, const struct sk_buff *,
- unsigned int header_len);
-extern int tcp_md5_hash_key(struct tcp_md5sig_pool *hp,
- const struct tcp_md5sig_key *key);
+int tcp_md5_hash_header(struct tcp_md5sig_pool *, const struct tcphdr *);
+int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, const struct sk_buff *,
+ unsigned int header_len);
+int tcp_md5_hash_key(struct tcp_md5sig_pool *hp,
+ const struct tcp_md5sig_key *key);
/* From tcp_fastopen.c */
-extern void tcp_fastopen_cache_get(struct sock *sk, u16 *mss,
- struct tcp_fastopen_cookie *cookie,
- int *syn_loss, unsigned long *last_syn_loss);
-extern void tcp_fastopen_cache_set(struct sock *sk, u16 mss,
- struct tcp_fastopen_cookie *cookie,
- bool syn_lost);
+void tcp_fastopen_cache_get(struct sock *sk, u16 *mss,
+ struct tcp_fastopen_cookie *cookie, int *syn_loss,
+ unsigned long *last_syn_loss);
+void tcp_fastopen_cache_set(struct sock *sk, u16 mss,
+ struct tcp_fastopen_cookie *cookie, bool syn_lost);
struct tcp_fastopen_request {
/* Fast Open cookie. Size 0 means a cookie request */
struct tcp_fastopen_cookie cookie;
@@ -1309,8 +1321,8 @@ void tcp_free_fastopen_req(struct tcp_sock *tp);
extern struct tcp_fastopen_context __rcu *tcp_fastopen_ctx;
int tcp_fastopen_reset_cipher(void *key, unsigned int len);
-extern void tcp_fastopen_cookie_gen(__be32 src, __be32 dst,
- struct tcp_fastopen_cookie *foc);
+void tcp_fastopen_cookie_gen(__be32 src, __be32 dst,
+ struct tcp_fastopen_cookie *foc);
#define TCP_FASTOPEN_KEY_LENGTH 16
@@ -1529,22 +1541,20 @@ struct tcp_iter_state {
loff_t last_pos;
};
-extern int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo);
-extern void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo);
+int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo);
+void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo);
extern struct request_sock_ops tcp_request_sock_ops;
extern struct request_sock_ops tcp6_request_sock_ops;
-extern void tcp_v4_destroy_sock(struct sock *sk);
+void tcp_v4_destroy_sock(struct sock *sk);
-extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
- netdev_features_t features);
-extern struct sk_buff **tcp_gro_receive(struct sk_buff **head,
- struct sk_buff *skb);
-extern int tcp_gro_complete(struct sk_buff *skb);
+struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
+ netdev_features_t features);
+struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb);
+int tcp_gro_complete(struct sk_buff *skb);
-extern void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr,
- __be32 daddr);
+void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, __be32 daddr);
static inline u32 tcp_notsent_lowat(const struct tcp_sock *tp)
{
@@ -1560,8 +1570,8 @@ static inline bool tcp_stream_memory_free(const struct sock *sk)
}
#ifdef CONFIG_PROC_FS
-extern int tcp4_proc_init(void);
-extern void tcp4_proc_exit(void);
+int tcp4_proc_init(void);
+void tcp4_proc_exit(void);
#endif
/* TCP af-specific functions */
@@ -1592,9 +1602,9 @@ struct tcp_request_sock_ops {
#endif
};
-extern int tcpv4_offload_init(void);
+int tcpv4_offload_init(void);
-extern void tcp_v4_init(void);
-extern void tcp_init(void);
+void tcp_v4_init(void);
+void tcp_init(void);
#endif /* _TCP_H */
diff --git a/include/net/udp.h b/include/net/udp.h
index ef2e0b7843a0..510b8cb4d1a7 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -79,7 +79,7 @@ struct udp_table {
unsigned int log;
};
extern struct udp_table udp_table;
-extern void udp_table_init(struct udp_table *, const char *);
+void udp_table_init(struct udp_table *, const char *);
static inline struct udp_hslot *udp_hashslot(struct udp_table *table,
struct net *net, unsigned int num)
{
@@ -162,52 +162,52 @@ static inline void udp_lib_hash(struct sock *sk)
BUG();
}
-extern void udp_lib_unhash(struct sock *sk);
-extern void udp_lib_rehash(struct sock *sk, u16 new_hash);
+void udp_lib_unhash(struct sock *sk);
+void udp_lib_rehash(struct sock *sk, u16 new_hash);
static inline void udp_lib_close(struct sock *sk, long timeout)
{
sk_common_release(sk);
}
-extern int udp_lib_get_port(struct sock *sk, unsigned short snum,
- int (*)(const struct sock *,const struct sock *),
- unsigned int hash2_nulladdr);
+int udp_lib_get_port(struct sock *sk, unsigned short snum,
+ int (*)(const struct sock *, const struct sock *),
+ unsigned int hash2_nulladdr);
/* net/ipv4/udp.c */
-extern int udp_get_port(struct sock *sk, unsigned short snum,
- int (*saddr_cmp)(const struct sock *,
- const struct sock *));
-extern void udp_err(struct sk_buff *, u32);
-extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk,
- struct msghdr *msg, size_t len);
-extern int udp_push_pending_frames(struct sock *sk);
-extern void udp_flush_pending_frames(struct sock *sk);
-extern void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst);
-extern int udp_rcv(struct sk_buff *skb);
-extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
-extern int udp_disconnect(struct sock *sk, int flags);
-extern unsigned int udp_poll(struct file *file, struct socket *sock,
- poll_table *wait);
-extern struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
- netdev_features_t features);
-extern int udp_lib_getsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int __user *optlen);
-extern int udp_lib_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, unsigned int optlen,
- int (*push_pending_frames)(struct sock *));
-extern struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
- __be32 daddr, __be16 dport,
- int dif);
-extern struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
- __be32 daddr, __be16 dport,
- int dif, struct udp_table *tbl);
-extern struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport,
- const struct in6_addr *daddr, __be16 dport,
- int dif);
-extern struct sock *__udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport,
- const struct in6_addr *daddr, __be16 dport,
- int dif, struct udp_table *tbl);
+int udp_get_port(struct sock *sk, unsigned short snum,
+ int (*saddr_cmp)(const struct sock *,
+ const struct sock *));
+void udp_err(struct sk_buff *, u32);
+int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ size_t len);
+int udp_push_pending_frames(struct sock *sk);
+void udp_flush_pending_frames(struct sock *sk);
+void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst);
+int udp_rcv(struct sk_buff *skb);
+int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
+int udp_disconnect(struct sock *sk, int flags);
+unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait);
+struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
+ netdev_features_t features);
+int udp_lib_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+int udp_lib_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, unsigned int optlen,
+ int (*push_pending_frames)(struct sock *));
+struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
+ __be32 daddr, __be16 dport, int dif);
+struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
+ __be32 daddr, __be16 dport, int dif,
+ struct udp_table *tbl);
+struct sock *udp6_lib_lookup(struct net *net,
+ const struct in6_addr *saddr, __be16 sport,
+ const struct in6_addr *daddr, __be16 dport,
+ int dif);
+struct sock *__udp6_lib_lookup(struct net *net,
+ const struct in6_addr *saddr, __be16 sport,
+ const struct in6_addr *daddr, __be16 dport,
+ int dif, struct udp_table *tbl);
/*
* SNMP statistics for UDP and UDP-Lite
@@ -259,19 +259,19 @@ struct udp_iter_state {
};
#ifdef CONFIG_PROC_FS
-extern int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo);
-extern void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo);
+int udp_proc_register(struct net *net, struct udp_seq_afinfo *afinfo);
+void udp_proc_unregister(struct net *net, struct udp_seq_afinfo *afinfo);
-extern int udp4_proc_init(void);
-extern void udp4_proc_exit(void);
+int udp4_proc_init(void);
+void udp4_proc_exit(void);
#endif
-extern int udpv4_offload_init(void);
+int udpv4_offload_init(void);
-extern void udp_init(void);
+void udp_init(void);
-extern void udp_encap_enable(void);
+void udp_encap_enable(void);
#if IS_ENABLED(CONFIG_IPV6)
-extern void udpv6_encap_enable(void);
+void udpv6_encap_enable(void);
#endif
#endif /* _UDP_H */
diff --git a/include/net/udplite.h b/include/net/udplite.h
index 71375459a884..2caadabcd07b 100644
--- a/include/net/udplite.h
+++ b/include/net/udplite.h
@@ -126,7 +126,7 @@ static inline __wsum udplite_csum(struct sk_buff *skb)
return skb_checksum(skb, off, len, 0);
}
-extern void udplite4_register(void);
-extern int udplite_get_port(struct sock *sk, unsigned short snum,
- int (*scmp)(const struct sock *, const struct sock *));
+void udplite4_register(void);
+int udplite_get_port(struct sock *sk, unsigned short snum,
+ int (*scmp)(const struct sock *, const struct sock *));
#endif /* _UDPLITE_H */
diff --git a/include/net/wext.h b/include/net/wext.h
index 4f6e7423174c..345911965dbb 100644
--- a/include/net/wext.h
+++ b/include/net/wext.h
@@ -6,13 +6,13 @@
struct net;
#ifdef CONFIG_WEXT_CORE
-extern int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
- void __user *arg);
-extern int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
- unsigned long arg);
+int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
+ void __user *arg);
+int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
+ unsigned long arg);
-extern struct iw_statistics *get_wireless_stats(struct net_device *dev);
-extern int call_commit_handler(struct net_device *dev);
+struct iw_statistics *get_wireless_stats(struct net_device *dev);
+int call_commit_handler(struct net_device *dev);
#else
static inline int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
void __user *arg)
@@ -27,8 +27,8 @@ static inline int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
#endif
#ifdef CONFIG_WEXT_PROC
-extern int wext_proc_init(struct net *net);
-extern void wext_proc_exit(struct net *net);
+int wext_proc_init(struct net *net);
+void wext_proc_exit(struct net *net);
#else
static inline int wext_proc_init(struct net *net)
{
diff --git a/include/net/wimax.h b/include/net/wimax.h
index bbb74f990cab..98498e1daa06 100644
--- a/include/net/wimax.h
+++ b/include/net/wimax.h
@@ -438,9 +438,9 @@ struct wimax_dev {
*
* These functions are not exported to user space.
*/
-extern void wimax_dev_init(struct wimax_dev *);
-extern int wimax_dev_add(struct wimax_dev *, struct net_device *);
-extern void wimax_dev_rm(struct wimax_dev *);
+void wimax_dev_init(struct wimax_dev *);
+int wimax_dev_add(struct wimax_dev *, struct net_device *);
+void wimax_dev_rm(struct wimax_dev *);
static inline
struct wimax_dev *net_dev_to_wimax(struct net_device *net_dev)
@@ -454,8 +454,8 @@ struct device *wimax_dev_to_dev(struct wimax_dev *wimax_dev)
return wimax_dev->net_dev->dev.parent;
}
-extern void wimax_state_change(struct wimax_dev *, enum wimax_st);
-extern enum wimax_st wimax_state_get(struct wimax_dev *);
+void wimax_state_change(struct wimax_dev *, enum wimax_st);
+enum wimax_st wimax_state_get(struct wimax_dev *);
/*
* Radio Switch state reporting.
@@ -463,8 +463,8 @@ extern enum wimax_st wimax_state_get(struct wimax_dev *);
* enum wimax_rf_state is declared in linux/wimax.h so the exports
* to user space can use it.
*/
-extern void wimax_report_rfkill_hw(struct wimax_dev *, enum wimax_rf_state);
-extern void wimax_report_rfkill_sw(struct wimax_dev *, enum wimax_rf_state);
+void wimax_report_rfkill_hw(struct wimax_dev *, enum wimax_rf_state);
+void wimax_report_rfkill_sw(struct wimax_dev *, enum wimax_rf_state);
/*
@@ -490,15 +490,14 @@ extern void wimax_report_rfkill_sw(struct wimax_dev *, enum wimax_rf_state);
* send diagnostics information that a device-specific diagnostics
* tool would be interested in.
*/
-extern struct sk_buff *wimax_msg_alloc(struct wimax_dev *, const char *,
- const void *, size_t, gfp_t);
-extern int wimax_msg_send(struct wimax_dev *, struct sk_buff *);
-extern int wimax_msg(struct wimax_dev *, const char *,
- const void *, size_t, gfp_t);
+struct sk_buff *wimax_msg_alloc(struct wimax_dev *, const char *, const void *,
+ size_t, gfp_t);
+int wimax_msg_send(struct wimax_dev *, struct sk_buff *);
+int wimax_msg(struct wimax_dev *, const char *, const void *, size_t, gfp_t);
-extern const void *wimax_msg_data_len(struct sk_buff *, size_t *);
-extern const void *wimax_msg_data(struct sk_buff *);
-extern ssize_t wimax_msg_len(struct sk_buff *);
+const void *wimax_msg_data_len(struct sk_buff *, size_t *);
+const void *wimax_msg_data(struct sk_buff *);
+ssize_t wimax_msg_len(struct sk_buff *);
/*
@@ -513,7 +512,7 @@ extern ssize_t wimax_msg_len(struct sk_buff *);
* device's control structure and (as such) the 'struct wimax_dev' is
* referenced by the caller.
*/
-extern int wimax_rfkill(struct wimax_dev *, enum wimax_rf_state);
-extern int wimax_reset(struct wimax_dev *);
+int wimax_rfkill(struct wimax_dev *, enum wimax_rf_state);
+int wimax_reset(struct wimax_dev *);
#endif /* #ifndef __NET__WIMAX_H__ */
diff --git a/include/net/x25.h b/include/net/x25.h
index b4a8a8923128..c383aa4edbf0 100644
--- a/include/net/x25.h
+++ b/include/net/x25.h
@@ -187,57 +187,57 @@ extern int sysctl_x25_clear_request_timeout;
extern int sysctl_x25_ack_holdback_timeout;
extern int sysctl_x25_forward;
-extern int x25_parse_address_block(struct sk_buff *skb,
- struct x25_address *called_addr,
- struct x25_address *calling_addr);
-
-extern int x25_addr_ntoa(unsigned char *, struct x25_address *,
- struct x25_address *);
-extern int x25_addr_aton(unsigned char *, struct x25_address *,
- struct x25_address *);
-extern struct sock *x25_find_socket(unsigned int, struct x25_neigh *);
-extern void x25_destroy_socket_from_timer(struct sock *);
-extern int x25_rx_call_request(struct sk_buff *, struct x25_neigh *, unsigned int);
-extern void x25_kill_by_neigh(struct x25_neigh *);
+int x25_parse_address_block(struct sk_buff *skb,
+ struct x25_address *called_addr,
+ struct x25_address *calling_addr);
+
+int x25_addr_ntoa(unsigned char *, struct x25_address *, struct x25_address *);
+int x25_addr_aton(unsigned char *, struct x25_address *, struct x25_address *);
+struct sock *x25_find_socket(unsigned int, struct x25_neigh *);
+void x25_destroy_socket_from_timer(struct sock *);
+int x25_rx_call_request(struct sk_buff *, struct x25_neigh *, unsigned int);
+void x25_kill_by_neigh(struct x25_neigh *);
/* x25_dev.c */
-extern void x25_send_frame(struct sk_buff *, struct x25_neigh *);
-extern int x25_lapb_receive_frame(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);
-extern void x25_establish_link(struct x25_neigh *);
-extern void x25_terminate_link(struct x25_neigh *);
+void x25_send_frame(struct sk_buff *, struct x25_neigh *);
+int x25_lapb_receive_frame(struct sk_buff *, struct net_device *,
+ struct packet_type *, struct net_device *);
+void x25_establish_link(struct x25_neigh *);
+void x25_terminate_link(struct x25_neigh *);
/* x25_facilities.c */
-extern int x25_parse_facilities(struct sk_buff *, struct x25_facilities *,
- struct x25_dte_facilities *, unsigned long *);
-extern int x25_create_facilities(unsigned char *, struct x25_facilities *,
- struct x25_dte_facilities *, unsigned long);
-extern int x25_negotiate_facilities(struct sk_buff *, struct sock *,
- struct x25_facilities *,
- struct x25_dte_facilities *);
-extern void x25_limit_facilities(struct x25_facilities *, struct x25_neigh *);
+int x25_parse_facilities(struct sk_buff *, struct x25_facilities *,
+ struct x25_dte_facilities *, unsigned long *);
+int x25_create_facilities(unsigned char *, struct x25_facilities *,
+ struct x25_dte_facilities *, unsigned long);
+int x25_negotiate_facilities(struct sk_buff *, struct sock *,
+ struct x25_facilities *,
+ struct x25_dte_facilities *);
+void x25_limit_facilities(struct x25_facilities *, struct x25_neigh *);
/* x25_forward.c */
-extern void x25_clear_forward_by_lci(unsigned int lci);
-extern void x25_clear_forward_by_dev(struct net_device *);
-extern int x25_forward_data(int, struct x25_neigh *, struct sk_buff *);
-extern int x25_forward_call(struct x25_address *, struct x25_neigh *,
- struct sk_buff *, int);
+void x25_clear_forward_by_lci(unsigned int lci);
+void x25_clear_forward_by_dev(struct net_device *);
+int x25_forward_data(int, struct x25_neigh *, struct sk_buff *);
+int x25_forward_call(struct x25_address *, struct x25_neigh *, struct sk_buff *,
+ int);
/* x25_in.c */
-extern int x25_process_rx_frame(struct sock *, struct sk_buff *);
-extern int x25_backlog_rcv(struct sock *, struct sk_buff *);
+int x25_process_rx_frame(struct sock *, struct sk_buff *);
+int x25_backlog_rcv(struct sock *, struct sk_buff *);
/* x25_link.c */
-extern void x25_link_control(struct sk_buff *, struct x25_neigh *, unsigned short);
-extern void x25_link_device_up(struct net_device *);
-extern void x25_link_device_down(struct net_device *);
-extern void x25_link_established(struct x25_neigh *);
-extern void x25_link_terminated(struct x25_neigh *);
-extern void x25_transmit_clear_request(struct x25_neigh *, unsigned int, unsigned char);
-extern void x25_transmit_link(struct sk_buff *, struct x25_neigh *);
-extern int x25_subscr_ioctl(unsigned int, void __user *);
-extern struct x25_neigh *x25_get_neigh(struct net_device *);
-extern void x25_link_free(void);
+void x25_link_control(struct sk_buff *, struct x25_neigh *, unsigned short);
+void x25_link_device_up(struct net_device *);
+void x25_link_device_down(struct net_device *);
+void x25_link_established(struct x25_neigh *);
+void x25_link_terminated(struct x25_neigh *);
+void x25_transmit_clear_request(struct x25_neigh *, unsigned int,
+ unsigned char);
+void x25_transmit_link(struct sk_buff *, struct x25_neigh *);
+int x25_subscr_ioctl(unsigned int, void __user *);
+struct x25_neigh *x25_get_neigh(struct net_device *);
+void x25_link_free(void);
/* x25_neigh.c */
static __inline__ void x25_neigh_hold(struct x25_neigh *nb)
@@ -252,16 +252,16 @@ static __inline__ void x25_neigh_put(struct x25_neigh *nb)
}
/* x25_out.c */
-extern int x25_output(struct sock *, struct sk_buff *);
-extern void x25_kick(struct sock *);
-extern void x25_enquiry_response(struct sock *);
+int x25_output(struct sock *, struct sk_buff *);
+void x25_kick(struct sock *);
+void x25_enquiry_response(struct sock *);
/* x25_route.c */
-extern struct x25_route *x25_get_route(struct x25_address *addr);
-extern struct net_device *x25_dev_get(char *);
-extern void x25_route_device_down(struct net_device *dev);
-extern int x25_route_ioctl(unsigned int, void __user *);
-extern void x25_route_free(void);
+struct x25_route *x25_get_route(struct x25_address *addr);
+struct net_device *x25_dev_get(char *);
+void x25_route_device_down(struct net_device *dev);
+int x25_route_ioctl(unsigned int, void __user *);
+void x25_route_free(void);
static __inline__ void x25_route_hold(struct x25_route *rt)
{
@@ -275,30 +275,31 @@ static __inline__ void x25_route_put(struct x25_route *rt)
}
/* x25_subr.c */
-extern void x25_clear_queues(struct sock *);
-extern void x25_frames_acked(struct sock *, unsigned short);
-extern void x25_requeue_frames(struct sock *);
-extern int x25_validate_nr(struct sock *, unsigned short);
-extern void x25_write_internal(struct sock *, int);
-extern int x25_decode(struct sock *, struct sk_buff *, int *, int *, int *, int *, int *);
-extern void x25_disconnect(struct sock *, int, unsigned char, unsigned char);
+void x25_clear_queues(struct sock *);
+void x25_frames_acked(struct sock *, unsigned short);
+void x25_requeue_frames(struct sock *);
+int x25_validate_nr(struct sock *, unsigned short);
+void x25_write_internal(struct sock *, int);
+int x25_decode(struct sock *, struct sk_buff *, int *, int *, int *, int *,
+ int *);
+void x25_disconnect(struct sock *, int, unsigned char, unsigned char);
/* x25_timer.c */
-extern void x25_init_timers(struct sock *sk);
-extern void x25_start_heartbeat(struct sock *);
-extern void x25_start_t2timer(struct sock *);
-extern void x25_start_t21timer(struct sock *);
-extern void x25_start_t22timer(struct sock *);
-extern void x25_start_t23timer(struct sock *);
-extern void x25_stop_heartbeat(struct sock *);
-extern void x25_stop_timer(struct sock *);
-extern unsigned long x25_display_timer(struct sock *);
-extern void x25_check_rbuf(struct sock *);
+void x25_init_timers(struct sock *sk);
+void x25_start_heartbeat(struct sock *);
+void x25_start_t2timer(struct sock *);
+void x25_start_t21timer(struct sock *);
+void x25_start_t22timer(struct sock *);
+void x25_start_t23timer(struct sock *);
+void x25_stop_heartbeat(struct sock *);
+void x25_stop_timer(struct sock *);
+unsigned long x25_display_timer(struct sock *);
+void x25_check_rbuf(struct sock *);
/* sysctl_net_x25.c */
#ifdef CONFIG_SYSCTL
-extern void x25_register_sysctl(void);
-extern void x25_unregister_sysctl(void);
+void x25_register_sysctl(void);
+void x25_unregister_sysctl(void);
#else
static inline void x25_register_sysctl(void) {};
static inline void x25_unregister_sysctl(void) {};
@@ -318,6 +319,6 @@ extern rwlock_t x25_forward_list_lock;
extern struct list_head x25_neigh_list;
extern rwlock_t x25_neigh_list_lock;
-extern int x25_proc_init(void);
-extern void x25_proc_exit(void);
+int x25_proc_init(void);
+void x25_proc_exit(void);
#endif
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index e253bf0cc7ef..041820cc38b2 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -307,15 +307,17 @@ struct xfrm_policy_afinfo {
struct dst_entry *(*blackhole_route)(struct net *net, struct dst_entry *orig);
};
-extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
-extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
-extern void km_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c);
-extern void km_state_notify(struct xfrm_state *x, const struct km_event *c);
+int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
+int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
+void km_policy_notify(struct xfrm_policy *xp, int dir,
+ const struct km_event *c);
+void km_state_notify(struct xfrm_state *x, const struct km_event *c);
struct xfrm_tmpl;
-extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
-extern void km_state_expired(struct xfrm_state *x, int hard, u32 portid);
-extern int __xfrm_state_delete(struct xfrm_state *x);
+int km_query(struct xfrm_state *x, struct xfrm_tmpl *t,
+ struct xfrm_policy *pol);
+void km_state_expired(struct xfrm_state *x, int hard, u32 portid);
+int __xfrm_state_delete(struct xfrm_state *x);
struct xfrm_state_afinfo {
unsigned int family;
@@ -344,12 +346,12 @@ struct xfrm_state_afinfo {
void (*local_error)(struct sk_buff *skb, u32 mtu);
};
-extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
-extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
-extern struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
-extern void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
+int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
+int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
+struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
+void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
-extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
+void xfrm_state_delete_tunnel(struct xfrm_state *x);
struct xfrm_type {
char *description;
@@ -372,8 +374,8 @@ struct xfrm_type {
u32 (*get_mtu)(struct xfrm_state *, int size);
};
-extern int xfrm_register_type(const struct xfrm_type *type, unsigned short family);
-extern int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family);
+int xfrm_register_type(const struct xfrm_type *type, unsigned short family);
+int xfrm_unregister_type(const struct xfrm_type *type, unsigned short family);
struct xfrm_mode {
/*
@@ -434,8 +436,8 @@ enum {
XFRM_MODE_FLAG_TUNNEL = 1,
};
-extern int xfrm_register_mode(struct xfrm_mode *mode, int family);
-extern int xfrm_unregister_mode(struct xfrm_mode *mode, int family);
+int xfrm_register_mode(struct xfrm_mode *mode, int family);
+int xfrm_unregister_mode(struct xfrm_mode *mode, int family);
static inline int xfrm_af2proto(unsigned int family)
{
@@ -595,8 +597,8 @@ struct xfrm_mgr {
const struct xfrm_kmaddress *k);
};
-extern int xfrm_register_km(struct xfrm_mgr *km);
-extern int xfrm_unregister_km(struct xfrm_mgr *km);
+int xfrm_register_km(struct xfrm_mgr *km);
+int xfrm_unregister_km(struct xfrm_mgr *km);
/*
* This structure is used for the duration where packets are being
@@ -713,23 +715,23 @@ static inline void xfrm_audit_helper_usrinfo(kuid_t auid, u32 ses, u32 secid,
audit_log_task_context(audit_buf);
}
-extern void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
- kuid_t auid, u32 ses, u32 secid);
-extern void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
- kuid_t auid, u32 ses, u32 secid);
-extern void xfrm_audit_state_add(struct xfrm_state *x, int result,
- kuid_t auid, u32 ses, u32 secid);
-extern void xfrm_audit_state_delete(struct xfrm_state *x, int result,
- kuid_t auid, u32 ses, u32 secid);
-extern void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
- struct sk_buff *skb);
-extern void xfrm_audit_state_replay(struct xfrm_state *x,
- struct sk_buff *skb, __be32 net_seq);
-extern void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family);
-extern void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
- __be32 net_spi, __be32 net_seq);
-extern void xfrm_audit_state_icvfail(struct xfrm_state *x,
- struct sk_buff *skb, u8 proto);
+void xfrm_audit_policy_add(struct xfrm_policy *xp, int result, kuid_t auid,
+ u32 ses, u32 secid);
+void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result, kuid_t auid,
+ u32 ses, u32 secid);
+void xfrm_audit_state_add(struct xfrm_state *x, int result, kuid_t auid,
+ u32 ses, u32 secid);
+void xfrm_audit_state_delete(struct xfrm_state *x, int result, kuid_t auid,
+ u32 ses, u32 secid);
+void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
+ struct sk_buff *skb);
+void xfrm_audit_state_replay(struct xfrm_state *x, struct sk_buff *skb,
+ __be32 net_seq);
+void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family);
+void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family, __be32 net_spi,
+ __be32 net_seq);
+void xfrm_audit_state_icvfail(struct xfrm_state *x, struct sk_buff *skb,
+ u8 proto);
#else
static inline void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
@@ -784,7 +786,7 @@ static inline void xfrm_pol_hold(struct xfrm_policy *policy)
atomic_inc(&policy->refcnt);
}
-extern void xfrm_policy_destroy(struct xfrm_policy *policy);
+void xfrm_policy_destroy(struct xfrm_policy *policy);
static inline void xfrm_pol_put(struct xfrm_policy *policy)
{
@@ -799,7 +801,7 @@ static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
xfrm_pol_put(pols[i]);
}
-extern void __xfrm_state_destroy(struct xfrm_state *);
+void __xfrm_state_destroy(struct xfrm_state *);
static inline void __xfrm_state_put(struct xfrm_state *x)
{
@@ -903,9 +905,8 @@ __be16 xfrm_flowi_dport(const struct flowi *fl, const union flowi_uli *uli)
return port;
}
-extern bool xfrm_selector_match(const struct xfrm_selector *sel,
- const struct flowi *fl,
- unsigned short family);
+bool xfrm_selector_match(const struct xfrm_selector *sel,
+ const struct flowi *fl, unsigned short family);
#ifdef CONFIG_SECURITY_NETWORK_XFRM
/* If neither has a context --> match
@@ -975,7 +976,7 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
}
#endif
-extern void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
+void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
struct sec_path {
atomic_t refcnt;
@@ -1000,7 +1001,7 @@ secpath_get(struct sec_path *sp)
return sp;
}
-extern void __secpath_destroy(struct sec_path *sp);
+void __secpath_destroy(struct sec_path *sp);
static inline void
secpath_put(struct sec_path *sp)
@@ -1009,7 +1010,7 @@ secpath_put(struct sec_path *sp)
__secpath_destroy(sp);
}
-extern struct sec_path *secpath_dup(struct sec_path *src);
+struct sec_path *secpath_dup(struct sec_path *src);
static inline void
secpath_reset(struct sk_buff *skb)
@@ -1059,7 +1060,8 @@ xfrm_state_addr_cmp(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x, un
}
#ifdef CONFIG_XFRM
-extern int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb, unsigned short family);
+int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb,
+ unsigned short family);
static inline int __xfrm_policy_check2(struct sock *sk, int dir,
struct sk_buff *skb,
@@ -1103,8 +1105,8 @@ static inline int xfrm6_policy_check_reverse(struct sock *sk, int dir,
return __xfrm_policy_check2(sk, dir, skb, AF_INET6, 1);
}
-extern int __xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
- unsigned int family, int reverse);
+int __xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
+ unsigned int family, int reverse);
static inline int xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
unsigned int family)
@@ -1119,7 +1121,7 @@ static inline int xfrm_decode_session_reverse(struct sk_buff *skb,
return __xfrm_decode_session(skb, fl, family, 1);
}
-extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family);
+int __xfrm_route_forward(struct sk_buff *skb, unsigned short family);
static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
{
@@ -1140,7 +1142,7 @@ static inline int xfrm6_route_forward(struct sk_buff *skb)
return xfrm_route_forward(skb, AF_INET6);
}
-extern int __xfrm_sk_clone_policy(struct sock *sk);
+int __xfrm_sk_clone_policy(struct sock *sk);
static inline int xfrm_sk_clone_policy(struct sock *sk)
{
@@ -1149,7 +1151,7 @@ static inline int xfrm_sk_clone_policy(struct sock *sk)
return 0;
}
-extern int xfrm_policy_delete(struct xfrm_policy *pol, int dir);
+int xfrm_policy_delete(struct xfrm_policy *pol, int dir);
static inline void xfrm_sk_free_policy(struct sock *sk)
{
@@ -1163,7 +1165,7 @@ static inline void xfrm_sk_free_policy(struct sock *sk)
}
}
-extern void xfrm_garbage_collect(struct net *net);
+void xfrm_garbage_collect(struct net *net);
#else
@@ -1355,6 +1357,12 @@ struct xfrm_tunnel {
int priority;
};
+struct xfrm_tunnel_notifier {
+ int (*handler)(struct sk_buff *skb);
+ struct xfrm_tunnel_notifier __rcu *next;
+ int priority;
+};
+
struct xfrm6_tunnel {
int (*handler)(struct sk_buff *skb);
int (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
@@ -1363,16 +1371,16 @@ struct xfrm6_tunnel {
int priority;
};
-extern void xfrm_init(void);
-extern void xfrm4_init(void);
-extern int xfrm_state_init(struct net *net);
-extern void xfrm_state_fini(struct net *net);
-extern void xfrm4_state_init(void);
+void xfrm_init(void);
+void xfrm4_init(void);
+int xfrm_state_init(struct net *net);
+void xfrm_state_fini(struct net *net);
+void xfrm4_state_init(void);
#ifdef CONFIG_XFRM
-extern int xfrm6_init(void);
-extern void xfrm6_fini(void);
-extern int xfrm6_state_init(void);
-extern void xfrm6_state_fini(void);
+int xfrm6_init(void);
+void xfrm6_fini(void);
+int xfrm6_state_init(void);
+void xfrm6_state_fini(void);
#else
static inline int xfrm6_init(void)
{
@@ -1385,52 +1393,52 @@ static inline void xfrm6_fini(void)
#endif
#ifdef CONFIG_XFRM_STATISTICS
-extern int xfrm_proc_init(struct net *net);
-extern void xfrm_proc_fini(struct net *net);
+int xfrm_proc_init(struct net *net);
+void xfrm_proc_fini(struct net *net);
#endif
-extern int xfrm_sysctl_init(struct net *net);
+int xfrm_sysctl_init(struct net *net);
#ifdef CONFIG_SYSCTL
-extern void xfrm_sysctl_fini(struct net *net);
+void xfrm_sysctl_fini(struct net *net);
#else
static inline void xfrm_sysctl_fini(struct net *net)
{
}
#endif
-extern void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto);
-extern int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
- int (*func)(struct xfrm_state *, int, void*), void *);
-extern void xfrm_state_walk_done(struct xfrm_state_walk *walk);
-extern struct xfrm_state *xfrm_state_alloc(struct net *net);
-extern struct xfrm_state *xfrm_state_find(const xfrm_address_t *daddr,
- const xfrm_address_t *saddr,
- const struct flowi *fl,
- struct xfrm_tmpl *tmpl,
- struct xfrm_policy *pol, int *err,
- unsigned short family);
-extern struct xfrm_state *xfrm_stateonly_find(struct net *net, u32 mark,
- xfrm_address_t *daddr,
- xfrm_address_t *saddr,
- unsigned short family,
- u8 mode, u8 proto, u32 reqid);
-extern int xfrm_state_check_expire(struct xfrm_state *x);
-extern void xfrm_state_insert(struct xfrm_state *x);
-extern int xfrm_state_add(struct xfrm_state *x);
-extern int xfrm_state_update(struct xfrm_state *x);
-extern struct xfrm_state *xfrm_state_lookup(struct net *net, u32 mark,
- const xfrm_address_t *daddr, __be32 spi,
- u8 proto, unsigned short family);
-extern struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, u32 mark,
- const xfrm_address_t *daddr,
- const xfrm_address_t *saddr,
- u8 proto,
- unsigned short family);
+void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto);
+int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
+ int (*func)(struct xfrm_state *, int, void*), void *);
+void xfrm_state_walk_done(struct xfrm_state_walk *walk);
+struct xfrm_state *xfrm_state_alloc(struct net *net);
+struct xfrm_state *xfrm_state_find(const xfrm_address_t *daddr,
+ const xfrm_address_t *saddr,
+ const struct flowi *fl,
+ struct xfrm_tmpl *tmpl,
+ struct xfrm_policy *pol, int *err,
+ unsigned short family);
+struct xfrm_state *xfrm_stateonly_find(struct net *net, u32 mark,
+ xfrm_address_t *daddr,
+ xfrm_address_t *saddr,
+ unsigned short family,
+ u8 mode, u8 proto, u32 reqid);
+int xfrm_state_check_expire(struct xfrm_state *x);
+void xfrm_state_insert(struct xfrm_state *x);
+int xfrm_state_add(struct xfrm_state *x);
+int xfrm_state_update(struct xfrm_state *x);
+struct xfrm_state *xfrm_state_lookup(struct net *net, u32 mark,
+ const xfrm_address_t *daddr, __be32 spi,
+ u8 proto, unsigned short family);
+struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, u32 mark,
+ const xfrm_address_t *daddr,
+ const xfrm_address_t *saddr,
+ u8 proto,
+ unsigned short family);
#ifdef CONFIG_XFRM_SUB_POLICY
-extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
- int n, unsigned short family);
-extern int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src,
- int n, unsigned short family);
+int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n,
+ unsigned short family);
+int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
+ unsigned short family);
#else
static inline int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src,
int n, unsigned short family)
@@ -1462,68 +1470,68 @@ struct xfrmk_spdinfo {
u32 spdhmcnt;
};
-extern struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark,
- u32 seq);
-extern int xfrm_state_delete(struct xfrm_state *x);
-extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info);
-extern void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
-extern void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
-extern u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq);
-extern int xfrm_init_replay(struct xfrm_state *x);
-extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
-extern int __xfrm_init_state(struct xfrm_state *x, bool init_replay);
-extern int xfrm_init_state(struct xfrm_state *x);
-extern int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb);
-extern int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi,
- int encap_type);
-extern int xfrm_input_resume(struct sk_buff *skb, int nexthdr);
-extern int xfrm_output_resume(struct sk_buff *skb, int err);
-extern int xfrm_output(struct sk_buff *skb);
-extern int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb);
-extern void xfrm_local_error(struct sk_buff *skb, int mtu);
-extern int xfrm4_extract_header(struct sk_buff *skb);
-extern int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb);
-extern int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
- int encap_type);
-extern int xfrm4_transport_finish(struct sk_buff *skb, int async);
-extern int xfrm4_rcv(struct sk_buff *skb);
+struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq);
+int xfrm_state_delete(struct xfrm_state *x);
+int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info);
+void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
+void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
+u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq);
+int xfrm_init_replay(struct xfrm_state *x);
+int xfrm_state_mtu(struct xfrm_state *x, int mtu);
+int __xfrm_init_state(struct xfrm_state *x, bool init_replay);
+int xfrm_init_state(struct xfrm_state *x);
+int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb);
+int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type);
+int xfrm_input_resume(struct sk_buff *skb, int nexthdr);
+int xfrm_output_resume(struct sk_buff *skb, int err);
+int xfrm_output(struct sk_buff *skb);
+int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb);
+void xfrm_local_error(struct sk_buff *skb, int mtu);
+int xfrm4_extract_header(struct sk_buff *skb);
+int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb);
+int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
+ int encap_type);
+int xfrm4_transport_finish(struct sk_buff *skb, int async);
+int xfrm4_rcv(struct sk_buff *skb);
static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
{
return xfrm4_rcv_encap(skb, nexthdr, spi, 0);
}
-extern int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb);
-extern int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
-extern int xfrm4_output(struct sk_buff *skb);
-extern int xfrm4_output_finish(struct sk_buff *skb);
-extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
-extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
-extern int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel *handler);
-extern int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel *handler);
-extern void xfrm4_local_error(struct sk_buff *skb, u32 mtu);
-extern int xfrm6_extract_header(struct sk_buff *skb);
-extern int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb);
-extern int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi);
-extern int xfrm6_transport_finish(struct sk_buff *skb, int async);
-extern int xfrm6_rcv(struct sk_buff *skb);
-extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
- xfrm_address_t *saddr, u8 proto);
-extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family);
-extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family);
-extern __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr);
-extern __be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr);
-extern int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb);
-extern int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
-extern int xfrm6_output(struct sk_buff *skb);
-extern int xfrm6_output_finish(struct sk_buff *skb);
-extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
- u8 **prevhdr);
-extern void xfrm6_local_error(struct sk_buff *skb, u32 mtu);
+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_finish(struct sk_buff *skb);
+int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
+int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
+int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler);
+int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler);
+void xfrm4_local_error(struct sk_buff *skb, u32 mtu);
+int xfrm6_extract_header(struct sk_buff *skb);
+int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb);
+int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi);
+int xfrm6_transport_finish(struct sk_buff *skb, int async);
+int xfrm6_rcv(struct sk_buff *skb);
+int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
+ xfrm_address_t *saddr, u8 proto);
+int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family);
+int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler,
+ unsigned short family);
+__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_finish(struct sk_buff *skb);
+int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
+ u8 **prevhdr);
+void xfrm6_local_error(struct sk_buff *skb, u32 mtu);
#ifdef CONFIG_XFRM
-extern int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb);
-extern int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen);
+int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb);
+int xfrm_user_policy(struct sock *sk, int optname,
+ u8 __user *optval, int optlen);
#else
static inline int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
{
@@ -1540,59 +1548,62 @@ static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp);
-extern void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type);
-extern int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
- int (*func)(struct xfrm_policy *, int, int, void*), void *);
-extern void xfrm_policy_walk_done(struct xfrm_policy_walk *walk);
+void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type);
+int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
+ int (*func)(struct xfrm_policy *, int, int, void*),
+ void *);
+void xfrm_policy_walk_done(struct xfrm_policy_walk *walk);
int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark,
u8 type, int dir,
struct xfrm_selector *sel,
struct xfrm_sec_ctx *ctx, int delete,
int *err);
-struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir, u32 id, int delete, int *err);
+struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir,
+ u32 id, int delete, int *err);
int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info);
u32 xfrm_get_acqseq(void);
-extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
+int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
struct xfrm_state *xfrm_find_acq(struct net *net, const struct xfrm_mark *mark,
u8 mode, u32 reqid, u8 proto,
const xfrm_address_t *daddr,
const xfrm_address_t *saddr, int create,
unsigned short family);
-extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
+int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
#ifdef CONFIG_XFRM_MIGRATE
-extern int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
- const struct xfrm_migrate *m, int num_bundles,
- const struct xfrm_kmaddress *k);
-extern struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m);
-extern struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x,
- struct xfrm_migrate *m);
-extern int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
- struct xfrm_migrate *m, int num_bundles,
- struct xfrm_kmaddress *k);
+int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
+ const struct xfrm_migrate *m, int num_bundles,
+ const struct xfrm_kmaddress *k);
+struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m);
+struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
+ struct xfrm_migrate *m);
+int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
+ struct xfrm_migrate *m, int num_bundles,
+ struct xfrm_kmaddress *k);
#endif
-extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
-extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 portid);
-extern int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
-
-extern void xfrm_input_init(void);
-extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq);
-
-extern void xfrm_probe_algs(void);
-extern int xfrm_count_pfkey_auth_supported(void);
-extern int xfrm_count_pfkey_enc_supported(void);
-extern struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx);
-extern struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx);
-extern struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id);
-extern struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id);
-extern struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id);
-extern struct xfrm_algo_desc *xfrm_aalg_get_byname(const char *name, int probe);
-extern struct xfrm_algo_desc *xfrm_ealg_get_byname(const char *name, int probe);
-extern struct xfrm_algo_desc *xfrm_calg_get_byname(const char *name, int probe);
-extern struct xfrm_algo_desc *xfrm_aead_get_byname(const char *name, int icv_len,
- int probe);
+int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
+void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 portid);
+int km_report(struct net *net, u8 proto, struct xfrm_selector *sel,
+ xfrm_address_t *addr);
+
+void xfrm_input_init(void);
+int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq);
+
+void xfrm_probe_algs(void);
+int xfrm_count_pfkey_auth_supported(void);
+int xfrm_count_pfkey_enc_supported(void);
+struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx);
+struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx);
+struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id);
+struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id);
+struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id);
+struct xfrm_algo_desc *xfrm_aalg_get_byname(const char *name, int probe);
+struct xfrm_algo_desc *xfrm_ealg_get_byname(const char *name, int probe);
+struct xfrm_algo_desc *xfrm_calg_get_byname(const char *name, int probe);
+struct xfrm_algo_desc *xfrm_aead_get_byname(const char *name, int icv_len,
+ int probe);
static inline bool xfrm6_addr_equal(const xfrm_address_t *a,
const xfrm_address_t *b)
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index ae9a227d35d3..d8acf0ca77be 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -105,6 +105,8 @@ int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
int pll_id, int source, unsigned int freq_in, unsigned int freq_out);
+int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio);
+
/* Digital Audio interface formatting */
int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
@@ -131,6 +133,7 @@ struct snd_soc_dai_ops {
int (*set_pll)(struct snd_soc_dai *dai, int pll_id, int source,
unsigned int freq_in, unsigned int freq_out);
int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);
+ int (*set_bclk_ratio)(struct snd_soc_dai *dai, unsigned int ratio);
/*
* DAI format configuration
diff --git a/include/sound/soc.h b/include/sound/soc.h
index d22cb0a06feb..6dd329a87c46 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -13,6 +13,7 @@
#ifndef __LINUX_SND_SOC_H
#define __LINUX_SND_SOC_H
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/notifier.h>
@@ -330,7 +331,6 @@ struct soc_enum;
struct snd_soc_jack;
struct snd_soc_jack_zone;
struct snd_soc_jack_pin;
-struct snd_soc_cache_ops;
#include <sound/soc-dapm.h>
#include <sound/soc-dpcm.h>
@@ -348,10 +348,6 @@ enum snd_soc_control_type {
SND_SOC_REGMAP,
};
-enum snd_soc_compress_type {
- SND_SOC_FLAT_COMPRESSION = 1,
-};
-
enum snd_soc_pcm_subclass {
SND_SOC_PCM_CLASS_PCM = 0,
SND_SOC_PCM_CLASS_BE = 1,
@@ -369,6 +365,7 @@ int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
int snd_soc_register_card(struct snd_soc_card *card);
int snd_soc_unregister_card(struct snd_soc_card *card);
+int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card);
int snd_soc_suspend(struct device *dev);
int snd_soc_resume(struct device *dev);
int snd_soc_poweroff(struct device *dev);
@@ -386,6 +383,9 @@ void snd_soc_unregister_codec(struct device *dev);
int snd_soc_register_component(struct device *dev,
const struct snd_soc_component_driver *cmpnt_drv,
struct snd_soc_dai_driver *dai_drv, int num_dai);
+int devm_snd_soc_register_component(struct device *dev,
+ const struct snd_soc_component_driver *cmpnt_drv,
+ struct snd_soc_dai_driver *dai_drv, int num_dai);
void snd_soc_unregister_component(struct device *dev);
int snd_soc_codec_volatile_register(struct snd_soc_codec *codec,
unsigned int reg);
@@ -403,12 +403,6 @@ int snd_soc_cache_write(struct snd_soc_codec *codec,
unsigned int reg, unsigned int value);
int snd_soc_cache_read(struct snd_soc_codec *codec,
unsigned int reg, unsigned int *value);
-int snd_soc_default_volatile_register(struct snd_soc_codec *codec,
- unsigned int reg);
-int snd_soc_default_readable_register(struct snd_soc_codec *codec,
- unsigned int reg);
-int snd_soc_default_writable_register(struct snd_soc_codec *codec,
- unsigned int reg);
int snd_soc_platform_read(struct snd_soc_platform *platform,
unsigned int reg);
int snd_soc_platform_write(struct snd_soc_platform *platform,
@@ -542,22 +536,6 @@ int snd_soc_put_strobe(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
/**
- * struct snd_soc_reg_access - Describes whether a given register is
- * readable, writable or volatile.
- *
- * @reg: the register number
- * @read: whether this register is readable
- * @write: whether this register is writable
- * @vol: whether this register is volatile
- */
-struct snd_soc_reg_access {
- u16 reg;
- u16 read;
- u16 write;
- u16 vol;
-};
-
-/**
* struct snd_soc_jack_pin - Describes a pin to update based on jack detection
*
* @pin: name of the pin to update
@@ -657,17 +635,24 @@ struct snd_soc_compr_ops {
int (*trigger)(struct snd_compr_stream *);
};
-/* SoC cache ops */
-struct snd_soc_cache_ops {
+/* component interface */
+struct snd_soc_component_driver {
const char *name;
- enum snd_soc_compress_type id;
- int (*init)(struct snd_soc_codec *codec);
- int (*exit)(struct snd_soc_codec *codec);
- int (*read)(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int *value);
- int (*write)(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value);
- int (*sync)(struct snd_soc_codec *codec);
+
+ /* DT */
+ int (*of_xlate_dai_name)(struct snd_soc_component *component,
+ struct of_phandle_args *args,
+ const char **dai_name);
+};
+
+struct snd_soc_component {
+ const char *name;
+ int id;
+ int num_dai;
+ struct device *dev;
+ struct list_head list;
+
+ const struct snd_soc_component_driver *driver;
};
/* SoC Audio Codec device */
@@ -683,8 +668,6 @@ struct snd_soc_codec {
struct list_head list;
struct list_head card_list;
int num_dai;
- enum snd_soc_compress_type compress_type;
- size_t reg_size; /* reg_cache_size * reg_word_size */
int (*volatile_register)(struct snd_soc_codec *, unsigned int);
int (*readable_register)(struct snd_soc_codec *, unsigned int);
int (*writable_register)(struct snd_soc_codec *, unsigned int);
@@ -708,13 +691,13 @@ struct snd_soc_codec {
unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int);
unsigned int (*read)(struct snd_soc_codec *, unsigned int);
int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
- int (*bulk_write_raw)(struct snd_soc_codec *, unsigned int, const void *, size_t);
void *reg_cache;
- const void *reg_def_copy;
- const struct snd_soc_cache_ops *cache_ops;
struct mutex cache_rw_mutex;
int val_bytes;
+ /* component */
+ struct snd_soc_component component;
+
/* dapm */
struct snd_soc_dapm_context dapm;
unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
@@ -733,6 +716,7 @@ struct snd_soc_codec_driver {
int (*remove)(struct snd_soc_codec *);
int (*suspend)(struct snd_soc_codec *);
int (*resume)(struct snd_soc_codec *);
+ struct snd_soc_component_driver component_driver;
/* Default control and setup, added after probe() is run */
const struct snd_kcontrol_new *controls;
@@ -760,9 +744,6 @@ struct snd_soc_codec_driver {
short reg_cache_step;
short reg_word_size;
const void *reg_cache_default;
- short reg_access_size;
- const struct snd_soc_reg_access *reg_access_default;
- enum snd_soc_compress_type compress_type;
/* codec bias level */
int (*set_bias_level)(struct snd_soc_codec *,
@@ -849,20 +830,6 @@ struct snd_soc_platform {
#endif
};
-struct snd_soc_component_driver {
- const char *name;
-};
-
-struct snd_soc_component {
- const char *name;
- int id;
- int num_dai;
- struct device *dev;
- struct list_head list;
-
- const struct snd_soc_component_driver *driver;
-};
-
struct snd_soc_dai_link {
/* config - must be set by machine driver */
const char *name; /* Codec name */
@@ -944,12 +911,6 @@ struct snd_soc_codec_conf {
* associated per device
*/
const char *name_prefix;
-
- /*
- * set this to the desired compression type if you want to
- * override the one supplied in codec->driver->compress_type
- */
- enum snd_soc_compress_type compress_type;
};
struct snd_soc_aux_dev {
@@ -1121,8 +1082,6 @@ struct soc_enum {
unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg);
unsigned int snd_soc_write(struct snd_soc_codec *codec,
unsigned int reg, unsigned int val);
-unsigned int snd_soc_bulk_write_raw(struct snd_soc_codec *codec,
- unsigned int reg, const void *data, size_t len);
/* device driver data */
@@ -1201,6 +1160,8 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
const char *propname);
unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
const char *prefix);
+int snd_soc_of_get_dai_name(struct device_node *of_node,
+ const char **dai_name);
#include <sound/soc-dai.h>
diff --git a/include/trace/events/asoc.h b/include/trace/events/asoc.h
index 5fc2dcdd21cd..03996b2bb04f 100644
--- a/include/trace/events/asoc.h
+++ b/include/trace/events/asoc.h
@@ -14,6 +14,7 @@ struct snd_soc_codec;
struct snd_soc_platform;
struct snd_soc_card;
struct snd_soc_dapm_widget;
+struct snd_soc_dapm_path;
/*
* Log register events
diff --git a/include/trace/events/bcache.h b/include/trace/events/bcache.h
index 5ebda976ea93..e2b9576d00e2 100644
--- a/include/trace/events/bcache.h
+++ b/include/trace/events/bcache.h
@@ -6,11 +6,9 @@
#include <linux/tracepoint.h>
-struct search;
-
DECLARE_EVENT_CLASS(bcache_request,
- TP_PROTO(struct search *s, struct bio *bio),
- TP_ARGS(s, bio),
+ TP_PROTO(struct bcache_device *d, struct bio *bio),
+ TP_ARGS(d, bio),
TP_STRUCT__entry(
__field(dev_t, dev )
@@ -24,8 +22,8 @@ DECLARE_EVENT_CLASS(bcache_request,
TP_fast_assign(
__entry->dev = bio->bi_bdev->bd_dev;
- __entry->orig_major = s->d->disk->major;
- __entry->orig_minor = s->d->disk->first_minor;
+ __entry->orig_major = d->disk->major;
+ __entry->orig_minor = d->disk->first_minor;
__entry->sector = bio->bi_sector;
__entry->orig_sector = bio->bi_sector - 16;
__entry->nr_sector = bio->bi_size >> 9;
@@ -79,13 +77,13 @@ DECLARE_EVENT_CLASS(btree_node,
/* request.c */
DEFINE_EVENT(bcache_request, bcache_request_start,
- TP_PROTO(struct search *s, struct bio *bio),
- TP_ARGS(s, bio)
+ TP_PROTO(struct bcache_device *d, struct bio *bio),
+ TP_ARGS(d, bio)
);
DEFINE_EVENT(bcache_request, bcache_request_end,
- TP_PROTO(struct search *s, struct bio *bio),
- TP_ARGS(s, bio)
+ TP_PROTO(struct bcache_device *d, struct bio *bio),
+ TP_ARGS(d, bio)
);
DECLARE_EVENT_CLASS(bcache_bio,
@@ -370,6 +368,35 @@ DEFINE_EVENT(btree_node, bcache_btree_set_root,
TP_ARGS(b)
);
+TRACE_EVENT(bcache_keyscan,
+ TP_PROTO(unsigned nr_found,
+ unsigned start_inode, uint64_t start_offset,
+ unsigned end_inode, uint64_t end_offset),
+ TP_ARGS(nr_found,
+ start_inode, start_offset,
+ end_inode, end_offset),
+
+ TP_STRUCT__entry(
+ __field(__u32, nr_found )
+ __field(__u32, start_inode )
+ __field(__u64, start_offset )
+ __field(__u32, end_inode )
+ __field(__u64, end_offset )
+ ),
+
+ TP_fast_assign(
+ __entry->nr_found = nr_found;
+ __entry->start_inode = start_inode;
+ __entry->start_offset = start_offset;
+ __entry->end_inode = end_inode;
+ __entry->end_offset = end_offset;
+ ),
+
+ TP_printk("found %u keys from %u:%llu to %u:%llu", __entry->nr_found,
+ __entry->start_inode, __entry->start_offset,
+ __entry->end_inode, __entry->end_offset)
+);
+
/* Allocator */
TRACE_EVENT(bcache_alloc_invalidate,
diff --git a/include/trace/events/iommu.h b/include/trace/events/iommu.h
new file mode 100644
index 000000000000..a8f5c32d174b
--- /dev/null
+++ b/include/trace/events/iommu.h
@@ -0,0 +1,162 @@
+/*
+ * iommu trace points
+ *
+ * Copyright (C) 2013 Shuah Khan <shuah.kh@samsung.com>
+ *
+ */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM iommu
+
+#if !defined(_TRACE_IOMMU_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_IOMMU_H
+
+#include <linux/tracepoint.h>
+#include <linux/pci.h>
+
+struct device;
+
+DECLARE_EVENT_CLASS(iommu_group_event,
+
+ TP_PROTO(int group_id, struct device *dev),
+
+ TP_ARGS(group_id, dev),
+
+ TP_STRUCT__entry(
+ __field(int, gid)
+ __string(device, dev_name(dev))
+ ),
+
+ TP_fast_assign(
+ __entry->gid = group_id;
+ __assign_str(device, dev_name(dev));
+ ),
+
+ TP_printk("IOMMU: groupID=%d device=%s",
+ __entry->gid, __get_str(device)
+ )
+);
+
+DEFINE_EVENT(iommu_group_event, add_device_to_group,
+
+ TP_PROTO(int group_id, struct device *dev),
+
+ TP_ARGS(group_id, dev)
+
+);
+
+DEFINE_EVENT(iommu_group_event, remove_device_from_group,
+
+ TP_PROTO(int group_id, struct device *dev),
+
+ TP_ARGS(group_id, dev)
+);
+
+DECLARE_EVENT_CLASS(iommu_device_event,
+
+ TP_PROTO(struct device *dev),
+
+ TP_ARGS(dev),
+
+ TP_STRUCT__entry(
+ __string(device, dev_name(dev))
+ ),
+
+ TP_fast_assign(
+ __assign_str(device, dev_name(dev));
+ ),
+
+ TP_printk("IOMMU: device=%s", __get_str(device)
+ )
+);
+
+DEFINE_EVENT(iommu_device_event, attach_device_to_domain,
+
+ TP_PROTO(struct device *dev),
+
+ TP_ARGS(dev)
+);
+
+DEFINE_EVENT(iommu_device_event, detach_device_from_domain,
+
+ TP_PROTO(struct device *dev),
+
+ TP_ARGS(dev)
+);
+
+DECLARE_EVENT_CLASS(iommu_map_unmap,
+
+ TP_PROTO(unsigned long iova, phys_addr_t paddr, size_t size),
+
+ TP_ARGS(iova, paddr, size),
+
+ TP_STRUCT__entry(
+ __field(u64, iova)
+ __field(u64, paddr)
+ __field(int, size)
+ ),
+
+ TP_fast_assign(
+ __entry->iova = iova;
+ __entry->paddr = paddr;
+ __entry->size = size;
+ ),
+
+ TP_printk("IOMMU: iova=0x%016llx paddr=0x%016llx size=0x%x",
+ __entry->iova, __entry->paddr, __entry->size
+ )
+);
+
+DEFINE_EVENT(iommu_map_unmap, map,
+
+ TP_PROTO(unsigned long iova, phys_addr_t paddr, size_t size),
+
+ TP_ARGS(iova, paddr, size)
+);
+
+DEFINE_EVENT_PRINT(iommu_map_unmap, unmap,
+
+ TP_PROTO(unsigned long iova, phys_addr_t paddr, size_t size),
+
+ TP_ARGS(iova, paddr, size),
+
+ TP_printk("IOMMU: iova=0x%016llx size=0x%x",
+ __entry->iova, __entry->size
+ )
+);
+
+DECLARE_EVENT_CLASS(iommu_error,
+
+ TP_PROTO(struct device *dev, unsigned long iova, int flags),
+
+ TP_ARGS(dev, iova, flags),
+
+ TP_STRUCT__entry(
+ __string(device, dev_name(dev))
+ __string(driver, dev_driver_string(dev))
+ __field(u64, iova)
+ __field(int, flags)
+ ),
+
+ TP_fast_assign(
+ __assign_str(device, dev_name(dev));
+ __assign_str(driver, dev_driver_string(dev));
+ __entry->iova = iova;
+ __entry->flags = flags;
+ ),
+
+ TP_printk("IOMMU:%s %s iova=0x%016llx flags=0x%04x",
+ __get_str(driver), __get_str(device),
+ __entry->iova, __entry->flags
+ )
+);
+
+DEFINE_EVENT(iommu_error, io_page_fault,
+
+ TP_PROTO(struct device *dev, unsigned long iova, int flags),
+
+ TP_ARGS(dev, iova, flags)
+);
+#endif /* _TRACE_IOMMU_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/random.h b/include/trace/events/random.h
index 422df19de732..2ffcaec5860a 100644
--- a/include/trace/events/random.h
+++ b/include/trace/events/random.h
@@ -7,6 +7,25 @@
#include <linux/writeback.h>
#include <linux/tracepoint.h>
+TRACE_EVENT(add_device_randomness,
+ TP_PROTO(int bytes, unsigned long IP),
+
+ TP_ARGS(bytes, IP),
+
+ TP_STRUCT__entry(
+ __field( int, bytes )
+ __field(unsigned long, IP )
+ ),
+
+ TP_fast_assign(
+ __entry->bytes = bytes;
+ __entry->IP = IP;
+ ),
+
+ TP_printk("bytes %d caller %pF",
+ __entry->bytes, (void *)__entry->IP)
+);
+
DECLARE_EVENT_CLASS(random__mix_pool_bytes,
TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
@@ -68,7 +87,7 @@ TRACE_EVENT(credit_entropy_bits,
(void *)__entry->IP)
);
-TRACE_EVENT(get_random_bytes,
+DECLARE_EVENT_CLASS(random__get_random_bytes,
TP_PROTO(int nbytes, unsigned long IP),
TP_ARGS(nbytes, IP),
@@ -86,6 +105,18 @@ TRACE_EVENT(get_random_bytes,
TP_printk("nbytes %d caller %pF", __entry->nbytes, (void *)__entry->IP)
);
+DEFINE_EVENT(random__get_random_bytes, get_random_bytes,
+ TP_PROTO(int nbytes, unsigned long IP),
+
+ TP_ARGS(nbytes, IP)
+);
+
+DEFINE_EVENT(random__get_random_bytes, get_random_bytes_arch,
+ TP_PROTO(int nbytes, unsigned long IP),
+
+ TP_ARGS(nbytes, IP)
+);
+
DECLARE_EVENT_CLASS(random__extract_entropy,
TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
unsigned long IP),
diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h
index ee2376cfaab3..aca382266411 100644
--- a/include/trace/events/rcu.h
+++ b/include/trace/events/rcu.h
@@ -39,15 +39,26 @@ TRACE_EVENT(rcu_utilization,
#if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU)
/*
- * Tracepoint for grace-period events: starting and ending a grace
- * period ("start" and "end", respectively), a CPU noting the start
- * of a new grace period or the end of an old grace period ("cpustart"
- * and "cpuend", respectively), a CPU passing through a quiescent
- * state ("cpuqs"), a CPU coming online or going offline ("cpuonl"
- * and "cpuofl", respectively), a CPU being kicked for being too
- * long in dyntick-idle mode ("kick"), a CPU accelerating its new
- * callbacks to RCU_NEXT_READY_TAIL ("AccReadyCB"), and a CPU
- * accelerating its new callbacks to RCU_WAIT_TAIL ("AccWaitCB").
+ * Tracepoint for grace-period events. Takes a string identifying the
+ * RCU flavor, the grace-period number, and a string identifying the
+ * grace-period-related event as follows:
+ *
+ * "AccReadyCB": CPU acclerates new callbacks to RCU_NEXT_READY_TAIL.
+ * "AccWaitCB": CPU accelerates new callbacks to RCU_WAIT_TAIL.
+ * "newreq": Request a new grace period.
+ * "start": Start a grace period.
+ * "cpustart": CPU first notices a grace-period start.
+ * "cpuqs": CPU passes through a quiescent state.
+ * "cpuonl": CPU comes online.
+ * "cpuofl": CPU goes offline.
+ * "reqwait": GP kthread sleeps waiting for grace-period request.
+ * "reqwaitsig": GP kthread awakened by signal from reqwait state.
+ * "fqswait": GP kthread waiting until time to force quiescent states.
+ * "fqsstart": GP kthread starts forcing quiescent states.
+ * "fqsend": GP kthread done forcing quiescent states.
+ * "fqswaitsig": GP kthread awakened by signal from fqswait state.
+ * "end": End a grace period.
+ * "cpuend": CPU first notices a grace-period end.
*/
TRACE_EVENT(rcu_grace_period,
@@ -161,6 +172,46 @@ TRACE_EVENT(rcu_grace_period_init,
);
/*
+ * Tracepoint for RCU no-CBs CPU callback handoffs. This event is intended
+ * to assist debugging of these handoffs.
+ *
+ * The first argument is the name of the RCU flavor, and the second is
+ * the number of the offloaded CPU are extracted. The third and final
+ * argument is a string as follows:
+ *
+ * "WakeEmpty": Wake rcuo kthread, first CB to empty list.
+ * "WakeOvf": Wake rcuo kthread, CB list is huge.
+ * "WakeNot": Don't wake rcuo kthread.
+ * "WakeNotPoll": Don't wake rcuo kthread because it is polling.
+ * "Poll": Start of new polling cycle for rcu_nocb_poll.
+ * "Sleep": Sleep waiting for CBs for !rcu_nocb_poll.
+ * "WokeEmpty": rcuo kthread woke to find empty list.
+ * "WokeNonEmpty": rcuo kthread woke to find non-empty list.
+ * "WaitQueue": Enqueue partially done, timed wait for it to complete.
+ * "WokeQueue": Partial enqueue now complete.
+ */
+TRACE_EVENT(rcu_nocb_wake,
+
+ TP_PROTO(const char *rcuname, int cpu, const char *reason),
+
+ TP_ARGS(rcuname, cpu, reason),
+
+ TP_STRUCT__entry(
+ __field(const char *, rcuname)
+ __field(int, cpu)
+ __field(const char *, reason)
+ ),
+
+ TP_fast_assign(
+ __entry->rcuname = rcuname;
+ __entry->cpu = cpu;
+ __entry->reason = reason;
+ ),
+
+ TP_printk("%s %d %s", __entry->rcuname, __entry->cpu, __entry->reason)
+);
+
+/*
* Tracepoint for tasks blocking within preemptible-RCU read-side
* critical sections. Track the type of RCU (which one day might
* include SRCU), the grace-period number that the task is blocking
@@ -540,17 +591,17 @@ TRACE_EVENT(rcu_invoke_kfree_callback,
TRACE_EVENT(rcu_batch_end,
TP_PROTO(const char *rcuname, int callbacks_invoked,
- bool cb, bool nr, bool iit, bool risk),
+ char cb, char nr, char iit, char risk),
TP_ARGS(rcuname, callbacks_invoked, cb, nr, iit, risk),
TP_STRUCT__entry(
__field(const char *, rcuname)
__field(int, callbacks_invoked)
- __field(bool, cb)
- __field(bool, nr)
- __field(bool, iit)
- __field(bool, risk)
+ __field(char, cb)
+ __field(char, nr)
+ __field(char, iit)
+ __field(char, risk)
),
TP_fast_assign(
@@ -656,6 +707,7 @@ TRACE_EVENT(rcu_barrier,
#define trace_rcu_future_grace_period(rcuname, gpnum, completed, c, \
level, grplo, grphi, event) \
do { } while (0)
+#define trace_rcu_nocb_wake(rcuname, cpu, reason) do { } while (0)
#define trace_rcu_preempt_task(rcuname, pid, gpnum) do { } while (0)
#define trace_rcu_unlock_preempted_task(rcuname, gpnum, pid) do { } while (0)
#define trace_rcu_quiescent_state_report(rcuname, gpnum, mask, qsmask, level, \
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index 2e7d9947a10d..613381bcde40 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -100,7 +100,7 @@ static inline long __trace_sched_switch_state(struct task_struct *p)
/*
* For all intents and purposes a preempted task is a running task.
*/
- if (task_thread_info(p)->preempt_count & PREEMPT_ACTIVE)
+ if (task_preempt_count(p) & PREEMPT_ACTIVE)
state = TASK_RUNNING | TASK_STATE_MAX;
#endif
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index ece867889cc7..9b24d65fed72 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -611,12 +611,37 @@ struct drm_gem_open {
__u64 size;
};
+#define DRM_CAP_DUMB_BUFFER 0x1
+#define DRM_CAP_VBLANK_HIGH_CRTC 0x2
+#define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3
+#define DRM_CAP_DUMB_PREFER_SHADOW 0x4
+#define DRM_CAP_PRIME 0x5
+#define DRM_PRIME_CAP_IMPORT 0x1
+#define DRM_PRIME_CAP_EXPORT 0x2
+#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
+#define DRM_CAP_ASYNC_PAGE_FLIP 0x7
+
/** DRM_IOCTL_GET_CAP ioctl argument type */
struct drm_get_cap {
__u64 capability;
__u64 value;
};
+/**
+ * DRM_CLIENT_CAP_STEREO_3D
+ *
+ * if set to 1, the DRM core will expose the stereo 3D capabilities of the
+ * monitor by advertising the supported 3D layouts in the flags of struct
+ * drm_mode_modeinfo.
+ */
+#define DRM_CLIENT_CAP_STEREO_3D 1
+
+/** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
+struct drm_set_client_cap {
+ __u64 capability;
+ __u64 value;
+};
+
#define DRM_CLOEXEC O_CLOEXEC
struct drm_prime_handle {
__u32 handle;
@@ -649,6 +674,7 @@ struct drm_prime_handle {
#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink)
#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open)
#define DRM_IOCTL_GET_CAP DRM_IOWR(0x0c, struct drm_get_cap)
+#define DRM_IOCTL_SET_CLIENT_CAP DRM_IOW( 0x0d, struct drm_set_client_cap)
#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique)
#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth)
@@ -774,17 +800,6 @@ struct drm_event_vblank {
__u32 reserved;
};
-#define DRM_CAP_DUMB_BUFFER 0x1
-#define DRM_CAP_VBLANK_HIGH_CRTC 0x2
-#define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3
-#define DRM_CAP_DUMB_PREFER_SHADOW 0x4
-#define DRM_CAP_PRIME 0x5
-#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
-#define DRM_CAP_ASYNC_PAGE_FLIP 0x7
-
-#define DRM_PRIME_CAP_IMPORT 0x1
-#define DRM_PRIME_CAP_EXPORT 0x2
-
/* typedef area */
#ifndef __KERNEL__
typedef struct drm_clip_rect drm_clip_rect_t;
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 550811712f78..bafe61252754 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -44,20 +44,28 @@
/* Video mode flags */
/* bit compatible with the xorg definitions. */
-#define DRM_MODE_FLAG_PHSYNC (1<<0)
-#define DRM_MODE_FLAG_NHSYNC (1<<1)
-#define DRM_MODE_FLAG_PVSYNC (1<<2)
-#define DRM_MODE_FLAG_NVSYNC (1<<3)
-#define DRM_MODE_FLAG_INTERLACE (1<<4)
-#define DRM_MODE_FLAG_DBLSCAN (1<<5)
-#define DRM_MODE_FLAG_CSYNC (1<<6)
-#define DRM_MODE_FLAG_PCSYNC (1<<7)
-#define DRM_MODE_FLAG_NCSYNC (1<<8)
-#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */
-#define DRM_MODE_FLAG_BCAST (1<<10)
-#define DRM_MODE_FLAG_PIXMUX (1<<11)
-#define DRM_MODE_FLAG_DBLCLK (1<<12)
-#define DRM_MODE_FLAG_CLKDIV2 (1<<13)
+#define DRM_MODE_FLAG_PHSYNC (1<<0)
+#define DRM_MODE_FLAG_NHSYNC (1<<1)
+#define DRM_MODE_FLAG_PVSYNC (1<<2)
+#define DRM_MODE_FLAG_NVSYNC (1<<3)
+#define DRM_MODE_FLAG_INTERLACE (1<<4)
+#define DRM_MODE_FLAG_DBLSCAN (1<<5)
+#define DRM_MODE_FLAG_CSYNC (1<<6)
+#define DRM_MODE_FLAG_PCSYNC (1<<7)
+#define DRM_MODE_FLAG_NCSYNC (1<<8)
+#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */
+#define DRM_MODE_FLAG_BCAST (1<<10)
+#define DRM_MODE_FLAG_PIXMUX (1<<11)
+#define DRM_MODE_FLAG_DBLCLK (1<<12)
+#define DRM_MODE_FLAG_CLKDIV2 (1<<13)
+#define DRM_MODE_FLAG_3D_FRAME_PACKING (1<<14)
+#define DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE (1<<15)
+#define DRM_MODE_FLAG_3D_LINE_ALTERNATIVE (1<<16)
+#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL (1<<17)
+#define DRM_MODE_FLAG_3D_L_DEPTH (1<<18)
+#define DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (1<<19)
+#define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (1<<20)
+#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (1<<21)
/* DPMS flags */
/* bit compatible with the xorg definitions. */
@@ -165,6 +173,7 @@ struct drm_mode_get_plane_res {
#define DRM_MODE_ENCODER_LVDS 3
#define DRM_MODE_ENCODER_TVDAC 4
#define DRM_MODE_ENCODER_VIRTUAL 5
+#define DRM_MODE_ENCODER_DSI 6
struct drm_mode_get_encoder {
__u32 encoder_id;
@@ -203,6 +212,7 @@ struct drm_mode_get_encoder {
#define DRM_MODE_CONNECTOR_TV 13
#define DRM_MODE_CONNECTOR_eDP 14
#define DRM_MODE_CONNECTOR_VIRTUAL 15
+#define DRM_MODE_CONNECTOR_DSI 16
struct drm_mode_get_connector {
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 55bb5729bd78..3a4e97bd8607 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -38,10 +38,10 @@
*
* I915_L3_PARITY_UEVENT - Generated when the driver receives a parity mismatch
* event from the gpu l3 cache. Additional information supplied is ROW,
- * BANK, SUBBANK of the affected cacheline. Userspace should keep track of
- * these events and if a specific cache-line seems to have a persistent
- * error remap it with the l3 remapping tool supplied in intel-gpu-tools.
- * The value supplied with the event is always 1.
+ * BANK, SUBBANK, SLICE of the affected cacheline. Userspace should keep
+ * track of these events and if a specific cache-line seems to have a
+ * persistent error remap it with the l3 remapping tool supplied in
+ * intel-gpu-tools. The value supplied with the event is always 1.
*
* I915_ERROR_UEVENT - Generated upon error detection, currently only via
* hangcheck. The error detection event is a good indicator of when things
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index 115add2515aa..33d2b8fe166d 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -241,6 +241,8 @@ header-y += media.h
header-y += mei.h
header-y += mempolicy.h
header-y += meye.h
+header-y += mic_common.h
+header-y += mic_ioctl.h
header-y += mii.h
header-y += minix_fs.h
header-y += mman.h
diff --git a/include/uapi/linux/aio_abi.h b/include/uapi/linux/aio_abi.h
index bb2554f7fbd1..22ce4bd25013 100644
--- a/include/uapi/linux/aio_abi.h
+++ b/include/uapi/linux/aio_abi.h
@@ -44,6 +44,8 @@ enum {
IOCB_CMD_NOOP = 6,
IOCB_CMD_PREADV = 7,
IOCB_CMD_PWRITEV = 8,
+ IOCB_CMD_READ_ITER = 9,
+ IOCB_CMD_WRITE_ITER = 10,
};
/*
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 75cef3fd97ad..db0b825b4810 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -329,7 +329,6 @@ enum {
#define AUDIT_ARCH_ARMEB (EM_ARM)
#define AUDIT_ARCH_CRIS (EM_CRIS|__AUDIT_ARCH_LE)
#define AUDIT_ARCH_FRV (EM_FRV)
-#define AUDIT_ARCH_H8300 (EM_H8_300)
#define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE)
#define AUDIT_ARCH_IA64 (EM_IA_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
#define AUDIT_ARCH_M32R (EM_M32R)
diff --git a/include/uapi/linux/bcache.h b/include/uapi/linux/bcache.h
new file mode 100644
index 000000000000..164a7e263988
--- /dev/null
+++ b/include/uapi/linux/bcache.h
@@ -0,0 +1,373 @@
+#ifndef _LINUX_BCACHE_H
+#define _LINUX_BCACHE_H
+
+/*
+ * Bcache on disk data structures
+ */
+
+#include <asm/types.h>
+
+#define BITMASK(name, type, field, offset, size) \
+static inline __u64 name(const type *k) \
+{ return (k->field >> offset) & ~(~0ULL << size); } \
+ \
+static inline void SET_##name(type *k, __u64 v) \
+{ \
+ k->field &= ~(~(~0ULL << size) << offset); \
+ k->field |= (v & ~(~0ULL << size)) << offset; \
+}
+
+/* Btree keys - all units are in sectors */
+
+struct bkey {
+ __u64 high;
+ __u64 low;
+ __u64 ptr[];
+};
+
+#define KEY_FIELD(name, field, offset, size) \
+ BITMASK(name, struct bkey, field, offset, size)
+
+#define PTR_FIELD(name, offset, size) \
+static inline __u64 name(const struct bkey *k, unsigned i) \
+{ return (k->ptr[i] >> offset) & ~(~0ULL << size); } \
+ \
+static inline void SET_##name(struct bkey *k, unsigned i, __u64 v) \
+{ \
+ k->ptr[i] &= ~(~(~0ULL << size) << offset); \
+ k->ptr[i] |= (v & ~(~0ULL << size)) << offset; \
+}
+
+#define KEY_SIZE_BITS 16
+
+KEY_FIELD(KEY_PTRS, high, 60, 3)
+KEY_FIELD(HEADER_SIZE, high, 58, 2)
+KEY_FIELD(KEY_CSUM, high, 56, 2)
+KEY_FIELD(KEY_PINNED, high, 55, 1)
+KEY_FIELD(KEY_DIRTY, high, 36, 1)
+
+KEY_FIELD(KEY_SIZE, high, 20, KEY_SIZE_BITS)
+KEY_FIELD(KEY_INODE, high, 0, 20)
+
+/* Next time I change the on disk format, KEY_OFFSET() won't be 64 bits */
+
+static inline __u64 KEY_OFFSET(const struct bkey *k)
+{
+ return k->low;
+}
+
+static inline void SET_KEY_OFFSET(struct bkey *k, __u64 v)
+{
+ k->low = v;
+}
+
+/*
+ * The high bit being set is a relic from when we used it to do binary
+ * searches - it told you where a key started. It's not used anymore,
+ * and can probably be safely dropped.
+ */
+#define KEY(inode, offset, size) \
+((struct bkey) { \
+ .high = (1ULL << 63) | ((__u64) (size) << 20) | (inode), \
+ .low = (offset) \
+})
+
+#define ZERO_KEY KEY(0, 0, 0)
+
+#define MAX_KEY_INODE (~(~0 << 20))
+#define MAX_KEY_OFFSET (~0ULL >> 1)
+#define MAX_KEY KEY(MAX_KEY_INODE, MAX_KEY_OFFSET, 0)
+
+#define KEY_START(k) (KEY_OFFSET(k) - KEY_SIZE(k))
+#define START_KEY(k) KEY(KEY_INODE(k), KEY_START(k), 0)
+
+#define PTR_DEV_BITS 12
+
+PTR_FIELD(PTR_DEV, 51, PTR_DEV_BITS)
+PTR_FIELD(PTR_OFFSET, 8, 43)
+PTR_FIELD(PTR_GEN, 0, 8)
+
+#define PTR_CHECK_DEV ((1 << PTR_DEV_BITS) - 1)
+
+#define PTR(gen, offset, dev) \
+ ((((__u64) dev) << 51) | ((__u64) offset) << 8 | gen)
+
+/* Bkey utility code */
+
+static inline unsigned long bkey_u64s(const struct bkey *k)
+{
+ return (sizeof(struct bkey) / sizeof(__u64)) + KEY_PTRS(k);
+}
+
+static inline unsigned long bkey_bytes(const struct bkey *k)
+{
+ return bkey_u64s(k) * sizeof(__u64);
+}
+
+#define bkey_copy(_dest, _src) memcpy(_dest, _src, bkey_bytes(_src))
+
+static inline void bkey_copy_key(struct bkey *dest, const struct bkey *src)
+{
+ SET_KEY_INODE(dest, KEY_INODE(src));
+ SET_KEY_OFFSET(dest, KEY_OFFSET(src));
+}
+
+static inline struct bkey *bkey_next(const struct bkey *k)
+{
+ __u64 *d = (void *) k;
+ return (struct bkey *) (d + bkey_u64s(k));
+}
+
+static inline struct bkey *bkey_last(const struct bkey *k, unsigned nr_keys)
+{
+ __u64 *d = (void *) k;
+ return (struct bkey *) (d + nr_keys);
+}
+/* Enough for a key with 6 pointers */
+#define BKEY_PAD 8
+
+#define BKEY_PADDED(key) \
+ union { struct bkey key; __u64 key ## _pad[BKEY_PAD]; }
+
+/* Superblock */
+
+/* Version 0: Cache device
+ * Version 1: Backing device
+ * Version 2: Seed pointer into btree node checksum
+ * Version 3: Cache device with new UUID format
+ * Version 4: Backing device with data offset
+ */
+#define BCACHE_SB_VERSION_CDEV 0
+#define BCACHE_SB_VERSION_BDEV 1
+#define BCACHE_SB_VERSION_CDEV_WITH_UUID 3
+#define BCACHE_SB_VERSION_BDEV_WITH_OFFSET 4
+#define BCACHE_SB_MAX_VERSION 4
+
+#define SB_SECTOR 8
+#define SB_SIZE 4096
+#define SB_LABEL_SIZE 32
+#define SB_JOURNAL_BUCKETS 256U
+/* SB_JOURNAL_BUCKETS must be divisible by BITS_PER_LONG */
+#define MAX_CACHES_PER_SET 8
+
+#define BDEV_DATA_START_DEFAULT 16 /* sectors */
+
+struct cache_sb {
+ __u64 csum;
+ __u64 offset; /* sector where this sb was written */
+ __u64 version;
+
+ __u8 magic[16];
+
+ __u8 uuid[16];
+ union {
+ __u8 set_uuid[16];
+ __u64 set_magic;
+ };
+ __u8 label[SB_LABEL_SIZE];
+
+ __u64 flags;
+ __u64 seq;
+ __u64 pad[8];
+
+ union {
+ struct {
+ /* Cache devices */
+ __u64 nbuckets; /* device size */
+
+ __u16 block_size; /* sectors */
+ __u16 bucket_size; /* sectors */
+
+ __u16 nr_in_set;
+ __u16 nr_this_dev;
+ };
+ struct {
+ /* Backing devices */
+ __u64 data_offset;
+
+ /*
+ * block_size from the cache device section is still used by
+ * backing devices, so don't add anything here until we fix
+ * things to not need it for backing devices anymore
+ */
+ };
+ };
+
+ __u32 last_mount; /* time_t */
+
+ __u16 first_bucket;
+ union {
+ __u16 njournal_buckets;
+ __u16 keys;
+ };
+ __u64 d[SB_JOURNAL_BUCKETS]; /* journal buckets */
+};
+
+static inline _Bool SB_IS_BDEV(const struct cache_sb *sb)
+{
+ return sb->version == BCACHE_SB_VERSION_BDEV
+ || sb->version == BCACHE_SB_VERSION_BDEV_WITH_OFFSET;
+}
+
+BITMASK(CACHE_SYNC, struct cache_sb, flags, 0, 1);
+BITMASK(CACHE_DISCARD, struct cache_sb, flags, 1, 1);
+BITMASK(CACHE_REPLACEMENT, struct cache_sb, flags, 2, 3);
+#define CACHE_REPLACEMENT_LRU 0U
+#define CACHE_REPLACEMENT_FIFO 1U
+#define CACHE_REPLACEMENT_RANDOM 2U
+
+BITMASK(BDEV_CACHE_MODE, struct cache_sb, flags, 0, 4);
+#define CACHE_MODE_WRITETHROUGH 0U
+#define CACHE_MODE_WRITEBACK 1U
+#define CACHE_MODE_WRITEAROUND 2U
+#define CACHE_MODE_NONE 3U
+BITMASK(BDEV_STATE, struct cache_sb, flags, 61, 2);
+#define BDEV_STATE_NONE 0U
+#define BDEV_STATE_CLEAN 1U
+#define BDEV_STATE_DIRTY 2U
+#define BDEV_STATE_STALE 3U
+
+/*
+ * Magic numbers
+ *
+ * The various other data structures have their own magic numbers, which are
+ * xored with the first part of the cache set's UUID
+ */
+
+#define JSET_MAGIC 0x245235c1a3625032ULL
+#define PSET_MAGIC 0x6750e15f87337f91ULL
+#define BSET_MAGIC 0x90135c78b99e07f5ULL
+
+static inline __u64 jset_magic(struct cache_sb *sb)
+{
+ return sb->set_magic ^ JSET_MAGIC;
+}
+
+static inline __u64 pset_magic(struct cache_sb *sb)
+{
+ return sb->set_magic ^ PSET_MAGIC;
+}
+
+static inline __u64 bset_magic(struct cache_sb *sb)
+{
+ return sb->set_magic ^ BSET_MAGIC;
+}
+
+/*
+ * Journal
+ *
+ * On disk format for a journal entry:
+ * seq is monotonically increasing; every journal entry has its own unique
+ * sequence number.
+ *
+ * last_seq is the oldest journal entry that still has keys the btree hasn't
+ * flushed to disk yet.
+ *
+ * version is for on disk format changes.
+ */
+
+#define BCACHE_JSET_VERSION_UUIDv1 1
+#define BCACHE_JSET_VERSION_UUID 1 /* Always latest UUID format */
+#define BCACHE_JSET_VERSION 1
+
+struct jset {
+ __u64 csum;
+ __u64 magic;
+ __u64 seq;
+ __u32 version;
+ __u32 keys;
+
+ __u64 last_seq;
+
+ BKEY_PADDED(uuid_bucket);
+ BKEY_PADDED(btree_root);
+ __u16 btree_level;
+ __u16 pad[3];
+
+ __u64 prio_bucket[MAX_CACHES_PER_SET];
+
+ union {
+ struct bkey start[0];
+ __u64 d[0];
+ };
+};
+
+/* Bucket prios/gens */
+
+struct prio_set {
+ __u64 csum;
+ __u64 magic;
+ __u64 seq;
+ __u32 version;
+ __u32 pad;
+
+ __u64 next_bucket;
+
+ struct bucket_disk {
+ __u16 prio;
+ __u8 gen;
+ } __attribute((packed)) data[];
+};
+
+/* UUIDS - per backing device/flash only volume metadata */
+
+struct uuid_entry {
+ union {
+ struct {
+ __u8 uuid[16];
+ __u8 label[32];
+ __u32 first_reg;
+ __u32 last_reg;
+ __u32 invalidated;
+
+ __u32 flags;
+ /* Size of flash only volumes */
+ __u64 sectors;
+ };
+
+ __u8 pad[128];
+ };
+};
+
+BITMASK(UUID_FLASH_ONLY, struct uuid_entry, flags, 0, 1);
+
+/* Btree nodes */
+
+/* Version 1: Seed pointer into btree node checksum
+ */
+#define BCACHE_BSET_CSUM 1
+#define BCACHE_BSET_VERSION 1
+
+/*
+ * Btree nodes
+ *
+ * On disk a btree node is a list/log of these; within each set the keys are
+ * sorted
+ */
+struct bset {
+ __u64 csum;
+ __u64 magic;
+ __u64 seq;
+ __u32 version;
+ __u32 keys;
+
+ union {
+ struct bkey start[0];
+ __u64 d[0];
+ };
+};
+
+/* OBSOLETE */
+
+/* UUIDS - per backing device/flash only volume metadata */
+
+struct uuid_entry_v0 {
+ __u8 uuid[16];
+ __u8 label[32];
+ __u32 first_reg;
+ __u32 last_reg;
+ __u32 invalidated;
+ __u32 pad;
+};
+
+#endif /* _LINUX_BCACHE_H */
diff --git a/include/uapi/linux/elf-em.h b/include/uapi/linux/elf-em.h
index 59c17a2d38ad..01529bd96438 100644
--- a/include/uapi/linux/elf-em.h
+++ b/include/uapi/linux/elf-em.h
@@ -31,7 +31,6 @@
#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */
#define EM_V850 87 /* NEC v850 */
#define EM_M32R 88 /* Renesas M32R */
-#define EM_H8_300 46 /* Renesas H8/300,300H,H8S */
#define EM_MN10300 89 /* Panasonic/MEI MN10300, AM33 */
#define EM_BLACKFIN 106 /* ADI Blackfin Processor */
#define EM_TI_C6000 140 /* TI C6X DSPs */
diff --git a/include/uapi/linux/loop.h b/include/uapi/linux/loop.h
index e0cecd2eabdc..6edc6b68badd 100644
--- a/include/uapi/linux/loop.h
+++ b/include/uapi/linux/loop.h
@@ -21,6 +21,7 @@ enum {
LO_FLAGS_READ_ONLY = 1,
LO_FLAGS_AUTOCLEAR = 4,
LO_FLAGS_PARTSCAN = 8,
+ LO_FLAGS_USE_AIO = 16,
};
#include <asm/posix_types.h> /* for __kernel_old_dev_t */
diff --git a/include/uapi/linux/mic_common.h b/include/uapi/linux/mic_common.h
new file mode 100644
index 000000000000..364ac751bd04
--- /dev/null
+++ b/include/uapi/linux/mic_common.h
@@ -0,0 +1,238 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC driver.
+ *
+ */
+#ifndef __MIC_COMMON_H_
+#define __MIC_COMMON_H_
+
+#include <linux/virtio_ring.h>
+
+#ifndef __KERNEL__
+#define ALIGN(a, x) (((a) + (x) - 1) & ~((x) - 1))
+#define __aligned(x) __attribute__ ((aligned(x)))
+#endif
+
+#define mic_aligned_size(x) ALIGN(sizeof(x), 8)
+
+/**
+ * struct mic_device_desc: Virtio device information shared between the
+ * virtio driver and userspace backend
+ *
+ * @type: Device type: console/network/disk etc. Type 0/-1 terminates.
+ * @num_vq: Number of virtqueues.
+ * @feature_len: Number of bytes of feature bits. Multiply by 2: one for
+ host features and one for guest acknowledgements.
+ * @config_len: Number of bytes of the config array after virtqueues.
+ * @status: A status byte, written by the Guest.
+ * @config: Start of the following variable length config.
+ */
+struct mic_device_desc {
+ __s8 type;
+ __u8 num_vq;
+ __u8 feature_len;
+ __u8 config_len;
+ __u8 status;
+ __u64 config[0];
+} __aligned(8);
+
+/**
+ * struct mic_device_ctrl: Per virtio device information in the device page
+ * used internally by the host and card side drivers.
+ *
+ * @vdev: Used for storing MIC vdev information by the guest.
+ * @config_change: Set to 1 by host when a config change is requested.
+ * @vdev_reset: Set to 1 by guest to indicate virtio device has been reset.
+ * @guest_ack: Set to 1 by guest to ack a command.
+ * @host_ack: Set to 1 by host to ack a command.
+ * @used_address_updated: Set to 1 by guest when the used address should be
+ * updated.
+ * @c2h_vdev_db: The doorbell number to be used by guest. Set by host.
+ * @h2c_vdev_db: The doorbell number to be used by host. Set by guest.
+ */
+struct mic_device_ctrl {
+ __u64 vdev;
+ __u8 config_change;
+ __u8 vdev_reset;
+ __u8 guest_ack;
+ __u8 host_ack;
+ __u8 used_address_updated;
+ __s8 c2h_vdev_db;
+ __s8 h2c_vdev_db;
+} __aligned(8);
+
+/**
+ * struct mic_bootparam: Virtio device independent information in device page
+ *
+ * @magic: A magic value used by the card to ensure it can see the host
+ * @c2h_shutdown_db: Card to Host shutdown doorbell set by host
+ * @h2c_shutdown_db: Host to Card shutdown doorbell set by card
+ * @h2c_config_db: Host to Card Virtio config doorbell set by card
+ * @shutdown_status: Card shutdown status set by card
+ * @shutdown_card: Set to 1 by the host when a card shutdown is initiated
+ */
+struct mic_bootparam {
+ __u32 magic;
+ __s8 c2h_shutdown_db;
+ __s8 h2c_shutdown_db;
+ __s8 h2c_config_db;
+ __u8 shutdown_status;
+ __u8 shutdown_card;
+} __aligned(8);
+
+/**
+ * struct mic_device_page: High level representation of the device page
+ *
+ * @bootparam: The bootparam structure is used for sharing information and
+ * status updates between MIC host and card drivers.
+ * @desc: Array of MIC virtio device descriptors.
+ */
+struct mic_device_page {
+ struct mic_bootparam bootparam;
+ struct mic_device_desc desc[0];
+};
+/**
+ * struct mic_vqconfig: This is how we expect the device configuration field
+ * for a virtqueue to be laid out in config space.
+ *
+ * @address: Guest/MIC physical address of the virtio ring
+ * (avail and desc rings)
+ * @used_address: Guest/MIC physical address of the used ring
+ * @num: The number of entries in the virtio_ring
+ */
+struct mic_vqconfig {
+ __u64 address;
+ __u64 used_address;
+ __u16 num;
+} __aligned(8);
+
+/*
+ * The alignment to use between consumer and producer parts of vring.
+ * This is pagesize for historical reasons.
+ */
+#define MIC_VIRTIO_RING_ALIGN 4096
+
+#define MIC_MAX_VRINGS 4
+#define MIC_VRING_ENTRIES 128
+
+/*
+ * Max vring entries (power of 2) to ensure desc and avail rings
+ * fit in a single page
+ */
+#define MIC_MAX_VRING_ENTRIES 128
+
+/**
+ * Max size of the desc block in bytes: includes:
+ * - struct mic_device_desc
+ * - struct mic_vqconfig (num_vq of these)
+ * - host and guest features
+ * - virtio device config space
+ */
+#define MIC_MAX_DESC_BLK_SIZE 256
+
+/**
+ * struct _mic_vring_info - Host vring info exposed to userspace backend
+ * for the avail index and magic for the card.
+ *
+ * @avail_idx: host avail idx
+ * @magic: A magic debug cookie.
+ */
+struct _mic_vring_info {
+ __u16 avail_idx;
+ int magic;
+};
+
+/**
+ * struct mic_vring - Vring information.
+ *
+ * @vr: The virtio ring.
+ * @info: Host vring information exposed to the userspace backend for the
+ * avail index and magic for the card.
+ * @va: The va for the buffer allocated for vr and info.
+ * @len: The length of the buffer required for allocating vr and info.
+ */
+struct mic_vring {
+ struct vring vr;
+ struct _mic_vring_info *info;
+ void *va;
+ int len;
+};
+
+#define mic_aligned_desc_size(d) ALIGN(mic_desc_size(d), 8)
+
+#ifndef INTEL_MIC_CARD
+static inline unsigned mic_desc_size(const struct mic_device_desc *desc)
+{
+ return mic_aligned_size(*desc)
+ + desc->num_vq * mic_aligned_size(struct mic_vqconfig)
+ + desc->feature_len * 2
+ + desc->config_len;
+}
+
+static inline struct mic_vqconfig *
+mic_vq_config(const struct mic_device_desc *desc)
+{
+ return (struct mic_vqconfig *)(desc + 1);
+}
+
+static inline __u8 *mic_vq_features(const struct mic_device_desc *desc)
+{
+ return (__u8 *)(mic_vq_config(desc) + desc->num_vq);
+}
+
+static inline __u8 *mic_vq_configspace(const struct mic_device_desc *desc)
+{
+ return mic_vq_features(desc) + desc->feature_len * 2;
+}
+static inline unsigned mic_total_desc_size(struct mic_device_desc *desc)
+{
+ return mic_aligned_desc_size(desc) +
+ mic_aligned_size(struct mic_device_ctrl);
+}
+#endif
+
+/* Device page size */
+#define MIC_DP_SIZE 4096
+
+#define MIC_MAGIC 0xc0ffee00
+
+/**
+ * enum mic_states - MIC states.
+ */
+enum mic_states {
+ MIC_OFFLINE = 0,
+ MIC_ONLINE,
+ MIC_SHUTTING_DOWN,
+ MIC_RESET_FAILED,
+ MIC_LAST
+};
+
+/**
+ * enum mic_status - MIC status reported by card after
+ * a host or card initiated shutdown or a card crash.
+ */
+enum mic_status {
+ MIC_NOP = 0,
+ MIC_CRASHED,
+ MIC_HALTED,
+ MIC_POWER_OFF,
+ MIC_RESTART,
+ MIC_STATUS_LAST
+};
+
+#endif
diff --git a/include/uapi/linux/mic_ioctl.h b/include/uapi/linux/mic_ioctl.h
new file mode 100644
index 000000000000..0e6cbf3e5292
--- /dev/null
+++ b/include/uapi/linux/mic_ioctl.h
@@ -0,0 +1,74 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 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.
+ *
+ * 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#ifndef _MIC_IOCTL_H_
+#define _MIC_IOCTL_H_
+
+/*
+ * mic_copy - MIC virtio descriptor copy.
+ *
+ * @iov: An array of IOVEC structures containing user space buffers.
+ * @iovcnt: Number of IOVEC structures in iov.
+ * @vr_idx: The vring index.
+ * @update_used: A non zero value results in used index being updated.
+ * @out_len: The aggregate of the total length written to or read from
+ * the virtio device.
+ */
+struct mic_copy_desc {
+#ifdef __KERNEL__
+ struct iovec __user *iov;
+#else
+ struct iovec *iov;
+#endif
+ int iovcnt;
+ __u8 vr_idx;
+ __u8 update_used;
+ __u32 out_len;
+};
+
+/*
+ * Add a new virtio device
+ * The (struct mic_device_desc *) pointer points to a device page entry
+ * for the virtio device consisting of:
+ * - struct mic_device_desc
+ * - struct mic_vqconfig (num_vq of these)
+ * - host and guest features
+ * - virtio device config space
+ * The total size referenced by the pointer should equal the size returned
+ * by desc_size() in mic_common.h
+ */
+#define MIC_VIRTIO_ADD_DEVICE _IOWR('s', 1, struct mic_device_desc *)
+
+/*
+ * Copy the number of entries in the iovec and update the used index
+ * if requested by the user.
+ */
+#define MIC_VIRTIO_COPY_DESC _IOWR('s', 2, struct mic_copy_desc *)
+
+/*
+ * Notify virtio device of a config change
+ * The (__u8 *) pointer points to config space values for the device
+ * as they should be written into the device page. The total size
+ * referenced by the pointer should equal the config_len field of struct
+ * mic_device_desc.
+ */
+#define MIC_VIRTIO_CONFIG_CHANGE _IOWR('s', 5, __u8 *)
+
+#endif
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index baa7852468ef..1a38377a0032 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -558,7 +558,8 @@
#define PCI_EXP_DEVCAP2_OBFF_MSG 0x00040000 /* New message signaling */
#define PCI_EXP_DEVCAP2_OBFF_WAKE 0x00080000 /* Re-use WAKE# for OBFF */
#define PCI_EXP_DEVCTL2 40 /* Device Control 2 */
-#define PCI_EXP_DEVCTL2_ARI 0x20 /* Alternative Routing-ID */
+#define PCI_EXP_DEVCTL2_COMP_TIMEOUT 0x000f /* Completion Timeout Value */
+#define PCI_EXP_DEVCTL2_ARI 0x0020 /* Alternative Routing-ID */
#define PCI_EXP_DEVCTL2_IDO_REQ_EN 0x0100 /* Allow IDO for requests */
#define PCI_EXP_DEVCTL2_IDO_CMP_EN 0x0200 /* Allow IDO for completions */
#define PCI_EXP_DEVCTL2_LTR_EN 0x0400 /* Enable LTR mechanism */
diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h
index 9b829134d422..f2624b549e61 100644
--- a/include/uapi/linux/pkt_sched.h
+++ b/include/uapi/linux/pkt_sched.h
@@ -357,6 +357,8 @@ enum {
TCA_HTB_CTAB,
TCA_HTB_RTAB,
TCA_HTB_DIRECT_QLEN,
+ TCA_HTB_RATE64,
+ TCA_HTB_CEIL64,
__TCA_HTB_MAX,
};
diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h
index 0f5a2fc69af9..c79f38131926 100644
--- a/include/video/atmel_lcdc.h
+++ b/include/video/atmel_lcdc.h
@@ -31,39 +31,20 @@
#define ATMEL_LCDC_WIRING_BGR 0
#define ATMEL_LCDC_WIRING_RGB 1
-struct atmel_lcdfb_config;
/* LCD Controller info data structure, stored in device platform_data */
-struct atmel_lcdfb_info {
- spinlock_t lock;
- struct fb_info *info;
- void __iomem *mmio;
- int irq_base;
- struct work_struct task;
-
+struct atmel_lcdfb_pdata {
unsigned int guard_time;
- unsigned int smem_len;
- struct platform_device *pdev;
- struct clk *bus_clk;
- struct clk *lcdc_clk;
-
-#ifdef CONFIG_BACKLIGHT_ATMEL_LCDC
- struct backlight_device *backlight;
- u8 bl_power;
-#endif
bool lcdcon_is_backlight;
bool lcdcon_pol_negative;
- u8 saved_lcdcon;
-
u8 default_bpp;
u8 lcd_wiring_mode;
unsigned int default_lcdcon2;
unsigned int default_dmacon;
- void (*atmel_lcdfb_power_control)(int on);
+ void (*atmel_lcdfb_power_control)(struct atmel_lcdfb_pdata *pdata, int on);
struct fb_monspecs *default_monspecs;
- u32 pseudo_palette[16];
- struct atmel_lcdfb_config *config;
+ struct list_head pwr_gpios;
};
#define ATMEL_LCDC_DMABADDR1 0x00
diff --git a/include/video/mmp_disp.h b/include/video/mmp_disp.h
index b9dd1fbb0082..9fd9398368d5 100644
--- a/include/video/mmp_disp.h
+++ b/include/video/mmp_disp.h
@@ -91,6 +91,11 @@ struct mmp_win {
u16 up_crop;
u16 bottom_crop;
int pix_fmt;
+ /*
+ * pitch[0]: graphics/video layer line length or y pitch
+ * pitch[1]/pitch[2]: video u/v pitch if non-zero
+ */
+ u32 pitch[3];
};
struct mmp_addr {
@@ -334,6 +339,7 @@ struct mmp_mach_path_config {
int output_type;
u32 path_config;
u32 link_config;
+ u32 dsi_rbswap;
};
struct mmp_mach_plat_info {
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 8e5addc45874..4b18a7326590 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -206,7 +206,7 @@ done:
* bangs.
*/
-dev_t name_to_dev_t(char *name)
+dev_t name_to_dev_t(const char *name)
{
char s[32];
char *p;
diff --git a/init/main.c b/init/main.c
index af310afbef28..379090fadac9 100644
--- a/init/main.c
+++ b/init/main.c
@@ -76,6 +76,7 @@
#include <linux/elevator.h>
#include <linux/sched_clock.h>
#include <linux/context_tracking.h>
+#include <linux/random.h>
#include <asm/io.h>
#include <asm/bugs.h>
@@ -692,7 +693,7 @@ int __init_or_module do_one_initcall(initcall_t fn)
if (preempt_count() != count) {
sprintf(msgbuf, "preemption imbalance ");
- preempt_count() = count;
+ preempt_count_set(count);
}
if (irqs_disabled()) {
strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
@@ -780,6 +781,7 @@ static void __init do_basic_setup(void)
do_ctors();
usermodehelper_enable();
do_initcalls();
+ random_int_secret_init();
}
static void __init do_pre_smp_initcalls(void)
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 2418b6e71a85..41f71c33702e 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -125,38 +125,6 @@ struct cfent {
};
/*
- * CSS ID -- ID per subsys's Cgroup Subsys State(CSS). used only when
- * cgroup_subsys->use_id != 0.
- */
-#define CSS_ID_MAX (65535)
-struct css_id {
- /*
- * The css to which this ID points. This pointer is set to valid value
- * after cgroup is populated. If cgroup is removed, this will be NULL.
- * This pointer is expected to be RCU-safe because destroy()
- * is called after synchronize_rcu(). But for safe use, css_tryget()
- * should be used for avoiding race.
- */
- struct cgroup_subsys_state __rcu *css;
- /*
- * ID of this css.
- */
- unsigned short id;
- /*
- * Depth in hierarchy which this ID belongs to.
- */
- unsigned short depth;
- /*
- * ID is freed by RCU. (and lookup routine is RCU safe.)
- */
- struct rcu_head rcu_head;
- /*
- * Hierarchy of CSS ID belongs to.
- */
- unsigned short stack[0]; /* Array of Length (depth+1) */
-};
-
-/*
* cgroup_event represents events which userspace want to receive.
*/
struct cgroup_event {
@@ -387,9 +355,6 @@ struct cgrp_cset_link {
static struct css_set init_css_set;
static struct cgrp_cset_link init_cgrp_cset_link;
-static int cgroup_init_idr(struct cgroup_subsys *ss,
- struct cgroup_subsys_state *css);
-
/*
* css_set_lock protects the list of css_set objects, and the chain of
* tasks off each css_set. Nests outside task->alloc_lock due to
@@ -841,8 +806,6 @@ static struct backing_dev_info cgroup_backing_dev_info = {
.capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK,
};
-static int alloc_css_id(struct cgroup_subsys_state *child_css);
-
static struct inode *cgroup_new_inode(umode_t mode, struct super_block *sb)
{
struct inode *inode = new_inode(sb);
@@ -3188,11 +3151,9 @@ css_next_descendant_post(struct cgroup_subsys_state *pos,
WARN_ON_ONCE(!rcu_read_lock_held());
- /* if first iteration, visit the leftmost descendant */
- if (!pos) {
- next = css_leftmost_descendant(root);
- return next != root ? next : NULL;
- }
+ /* if first iteration, visit leftmost descendant which may be @root */
+ if (!pos)
+ return css_leftmost_descendant(root);
/* if we visited @root, we're done */
if (pos == root)
@@ -4242,21 +4203,6 @@ static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask)
goto err;
}
}
-
- /* This cgroup is ready now */
- for_each_root_subsys(cgrp->root, ss) {
- struct cgroup_subsys_state *css = cgroup_css(cgrp, ss);
- struct css_id *id = rcu_dereference_protected(css->id, true);
-
- /*
- * Update id->css pointer and make this css visible from
- * CSS ID functions. This pointer will be dereferened
- * from RCU-read-side without locks.
- */
- if (id)
- rcu_assign_pointer(id->css, css);
- }
-
return 0;
err:
cgroup_clear_dir(cgrp, subsys_mask);
@@ -4325,7 +4271,6 @@ static void init_css(struct cgroup_subsys_state *css, struct cgroup_subsys *ss,
css->cgroup = cgrp;
css->ss = ss;
css->flags = 0;
- css->id = NULL;
if (cgrp->parent)
css->parent = cgroup_css(cgrp->parent, ss);
@@ -4457,12 +4402,6 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
goto err_free_all;
init_css(css, ss, cgrp);
-
- if (ss->use_id) {
- err = alloc_css_id(css);
- if (err)
- goto err_free_all;
- }
}
/*
@@ -4927,12 +4866,6 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
/* our new subsystem will be attached to the dummy hierarchy. */
init_css(css, ss, cgroup_dummy_top);
- /* init_idr must be after init_css() because it sets css->id. */
- if (ss->use_id) {
- ret = cgroup_init_idr(ss, css);
- if (ret)
- goto err_unload;
- }
/*
* Now we need to entangle the css into the existing css_sets. unlike
@@ -4998,9 +4931,6 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
offline_css(cgroup_css(cgroup_dummy_top, ss));
- if (ss->use_id)
- idr_destroy(&ss->idr);
-
/* deassign the subsys_id */
cgroup_subsys[ss->subsys_id] = NULL;
@@ -5027,8 +4957,7 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
/*
* remove subsystem's css from the cgroup_dummy_top and free it -
* need to free before marking as null because ss->css_free needs
- * the cgrp->subsys pointer to find their state. note that this
- * also takes care of freeing the css_id.
+ * the cgrp->subsys pointer to find their state.
*/
ss->css_free(cgroup_css(cgroup_dummy_top, ss));
RCU_INIT_POINTER(cgroup_dummy_top->subsys[ss->subsys_id], NULL);
@@ -5099,8 +5028,6 @@ int __init cgroup_init(void)
for_each_builtin_subsys(ss, i) {
if (!ss->early_init)
cgroup_init_subsys(ss);
- if (ss->use_id)
- cgroup_init_idr(ss, init_css_set.subsys[ss->subsys_id]);
}
/* allocate id for the dummy hierarchy */
@@ -5520,181 +5447,6 @@ static int __init cgroup_disable(char *str)
}
__setup("cgroup_disable=", cgroup_disable);
-/*
- * Functons for CSS ID.
- */
-
-/* to get ID other than 0, this should be called when !cgroup_is_dead() */
-unsigned short css_id(struct cgroup_subsys_state *css)
-{
- struct css_id *cssid;
-
- /*
- * This css_id() can return correct value when somone has refcnt
- * on this or this is under rcu_read_lock(). Once css->id is allocated,
- * it's unchanged until freed.
- */
- cssid = rcu_dereference_raw(css->id);
-
- if (cssid)
- return cssid->id;
- return 0;
-}
-EXPORT_SYMBOL_GPL(css_id);
-
-/**
- * css_is_ancestor - test "root" css is an ancestor of "child"
- * @child: the css to be tested.
- * @root: the css supporsed to be an ancestor of the child.
- *
- * Returns true if "root" is an ancestor of "child" in its hierarchy. Because
- * this function reads css->id, the caller must hold rcu_read_lock().
- * But, considering usual usage, the csses should be valid objects after test.
- * Assuming that the caller will do some action to the child if this returns
- * returns true, the caller must take "child";s reference count.
- * If "child" is valid object and this returns true, "root" is valid, too.
- */
-
-bool css_is_ancestor(struct cgroup_subsys_state *child,
- const struct cgroup_subsys_state *root)
-{
- struct css_id *child_id;
- struct css_id *root_id;
-
- child_id = rcu_dereference(child->id);
- if (!child_id)
- return false;
- root_id = rcu_dereference(root->id);
- if (!root_id)
- return false;
- if (child_id->depth < root_id->depth)
- return false;
- if (child_id->stack[root_id->depth] != root_id->id)
- return false;
- return true;
-}
-
-void free_css_id(struct cgroup_subsys *ss, struct cgroup_subsys_state *css)
-{
- struct css_id *id = rcu_dereference_protected(css->id, true);
-
- /* When this is called before css_id initialization, id can be NULL */
- if (!id)
- return;
-
- BUG_ON(!ss->use_id);
-
- rcu_assign_pointer(id->css, NULL);
- rcu_assign_pointer(css->id, NULL);
- spin_lock(&ss->id_lock);
- idr_remove(&ss->idr, id->id);
- spin_unlock(&ss->id_lock);
- kfree_rcu(id, rcu_head);
-}
-EXPORT_SYMBOL_GPL(free_css_id);
-
-/*
- * This is called by init or create(). Then, calls to this function are
- * always serialized (By cgroup_mutex() at create()).
- */
-
-static struct css_id *get_new_cssid(struct cgroup_subsys *ss, int depth)
-{
- struct css_id *newid;
- int ret, size;
-
- BUG_ON(!ss->use_id);
-
- size = sizeof(*newid) + sizeof(unsigned short) * (depth + 1);
- newid = kzalloc(size, GFP_KERNEL);
- if (!newid)
- return ERR_PTR(-ENOMEM);
-
- idr_preload(GFP_KERNEL);
- spin_lock(&ss->id_lock);
- /* Don't use 0. allocates an ID of 1-65535 */
- ret = idr_alloc(&ss->idr, newid, 1, CSS_ID_MAX + 1, GFP_NOWAIT);
- spin_unlock(&ss->id_lock);
- idr_preload_end();
-
- /* Returns error when there are no free spaces for new ID.*/
- if (ret < 0)
- goto err_out;
-
- newid->id = ret;
- newid->depth = depth;
- return newid;
-err_out:
- kfree(newid);
- return ERR_PTR(ret);
-
-}
-
-static int __init_or_module cgroup_init_idr(struct cgroup_subsys *ss,
- struct cgroup_subsys_state *rootcss)
-{
- struct css_id *newid;
-
- spin_lock_init(&ss->id_lock);
- idr_init(&ss->idr);
-
- newid = get_new_cssid(ss, 0);
- if (IS_ERR(newid))
- return PTR_ERR(newid);
-
- newid->stack[0] = newid->id;
- RCU_INIT_POINTER(newid->css, rootcss);
- RCU_INIT_POINTER(rootcss->id, newid);
- return 0;
-}
-
-static int alloc_css_id(struct cgroup_subsys_state *child_css)
-{
- struct cgroup_subsys_state *parent_css = css_parent(child_css);
- struct css_id *child_id, *parent_id;
- int i, depth;
-
- parent_id = rcu_dereference_protected(parent_css->id, true);
- depth = parent_id->depth + 1;
-
- child_id = get_new_cssid(child_css->ss, depth);
- if (IS_ERR(child_id))
- return PTR_ERR(child_id);
-
- for (i = 0; i < depth; i++)
- child_id->stack[i] = parent_id->stack[i];
- child_id->stack[depth] = child_id->id;
- /*
- * child_id->css pointer will be set after this cgroup is available
- * see cgroup_populate_dir()
- */
- rcu_assign_pointer(child_css->id, child_id);
-
- return 0;
-}
-
-/**
- * css_lookup - lookup css by id
- * @ss: cgroup subsys to be looked into.
- * @id: the id
- *
- * Returns pointer to cgroup_subsys_state if there is valid one with id.
- * NULL if not. Should be called under rcu_read_lock()
- */
-struct cgroup_subsys_state *css_lookup(struct cgroup_subsys *ss, int id)
-{
- struct css_id *cssid = NULL;
-
- BUG_ON(!ss->use_id);
- cssid = idr_find(&ss->idr, id);
-
- if (unlikely(!cssid))
- return NULL;
-
- return rcu_dereference(cssid->css);
-}
-EXPORT_SYMBOL_GPL(css_lookup);
-
/**
* css_from_dir - get corresponding css from the dentry of a cgroup dir
* @dentry: directory dentry of interest
diff --git a/kernel/context_tracking.c b/kernel/context_tracking.c
index 247091bf0587..013161f1c807 100644
--- a/kernel/context_tracking.c
+++ b/kernel/context_tracking.c
@@ -111,7 +111,7 @@ void context_tracking_user_enter(void)
* instead of preempt_schedule() to exit user context if needed before
* calling the scheduler.
*/
-void __sched notrace preempt_schedule_context(void)
+asmlinkage void __sched notrace preempt_schedule_context(void)
{
enum ctx_state prev_ctx;
diff --git a/kernel/cpu/idle.c b/kernel/cpu/idle.c
index e695c0a0bcb5..988573a9a387 100644
--- a/kernel/cpu/idle.c
+++ b/kernel/cpu/idle.c
@@ -44,7 +44,7 @@ static inline int cpu_idle_poll(void)
rcu_idle_enter();
trace_cpu_idle_rcuidle(0, smp_processor_id());
local_irq_enable();
- while (!need_resched())
+ while (!tif_need_resched())
cpu_relax();
trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id());
rcu_idle_exit();
@@ -92,8 +92,7 @@ static void cpu_idle_loop(void)
if (cpu_idle_force_poll || tick_check_broadcast_expired()) {
cpu_idle_poll();
} else {
- current_clr_polling();
- if (!need_resched()) {
+ if (!current_clr_polling_and_test()) {
stop_critical_timings();
rcu_idle_enter();
arch_cpu_idle();
@@ -103,9 +102,16 @@ static void cpu_idle_loop(void)
} else {
local_irq_enable();
}
- current_set_polling();
+ __current_set_polling();
}
arch_cpu_idle_exit();
+ /*
+ * We need to test and propagate the TIF_NEED_RESCHED
+ * bit here because we might not have send the
+ * reschedule IPI to idle tasks.
+ */
+ if (tif_need_resched())
+ set_preempt_need_resched();
}
tick_nohz_idle_exit();
schedule_preempt_disabled();
@@ -129,7 +135,7 @@ void cpu_startup_entry(enum cpuhp_state state)
*/
boot_init_stack_canary();
#endif
- current_set_polling();
+ __current_set_polling();
arch_cpu_idle_prepare();
cpu_idle_loop();
}
diff --git a/kernel/events/core.c b/kernel/events/core.c
index cb4238e85b38..4ccb29bb761e 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -6292,6 +6292,7 @@ type_show(struct device *dev, struct device_attribute *attr, char *page)
return snprintf(page, PAGE_SIZE-1, "%d\n", pmu->type);
}
+static DEVICE_ATTR_RO(type);
static ssize_t
perf_event_mux_interval_ms_show(struct device *dev,
@@ -6336,17 +6337,19 @@ perf_event_mux_interval_ms_store(struct device *dev,
return count;
}
+static DEVICE_ATTR_RW(perf_event_mux_interval_ms);
-static struct device_attribute pmu_dev_attrs[] = {
- __ATTR_RO(type),
- __ATTR_RW(perf_event_mux_interval_ms),
- __ATTR_NULL,
+static struct attribute *pmu_dev_attrs[] = {
+ &dev_attr_type.attr,
+ &dev_attr_perf_event_mux_interval_ms.attr,
+ NULL,
};
+ATTRIBUTE_GROUPS(pmu_dev);
static int pmu_bus_running;
static struct bus_type pmu_bus = {
.name = "event_source",
- .dev_attrs = pmu_dev_attrs,
+ .dev_groups = pmu_dev_groups,
};
static void pmu_dev_release(struct device *dev)
diff --git a/kernel/hung_task.c b/kernel/hung_task.c
index 3e97fb126e6b..042252383fd2 100644
--- a/kernel/hung_task.c
+++ b/kernel/hung_task.c
@@ -20,7 +20,7 @@
/*
* The number of tasks checked:
*/
-unsigned long __read_mostly sysctl_hung_task_check_count = PID_MAX_LIMIT;
+int __read_mostly sysctl_hung_task_check_count = PID_MAX_LIMIT;
/*
* Limit number of tasks checked in a batch.
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index e16c45b9ee77..4e8e14c34e42 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -4224,7 +4224,7 @@ void lockdep_rcu_suspicious(const char *file, const int line, const char *s)
printk("\n%srcu_scheduler_active = %d, debug_locks = %d\n",
!rcu_lockdep_current_cpu_online()
? "RCU used illegally from offline CPU!\n"
- : rcu_is_cpu_idle()
+ : !rcu_is_watching()
? "RCU used illegally from idle CPU!\n"
: "",
rcu_scheduler_active, debug_locks);
@@ -4247,7 +4247,7 @@ void lockdep_rcu_suspicious(const char *file, const int line, const char *s)
* So complain bitterly if someone does call rcu_read_lock(),
* rcu_read_lock_bh() and so on from extended quiescent states.
*/
- if (rcu_is_cpu_idle())
+ if (!rcu_is_watching())
printk("RCU used illegally from extended quiescent state!\n");
lockdep_print_held_locks(curr);
diff --git a/kernel/notifier.c b/kernel/notifier.c
index 2d5cc4ccff7f..1857c71bae40 100644
--- a/kernel/notifier.c
+++ b/kernel/notifier.c
@@ -51,7 +51,7 @@ static int notifier_chain_unregister(struct notifier_block **nl,
{
while ((*nl) != NULL) {
if ((*nl) == n) {
- rcu_assign_pointer(*nl, n->next);
+ rcu_assign_pointer(*nl, rcu_access_pointer(n->next));
return 0;
}
nl = &((*nl)->next);
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 78b7c0f38259..59754db5be42 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1267,8 +1267,6 @@ static void call_console_drivers(int level, const char *text, size_t len)
trace_console(text, len);
- if (level >= console_loglevel && !ignore_loglevel)
- return;
if (!console_drivers)
return;
@@ -1282,6 +1280,9 @@ static void call_console_drivers(int level, const char *text, size_t len)
if (!cpu_online(smp_processor_id()) &&
!(con->flags & CON_ANYTIME))
continue;
+ if (level >= console_loglevel && !ignore_loglevel &&
+ !(con->flags & CON_ALLDATA))
+ continue;
con->write(con, text, len);
}
}
diff --git a/kernel/rcu.h b/kernel/rcu.h
index 77131966c4ad..7859a0a3951e 100644
--- a/kernel/rcu.h
+++ b/kernel/rcu.h
@@ -122,4 +122,11 @@ int rcu_jiffies_till_stall_check(void);
#endif /* #ifdef CONFIG_RCU_STALL_COMMON */
+/*
+ * Strings used in tracepoints need to be exported via the
+ * tracing system such that tools like perf and trace-cmd can
+ * translate the string address pointers to actual text.
+ */
+#define TPS(x) tracepoint_string(x)
+
#endif /* __LINUX_RCU_H */
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index b02a339836b4..c07af1c4e1bb 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -148,7 +148,7 @@ int rcu_read_lock_bh_held(void)
{
if (!debug_lockdep_rcu_enabled())
return 1;
- if (rcu_is_cpu_idle())
+ if (!rcu_is_watching())
return 0;
if (!rcu_lockdep_current_cpu_online())
return 0;
@@ -298,7 +298,7 @@ EXPORT_SYMBOL_GPL(do_trace_rcu_torture_read);
#endif
int rcu_cpu_stall_suppress __read_mostly; /* 1 = suppress stall warnings. */
-int rcu_cpu_stall_timeout __read_mostly = CONFIG_RCU_CPU_STALL_TIMEOUT;
+static int rcu_cpu_stall_timeout __read_mostly = CONFIG_RCU_CPU_STALL_TIMEOUT;
module_param(rcu_cpu_stall_suppress, int, 0644);
module_param(rcu_cpu_stall_timeout, int, 0644);
diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c
index 9ed6075dc562..312e9709713f 100644
--- a/kernel/rcutiny.c
+++ b/kernel/rcutiny.c
@@ -35,6 +35,7 @@
#include <linux/time.h>
#include <linux/cpu.h>
#include <linux/prefetch.h>
+#include <linux/ftrace_event.h>
#ifdef CONFIG_RCU_TRACE
#include <trace/events/rcu.h>
@@ -58,16 +59,17 @@ static long long rcu_dynticks_nesting = DYNTICK_TASK_EXIT_IDLE;
static void rcu_idle_enter_common(long long newval)
{
if (newval) {
- RCU_TRACE(trace_rcu_dyntick("--=",
+ RCU_TRACE(trace_rcu_dyntick(TPS("--="),
rcu_dynticks_nesting, newval));
rcu_dynticks_nesting = newval;
return;
}
- RCU_TRACE(trace_rcu_dyntick("Start", rcu_dynticks_nesting, newval));
+ RCU_TRACE(trace_rcu_dyntick(TPS("Start"),
+ rcu_dynticks_nesting, newval));
if (!is_idle_task(current)) {
struct task_struct *idle = idle_task(smp_processor_id());
- RCU_TRACE(trace_rcu_dyntick("Error on entry: not idle task",
+ RCU_TRACE(trace_rcu_dyntick(TPS("Entry error: not idle task"),
rcu_dynticks_nesting, newval));
ftrace_dump(DUMP_ALL);
WARN_ONCE(1, "Current pid: %d comm: %s / Idle pid: %d comm: %s",
@@ -120,15 +122,15 @@ EXPORT_SYMBOL_GPL(rcu_irq_exit);
static void rcu_idle_exit_common(long long oldval)
{
if (oldval) {
- RCU_TRACE(trace_rcu_dyntick("++=",
+ RCU_TRACE(trace_rcu_dyntick(TPS("++="),
oldval, rcu_dynticks_nesting));
return;
}
- RCU_TRACE(trace_rcu_dyntick("End", oldval, rcu_dynticks_nesting));
+ RCU_TRACE(trace_rcu_dyntick(TPS("End"), oldval, rcu_dynticks_nesting));
if (!is_idle_task(current)) {
struct task_struct *idle = idle_task(smp_processor_id());
- RCU_TRACE(trace_rcu_dyntick("Error on exit: not idle task",
+ RCU_TRACE(trace_rcu_dyntick(TPS("Exit error: not idle task"),
oldval, rcu_dynticks_nesting));
ftrace_dump(DUMP_ALL);
WARN_ONCE(1, "Current pid: %d comm: %s / Idle pid: %d comm: %s",
@@ -174,18 +176,18 @@ void rcu_irq_enter(void)
}
EXPORT_SYMBOL_GPL(rcu_irq_enter);
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
+#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE)
/*
* Test whether RCU thinks that the current CPU is idle.
*/
-int rcu_is_cpu_idle(void)
+bool __rcu_is_watching(void)
{
- return !rcu_dynticks_nesting;
+ return rcu_dynticks_nesting;
}
-EXPORT_SYMBOL(rcu_is_cpu_idle);
+EXPORT_SYMBOL(__rcu_is_watching);
-#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+#endif /* defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) */
/*
* Test whether the current CPU was interrupted from idle. Nested
@@ -273,7 +275,7 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp)
if (&rcp->rcucblist == rcp->donetail) {
RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, 0, -1));
RCU_TRACE(trace_rcu_batch_end(rcp->name, 0,
- ACCESS_ONCE(rcp->rcucblist),
+ !!ACCESS_ONCE(rcp->rcucblist),
need_resched(),
is_idle_task(current),
false));
@@ -304,7 +306,8 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp)
RCU_TRACE(cb_count++);
}
RCU_TRACE(rcu_trace_sub_qlen(rcp, cb_count));
- RCU_TRACE(trace_rcu_batch_end(rcp->name, cb_count, 0, need_resched(),
+ RCU_TRACE(trace_rcu_batch_end(rcp->name,
+ cb_count, 0, need_resched(),
is_idle_task(current),
false));
}
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 32618b3fe4e6..aa127f74060c 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -61,13 +61,6 @@
#include "rcu.h"
-/*
- * Strings used in tracepoints need to be exported via the
- * tracing system such that tools like perf and trace-cmd can
- * translate the string address pointers to actual text.
- */
-#define TPS(x) tracepoint_string(x)
-
/* Data structures. */
static struct lock_class_key rcu_node_class[RCU_NUM_LVLS];
@@ -222,7 +215,7 @@ void rcu_note_context_switch(int cpu)
}
EXPORT_SYMBOL_GPL(rcu_note_context_switch);
-DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = {
+static DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = {
.dynticks_nesting = DYNTICK_TASK_EXIT_IDLE,
.dynticks = ATOMIC_INIT(1),
#ifdef CONFIG_NO_HZ_FULL_SYSIDLE
@@ -371,7 +364,8 @@ static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval,
{
trace_rcu_dyntick(TPS("Start"), oldval, rdtp->dynticks_nesting);
if (!user && !is_idle_task(current)) {
- struct task_struct *idle = idle_task(smp_processor_id());
+ struct task_struct *idle __maybe_unused =
+ idle_task(smp_processor_id());
trace_rcu_dyntick(TPS("Error on entry: not idle task"), oldval, 0);
ftrace_dump(DUMP_ORIG);
@@ -407,7 +401,7 @@ static void rcu_eqs_enter(bool user)
long long oldval;
struct rcu_dynticks *rdtp;
- rdtp = &__get_cpu_var(rcu_dynticks);
+ rdtp = this_cpu_ptr(&rcu_dynticks);
oldval = rdtp->dynticks_nesting;
WARN_ON_ONCE((oldval & DYNTICK_TASK_NEST_MASK) == 0);
if ((oldval & DYNTICK_TASK_NEST_MASK) == DYNTICK_TASK_NEST_VALUE)
@@ -435,7 +429,7 @@ void rcu_idle_enter(void)
local_irq_save(flags);
rcu_eqs_enter(false);
- rcu_sysidle_enter(&__get_cpu_var(rcu_dynticks), 0);
+ rcu_sysidle_enter(this_cpu_ptr(&rcu_dynticks), 0);
local_irq_restore(flags);
}
EXPORT_SYMBOL_GPL(rcu_idle_enter);
@@ -478,7 +472,7 @@ void rcu_irq_exit(void)
struct rcu_dynticks *rdtp;
local_irq_save(flags);
- rdtp = &__get_cpu_var(rcu_dynticks);
+ rdtp = this_cpu_ptr(&rcu_dynticks);
oldval = rdtp->dynticks_nesting;
rdtp->dynticks_nesting--;
WARN_ON_ONCE(rdtp->dynticks_nesting < 0);
@@ -508,7 +502,8 @@ static void rcu_eqs_exit_common(struct rcu_dynticks *rdtp, long long oldval,
rcu_cleanup_after_idle(smp_processor_id());
trace_rcu_dyntick(TPS("End"), oldval, rdtp->dynticks_nesting);
if (!user && !is_idle_task(current)) {
- struct task_struct *idle = idle_task(smp_processor_id());
+ struct task_struct *idle __maybe_unused =
+ idle_task(smp_processor_id());
trace_rcu_dyntick(TPS("Error on exit: not idle task"),
oldval, rdtp->dynticks_nesting);
@@ -528,7 +523,7 @@ static void rcu_eqs_exit(bool user)
struct rcu_dynticks *rdtp;
long long oldval;
- rdtp = &__get_cpu_var(rcu_dynticks);
+ rdtp = this_cpu_ptr(&rcu_dynticks);
oldval = rdtp->dynticks_nesting;
WARN_ON_ONCE(oldval < 0);
if (oldval & DYNTICK_TASK_NEST_MASK)
@@ -555,7 +550,7 @@ void rcu_idle_exit(void)
local_irq_save(flags);
rcu_eqs_exit(false);
- rcu_sysidle_exit(&__get_cpu_var(rcu_dynticks), 0);
+ rcu_sysidle_exit(this_cpu_ptr(&rcu_dynticks), 0);
local_irq_restore(flags);
}
EXPORT_SYMBOL_GPL(rcu_idle_exit);
@@ -599,7 +594,7 @@ void rcu_irq_enter(void)
long long oldval;
local_irq_save(flags);
- rdtp = &__get_cpu_var(rcu_dynticks);
+ rdtp = this_cpu_ptr(&rcu_dynticks);
oldval = rdtp->dynticks_nesting;
rdtp->dynticks_nesting++;
WARN_ON_ONCE(rdtp->dynticks_nesting == 0);
@@ -620,7 +615,7 @@ void rcu_irq_enter(void)
*/
void rcu_nmi_enter(void)
{
- struct rcu_dynticks *rdtp = &__get_cpu_var(rcu_dynticks);
+ struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
if (rdtp->dynticks_nmi_nesting == 0 &&
(atomic_read(&rdtp->dynticks) & 0x1))
@@ -642,7 +637,7 @@ void rcu_nmi_enter(void)
*/
void rcu_nmi_exit(void)
{
- struct rcu_dynticks *rdtp = &__get_cpu_var(rcu_dynticks);
+ struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
if (rdtp->dynticks_nmi_nesting == 0 ||
--rdtp->dynticks_nmi_nesting != 0)
@@ -655,21 +650,34 @@ void rcu_nmi_exit(void)
}
/**
- * rcu_is_cpu_idle - see if RCU thinks that the current CPU is idle
+ * __rcu_is_watching - are RCU read-side critical sections safe?
+ *
+ * Return true if RCU is watching the running CPU, which means that
+ * this CPU can safely enter RCU read-side critical sections. Unlike
+ * rcu_is_watching(), the caller of __rcu_is_watching() must have at
+ * least disabled preemption.
+ */
+bool __rcu_is_watching(void)
+{
+ return atomic_read(this_cpu_ptr(&rcu_dynticks.dynticks)) & 0x1;
+}
+
+/**
+ * rcu_is_watching - see if RCU thinks that the current CPU is idle
*
* If the current CPU is in its idle loop and is neither in an interrupt
* or NMI handler, return true.
*/
-int rcu_is_cpu_idle(void)
+bool rcu_is_watching(void)
{
int ret;
preempt_disable();
- ret = (atomic_read(&__get_cpu_var(rcu_dynticks).dynticks) & 0x1) == 0;
+ ret = __rcu_is_watching();
preempt_enable();
return ret;
}
-EXPORT_SYMBOL(rcu_is_cpu_idle);
+EXPORT_SYMBOL_GPL(rcu_is_watching);
#if defined(CONFIG_PROVE_RCU) && defined(CONFIG_HOTPLUG_CPU)
@@ -703,7 +711,7 @@ bool rcu_lockdep_current_cpu_online(void)
if (in_nmi())
return 1;
preempt_disable();
- rdp = &__get_cpu_var(rcu_sched_data);
+ rdp = this_cpu_ptr(&rcu_sched_data);
rnp = rdp->mynode;
ret = (rdp->grpmask & rnp->qsmaskinit) ||
!rcu_scheduler_fully_active;
@@ -723,7 +731,7 @@ EXPORT_SYMBOL_GPL(rcu_lockdep_current_cpu_online);
*/
static int rcu_is_cpu_rrupt_from_idle(void)
{
- return __get_cpu_var(rcu_dynticks).dynticks_nesting <= 1;
+ return __this_cpu_read(rcu_dynticks.dynticks_nesting) <= 1;
}
/*
@@ -802,8 +810,11 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp,
static void record_gp_stall_check_time(struct rcu_state *rsp)
{
- rsp->gp_start = jiffies;
- rsp->jiffies_stall = jiffies + rcu_jiffies_till_stall_check();
+ unsigned long j = ACCESS_ONCE(jiffies);
+
+ rsp->gp_start = j;
+ smp_wmb(); /* Record start time before stall time. */
+ rsp->jiffies_stall = j + rcu_jiffies_till_stall_check();
}
/*
@@ -898,6 +909,12 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
force_quiescent_state(rsp); /* Kick them all. */
}
+/*
+ * This function really isn't for public consumption, but RCU is special in
+ * that context switches can allow the state machine to make progress.
+ */
+extern void resched_cpu(int cpu);
+
static void print_cpu_stall(struct rcu_state *rsp)
{
int cpu;
@@ -927,22 +944,60 @@ static void print_cpu_stall(struct rcu_state *rsp)
3 * rcu_jiffies_till_stall_check() + 3;
raw_spin_unlock_irqrestore(&rnp->lock, flags);
- set_need_resched(); /* kick ourselves to get things going. */
+ /*
+ * Attempt to revive the RCU machinery by forcing a context switch.
+ *
+ * A context switch would normally allow the RCU state machine to make
+ * progress and it could be we're stuck in kernel space without context
+ * switches for an entirely unreasonable amount of time.
+ */
+ resched_cpu(smp_processor_id());
}
static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
{
+ unsigned long completed;
+ unsigned long gpnum;
+ unsigned long gps;
unsigned long j;
unsigned long js;
struct rcu_node *rnp;
- if (rcu_cpu_stall_suppress)
+ if (rcu_cpu_stall_suppress || !rcu_gp_in_progress(rsp))
return;
j = ACCESS_ONCE(jiffies);
+
+ /*
+ * Lots of memory barriers to reject false positives.
+ *
+ * The idea is to pick up rsp->gpnum, then rsp->jiffies_stall,
+ * then rsp->gp_start, and finally rsp->completed. These values
+ * are updated in the opposite order with memory barriers (or
+ * equivalent) during grace-period initialization and cleanup.
+ * Now, a false positive can occur if we get an new value of
+ * rsp->gp_start and a old value of rsp->jiffies_stall. But given
+ * the memory barriers, the only way that this can happen is if one
+ * grace period ends and another starts between these two fetches.
+ * Detect this by comparing rsp->completed with the previous fetch
+ * from rsp->gpnum.
+ *
+ * Given this check, comparisons of jiffies, rsp->jiffies_stall,
+ * and rsp->gp_start suffice to forestall false positives.
+ */
+ gpnum = ACCESS_ONCE(rsp->gpnum);
+ smp_rmb(); /* Pick up ->gpnum first... */
js = ACCESS_ONCE(rsp->jiffies_stall);
+ smp_rmb(); /* ...then ->jiffies_stall before the rest... */
+ gps = ACCESS_ONCE(rsp->gp_start);
+ smp_rmb(); /* ...and finally ->gp_start before ->completed. */
+ completed = ACCESS_ONCE(rsp->completed);
+ if (ULONG_CMP_GE(completed, gpnum) ||
+ ULONG_CMP_LT(j, js) ||
+ ULONG_CMP_GE(gps, js))
+ return; /* No stall or GP completed since entering function. */
rnp = rdp->mynode;
if (rcu_gp_in_progress(rsp) &&
- (ACCESS_ONCE(rnp->qsmask) & rdp->grpmask) && ULONG_CMP_GE(j, js)) {
+ (ACCESS_ONCE(rnp->qsmask) & rdp->grpmask)) {
/* We haven't checked in, so go dump stack. */
print_cpu_stall(rsp);
@@ -1297,7 +1352,7 @@ static void note_gp_changes(struct rcu_state *rsp, struct rcu_data *rdp)
}
/*
- * Initialize a new grace period.
+ * Initialize a new grace period. Return 0 if no grace period required.
*/
static int rcu_gp_init(struct rcu_state *rsp)
{
@@ -1306,18 +1361,27 @@ static int rcu_gp_init(struct rcu_state *rsp)
rcu_bind_gp_kthread();
raw_spin_lock_irq(&rnp->lock);
+ if (rsp->gp_flags == 0) {
+ /* Spurious wakeup, tell caller to go back to sleep. */
+ raw_spin_unlock_irq(&rnp->lock);
+ return 0;
+ }
rsp->gp_flags = 0; /* Clear all flags: New grace period. */
- if (rcu_gp_in_progress(rsp)) {
- /* Grace period already in progress, don't start another. */
+ if (WARN_ON_ONCE(rcu_gp_in_progress(rsp))) {
+ /*
+ * Grace period already in progress, don't start another.
+ * Not supposed to be able to happen.
+ */
raw_spin_unlock_irq(&rnp->lock);
return 0;
}
/* Advance to a new grace period and initialize state. */
+ record_gp_stall_check_time(rsp);
+ smp_wmb(); /* Record GP times before starting GP. */
rsp->gpnum++;
trace_rcu_grace_period(rsp->name, rsp->gpnum, TPS("start"));
- record_gp_stall_check_time(rsp);
raw_spin_unlock_irq(&rnp->lock);
/* Exclude any concurrent CPU-hotplug operations. */
@@ -1366,7 +1430,7 @@ static int rcu_gp_init(struct rcu_state *rsp)
/*
* Do one round of quiescent-state forcing.
*/
-int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in)
+static int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in)
{
int fqs_state = fqs_state_in;
bool isidle = false;
@@ -1451,8 +1515,12 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
rsp->fqs_state = RCU_GP_IDLE;
rdp = this_cpu_ptr(rsp->rda);
rcu_advance_cbs(rsp, rnp, rdp); /* Reduce false positives below. */
- if (cpu_needs_another_gp(rsp, rdp))
- rsp->gp_flags = 1;
+ if (cpu_needs_another_gp(rsp, rdp)) {
+ rsp->gp_flags = RCU_GP_FLAG_INIT;
+ trace_rcu_grace_period(rsp->name,
+ ACCESS_ONCE(rsp->gpnum),
+ TPS("newreq"));
+ }
raw_spin_unlock_irq(&rnp->lock);
}
@@ -1462,6 +1530,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
static int __noreturn rcu_gp_kthread(void *arg)
{
int fqs_state;
+ int gf;
unsigned long j;
int ret;
struct rcu_state *rsp = arg;
@@ -1471,14 +1540,19 @@ static int __noreturn rcu_gp_kthread(void *arg)
/* Handle grace-period start. */
for (;;) {
+ trace_rcu_grace_period(rsp->name,
+ ACCESS_ONCE(rsp->gpnum),
+ TPS("reqwait"));
wait_event_interruptible(rsp->gp_wq,
- rsp->gp_flags &
+ ACCESS_ONCE(rsp->gp_flags) &
RCU_GP_FLAG_INIT);
- if ((rsp->gp_flags & RCU_GP_FLAG_INIT) &&
- rcu_gp_init(rsp))
+ if (rcu_gp_init(rsp))
break;
cond_resched();
flush_signals(current);
+ trace_rcu_grace_period(rsp->name,
+ ACCESS_ONCE(rsp->gpnum),
+ TPS("reqwaitsig"));
}
/* Handle quiescent-state forcing. */
@@ -1488,10 +1562,16 @@ static int __noreturn rcu_gp_kthread(void *arg)
j = HZ;
jiffies_till_first_fqs = HZ;
}
+ ret = 0;
for (;;) {
- rsp->jiffies_force_qs = jiffies + j;
+ if (!ret)
+ rsp->jiffies_force_qs = jiffies + j;
+ trace_rcu_grace_period(rsp->name,
+ ACCESS_ONCE(rsp->gpnum),
+ TPS("fqswait"));
ret = wait_event_interruptible_timeout(rsp->gp_wq,
- (rsp->gp_flags & RCU_GP_FLAG_FQS) ||
+ ((gf = ACCESS_ONCE(rsp->gp_flags)) &
+ RCU_GP_FLAG_FQS) ||
(!ACCESS_ONCE(rnp->qsmask) &&
!rcu_preempt_blocked_readers_cgp(rnp)),
j);
@@ -1500,13 +1580,23 @@ static int __noreturn rcu_gp_kthread(void *arg)
!rcu_preempt_blocked_readers_cgp(rnp))
break;
/* If time for quiescent-state forcing, do it. */
- if (ret == 0 || (rsp->gp_flags & RCU_GP_FLAG_FQS)) {
+ if (ULONG_CMP_GE(jiffies, rsp->jiffies_force_qs) ||
+ (gf & RCU_GP_FLAG_FQS)) {
+ trace_rcu_grace_period(rsp->name,
+ ACCESS_ONCE(rsp->gpnum),
+ TPS("fqsstart"));
fqs_state = rcu_gp_fqs(rsp, fqs_state);
+ trace_rcu_grace_period(rsp->name,
+ ACCESS_ONCE(rsp->gpnum),
+ TPS("fqsend"));
cond_resched();
} else {
/* Deal with stray signal. */
cond_resched();
flush_signals(current);
+ trace_rcu_grace_period(rsp->name,
+ ACCESS_ONCE(rsp->gpnum),
+ TPS("fqswaitsig"));
}
j = jiffies_till_next_fqs;
if (j > HZ) {
@@ -1554,6 +1644,8 @@ rcu_start_gp_advanced(struct rcu_state *rsp, struct rcu_node *rnp,
return;
}
rsp->gp_flags = RCU_GP_FLAG_INIT;
+ trace_rcu_grace_period(rsp->name, ACCESS_ONCE(rsp->gpnum),
+ TPS("newreq"));
/*
* We can't do wakeups while holding the rnp->lock, as that
@@ -2255,7 +2347,7 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp,
* If called from an extended quiescent state, invoke the RCU
* core in order to force a re-evaluation of RCU's idleness.
*/
- if (rcu_is_cpu_idle() && cpu_online(smp_processor_id()))
+ if (!rcu_is_watching() && cpu_online(smp_processor_id()))
invoke_rcu_core();
/* If interrupts were disabled or CPU offline, don't invoke RCU core. */
@@ -2725,10 +2817,13 @@ static int rcu_cpu_has_callbacks(int cpu, bool *all_lazy)
for_each_rcu_flavor(rsp) {
rdp = per_cpu_ptr(rsp->rda, cpu);
- if (rdp->qlen != rdp->qlen_lazy)
+ if (!rdp->nxtlist)
+ continue;
+ hc = true;
+ if (rdp->qlen != rdp->qlen_lazy || !all_lazy) {
al = false;
- if (rdp->nxtlist)
- hc = true;
+ break;
+ }
}
if (all_lazy)
*all_lazy = al;
@@ -3295,8 +3390,8 @@ void __init rcu_init(void)
rcu_bootup_announce();
rcu_init_geometry();
- rcu_init_one(&rcu_sched_state, &rcu_sched_data);
rcu_init_one(&rcu_bh_state, &rcu_bh_data);
+ rcu_init_one(&rcu_sched_state, &rcu_sched_data);
__rcu_init_preempt();
open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index 5f97eab602cd..52be957c9fe2 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -104,6 +104,8 @@ struct rcu_dynticks {
/* idle-period nonlazy_posted snapshot. */
unsigned long last_accelerate;
/* Last jiffy CBs were accelerated. */
+ unsigned long last_advance_all;
+ /* Last jiffy CBs were all advanced. */
int tick_nohz_enabled_snap; /* Previously seen value from sysfs. */
#endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */
};
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index 130c97b027f2..8d85a5ce093a 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -96,10 +96,15 @@ static void __init rcu_bootup_announce_oddness(void)
#endif /* #ifdef CONFIG_RCU_NOCB_CPU_ZERO */
#ifdef CONFIG_RCU_NOCB_CPU_ALL
pr_info("\tOffload RCU callbacks from all CPUs\n");
- cpumask_setall(rcu_nocb_mask);
+ cpumask_copy(rcu_nocb_mask, cpu_possible_mask);
#endif /* #ifdef CONFIG_RCU_NOCB_CPU_ALL */
#endif /* #ifndef CONFIG_RCU_NOCB_CPU_NONE */
if (have_rcu_nocb_mask) {
+ if (!cpumask_subset(rcu_nocb_mask, cpu_possible_mask)) {
+ pr_info("\tNote: kernel parameter 'rcu_nocbs=' contains nonexistent CPUs.\n");
+ cpumask_and(rcu_nocb_mask, cpu_possible_mask,
+ rcu_nocb_mask);
+ }
cpulist_scnprintf(nocb_buf, sizeof(nocb_buf), rcu_nocb_mask);
pr_info("\tOffload RCU callbacks from CPUs: %s.\n", nocb_buf);
if (rcu_nocb_poll)
@@ -660,7 +665,7 @@ static void rcu_preempt_check_callbacks(int cpu)
static void rcu_preempt_do_callbacks(void)
{
- rcu_do_batch(&rcu_preempt_state, &__get_cpu_var(rcu_preempt_data));
+ rcu_do_batch(&rcu_preempt_state, this_cpu_ptr(&rcu_preempt_data));
}
#endif /* #ifdef CONFIG_RCU_BOOST */
@@ -1332,7 +1337,7 @@ static void invoke_rcu_callbacks_kthread(void)
*/
static bool rcu_is_callbacks_kthread(void)
{
- return __get_cpu_var(rcu_cpu_kthread_task) == current;
+ return __this_cpu_read(rcu_cpu_kthread_task) == current;
}
#define RCU_BOOST_DELAY_JIFFIES DIV_ROUND_UP(CONFIG_RCU_BOOST_DELAY * HZ, 1000)
@@ -1382,8 +1387,8 @@ static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
static void rcu_kthread_do_work(void)
{
- rcu_do_batch(&rcu_sched_state, &__get_cpu_var(rcu_sched_data));
- rcu_do_batch(&rcu_bh_state, &__get_cpu_var(rcu_bh_data));
+ rcu_do_batch(&rcu_sched_state, this_cpu_ptr(&rcu_sched_data));
+ rcu_do_batch(&rcu_bh_state, this_cpu_ptr(&rcu_bh_data));
rcu_preempt_do_callbacks();
}
@@ -1402,7 +1407,7 @@ static void rcu_cpu_kthread_park(unsigned int cpu)
static int rcu_cpu_kthread_should_run(unsigned int cpu)
{
- return __get_cpu_var(rcu_cpu_has_work);
+ return __this_cpu_read(rcu_cpu_has_work);
}
/*
@@ -1412,8 +1417,8 @@ static int rcu_cpu_kthread_should_run(unsigned int cpu)
*/
static void rcu_cpu_kthread(unsigned int cpu)
{
- unsigned int *statusp = &__get_cpu_var(rcu_cpu_kthread_status);
- char work, *workp = &__get_cpu_var(rcu_cpu_has_work);
+ unsigned int *statusp = this_cpu_ptr(&rcu_cpu_kthread_status);
+ char work, *workp = this_cpu_ptr(&rcu_cpu_has_work);
int spincnt;
for (spincnt = 0; spincnt < 10; spincnt++) {
@@ -1630,17 +1635,23 @@ module_param(rcu_idle_lazy_gp_delay, int, 0644);
extern int tick_nohz_enabled;
/*
- * Try to advance callbacks for all flavors of RCU on the current CPU.
- * Afterwards, if there are any callbacks ready for immediate invocation,
- * return true.
+ * Try to advance callbacks for all flavors of RCU on the current CPU, but
+ * only if it has been awhile since the last time we did so. Afterwards,
+ * if there are any callbacks ready for immediate invocation, return true.
*/
static bool rcu_try_advance_all_cbs(void)
{
bool cbs_ready = false;
struct rcu_data *rdp;
+ struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
struct rcu_node *rnp;
struct rcu_state *rsp;
+ /* Exit early if we advanced recently. */
+ if (jiffies == rdtp->last_advance_all)
+ return 0;
+ rdtp->last_advance_all = jiffies;
+
for_each_rcu_flavor(rsp) {
rdp = this_cpu_ptr(rsp->rda);
rnp = rdp->mynode;
@@ -1739,6 +1750,8 @@ static void rcu_prepare_for_idle(int cpu)
*/
if (rdtp->all_lazy &&
rdtp->nonlazy_posted != rdtp->nonlazy_posted_snap) {
+ rdtp->all_lazy = false;
+ rdtp->nonlazy_posted_snap = rdtp->nonlazy_posted;
invoke_rcu_core();
return;
}
@@ -1768,17 +1781,11 @@ static void rcu_prepare_for_idle(int cpu)
*/
static void rcu_cleanup_after_idle(int cpu)
{
- struct rcu_data *rdp;
- struct rcu_state *rsp;
if (rcu_is_nocb_cpu(cpu))
return;
- rcu_try_advance_all_cbs();
- for_each_rcu_flavor(rsp) {
- rdp = per_cpu_ptr(rsp->rda, cpu);
- if (cpu_has_callbacks_ready_to_invoke(rdp))
- invoke_rcu_core();
- }
+ if (rcu_try_advance_all_cbs())
+ invoke_rcu_core();
}
/*
@@ -2108,15 +2115,22 @@ static void __call_rcu_nocb_enqueue(struct rcu_data *rdp,
/* If we are not being polled and there is a kthread, awaken it ... */
t = ACCESS_ONCE(rdp->nocb_kthread);
- if (rcu_nocb_poll | !t)
+ if (rcu_nocb_poll || !t) {
+ trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
+ TPS("WakeNotPoll"));
return;
+ }
len = atomic_long_read(&rdp->nocb_q_count);
if (old_rhpp == &rdp->nocb_head) {
wake_up(&rdp->nocb_wq); /* ... only if queue was empty ... */
rdp->qlen_last_fqs_check = 0;
+ trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeEmpty"));
} else if (len > rdp->qlen_last_fqs_check + qhimark) {
wake_up_process(t); /* ... or if many callbacks queued. */
rdp->qlen_last_fqs_check = LONG_MAX / 2;
+ trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeOvf"));
+ } else {
+ trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeNot"));
}
return;
}
@@ -2140,10 +2154,12 @@ static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
if (__is_kfree_rcu_offset((unsigned long)rhp->func))
trace_rcu_kfree_callback(rdp->rsp->name, rhp,
(unsigned long)rhp->func,
- rdp->qlen_lazy, rdp->qlen);
+ -atomic_long_read(&rdp->nocb_q_count_lazy),
+ -atomic_long_read(&rdp->nocb_q_count));
else
trace_rcu_callback(rdp->rsp->name, rhp,
- rdp->qlen_lazy, rdp->qlen);
+ -atomic_long_read(&rdp->nocb_q_count_lazy),
+ -atomic_long_read(&rdp->nocb_q_count));
return 1;
}
@@ -2221,6 +2237,7 @@ static void rcu_nocb_wait_gp(struct rcu_data *rdp)
static int rcu_nocb_kthread(void *arg)
{
int c, cl;
+ bool firsttime = 1;
struct rcu_head *list;
struct rcu_head *next;
struct rcu_head **tail;
@@ -2229,14 +2246,27 @@ static int rcu_nocb_kthread(void *arg)
/* Each pass through this loop invokes one batch of callbacks */
for (;;) {
/* If not polling, wait for next batch of callbacks. */
- if (!rcu_nocb_poll)
+ if (!rcu_nocb_poll) {
+ trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
+ TPS("Sleep"));
wait_event_interruptible(rdp->nocb_wq, rdp->nocb_head);
+ } else if (firsttime) {
+ firsttime = 0;
+ trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
+ TPS("Poll"));
+ }
list = ACCESS_ONCE(rdp->nocb_head);
if (!list) {
+ if (!rcu_nocb_poll)
+ trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
+ TPS("WokeEmpty"));
schedule_timeout_interruptible(1);
flush_signals(current);
continue;
}
+ firsttime = 1;
+ trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
+ TPS("WokeNonEmpty"));
/*
* Extract queued callbacks, update counts, and wait
@@ -2257,7 +2287,11 @@ static int rcu_nocb_kthread(void *arg)
next = list->next;
/* Wait for enqueuing to complete, if needed. */
while (next == NULL && &list->next != tail) {
+ trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
+ TPS("WaitQueue"));
schedule_timeout_interruptible(1);
+ trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
+ TPS("WokeQueue"));
next = list->next;
}
debug_rcu_head_unqueue(list);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 5ac63c9a995a..f575d5bd7e7a 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -513,12 +513,11 @@ static inline void init_hrtick(void)
* might also involve a cross-CPU call to trigger the scheduler on
* the target CPU.
*/
-#ifdef CONFIG_SMP
void resched_task(struct task_struct *p)
{
int cpu;
- assert_raw_spin_locked(&task_rq(p)->lock);
+ lockdep_assert_held(&task_rq(p)->lock);
if (test_tsk_need_resched(p))
return;
@@ -526,8 +525,10 @@ void resched_task(struct task_struct *p)
set_tsk_need_resched(p);
cpu = task_cpu(p);
- if (cpu == smp_processor_id())
+ if (cpu == smp_processor_id()) {
+ set_preempt_need_resched();
return;
+ }
/* NEED_RESCHED must be visible before we test polling */
smp_mb();
@@ -546,6 +547,7 @@ void resched_cpu(int cpu)
raw_spin_unlock_irqrestore(&rq->lock, flags);
}
+#ifdef CONFIG_SMP
#ifdef CONFIG_NO_HZ_COMMON
/*
* In the semi idle case, use the nearest busy cpu for migrating timers
@@ -693,12 +695,6 @@ void sched_avg_update(struct rq *rq)
}
}
-#else /* !CONFIG_SMP */
-void resched_task(struct task_struct *p)
-{
- assert_raw_spin_locked(&task_rq(p)->lock);
- set_tsk_need_resched(p);
-}
#endif /* CONFIG_SMP */
#if defined(CONFIG_RT_GROUP_SCHED) || (defined(CONFIG_FAIR_GROUP_SCHED) && \
@@ -767,14 +763,14 @@ static void set_load_weight(struct task_struct *p)
static void enqueue_task(struct rq *rq, struct task_struct *p, int flags)
{
update_rq_clock(rq);
- sched_info_queued(p);
+ sched_info_queued(rq, p);
p->sched_class->enqueue_task(rq, p, flags);
}
static void dequeue_task(struct rq *rq, struct task_struct *p, int flags)
{
update_rq_clock(rq);
- sched_info_dequeued(p);
+ sched_info_dequeued(rq, p);
p->sched_class->dequeue_task(rq, p, flags);
}
@@ -987,7 +983,7 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
* ttwu() will sort out the placement.
*/
WARN_ON_ONCE(p->state != TASK_RUNNING && p->state != TASK_WAKING &&
- !(task_thread_info(p)->preempt_count & PREEMPT_ACTIVE));
+ !(task_preempt_count(p) & PREEMPT_ACTIVE));
#ifdef CONFIG_LOCKDEP
/*
@@ -1330,12 +1326,13 @@ ttwu_do_wakeup(struct rq *rq, struct task_struct *p, int wake_flags)
if (rq->idle_stamp) {
u64 delta = rq_clock(rq) - rq->idle_stamp;
- u64 max = 2*sysctl_sched_migration_cost;
+ u64 max = 2*rq->max_idle_balance_cost;
+
+ update_avg(&rq->avg_idle, delta);
- if (delta > max)
+ if (rq->avg_idle > max)
rq->avg_idle = max;
- else
- update_avg(&rq->avg_idle, delta);
+
rq->idle_stamp = 0;
}
#endif
@@ -1396,6 +1393,14 @@ static void sched_ttwu_pending(void)
void scheduler_ipi(void)
{
+ /*
+ * Fold TIF_NEED_RESCHED into the preempt_count; anybody setting
+ * TIF_NEED_RESCHED remotely (for the first time) will also send
+ * this IPI.
+ */
+ if (tif_need_resched())
+ set_preempt_need_resched();
+
if (llist_empty(&this_rq()->wake_list)
&& !tick_nohz_full_cpu(smp_processor_id())
&& !got_nohz_idle_kick())
@@ -1717,10 +1722,7 @@ void sched_fork(struct task_struct *p)
#if defined(CONFIG_SMP)
p->on_cpu = 0;
#endif
-#ifdef CONFIG_PREEMPT_COUNT
- /* Want to start with kernel preemption disabled. */
- task_thread_info(p)->preempt_count = 1;
-#endif
+ init_task_preempt_count(p);
#ifdef CONFIG_SMP
plist_node_init(&p->pushable_tasks, MAX_PRIO);
#endif
@@ -1838,7 +1840,7 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev,
struct task_struct *next)
{
trace_sched_switch(prev, next);
- sched_info_switch(prev, next);
+ sched_info_switch(rq, prev, next);
perf_event_task_sched_out(prev, next);
fire_sched_out_preempt_notifiers(prev, next);
prepare_lock_switch(rq, next);
@@ -2215,7 +2217,7 @@ notrace unsigned long get_parent_ip(unsigned long addr)
#if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \
defined(CONFIG_PREEMPT_TRACER))
-void __kprobes add_preempt_count(int val)
+void __kprobes preempt_count_add(int val)
{
#ifdef CONFIG_DEBUG_PREEMPT
/*
@@ -2224,7 +2226,7 @@ void __kprobes add_preempt_count(int val)
if (DEBUG_LOCKS_WARN_ON((preempt_count() < 0)))
return;
#endif
- preempt_count() += val;
+ __preempt_count_add(val);
#ifdef CONFIG_DEBUG_PREEMPT
/*
* Spinlock count overflowing soon?
@@ -2235,9 +2237,9 @@ void __kprobes add_preempt_count(int val)
if (preempt_count() == val)
trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
}
-EXPORT_SYMBOL(add_preempt_count);
+EXPORT_SYMBOL(preempt_count_add);
-void __kprobes sub_preempt_count(int val)
+void __kprobes preempt_count_sub(int val)
{
#ifdef CONFIG_DEBUG_PREEMPT
/*
@@ -2255,9 +2257,9 @@ void __kprobes sub_preempt_count(int val)
if (preempt_count() == val)
trace_preempt_on(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
- preempt_count() -= val;
+ __preempt_count_sub(val);
}
-EXPORT_SYMBOL(sub_preempt_count);
+EXPORT_SYMBOL(preempt_count_sub);
#endif
@@ -2430,6 +2432,7 @@ need_resched:
put_prev_task(rq, prev);
next = pick_next_task(rq);
clear_tsk_need_resched(prev);
+ clear_preempt_need_resched();
rq->skip_clock_update = 0;
if (likely(prev != next)) {
@@ -2520,9 +2523,9 @@ asmlinkage void __sched notrace preempt_schedule(void)
return;
do {
- add_preempt_count_notrace(PREEMPT_ACTIVE);
+ __preempt_count_add(PREEMPT_ACTIVE);
__schedule();
- sub_preempt_count_notrace(PREEMPT_ACTIVE);
+ __preempt_count_sub(PREEMPT_ACTIVE);
/*
* Check again in case we missed a preemption opportunity
@@ -2541,20 +2544,19 @@ EXPORT_SYMBOL(preempt_schedule);
*/
asmlinkage void __sched preempt_schedule_irq(void)
{
- struct thread_info *ti = current_thread_info();
enum ctx_state prev_state;
/* Catch callers which need to be fixed */
- BUG_ON(ti->preempt_count || !irqs_disabled());
+ BUG_ON(preempt_count() || !irqs_disabled());
prev_state = exception_enter();
do {
- add_preempt_count(PREEMPT_ACTIVE);
+ __preempt_count_add(PREEMPT_ACTIVE);
local_irq_enable();
__schedule();
local_irq_disable();
- sub_preempt_count(PREEMPT_ACTIVE);
+ __preempt_count_sub(PREEMPT_ACTIVE);
/*
* Check again in case we missed a preemption opportunity
@@ -3794,16 +3796,11 @@ SYSCALL_DEFINE0(sched_yield)
return 0;
}
-static inline int should_resched(void)
-{
- return need_resched() && !(preempt_count() & PREEMPT_ACTIVE);
-}
-
static void __cond_resched(void)
{
- add_preempt_count(PREEMPT_ACTIVE);
+ __preempt_count_add(PREEMPT_ACTIVE);
__schedule();
- sub_preempt_count(PREEMPT_ACTIVE);
+ __preempt_count_sub(PREEMPT_ACTIVE);
}
int __sched _cond_resched(void)
@@ -4212,7 +4209,7 @@ void init_idle(struct task_struct *idle, int cpu)
raw_spin_unlock_irqrestore(&rq->lock, flags);
/* Set the preempt count _outside_ the spinlocks! */
- task_thread_info(idle)->preempt_count = 0;
+ init_idle_preempt_count(idle, cpu);
/*
* The idle tasks have their own, simple scheduling class:
@@ -6505,6 +6502,7 @@ void __init sched_init(void)
rq->online = 0;
rq->idle_stamp = 0;
rq->avg_idle = 2*sysctl_sched_migration_cost;
+ rq->max_idle_balance_cost = sysctl_sched_migration_cost;
INIT_LIST_HEAD(&rq->cfs_tasks);
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 7c70201fbc61..2b89cd244b0d 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -3906,7 +3906,8 @@ static unsigned long __read_mostly max_load_balance_interval = HZ/10;
#define LBF_ALL_PINNED 0x01
#define LBF_NEED_BREAK 0x02
-#define LBF_SOME_PINNED 0x04
+#define LBF_DST_PINNED 0x04
+#define LBF_SOME_PINNED 0x08
struct lb_env {
struct sched_domain *sd;
@@ -3997,6 +3998,8 @@ int can_migrate_task(struct task_struct *p, struct lb_env *env)
schedstat_inc(p, se.statistics.nr_failed_migrations_affine);
+ env->flags |= LBF_SOME_PINNED;
+
/*
* Remember if this task can be migrated to any other cpu in
* our sched_group. We may want to revisit it if we couldn't
@@ -4005,13 +4008,13 @@ int can_migrate_task(struct task_struct *p, struct lb_env *env)
* Also avoid computing new_dst_cpu if we have already computed
* one in current iteration.
*/
- if (!env->dst_grpmask || (env->flags & LBF_SOME_PINNED))
+ if (!env->dst_grpmask || (env->flags & LBF_DST_PINNED))
return 0;
/* Prevent to re-select dst_cpu via env's cpus */
for_each_cpu_and(cpu, env->dst_grpmask, env->cpus) {
if (cpumask_test_cpu(cpu, tsk_cpus_allowed(p))) {
- env->flags |= LBF_SOME_PINNED;
+ env->flags |= LBF_DST_PINNED;
env->new_dst_cpu = cpu;
break;
}
@@ -4447,7 +4450,7 @@ void update_group_power(struct sched_domain *sd, int cpu)
{
struct sched_domain *child = sd->child;
struct sched_group *group, *sdg = sd->groups;
- unsigned long power;
+ unsigned long power, power_orig;
unsigned long interval;
interval = msecs_to_jiffies(sd->balance_interval);
@@ -4459,7 +4462,7 @@ void update_group_power(struct sched_domain *sd, int cpu)
return;
}
- power = 0;
+ power_orig = power = 0;
if (child->flags & SD_OVERLAP) {
/*
@@ -4467,8 +4470,12 @@ void update_group_power(struct sched_domain *sd, int cpu)
* span the current group.
*/
- for_each_cpu(cpu, sched_group_cpus(sdg))
- power += power_of(cpu);
+ for_each_cpu(cpu, sched_group_cpus(sdg)) {
+ struct sched_group *sg = cpu_rq(cpu)->sd->groups;
+
+ power_orig += sg->sgp->power_orig;
+ power += sg->sgp->power;
+ }
} else {
/*
* !SD_OVERLAP domains can assume that child groups
@@ -4477,12 +4484,14 @@ void update_group_power(struct sched_domain *sd, int cpu)
group = child->groups;
do {
+ power_orig += group->sgp->power_orig;
power += group->sgp->power;
group = group->next;
} while (group != child->groups);
}
- sdg->sgp->power_orig = sdg->sgp->power = power;
+ sdg->sgp->power_orig = power_orig;
+ sdg->sgp->power = power;
}
/*
@@ -4526,13 +4535,12 @@ fix_small_capacity(struct sched_domain *sd, struct sched_group *group)
* cpu 3 and leave one of the cpus in the second group unused.
*
* The current solution to this issue is detecting the skew in the first group
- * by noticing it has a cpu that is overloaded while the remaining cpus are
- * idle -- or rather, there's a distinct imbalance in the cpus; see
- * sg_imbalanced().
+ * by noticing the lower domain failed to reach balance and had difficulty
+ * moving tasks due to affinity constraints.
*
* When this is so detected; this group becomes a candidate for busiest; see
* update_sd_pick_busiest(). And calculcate_imbalance() and
- * find_busiest_group() avoid some of the usual balance conditional to allow it
+ * find_busiest_group() avoid some of the usual balance conditions to allow it
* to create an effective group imbalance.
*
* This is a somewhat tricky proposition since the next run might not find the
@@ -4540,49 +4548,36 @@ fix_small_capacity(struct sched_domain *sd, struct sched_group *group)
* subtle and fragile situation.
*/
-struct sg_imb_stats {
- unsigned long max_nr_running, min_nr_running;
- unsigned long max_cpu_load, min_cpu_load;
-};
-
-static inline void init_sg_imb_stats(struct sg_imb_stats *sgi)
+static inline int sg_imbalanced(struct sched_group *group)
{
- sgi->max_cpu_load = sgi->max_nr_running = 0UL;
- sgi->min_cpu_load = sgi->min_nr_running = ~0UL;
+ return group->sgp->imbalance;
}
-static inline void
-update_sg_imb_stats(struct sg_imb_stats *sgi,
- unsigned long load, unsigned long nr_running)
+/*
+ * Compute the group capacity.
+ *
+ * Avoid the issue where N*frac(smt_power) >= 1 creates 'phantom' cores by
+ * first dividing out the smt factor and computing the actual number of cores
+ * and limit power unit capacity with that.
+ */
+static inline int sg_capacity(struct lb_env *env, struct sched_group *group)
{
- if (load > sgi->max_cpu_load)
- sgi->max_cpu_load = load;
- if (sgi->min_cpu_load > load)
- sgi->min_cpu_load = load;
+ unsigned int capacity, smt, cpus;
+ unsigned int power, power_orig;
- if (nr_running > sgi->max_nr_running)
- sgi->max_nr_running = nr_running;
- if (sgi->min_nr_running > nr_running)
- sgi->min_nr_running = nr_running;
-}
+ power = group->sgp->power;
+ power_orig = group->sgp->power_orig;
+ cpus = group->group_weight;
-static inline int
-sg_imbalanced(struct sg_lb_stats *sgs, struct sg_imb_stats *sgi)
-{
- /*
- * Consider the group unbalanced when the imbalance is larger
- * than the average weight of a task.
- *
- * APZ: with cgroup the avg task weight can vary wildly and
- * might not be a suitable number - should we keep a
- * normalized nr_running number somewhere that negates
- * the hierarchy?
- */
- if ((sgi->max_cpu_load - sgi->min_cpu_load) >= sgs->load_per_task &&
- (sgi->max_nr_running - sgi->min_nr_running) > 1)
- return 1;
+ /* smt := ceil(cpus / power), assumes: 1 < smt_power < 2 */
+ smt = DIV_ROUND_UP(SCHED_POWER_SCALE * cpus, power_orig);
+ capacity = cpus / smt; /* cores */
- return 0;
+ capacity = min_t(unsigned, capacity, DIV_ROUND_CLOSEST(power, SCHED_POWER_SCALE));
+ if (!capacity)
+ capacity = fix_small_capacity(env->sd, group);
+
+ return capacity;
}
/**
@@ -4597,12 +4592,11 @@ static inline void update_sg_lb_stats(struct lb_env *env,
struct sched_group *group, int load_idx,
int local_group, struct sg_lb_stats *sgs)
{
- struct sg_imb_stats sgi;
unsigned long nr_running;
unsigned long load;
int i;
- init_sg_imb_stats(&sgi);
+ memset(sgs, 0, sizeof(*sgs));
for_each_cpu_and(i, sched_group_cpus(group), env->cpus) {
struct rq *rq = cpu_rq(i);
@@ -4610,12 +4604,10 @@ static inline void update_sg_lb_stats(struct lb_env *env,
nr_running = rq->nr_running;
/* Bias balancing toward cpus of our domain */
- if (local_group) {
+ if (local_group)
load = target_load(i, load_idx);
- } else {
+ else
load = source_load(i, load_idx);
- update_sg_imb_stats(&sgi, load, nr_running);
- }
sgs->group_load += load;
sgs->sum_nr_running += nr_running;
@@ -4624,10 +4616,6 @@ static inline void update_sg_lb_stats(struct lb_env *env,
sgs->idle_cpus++;
}
- if (local_group && (env->idle != CPU_NEWLY_IDLE ||
- time_after_eq(jiffies, group->sgp->next_update)))
- update_group_power(env->sd, env->dst_cpu);
-
/* Adjust by relative CPU power of the group */
sgs->group_power = group->sgp->power;
sgs->avg_load = (sgs->group_load*SCHED_POWER_SCALE) / sgs->group_power;
@@ -4635,16 +4623,11 @@ static inline void update_sg_lb_stats(struct lb_env *env,
if (sgs->sum_nr_running)
sgs->load_per_task = sgs->sum_weighted_load / sgs->sum_nr_running;
- sgs->group_imb = sg_imbalanced(sgs, &sgi);
-
- sgs->group_capacity =
- DIV_ROUND_CLOSEST(sgs->group_power, SCHED_POWER_SCALE);
-
- if (!sgs->group_capacity)
- sgs->group_capacity = fix_small_capacity(env->sd, group);
-
sgs->group_weight = group->group_weight;
+ sgs->group_imb = sg_imbalanced(group);
+ sgs->group_capacity = sg_capacity(env, group);
+
if (sgs->group_capacity > sgs->sum_nr_running)
sgs->group_has_capacity = 1;
}
@@ -4720,11 +4703,17 @@ static inline void update_sd_lb_stats(struct lb_env *env,
if (local_group) {
sds->local = sg;
sgs = &sds->local_stat;
+
+ if (env->idle != CPU_NEWLY_IDLE ||
+ time_after_eq(jiffies, sg->sgp->next_update))
+ update_group_power(env->sd, env->dst_cpu);
}
- memset(sgs, 0, sizeof(*sgs));
update_sg_lb_stats(env, sg, load_idx, local_group, sgs);
+ if (local_group)
+ goto next_group;
+
/*
* In case the child domain prefers tasks go to siblings
* first, lower the sg capacity to one so that we'll try
@@ -4735,19 +4724,20 @@ static inline void update_sd_lb_stats(struct lb_env *env,
* heaviest group when it is already under-utilized (possible
* with a large weight task outweighs the tasks on the system).
*/
- if (prefer_sibling && !local_group &&
- sds->local && sds->local_stat.group_has_capacity)
+ if (prefer_sibling && sds->local &&
+ sds->local_stat.group_has_capacity)
sgs->group_capacity = min(sgs->group_capacity, 1U);
- /* Now, start updating sd_lb_stats */
- sds->total_load += sgs->group_load;
- sds->total_pwr += sgs->group_power;
-
- if (!local_group && update_sd_pick_busiest(env, sds, sg, sgs)) {
+ if (update_sd_pick_busiest(env, sds, sg, sgs)) {
sds->busiest = sg;
sds->busiest_stat = *sgs;
}
+next_group:
+ /* Now, start updating sd_lb_stats */
+ sds->total_load += sgs->group_load;
+ sds->total_pwr += sgs->group_power;
+
sg = sg->next;
} while (sg != env->sd->groups);
}
@@ -5164,6 +5154,7 @@ static int load_balance(int this_cpu, struct rq *this_rq,
int *continue_balancing)
{
int ld_moved, cur_ld_moved, active_balance = 0;
+ struct sched_domain *sd_parent = sd->parent;
struct sched_group *group;
struct rq *busiest;
unsigned long flags;
@@ -5268,17 +5259,17 @@ more_balance:
* moreover subsequent load balance cycles should correct the
* excess load moved.
*/
- if ((env.flags & LBF_SOME_PINNED) && env.imbalance > 0) {
+ if ((env.flags & LBF_DST_PINNED) && env.imbalance > 0) {
+
+ /* Prevent to re-select dst_cpu via env's cpus */
+ cpumask_clear_cpu(env.dst_cpu, env.cpus);
env.dst_rq = cpu_rq(env.new_dst_cpu);
env.dst_cpu = env.new_dst_cpu;
- env.flags &= ~LBF_SOME_PINNED;
+ env.flags &= ~LBF_DST_PINNED;
env.loop = 0;
env.loop_break = sched_nr_migrate_break;
- /* Prevent to re-select dst_cpu via env's cpus */
- cpumask_clear_cpu(env.dst_cpu, env.cpus);
-
/*
* Go back to "more_balance" rather than "redo" since we
* need to continue with same src_cpu.
@@ -5286,6 +5277,18 @@ more_balance:
goto more_balance;
}
+ /*
+ * We failed to reach balance because of affinity.
+ */
+ if (sd_parent) {
+ int *group_imbalance = &sd_parent->groups->sgp->imbalance;
+
+ if ((env.flags & LBF_SOME_PINNED) && env.imbalance > 0) {
+ *group_imbalance = 1;
+ } else if (*group_imbalance)
+ *group_imbalance = 0;
+ }
+
/* All tasks on this runqueue were pinned by CPU affinity */
if (unlikely(env.flags & LBF_ALL_PINNED)) {
cpumask_clear_cpu(cpu_of(busiest), cpus);
@@ -5393,6 +5396,7 @@ void idle_balance(int this_cpu, struct rq *this_rq)
struct sched_domain *sd;
int pulled_task = 0;
unsigned long next_balance = jiffies + HZ;
+ u64 curr_cost = 0;
this_rq->idle_stamp = rq_clock(this_rq);
@@ -5409,15 +5413,27 @@ void idle_balance(int this_cpu, struct rq *this_rq)
for_each_domain(this_cpu, sd) {
unsigned long interval;
int continue_balancing = 1;
+ u64 t0, domain_cost;
if (!(sd->flags & SD_LOAD_BALANCE))
continue;
+ if (this_rq->avg_idle < curr_cost + sd->max_newidle_lb_cost)
+ break;
+
if (sd->flags & SD_BALANCE_NEWIDLE) {
+ t0 = sched_clock_cpu(this_cpu);
+
/* If we've pulled tasks over stop searching: */
pulled_task = load_balance(this_cpu, this_rq,
sd, CPU_NEWLY_IDLE,
&continue_balancing);
+
+ domain_cost = sched_clock_cpu(this_cpu) - t0;
+ if (domain_cost > sd->max_newidle_lb_cost)
+ sd->max_newidle_lb_cost = domain_cost;
+
+ curr_cost += domain_cost;
}
interval = msecs_to_jiffies(sd->balance_interval);
@@ -5439,6 +5455,9 @@ void idle_balance(int this_cpu, 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;
}
/*
@@ -5662,15 +5681,39 @@ static void rebalance_domains(int cpu, enum cpu_idle_type idle)
/* Earliest time when we have to do rebalance again */
unsigned long next_balance = jiffies + 60*HZ;
int update_next_balance = 0;
- int need_serialize;
+ int need_serialize, need_decay = 0;
+ u64 max_cost = 0;
update_blocked_averages(cpu);
rcu_read_lock();
for_each_domain(cpu, sd) {
+ /*
+ * Decay the newidle max times here because this is a regular
+ * visit to all the domains. Decay ~1% per second.
+ */
+ if (time_after(jiffies, sd->next_decay_max_lb_cost)) {
+ sd->max_newidle_lb_cost =
+ (sd->max_newidle_lb_cost * 253) / 256;
+ sd->next_decay_max_lb_cost = jiffies + HZ;
+ need_decay = 1;
+ }
+ max_cost += sd->max_newidle_lb_cost;
+
if (!(sd->flags & SD_LOAD_BALANCE))
continue;
+ /*
+ * Stop the load balance at this level. There is another
+ * CPU in our sched group which is doing load balancing more
+ * actively.
+ */
+ if (!continue_balancing) {
+ if (need_decay)
+ continue;
+ break;
+ }
+
interval = sd->balance_interval;
if (idle != CPU_IDLE)
interval *= sd->busy_factor;
@@ -5689,7 +5732,7 @@ static void rebalance_domains(int cpu, enum cpu_idle_type idle)
if (time_after_eq(jiffies, sd->last_balance + interval)) {
if (load_balance(cpu, rq, sd, idle, &continue_balancing)) {
/*
- * The LBF_SOME_PINNED logic could have changed
+ * The LBF_DST_PINNED logic could have changed
* env->dst_cpu, so we can't know our idle
* state even if we migrated tasks. Update it.
*/
@@ -5704,14 +5747,14 @@ out:
next_balance = sd->last_balance + interval;
update_next_balance = 1;
}
-
+ }
+ if (need_decay) {
/*
- * Stop the load balance at this level. There is another
- * CPU in our sched group which is doing load balancing more
- * actively.
+ * Ensure the rq-wide value also decays but keep it at a
+ * reasonable floor to avoid funnies with rq->avg_idle.
*/
- if (!continue_balancing)
- break;
+ rq->max_idle_balance_cost =
+ max((u64)sysctl_sched_migration_cost, max_cost);
}
rcu_read_unlock();
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index b3c5653e1dca..e82484db7699 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -476,6 +476,9 @@ struct rq {
u64 age_stamp;
u64 idle_stamp;
u64 avg_idle;
+
+ /* This is used to determine avg_idle's max value */
+ u64 max_idle_balance_cost;
#endif
#ifdef CONFIG_IRQ_TIME_ACCOUNTING
@@ -605,6 +608,7 @@ struct sched_group_power {
*/
unsigned int power, power_orig;
unsigned long next_update;
+ int imbalance; /* XXX unrelated to power but shared group state */
/*
* Number of busy cpus in this group.
*/
diff --git a/kernel/sched/stats.h b/kernel/sched/stats.h
index c7edee71bce8..4ab704339656 100644
--- a/kernel/sched/stats.h
+++ b/kernel/sched/stats.h
@@ -59,9 +59,9 @@ static inline void sched_info_reset_dequeued(struct task_struct *t)
* from dequeue_task() to account for possible rq->clock skew across cpus. The
* delta taken on each cpu would annul the skew.
*/
-static inline void sched_info_dequeued(struct task_struct *t)
+static inline void sched_info_dequeued(struct rq *rq, struct task_struct *t)
{
- unsigned long long now = rq_clock(task_rq(t)), delta = 0;
+ unsigned long long now = rq_clock(rq), delta = 0;
if (unlikely(sched_info_on()))
if (t->sched_info.last_queued)
@@ -69,7 +69,7 @@ static inline void sched_info_dequeued(struct task_struct *t)
sched_info_reset_dequeued(t);
t->sched_info.run_delay += delta;
- rq_sched_info_dequeued(task_rq(t), delta);
+ rq_sched_info_dequeued(rq, delta);
}
/*
@@ -77,9 +77,9 @@ static inline void sched_info_dequeued(struct task_struct *t)
* long it was waiting to run. We also note when it began so that we
* can keep stats on how long its timeslice is.
*/
-static void sched_info_arrive(struct task_struct *t)
+static void sched_info_arrive(struct rq *rq, struct task_struct *t)
{
- unsigned long long now = rq_clock(task_rq(t)), delta = 0;
+ unsigned long long now = rq_clock(rq), delta = 0;
if (t->sched_info.last_queued)
delta = now - t->sched_info.last_queued;
@@ -88,7 +88,7 @@ static void sched_info_arrive(struct task_struct *t)
t->sched_info.last_arrival = now;
t->sched_info.pcount++;
- rq_sched_info_arrive(task_rq(t), delta);
+ rq_sched_info_arrive(rq, delta);
}
/*
@@ -96,11 +96,11 @@ static void sched_info_arrive(struct task_struct *t)
* the timestamp if it is already not set. It's assumed that
* sched_info_dequeued() will clear that stamp when appropriate.
*/
-static inline void sched_info_queued(struct task_struct *t)
+static inline void sched_info_queued(struct rq *rq, struct task_struct *t)
{
if (unlikely(sched_info_on()))
if (!t->sched_info.last_queued)
- t->sched_info.last_queued = rq_clock(task_rq(t));
+ t->sched_info.last_queued = rq_clock(rq);
}
/*
@@ -111,15 +111,15 @@ static inline void sched_info_queued(struct task_struct *t)
* sched_info_queued() to mark that it has now again started waiting on
* the runqueue.
*/
-static inline void sched_info_depart(struct task_struct *t)
+static inline void sched_info_depart(struct rq *rq, struct task_struct *t)
{
- unsigned long long delta = rq_clock(task_rq(t)) -
+ unsigned long long delta = rq_clock(rq) -
t->sched_info.last_arrival;
- rq_sched_info_depart(task_rq(t), delta);
+ rq_sched_info_depart(rq, delta);
if (t->state == TASK_RUNNING)
- sched_info_queued(t);
+ sched_info_queued(rq, t);
}
/*
@@ -128,32 +128,34 @@ static inline void sched_info_depart(struct task_struct *t)
* the idle task.) We are only called when prev != next.
*/
static inline void
-__sched_info_switch(struct task_struct *prev, struct task_struct *next)
+__sched_info_switch(struct rq *rq,
+ struct task_struct *prev, struct task_struct *next)
{
- struct rq *rq = task_rq(prev);
-
/*
* prev now departs the cpu. It's not interesting to record
* stats about how efficient we were at scheduling the idle
* process, however.
*/
if (prev != rq->idle)
- sched_info_depart(prev);
+ sched_info_depart(rq, prev);
if (next != rq->idle)
- sched_info_arrive(next);
+ sched_info_arrive(rq, next);
}
static inline void
-sched_info_switch(struct task_struct *prev, struct task_struct *next)
+sched_info_switch(struct rq *rq,
+ struct task_struct *prev, struct task_struct *next)
{
if (unlikely(sched_info_on()))
- __sched_info_switch(prev, next);
+ __sched_info_switch(rq, prev, next);
}
#else
-#define sched_info_queued(t) do { } while (0)
+#define sched_info_queued(rq, t) do { } while (0)
#define sched_info_reset_dequeued(t) do { } while (0)
-#define sched_info_dequeued(t) do { } while (0)
-#define sched_info_switch(t, next) do { } while (0)
+#define sched_info_dequeued(rq, t) do { } while (0)
+#define sched_info_depart(rq, t) do { } while (0)
+#define sched_info_arrive(rq, next) do { } while (0)
+#define sched_info_switch(rq, t, next) do { } while (0)
#endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */
/*
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 53cc09ceb0b8..3e88612fc87e 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -100,13 +100,13 @@ static void __local_bh_disable(unsigned long ip, unsigned int cnt)
raw_local_irq_save(flags);
/*
- * The preempt tracer hooks into add_preempt_count and will break
+ * The preempt tracer hooks into preempt_count_add and will break
* lockdep because it calls back into lockdep after SOFTIRQ_OFFSET
* is set and before current->softirq_enabled is cleared.
* We must manually increment preempt_count here and manually
* call the trace_preempt_off later.
*/
- preempt_count() += cnt;
+ __preempt_count_add(cnt);
/*
* Were softirqs turned off above:
*/
@@ -120,7 +120,7 @@ static void __local_bh_disable(unsigned long ip, unsigned int cnt)
#else /* !CONFIG_TRACE_IRQFLAGS */
static inline void __local_bh_disable(unsigned long ip, unsigned int cnt)
{
- add_preempt_count(cnt);
+ preempt_count_add(cnt);
barrier();
}
#endif /* CONFIG_TRACE_IRQFLAGS */
@@ -139,7 +139,7 @@ static void __local_bh_enable(unsigned int cnt)
if (softirq_count() == cnt)
trace_softirqs_on(_RET_IP_);
- sub_preempt_count(cnt);
+ preempt_count_sub(cnt);
}
/*
@@ -169,12 +169,12 @@ static inline void _local_bh_enable_ip(unsigned long ip)
* Keep preemption disabled until we are done with
* softirq processing:
*/
- sub_preempt_count(SOFTIRQ_DISABLE_OFFSET - 1);
+ preempt_count_sub(SOFTIRQ_DISABLE_OFFSET - 1);
if (unlikely(!in_interrupt() && local_softirq_pending()))
do_softirq();
- dec_preempt_count();
+ preempt_count_dec();
#ifdef CONFIG_TRACE_IRQFLAGS
local_irq_enable();
#endif
@@ -256,7 +256,7 @@ restart:
" exited with %08x?\n", vec_nr,
softirq_to_name[vec_nr], h->action,
prev_count, preempt_count());
- preempt_count() = prev_count;
+ preempt_count_set(prev_count);
}
rcu_bh_qs(cpu);
@@ -360,7 +360,7 @@ void irq_exit(void)
account_irq_exit_time(current);
trace_hardirq_exit();
- sub_preempt_count(HARDIRQ_OFFSET);
+ preempt_count_sub(HARDIRQ_OFFSET);
if (!in_interrupt() && local_softirq_pending())
invoke_softirq();
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 74534186a122..bcb35aba9570 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -962,9 +962,10 @@ static struct ctl_table kern_table[] = {
{
.procname = "hung_task_check_count",
.data = &sysctl_hung_task_check_count,
- .maxlen = sizeof(unsigned long),
+ .maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = proc_doulongvec_minmax,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
},
{
.procname = "hung_task_timeout_secs",
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 50a8736757f3..64cf63ca09cc 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -479,6 +479,7 @@ static inline void clocksource_dequeue_watchdog(struct clocksource *cs) { }
static inline void clocksource_resume_watchdog(void) { }
static inline int __clocksource_watchdog_kthread(void) { return 0; }
static bool clocksource_is_watchdog(struct clocksource *cs) { return false; }
+void clocksource_mark_unstable(struct clocksource *cs) { }
#endif /* CONFIG_CLOCKSOURCE_WATCHDOG */
@@ -537,40 +538,55 @@ static u32 clocksource_max_adjustment(struct clocksource *cs)
}
/**
- * clocksource_max_deferment - Returns max time the clocksource can be deferred
- * @cs: Pointer to clocksource
- *
+ * clocks_calc_max_nsecs - Returns maximum nanoseconds that can be converted
+ * @mult: cycle to nanosecond multiplier
+ * @shift: cycle to nanosecond divisor (power of two)
+ * @maxadj: maximum adjustment value to mult (~11%)
+ * @mask: bitmask for two's complement subtraction of non 64 bit counters
*/
-static u64 clocksource_max_deferment(struct clocksource *cs)
+u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask)
{
u64 max_nsecs, max_cycles;
/*
* Calculate the maximum number of cycles that we can pass to the
* cyc2ns function without overflowing a 64-bit signed result. The
- * maximum number of cycles is equal to ULLONG_MAX/(cs->mult+cs->maxadj)
+ * maximum number of cycles is equal to ULLONG_MAX/(mult+maxadj)
* which is equivalent to the below.
- * max_cycles < (2^63)/(cs->mult + cs->maxadj)
- * max_cycles < 2^(log2((2^63)/(cs->mult + cs->maxadj)))
- * max_cycles < 2^(log2(2^63) - log2(cs->mult + cs->maxadj))
- * max_cycles < 2^(63 - log2(cs->mult + cs->maxadj))
- * max_cycles < 1 << (63 - log2(cs->mult + cs->maxadj))
+ * max_cycles < (2^63)/(mult + maxadj)
+ * max_cycles < 2^(log2((2^63)/(mult + maxadj)))
+ * max_cycles < 2^(log2(2^63) - log2(mult + maxadj))
+ * max_cycles < 2^(63 - log2(mult + maxadj))
+ * max_cycles < 1 << (63 - log2(mult + maxadj))
* Please note that we add 1 to the result of the log2 to account for
* any rounding errors, ensure the above inequality is satisfied and
* no overflow will occur.
*/
- max_cycles = 1ULL << (63 - (ilog2(cs->mult + cs->maxadj) + 1));
+ max_cycles = 1ULL << (63 - (ilog2(mult + maxadj) + 1));
/*
* The actual maximum number of cycles we can defer the clocksource is
- * determined by the minimum of max_cycles and cs->mask.
+ * determined by the minimum of max_cycles and mask.
* Note: Here we subtract the maxadj to make sure we don't sleep for
* too long if there's a large negative adjustment.
*/
- max_cycles = min_t(u64, max_cycles, (u64) cs->mask);
- max_nsecs = clocksource_cyc2ns(max_cycles, cs->mult - cs->maxadj,
- cs->shift);
+ max_cycles = min(max_cycles, mask);
+ max_nsecs = clocksource_cyc2ns(max_cycles, mult - maxadj, shift);
+
+ return max_nsecs;
+}
+
+/**
+ * clocksource_max_deferment - Returns max time the clocksource can be deferred
+ * @cs: Pointer to clocksource
+ *
+ */
+static u64 clocksource_max_deferment(struct clocksource *cs)
+{
+ u64 max_nsecs;
+ max_nsecs = clocks_calc_max_nsecs(cs->mult, cs->shift, cs->maxadj,
+ cs->mask);
/*
* To ensure that the clocksource does not wrap whilst we are idle,
* limit the time the clocksource can be deferred by 12.5%. Please
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index bb2215174f05..af8d1d4f3d55 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -475,6 +475,7 @@ static void sync_cmos_clock(struct work_struct *work)
* called as close as possible to 500 ms before the new second starts.
* This code is run on a timer. If the clock is set, that timer
* may not expire at the correct time. Thus, we adjust...
+ * We want the clock to be within a couple of ticks from the target.
*/
if (!ntp_synced()) {
/*
@@ -485,7 +486,7 @@ static void sync_cmos_clock(struct work_struct *work)
}
getnstimeofday(&now);
- if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) {
+ if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec * 5) {
struct timespec adjust = now;
fail = -ENODEV;
diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c
index f9a28dd3f494..c3cfaae8fd06 100644
--- a/kernel/time/sched_clock.c
+++ b/kernel/time/sched_clock.c
@@ -8,25 +8,28 @@
#include <linux/clocksource.h>
#include <linux/init.h>
#include <linux/jiffies.h>
+#include <linux/ktime.h>
#include <linux/kernel.h>
#include <linux/moduleparam.h>
#include <linux/sched.h>
#include <linux/syscore_ops.h>
-#include <linux/timer.h>
+#include <linux/hrtimer.h>
#include <linux/sched_clock.h>
+#include <linux/seqlock.h>
+#include <linux/bitops.h>
struct clock_data {
+ ktime_t wrap_kt;
u64 epoch_ns;
- u32 epoch_cyc;
- u32 epoch_cyc_copy;
+ u64 epoch_cyc;
+ seqcount_t seq;
unsigned long rate;
u32 mult;
u32 shift;
bool suspended;
};
-static void sched_clock_poll(unsigned long wrap_ticks);
-static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0);
+static struct hrtimer sched_clock_timer;
static int irqtime = -1;
core_param(irqtime, irqtime, int, 0400);
@@ -35,14 +38,25 @@ static struct clock_data cd = {
.mult = NSEC_PER_SEC / HZ,
};
-static u32 __read_mostly sched_clock_mask = 0xffffffff;
+static u64 __read_mostly sched_clock_mask;
-static u32 notrace jiffy_sched_clock_read(void)
+static u64 notrace jiffy_sched_clock_read(void)
{
- return (u32)(jiffies - INITIAL_JIFFIES);
+ /*
+ * We don't need to use get_jiffies_64 on 32-bit arches here
+ * because we register with BITS_PER_LONG
+ */
+ return (u64)(jiffies - INITIAL_JIFFIES);
}
-static u32 __read_mostly (*read_sched_clock)(void) = jiffy_sched_clock_read;
+static u32 __read_mostly (*read_sched_clock_32)(void);
+
+static u64 notrace read_sched_clock_32_wrapper(void)
+{
+ return read_sched_clock_32();
+}
+
+static u64 __read_mostly (*read_sched_clock)(void) = jiffy_sched_clock_read;
static inline u64 notrace cyc_to_ns(u64 cyc, u32 mult, u32 shift)
{
@@ -52,25 +66,18 @@ static inline u64 notrace cyc_to_ns(u64 cyc, u32 mult, u32 shift)
static unsigned long long notrace sched_clock_32(void)
{
u64 epoch_ns;
- u32 epoch_cyc;
- u32 cyc;
+ u64 epoch_cyc;
+ u64 cyc;
+ unsigned long seq;
if (cd.suspended)
return cd.epoch_ns;
- /*
- * Load the epoch_cyc and epoch_ns atomically. We do this by
- * ensuring that we always write epoch_cyc, epoch_ns and
- * epoch_cyc_copy in strict order, and read them in strict order.
- * If epoch_cyc and epoch_cyc_copy are not equal, then we're in
- * the middle of an update, and we should repeat the load.
- */
do {
+ seq = read_seqcount_begin(&cd.seq);
epoch_cyc = cd.epoch_cyc;
- smp_rmb();
epoch_ns = cd.epoch_ns;
- smp_rmb();
- } while (epoch_cyc != cd.epoch_cyc_copy);
+ } while (read_seqcount_retry(&cd.seq, seq));
cyc = read_sched_clock();
cyc = (cyc - epoch_cyc) & sched_clock_mask;
@@ -83,49 +90,46 @@ static unsigned long long notrace sched_clock_32(void)
static void notrace update_sched_clock(void)
{
unsigned long flags;
- u32 cyc;
+ u64 cyc;
u64 ns;
cyc = read_sched_clock();
ns = cd.epoch_ns +
cyc_to_ns((cyc - cd.epoch_cyc) & sched_clock_mask,
cd.mult, cd.shift);
- /*
- * Write epoch_cyc and epoch_ns in a way that the update is
- * detectable in cyc_to_fixed_sched_clock().
- */
+
raw_local_irq_save(flags);
- cd.epoch_cyc_copy = cyc;
- smp_wmb();
+ write_seqcount_begin(&cd.seq);
cd.epoch_ns = ns;
- smp_wmb();
cd.epoch_cyc = cyc;
+ write_seqcount_end(&cd.seq);
raw_local_irq_restore(flags);
}
-static void sched_clock_poll(unsigned long wrap_ticks)
+static enum hrtimer_restart sched_clock_poll(struct hrtimer *hrt)
{
- mod_timer(&sched_clock_timer, round_jiffies(jiffies + wrap_ticks));
update_sched_clock();
+ hrtimer_forward_now(hrt, cd.wrap_kt);
+ return HRTIMER_RESTART;
}
-void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
+void __init sched_clock_register(u64 (*read)(void), int bits,
+ unsigned long rate)
{
- unsigned long r, w;
+ unsigned long r;
u64 res, wrap;
char r_unit;
if (cd.rate > rate)
return;
- BUG_ON(bits > 32);
WARN_ON(!irqs_disabled());
read_sched_clock = read;
- sched_clock_mask = (1ULL << bits) - 1;
+ sched_clock_mask = CLOCKSOURCE_MASK(bits);
cd.rate = rate;
/* calculate the mult/shift to convert counter ticks to ns. */
- clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 0);
+ clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 3600);
r = rate;
/*
@@ -142,20 +146,14 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
r_unit = ' ';
/* calculate how many ns until we wrap */
- wrap = cyc_to_ns((1ULL << bits) - 1, cd.mult, cd.shift);
- do_div(wrap, NSEC_PER_MSEC);
- w = wrap;
+ wrap = clocks_calc_max_nsecs(cd.mult, cd.shift, 0, sched_clock_mask);
+ cd.wrap_kt = ns_to_ktime(wrap - (wrap >> 3));
/* calculate the ns resolution of this counter */
res = cyc_to_ns(1ULL, cd.mult, cd.shift);
- pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lums\n",
- bits, r, r_unit, res, w);
+ pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lluns\n",
+ bits, r, r_unit, res, wrap);
- /*
- * Start the timer to keep sched_clock() properly updated and
- * sets the initial epoch.
- */
- sched_clock_timer.data = msecs_to_jiffies(w - (w / 10));
update_sched_clock();
/*
@@ -170,6 +168,12 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
pr_debug("Registered %pF as sched_clock source\n", read);
}
+void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
+{
+ read_sched_clock_32 = read;
+ sched_clock_register(read_sched_clock_32_wrapper, bits, rate);
+}
+
unsigned long long __read_mostly (*sched_clock_func)(void) = sched_clock_32;
unsigned long long notrace sched_clock(void)
@@ -184,14 +188,22 @@ void __init sched_clock_postinit(void)
* make it the final one one.
*/
if (read_sched_clock == jiffy_sched_clock_read)
- setup_sched_clock(jiffy_sched_clock_read, 32, HZ);
+ sched_clock_register(jiffy_sched_clock_read, BITS_PER_LONG, HZ);
- sched_clock_poll(sched_clock_timer.data);
+ update_sched_clock();
+
+ /*
+ * Start the timer to keep sched_clock() properly updated and
+ * sets the initial epoch.
+ */
+ hrtimer_init(&sched_clock_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ sched_clock_timer.function = sched_clock_poll;
+ hrtimer_start(&sched_clock_timer, cd.wrap_kt, HRTIMER_MODE_REL);
}
static int sched_clock_suspend(void)
{
- sched_clock_poll(sched_clock_timer.data);
+ sched_clock_poll(&sched_clock_timer);
cd.suspended = true;
return 0;
}
@@ -199,7 +211,6 @@ static int sched_clock_suspend(void)
static void sched_clock_resume(void)
{
cd.epoch_cyc = read_sched_clock();
- cd.epoch_cyc_copy = cd.epoch_cyc;
cd.suspended = false;
}
diff --git a/kernel/timer.c b/kernel/timer.c
index fab8eac627db..accfd241b9e5 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1092,7 +1092,7 @@ static int cascade(struct tvec_base *base, struct tvec *tv, int index)
static void call_timer_fn(struct timer_list *timer, void (*fn)(unsigned long),
unsigned long data)
{
- int preempt_count = preempt_count();
+ int count = preempt_count();
#ifdef CONFIG_LOCKDEP
/*
@@ -1119,16 +1119,16 @@ static void call_timer_fn(struct timer_list *timer, void (*fn)(unsigned long),
lock_map_release(&lockdep_map);
- if (preempt_count != preempt_count()) {
+ if (count != preempt_count()) {
WARN_ONCE(1, "timer: %pF preempt leak: %08x -> %08x\n",
- fn, preempt_count, preempt_count());
+ fn, count, preempt_count());
/*
* Restore the preempt count. That gives us a decent
* chance to survive and extract information. If the
* callback kept a lock held, bad luck, but not worse
* than the BUG() we had.
*/
- preempt_count() = preempt_count;
+ preempt_count_set(count);
}
}
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 987293d03ebc..98a937eb9f7a 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -305,6 +305,9 @@ static DEFINE_HASHTABLE(unbound_pool_hash, UNBOUND_POOL_HASH_ORDER);
/* I: attributes used when instantiating standard unbound pools on demand */
static struct workqueue_attrs *unbound_std_wq_attrs[NR_STD_WORKER_POOLS];
+/* I: attributes used when instantiating ordered pools on demand */
+static struct workqueue_attrs *ordered_wq_attrs[NR_STD_WORKER_POOLS];
+
struct workqueue_struct *system_wq __read_mostly;
EXPORT_SYMBOL(system_wq);
struct workqueue_struct *system_highpri_wq __read_mostly;
@@ -518,14 +521,21 @@ static inline void debug_work_activate(struct work_struct *work) { }
static inline void debug_work_deactivate(struct work_struct *work) { }
#endif
-/* allocate ID and assign it to @pool */
+/**
+ * worker_pool_assign_id - allocate ID and assing it to @pool
+ * @pool: the pool pointer of interest
+ *
+ * Returns 0 if ID in [0, WORK_OFFQ_POOL_NONE) is allocated and assigned
+ * successfully, -errno on failure.
+ */
static int worker_pool_assign_id(struct worker_pool *pool)
{
int ret;
lockdep_assert_held(&wq_pool_mutex);
- ret = idr_alloc(&worker_pool_idr, pool, 0, 0, GFP_KERNEL);
+ ret = idr_alloc(&worker_pool_idr, pool, 0, WORK_OFFQ_POOL_NONE,
+ GFP_KERNEL);
if (ret >= 0) {
pool->id = ret;
return 0;
@@ -1320,7 +1330,7 @@ static void __queue_work(int cpu, struct workqueue_struct *wq,
debug_work_activate(work);
- /* if dying, only works from the same workqueue are allowed */
+ /* if draining, only works from the same workqueue are allowed */
if (unlikely(wq->flags & __WQ_DRAINING) &&
WARN_ON_ONCE(!is_chained_work(wq)))
return;
@@ -4106,7 +4116,7 @@ out_unlock:
static int alloc_and_link_pwqs(struct workqueue_struct *wq)
{
bool highpri = wq->flags & WQ_HIGHPRI;
- int cpu;
+ int cpu, ret;
if (!(wq->flags & WQ_UNBOUND)) {
wq->cpu_pwqs = alloc_percpu(struct pool_workqueue);
@@ -4126,6 +4136,13 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)
mutex_unlock(&wq->mutex);
}
return 0;
+ } else if (wq->flags & __WQ_ORDERED) {
+ ret = apply_workqueue_attrs(wq, ordered_wq_attrs[highpri]);
+ /* there should only be single pwq for ordering guarantee */
+ WARN(!ret && (wq->pwqs.next != &wq->dfl_pwq->pwqs_node ||
+ wq->pwqs.prev != &wq->dfl_pwq->pwqs_node),
+ "ordering guarantee broken for workqueue %s\n", wq->name);
+ return ret;
} else {
return apply_workqueue_attrs(wq, unbound_std_wq_attrs[highpri]);
}
@@ -5009,10 +5026,6 @@ static int __init init_workqueues(void)
int std_nice[NR_STD_WORKER_POOLS] = { 0, HIGHPRI_NICE_LEVEL };
int i, cpu;
- /* make sure we have enough bits for OFFQ pool ID */
- BUILD_BUG_ON((1LU << (BITS_PER_LONG - WORK_OFFQ_POOL_SHIFT)) <
- WORK_CPU_END * NR_STD_WORKER_POOLS);
-
WARN_ON(__alignof__(struct pool_workqueue) < __alignof__(long long));
pwq_cache = KMEM_CACHE(pool_workqueue, SLAB_PANIC);
@@ -5051,13 +5064,23 @@ static int __init init_workqueues(void)
}
}
- /* create default unbound wq attrs */
+ /* create default unbound and ordered wq attrs */
for (i = 0; i < NR_STD_WORKER_POOLS; i++) {
struct workqueue_attrs *attrs;
BUG_ON(!(attrs = alloc_workqueue_attrs(GFP_KERNEL)));
attrs->nice = std_nice[i];
unbound_std_wq_attrs[i] = attrs;
+
+ /*
+ * An ordered wq should have only one pwq as ordering is
+ * guaranteed by max_active which is enforced by pwqs.
+ * Turn off NUMA so that dfl_pwq is used for all nodes.
+ */
+ BUG_ON(!(attrs = alloc_workqueue_attrs(GFP_KERNEL)));
+ attrs->nice = std_nice[i];
+ attrs->no_numa = true;
+ ordered_wq_attrs[i] = attrs;
}
system_wq = alloc_workqueue("events", 0, 0);
diff --git a/lib/hexdump.c b/lib/hexdump.c
index 3f0494c9d57a..8499c810909a 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -14,6 +14,8 @@
const char hex_asc[] = "0123456789abcdef";
EXPORT_SYMBOL(hex_asc);
+const char hex_asc_upper[] = "0123456789ABCDEF";
+EXPORT_SYMBOL(hex_asc_upper);
/**
* hex_to_bin - convert a hex digit to its real value
diff --git a/lib/kobject.c b/lib/kobject.c
index 962175134702..151089788c21 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -13,11 +13,33 @@
*/
#include <linux/kobject.h>
+#include <linux/kobj_completion.h>
#include <linux/string.h>
#include <linux/export.h>
#include <linux/stat.h>
#include <linux/slab.h>
+/**
+ * kobject_namespace - return @kobj's namespace tag
+ * @kobj: kobject in question
+ *
+ * Returns namespace tag of @kobj if its parent has namespace ops enabled
+ * and thus @kobj should have a namespace tag associated with it. Returns
+ * %NULL otherwise.
+ */
+const void *kobject_namespace(struct kobject *kobj)
+{
+ const struct kobj_ns_type_operations *ns_ops = kobj_ns_ops(kobj);
+ const void *ns;
+
+ if (!ns_ops || ns_ops->type == KOBJ_NS_TYPE_NONE)
+ return NULL;
+
+ ns = kobj->ktype->namespace(kobj);
+ WARN_ON(!ns); /* @kobj in a namespace is required to have !NULL tag */
+ return ns;
+}
+
/*
* populate_dir - populate directory with attributes.
* @kobj: object we're working on.
@@ -46,8 +68,9 @@ static int populate_dir(struct kobject *kobj)
static int create_dir(struct kobject *kobj)
{
- int error = 0;
- error = sysfs_create_dir(kobj);
+ int error;
+
+ error = sysfs_create_dir_ns(kobj, kobject_namespace(kobj));
if (!error) {
error = populate_dir(kobj);
if (error)
@@ -428,7 +451,7 @@ int kobject_rename(struct kobject *kobj, const char *new_name)
goto out;
}
- error = sysfs_rename_dir(kobj, new_name);
+ error = sysfs_rename_dir_ns(kobj, new_name, kobject_namespace(kobj));
if (error)
goto out;
@@ -472,6 +495,7 @@ int kobject_move(struct kobject *kobj, struct kobject *new_parent)
if (kobj->kset)
new_parent = kobject_get(&kobj->kset->kobj);
}
+
/* old object path */
devpath = kobject_get_path(kobj, GFP_KERNEL);
if (!devpath) {
@@ -486,7 +510,7 @@ int kobject_move(struct kobject *kobj, struct kobject *new_parent)
sprintf(devpath_string, "DEVPATH_OLD=%s", devpath);
envp[0] = devpath_string;
envp[1] = NULL;
- error = sysfs_move_dir(kobj, new_parent);
+ error = sysfs_move_dir_ns(kobj, new_parent, kobject_namespace(kobj));
if (error)
goto out;
old_parent = kobj->parent;
@@ -727,6 +751,55 @@ const struct sysfs_ops kobj_sysfs_ops = {
};
/**
+ * kobj_completion_init - initialize a kobj_completion object.
+ * @kc: kobj_completion
+ * @ktype: type of kobject to initialize
+ *
+ * kobj_completion structures can be embedded within structures with different
+ * lifetime rules. During the release of the enclosing object, we can
+ * wait on the release of the kobject so that we don't free it while it's
+ * still busy.
+ */
+void kobj_completion_init(struct kobj_completion *kc, struct kobj_type *ktype)
+{
+ init_completion(&kc->kc_unregister);
+ kobject_init(&kc->kc_kobj, ktype);
+}
+EXPORT_SYMBOL_GPL(kobj_completion_init);
+
+/**
+ * kobj_completion_release - release a kobj_completion object
+ * @kobj: kobject embedded in kobj_completion
+ *
+ * Used with kobject_release to notify waiters that the kobject has been
+ * released.
+ */
+void kobj_completion_release(struct kobject *kobj)
+{
+ struct kobj_completion *kc = kobj_to_kobj_completion(kobj);
+ complete(&kc->kc_unregister);
+}
+EXPORT_SYMBOL_GPL(kobj_completion_release);
+
+/**
+ * kobj_completion_del_and_wait - release the kobject and wait for it
+ * @kc: kobj_completion object to release
+ *
+ * Delete the kobject from sysfs and drop the reference count. Then wait
+ * until any other outstanding references are also dropped. This routine
+ * is only necessary once other references may have been taken on the
+ * kobject. Typically this happens when the kobject has been published
+ * to sysfs via kobject_add.
+ */
+void kobj_completion_del_and_wait(struct kobj_completion *kc)
+{
+ kobject_del(&kc->kc_kobj);
+ kobject_put(&kc->kc_kobj);
+ wait_for_completion(&kc->kc_unregister);
+}
+EXPORT_SYMBOL_GPL(kobj_completion_del_and_wait);
+
+/**
* kset_register - initialize and add a kset.
* @k: kset.
*/
@@ -933,10 +1006,7 @@ const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj)
bool kobj_ns_current_may_mount(enum kobj_ns_type type)
{
- bool may_mount = false;
-
- if (type == KOBJ_NS_TYPE_NONE)
- return true;
+ bool may_mount = true;
spin_lock(&kobj_ns_type_lock);
if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) &&
diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c
index 6dc09d8f4c24..872a15a2a637 100644
--- a/lib/locking-selftest.c
+++ b/lib/locking-selftest.c
@@ -1002,7 +1002,7 @@ static void dotest(void (*testcase_fn)(void), int expected, int lockclass_mask)
* Some tests (e.g. double-unlock) might corrupt the preemption
* count, so restore it:
*/
- preempt_count() = saved_preempt_count;
+ preempt_count_set(saved_preempt_count);
#ifdef CONFIG_TRACE_IRQFLAGS
if (softirq_count())
current->softirqs_enabled = 0;
diff --git a/lib/lzo/lzo1x_decompress_safe.c b/lib/lzo/lzo1x_decompress_safe.c
index 569985d522d5..e3edc5f3f5ee 100644
--- a/lib/lzo/lzo1x_decompress_safe.c
+++ b/lib/lzo/lzo1x_decompress_safe.c
@@ -72,9 +72,11 @@ copy_literal_run:
COPY8(op, ip);
op += 8;
ip += 8;
+# if !defined(__arm__)
COPY8(op, ip);
op += 8;
ip += 8;
+# endif
} while (ip < ie);
ip = ie;
op = oe;
@@ -159,9 +161,11 @@ copy_literal_run:
COPY8(op, m_pos);
op += 8;
m_pos += 8;
+# if !defined(__arm__)
COPY8(op, m_pos);
op += 8;
m_pos += 8;
+# endif
} while (op < oe);
op = oe;
if (HAVE_IP(6)) {
diff --git a/lib/lzo/lzodefs.h b/lib/lzo/lzodefs.h
index 6710b83ce72e..db756ccb2756 100644
--- a/lib/lzo/lzodefs.h
+++ b/lib/lzo/lzodefs.h
@@ -12,8 +12,14 @@
*/
+#if 1 && defined(__arm__) && ((__LINUX_ARM_ARCH__ >= 6) || defined(__ARM_FEATURE_UNALIGNED))
+#define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 1
+#define COPY4(dst, src) \
+ * (u32 *) (void *) (dst) = * (const u32 *) (const void *) (src)
+#else
#define COPY4(dst, src) \
put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
+#endif
#if defined(__x86_64__)
#define COPY8(dst, src) \
put_unaligned(get_unaligned((const u64 *)(src)), (u64 *)(dst))
diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c
index 4c0d0e51d49e..04abe53f12a1 100644
--- a/lib/smp_processor_id.c
+++ b/lib/smp_processor_id.c
@@ -9,10 +9,9 @@
notrace unsigned int debug_smp_processor_id(void)
{
- unsigned long preempt_count = preempt_count();
int this_cpu = raw_smp_processor_id();
- if (likely(preempt_count))
+ if (likely(preempt_count()))
goto out;
if (irqs_disabled())
diff --git a/mm/filemap.c b/mm/filemap.c
index 84b0a13465f0..d99b21d01d5d 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1317,44 +1317,6 @@ out:
file_accessed(filp);
}
-int file_read_actor(read_descriptor_t *desc, struct page *page,
- unsigned long offset, unsigned long size)
-{
- char *kaddr;
- unsigned long left, count = desc->count;
-
- if (size > count)
- size = count;
-
- /*
- * Faults on the destination of a read are common, so do it before
- * taking the kmap.
- */
- if (!fault_in_pages_writeable(desc->arg.buf, size)) {
- kaddr = kmap_atomic(page);
- left = __copy_to_user_inatomic(desc->arg.buf,
- kaddr + offset, size);
- kunmap_atomic(kaddr);
- if (left == 0)
- goto success;
- }
-
- /* Do it the slow way */
- kaddr = kmap(page);
- left = __copy_to_user(desc->arg.buf, kaddr + offset, size);
- kunmap(page);
-
- if (left) {
- size -= left;
- desc->error = -EFAULT;
- }
-success:
- desc->count = count - size;
- desc->written += size;
- desc->arg.buf += size;
- return size;
-}
-
/*
* Performs necessary checks before doing a write
* @iov: io vector request
@@ -1394,31 +1356,41 @@ int generic_segment_checks(const struct iovec *iov,
}
EXPORT_SYMBOL(generic_segment_checks);
+int file_read_iter_actor(read_descriptor_t *desc, struct page *page,
+ unsigned long offset, unsigned long size)
+{
+ struct iov_iter *iter = desc->arg.data;
+ unsigned long copied = 0;
+
+ if (size > desc->count)
+ size = desc->count;
+
+ copied = __iov_iter_copy_to_user(page, iter, offset, size);
+ if (copied < size)
+ desc->error = -EFAULT;
+
+ iov_iter_advance(iter, copied);
+ desc->count -= copied;
+ desc->written += copied;
+
+ return copied;
+}
+
/**
- * generic_file_aio_read - generic filesystem read routine
+ * generic_file_read_iter - generic filesystem read routine
* @iocb: kernel I/O control block
- * @iov: io vector request
- * @nr_segs: number of segments in the iovec
+ * @iter: memory vector
* @pos: current file position
- *
- * This is the "read()" routine for all filesystems
- * that can use the page cache directly.
*/
ssize_t
-generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
+generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
{
struct file *filp = iocb->ki_filp;
- ssize_t retval;
- unsigned long seg = 0;
- size_t count;
+ read_descriptor_t desc;
+ ssize_t retval = 0;
+ size_t count = iov_iter_count(iter);
loff_t *ppos = &iocb->ki_pos;
- count = 0;
- retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE);
- if (retval)
- return retval;
-
/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
if (filp->f_flags & O_DIRECT) {
loff_t size;
@@ -1432,11 +1404,10 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
size = i_size_read(inode);
if (pos < size) {
retval = filemap_write_and_wait_range(mapping, pos,
- pos + iov_length(iov, nr_segs) - 1);
- if (!retval) {
+ pos + count - 1);
+ if (!retval)
retval = mapping->a_ops->direct_IO(READ, iocb,
- iov, pos, nr_segs);
- }
+ iter, pos);
if (retval > 0) {
*ppos = pos + retval;
count -= retval;
@@ -1457,42 +1428,47 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
}
}
- count = retval;
- for (seg = 0; seg < nr_segs; seg++) {
- read_descriptor_t desc;
- loff_t offset = 0;
-
- /*
- * If we did a short DIO read we need to skip the section of the
- * iov that we've already read data into.
- */
- if (count) {
- if (count > iov[seg].iov_len) {
- count -= iov[seg].iov_len;
- continue;
- }
- offset = count;
- count = 0;
- }
-
- desc.written = 0;
- desc.arg.buf = iov[seg].iov_base + offset;
- desc.count = iov[seg].iov_len - offset;
- if (desc.count == 0)
- continue;
- desc.error = 0;
- do_generic_file_read(filp, ppos, &desc, file_read_actor);
- retval += desc.written;
- if (desc.error) {
- retval = retval ?: desc.error;
- break;
- }
- if (desc.count > 0)
- break;
- }
+ desc.written = 0;
+ desc.arg.data = iter;
+ desc.count = count;
+ desc.error = 0;
+ do_generic_file_read(filp, ppos, &desc, file_read_iter_actor);
+ if (desc.written)
+ retval = desc.written;
+ else
+ retval = desc.error;
out:
return retval;
}
+EXPORT_SYMBOL(generic_file_read_iter);
+
+/**
+ * generic_file_aio_read - generic filesystem read routine
+ * @iocb: kernel I/O control block
+ * @iov: io vector request
+ * @nr_segs: number of segments in the iovec
+ * @pos: current file position
+ *
+ * This is the "read()" routine for all filesystems
+ * that can use the page cache directly.
+ */
+ssize_t
+generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
+{
+ struct iov_iter iter;
+ int ret;
+ size_t count;
+
+ count = 0;
+ ret = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE);
+ if (ret)
+ return ret;
+
+ iov_iter_init(&iter, iov, nr_segs, count, 0);
+
+ return generic_file_read_iter(iocb, &iter, pos);
+}
EXPORT_SYMBOL(generic_file_aio_read);
#ifdef CONFIG_MMU
@@ -1954,150 +1930,6 @@ struct page *read_cache_page(struct address_space *mapping,
}
EXPORT_SYMBOL(read_cache_page);
-static size_t __iovec_copy_from_user_inatomic(char *vaddr,
- const struct iovec *iov, size_t base, size_t bytes)
-{
- size_t copied = 0, left = 0;
-
- while (bytes) {
- char __user *buf = iov->iov_base + base;
- int copy = min(bytes, iov->iov_len - base);
-
- base = 0;
- left = __copy_from_user_inatomic(vaddr, buf, copy);
- copied += copy;
- bytes -= copy;
- vaddr += copy;
- iov++;
-
- if (unlikely(left))
- break;
- }
- return copied - left;
-}
-
-/*
- * Copy as much as we can into the page and return the number of bytes which
- * were successfully copied. If a fault is encountered then return the number of
- * bytes which were copied.
- */
-size_t iov_iter_copy_from_user_atomic(struct page *page,
- struct iov_iter *i, unsigned long offset, size_t bytes)
-{
- char *kaddr;
- size_t copied;
-
- BUG_ON(!in_atomic());
- kaddr = kmap_atomic(page);
- if (likely(i->nr_segs == 1)) {
- int left;
- char __user *buf = i->iov->iov_base + i->iov_offset;
- left = __copy_from_user_inatomic(kaddr + offset, buf, bytes);
- copied = bytes - left;
- } else {
- copied = __iovec_copy_from_user_inatomic(kaddr + offset,
- i->iov, i->iov_offset, bytes);
- }
- kunmap_atomic(kaddr);
-
- return copied;
-}
-EXPORT_SYMBOL(iov_iter_copy_from_user_atomic);
-
-/*
- * This has the same sideeffects and return value as
- * iov_iter_copy_from_user_atomic().
- * The difference is that it attempts to resolve faults.
- * Page must not be locked.
- */
-size_t iov_iter_copy_from_user(struct page *page,
- struct iov_iter *i, unsigned long offset, size_t bytes)
-{
- char *kaddr;
- size_t copied;
-
- kaddr = kmap(page);
- if (likely(i->nr_segs == 1)) {
- int left;
- char __user *buf = i->iov->iov_base + i->iov_offset;
- left = __copy_from_user(kaddr + offset, buf, bytes);
- copied = bytes - left;
- } else {
- copied = __iovec_copy_from_user_inatomic(kaddr + offset,
- i->iov, i->iov_offset, bytes);
- }
- kunmap(page);
- return copied;
-}
-EXPORT_SYMBOL(iov_iter_copy_from_user);
-
-void iov_iter_advance(struct iov_iter *i, size_t bytes)
-{
- BUG_ON(i->count < bytes);
-
- if (likely(i->nr_segs == 1)) {
- i->iov_offset += bytes;
- i->count -= bytes;
- } else {
- const struct iovec *iov = i->iov;
- size_t base = i->iov_offset;
- unsigned long nr_segs = i->nr_segs;
-
- /*
- * The !iov->iov_len check ensures we skip over unlikely
- * zero-length segments (without overruning the iovec).
- */
- while (bytes || unlikely(i->count && !iov->iov_len)) {
- int copy;
-
- copy = min(bytes, iov->iov_len - base);
- BUG_ON(!i->count || i->count < copy);
- i->count -= copy;
- bytes -= copy;
- base += copy;
- if (iov->iov_len == base) {
- iov++;
- nr_segs--;
- base = 0;
- }
- }
- i->iov = iov;
- i->iov_offset = base;
- i->nr_segs = nr_segs;
- }
-}
-EXPORT_SYMBOL(iov_iter_advance);
-
-/*
- * Fault in the first iovec of the given iov_iter, to a maximum length
- * of bytes. Returns 0 on success, or non-zero if the memory could not be
- * accessed (ie. because it is an invalid address).
- *
- * writev-intensive code may want this to prefault several iovecs -- that
- * would be possible (callers must not rely on the fact that _only_ the
- * first iovec will be faulted with the current implementation).
- */
-int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes)
-{
- char __user *buf = i->iov->iov_base + i->iov_offset;
- bytes = min(bytes, i->iov->iov_len - i->iov_offset);
- return fault_in_pages_readable(buf, bytes);
-}
-EXPORT_SYMBOL(iov_iter_fault_in_readable);
-
-/*
- * Return the count of just the current iov_iter segment.
- */
-size_t iov_iter_single_seg_count(const struct iov_iter *i)
-{
- const struct iovec *iov = i->iov;
- if (i->nr_segs == 1)
- return i->count;
- else
- return min(i->count, iov->iov_len - i->iov_offset);
-}
-EXPORT_SYMBOL(iov_iter_single_seg_count);
-
/*
* Performs necessary checks before doing a write
*
@@ -2203,9 +2035,8 @@ int pagecache_write_end(struct file *file, struct address_space *mapping,
EXPORT_SYMBOL(pagecache_write_end);
ssize_t
-generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long *nr_segs, loff_t pos, loff_t *ppos,
- size_t count, size_t ocount)
+generic_file_direct_write_iter(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos, loff_t *ppos, size_t count)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
@@ -2214,10 +2045,13 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
size_t write_len;
pgoff_t end;
- if (count != ocount)
- *nr_segs = iov_shorten((struct iovec *)iov, *nr_segs, count);
+ if (count != iov_iter_count(iter)) {
+ written = iov_iter_shorten(iter, count);
+ if (written)
+ goto out;
+ }
- write_len = iov_length(iov, *nr_segs);
+ write_len = count;
end = (pos + write_len - 1) >> PAGE_CACHE_SHIFT;
written = filemap_write_and_wait_range(mapping, pos, pos + write_len - 1);
@@ -2244,7 +2078,7 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
}
}
- written = mapping->a_ops->direct_IO(WRITE, iocb, iov, pos, *nr_segs);
+ written = mapping->a_ops->direct_IO(WRITE, iocb, iter, pos);
/*
* Finally, try again to invalidate clean pages which might have been
@@ -2270,6 +2104,23 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
out:
return written;
}
+EXPORT_SYMBOL(generic_file_direct_write_iter);
+
+ssize_t
+generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long *nr_segs, loff_t pos, loff_t *ppos,
+ size_t count, size_t ocount)
+{
+ struct iov_iter iter;
+ ssize_t ret;
+
+ iov_iter_init(&iter, iov, *nr_segs, ocount, 0);
+ ret = generic_file_direct_write_iter(iocb, &iter, pos, ppos, count);
+ /* generic_file_direct_write_iter() might have shortened the vec */
+ if (*nr_segs != iter.nr_segs)
+ *nr_segs = iter.nr_segs;
+ return ret;
+}
EXPORT_SYMBOL(generic_file_direct_write);
/*
@@ -2403,16 +2254,19 @@ again:
}
ssize_t
-generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos, loff_t *ppos,
- size_t count, ssize_t written)
+generic_file_buffered_write_iter(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos, loff_t *ppos, size_t count, ssize_t written)
{
struct file *file = iocb->ki_filp;
ssize_t status;
- struct iov_iter i;
- iov_iter_init(&i, iov, nr_segs, count, written);
- status = generic_perform_write(file, &i, pos);
+ if ((count + written) != iov_iter_count(iter)) {
+ int rc = iov_iter_shorten(iter, count + written);
+ if (rc)
+ return rc;
+ }
+
+ status = generic_perform_write(file, iter, pos);
if (likely(status >= 0)) {
written += status;
@@ -2421,13 +2275,24 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
return written ? written : status;
}
+EXPORT_SYMBOL(generic_file_buffered_write_iter);
+
+ssize_t
+generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos, loff_t *ppos,
+ size_t count, ssize_t written)
+{
+ struct iov_iter iter;
+ iov_iter_init(&iter, iov, nr_segs, count, written);
+ return generic_file_buffered_write_iter(iocb, &iter, pos, ppos,
+ count, written);
+}
EXPORT_SYMBOL(generic_file_buffered_write);
/**
* __generic_file_aio_write - write data to a file
* @iocb: IO state structure (file, offset, etc.)
- * @iov: vector with data to write
- * @nr_segs: number of segments in the vector
+ * @iter: iov_iter specifying memory to write
* @ppos: position where to write
*
* This function does all the work needed for actually writing data to a
@@ -2442,24 +2307,18 @@ EXPORT_SYMBOL(generic_file_buffered_write);
* A caller has to handle it. This is mainly due to the fact that we want to
* avoid syncing under i_mutex.
*/
-ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t *ppos)
+ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t *ppos)
{
struct file *file = iocb->ki_filp;
struct address_space * mapping = file->f_mapping;
- size_t ocount; /* original count */
size_t count; /* after file limit checks */
struct inode *inode = mapping->host;
loff_t pos;
ssize_t written;
ssize_t err;
- ocount = 0;
- err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
- if (err)
- return err;
-
- count = ocount;
+ count = iov_iter_count(iter);
pos = *ppos;
/* We can write back this queue in page reclaim */
@@ -2486,8 +2345,8 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
loff_t endbyte;
ssize_t written_buffered;
- written = generic_file_direct_write(iocb, iov, &nr_segs, pos,
- ppos, count, ocount);
+ written = generic_file_direct_write_iter(iocb, iter, pos,
+ ppos, count);
if (written < 0 || written == count)
goto out;
/*
@@ -2496,9 +2355,9 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
*/
pos += written;
count -= written;
- written_buffered = generic_file_buffered_write(iocb, iov,
- nr_segs, pos, ppos, count,
- written);
+ iov_iter_advance(iter, written);
+ written_buffered = generic_file_buffered_write_iter(iocb, iter,
+ pos, ppos, count, written);
/*
* If generic_file_buffered_write() retuned a synchronous error
* then we want to return the number of bytes which were
@@ -2530,13 +2389,57 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
*/
}
} else {
- written = generic_file_buffered_write(iocb, iov, nr_segs,
+ iter->count = count;
+ written = generic_file_buffered_write_iter(iocb, iter,
pos, ppos, count, written);
}
out:
current->backing_dev_info = NULL;
return written ? written : err;
}
+EXPORT_SYMBOL(__generic_file_write_iter);
+
+ssize_t generic_file_write_iter(struct kiocb *iocb, struct iov_iter *iter,
+ loff_t pos)
+{
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file->f_mapping->host;
+ ssize_t ret;
+
+ mutex_lock(&inode->i_mutex);
+ ret = __generic_file_write_iter(iocb, iter, &iocb->ki_pos);
+ mutex_unlock(&inode->i_mutex);
+
+ if (ret > 0 || ret == -EIOCBQUEUED) {
+ ssize_t err;
+
+ err = generic_write_sync(file, pos, ret);
+ if (err < 0 && ret > 0)
+ ret = err;
+ }
+ return ret;
+}
+EXPORT_SYMBOL(generic_file_write_iter);
+
+ssize_t
+__generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t *ppos)
+{
+ struct iov_iter iter;
+ size_t count;
+ int ret;
+
+ count = 0;
+ ret = generic_segment_checks(iov, &nr_segs, &count, VERIFY_READ);
+ if (ret)
+ goto out;
+
+ iov_iter_init(&iter, iov, nr_segs, count, 0);
+
+ ret = __generic_file_write_iter(iocb, &iter, ppos);
+out:
+ return ret;
+}
EXPORT_SYMBOL(__generic_file_aio_write);
/**
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 52eb3e0902cc..54766a194aa3 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -498,6 +498,29 @@ static inline bool mem_cgroup_is_root(struct mem_cgroup *memcg)
return (memcg == root_mem_cgroup);
}
+/*
+ * We restrict the id in the range of [1, 65535], so it can fit into
+ * an unsigned short.
+ */
+#define MEM_CGROUP_ID_MAX USHRT_MAX
+
+static inline unsigned short mem_cgroup_id(struct mem_cgroup *memcg)
+{
+ /*
+ * The ID of the root cgroup is 0, but memcg treat 0 as an
+ * invalid ID, so we return (cgroup_id + 1).
+ */
+ return memcg->css.cgroup->id + 1;
+}
+
+static inline struct mem_cgroup *mem_cgroup_from_id(unsigned short id)
+{
+ struct cgroup_subsys_state *css;
+
+ css = css_from_id(id - 1, &mem_cgroup_subsys);
+ return mem_cgroup_from_css(css);
+}
+
/* Writing them here to avoid exposing memcg's inner layout */
#if defined(CONFIG_INET) && defined(CONFIG_MEMCG_KMEM)
@@ -569,16 +592,11 @@ static void disarm_sock_keys(struct mem_cgroup *memcg)
#ifdef CONFIG_MEMCG_KMEM
/*
* This will be the memcg's index in each cache's ->memcg_params->memcg_caches.
- * There are two main reasons for not using the css_id for this:
- * 1) this works better in sparse environments, where we have a lot of memcgs,
- * but only a few kmem-limited. Or also, if we have, for instance, 200
- * memcgs, and none but the 200th is kmem-limited, we'd have to have a
- * 200 entry array for that.
- *
- * 2) In order not to violate the cgroup API, we would like to do all memory
- * allocation in ->create(). At that point, we haven't yet allocated the
- * css_id. Having a separate index prevents us from messing with the cgroup
- * core for this
+ * The main reason for not using cgroup id for this:
+ * this works better in sparse environments, where we have a lot of memcgs,
+ * but only a few kmem-limited. Or also, if we have, for instance, 200
+ * memcgs, and none but the 200th is kmem-limited, we'd have to have a
+ * 200 entry array for that.
*
* The current size of the caches array is stored in
* memcg_limited_groups_array_size. It will double each time we have to
@@ -593,14 +611,14 @@ int memcg_limited_groups_array_size;
* cgroups is a reasonable guess. In the future, it could be a parameter or
* tunable, but that is strictly not necessary.
*
- * MAX_SIZE should be as large as the number of css_ids. Ideally, we could get
+ * MAX_SIZE should be as large as the number of cgrp_ids. Ideally, we could get
* this constant directly from cgroup, but it is understandable that this is
* better kept as an internal representation in cgroup.c. In any case, the
- * css_id space is not getting any smaller, and we don't have to necessarily
+ * cgrp_id space is not getting any smaller, and we don't have to necessarily
* increase ours as well if it increases.
*/
#define MEMCG_CACHES_MIN_SIZE 4
-#define MEMCG_CACHES_MAX_SIZE 65535
+#define MEMCG_CACHES_MAX_SIZE MEM_CGROUP_ID_MAX
/*
* A lot of the calls to the cache allocation functions are expected to be
@@ -1405,7 +1423,7 @@ bool __mem_cgroup_same_or_subtree(const struct mem_cgroup *root_memcg,
return true;
if (!root_memcg->use_hierarchy || !memcg)
return false;
- return css_is_ancestor(&memcg->css, &root_memcg->css);
+ return cgroup_is_descendant(memcg->css.cgroup, root_memcg->css.cgroup);
}
static bool mem_cgroup_same_or_subtree(const struct mem_cgroup *root_memcg,
@@ -2850,15 +2868,10 @@ static void __mem_cgroup_cancel_local_charge(struct mem_cgroup *memcg,
*/
static struct mem_cgroup *mem_cgroup_lookup(unsigned short id)
{
- struct cgroup_subsys_state *css;
-
/* ID 0 is unused ID */
if (!id)
return NULL;
- css = css_lookup(&mem_cgroup_subsys, id);
- if (!css)
- return NULL;
- return mem_cgroup_from_css(css);
+ return mem_cgroup_from_id(id);
}
struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
@@ -4368,7 +4381,7 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
* css_get() was called in uncharge().
*/
if (do_swap_account && swapout && memcg)
- swap_cgroup_record(ent, css_id(&memcg->css));
+ swap_cgroup_record(ent, mem_cgroup_id(memcg));
}
#endif
@@ -4420,8 +4433,8 @@ static int mem_cgroup_move_swap_account(swp_entry_t entry,
{
unsigned short old_id, new_id;
- old_id = css_id(&from->css);
- new_id = css_id(&to->css);
+ old_id = mem_cgroup_id(from);
+ new_id = mem_cgroup_id(to);
if (swap_cgroup_cmpxchg(entry, old_id, new_id) == old_id) {
mem_cgroup_swap_statistics(from, false);
@@ -6202,7 +6215,6 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg)
size_t size = memcg_size();
mem_cgroup_remove_from_trees(memcg);
- free_css_id(&mem_cgroup_subsys, &memcg->css);
for_each_node(node)
free_mem_cgroup_per_zone_info(memcg, node);
@@ -6305,6 +6317,9 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css)
struct mem_cgroup *parent = mem_cgroup_from_css(css_parent(css));
int error = 0;
+ if (css->cgroup->id > MEM_CGROUP_ID_MAX)
+ return -ENOSPC;
+
if (!parent)
return 0;
@@ -6576,7 +6591,7 @@ static enum mc_target_type get_mctgt_type(struct vm_area_struct *vma,
}
/* There is a swap entry and a page doesn't exist or isn't charged */
if (ent.val && !ret &&
- css_id(&mc.from->css) == lookup_swap_cgroup_id(ent)) {
+ mem_cgroup_id(mc.from) == lookup_swap_cgroup_id(ent)) {
ret = MC_TARGET_SWAP;
if (target)
target->ent = ent;
@@ -6996,7 +7011,6 @@ struct cgroup_subsys mem_cgroup_subsys = {
.bind = mem_cgroup_bind,
.base_cftypes = mem_cgroup_files,
.early_init = 0,
- .use_id = 1,
};
#ifdef CONFIG_MEMCG_SWAP
diff --git a/mm/page_io.c b/mm/page_io.c
index 8c79a4764be0..e4e6a4f57b09 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -258,11 +258,14 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
if (sis->flags & SWP_FILE) {
struct kiocb kiocb;
struct file *swap_file = sis->swap_file;
- struct address_space *mapping = swap_file->f_mapping;
- struct iovec iov = {
- .iov_base = kmap(page),
- .iov_len = PAGE_SIZE,
+ struct bio_vec bvec = {
+ .bv_page = kmap(page),
+ .bv_len = PAGE_SIZE,
+ .bv_offset = 0,
};
+ struct iov_iter iter;
+
+ iov_iter_init_bvec(&iter, &bvec, 1, PAGE_SIZE, 0);
init_sync_kiocb(&kiocb, swap_file);
kiocb.ki_pos = page_file_offset(page);
@@ -270,9 +273,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
set_page_writeback(page);
unlock_page(page);
- ret = mapping->a_ops->direct_IO(KERNEL_WRITE,
- &kiocb, &iov,
- kiocb.ki_pos, 1);
+ ret = swap_file->f_op->write_iter(&kiocb, &iter, kiocb.ki_pos);
kunmap(page);
if (ret == PAGE_SIZE) {
count_vm_event(PSWPOUT);
diff --git a/mm/percpu.c b/mm/percpu.c
index 8c8e08f3a692..0d10defe951e 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -1706,8 +1706,9 @@ int __init pcpu_embed_first_chunk(size_t reserved_size, size_t dyn_size,
out_free_areas:
for (group = 0; group < ai->nr_groups; group++)
- free_fn(areas[group],
- ai->groups[group].nr_units * ai->unit_size);
+ if (areas[group])
+ free_fn(areas[group],
+ ai->groups[group].nr_units * ai->unit_size);
out_free:
pcpu_free_alloc_info(ai);
if (areas)
diff --git a/mm/shmem.c b/mm/shmem.c
index 8297623fcaed..8612a95d7d7e 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1464,14 +1464,23 @@ shmem_write_end(struct file *file, struct address_space *mapping,
return copied;
}
-static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_t *desc, read_actor_t actor)
+static ssize_t shmem_file_read_iter(struct kiocb *iocb,
+ struct iov_iter *iter, loff_t pos)
{
+ read_descriptor_t desc;
+ loff_t *ppos = &iocb->ki_pos;
+ struct file *filp = iocb->ki_filp;
struct inode *inode = file_inode(filp);
struct address_space *mapping = inode->i_mapping;
pgoff_t index;
unsigned long offset;
enum sgp_type sgp = SGP_READ;
+ desc.written = 0;
+ desc.count = iov_iter_count(iter);
+ desc.arg.data = iter;
+ desc.error = 0;
+
/*
* Might this read be for a stacking filesystem? Then when reading
* holes of a sparse file, we actually need to allocate those pages,
@@ -1498,10 +1507,10 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_
break;
}
- desc->error = shmem_getpage(inode, index, &page, sgp, NULL);
- if (desc->error) {
- if (desc->error == -EINVAL)
- desc->error = 0;
+ desc.error = shmem_getpage(inode, index, &page, sgp, NULL);
+ if (desc.error) {
+ if (desc.error == -EINVAL)
+ desc.error = 0;
break;
}
if (page)
@@ -1552,13 +1561,13 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_
* "pos" here (the actor routine has to update the user buffer
* pointers and the remaining count).
*/
- ret = actor(desc, page, offset, nr);
+ ret = file_read_iter_actor(&desc, page, offset, nr);
offset += ret;
index += offset >> PAGE_CACHE_SHIFT;
offset &= ~PAGE_CACHE_MASK;
page_cache_release(page);
- if (ret != nr || !desc->count)
+ if (ret != nr || !desc.count)
break;
cond_resched();
@@ -1566,40 +1575,8 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_
*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
file_accessed(filp);
-}
-
-static ssize_t shmem_file_aio_read(struct kiocb *iocb,
- const struct iovec *iov, unsigned long nr_segs, loff_t pos)
-{
- struct file *filp = iocb->ki_filp;
- ssize_t retval;
- unsigned long seg;
- size_t count;
- loff_t *ppos = &iocb->ki_pos;
- retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE);
- if (retval)
- return retval;
-
- for (seg = 0; seg < nr_segs; seg++) {
- read_descriptor_t desc;
-
- desc.written = 0;
- desc.arg.buf = iov[seg].iov_base;
- desc.count = iov[seg].iov_len;
- if (desc.count == 0)
- continue;
- desc.error = 0;
- do_shmem_file_read(filp, ppos, &desc, file_read_actor);
- retval += desc.written;
- if (desc.error) {
- retval = retval ?: desc.error;
- break;
- }
- if (desc.count > 0)
- break;
- }
- return retval;
+ return desc.written ? desc.written : desc.error;
}
static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
@@ -2724,8 +2701,8 @@ static const struct file_operations shmem_file_operations = {
.llseek = shmem_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
- .aio_read = shmem_file_aio_read,
- .aio_write = generic_file_aio_write,
+ .read_iter = shmem_file_read_iter,
+ .write_iter = generic_file_write_iter,
.fsync = noop_fsync,
.splice_read = shmem_file_splice_read,
.splice_write = generic_file_splice_write,
diff --git a/net/802/mrp.c b/net/802/mrp.c
index 1eb05d80b07b..3ed616215870 100644
--- a/net/802/mrp.c
+++ b/net/802/mrp.c
@@ -24,6 +24,11 @@
static unsigned int mrp_join_time __read_mostly = 200;
module_param(mrp_join_time, uint, 0644);
MODULE_PARM_DESC(mrp_join_time, "Join time in ms (default 200ms)");
+
+static unsigned int mrp_periodic_time __read_mostly = 1000;
+module_param(mrp_periodic_time, uint, 0644);
+MODULE_PARM_DESC(mrp_periodic_time, "Periodic time in ms (default 1s)");
+
MODULE_LICENSE("GPL");
static const u8
@@ -595,6 +600,24 @@ static void mrp_join_timer(unsigned long data)
mrp_join_timer_arm(app);
}
+static void mrp_periodic_timer_arm(struct mrp_applicant *app)
+{
+ mod_timer(&app->periodic_timer,
+ jiffies + msecs_to_jiffies(mrp_periodic_time));
+}
+
+static void mrp_periodic_timer(unsigned long data)
+{
+ struct mrp_applicant *app = (struct mrp_applicant *)data;
+
+ spin_lock(&app->lock);
+ mrp_mad_event(app, MRP_EVENT_PERIODIC);
+ mrp_pdu_queue(app);
+ spin_unlock(&app->lock);
+
+ mrp_periodic_timer_arm(app);
+}
+
static int mrp_pdu_parse_end_mark(struct sk_buff *skb, int *offset)
{
__be16 endmark;
@@ -845,6 +868,9 @@ int mrp_init_applicant(struct net_device *dev, struct mrp_application *appl)
rcu_assign_pointer(dev->mrp_port->applicants[appl->type], app);
setup_timer(&app->join_timer, mrp_join_timer, (unsigned long)app);
mrp_join_timer_arm(app);
+ setup_timer(&app->periodic_timer, mrp_periodic_timer,
+ (unsigned long)app);
+ mrp_periodic_timer_arm(app);
return 0;
err3:
@@ -870,6 +896,7 @@ void mrp_uninit_applicant(struct net_device *dev, struct mrp_application *appl)
* all pending messages before the applicant is gone.
*/
del_timer_sync(&app->join_timer);
+ del_timer_sync(&app->periodic_timer);
spin_lock_bh(&app->lock);
mrp_mad_event(app, MRP_EVENT_TX);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 61fc573f1142..b3d17d1c49c3 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -98,14 +98,14 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
vlan_gvrp_request_leave(dev);
vlan_group_set_device(grp, vlan->vlan_proto, vlan_id, NULL);
+
+ netdev_upper_dev_unlink(real_dev, dev);
/* Because unregister_netdevice_queue() makes sure at least one rcu
* grace period is respected before device freeing,
* we dont need to call synchronize_net() here.
*/
unregister_netdevice_queue(dev, head);
- netdev_upper_dev_unlink(real_dev, dev);
-
if (grp->nr_vlan_devs == 0) {
vlan_mvrp_uninit_applicant(real_dev);
vlan_gvrp_uninit_applicant(real_dev);
@@ -169,13 +169,13 @@ int register_vlan_dev(struct net_device *dev)
if (err < 0)
goto out_uninit_mvrp;
- err = netdev_upper_dev_link(real_dev, dev);
- if (err)
- goto out_uninit_mvrp;
-
err = register_netdevice(dev);
if (err < 0)
- goto out_upper_dev_unlink;
+ goto out_uninit_mvrp;
+
+ err = netdev_upper_dev_link(real_dev, dev);
+ if (err)
+ goto out_unregister_netdev;
/* Account for reference in struct vlan_dev_priv */
dev_hold(real_dev);
@@ -191,8 +191,8 @@ int register_vlan_dev(struct net_device *dev)
return 0;
-out_upper_dev_unlink:
- netdev_upper_dev_unlink(real_dev, dev);
+out_unregister_netdev:
+ unregister_netdevice(dev);
out_uninit_mvrp:
if (grp->nr_vlan_devs == 0)
vlan_mvrp_uninit_applicant(real_dev);
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 9096137c889c..e6e1278dca89 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -490,6 +490,7 @@ int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
}
EXPORT_SYMBOL(bt_sock_ioctl);
+/* This function expects the sk lock to be held when called */
int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
{
DECLARE_WAITQUEUE(wait, current);
@@ -525,6 +526,46 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
}
EXPORT_SYMBOL(bt_sock_wait_state);
+/* This function expects the sk lock to be held when called */
+int bt_sock_wait_ready(struct sock *sk, unsigned long flags)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ unsigned long timeo;
+ int err = 0;
+
+ BT_DBG("sk %p", sk);
+
+ timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
+
+ add_wait_queue(sk_sleep(sk), &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ while (test_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags)) {
+ if (!timeo) {
+ err = -EAGAIN;
+ break;
+ }
+
+ if (signal_pending(current)) {
+ err = sock_intr_errno(timeo);
+ break;
+ }
+
+ release_sock(sk);
+ timeo = schedule_timeout(timeo);
+ lock_sock(sk);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ err = sock_error(sk);
+ if (err)
+ break;
+ }
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(sk_sleep(sk), &wait);
+
+ return err;
+}
+EXPORT_SYMBOL(bt_sock_wait_ready);
+
#ifdef CONFIG_PROC_FS
struct bt_seq_state {
struct bt_sock_list *l;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index f0817121ec5e..d2380e0c7df0 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -518,6 +518,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
list_for_each_entry(d, &hci_dev_list, list) {
if (!test_bit(HCI_UP, &d->flags) ||
test_bit(HCI_RAW, &d->flags) ||
+ test_bit(HCI_USER_CHANNEL, &d->dev_flags) ||
d->dev_type != HCI_BREDR)
continue;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 634debab4d54..956e7aa19e93 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -607,6 +607,34 @@ static void hci_set_le_support(struct hci_request *req)
&cp);
}
+static void hci_set_event_mask_page_2(struct hci_request *req)
+{
+ struct hci_dev *hdev = req->hdev;
+ u8 events[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ /* If Connectionless Slave Broadcast master role is supported
+ * enable all necessary events for it.
+ */
+ if (hdev->features[2][0] & 0x01) {
+ events[1] |= 0x40; /* Triggered Clock Capture */
+ events[1] |= 0x80; /* Synchronization Train Complete */
+ events[2] |= 0x10; /* Slave Page Response Timeout */
+ events[2] |= 0x20; /* CSB Channel Map Change */
+ }
+
+ /* If Connectionless Slave Broadcast slave role is supported
+ * enable all necessary events for it.
+ */
+ if (hdev->features[2][0] & 0x02) {
+ events[2] |= 0x01; /* Synchronization Train Received */
+ events[2] |= 0x02; /* CSB Receive */
+ events[2] |= 0x04; /* CSB Timeout */
+ events[2] |= 0x08; /* Truncated Page Complete */
+ }
+
+ hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, sizeof(events), events);
+}
+
static void hci_init3_req(struct hci_request *req, unsigned long opt)
{
struct hci_dev *hdev = req->hdev;
@@ -648,6 +676,19 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
}
}
+static void hci_init4_req(struct hci_request *req, unsigned long opt)
+{
+ struct hci_dev *hdev = req->hdev;
+
+ /* Set event mask page 2 if the HCI command for it is supported */
+ if (hdev->commands[22] & 0x04)
+ hci_set_event_mask_page_2(req);
+
+ /* Check for Synchronization Train support */
+ if (hdev->features[2][0] & 0x04)
+ hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL);
+}
+
static int __hci_init(struct hci_dev *hdev)
{
int err;
@@ -667,7 +708,11 @@ static int __hci_init(struct hci_dev *hdev)
if (err < 0)
return err;
- return __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT);
+ err = __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT);
+ if (err < 0)
+ return err;
+
+ return __hci_req_sync(hdev, hci_init4_req, 0, HCI_INIT_TIMEOUT);
}
static void hci_scan_req(struct hci_request *req, unsigned long opt)
@@ -984,6 +1029,11 @@ int hci_inquiry(void __user *arg)
if (!hdev)
return -ENODEV;
+ if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+ err = -EBUSY;
+ goto done;
+ }
+
hci_dev_lock(hdev);
if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX ||
inquiry_cache_empty(hdev) || ir.flags & IREQ_CACHE_FLUSH) {
@@ -1146,7 +1196,11 @@ int hci_dev_open(__u16 dev)
goto done;
}
- if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) {
+ /* Check for rfkill but allow the HCI setup stage to proceed
+ * (which in itself doesn't cause any RF activity).
+ */
+ if (test_bit(HCI_RFKILLED, &hdev->dev_flags) &&
+ !test_bit(HCI_SETUP, &hdev->dev_flags)) {
ret = -ERFKILL;
goto done;
}
@@ -1177,7 +1231,8 @@ int hci_dev_open(__u16 dev)
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
set_bit(HCI_RAW, &hdev->flags);
- if (!test_bit(HCI_RAW, &hdev->flags))
+ if (!test_bit(HCI_RAW, &hdev->flags) &&
+ !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags))
ret = __hci_init(hdev);
}
@@ -1188,6 +1243,7 @@ int hci_dev_open(__u16 dev)
set_bit(HCI_UP, &hdev->flags);
hci_notify(hdev, HCI_DEV_UP);
if (!test_bit(HCI_SETUP, &hdev->dev_flags) &&
+ !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) &&
mgmt_valid_hdev(hdev)) {
hci_dev_lock(hdev);
mgmt_powered(hdev, 1);
@@ -1324,11 +1380,17 @@ int hci_dev_close(__u16 dev)
if (!hdev)
return -ENODEV;
+ if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+ err = -EBUSY;
+ goto done;
+ }
+
if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags))
cancel_delayed_work(&hdev->power_off);
err = hci_dev_do_close(hdev);
+done:
hci_dev_put(hdev);
return err;
}
@@ -1344,8 +1406,15 @@ int hci_dev_reset(__u16 dev)
hci_req_lock(hdev);
- if (!test_bit(HCI_UP, &hdev->flags))
+ if (!test_bit(HCI_UP, &hdev->flags)) {
+ ret = -ENETDOWN;
goto done;
+ }
+
+ if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+ ret = -EBUSY;
+ goto done;
+ }
/* Drop queues */
skb_queue_purge(&hdev->rx_q);
@@ -1380,10 +1449,15 @@ int hci_dev_reset_stat(__u16 dev)
if (!hdev)
return -ENODEV;
+ if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+ ret = -EBUSY;
+ goto done;
+ }
+
memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
+done:
hci_dev_put(hdev);
-
return ret;
}
@@ -1400,6 +1474,11 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
if (!hdev)
return -ENODEV;
+ if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+ err = -EBUSY;
+ goto done;
+ }
+
switch (cmd) {
case HCISETAUTH:
err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt,
@@ -1458,6 +1537,7 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
break;
}
+done:
hci_dev_put(hdev);
return err;
}
@@ -1566,10 +1646,16 @@ static int hci_rfkill_set_block(void *data, bool blocked)
BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked);
- if (!blocked)
- return 0;
+ if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags))
+ return -EBUSY;
- hci_dev_do_close(hdev);
+ if (blocked) {
+ set_bit(HCI_RFKILLED, &hdev->dev_flags);
+ if (!test_bit(HCI_SETUP, &hdev->dev_flags))
+ hci_dev_do_close(hdev);
+ } else {
+ clear_bit(HCI_RFKILLED, &hdev->dev_flags);
+}
return 0;
}
@@ -1591,9 +1677,13 @@ static void hci_power_on(struct work_struct *work)
return;
}
- if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
+ if (test_bit(HCI_RFKILLED, &hdev->dev_flags)) {
+ clear_bit(HCI_AUTO_OFF, &hdev->dev_flags);
+ hci_dev_do_close(hdev);
+ } else if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
HCI_AUTO_OFF_TIMEOUT);
+ }
if (test_and_clear_bit(HCI_SETUP, &hdev->dev_flags))
mgmt_index_added(hdev);
@@ -2209,6 +2299,9 @@ int hci_register_dev(struct hci_dev *hdev)
}
}
+ if (hdev->rfkill && rfkill_blocked(hdev->rfkill))
+ set_bit(HCI_RFKILLED, &hdev->dev_flags);
+
set_bit(HCI_SETUP, &hdev->dev_flags);
if (hdev->dev_type != HCI_AMP)
@@ -3258,15 +3351,13 @@ static void hci_tx_work(struct work_struct *work)
BT_DBG("%s acl %d sco %d le %d", hdev->name, hdev->acl_cnt,
hdev->sco_cnt, hdev->le_cnt);
- /* Schedule queues and send stuff to HCI driver */
-
- hci_sched_acl(hdev);
-
- hci_sched_sco(hdev);
-
- hci_sched_esco(hdev);
-
- hci_sched_le(hdev);
+ if (!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+ /* Schedule queues and send stuff to HCI driver */
+ hci_sched_acl(hdev);
+ hci_sched_sco(hdev);
+ hci_sched_esco(hdev);
+ hci_sched_le(hdev);
+ }
/* Send next queued raw (unknown type) packet */
while ((skb = skb_dequeue(&hdev->raw_q)))
@@ -3457,7 +3548,8 @@ static void hci_rx_work(struct work_struct *work)
hci_send_to_sock(hdev, skb);
}
- if (test_bit(HCI_RAW, &hdev->flags)) {
+ if (test_bit(HCI_RAW, &hdev->flags) ||
+ test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
kfree_skb(skb);
continue;
}
@@ -3512,7 +3604,7 @@ static void hci_cmd_work(struct work_struct *work)
kfree_skb(hdev->sent_cmd);
- hdev->sent_cmd = skb_clone(skb, GFP_ATOMIC);
+ hdev->sent_cmd = skb_clone(skb, GFP_KERNEL);
if (hdev->sent_cmd) {
atomic_dec(&hdev->cmd_cnt);
hci_send_frame(skb);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 94aab73f89d4..d171c04bddbd 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -994,20 +994,20 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev,
return;
if (!status) {
- if (sent->le)
+ if (sent->le) {
hdev->features[1][0] |= LMP_HOST_LE;
- else
+ set_bit(HCI_LE_ENABLED, &hdev->dev_flags);
+ } else {
hdev->features[1][0] &= ~LMP_HOST_LE;
+ clear_bit(HCI_LE_ENABLED, &hdev->dev_flags);
+ clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
+ }
if (sent->simul)
hdev->features[1][0] |= LMP_HOST_LE_BREDR;
else
hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
}
-
- if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
- !test_bit(HCI_INIT, &hdev->flags))
- mgmt_le_enable_complete(hdev, sent->le, status);
}
static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev,
@@ -3557,7 +3557,11 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
cp.handle = cpu_to_le16(conn->handle);
if (ltk->authenticated)
- conn->sec_level = BT_SECURITY_HIGH;
+ conn->pending_sec_level = BT_SECURITY_HIGH;
+ else
+ conn->pending_sec_level = BT_SECURITY_MEDIUM;
+
+ conn->enc_key_size = ltk->enc_size;
hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 9bd7d959e384..c09e97638065 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -66,6 +66,46 @@ static struct bt_sock_list hci_sk_list = {
.lock = __RW_LOCK_UNLOCKED(hci_sk_list.lock)
};
+static bool is_filtered_packet(struct sock *sk, struct sk_buff *skb)
+{
+ struct hci_filter *flt;
+ int flt_type, flt_event;
+
+ /* Apply filter */
+ flt = &hci_pi(sk)->filter;
+
+ if (bt_cb(skb)->pkt_type == HCI_VENDOR_PKT)
+ flt_type = 0;
+ else
+ flt_type = bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS;
+
+ if (!test_bit(flt_type, &flt->type_mask))
+ return true;
+
+ /* Extra filter for event packets only */
+ if (bt_cb(skb)->pkt_type != HCI_EVENT_PKT)
+ return false;
+
+ flt_event = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS);
+
+ if (!hci_test_bit(flt_event, &flt->event_mask))
+ return true;
+
+ /* Check filter only when opcode is set */
+ if (!flt->opcode)
+ return false;
+
+ if (flt_event == HCI_EV_CMD_COMPLETE &&
+ flt->opcode != get_unaligned((__le16 *)(skb->data + 3)))
+ return true;
+
+ if (flt_event == HCI_EV_CMD_STATUS &&
+ flt->opcode != get_unaligned((__le16 *)(skb->data + 4)))
+ return true;
+
+ return false;
+}
+
/* Send frame to RAW socket */
void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
{
@@ -77,7 +117,6 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
read_lock(&hci_sk_list.lock);
sk_for_each(sk, &hci_sk_list.head) {
- struct hci_filter *flt;
struct sk_buff *nskb;
if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev)
@@ -87,31 +126,19 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
if (skb->sk == sk)
continue;
- if (hci_pi(sk)->channel != HCI_CHANNEL_RAW)
- continue;
-
- /* Apply filter */
- flt = &hci_pi(sk)->filter;
-
- if (!test_bit((bt_cb(skb)->pkt_type == HCI_VENDOR_PKT) ?
- 0 : (bt_cb(skb)->pkt_type & HCI_FLT_TYPE_BITS),
- &flt->type_mask))
- continue;
-
- if (bt_cb(skb)->pkt_type == HCI_EVENT_PKT) {
- int evt = (*(__u8 *)skb->data & HCI_FLT_EVENT_BITS);
-
- if (!hci_test_bit(evt, &flt->event_mask))
+ if (hci_pi(sk)->channel == HCI_CHANNEL_RAW) {
+ if (is_filtered_packet(sk, skb))
continue;
-
- if (flt->opcode &&
- ((evt == HCI_EV_CMD_COMPLETE &&
- flt->opcode !=
- get_unaligned((__le16 *)(skb->data + 3))) ||
- (evt == HCI_EV_CMD_STATUS &&
- flt->opcode !=
- get_unaligned((__le16 *)(skb->data + 4)))))
+ } else if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
+ if (!bt_cb(skb)->incoming)
+ continue;
+ if (bt_cb(skb)->pkt_type != HCI_EVENT_PKT &&
+ bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
+ bt_cb(skb)->pkt_type != HCI_SCODATA_PKT)
continue;
+ } else {
+ /* Don't send frame to other channel types */
+ continue;
}
if (!skb_copy) {
@@ -426,6 +453,12 @@ static int hci_sock_release(struct socket *sock)
bt_sock_unlink(&hci_sk_list, sk);
if (hdev) {
+ if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
+ mgmt_index_added(hdev);
+ clear_bit(HCI_USER_CHANNEL, &hdev->dev_flags);
+ hci_dev_close(hdev->id);
+ }
+
atomic_dec(&hdev->promisc);
hci_dev_put(hdev);
}
@@ -482,6 +515,9 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
if (!hdev)
return -EBADFD;
+ if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags))
+ return -EBUSY;
+
switch (cmd) {
case HCISETRAW:
if (!capable(CAP_NET_ADMIN))
@@ -512,23 +548,32 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
if (!capable(CAP_NET_ADMIN))
return -EPERM;
return hci_sock_blacklist_del(hdev, (void __user *) arg);
-
- default:
- if (hdev->ioctl)
- return hdev->ioctl(hdev, cmd, arg);
- return -EINVAL;
}
+
+ if (hdev->ioctl)
+ return hdev->ioctl(hdev, cmd, arg);
+
+ return -EINVAL;
}
static int hci_sock_ioctl(struct socket *sock, unsigned int cmd,
unsigned long arg)
{
- struct sock *sk = sock->sk;
void __user *argp = (void __user *) arg;
+ struct sock *sk = sock->sk;
int err;
BT_DBG("cmd %x arg %lx", cmd, arg);
+ lock_sock(sk);
+
+ if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
+ err = -EBADFD;
+ goto done;
+ }
+
+ release_sock(sk);
+
switch (cmd) {
case HCIGETDEVLIST:
return hci_get_dev_list(argp);
@@ -573,13 +618,15 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd,
case HCIINQUIRY:
return hci_inquiry(argp);
-
- default:
- lock_sock(sk);
- err = hci_sock_bound_ioctl(sk, cmd, arg);
- release_sock(sk);
- return err;
}
+
+ lock_sock(sk);
+
+ err = hci_sock_bound_ioctl(sk, cmd, arg);
+
+done:
+ release_sock(sk);
+ return err;
}
static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
@@ -629,6 +676,56 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr,
hci_pi(sk)->hdev = hdev;
break;
+ case HCI_CHANNEL_USER:
+ if (hci_pi(sk)->hdev) {
+ err = -EALREADY;
+ goto done;
+ }
+
+ if (haddr.hci_dev == HCI_DEV_NONE) {
+ err = -EINVAL;
+ goto done;
+ }
+
+ if (!capable(CAP_NET_RAW)) {
+ err = -EPERM;
+ goto done;
+ }
+
+ hdev = hci_dev_get(haddr.hci_dev);
+ if (!hdev) {
+ err = -ENODEV;
+ goto done;
+ }
+
+ if (test_bit(HCI_UP, &hdev->flags) ||
+ test_bit(HCI_INIT, &hdev->flags) ||
+ test_bit(HCI_SETUP, &hdev->dev_flags)) {
+ err = -EBUSY;
+ hci_dev_put(hdev);
+ goto done;
+ }
+
+ if (test_and_set_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+ err = -EUSERS;
+ hci_dev_put(hdev);
+ goto done;
+ }
+
+ mgmt_index_removed(hdev);
+
+ err = hci_dev_open(hdev->id);
+ if (err) {
+ clear_bit(HCI_USER_CHANNEL, &hdev->dev_flags);
+ hci_dev_put(hdev);
+ goto done;
+ }
+
+ atomic_inc(&hdev->promisc);
+
+ hci_pi(sk)->hdev = hdev;
+ break;
+
case HCI_CHANNEL_CONTROL:
if (haddr.hci_dev != HCI_DEV_NONE) {
err = -EINVAL;
@@ -677,22 +774,30 @@ static int hci_sock_getname(struct socket *sock, struct sockaddr *addr,
{
struct sockaddr_hci *haddr = (struct sockaddr_hci *) addr;
struct sock *sk = sock->sk;
- struct hci_dev *hdev = hci_pi(sk)->hdev;
+ struct hci_dev *hdev;
+ int err = 0;
BT_DBG("sock %p sk %p", sock, sk);
- if (!hdev)
- return -EBADFD;
+ if (peer)
+ return -EOPNOTSUPP;
lock_sock(sk);
+ hdev = hci_pi(sk)->hdev;
+ if (!hdev) {
+ err = -EBADFD;
+ goto done;
+ }
+
*addr_len = sizeof(*haddr);
haddr->hci_family = AF_BLUETOOTH;
haddr->hci_dev = hdev->id;
- haddr->hci_channel= 0;
+ haddr->hci_channel= hci_pi(sk)->channel;
+done:
release_sock(sk);
- return 0;
+ return err;
}
static void hci_sock_cmsg(struct sock *sk, struct msghdr *msg,
@@ -767,6 +872,7 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
case HCI_CHANNEL_RAW:
hci_sock_cmsg(sk, msg, skb);
break;
+ case HCI_CHANNEL_USER:
case HCI_CHANNEL_CONTROL:
case HCI_CHANNEL_MONITOR:
sock_recv_timestamp(msg, sk, skb);
@@ -801,6 +907,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
switch (hci_pi(sk)->channel) {
case HCI_CHANNEL_RAW:
+ case HCI_CHANNEL_USER:
break;
case HCI_CHANNEL_CONTROL:
err = mgmt_control(sk, msg, len);
@@ -837,7 +944,8 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
skb_pull(skb, 1);
skb->dev = (void *) hdev;
- if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
+ if (hci_pi(sk)->channel == HCI_CHANNEL_RAW &&
+ bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
u16 opcode = get_unaligned_le16(skb->data);
u16 ogf = hci_opcode_ogf(opcode);
u16 ocf = hci_opcode_ocf(opcode);
@@ -868,6 +976,14 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
goto drop;
}
+ if (hci_pi(sk)->channel == HCI_CHANNEL_USER &&
+ bt_cb(skb)->pkt_type != HCI_COMMAND_PKT &&
+ bt_cb(skb)->pkt_type != HCI_ACLDATA_PKT &&
+ bt_cb(skb)->pkt_type != HCI_SCODATA_PKT) {
+ err = -EINVAL;
+ goto drop;
+ }
+
skb_queue_tail(&hdev->raw_q, skb);
queue_work(hdev->workqueue, &hdev->tx_work);
}
@@ -895,7 +1011,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
lock_sock(sk);
if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
- err = -EINVAL;
+ err = -EBADFD;
goto done;
}
@@ -981,7 +1097,7 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname,
lock_sock(sk);
if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
- err = -EINVAL;
+ err = -EBADFD;
goto done;
}
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index b3bb7bca8e60..d1f1e78d1140 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3755,6 +3755,13 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
sk = chan->sk;
+ /* For certain devices (ex: HID mouse), support for authentication,
+ * pairing and bonding is optional. For such devices, inorder to avoid
+ * the ACL alive for too long after L2CAP disconnection, reset the ACL
+ * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect.
+ */
+ conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
+
bacpy(&bt_sk(sk)->src, conn->src);
bacpy(&bt_sk(sk)->dst, conn->dst);
chan->psm = psm;
@@ -3884,13 +3891,13 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
if (scid) {
chan = __l2cap_get_chan_by_scid(conn, scid);
if (!chan) {
- err = -EFAULT;
+ err = -EBADSLT;
goto unlock;
}
} else {
chan = __l2cap_get_chan_by_ident(conn, cmd->ident);
if (!chan) {
- err = -EFAULT;
+ err = -EBADSLT;
goto unlock;
}
}
@@ -3978,7 +3985,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
chan = l2cap_get_chan_by_scid(conn, dcid);
if (!chan)
- return -ENOENT;
+ return -EBADSLT;
if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
struct l2cap_cmd_rej_cid rej;
@@ -4206,7 +4213,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
chan = __l2cap_get_chan_by_scid(conn, dcid);
if (!chan) {
mutex_unlock(&conn->chan_lock);
- return 0;
+ return -EBADSLT;
}
l2cap_chan_lock(chan);
@@ -4438,7 +4445,7 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn,
hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, conn->dst);
if (!hs_hcon) {
hci_dev_put(hdev);
- return -EFAULT;
+ return -EBADSLT;
}
BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon);
@@ -4462,7 +4469,7 @@ error:
l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
sizeof(rsp), &rsp);
- return -EFAULT;
+ return 0;
}
static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id)
@@ -5212,7 +5219,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
case L2CAP_CONN_RSP:
case L2CAP_CREATE_CHAN_RSP:
- err = l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
+ l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
break;
case L2CAP_CONF_REQ:
@@ -5220,7 +5227,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
break;
case L2CAP_CONF_RSP:
- err = l2cap_config_rsp(conn, cmd, cmd_len, data);
+ l2cap_config_rsp(conn, cmd, cmd_len, data);
break;
case L2CAP_DISCONN_REQ:
@@ -5228,7 +5235,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
break;
case L2CAP_DISCONN_RSP:
- err = l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
+ l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
break;
case L2CAP_ECHO_REQ:
@@ -5243,7 +5250,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
break;
case L2CAP_INFO_RSP:
- err = l2cap_information_rsp(conn, cmd, cmd_len, data);
+ l2cap_information_rsp(conn, cmd, cmd_len, data);
break;
case L2CAP_CREATE_CHAN_REQ:
@@ -5255,7 +5262,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
break;
case L2CAP_MOVE_CHAN_RSP:
- err = l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
+ l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
break;
case L2CAP_MOVE_CHAN_CFM:
@@ -5263,7 +5270,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
break;
case L2CAP_MOVE_CHAN_CFM_RSP:
- err = l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
+ l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
break;
default:
@@ -5294,9 +5301,24 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
}
}
+static __le16 l2cap_err_to_reason(int err)
+{
+ switch (err) {
+ case -EBADSLT:
+ return __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
+ case -EMSGSIZE:
+ return __constant_cpu_to_le16(L2CAP_REJ_MTU_EXCEEDED);
+ case -EINVAL:
+ case -EPROTO:
+ default:
+ return __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
+ }
+}
+
static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
struct sk_buff *skb)
{
+ struct hci_conn *hcon = conn->hcon;
u8 *data = skb->data;
int len = skb->len;
struct l2cap_cmd_hdr cmd;
@@ -5304,6 +5326,9 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
l2cap_raw_recv(conn, skb);
+ if (hcon->type != LE_LINK)
+ return;
+
while (len >= L2CAP_CMD_HDR_SIZE) {
u16 cmd_len;
memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
@@ -5326,8 +5351,7 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
BT_ERR("Wrong link type (%d)", err);
- /* FIXME: Map err to a valid reason */
- rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
+ rej.reason = l2cap_err_to_reason(err);
l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
sizeof(rej), &rej);
}
@@ -5342,6 +5366,7 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
static inline void l2cap_sig_channel(struct l2cap_conn *conn,
struct sk_buff *skb)
{
+ struct hci_conn *hcon = conn->hcon;
u8 *data = skb->data;
int len = skb->len;
struct l2cap_cmd_hdr cmd;
@@ -5349,6 +5374,9 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
l2cap_raw_recv(conn, skb);
+ if (hcon->type != ACL_LINK)
+ return;
+
while (len >= L2CAP_CMD_HDR_SIZE) {
u16 cmd_len;
memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
@@ -5371,8 +5399,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
BT_ERR("Wrong link type (%d)", err);
- /* FIXME: Map err to a valid reason */
- rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
+ rej.reason = l2cap_err_to_reason(err);
l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
sizeof(rej), &rej);
}
@@ -5777,7 +5804,7 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan,
struct sk_buff *skb, u8 event)
{
int err = 0;
- bool skb_in_use = 0;
+ bool skb_in_use = false;
BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
event);
@@ -5798,7 +5825,7 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan,
control->txseq);
chan->buffer_seq = chan->expected_tx_seq;
- skb_in_use = 1;
+ skb_in_use = true;
err = l2cap_reassemble_sdu(chan, skb, control);
if (err)
@@ -5834,7 +5861,7 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan,
* current frame is stored for later use.
*/
skb_queue_tail(&chan->srej_q, skb);
- skb_in_use = 1;
+ skb_in_use = true;
BT_DBG("Queued %p (queue len %d)", skb,
skb_queue_len(&chan->srej_q));
@@ -5912,7 +5939,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
{
int err = 0;
u16 txseq = control->txseq;
- bool skb_in_use = 0;
+ bool skb_in_use = false;
BT_DBG("chan %p, control %p, skb %p, event %d", chan, control, skb,
event);
@@ -5924,7 +5951,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
/* Keep frame for reassembly later */
l2cap_pass_to_tx(chan, control);
skb_queue_tail(&chan->srej_q, skb);
- skb_in_use = 1;
+ skb_in_use = true;
BT_DBG("Queued %p (queue len %d)", skb,
skb_queue_len(&chan->srej_q));
@@ -5935,7 +5962,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
l2cap_pass_to_tx(chan, control);
skb_queue_tail(&chan->srej_q, skb);
- skb_in_use = 1;
+ skb_in_use = true;
BT_DBG("Queued %p (queue len %d)", skb,
skb_queue_len(&chan->srej_q));
@@ -5950,7 +5977,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
* the missing frames.
*/
skb_queue_tail(&chan->srej_q, skb);
- skb_in_use = 1;
+ skb_in_use = true;
BT_DBG("Queued %p (queue len %d)", skb,
skb_queue_len(&chan->srej_q));
@@ -5964,7 +5991,7 @@ static int l2cap_rx_state_srej_sent(struct l2cap_chan *chan,
* SREJ'd frames.
*/
skb_queue_tail(&chan->srej_q, skb);
- skb_in_use = 1;
+ skb_in_use = true;
BT_DBG("Queued %p (queue len %d)", skb,
skb_queue_len(&chan->srej_q));
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 0098af80b213..c85537ca1a23 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -777,6 +777,12 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
if (sk->sk_state != BT_CONNECTED)
return -ENOTCONN;
+ lock_sock(sk);
+ err = bt_sock_wait_ready(sk, msg->msg_flags);
+ release_sock(sk);
+ if (err)
+ return err;
+
l2cap_chan_lock(chan);
err = l2cap_chan_send(chan, msg, len, sk->sk_priority);
l2cap_chan_unlock(chan);
@@ -799,8 +805,8 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
pi->chan->state = BT_CONFIG;
__l2cap_connect_rsp_defer(pi->chan);
- release_sock(sk);
- return 0;
+ err = 0;
+ goto done;
}
release_sock(sk);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index fedc5399d465..1b5b10fab545 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -76,6 +76,7 @@ static const u16 mgmt_commands[] = {
MGMT_OP_BLOCK_DEVICE,
MGMT_OP_UNBLOCK_DEVICE,
MGMT_OP_SET_DEVICE_ID,
+ MGMT_OP_SET_ADVERTISING,
};
static const u16 mgmt_events[] = {
@@ -339,6 +340,9 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
if (test_bit(HCI_SETUP, &d->dev_flags))
continue;
+ if (test_bit(HCI_USER_CHANNEL, &d->dev_flags))
+ continue;
+
if (!mgmt_valid_hdev(d))
continue;
@@ -381,8 +385,10 @@ static u32 get_supported_settings(struct hci_dev *hdev)
if (enable_hs)
settings |= MGMT_SETTING_HS;
- if (lmp_le_capable(hdev))
+ if (lmp_le_capable(hdev)) {
settings |= MGMT_SETTING_LE;
+ settings |= MGMT_SETTING_ADVERTISING;
+ }
return settings;
}
@@ -421,6 +427,9 @@ static u32 get_current_settings(struct hci_dev *hdev)
if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
settings |= MGMT_SETTING_HS;
+ if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags))
+ settings |= MGMT_SETTING_ADVERTISING;
+
return settings;
}
@@ -804,6 +813,12 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
hci_dev_lock(hdev);
+ if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
+ err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
+ MGMT_STATUS_BUSY);
+ goto failed;
+ }
+
if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
cancel_delayed_work(&hdev->power_off);
@@ -820,12 +835,6 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
goto failed;
}
- if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
- err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
- MGMT_STATUS_BUSY);
- goto failed;
- }
-
cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
@@ -883,6 +892,36 @@ static int new_settings(struct hci_dev *hdev, struct sock *skip)
return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
}
+struct cmd_lookup {
+ struct sock *sk;
+ struct hci_dev *hdev;
+ u8 mgmt_status;
+};
+
+static void settings_rsp(struct pending_cmd *cmd, void *data)
+{
+ struct cmd_lookup *match = data;
+
+ send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
+
+ list_del(&cmd->list);
+
+ if (match->sk == NULL) {
+ match->sk = cmd->sk;
+ sock_hold(match->sk);
+ }
+
+ mgmt_pending_free(cmd);
+}
+
+static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
+{
+ u8 *status = data;
+
+ cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
+ mgmt_pending_remove(cmd);
+}
+
static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
@@ -1321,11 +1360,32 @@ static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
return send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
}
+static void le_enable_complete(struct hci_dev *hdev, u8 status)
+{
+ struct cmd_lookup match = { NULL, hdev };
+
+ if (status) {
+ u8 mgmt_err = mgmt_status(status);
+
+ mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
+ &mgmt_err);
+ return;
+ }
+
+ mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
+
+ new_settings(hdev, match.sk);
+
+ if (match.sk)
+ sock_put(match.sk);
+}
+
static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
{
struct mgmt_mode *cp = data;
struct hci_cp_write_le_host_supported hci_cp;
struct pending_cmd *cmd;
+ struct hci_request req;
int err;
u8 val, enabled;
@@ -1357,6 +1417,11 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
changed = true;
}
+ if (!val && test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) {
+ clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
+ changed = true;
+ }
+
err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
if (err < 0)
goto unlock;
@@ -1367,7 +1432,8 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
goto unlock;
}
- if (mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
+ if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
+ mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
MGMT_STATUS_BUSY);
goto unlock;
@@ -1386,8 +1452,15 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
hci_cp.simul = lmp_le_br_capable(hdev);
}
- err = hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
- &hci_cp);
+ hci_req_init(&req, hdev);
+
+ if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags) && !val)
+ hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(val), &val);
+
+ hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
+ &hci_cp);
+
+ err = hci_req_run(&req, le_enable_complete);
if (err < 0)
mgmt_pending_remove(cmd);
@@ -3065,6 +3138,98 @@ static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
return err;
}
+static void set_advertising_complete(struct hci_dev *hdev, u8 status)
+{
+ struct cmd_lookup match = { NULL, hdev };
+
+ if (status) {
+ u8 mgmt_err = mgmt_status(status);
+
+ mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
+ cmd_status_rsp, &mgmt_err);
+ return;
+ }
+
+ mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
+ &match);
+
+ new_settings(hdev, match.sk);
+
+ if (match.sk)
+ sock_put(match.sk);
+}
+
+static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
+{
+ struct mgmt_mode *cp = data;
+ struct pending_cmd *cmd;
+ struct hci_request req;
+ u8 val, enabled;
+ int err;
+
+ BT_DBG("request for %s", hdev->name);
+
+ if (!lmp_le_capable(hdev))
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
+ MGMT_STATUS_NOT_SUPPORTED);
+
+ if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
+ MGMT_STATUS_REJECTED);
+
+ if (cp->val != 0x00 && cp->val != 0x01)
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
+ MGMT_STATUS_INVALID_PARAMS);
+
+ hci_dev_lock(hdev);
+
+ val = !!cp->val;
+ enabled = test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
+
+ if (!hdev_is_powered(hdev) || val == enabled) {
+ bool changed = false;
+
+ if (val != test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) {
+ change_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags);
+ changed = true;
+ }
+
+ err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
+ if (err < 0)
+ goto unlock;
+
+ if (changed)
+ err = new_settings(hdev, sk);
+
+ goto unlock;
+ }
+
+ if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
+ mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
+ err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
+ MGMT_STATUS_BUSY);
+ goto unlock;
+ }
+
+ cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
+ if (!cmd) {
+ err = -ENOMEM;
+ goto unlock;
+ }
+
+ hci_req_init(&req, hdev);
+
+ hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(val), &val);
+
+ err = hci_req_run(&req, set_advertising_complete);
+ if (err < 0)
+ mgmt_pending_remove(cmd);
+
+unlock:
+ hci_dev_unlock(hdev);
+ return err;
+}
+
static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
{
struct pending_cmd *cmd;
@@ -3276,6 +3441,7 @@ static const struct mgmt_handler {
{ block_device, false, MGMT_BLOCK_DEVICE_SIZE },
{ unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
{ set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
+ { set_advertising, false, MGMT_SETTING_SIZE },
};
@@ -3320,6 +3486,12 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
MGMT_STATUS_INVALID_INDEX);
goto done;
}
+
+ if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+ err = cmd_status(sk, index, opcode,
+ MGMT_STATUS_INVALID_INDEX);
+ goto done;
+ }
}
if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
@@ -3365,14 +3537,6 @@ done:
return err;
}
-static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
-{
- u8 *status = data;
-
- cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
- mgmt_pending_remove(cmd);
-}
-
int mgmt_index_added(struct hci_dev *hdev)
{
if (!mgmt_valid_hdev(hdev))
@@ -3393,28 +3557,6 @@ int mgmt_index_removed(struct hci_dev *hdev)
return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
}
-struct cmd_lookup {
- struct sock *sk;
- struct hci_dev *hdev;
- u8 mgmt_status;
-};
-
-static void settings_rsp(struct pending_cmd *cmd, void *data)
-{
- struct cmd_lookup *match = data;
-
- send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
-
- list_del(&cmd->list);
-
- if (match->sk == NULL) {
- match->sk = cmd->sk;
- sock_hold(match->sk);
- }
-
- mgmt_pending_free(cmd);
-}
-
static void set_bredr_scan(struct hci_request *req)
{
struct hci_dev *hdev = req->hdev;
@@ -3483,6 +3625,12 @@ static int powered_update_hci(struct hci_dev *hdev)
sizeof(cp), &cp);
}
+ if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) {
+ u8 adv = 0x01;
+
+ hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(adv), &adv);
+ }
+
link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
@@ -4132,44 +4280,6 @@ int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
return err;
}
-int mgmt_le_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
-{
- struct cmd_lookup match = { NULL, hdev };
- bool changed = false;
- int err = 0;
-
- if (status) {
- u8 mgmt_err = mgmt_status(status);
-
- if (enable && test_and_clear_bit(HCI_LE_ENABLED,
- &hdev->dev_flags))
- err = new_settings(hdev, NULL);
-
- mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
- &mgmt_err);
-
- return err;
- }
-
- if (enable) {
- if (!test_and_set_bit(HCI_LE_ENABLED, &hdev->dev_flags))
- changed = true;
- } else {
- if (test_and_clear_bit(HCI_LE_ENABLED, &hdev->dev_flags))
- changed = true;
- }
-
- mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
-
- if (changed)
- err = new_settings(hdev, match.sk);
-
- if (match.sk)
- sock_put(match.sk);
-
- return err;
-}
-
int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8
ssp, u8 *eir, u16 eir_len)
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 30b3721dc6d7..072938dc527d 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -544,7 +544,7 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
struct sock *sk = sock->sk;
struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
struct sk_buff *skb;
- int sent = 0;
+ int sent;
if (test_bit(RFCOMM_DEFER_SETUP, &d->flags))
return -ENOTCONN;
@@ -559,6 +559,10 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
lock_sock(sk);
+ sent = bt_sock_wait_ready(sk, msg->msg_flags);
+ if (sent)
+ goto done;
+
while (len) {
size_t size = min_t(size_t, len, d->mtu);
int err;
@@ -594,6 +598,7 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
len -= size;
}
+done:
release_sock(sk);
return sent;
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 6d126faf145f..84fcf9fff3ea 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -569,7 +569,6 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
{
struct rfcomm_dev *dev = dlc->owner;
- struct tty_struct *tty;
if (!dev)
return;
@@ -581,38 +580,8 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
DPM_ORDER_DEV_AFTER_PARENT);
wake_up_interruptible(&dev->port.open_wait);
- } else if (dlc->state == BT_CLOSED) {
- tty = tty_port_tty_get(&dev->port);
- if (!tty) {
- if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
- /* Drop DLC lock here to avoid deadlock
- * 1. rfcomm_dev_get will take rfcomm_dev_lock
- * but in rfcomm_dev_add there's lock order:
- * rfcomm_dev_lock -> dlc lock
- * 2. tty_port_put will deadlock if it's
- * the last reference
- *
- * FIXME: when we release the lock anything
- * could happen to dev, even its destruction
- */
- rfcomm_dlc_unlock(dlc);
- if (rfcomm_dev_get(dev->id) == NULL) {
- rfcomm_dlc_lock(dlc);
- return;
- }
-
- if (!test_and_set_bit(RFCOMM_TTY_RELEASED,
- &dev->flags))
- tty_port_put(&dev->port);
-
- tty_port_put(&dev->port);
- rfcomm_dlc_lock(dlc);
- }
- } else {
- tty_hangup(tty);
- tty_kref_put(tty);
- }
- }
+ } else if (dlc->state == BT_CLOSED)
+ tty_port_tty_hangup(&dev->port, false);
}
static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig)
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index 85a09bb5ca51..3184c8812b49 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -447,7 +447,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry)
if (p->port->state == BR_STATE_DISABLED)
goto unlock;
- rcu_assign_pointer(*pp, p->next);
+ rcu_assign_pointer(*pp, rcu_access_pointer(p->next));
hlist_del_init(&p->mglist);
del_timer(&p->timer);
call_rcu_bh(&p->rcu, br_multicast_free_pg);
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index d1c578630678..314c81cc5855 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -267,7 +267,7 @@ static void br_multicast_del_pg(struct net_bridge *br,
if (p != pg)
continue;
- rcu_assign_pointer(*pp, p->next);
+ rcu_assign_pointer(*pp, rcu_access_pointer(p->next));
hlist_del_init(&p->mglist);
del_timer(&p->timer);
call_rcu_bh(&p->rcu, br_multicast_free_pg);
@@ -646,7 +646,7 @@ struct net_bridge_port_group *br_multicast_new_port_group(
p->addr = *group;
p->port = port;
p->state = state;
- rcu_assign_pointer(p->next, next);
+ rcu_assign_pointer(p->next, rcu_access_pointer(next));
hlist_add_head(&p->mglist, &port->mglist);
setup_timer(&p->timer, br_multicast_port_group_expired,
(unsigned long)p);
diff --git a/net/core/dev.c b/net/core/dev.c
index 5c713f2239cc..25ab6fe80da2 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4373,42 +4373,40 @@ struct netdev_adjacent {
/* upper master flag, there can only be one master device per list */
bool master;
- /* indicates that this dev is our first-level lower/upper device */
- bool neighbour;
-
/* counter for the number of times this device was added to us */
u16 ref_nr;
+ /* private field for the users */
+ void *private;
+
struct list_head list;
struct rcu_head rcu;
};
-static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev,
- struct net_device *adj_dev,
- bool upper)
+static struct netdev_adjacent *__netdev_find_adj_rcu(struct net_device *dev,
+ struct net_device *adj_dev,
+ struct list_head *adj_list)
{
struct netdev_adjacent *adj;
- struct list_head *dev_list;
- dev_list = upper ? &dev->upper_dev_list : &dev->lower_dev_list;
-
- list_for_each_entry(adj, dev_list, list) {
+ list_for_each_entry_rcu(adj, adj_list, list) {
if (adj->dev == adj_dev)
return adj;
}
return NULL;
}
-static inline struct netdev_adjacent *__netdev_find_upper(struct net_device *dev,
- struct net_device *udev)
+static struct netdev_adjacent *__netdev_find_adj(struct net_device *dev,
+ struct net_device *adj_dev,
+ struct list_head *adj_list)
{
- return __netdev_find_adj(dev, udev, true);
-}
+ struct netdev_adjacent *adj;
-static inline struct netdev_adjacent *__netdev_find_lower(struct net_device *dev,
- struct net_device *ldev)
-{
- return __netdev_find_adj(dev, ldev, false);
+ list_for_each_entry(adj, adj_list, list) {
+ if (adj->dev == adj_dev)
+ return adj;
+ }
+ return NULL;
}
/**
@@ -4425,7 +4423,7 @@ bool netdev_has_upper_dev(struct net_device *dev,
{
ASSERT_RTNL();
- return __netdev_find_upper(dev, upper_dev);
+ return __netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper);
}
EXPORT_SYMBOL(netdev_has_upper_dev);
@@ -4440,7 +4438,7 @@ bool netdev_has_any_upper_dev(struct net_device *dev)
{
ASSERT_RTNL();
- return !list_empty(&dev->upper_dev_list);
+ return !list_empty(&dev->all_adj_list.upper);
}
EXPORT_SYMBOL(netdev_has_any_upper_dev);
@@ -4457,10 +4455,10 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
ASSERT_RTNL();
- if (list_empty(&dev->upper_dev_list))
+ if (list_empty(&dev->adj_list.upper))
return NULL;
- upper = list_first_entry(&dev->upper_dev_list,
+ upper = list_first_entry(&dev->adj_list.upper,
struct netdev_adjacent, list);
if (likely(upper->master))
return upper->dev;
@@ -4468,15 +4466,26 @@ struct net_device *netdev_master_upper_dev_get(struct net_device *dev)
}
EXPORT_SYMBOL(netdev_master_upper_dev_get);
-/* netdev_upper_get_next_dev_rcu - Get the next dev from upper list
+void *netdev_adjacent_get_private(struct list_head *adj_list)
+{
+ struct netdev_adjacent *adj;
+
+ adj = list_entry(adj_list, struct netdev_adjacent, list);
+
+ return adj->private;
+}
+EXPORT_SYMBOL(netdev_adjacent_get_private);
+
+/**
+ * netdev_all_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 net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
+ struct list_head **iter)
{
struct netdev_adjacent *upper;
@@ -4484,14 +4493,71 @@ struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
- if (&upper->list == &dev->upper_dev_list)
+ if (&upper->list == &dev->all_adj_list.upper)
return NULL;
*iter = &upper->list;
return upper->dev;
}
-EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu);
+EXPORT_SYMBOL(netdev_all_upper_get_next_dev_rcu);
+
+/**
+ * netdev_lower_get_next_private - Get the next ->private from the
+ * lower neighbour list
+ * @dev: device
+ * @iter: list_head ** of the current position
+ *
+ * Gets the next netdev_adjacent->private from the dev's lower neighbour
+ * list, starting from iter position. The caller must hold either hold the
+ * RTNL lock or its own locking that guarantees that the neighbour lower
+ * list will remain unchainged.
+ */
+void *netdev_lower_get_next_private(struct net_device *dev,
+ struct list_head **iter)
+{
+ struct netdev_adjacent *lower;
+
+ lower = list_entry(*iter, struct netdev_adjacent, list);
+
+ if (&lower->list == &dev->adj_list.lower)
+ return NULL;
+
+ if (iter)
+ *iter = lower->list.next;
+
+ return lower->private;
+}
+EXPORT_SYMBOL(netdev_lower_get_next_private);
+
+/**
+ * netdev_lower_get_next_private_rcu - Get the next ->private from the
+ * lower neighbour list, RCU
+ * variant
+ * @dev: device
+ * @iter: list_head ** of the current position
+ *
+ * Gets the next netdev_adjacent->private from the dev's lower neighbour
+ * list, starting from iter position. The caller must hold RCU read lock.
+ */
+void *netdev_lower_get_next_private_rcu(struct net_device *dev,
+ struct list_head **iter)
+{
+ struct netdev_adjacent *lower;
+
+ WARN_ON_ONCE(!rcu_read_lock_held());
+
+ lower = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
+
+ if (&lower->list == &dev->adj_list.lower)
+ return NULL;
+
+ if (iter)
+ *iter = &lower->list;
+
+ return lower->private;
+}
+EXPORT_SYMBOL(netdev_lower_get_next_private_rcu);
/**
* netdev_master_upper_dev_get_rcu - Get master upper device
@@ -4504,7 +4570,7 @@ struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev)
{
struct netdev_adjacent *upper;
- upper = list_first_or_null_rcu(&dev->upper_dev_list,
+ upper = list_first_or_null_rcu(&dev->adj_list.upper,
struct netdev_adjacent, list);
if (upper && likely(upper->master))
return upper->dev;
@@ -4514,15 +4580,16 @@ EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu);
static int __netdev_adjacent_dev_insert(struct net_device *dev,
struct net_device *adj_dev,
- bool neighbour, bool master,
- bool upper)
+ struct list_head *dev_list,
+ void *private, bool master)
{
struct netdev_adjacent *adj;
+ char linkname[IFNAMSIZ+7];
+ int ret;
- adj = __netdev_find_adj(dev, adj_dev, upper);
+ adj = __netdev_find_adj(dev, adj_dev, dev_list);
if (adj) {
- BUG_ON(neighbour);
adj->ref_nr++;
return 0;
}
@@ -4533,124 +4600,178 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
adj->dev = adj_dev;
adj->master = master;
- adj->neighbour = neighbour;
adj->ref_nr = 1;
-
+ adj->private = private;
dev_hold(adj_dev);
- pr_debug("dev_hold for %s, because of %s link added from %s to %s\n",
- adj_dev->name, upper ? "upper" : "lower", dev->name,
- adj_dev->name);
- if (!upper) {
- list_add_tail_rcu(&adj->list, &dev->lower_dev_list);
- return 0;
+ pr_debug("dev_hold for %s, because of link added from %s to %s\n",
+ adj_dev->name, dev->name, adj_dev->name);
+
+ if (dev_list == &dev->adj_list.lower) {
+ sprintf(linkname, "lower_%s", adj_dev->name);
+ ret = sysfs_create_link(&(dev->dev.kobj),
+ &(adj_dev->dev.kobj), linkname);
+ if (ret)
+ goto free_adj;
+ } else if (dev_list == &dev->adj_list.upper) {
+ sprintf(linkname, "upper_%s", adj_dev->name);
+ ret = sysfs_create_link(&(dev->dev.kobj),
+ &(adj_dev->dev.kobj), linkname);
+ if (ret)
+ goto free_adj;
}
- /* Ensure that master upper link is always the first item in list. */
- if (master)
- list_add_rcu(&adj->list, &dev->upper_dev_list);
- else
- list_add_tail_rcu(&adj->list, &dev->upper_dev_list);
+ /* Ensure that master link is always the first item in list. */
+ if (master) {
+ ret = sysfs_create_link(&(dev->dev.kobj),
+ &(adj_dev->dev.kobj), "master");
+ if (ret)
+ goto remove_symlinks;
+
+ list_add_rcu(&adj->list, dev_list);
+ } else {
+ list_add_tail_rcu(&adj->list, dev_list);
+ }
return 0;
-}
-static inline int __netdev_upper_dev_insert(struct net_device *dev,
- struct net_device *udev,
- bool master, bool neighbour)
-{
- return __netdev_adjacent_dev_insert(dev, udev, neighbour, master,
- true);
-}
+remove_symlinks:
+ if (dev_list == &dev->adj_list.lower) {
+ sprintf(linkname, "lower_%s", adj_dev->name);
+ sysfs_remove_link(&(dev->dev.kobj), linkname);
+ } else if (dev_list == &dev->adj_list.upper) {
+ sprintf(linkname, "upper_%s", adj_dev->name);
+ sysfs_remove_link(&(dev->dev.kobj), linkname);
+ }
-static inline int __netdev_lower_dev_insert(struct net_device *dev,
- struct net_device *ldev,
- bool neighbour)
-{
- return __netdev_adjacent_dev_insert(dev, ldev, neighbour, false,
- false);
+free_adj:
+ kfree(adj);
+
+ return ret;
}
void __netdev_adjacent_dev_remove(struct net_device *dev,
- struct net_device *adj_dev, bool upper)
+ struct net_device *adj_dev,
+ struct list_head *dev_list)
{
struct netdev_adjacent *adj;
+ char linkname[IFNAMSIZ+7];
- if (upper)
- adj = __netdev_find_upper(dev, adj_dev);
- else
- adj = __netdev_find_lower(dev, adj_dev);
+ adj = __netdev_find_adj(dev, adj_dev, dev_list);
- if (!adj)
+ if (!adj) {
+ pr_err("tried to remove device %s from %s\n",
+ dev->name, adj_dev->name);
BUG();
+ }
if (adj->ref_nr > 1) {
+ pr_debug("%s to %s ref_nr-- = %d\n", dev->name, adj_dev->name,
+ adj->ref_nr-1);
adj->ref_nr--;
return;
}
+ if (adj->master)
+ sysfs_remove_link(&(dev->dev.kobj), "master");
+
+ if (dev_list == &dev->adj_list.lower) {
+ sprintf(linkname, "lower_%s", adj_dev->name);
+ sysfs_remove_link(&(dev->dev.kobj), linkname);
+ } else if (dev_list == &dev->adj_list.upper) {
+ sprintf(linkname, "upper_%s", adj_dev->name);
+ sysfs_remove_link(&(dev->dev.kobj), linkname);
+ }
+
list_del_rcu(&adj->list);
- pr_debug("dev_put for %s, because of %s link removed from %s to %s\n",
- adj_dev->name, upper ? "upper" : "lower", dev->name,
- adj_dev->name);
+ pr_debug("dev_put for %s, because link removed from %s to %s\n",
+ adj_dev->name, dev->name, adj_dev->name);
dev_put(adj_dev);
kfree_rcu(adj, rcu);
}
-static inline void __netdev_upper_dev_remove(struct net_device *dev,
- struct net_device *udev)
-{
- return __netdev_adjacent_dev_remove(dev, udev, true);
-}
-
-static inline void __netdev_lower_dev_remove(struct net_device *dev,
- struct net_device *ldev)
-{
- return __netdev_adjacent_dev_remove(dev, ldev, false);
-}
-
-int __netdev_adjacent_dev_insert_link(struct net_device *dev,
- struct net_device *upper_dev,
- bool master, bool neighbour)
+int __netdev_adjacent_dev_link_lists(struct net_device *dev,
+ struct net_device *upper_dev,
+ struct list_head *up_list,
+ struct list_head *down_list,
+ void *private, bool master)
{
int ret;
- ret = __netdev_upper_dev_insert(dev, upper_dev, master, neighbour);
+ ret = __netdev_adjacent_dev_insert(dev, upper_dev, up_list, private,
+ master);
if (ret)
return ret;
- ret = __netdev_lower_dev_insert(upper_dev, dev, neighbour);
+ ret = __netdev_adjacent_dev_insert(upper_dev, dev, down_list, private,
+ false);
if (ret) {
- __netdev_upper_dev_remove(dev, upper_dev);
+ __netdev_adjacent_dev_remove(dev, upper_dev, up_list);
return ret;
}
return 0;
}
-static inline int __netdev_adjacent_dev_link(struct net_device *dev,
- struct net_device *udev)
+int __netdev_adjacent_dev_link(struct net_device *dev,
+ struct net_device *upper_dev)
{
- return __netdev_adjacent_dev_insert_link(dev, udev, false, false);
+ return __netdev_adjacent_dev_link_lists(dev, upper_dev,
+ &dev->all_adj_list.upper,
+ &upper_dev->all_adj_list.lower,
+ NULL, false);
}
-static inline int __netdev_adjacent_dev_link_neighbour(struct net_device *dev,
- struct net_device *udev,
- bool master)
+void __netdev_adjacent_dev_unlink_lists(struct net_device *dev,
+ struct net_device *upper_dev,
+ struct list_head *up_list,
+ struct list_head *down_list)
{
- return __netdev_adjacent_dev_insert_link(dev, udev, master, true);
+ __netdev_adjacent_dev_remove(dev, upper_dev, up_list);
+ __netdev_adjacent_dev_remove(upper_dev, dev, down_list);
}
void __netdev_adjacent_dev_unlink(struct net_device *dev,
struct net_device *upper_dev)
{
- __netdev_upper_dev_remove(dev, upper_dev);
- __netdev_lower_dev_remove(upper_dev, dev);
+ __netdev_adjacent_dev_unlink_lists(dev, upper_dev,
+ &dev->all_adj_list.upper,
+ &upper_dev->all_adj_list.lower);
+}
+
+int __netdev_adjacent_dev_link_neighbour(struct net_device *dev,
+ struct net_device *upper_dev,
+ void *private, bool master)
+{
+ int ret = __netdev_adjacent_dev_link(dev, upper_dev);
+
+ if (ret)
+ return ret;
+
+ ret = __netdev_adjacent_dev_link_lists(dev, upper_dev,
+ &dev->adj_list.upper,
+ &upper_dev->adj_list.lower,
+ private, master);
+ if (ret) {
+ __netdev_adjacent_dev_unlink(dev, upper_dev);
+ return ret;
+ }
+
+ return 0;
}
+void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev,
+ struct net_device *upper_dev)
+{
+ __netdev_adjacent_dev_unlink(dev, upper_dev);
+ __netdev_adjacent_dev_unlink_lists(dev, upper_dev,
+ &dev->adj_list.upper,
+ &upper_dev->adj_list.lower);
+}
static int __netdev_upper_dev_link(struct net_device *dev,
- struct net_device *upper_dev, bool master)
+ struct net_device *upper_dev, bool master,
+ void *private)
{
struct netdev_adjacent *i, *j, *to_i, *to_j;
int ret = 0;
@@ -4661,26 +4782,29 @@ static int __netdev_upper_dev_link(struct net_device *dev,
return -EBUSY;
/* To prevent loops, check if dev is not upper device to upper_dev. */
- if (__netdev_find_upper(upper_dev, dev))
+ if (__netdev_find_adj(upper_dev, dev, &upper_dev->all_adj_list.upper))
return -EBUSY;
- if (__netdev_find_upper(dev, upper_dev))
+ if (__netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper))
return -EEXIST;
if (master && netdev_master_upper_dev_get(dev))
return -EBUSY;
- ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, master);
+ ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, private,
+ master);
if (ret)
return ret;
/* Now that we linked these devs, make all the upper_dev's
- * upper_dev_list visible to every dev's lower_dev_list and vice
+ * all_adj_list.upper visible to every dev's all_adj_list.lower an
* versa, and don't forget the devices itself. All of these
* links are non-neighbours.
*/
- list_for_each_entry(i, &dev->lower_dev_list, list) {
- list_for_each_entry(j, &upper_dev->upper_dev_list, list) {
+ list_for_each_entry(i, &dev->all_adj_list.lower, list) {
+ list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) {
+ pr_debug("Interlinking %s with %s, non-neighbour\n",
+ i->dev->name, j->dev->name);
ret = __netdev_adjacent_dev_link(i->dev, j->dev);
if (ret)
goto rollback_mesh;
@@ -4688,14 +4812,18 @@ static int __netdev_upper_dev_link(struct net_device *dev,
}
/* add dev to every upper_dev's upper device */
- list_for_each_entry(i, &upper_dev->upper_dev_list, list) {
+ list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) {
+ pr_debug("linking %s's upper device %s with %s\n",
+ upper_dev->name, i->dev->name, dev->name);
ret = __netdev_adjacent_dev_link(dev, i->dev);
if (ret)
goto rollback_upper_mesh;
}
/* add upper_dev to every dev's lower device */
- list_for_each_entry(i, &dev->lower_dev_list, list) {
+ list_for_each_entry(i, &dev->all_adj_list.lower, list) {
+ pr_debug("linking %s's lower device %s with %s\n", dev->name,
+ i->dev->name, upper_dev->name);
ret = __netdev_adjacent_dev_link(i->dev, upper_dev);
if (ret)
goto rollback_lower_mesh;
@@ -4706,7 +4834,7 @@ static int __netdev_upper_dev_link(struct net_device *dev,
rollback_lower_mesh:
to_i = i;
- list_for_each_entry(i, &dev->lower_dev_list, list) {
+ list_for_each_entry(i, &dev->all_adj_list.lower, list) {
if (i == to_i)
break;
__netdev_adjacent_dev_unlink(i->dev, upper_dev);
@@ -4716,7 +4844,7 @@ rollback_lower_mesh:
rollback_upper_mesh:
to_i = i;
- list_for_each_entry(i, &upper_dev->upper_dev_list, list) {
+ list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) {
if (i == to_i)
break;
__netdev_adjacent_dev_unlink(dev, i->dev);
@@ -4727,8 +4855,8 @@ rollback_upper_mesh:
rollback_mesh:
to_i = i;
to_j = j;
- list_for_each_entry(i, &dev->lower_dev_list, list) {
- list_for_each_entry(j, &upper_dev->upper_dev_list, list) {
+ list_for_each_entry(i, &dev->all_adj_list.lower, list) {
+ list_for_each_entry(j, &upper_dev->all_adj_list.upper, list) {
if (i == to_i && j == to_j)
break;
__netdev_adjacent_dev_unlink(i->dev, j->dev);
@@ -4737,7 +4865,7 @@ rollback_mesh:
break;
}
- __netdev_adjacent_dev_unlink(dev, upper_dev);
+ __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
return ret;
}
@@ -4755,7 +4883,7 @@ rollback_mesh:
int netdev_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev)
{
- return __netdev_upper_dev_link(dev, upper_dev, false);
+ return __netdev_upper_dev_link(dev, upper_dev, false, NULL);
}
EXPORT_SYMBOL(netdev_upper_dev_link);
@@ -4773,10 +4901,18 @@ EXPORT_SYMBOL(netdev_upper_dev_link);
int netdev_master_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev)
{
- return __netdev_upper_dev_link(dev, upper_dev, true);
+ return __netdev_upper_dev_link(dev, upper_dev, true, NULL);
}
EXPORT_SYMBOL(netdev_master_upper_dev_link);
+int netdev_master_upper_dev_link_private(struct net_device *dev,
+ struct net_device *upper_dev,
+ void *private)
+{
+ return __netdev_upper_dev_link(dev, upper_dev, true, private);
+}
+EXPORT_SYMBOL(netdev_master_upper_dev_link_private);
+
/**
* netdev_upper_dev_unlink - Removes a link to upper device
* @dev: device
@@ -4791,29 +4927,59 @@ void netdev_upper_dev_unlink(struct net_device *dev,
struct netdev_adjacent *i, *j;
ASSERT_RTNL();
- __netdev_adjacent_dev_unlink(dev, upper_dev);
+ __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
/* Here is the tricky part. We must remove all dev's lower
* devices from all upper_dev's upper devices and vice
* versa, to maintain the graph relationship.
*/
- list_for_each_entry(i, &dev->lower_dev_list, list)
- list_for_each_entry(j, &upper_dev->upper_dev_list, list)
+ list_for_each_entry(i, &dev->all_adj_list.lower, list)
+ list_for_each_entry(j, &upper_dev->all_adj_list.upper, list)
__netdev_adjacent_dev_unlink(i->dev, j->dev);
/* remove also the devices itself from lower/upper device
* list
*/
- list_for_each_entry(i, &dev->lower_dev_list, list)
+ list_for_each_entry(i, &dev->all_adj_list.lower, list)
__netdev_adjacent_dev_unlink(i->dev, upper_dev);
- list_for_each_entry(i, &upper_dev->upper_dev_list, list)
+ list_for_each_entry(i, &upper_dev->all_adj_list.upper, list)
__netdev_adjacent_dev_unlink(dev, i->dev);
call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev);
}
EXPORT_SYMBOL(netdev_upper_dev_unlink);
+void *netdev_lower_dev_get_private_rcu(struct net_device *dev,
+ struct net_device *lower_dev)
+{
+ struct netdev_adjacent *lower;
+
+ if (!lower_dev)
+ return NULL;
+ lower = __netdev_find_adj_rcu(dev, lower_dev, &dev->adj_list.lower);
+ if (!lower)
+ return NULL;
+
+ return lower->private;
+}
+EXPORT_SYMBOL(netdev_lower_dev_get_private_rcu);
+
+void *netdev_lower_dev_get_private(struct net_device *dev,
+ struct net_device *lower_dev)
+{
+ struct netdev_adjacent *lower;
+
+ if (!lower_dev)
+ return NULL;
+ lower = __netdev_find_adj(dev, lower_dev, &dev->adj_list.lower);
+ if (!lower)
+ return NULL;
+
+ return lower->private;
+}
+EXPORT_SYMBOL(netdev_lower_dev_get_private);
+
static void dev_change_rx_flags(struct net_device *dev, int flags)
{
const struct net_device_ops *ops = dev->netdev_ops;
@@ -6069,8 +6235,10 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
INIT_LIST_HEAD(&dev->napi_list);
INIT_LIST_HEAD(&dev->unreg_list);
INIT_LIST_HEAD(&dev->link_watch_list);
- INIT_LIST_HEAD(&dev->upper_dev_list);
- INIT_LIST_HEAD(&dev->lower_dev_list);
+ INIT_LIST_HEAD(&dev->adj_list.upper);
+ INIT_LIST_HEAD(&dev->adj_list.lower);
+ INIT_LIST_HEAD(&dev->all_adj_list.upper);
+ INIT_LIST_HEAD(&dev->all_adj_list.lower);
dev->priv_flags = IFF_XMIT_DST_RELEASE;
setup(dev);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 6072610a8672..ca15f32821fb 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -867,7 +867,7 @@ static void neigh_invalidate(struct neighbour *neigh)
static void neigh_probe(struct neighbour *neigh)
__releases(neigh->lock)
{
- struct sk_buff *skb = skb_peek(&neigh->arp_queue);
+ struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
/* keep skb alive even if arp_queue overflows */
if (skb)
skb = skb_copy(skb, GFP_ATOMIC);
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index d954b56b4e47..325dee863e46 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -1344,17 +1344,19 @@ int netdev_register_kobject(struct net_device *net)
return error;
}
-int netdev_class_create_file(struct class_attribute *class_attr)
+int netdev_class_create_file_ns(struct class_attribute *class_attr,
+ const void *ns)
{
- return class_create_file(&net_class, class_attr);
+ return class_create_file_ns(&net_class, class_attr, ns);
}
-EXPORT_SYMBOL(netdev_class_create_file);
+EXPORT_SYMBOL(netdev_class_create_file_ns);
-void netdev_class_remove_file(struct class_attribute *class_attr)
+void netdev_class_remove_file_ns(struct class_attribute *class_attr,
+ const void *ns)
{
- class_remove_file(&net_class, class_attr);
+ class_remove_file_ns(&net_class, class_attr, ns);
}
-EXPORT_SYMBOL(netdev_class_remove_file);
+EXPORT_SYMBOL(netdev_class_remove_file_ns);
int netdev_kobject_init(void)
{
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index fe32388ea24f..3b1357bcfc92 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -345,7 +345,7 @@ static int dn_insert_route(struct dn_route *rt, unsigned int hash, struct dn_rou
/* Put it first */
*rthp = rth->dst.dn_next;
rcu_assign_pointer(rth->dst.dn_next,
- dn_rt_hash_table[hash].chain);
+ rcu_access_pointer(dn_rt_hash_table[hash].chain));
rcu_assign_pointer(dn_rt_hash_table[hash].chain, rth);
dst_use(&rth->dst, now);
@@ -358,7 +358,8 @@ static int dn_insert_route(struct dn_route *rt, unsigned int hash, struct dn_rou
rthp = &rth->dst.dn_next;
}
- rcu_assign_pointer(rt->dst.dn_next, dn_rt_hash_table[hash].chain);
+ rcu_assign_pointer(rt->dst.dn_next,
+ rcu_access_pointer(dn_rt_hash_table[hash].chain));
rcu_assign_pointer(dn_rt_hash_table[hash].chain, rt);
dst_use(&rt->dst, now);
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index be1f64d35358..9bd3c31c30e5 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -58,7 +58,7 @@
#include <net/ipv6.h>
#include <net/ip.h>
#include <net/dsa.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
__setup("ether=", netdev_boot_setup);
@@ -133,7 +133,7 @@ int eth_rebuild_header(struct sk_buff *skb)
return arp_find(eth->h_dest, skb);
#endif
default:
- printk(KERN_DEBUG
+ netdev_dbg(dev,
"%s: unable to resolve type %X addresses.\n",
dev->name, ntohs(eth->h_proto));
@@ -178,7 +178,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
* seems to set IFF_PROMISC.
*/
- else if (1 /*dev->flags&IFF_PROMISC */ ) {
+ else if (1 /*dev->flags&IFF_PROMISC */) {
if (unlikely(!ether_addr_equal_64bits(eth->h_dest,
dev->dev_addr)))
skb->pkt_type = PACKET_OTHERHOST;
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index d9c4f113d709..d328f158f0e5 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -269,7 +269,7 @@ int ip_ra_control(struct sock *sk, unsigned char on,
}
/* dont let ip_call_ra_chain() use sk again */
ra->sk = NULL;
- rcu_assign_pointer(*rap, ra->next);
+ rcu_assign_pointer(*rap, rcu_access_pointer(ra->next));
spin_unlock_bh(&ip_ra_lock);
if (ra->destructor)
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index e805e7b3030e..91f69bc883fe 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -49,70 +49,6 @@ static struct rtnl_link_ops vti_link_ops __read_mostly;
static int vti_net_id __read_mostly;
static int vti_tunnel_init(struct net_device *dev);
-static int vti_err(struct sk_buff *skb, u32 info)
-{
-
- /* All the routers (except for Linux) return only
- * 8 bytes of packet payload. It means, that precise relaying of
- * ICMP in the real Internet is absolutely infeasible.
- */
- struct net *net = dev_net(skb->dev);
- struct ip_tunnel_net *itn = net_generic(net, vti_net_id);
- struct iphdr *iph = (struct iphdr *)skb->data;
- const int type = icmp_hdr(skb)->type;
- const int code = icmp_hdr(skb)->code;
- struct ip_tunnel *t;
- int err;
-
- switch (type) {
- default:
- case ICMP_PARAMETERPROB:
- return 0;
-
- case ICMP_DEST_UNREACH:
- switch (code) {
- case ICMP_SR_FAILED:
- case ICMP_PORT_UNREACH:
- /* Impossible event. */
- return 0;
- default:
- /* All others are translated to HOST_UNREACH. */
- break;
- }
- break;
- case ICMP_TIME_EXCEEDED:
- if (code != ICMP_EXC_TTL)
- return 0;
- break;
- }
-
- err = -ENOENT;
-
- t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
- iph->daddr, iph->saddr, 0);
- if (t == NULL)
- goto out;
-
- if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
- ipv4_update_pmtu(skb, dev_net(skb->dev), info,
- t->parms.link, 0, IPPROTO_IPIP, 0);
- err = 0;
- goto out;
- }
-
- err = 0;
- if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
- goto out;
-
- if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
- t->err_count++;
- else
- t->err_count = 1;
- t->err_time = jiffies;
-out:
- return err;
-}
-
/* We dont digest the packet therefore let the packet pass */
static int vti_rcv(struct sk_buff *skb)
{
@@ -296,9 +232,8 @@ static void __net_init vti_fb_tunnel_init(struct net_device *dev)
iph->ihl = 5;
}
-static struct xfrm_tunnel vti_handler __read_mostly = {
+static struct xfrm_tunnel_notifier vti_handler __read_mostly = {
.handler = vti_rcv,
- .err_handler = vti_err,
.priority = 1,
};
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index bfec521c717f..193db03540ad 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -218,8 +218,10 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info)
if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
ipv4_sk_update_pmtu(skb, sk, info);
- else if (type == ICMP_REDIRECT)
+ else if (type == ICMP_REDIRECT) {
ipv4_sk_redirect(skb, sk);
+ return;
+ }
/* Report error on raw socket, if:
1. User requested ip_recverr.
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 14a15c49129d..15e024105f91 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -89,8 +89,7 @@ __u32 cookie_init_timestamp(struct request_sock *req)
static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport,
- __be16 dport, __u32 sseq, __u32 count,
- __u32 data)
+ __be16 dport, __u32 sseq, __u32 data)
{
/*
* Compute the secure sequence number.
@@ -102,7 +101,7 @@ static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport,
* As an extra hack, we add a small "data" value that encodes the
* MSS into the second hash value.
*/
-
+ u32 count = tcp_cookie_time();
return (cookie_hash(saddr, daddr, sport, dport, 0, 0) +
sseq + (count << COOKIEBITS) +
((cookie_hash(saddr, daddr, sport, dport, count, 1) + data)
@@ -114,22 +113,21 @@ static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport,
* If the syncookie is bad, the data returned will be out of
* range. This must be checked by the caller.
*
- * The count value used to generate the cookie must be within
- * "maxdiff" if the current (passed-in) "count". The return value
- * is (__u32)-1 if this test fails.
+ * The count value used to generate the cookie must be less than
+ * MAX_SYNCOOKIE_AGE minutes in the past.
+ * The return value (__u32)-1 if this test fails.
*/
static __u32 check_tcp_syn_cookie(__u32 cookie, __be32 saddr, __be32 daddr,
- __be16 sport, __be16 dport, __u32 sseq,
- __u32 count, __u32 maxdiff)
+ __be16 sport, __be16 dport, __u32 sseq)
{
- __u32 diff;
+ u32 diff, count = tcp_cookie_time();
/* Strip away the layers from the cookie */
cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq;
/* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */
diff = (count - (cookie >> COOKIEBITS)) & ((__u32) - 1 >> COOKIEBITS);
- if (diff >= maxdiff)
+ if (diff >= MAX_SYNCOOKIE_AGE)
return (__u32)-1;
return (cookie -
@@ -138,22 +136,22 @@ static __u32 check_tcp_syn_cookie(__u32 cookie, __be32 saddr, __be32 daddr,
}
/*
- * MSS Values are taken from the 2009 paper
- * 'Measuring TCP Maximum Segment Size' by S. Alcock and R. Nelson:
- * - values 1440 to 1460 accounted for 80% of observed mss values
- * - values outside the 536-1460 range are rare (<0.2%).
+ * MSS Values are chosen based on the 2011 paper
+ * 'An Analysis of TCP Maximum Segement Sizes' by S. Alcock and R. Nelson.
+ * Values ..
+ * .. lower than 536 are rare (< 0.2%)
+ * .. between 537 and 1299 account for less than < 1.5% of observed values
+ * .. in the 1300-1349 range account for about 15 to 20% of observed mss values
+ * .. exceeding 1460 are very rare (< 0.04%)
*
- * Table must be sorted.
+ * 1460 is the single most frequently announced mss value (30 to 46% depending
+ * on monitor location). Table must be sorted.
*/
static __u16 const msstab[] = {
- 64,
- 512,
536,
- 1024,
- 1440,
+ 1300,
+ 1440, /* 1440, 1452: PPPoE */
1460,
- 4312,
- 8960,
};
/*
@@ -173,7 +171,7 @@ u32 __cookie_v4_init_sequence(const struct iphdr *iph, const struct tcphdr *th,
return secure_tcp_syn_cookie(iph->saddr, iph->daddr,
th->source, th->dest, ntohl(th->seq),
- jiffies / (HZ * 60), mssind);
+ mssind);
}
EXPORT_SYMBOL_GPL(__cookie_v4_init_sequence);
@@ -189,13 +187,6 @@ __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp)
}
/*
- * This (misnamed) value is the age of syncookie which is permitted.
- * Its ideal value should be dependent on TCP_TIMEOUT_INIT and
- * sysctl_tcp_retries1. It's a rather complicated formula (exponential
- * backoff) to compute at runtime so it's currently hardcoded here.
- */
-#define COUNTER_TRIES 4
-/*
* Check if a ack sequence number is a valid syncookie.
* Return the decoded mss if it is, or 0 if not.
*/
@@ -204,9 +195,7 @@ int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th,
{
__u32 seq = ntohl(th->seq) - 1;
__u32 mssind = check_tcp_syn_cookie(cookie, iph->saddr, iph->daddr,
- th->source, th->dest, seq,
- jiffies / (HZ * 60),
- COUNTER_TRIES);
+ th->source, th->dest, seq);
return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0;
}
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 25a89eaa669d..5d083855c111 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -355,6 +355,12 @@ static void tcp_fixup_rcvbuf(struct sock *sk)
rcvmem = 2 * SKB_TRUESIZE(mss + MAX_TCP_HEADER) *
tcp_default_init_rwnd(mss);
+ /* Dynamic Right Sizing (DRS) has 2 to 3 RTT latency
+ * Allow enough cushion so that sender is not limited by our window
+ */
+ if (sysctl_tcp_moderate_rcvbuf)
+ rcvmem <<= 2;
+
if (sk->sk_rcvbuf < rcvmem)
sk->sk_rcvbuf = min(rcvmem, sysctl_tcp_rmem[2]);
}
@@ -373,6 +379,8 @@ void tcp_init_buffer_space(struct sock *sk)
tcp_fixup_sndbuf(sk);
tp->rcvq_space.space = tp->rcv_wnd;
+ tp->rcvq_space.time = tcp_time_stamp;
+ tp->rcvq_space.seq = tp->copied_seq;
maxwin = tcp_full_space(sk);
@@ -512,48 +520,62 @@ void tcp_rcv_space_adjust(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
int time;
- int space;
-
- if (tp->rcvq_space.time == 0)
- goto new_measure;
+ int copied;
time = tcp_time_stamp - tp->rcvq_space.time;
if (time < (tp->rcv_rtt_est.rtt >> 3) || tp->rcv_rtt_est.rtt == 0)
return;
- space = 2 * (tp->copied_seq - tp->rcvq_space.seq);
+ /* Number of bytes copied to user in last RTT */
+ copied = tp->copied_seq - tp->rcvq_space.seq;
+ if (copied <= tp->rcvq_space.space)
+ goto new_measure;
+
+ /* A bit of theory :
+ * copied = bytes received in previous RTT, our base window
+ * To cope with packet losses, we need a 2x factor
+ * To cope with slow start, and sender growing its cwin by 100 %
+ * every RTT, we need a 4x factor, because the ACK we are sending
+ * now is for the next RTT, not the current one :
+ * <prev RTT . ><current RTT .. ><next RTT .... >
+ */
+
+ if (sysctl_tcp_moderate_rcvbuf &&
+ !(sk->sk_userlocks & SOCK_RCVBUF_LOCK)) {
+ int rcvwin, rcvmem, rcvbuf;
- space = max(tp->rcvq_space.space, space);
+ /* minimal window to cope with packet losses, assuming
+ * steady state. Add some cushion because of small variations.
+ */
+ rcvwin = (copied << 1) + 16 * tp->advmss;
- if (tp->rcvq_space.space != space) {
- int rcvmem;
+ /* If rate increased by 25%,
+ * assume slow start, rcvwin = 3 * copied
+ * If rate increased by 50%,
+ * assume sender can use 2x growth, rcvwin = 4 * copied
+ */
+ if (copied >=
+ tp->rcvq_space.space + (tp->rcvq_space.space >> 2)) {
+ if (copied >=
+ tp->rcvq_space.space + (tp->rcvq_space.space >> 1))
+ rcvwin <<= 1;
+ else
+ rcvwin += (rcvwin >> 1);
+ }
- tp->rcvq_space.space = space;
+ rcvmem = SKB_TRUESIZE(tp->advmss + MAX_TCP_HEADER);
+ while (tcp_win_from_space(rcvmem) < tp->advmss)
+ rcvmem += 128;
- if (sysctl_tcp_moderate_rcvbuf &&
- !(sk->sk_userlocks & SOCK_RCVBUF_LOCK)) {
- int new_clamp = space;
+ rcvbuf = min(rcvwin / tp->advmss * rcvmem, sysctl_tcp_rmem[2]);
+ if (rcvbuf > sk->sk_rcvbuf) {
+ sk->sk_rcvbuf = rcvbuf;
- /* Receive space grows, normalize in order to
- * take into account packet headers and sk_buff
- * structure overhead.
- */
- space /= tp->advmss;
- if (!space)
- space = 1;
- rcvmem = SKB_TRUESIZE(tp->advmss + MAX_TCP_HEADER);
- while (tcp_win_from_space(rcvmem) < tp->advmss)
- rcvmem += 128;
- space *= rcvmem;
- space = min(space, sysctl_tcp_rmem[2]);
- if (space > sk->sk_rcvbuf) {
- sk->sk_rcvbuf = space;
-
- /* Make the window clamp follow along. */
- tp->window_clamp = new_clamp;
- }
+ /* Make the window clamp follow along. */
+ tp->window_clamp = rcvwin;
}
}
+ tp->rcvq_space.space = copied;
new_measure:
tp->rcvq_space.seq = tp->copied_seq;
@@ -5674,8 +5696,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
tcp_init_congestion_control(sk);
tcp_mtup_init(sk);
- tcp_init_buffer_space(sk);
tp->copied_seq = tp->rcv_nxt;
+ tcp_init_buffer_space(sk);
}
smp_mb();
tcp_set_state(sk, TCP_ESTABLISHED);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 74d2c95db57f..0ca44df51ee9 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -658,7 +658,7 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
break;
case ICMP_REDIRECT:
ipv4_sk_redirect(skb, sk);
- break;
+ goto out;
}
/*
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index b5663c37f089..31b18152528f 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -16,13 +16,13 @@
#include <net/xfrm.h>
/* Informational hook. The decap is still done here. */
-static struct xfrm_tunnel __rcu *rcv_notify_handlers __read_mostly;
+static struct xfrm_tunnel_notifier __rcu *rcv_notify_handlers __read_mostly;
static DEFINE_MUTEX(xfrm4_mode_tunnel_input_mutex);
-int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel *handler)
+int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler)
{
- struct xfrm_tunnel __rcu **pprev;
- struct xfrm_tunnel *t;
+ struct xfrm_tunnel_notifier __rcu **pprev;
+ struct xfrm_tunnel_notifier *t;
int ret = -EEXIST;
int priority = handler->priority;
@@ -50,10 +50,10 @@ err:
}
EXPORT_SYMBOL_GPL(xfrm4_mode_tunnel_input_register);
-int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel *handler)
+int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler)
{
- struct xfrm_tunnel __rcu **pprev;
- struct xfrm_tunnel *t;
+ struct xfrm_tunnel_notifier __rcu **pprev;
+ struct xfrm_tunnel_notifier *t;
int ret = -ENOENT;
mutex_lock(&xfrm4_mode_tunnel_input_mutex);
@@ -134,7 +134,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
{
- struct xfrm_tunnel *handler;
+ struct xfrm_tunnel_notifier *handler;
int err = -EINVAL;
if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP)
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 9a459be24af7..ccde54248c8c 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -107,6 +107,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
memset(fl4, 0, sizeof(struct flowi4));
fl4->flowi4_mark = skb->mark;
+ fl4->flowi4_oif = skb_dst(skb)->dev->ifindex;
if (!ip_is_fragment(iph)) {
switch (iph->protocol) {
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 7c96100b021e..4966b124dc2e 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -1028,52 +1028,4 @@ out_unregister_tcp_proto:
}
module_init(inet6_init);
-static void __exit inet6_exit(void)
-{
- if (disable_ipv6_mod)
- return;
-
- /* First of all disallow new sockets creation. */
- sock_unregister(PF_INET6);
- /* Disallow any further netlink messages */
- rtnl_unregister_all(PF_INET6);
-
- udpv6_exit();
- udplitev6_exit();
- tcpv6_exit();
-
- /* Cleanup code parts. */
- ipv6_packet_cleanup();
- ipv6_frag_exit();
- ipv6_exthdrs_exit();
- addrconf_cleanup();
- ip6_flowlabel_cleanup();
- ndisc_late_cleanup();
- ip6_route_cleanup();
-#ifdef CONFIG_PROC_FS
-
- /* Cleanup code parts. */
- if6_proc_exit();
- ipv6_misc_proc_exit();
- udplite6_proc_exit();
- raw6_proc_exit();
-#endif
- ipv6_netfilter_fini();
- ipv6_stub = NULL;
- igmp6_cleanup();
- ndisc_cleanup();
- ip6_mr_cleanup();
- icmpv6_cleanup();
- rawv6_exit();
-
- unregister_pernet_subsys(&inet6_net_ops);
- proto_unregister(&rawv6_prot);
- proto_unregister(&udplitev6_prot);
- proto_unregister(&udpv6_prot);
- proto_unregister(&tcpv6_prot);
-
- rcu_barrier(); /* Wait for completion of call_rcu()'s */
-}
-module_exit(inet6_exit);
-
MODULE_ALIAS_NETPROTO(PF_INET6);
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 73784c3d4642..82e1da3a40b9 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -618,8 +618,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+offset);
struct xfrm_state *x;
- if (type != ICMPV6_DEST_UNREACH &&
- type != ICMPV6_PKT_TOOBIG &&
+ if (type != ICMPV6_PKT_TOOBIG &&
type != NDISC_REDIRECT)
return;
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index d3618a78fcac..e67e63f9858d 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -436,8 +436,7 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data + offset);
struct xfrm_state *x;
- if (type != ICMPV6_DEST_UNREACH &&
- type != ICMPV6_PKT_TOOBIG &&
+ if (type != ICMPV6_PKT_TOOBIG &&
type != NDISC_REDIRECT)
return;
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 6b26e9feafb9..a0b8f4056f05 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -276,7 +276,7 @@ static void ip6gre_tunnel_unlink(struct ip6gre_net *ign, struct ip6_tnl *t)
(iter = rtnl_dereference(*tp)) != NULL;
tp = &iter->next) {
if (t == iter) {
- rcu_assign_pointer(*tp, t->next);
+ rcu_assign_pointer(*tp, rcu_access_pointer(t->next));
break;
}
}
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 3a692d529163..a54c45ce4a48 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1015,6 +1015,8 @@ static inline int ip6_ufo_append_data(struct sock *sk,
* udp datagram
*/
if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) {
+ struct frag_hdr fhdr;
+
skb = sock_alloc_send_skb(sk,
hh_len + fragheaderlen + transhdrlen + 20,
(flags & MSG_DONTWAIT), &err);
@@ -1036,12 +1038,6 @@ static inline int ip6_ufo_append_data(struct sock *sk,
skb->protocol = htons(ETH_P_IPV6);
skb->ip_summed = CHECKSUM_PARTIAL;
skb->csum = 0;
- }
-
- err = skb_append_datato_frags(sk,skb, getfrag, from,
- (length - transhdrlen));
- if (!err) {
- struct frag_hdr fhdr;
/* Specify the length of each IPv6 datagram fragment.
* It has to be a multiple of 8.
@@ -1052,15 +1048,10 @@ static inline int ip6_ufo_append_data(struct sock *sk,
ipv6_select_ident(&fhdr, rt);
skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
__skb_queue_tail(&sk->sk_write_queue, skb);
-
- return 0;
}
- /* There is not enough support do UPD LSO,
- * so follow normal path
- */
- kfree_skb(skb);
- return err;
+ return skb_append_datato_frags(sk, skb, getfrag, from,
+ (length - transhdrlen));
}
static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src,
@@ -1227,27 +1218,27 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
* --yoshfuji
*/
- cork->length += length;
- if (length > mtu) {
- int proto = sk->sk_protocol;
- if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){
- ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen);
- return -EMSGSIZE;
- }
-
- if (proto == IPPROTO_UDP &&
- (rt->dst.dev->features & NETIF_F_UFO)) {
+ if ((length > mtu) && dontfrag && (sk->sk_protocol == IPPROTO_UDP ||
+ sk->sk_protocol == IPPROTO_RAW)) {
+ ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen);
+ return -EMSGSIZE;
+ }
- err = ip6_ufo_append_data(sk, getfrag, from, length,
- hh_len, fragheaderlen,
- transhdrlen, mtu, flags, rt);
- if (err)
- goto error;
- return 0;
- }
+ skb = skb_peek_tail(&sk->sk_write_queue);
+ cork->length += length;
+ if (((length > mtu) ||
+ (skb && skb_is_gso(skb))) &&
+ (sk->sk_protocol == IPPROTO_UDP) &&
+ (rt->dst.dev->features & NETIF_F_UFO)) {
+ err = ip6_ufo_append_data(sk, getfrag, from, length,
+ hh_len, fragheaderlen,
+ transhdrlen, mtu, flags, rt);
+ if (err)
+ goto error;
+ return 0;
}
- if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
+ if (!skb)
goto alloc_new_skb;
while (length > 0) {
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 2d8f4829575b..6979ff1d70ec 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -245,7 +245,7 @@ ip6_tnl_unlink(struct ip6_tnl_net *ip6n, struct ip6_tnl *t)
(iter = rtnl_dereference(*tp)) != NULL;
tp = &iter->next) {
if (t == iter) {
- rcu_assign_pointer(*tp, t->next);
+ rcu_assign_pointer(*tp, rcu_access_pointer(t->next));
break;
}
}
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 5636a912074a..ce507d9e1c90 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -64,8 +64,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
(struct ip_comp_hdr *)(skb->data + offset);
struct xfrm_state *x;
- if (type != ICMPV6_DEST_UNREACH &&
- type != ICMPV6_PKT_TOOBIG &&
+ if (type != ICMPV6_PKT_TOOBIG &&
type != NDISC_REDIRECT)
return;
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 58916bbb1728..a4ed2416399e 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -335,8 +335,10 @@ static void rawv6_err(struct sock *sk, struct sk_buff *skb,
ip6_sk_update_pmtu(skb, sk, info);
harderr = (np->pmtudisc == IPV6_PMTUDISC_DO);
}
- if (type == NDISC_REDIRECT)
+ if (type == NDISC_REDIRECT) {
ip6_sk_redirect(skb, sk);
+ return;
+ }
if (np->recverr) {
u8 *payload = skb->data;
if (!inet->hdrincl)
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 7ee5cb96db34..fcb050ab5134 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -157,7 +157,7 @@ static void ipip6_tunnel_unlink(struct sit_net *sitn, struct ip_tunnel *t)
(iter = rtnl_dereference(*tp)) != NULL;
tp = &iter->next) {
if (t == iter) {
- rcu_assign_pointer(*tp, t->next);
+ rcu_assign_pointer(*tp, rcu_access_pointer(t->next));
break;
}
}
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index bf63ac8a49b9..d703218a653b 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -24,26 +24,21 @@
#define COOKIEBITS 24 /* Upper bits store count */
#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
-/* Table must be sorted. */
+/* RFC 2460, Section 8.3:
+ * [ipv6 tcp] MSS must be computed as the maximum packet size minus 60 [..]
+ *
+ * Due to IPV6_MIN_MTU=1280 the lowest possible MSS is 1220, which allows
+ * using higher values than ipv4 tcp syncookies.
+ * The other values are chosen based on ethernet (1500 and 9k MTU), plus
+ * one that accounts for common encap (PPPoe) overhead. Table must be sorted.
+ */
static __u16 const msstab[] = {
- 64,
- 512,
- 536,
- 1280 - 60,
+ 1280 - 60, /* IPV6_MIN_MTU - 60 */
1480 - 60,
1500 - 60,
- 4460 - 60,
9000 - 60,
};
-/*
- * This (misnamed) value is the age of syncookie which is permitted.
- * Its ideal value should be dependent on TCP_TIMEOUT_INIT and
- * sysctl_tcp_retries1. It's a rather complicated formula (exponential
- * backoff) to compute at runtime so it's currently hardcoded here.
- */
-#define COUNTER_TRIES 4
-
static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
struct request_sock *req,
struct dst_entry *dst)
@@ -86,8 +81,9 @@ static u32 cookie_hash(const struct in6_addr *saddr, const struct in6_addr *dadd
static __u32 secure_tcp_syn_cookie(const struct in6_addr *saddr,
const struct in6_addr *daddr,
__be16 sport, __be16 dport, __u32 sseq,
- __u32 count, __u32 data)
+ __u32 data)
{
+ u32 count = tcp_cookie_time();
return (cookie_hash(saddr, daddr, sport, dport, 0, 0) +
sseq + (count << COOKIEBITS) +
((cookie_hash(saddr, daddr, sport, dport, count, 1) + data)
@@ -96,15 +92,14 @@ static __u32 secure_tcp_syn_cookie(const struct in6_addr *saddr,
static __u32 check_tcp_syn_cookie(__u32 cookie, const struct in6_addr *saddr,
const struct in6_addr *daddr, __be16 sport,
- __be16 dport, __u32 sseq, __u32 count,
- __u32 maxdiff)
+ __be16 dport, __u32 sseq)
{
- __u32 diff;
+ __u32 diff, count = tcp_cookie_time();
cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq;
diff = (count - (cookie >> COOKIEBITS)) & ((__u32) -1 >> COOKIEBITS);
- if (diff >= maxdiff)
+ if (diff >= MAX_SYNCOOKIE_AGE)
return (__u32)-1;
return (cookie -
@@ -125,8 +120,7 @@ u32 __cookie_v6_init_sequence(const struct ipv6hdr *iph,
*mssp = msstab[mssind];
return secure_tcp_syn_cookie(&iph->saddr, &iph->daddr, th->source,
- th->dest, ntohl(th->seq),
- jiffies / (HZ * 60), mssind);
+ th->dest, ntohl(th->seq), mssind);
}
EXPORT_SYMBOL_GPL(__cookie_v6_init_sequence);
@@ -146,8 +140,7 @@ int __cookie_v6_check(const struct ipv6hdr *iph, const struct tcphdr *th,
{
__u32 seq = ntohl(th->seq) - 1;
__u32 mssind = check_tcp_syn_cookie(cookie, &iph->saddr, &iph->daddr,
- th->source, th->dest, seq,
- jiffies / (HZ * 60), COUNTER_TRIES);
+ th->source, th->dest, seq);
return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0;
}
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index f4058150262b..72b7eaaf3ca0 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -525,8 +525,10 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
if (type == ICMPV6_PKT_TOOBIG)
ip6_sk_update_pmtu(skb, sk, info);
- if (type == NDISC_REDIRECT)
+ if (type == NDISC_REDIRECT) {
ip6_sk_redirect(skb, sk);
+ goto out;
+ }
np = inet6_sk(sk);
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 23ed03d786c8..08ed2772b7aa 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -138,6 +138,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
memset(fl6, 0, sizeof(struct flowi6));
fl6->flowi6_mark = skb->mark;
+ fl6->flowi6_oif = skb_dst(skb)->dev->ifindex;
fl6->daddr = reverse ? hdr->saddr : hdr->daddr;
fl6->saddr = reverse ? hdr->daddr : hdr->saddr;
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 9d585370c5b4..911ef03bf8fb 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1098,7 +1098,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
x->id.proto = proto;
x->id.spi = sa->sadb_sa_spi;
- x->props.replay_window = sa->sadb_sa_replay;
+ x->props.replay_window = min_t(unsigned int, sa->sadb_sa_replay,
+ (sizeof(x->replay.bitmap) * 8));
if (sa->sadb_sa_flags & SADB_SAFLAGS_NOECN)
x->props.flags |= XFRM_STATE_NOECN;
if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP)
diff --git a/net/lapb/lapb_timer.c b/net/lapb/lapb_timer.c
index 54563ad8aeb1..355cc3b6fa4d 100644
--- a/net/lapb/lapb_timer.c
+++ b/net/lapb/lapb_timer.c
@@ -154,6 +154,7 @@ static void lapb_t1timer_expiry(unsigned long param)
} else {
lapb->n2count++;
lapb_requeue_frames(lapb);
+ lapb_kick(lapb);
}
break;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index aeb967a0aeed..d18ab89a5725 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -75,7 +75,7 @@ static int sta_info_hash_del(struct ieee80211_local *local,
return -ENOENT;
if (s == sta) {
rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)],
- s->hnext);
+ rcu_access_pointer(s->hnext));
return 0;
}
@@ -84,7 +84,7 @@ static int sta_info_hash_del(struct ieee80211_local *local,
s = rcu_dereference_protected(s->hnext,
lockdep_is_held(&local->sta_mtx));
if (rcu_access_pointer(s->hnext)) {
- rcu_assign_pointer(s->hnext, sta->hnext);
+ rcu_assign_pointer(s->hnext, rcu_access_pointer(sta->hnext));
return 0;
}
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 189e3c5b3d09..272d8e924cf6 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -231,14 +231,14 @@ override:
}
if (R_tab) {
police->rate_present = true;
- psched_ratecfg_precompute(&police->rate, &R_tab->rate);
+ psched_ratecfg_precompute(&police->rate, &R_tab->rate, 0);
qdisc_put_rtab(R_tab);
} else {
police->rate_present = false;
}
if (P_tab) {
police->peak_present = true;
- psched_ratecfg_precompute(&police->peak, &P_tab->rate);
+ psched_ratecfg_precompute(&police->peak, &P_tab->rate, 0);
qdisc_put_rtab(P_tab);
} else {
police->peak_present = false;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index a74e278654aa..e7121d29c4bd 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -910,11 +910,12 @@ void dev_shutdown(struct net_device *dev)
}
void psched_ratecfg_precompute(struct psched_ratecfg *r,
- const struct tc_ratespec *conf)
+ const struct tc_ratespec *conf,
+ u64 rate64)
{
memset(r, 0, sizeof(*r));
r->overhead = conf->overhead;
- r->rate_bytes_ps = conf->rate;
+ r->rate_bytes_ps = max_t(u64, conf->rate, rate64);
r->linklayer = (conf->linklayer & TC_LINKLAYER_MASK);
r->mult = 1;
/*
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 863846cc5513..0e1e38b40025 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -997,6 +997,8 @@ static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = {
[TCA_HTB_CTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
[TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
[TCA_HTB_DIRECT_QLEN] = { .type = NLA_U32 },
+ [TCA_HTB_RATE64] = { .type = NLA_U64 },
+ [TCA_HTB_CEIL64] = { .type = NLA_U64 },
};
static void htb_work_func(struct work_struct *work)
@@ -1114,6 +1116,12 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
opt.level = cl->level;
if (nla_put(skb, TCA_HTB_PARMS, sizeof(opt), &opt))
goto nla_put_failure;
+ if ((cl->rate.rate_bytes_ps >= (1ULL << 32)) &&
+ nla_put_u64(skb, TCA_HTB_RATE64, cl->rate.rate_bytes_ps))
+ goto nla_put_failure;
+ if ((cl->ceil.rate_bytes_ps >= (1ULL << 32)) &&
+ nla_put_u64(skb, TCA_HTB_CEIL64, cl->ceil.rate_bytes_ps))
+ goto nla_put_failure;
nla_nest_end(skb, nest);
spin_unlock_bh(root_lock);
@@ -1332,6 +1340,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
struct qdisc_rate_table *rtab = NULL, *ctab = NULL;
struct nlattr *tb[TCA_HTB_MAX + 1];
struct tc_htb_opt *hopt;
+ u64 rate64, ceil64;
/* extract all subattrs from opt attr */
if (!opt)
@@ -1491,8 +1500,12 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
cl->prio = TC_HTB_NUMPRIO - 1;
}
- psched_ratecfg_precompute(&cl->rate, &hopt->rate);
- psched_ratecfg_precompute(&cl->ceil, &hopt->ceil);
+ rate64 = tb[TCA_HTB_RATE64] ? nla_get_u64(tb[TCA_HTB_RATE64]) : 0;
+
+ ceil64 = tb[TCA_HTB_CEIL64] ? nla_get_u64(tb[TCA_HTB_CEIL64]) : 0;
+
+ psched_ratecfg_precompute(&cl->rate, &hopt->rate, rate64);
+ psched_ratecfg_precompute(&cl->ceil, &hopt->ceil, ceil64);
cl->buffer = PSCHED_TICKS2NS(hopt->buffer);
cl->cbuffer = PSCHED_TICKS2NS(hopt->cbuffer);
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 1aaf1b6e51a2..b0571224f3c9 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -341,9 +341,9 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
q->tokens = q->buffer;
q->ptokens = q->mtu;
- psched_ratecfg_precompute(&q->rate, &rtab->rate);
+ psched_ratecfg_precompute(&q->rate, &rtab->rate, 0);
if (ptab) {
- psched_ratecfg_precompute(&q->peak, &ptab->rate);
+ psched_ratecfg_precompute(&q->peak, &ptab->rate, 0);
q->peak_present = true;
} else {
q->peak_present = false;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index f94567b45bb3..d0d14a04dce1 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -519,8 +519,8 @@ static int __rpc_create_common(struct inode *dir, struct dentry *dentry,
d_add(dentry, inode);
return 0;
out_err:
- printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n",
- __FILE__, __func__, dentry->d_name.name);
+ printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %pd\n",
+ __FILE__, __func__, dentry);
dput(dentry);
return -ENOMEM;
}
@@ -755,8 +755,8 @@ static int rpc_populate(struct dentry *parent,
out_bad:
__rpc_depopulate(parent, files, start, eof);
mutex_unlock(&dir->i_mutex);
- printk(KERN_WARNING "%s: %s failed to populate directory %s\n",
- __FILE__, __func__, parent->d_name.name);
+ printk(KERN_WARNING "%s: %s failed to populate directory %pd\n",
+ __FILE__, __func__, parent);
return err;
}
@@ -852,8 +852,8 @@ out:
return dentry;
out_err:
dentry = ERR_PTR(err);
- printk(KERN_WARNING "%s: %s() failed to create pipe %s/%s (errno = %d)\n",
- __FILE__, __func__, parent->d_name.name, name,
+ printk(KERN_WARNING "%s: %s() failed to create pipe %pd/%s (errno = %d)\n",
+ __FILE__, __func__, parent, name,
err);
goto out;
}
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index eeb71480f1af..edde117c1863 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -671,7 +671,7 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev,
bss->pub.hidden_beacon_bss = &new->pub;
new->refcount += bss->refcount;
rcu_assign_pointer(bss->pub.beacon_ies,
- new->pub.beacon_ies);
+ rcu_access_pointer(new->pub.beacon_ies));
}
return true;
@@ -706,10 +706,10 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
old = rcu_access_pointer(found->pub.proberesp_ies);
rcu_assign_pointer(found->pub.proberesp_ies,
- tmp->pub.proberesp_ies);
+ rcu_access_pointer(tmp->pub.proberesp_ies));
/* Override possible earlier Beacon frame IEs */
rcu_assign_pointer(found->pub.ies,
- tmp->pub.proberesp_ies);
+ rcu_access_pointer(tmp->pub.proberesp_ies));
if (old)
kfree_rcu((struct cfg80211_bss_ies *)old,
rcu_head);
@@ -740,12 +740,12 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
old = rcu_access_pointer(found->pub.beacon_ies);
rcu_assign_pointer(found->pub.beacon_ies,
- tmp->pub.beacon_ies);
+ rcu_access_pointer(tmp->pub.beacon_ies));
/* Override IEs if they were from a beacon before */
if (old == rcu_access_pointer(found->pub.ies))
rcu_assign_pointer(found->pub.ies,
- tmp->pub.beacon_ies);
+ rcu_access_pointer(tmp->pub.beacon_ies));
/* Assign beacon IEs to all sub entries */
list_for_each_entry(bss, &found->hidden_list,
@@ -756,7 +756,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
WARN_ON(ies != old);
rcu_assign_pointer(bss->pub.beacon_ies,
- tmp->pub.beacon_ies);
+ rcu_access_pointer(tmp->pub.beacon_ies));
}
if (old)
@@ -804,7 +804,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
&hidden->hidden_list);
hidden->refcount++;
rcu_assign_pointer(new->pub.beacon_ies,
- hidden->pub.beacon_ies);
+ rcu_access_pointer(hidden->pub.beacon_ies));
}
} else {
/*
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c
index 8dafe6d3c6e4..dab57daae408 100644
--- a/net/xfrm/xfrm_replay.c
+++ b/net/xfrm/xfrm_replay.c
@@ -61,9 +61,9 @@ static void xfrm_replay_notify(struct xfrm_state *x, int event)
switch (event) {
case XFRM_REPLAY_UPDATE:
- if (x->replay_maxdiff &&
- (x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
- (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) {
+ if (!x->replay_maxdiff ||
+ ((x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
+ (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff))) {
if (x->xflags & XFRM_TIME_DEFER)
event = XFRM_REPLAY_TIMEOUT;
else
@@ -129,8 +129,7 @@ static int xfrm_replay_check(struct xfrm_state *x,
return 0;
diff = x->replay.seq - seq;
- if (diff >= min_t(unsigned int, x->props.replay_window,
- sizeof(x->replay.bitmap) * 8)) {
+ if (diff >= x->props.replay_window) {
x->stats.replay_window++;
goto err;
}
@@ -302,9 +301,10 @@ static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event)
switch (event) {
case XFRM_REPLAY_UPDATE:
- if (x->replay_maxdiff &&
- (replay_esn->seq - preplay_esn->seq < x->replay_maxdiff) &&
- (replay_esn->oseq - preplay_esn->oseq < x->replay_maxdiff)) {
+ if (!x->replay_maxdiff ||
+ ((replay_esn->seq - preplay_esn->seq < x->replay_maxdiff) &&
+ (replay_esn->oseq - preplay_esn->oseq
+ < x->replay_maxdiff))) {
if (x->xflags & XFRM_TIME_DEFER)
event = XFRM_REPLAY_TIMEOUT;
else
@@ -353,28 +353,30 @@ static void xfrm_replay_notify_esn(struct xfrm_state *x, int event)
switch (event) {
case XFRM_REPLAY_UPDATE:
- if (!x->replay_maxdiff)
- break;
-
- if (replay_esn->seq_hi == preplay_esn->seq_hi)
- seq_diff = replay_esn->seq - preplay_esn->seq;
- else
- seq_diff = ~preplay_esn->seq + replay_esn->seq + 1;
-
- if (replay_esn->oseq_hi == preplay_esn->oseq_hi)
- oseq_diff = replay_esn->oseq - preplay_esn->oseq;
- else
- oseq_diff = ~preplay_esn->oseq + replay_esn->oseq + 1;
-
- if (seq_diff < x->replay_maxdiff &&
- oseq_diff < x->replay_maxdiff) {
+ if (x->replay_maxdiff) {
+ if (replay_esn->seq_hi == preplay_esn->seq_hi)
+ seq_diff = replay_esn->seq - preplay_esn->seq;
+ else
+ seq_diff = ~preplay_esn->seq + replay_esn->seq
+ + 1;
- if (x->xflags & XFRM_TIME_DEFER)
- event = XFRM_REPLAY_TIMEOUT;
+ if (replay_esn->oseq_hi == preplay_esn->oseq_hi)
+ oseq_diff = replay_esn->oseq
+ - preplay_esn->oseq;
else
- return;
+ oseq_diff = ~preplay_esn->oseq
+ + replay_esn->oseq + 1;
+
+ if (seq_diff >= x->replay_maxdiff ||
+ oseq_diff >= x->replay_maxdiff)
+ break;
}
+ if (x->xflags & XFRM_TIME_DEFER)
+ event = XFRM_REPLAY_TIMEOUT;
+ else
+ return;
+
break;
case XFRM_REPLAY_TIMEOUT:
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index b9c3f9e943a9..d6e7f98fbfbf 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -468,7 +468,7 @@ expired:
}
err = __xfrm_state_delete(x);
- if (!err && x->id.spi)
+ if (!err)
km_state_expired(x, 1, 0);
xfrm_audit_state_delete(x, err ? 0 : 1,
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 3f565e495ac6..f964d4c00ffb 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -446,7 +446,8 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
memcpy(&x->sel, &p->sel, sizeof(x->sel));
memcpy(&x->lft, &p->lft, sizeof(x->lft));
x->props.mode = p->mode;
- x->props.replay_window = p->replay_window;
+ x->props.replay_window = min_t(unsigned int, p->replay_window,
+ sizeof(x->replay.bitmap) * 8);
x->props.reqid = p->reqid;
x->props.family = p->family;
memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr));
@@ -1856,7 +1857,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
if (x->km.state != XFRM_STATE_VALID)
goto out;
- err = xfrm_replay_verify_len(x->replay_esn, rp);
+ err = xfrm_replay_verify_len(x->replay_esn, re);
if (err)
goto out;
diff --git a/security/Makefile b/security/Makefile
index c26c81e92571..a5918e01a4f7 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -16,7 +16,6 @@ obj-$(CONFIG_MMU) += min_addr.o
# Object file lists
obj-$(CONFIG_SECURITY) += security.o capability.o
obj-$(CONFIG_SECURITYFS) += inode.o
-# Must precede capability.o in order to stack properly.
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
obj-$(CONFIG_AUDIT) += lsm_audit.o
diff --git a/security/capability.c b/security/capability.c
index dbeb9bc27b24..8b4f24ae4338 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -777,9 +777,15 @@ static int cap_xfrm_policy_delete_security(struct xfrm_sec_ctx *ctx)
return 0;
}
-static int cap_xfrm_state_alloc_security(struct xfrm_state *x,
- struct xfrm_user_sec_ctx *sec_ctx,
- u32 secid)
+static int cap_xfrm_state_alloc(struct xfrm_state *x,
+ struct xfrm_user_sec_ctx *sec_ctx)
+{
+ return 0;
+}
+
+static int cap_xfrm_state_alloc_acquire(struct xfrm_state *x,
+ struct xfrm_sec_ctx *polsec,
+ u32 secid)
{
return 0;
}
@@ -1101,7 +1107,8 @@ void __init security_fixup_ops(struct security_operations *ops)
set_to_cap_if_null(ops, xfrm_policy_clone_security);
set_to_cap_if_null(ops, xfrm_policy_free_security);
set_to_cap_if_null(ops, xfrm_policy_delete_security);
- set_to_cap_if_null(ops, xfrm_state_alloc_security);
+ set_to_cap_if_null(ops, xfrm_state_alloc);
+ set_to_cap_if_null(ops, xfrm_state_alloc_acquire);
set_to_cap_if_null(ops, xfrm_state_free_security);
set_to_cap_if_null(ops, xfrm_state_delete_security);
set_to_cap_if_null(ops, xfrm_policy_lookup);
diff --git a/security/security.c b/security/security.c
index 4dc31f4f2700..15b6928592ef 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1340,22 +1340,17 @@ int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
return security_ops->xfrm_policy_delete_security(ctx);
}
-int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
+int security_xfrm_state_alloc(struct xfrm_state *x,
+ struct xfrm_user_sec_ctx *sec_ctx)
{
- return security_ops->xfrm_state_alloc_security(x, sec_ctx, 0);
+ return security_ops->xfrm_state_alloc(x, sec_ctx);
}
EXPORT_SYMBOL(security_xfrm_state_alloc);
int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
struct xfrm_sec_ctx *polsec, u32 secid)
{
- if (!polsec)
- return 0;
- /*
- * We want the context to be taken from secid which is usually
- * from the sock.
- */
- return security_ops->xfrm_state_alloc_security(x, NULL, secid);
+ return security_ops->xfrm_state_alloc_acquire(x, polsec, secid);
}
int security_xfrm_state_delete(struct xfrm_state *x)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index a5091ec06aa6..6d0bf5c0c832 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -95,7 +95,9 @@
#include "audit.h"
#include "avc_ss.h"
-#define NUM_SEL_MNT_OPTS 5
+#define SB_TYPE_FMT "%s%s%s"
+#define SB_SUBTYPE(sb) (sb->s_subtype && sb->s_subtype[0])
+#define SB_TYPE_ARGS(sb) sb->s_type->name, SB_SUBTYPE(sb) ? "." : "", SB_SUBTYPE(sb) ? sb->s_subtype : ""
extern struct security_operations *security_ops;
@@ -139,12 +141,28 @@ static struct kmem_cache *sel_inode_cache;
* This function checks the SECMARK reference counter to see if any SECMARK
* targets are currently configured, if the reference counter is greater than
* zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
- * enabled, false (0) if SECMARK is disabled.
+ * enabled, false (0) if SECMARK is disabled. If the always_check_network
+ * policy capability is enabled, SECMARK is always considered enabled.
*
*/
static int selinux_secmark_enabled(void)
{
- return (atomic_read(&selinux_secmark_refcount) > 0);
+ return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
+}
+
+/**
+ * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
+ *
+ * Description:
+ * This function checks if NetLabel or labeled IPSEC is enabled. Returns true
+ * (1) if any are enabled or false (0) if neither are enabled. If the
+ * always_check_network policy capability is enabled, peer labeling
+ * is always considered enabled.
+ *
+ */
+static int selinux_peerlbl_enabled(void)
+{
+ return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
}
/*
@@ -309,8 +327,11 @@ enum {
Opt_defcontext = 3,
Opt_rootcontext = 4,
Opt_labelsupport = 5,
+ Opt_nextmntopt = 6,
};
+#define NUM_SEL_MNT_OPTS (Opt_nextmntopt - 1)
+
static const match_table_t tokens = {
{Opt_context, CONTEXT_STR "%s"},
{Opt_fscontext, FSCONTEXT_STR "%s"},
@@ -355,6 +376,29 @@ static int may_context_mount_inode_relabel(u32 sid,
return rc;
}
+static int selinux_is_sblabel_mnt(struct super_block *sb)
+{
+ struct superblock_security_struct *sbsec = sb->s_security;
+
+ if (sbsec->behavior == SECURITY_FS_USE_XATTR ||
+ sbsec->behavior == SECURITY_FS_USE_TRANS ||
+ sbsec->behavior == SECURITY_FS_USE_TASK)
+ return 1;
+
+ /* Special handling for sysfs. Is genfs but also has setxattr handler*/
+ if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
+ return 1;
+
+ /*
+ * Special handling for rootfs. Is genfs but supports
+ * setting SELinux context on in-core inodes.
+ */
+ if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0)
+ return 1;
+
+ return 0;
+}
+
static int sb_finish_set_opts(struct super_block *sb)
{
struct superblock_security_struct *sbsec = sb->s_security;
@@ -369,8 +413,8 @@ static int sb_finish_set_opts(struct super_block *sb)
the first boot of the SELinux kernel before we have
assigned xattr values to the filesystem. */
if (!root_inode->i_op->getxattr) {
- printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
- "xattr support\n", sb->s_id, sb->s_type->name);
+ printk(KERN_WARNING "SELinux: (dev %s, type "SB_TYPE_FMT") has no "
+ "xattr support\n", sb->s_id, SB_TYPE_ARGS(sb));
rc = -EOPNOTSUPP;
goto out;
}
@@ -378,35 +422,27 @@ static int sb_finish_set_opts(struct super_block *sb)
if (rc < 0 && rc != -ENODATA) {
if (rc == -EOPNOTSUPP)
printk(KERN_WARNING "SELinux: (dev %s, type "
- "%s) has no security xattr handler\n",
- sb->s_id, sb->s_type->name);
+ SB_TYPE_FMT") has no security xattr handler\n",
+ sb->s_id, SB_TYPE_ARGS(sb));
else
printk(KERN_WARNING "SELinux: (dev %s, type "
- "%s) getxattr errno %d\n", sb->s_id,
- sb->s_type->name, -rc);
+ SB_TYPE_FMT") getxattr errno %d\n", sb->s_id,
+ SB_TYPE_ARGS(sb), -rc);
goto out;
}
}
- sbsec->flags |= (SE_SBINITIALIZED | SE_SBLABELSUPP);
-
if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
- printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
- sb->s_id, sb->s_type->name);
+ printk(KERN_ERR "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), unknown behavior\n",
+ sb->s_id, SB_TYPE_ARGS(sb));
else
- printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
- sb->s_id, sb->s_type->name,
+ printk(KERN_DEBUG "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), %s\n",
+ sb->s_id, SB_TYPE_ARGS(sb),
labeling_behaviors[sbsec->behavior-1]);
- if (sbsec->behavior == SECURITY_FS_USE_GENFS ||
- sbsec->behavior == SECURITY_FS_USE_MNTPOINT ||
- sbsec->behavior == SECURITY_FS_USE_NONE ||
- sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
- sbsec->flags &= ~SE_SBLABELSUPP;
-
- /* Special handling for sysfs. Is genfs but also has setxattr handler*/
- if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
- sbsec->flags |= SE_SBLABELSUPP;
+ sbsec->flags |= SE_SBINITIALIZED;
+ if (selinux_is_sblabel_mnt(sb))
+ sbsec->flags |= SBLABEL_MNT;
/* Initialize the root inode. */
rc = inode_doinit_with_dentry(root_inode, root);
@@ -460,15 +496,18 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
if (!ss_initialized)
return -EINVAL;
+ /* make sure we always check enough bits to cover the mask */
+ BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
+
tmp = sbsec->flags & SE_MNTMASK;
/* count the number of mount options for this sb */
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
if (tmp & 0x01)
opts->num_mnt_opts++;
tmp >>= 1;
}
/* Check if the Label support flag is set */
- if (sbsec->flags & SE_SBLABELSUPP)
+ if (sbsec->flags & SBLABEL_MNT)
opts->num_mnt_opts++;
opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
@@ -515,9 +554,9 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
opts->mnt_opts[i] = context;
opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
}
- if (sbsec->flags & SE_SBLABELSUPP) {
+ if (sbsec->flags & SBLABEL_MNT) {
opts->mnt_opts[i] = NULL;
- opts->mnt_opts_flags[i++] = SE_SBLABELSUPP;
+ opts->mnt_opts_flags[i++] = SBLABEL_MNT;
}
BUG_ON(i != opts->num_mnt_opts);
@@ -561,7 +600,6 @@ static int selinux_set_mnt_opts(struct super_block *sb,
const struct cred *cred = current_cred();
int rc = 0, i;
struct superblock_security_struct *sbsec = sb->s_security;
- const char *name = sb->s_type->name;
struct inode *inode = sbsec->sb->s_root->d_inode;
struct inode_security_struct *root_isec = inode->i_security;
u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
@@ -614,14 +652,14 @@ static int selinux_set_mnt_opts(struct super_block *sb,
for (i = 0; i < num_opts; i++) {
u32 sid;
- if (flags[i] == SE_SBLABELSUPP)
+ if (flags[i] == SBLABEL_MNT)
continue;
rc = security_context_to_sid(mount_options[i],
strlen(mount_options[i]), &sid);
if (rc) {
printk(KERN_WARNING "SELinux: security_context_to_sid"
- "(%s) failed for (dev %s, type %s) errno=%d\n",
- mount_options[i], sb->s_id, name, rc);
+ "(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
+ mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
goto out;
}
switch (flags[i]) {
@@ -685,9 +723,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
* Determine the labeling behavior to use for this
* filesystem type.
*/
- rc = security_fs_use((sbsec->flags & SE_SBPROC) ?
- "proc" : sb->s_type->name,
- &sbsec->behavior, &sbsec->sid);
+ rc = security_fs_use(sb);
if (rc) {
printk(KERN_WARNING
"%s: security_fs_use(%s) returned %d\n",
@@ -770,7 +806,8 @@ out:
out_double_mount:
rc = -EINVAL;
printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different "
- "security settings for (dev %s, type %s)\n", sb->s_id, name);
+ "security settings for (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
+ SB_TYPE_ARGS(sb));
goto out;
}
@@ -1037,7 +1074,7 @@ static void selinux_write_opts(struct seq_file *m,
case DEFCONTEXT_MNT:
prefix = DEFCONTEXT_STR;
break;
- case SE_SBLABELSUPP:
+ case SBLABEL_MNT:
seq_putc(m, ',');
seq_puts(m, LABELSUPP_STR);
continue;
@@ -1650,7 +1687,7 @@ static int may_create(struct inode *dir,
if (rc)
return rc;
- if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
+ if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
rc = security_transition_sid(sid, dsec->sid, tclass,
&dentry->d_name, &newsid);
if (rc)
@@ -2438,14 +2475,14 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
u32 sid;
size_t len;
- if (flags[i] == SE_SBLABELSUPP)
+ if (flags[i] == SBLABEL_MNT)
continue;
len = strlen(mount_options[i]);
rc = security_context_to_sid(mount_options[i], len, &sid);
if (rc) {
printk(KERN_WARNING "SELinux: security_context_to_sid"
- "(%s) failed for (dev %s, type %s) errno=%d\n",
- mount_options[i], sb->s_id, sb->s_type->name, rc);
+ "(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
+ mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
goto out_free_opts;
}
rc = -EINVAL;
@@ -2483,8 +2520,8 @@ out_free_secdata:
return rc;
out_bad_option:
printk(KERN_WARNING "SELinux: unable to change security options "
- "during remount (dev %s, type=%s)\n", sb->s_id,
- sb->s_type->name);
+ "during remount (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
+ SB_TYPE_ARGS(sb));
goto out_free_opts;
}
@@ -2607,7 +2644,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
if ((sbsec->flags & SE_SBINITIALIZED) &&
(sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
newsid = sbsec->mntpoint_sid;
- else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
+ else if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
rc = security_transition_sid(sid, dsec->sid,
inode_mode_to_security_class(inode->i_mode),
qstr, &newsid);
@@ -2629,7 +2666,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
isec->initialized = 1;
}
- if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP))
+ if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
return -EOPNOTSUPP;
if (name)
@@ -2831,7 +2868,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
return selinux_inode_setotherxattr(dentry, name);
sbsec = inode->i_sb->s_security;
- if (!(sbsec->flags & SE_SBLABELSUPP))
+ if (!(sbsec->flags & SBLABEL_MNT))
return -EOPNOTSUPP;
if (!inode_owner_or_capable(inode))
@@ -3792,8 +3829,12 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
u32 nlbl_sid;
u32 nlbl_type;
- selinux_skb_xfrm_sid(skb, &xfrm_sid);
- selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
+ err = selinux_skb_xfrm_sid(skb, &xfrm_sid);
+ if (unlikely(err))
+ return -EACCES;
+ err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
+ if (unlikely(err))
+ return -EACCES;
err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
if (unlikely(err)) {
@@ -4247,7 +4288,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
return selinux_sock_rcv_skb_compat(sk, skb, family);
secmark_active = selinux_secmark_enabled();
- peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
+ peerlbl_active = selinux_peerlbl_enabled();
if (!secmark_active && !peerlbl_active)
return 0;
@@ -4629,7 +4670,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
secmark_active = selinux_secmark_enabled();
netlbl_active = netlbl_enabled();
- peerlbl_active = netlbl_active || selinux_xfrm_enabled();
+ peerlbl_active = selinux_peerlbl_enabled();
if (!secmark_active && !peerlbl_active)
return NF_ACCEPT;
@@ -4781,7 +4822,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
return NF_ACCEPT;
#endif
secmark_active = selinux_secmark_enabled();
- peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
+ peerlbl_active = selinux_peerlbl_enabled();
if (!secmark_active && !peerlbl_active)
return NF_ACCEPT;
@@ -5785,7 +5826,8 @@ static struct security_operations selinux_ops = {
.xfrm_policy_clone_security = selinux_xfrm_policy_clone,
.xfrm_policy_free_security = selinux_xfrm_policy_free,
.xfrm_policy_delete_security = selinux_xfrm_policy_delete,
- .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
+ .xfrm_state_alloc = selinux_xfrm_state_alloc,
+ .xfrm_state_alloc_acquire = selinux_xfrm_state_alloc_acquire,
.xfrm_state_free_security = selinux_xfrm_state_free,
.xfrm_state_delete_security = selinux_xfrm_state_delete,
.xfrm_policy_lookup = selinux_xfrm_policy_lookup,
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index aa47bcabb5f6..b1dfe1049450 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -58,8 +58,8 @@ struct superblock_security_struct {
u32 sid; /* SID of file system superblock */
u32 def_sid; /* default SID for labeling */
u32 mntpoint_sid; /* SECURITY_FS_USE_MNTPOINT context for files */
- unsigned int behavior; /* labeling behavior */
- unsigned char flags; /* which mount options were specified */
+ unsigned short behavior; /* labeling behavior */
+ unsigned short flags; /* which mount options were specified */
struct mutex lock;
struct list_head isec_head;
spinlock_t isec_lock;
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 8fd8e18ea340..fe341ae37004 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -45,14 +45,15 @@
/* Mask for just the mount related flags */
#define SE_MNTMASK 0x0f
/* Super block security struct flags for mount options */
+/* BE CAREFUL, these need to be the low order bits for selinux_get_mnt_opts */
#define CONTEXT_MNT 0x01
#define FSCONTEXT_MNT 0x02
#define ROOTCONTEXT_MNT 0x04
#define DEFCONTEXT_MNT 0x08
+#define SBLABEL_MNT 0x10
/* Non-mount related flags */
-#define SE_SBINITIALIZED 0x10
-#define SE_SBPROC 0x20
-#define SE_SBLABELSUPP 0x40
+#define SE_SBINITIALIZED 0x0100
+#define SE_SBPROC 0x0200
#define CONTEXT_STR "context="
#define FSCONTEXT_STR "fscontext="
@@ -68,12 +69,15 @@ extern int selinux_enabled;
enum {
POLICYDB_CAPABILITY_NETPEER,
POLICYDB_CAPABILITY_OPENPERM,
+ POLICYDB_CAPABILITY_REDHAT1,
+ POLICYDB_CAPABILITY_ALWAYSNETWORK,
__POLICYDB_CAPABILITY_MAX
};
#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
extern int selinux_policycap_netpeer;
extern int selinux_policycap_openperm;
+extern int selinux_policycap_alwaysnetwork;
/*
* type_datum properties
@@ -172,8 +176,7 @@ int security_get_allow_unknown(void);
#define SECURITY_FS_USE_NATIVE 7 /* use native label support */
#define SECURITY_FS_USE_MAX 7 /* Highest SECURITY_FS_USE_XXX */
-int security_fs_use(const char *fstype, unsigned int *behavior,
- u32 *sid);
+int security_fs_use(struct super_block *sb);
int security_genfs_sid(const char *fstype, char *name, u16 sclass,
u32 *sid);
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 6713f04e30ba..0dec76c64cf5 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -10,29 +10,21 @@
#include <net/flow.h>
int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
- struct xfrm_user_sec_ctx *sec_ctx);
+ struct xfrm_user_sec_ctx *uctx);
int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
struct xfrm_sec_ctx **new_ctxp);
void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx);
int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx);
int selinux_xfrm_state_alloc(struct xfrm_state *x,
- struct xfrm_user_sec_ctx *sec_ctx, u32 secid);
+ struct xfrm_user_sec_ctx *uctx);
+int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
+ struct xfrm_sec_ctx *polsec, u32 secid);
void selinux_xfrm_state_free(struct xfrm_state *x);
int selinux_xfrm_state_delete(struct xfrm_state *x);
int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
- struct xfrm_policy *xp, const struct flowi *fl);
-
-/*
- * Extract the security blob from the sock (it's actually on the socket)
- */
-static inline struct inode_security_struct *get_sock_isec(struct sock *sk)
-{
- if (!sk->sk_socket)
- return NULL;
-
- return SOCK_INODE(sk->sk_socket)->i_security;
-}
+ struct xfrm_policy *xp,
+ const struct flowi *fl);
#ifdef CONFIG_SECURITY_NETWORK_XFRM
extern atomic_t selinux_xfrm_refcount;
@@ -42,10 +34,10 @@ static inline int selinux_xfrm_enabled(void)
return (atomic_read(&selinux_xfrm_refcount) > 0);
}
-int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb,
- struct common_audit_data *ad);
-int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
- struct common_audit_data *ad, u8 proto);
+int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
+ struct common_audit_data *ad);
+int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
+ struct common_audit_data *ad, u8 proto);
int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
static inline void selinux_xfrm_notify_policyload(void)
@@ -64,19 +56,21 @@ static inline int selinux_xfrm_enabled(void)
return 0;
}
-static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
- struct common_audit_data *ad)
+static inline int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
+ struct common_audit_data *ad)
{
return 0;
}
-static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
- struct common_audit_data *ad, u8 proto)
+static inline int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
+ struct common_audit_data *ad,
+ u8 proto)
{
return 0;
}
-static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
+static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid,
+ int ckall)
{
*sid = SECSID_NULL;
return 0;
@@ -87,10 +81,9 @@ static inline void selinux_xfrm_notify_policyload(void)
}
#endif
-static inline void selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
+static inline int selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
{
- int err = selinux_xfrm_decode_session(skb, sid, 0);
- BUG_ON(err);
+ return selinux_xfrm_decode_session(skb, sid, 0);
}
#endif /* _SELINUX_XFRM_H_ */
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index da4b8b233280..6235d052338b 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -442,8 +442,7 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
sksec->nlbl_state != NLBL_CONNLABELED)
return 0;
- local_bh_disable();
- bh_lock_sock_nested(sk);
+ lock_sock(sk);
/* connected sockets are allowed to disconnect when the address family
* is set to AF_UNSPEC, if that is what is happening we want to reset
@@ -464,7 +463,6 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
sksec->nlbl_state = NLBL_CONNLABELED;
socket_connect_return:
- bh_unlock_sock(sk);
- local_bh_enable();
+ release_sock(sk);
return rc;
}
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
index c5454c0477c3..03a72c32afd7 100644
--- a/security/selinux/netnode.c
+++ b/security/selinux/netnode.c
@@ -166,6 +166,7 @@ static void sel_netnode_insert(struct sel_netnode *node)
break;
default:
BUG();
+ return;
}
/* we need to impose a limit on the growth of the hash table so check
@@ -225,6 +226,7 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
break;
default:
BUG();
+ ret = -EINVAL;
}
if (ret != 0)
goto out;
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index ff427733c290..5122affe06a8 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -44,7 +44,9 @@
/* Policy capability filenames */
static char *policycap_names[] = {
"network_peer_controls",
- "open_perms"
+ "open_perms",
+ "redhat1",
+ "always_check_network"
};
unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index 30f119b1d1ec..820313a04d49 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -213,7 +213,12 @@ netlbl_import_failure:
}
#endif /* CONFIG_NETLABEL */
-int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
+/*
+ * Check to see if all the bits set in e2 are also set in e1. Optionally,
+ * if last_e2bit is non-zero, the highest set bit in e2 cannot exceed
+ * last_e2bit.
+ */
+int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2, u32 last_e2bit)
{
struct ebitmap_node *n1, *n2;
int i;
@@ -223,14 +228,25 @@ int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
n1 = e1->node;
n2 = e2->node;
+
while (n1 && n2 && (n1->startbit <= n2->startbit)) {
if (n1->startbit < n2->startbit) {
n1 = n1->next;
continue;
}
- for (i = 0; i < EBITMAP_UNIT_NUMS; i++) {
+ for (i = EBITMAP_UNIT_NUMS - 1; (i >= 0) && !n2->maps[i]; )
+ i--; /* Skip trailing NULL map entries */
+ if (last_e2bit && (i >= 0)) {
+ u32 lastsetbit = n2->startbit + i * EBITMAP_UNIT_SIZE +
+ __fls(n2->maps[i]);
+ if (lastsetbit > last_e2bit)
+ return 0;
+ }
+
+ while (i >= 0) {
if ((n1->maps[i] & n2->maps[i]) != n2->maps[i])
return 0;
+ i--;
}
n1 = n1->next;
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index 922f8afa89dd..712c8a7b8e8b 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -16,7 +16,13 @@
#include <net/netlabel.h>
-#define EBITMAP_UNIT_NUMS ((32 - sizeof(void *) - sizeof(u32)) \
+#ifdef CONFIG_64BIT
+#define EBITMAP_NODE_SIZE 64
+#else
+#define EBITMAP_NODE_SIZE 32
+#endif
+
+#define EBITMAP_UNIT_NUMS ((EBITMAP_NODE_SIZE-sizeof(void *)-sizeof(u32))\
/ sizeof(unsigned long))
#define EBITMAP_UNIT_SIZE BITS_PER_LONG
#define EBITMAP_SIZE (EBITMAP_UNIT_NUMS * EBITMAP_UNIT_SIZE)
@@ -117,7 +123,7 @@ static inline void ebitmap_node_clr_bit(struct ebitmap_node *n,
int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
-int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2);
+int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2, u32 last_e2bit);
int ebitmap_get_bit(struct ebitmap *e, unsigned long bit);
int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
void ebitmap_destroy(struct ebitmap *e);
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 40de8d3f208e..c85bc1ec040c 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -160,8 +160,6 @@ void mls_sid_to_context(struct context *context,
int mls_level_isvalid(struct policydb *p, struct mls_level *l)
{
struct level_datum *levdatum;
- struct ebitmap_node *node;
- int i;
if (!l->sens || l->sens > p->p_levels.nprim)
return 0;
@@ -170,19 +168,13 @@ int mls_level_isvalid(struct policydb *p, struct mls_level *l)
if (!levdatum)
return 0;
- ebitmap_for_each_positive_bit(&l->cat, node, i) {
- if (i > p->p_cats.nprim)
- return 0;
- if (!ebitmap_get_bit(&levdatum->level->cat, i)) {
- /*
- * Category may not be associated with
- * sensitivity.
- */
- return 0;
- }
- }
-
- return 1;
+ /*
+ * Return 1 iff all the bits set in l->cat are also be set in
+ * levdatum->level->cat and no bit in l->cat is larger than
+ * p->p_cats.nprim.
+ */
+ return ebitmap_contains(&levdatum->level->cat, &l->cat,
+ p->p_cats.nprim);
}
int mls_range_isvalid(struct policydb *p, struct mls_range *r)
diff --git a/security/selinux/ss/mls_types.h b/security/selinux/ss/mls_types.h
index 03bed52a8052..e93648774137 100644
--- a/security/selinux/ss/mls_types.h
+++ b/security/selinux/ss/mls_types.h
@@ -35,7 +35,7 @@ static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2)
static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2)
{
return ((l1->sens >= l2->sens) &&
- ebitmap_contains(&l1->cat, &l2->cat));
+ ebitmap_contains(&l1->cat, &l2->cat, 0));
}
#define mls_level_incomp(l1, l2) \
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index c8adde3aff8f..f6195ebde3c9 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -3203,9 +3203,8 @@ static int range_write_helper(void *key, void *data, void *ptr)
static int range_write(struct policydb *p, void *fp)
{
- size_t nel;
__le32 buf[1];
- int rc;
+ int rc, nel;
struct policy_data pd;
pd.p = p;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index b4feecc3fe01..ee470a0b5c27 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -72,6 +72,7 @@
int selinux_policycap_netpeer;
int selinux_policycap_openperm;
+int selinux_policycap_alwaysnetwork;
static DEFINE_RWLOCK(policy_rwlock);
@@ -1812,6 +1813,8 @@ static void security_load_policycaps(void)
POLICYDB_CAPABILITY_NETPEER);
selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
POLICYDB_CAPABILITY_OPENPERM);
+ selinux_policycap_alwaysnetwork = ebitmap_get_bit(&policydb.policycaps,
+ POLICYDB_CAPABILITY_ALWAYSNETWORK);
}
static int security_preserve_bools(struct policydb *p);
@@ -2323,43 +2326,74 @@ out:
/**
* security_fs_use - Determine how to handle labeling for a filesystem.
- * @fstype: filesystem type
- * @behavior: labeling behavior
- * @sid: SID for filesystem (superblock)
+ * @sb: superblock in question
*/
-int security_fs_use(
- const char *fstype,
- unsigned int *behavior,
- u32 *sid)
+int security_fs_use(struct super_block *sb)
{
int rc = 0;
struct ocontext *c;
+ struct superblock_security_struct *sbsec = sb->s_security;
+ const char *fstype = sb->s_type->name;
+ const char *subtype = (sb->s_subtype && sb->s_subtype[0]) ? sb->s_subtype : NULL;
+ struct ocontext *base = NULL;
read_lock(&policy_rwlock);
- c = policydb.ocontexts[OCON_FSUSE];
- while (c) {
- if (strcmp(fstype, c->u.name) == 0)
+ for (c = policydb.ocontexts[OCON_FSUSE]; c; c = c->next) {
+ char *sub;
+ int baselen;
+
+ baselen = strlen(fstype);
+
+ /* if base does not match, this is not the one */
+ if (strncmp(fstype, c->u.name, baselen))
+ continue;
+
+ /* if there is no subtype, this is the one! */
+ if (!subtype)
+ break;
+
+ /* skip past the base in this entry */
+ sub = c->u.name + baselen;
+
+ /* entry is only a base. save it. keep looking for subtype */
+ if (sub[0] == '\0') {
+ base = c;
+ continue;
+ }
+
+ /* entry is not followed by a subtype, so it is not a match */
+ if (sub[0] != '.')
+ continue;
+
+ /* whew, we found a subtype of this fstype */
+ sub++; /* move past '.' */
+
+ /* exact match of fstype AND subtype */
+ if (!strcmp(subtype, sub))
break;
- c = c->next;
}
+ /* in case we had found an fstype match but no subtype match */
+ if (!c)
+ c = base;
+
if (c) {
- *behavior = c->v.behavior;
+ sbsec->behavior = c->v.behavior;
if (!c->sid[0]) {
rc = sidtab_context_to_sid(&sidtab, &c->context[0],
&c->sid[0]);
if (rc)
goto out;
}
- *sid = c->sid[0];
+ sbsec->sid = c->sid[0];
} else {
- rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, sid);
+ rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, &sbsec->sid);
if (rc) {
- *behavior = SECURITY_FS_USE_NONE;
+ sbsec->behavior = SECURITY_FS_USE_NONE;
rc = 0;
} else {
- *behavior = SECURITY_FS_USE_GENFS;
+ sbsec->behavior = SECURITY_FS_USE_GENFS;
}
}
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index d03081886214..a91d205ec0c6 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -56,7 +56,7 @@
atomic_t selinux_xfrm_refcount = ATOMIC_INIT(0);
/*
- * Returns true if an LSM/SELinux context
+ * Returns true if the context is an LSM/SELinux context.
*/
static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx)
{
@@ -66,7 +66,7 @@ static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx)
}
/*
- * Returns true if the xfrm contains a security blob for SELinux
+ * Returns true if the xfrm contains a security blob for SELinux.
*/
static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
{
@@ -74,48 +74,111 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
}
/*
- * LSM hook implementation that authorizes that a flow can use
- * a xfrm policy rule.
+ * Allocates a xfrm_sec_state and populates it using the supplied security
+ * xfrm_user_sec_ctx context.
*/
-int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
+static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,
+ struct xfrm_user_sec_ctx *uctx)
{
int rc;
- u32 sel_sid;
+ const struct task_security_struct *tsec = current_security();
+ struct xfrm_sec_ctx *ctx = NULL;
+ u32 str_len;
- /* Context sid is either set to label or ANY_ASSOC */
- if (ctx) {
- if (!selinux_authorizable_ctx(ctx))
- return -EINVAL;
-
- sel_sid = ctx->ctx_sid;
- } else
- /*
- * All flows should be treated as polmatch'ing an
- * otherwise applicable "non-labeled" policy. This
- * would prevent inadvertent "leaks".
- */
- return 0;
+ if (ctxp == NULL || uctx == NULL ||
+ uctx->ctx_doi != XFRM_SC_DOI_LSM ||
+ uctx->ctx_alg != XFRM_SC_ALG_SELINUX)
+ return -EINVAL;
- rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION,
- ASSOCIATION__POLMATCH,
- NULL);
+ str_len = uctx->ctx_len;
+ if (str_len >= PAGE_SIZE)
+ return -ENOMEM;
- if (rc == -EACCES)
- return -ESRCH;
+ ctx = kmalloc(sizeof(*ctx) + str_len + 1, GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+ ctx->ctx_doi = XFRM_SC_DOI_LSM;
+ ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
+ ctx->ctx_len = str_len;
+ memcpy(ctx->ctx_str, &uctx[1], str_len);
+ ctx->ctx_str[str_len] = '\0';
+ rc = security_context_to_sid(ctx->ctx_str, str_len, &ctx->ctx_sid);
+ if (rc)
+ goto err;
+
+ rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
+ SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL);
+ if (rc)
+ goto err;
+
+ *ctxp = ctx;
+ atomic_inc(&selinux_xfrm_refcount);
+ return 0;
+
+err:
+ kfree(ctx);
return rc;
}
/*
+ * Free the xfrm_sec_ctx structure.
+ */
+static void selinux_xfrm_free(struct xfrm_sec_ctx *ctx)
+{
+ if (!ctx)
+ return;
+
+ atomic_dec(&selinux_xfrm_refcount);
+ kfree(ctx);
+}
+
+/*
+ * Authorize the deletion of a labeled SA or policy rule.
+ */
+static int selinux_xfrm_delete(struct xfrm_sec_ctx *ctx)
+{
+ const struct task_security_struct *tsec = current_security();
+
+ if (!ctx)
+ return 0;
+
+ return avc_has_perm(tsec->sid, ctx->ctx_sid,
+ SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
+ NULL);
+}
+
+/*
+ * LSM hook implementation that authorizes that a flow can use a xfrm policy
+ * rule.
+ */
+int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
+{
+ int rc;
+
+ /* All flows should be treated as polmatch'ing an otherwise applicable
+ * "non-labeled" policy. This would prevent inadvertent "leaks". */
+ if (!ctx)
+ return 0;
+
+ /* Context sid is either set to label or ANY_ASSOC */
+ if (!selinux_authorizable_ctx(ctx))
+ return -EINVAL;
+
+ rc = avc_has_perm(fl_secid, ctx->ctx_sid,
+ SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, NULL);
+ return (rc == -EACCES ? -ESRCH : rc);
+}
+
+/*
* LSM hook implementation that authorizes that a state matches
* the given policy, flow combo.
*/
-
-int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp,
- const struct flowi *fl)
+int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
+ struct xfrm_policy *xp,
+ const struct flowi *fl)
{
u32 state_sid;
- int rc;
if (!xp->security)
if (x->security)
@@ -138,187 +201,80 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
if (fl->flowi_secid != state_sid)
return 0;
- rc = avc_has_perm(fl->flowi_secid, state_sid, SECCLASS_ASSOCIATION,
- ASSOCIATION__SENDTO,
- NULL)? 0:1;
-
- /*
- * We don't need a separate SA Vs. policy polmatch check
- * since the SA is now of the same label as the flow and
- * a flow Vs. policy polmatch check had already happened
- * in selinux_xfrm_policy_lookup() above.
- */
-
- return rc;
+ /* We don't need a separate SA Vs. policy polmatch check since the SA
+ * is now of the same label as the flow and a flow Vs. policy polmatch
+ * check had already happened in selinux_xfrm_policy_lookup() above. */
+ return (avc_has_perm(fl->flowi_secid, state_sid,
+ SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO,
+ NULL) ? 0 : 1);
}
/*
* LSM hook implementation that checks and/or returns the xfrm sid for the
* incoming packet.
*/
-
int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
{
+ u32 sid_session = SECSID_NULL;
struct sec_path *sp;
- *sid = SECSID_NULL;
-
if (skb == NULL)
- return 0;
+ goto out;
sp = skb->sp;
if (sp) {
- int i, sid_set = 0;
+ int i;
- for (i = sp->len-1; i >= 0; i--) {
+ for (i = sp->len - 1; i >= 0; i--) {
struct xfrm_state *x = sp->xvec[i];
if (selinux_authorizable_xfrm(x)) {
struct xfrm_sec_ctx *ctx = x->security;
- if (!sid_set) {
- *sid = ctx->ctx_sid;
- sid_set = 1;
-
+ if (sid_session == SECSID_NULL) {
+ sid_session = ctx->ctx_sid;
if (!ckall)
- break;
- } else if (*sid != ctx->ctx_sid)
+ goto out;
+ } else if (sid_session != ctx->ctx_sid) {
+ *sid = SECSID_NULL;
return -EINVAL;
+ }
}
}
}
- return 0;
-}
-
-/*
- * Security blob allocation for xfrm_policy and xfrm_state
- * CTX does not have a meaningful value on input
- */
-static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
- struct xfrm_user_sec_ctx *uctx, u32 sid)
-{
- int rc = 0;
- const struct task_security_struct *tsec = current_security();
- struct xfrm_sec_ctx *ctx = NULL;
- char *ctx_str = NULL;
- u32 str_len;
-
- BUG_ON(uctx && sid);
-
- if (!uctx)
- goto not_from_user;
-
- if (uctx->ctx_alg != XFRM_SC_ALG_SELINUX)
- return -EINVAL;
-
- str_len = uctx->ctx_len;
- if (str_len >= PAGE_SIZE)
- return -ENOMEM;
-
- *ctxp = ctx = kmalloc(sizeof(*ctx) +
- str_len + 1,
- GFP_KERNEL);
-
- if (!ctx)
- return -ENOMEM;
-
- ctx->ctx_doi = uctx->ctx_doi;
- ctx->ctx_len = str_len;
- ctx->ctx_alg = uctx->ctx_alg;
-
- memcpy(ctx->ctx_str,
- uctx+1,
- str_len);
- ctx->ctx_str[str_len] = 0;
- rc = security_context_to_sid(ctx->ctx_str,
- str_len,
- &ctx->ctx_sid);
-
- if (rc)
- goto out;
-
- /*
- * Does the subject have permission to set security context?
- */
- rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
- SECCLASS_ASSOCIATION,
- ASSOCIATION__SETCONTEXT, NULL);
- if (rc)
- goto out;
-
- return rc;
-
-not_from_user:
- rc = security_sid_to_context(sid, &ctx_str, &str_len);
- if (rc)
- goto out;
-
- *ctxp = ctx = kmalloc(sizeof(*ctx) +
- str_len,
- GFP_ATOMIC);
-
- if (!ctx) {
- rc = -ENOMEM;
- goto out;
- }
-
- ctx->ctx_doi = XFRM_SC_DOI_LSM;
- ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
- ctx->ctx_sid = sid;
- ctx->ctx_len = str_len;
- memcpy(ctx->ctx_str,
- ctx_str,
- str_len);
-
- goto out2;
-
out:
- *ctxp = NULL;
- kfree(ctx);
-out2:
- kfree(ctx_str);
- return rc;
+ *sid = sid_session;
+ return 0;
}
/*
- * LSM hook implementation that allocs and transfers uctx spec to
- * xfrm_policy.
+ * LSM hook implementation that allocs and transfers uctx spec to xfrm_policy.
*/
int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
struct xfrm_user_sec_ctx *uctx)
{
- int err;
-
- BUG_ON(!uctx);
-
- err = selinux_xfrm_sec_ctx_alloc(ctxp, uctx, 0);
- if (err == 0)
- atomic_inc(&selinux_xfrm_refcount);
-
- return err;
+ return selinux_xfrm_alloc_user(ctxp, uctx);
}
-
/*
- * LSM hook implementation that copies security data structure from old to
- * new for policy cloning.
+ * LSM hook implementation that copies security data structure from old to new
+ * for policy cloning.
*/
int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
struct xfrm_sec_ctx **new_ctxp)
{
struct xfrm_sec_ctx *new_ctx;
- if (old_ctx) {
- new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len,
- GFP_ATOMIC);
- if (!new_ctx)
- return -ENOMEM;
+ if (!old_ctx)
+ return 0;
+
+ new_ctx = kmemdup(old_ctx, sizeof(*old_ctx) + old_ctx->ctx_len,
+ GFP_ATOMIC);
+ if (!new_ctx)
+ return -ENOMEM;
+ atomic_inc(&selinux_xfrm_refcount);
+ *new_ctxp = new_ctx;
- memcpy(new_ctx, old_ctx, sizeof(*new_ctx));
- memcpy(new_ctx->ctx_str, old_ctx->ctx_str, new_ctx->ctx_len);
- atomic_inc(&selinux_xfrm_refcount);
- *new_ctxp = new_ctx;
- }
return 0;
}
@@ -327,8 +283,7 @@ int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
*/
void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
{
- atomic_dec(&selinux_xfrm_refcount);
- kfree(ctx);
+ selinux_xfrm_free(ctx);
}
/*
@@ -336,31 +291,55 @@ void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
*/
int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
{
- const struct task_security_struct *tsec = current_security();
-
- if (!ctx)
- return 0;
+ return selinux_xfrm_delete(ctx);
+}
- return avc_has_perm(tsec->sid, ctx->ctx_sid,
- SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
- NULL);
+/*
+ * LSM hook implementation that allocates a xfrm_sec_state, populates it using
+ * the supplied security context, and assigns it to the xfrm_state.
+ */
+int selinux_xfrm_state_alloc(struct xfrm_state *x,
+ struct xfrm_user_sec_ctx *uctx)
+{
+ return selinux_xfrm_alloc_user(&x->security, uctx);
}
/*
- * LSM hook implementation that allocs and transfers sec_ctx spec to
- * xfrm_state.
+ * LSM hook implementation that allocates a xfrm_sec_state and populates based
+ * on a secid.
*/
-int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx,
- u32 secid)
+int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
+ struct xfrm_sec_ctx *polsec, u32 secid)
{
- int err;
+ int rc;
+ struct xfrm_sec_ctx *ctx;
+ char *ctx_str = NULL;
+ int str_len;
+
+ if (!polsec)
+ return 0;
- BUG_ON(!x);
+ if (secid == 0)
+ return -EINVAL;
- err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, secid);
- if (err == 0)
- atomic_inc(&selinux_xfrm_refcount);
- return err;
+ rc = security_sid_to_context(secid, &ctx_str, &str_len);
+ if (rc)
+ return rc;
+
+ ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->ctx_doi = XFRM_SC_DOI_LSM;
+ ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
+ ctx->ctx_sid = secid;
+ ctx->ctx_len = str_len;
+ memcpy(ctx->ctx_str, ctx_str, str_len);
+ kfree(ctx_str);
+
+ x->security = ctx;
+ atomic_inc(&selinux_xfrm_refcount);
+ return 0;
}
/*
@@ -368,24 +347,15 @@ int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uct
*/
void selinux_xfrm_state_free(struct xfrm_state *x)
{
- atomic_dec(&selinux_xfrm_refcount);
- kfree(x->security);
+ selinux_xfrm_free(x->security);
}
- /*
- * LSM hook implementation that authorizes deletion of labeled SAs.
- */
+/*
+ * LSM hook implementation that authorizes deletion of labeled SAs.
+ */
int selinux_xfrm_state_delete(struct xfrm_state *x)
{
- const struct task_security_struct *tsec = current_security();
- struct xfrm_sec_ctx *ctx = x->security;
-
- if (!ctx)
- return 0;
-
- return avc_has_perm(tsec->sid, ctx->ctx_sid,
- SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
- NULL);
+ return selinux_xfrm_delete(x->security);
}
/*
@@ -395,14 +365,12 @@ int selinux_xfrm_state_delete(struct xfrm_state *x)
* we need to check for unlabelled access since this may not have
* gone thru the IPSec process.
*/
-int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
- struct common_audit_data *ad)
+int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
+ struct common_audit_data *ad)
{
- int i, rc = 0;
- struct sec_path *sp;
- u32 sel_sid = SECINITSID_UNLABELED;
-
- sp = skb->sp;
+ int i;
+ struct sec_path *sp = skb->sp;
+ u32 peer_sid = SECINITSID_UNLABELED;
if (sp) {
for (i = 0; i < sp->len; i++) {
@@ -410,23 +378,17 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
if (x && selinux_authorizable_xfrm(x)) {
struct xfrm_sec_ctx *ctx = x->security;
- sel_sid = ctx->ctx_sid;
+ peer_sid = ctx->ctx_sid;
break;
}
}
}
- /*
- * This check even when there's no association involved is
- * intended, according to Trent Jaeger, to make sure a
- * process can't engage in non-ipsec communication unless
- * explicitly allowed by policy.
- */
-
- rc = avc_has_perm(isec_sid, sel_sid, SECCLASS_ASSOCIATION,
- ASSOCIATION__RECVFROM, ad);
-
- return rc;
+ /* This check even when there's no association involved is intended,
+ * according to Trent Jaeger, to make sure a process can't engage in
+ * non-IPsec communication unless explicitly allowed by policy. */
+ return avc_has_perm(sk_sid, peer_sid,
+ SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, ad);
}
/*
@@ -436,49 +398,38 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
* If we do have a authorizable security association, then it has already been
* checked in the selinux_xfrm_state_pol_flow_match hook above.
*/
-int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
- struct common_audit_data *ad, u8 proto)
+int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
+ struct common_audit_data *ad, u8 proto)
{
struct dst_entry *dst;
- int rc = 0;
-
- dst = skb_dst(skb);
-
- if (dst) {
- struct dst_entry *dst_test;
-
- for (dst_test = dst; dst_test != NULL;
- dst_test = dst_test->child) {
- struct xfrm_state *x = dst_test->xfrm;
-
- if (x && selinux_authorizable_xfrm(x))
- goto out;
- }
- }
switch (proto) {
case IPPROTO_AH:
case IPPROTO_ESP:
case IPPROTO_COMP:
- /*
- * We should have already seen this packet once before
- * it underwent xfrm(s). No need to subject it to the
- * unlabeled check.
- */
- goto out;
+ /* We should have already seen this packet once before it
+ * underwent xfrm(s). No need to subject it to the unlabeled
+ * check. */
+ return 0;
default:
break;
}
- /*
- * This check even when there's no association involved is
- * intended, according to Trent Jaeger, to make sure a
- * process can't engage in non-ipsec communication unless
- * explicitly allowed by policy.
- */
+ dst = skb_dst(skb);
+ if (dst) {
+ struct dst_entry *iter;
- rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
- ASSOCIATION__SENDTO, ad);
-out:
- return rc;
+ for (iter = dst; iter != NULL; iter = iter->child) {
+ struct xfrm_state *x = iter->xfrm;
+
+ if (x && selinux_authorizable_xfrm(x))
+ return 0;
+ }
+ }
+
+ /* This check even when there's no association involved is intended,
+ * according to Trent Jaeger, to make sure a process can't engage in
+ * non-IPsec communication unless explicitly allowed by policy. */
+ return avc_has_perm(sk_sid, SECINITSID_UNLABELED,
+ SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, ad);
}
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index 98969541cbcc..bea523a5d852 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -139,6 +139,18 @@ static int snd_compr_open(struct inode *inode, struct file *f)
static int snd_compr_free(struct inode *inode, struct file *f)
{
struct snd_compr_file *data = f->private_data;
+ struct snd_compr_runtime *runtime = data->stream.runtime;
+
+ switch (runtime->state) {
+ case SNDRV_PCM_STATE_RUNNING:
+ case SNDRV_PCM_STATE_DRAINING:
+ case SNDRV_PCM_STATE_PAUSED:
+ data->stream.ops->trigger(&data->stream, SNDRV_PCM_TRIGGER_STOP);
+ break;
+ default:
+ break;
+ }
+
data->stream.ops->free(&data->stream);
kfree(data->stream.runtime->buffer);
kfree(data->stream.runtime);
@@ -837,7 +849,8 @@ static int snd_compress_dev_disconnect(struct snd_device *device)
struct snd_compr *compr;
compr = device->device_data;
- snd_unregister_device(compr->direction, compr->card, compr->device);
+ snd_unregister_device(SNDRV_DEVICE_TYPE_COMPRESS, compr->card,
+ compr->device);
return 0;
}
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c
index ea995af6d049..4b08b25a4db8 100644
--- a/sound/firewire/amdtp.c
+++ b/sound/firewire/amdtp.c
@@ -268,7 +268,7 @@ static void amdtp_write_s32(struct amdtp_out_stream *s,
channels = s->pcm_channels;
src = (void *)runtime->dma_area +
- s->pcm_buffer_pointer * (runtime->frame_bits / 8);
+ frames_to_bytes(runtime, s->pcm_buffer_pointer);
remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
frame_step = s->data_block_quadlets - channels;
@@ -294,7 +294,7 @@ static void amdtp_write_s16(struct amdtp_out_stream *s,
channels = s->pcm_channels;
src = (void *)runtime->dma_area +
- s->pcm_buffer_pointer * (runtime->frame_bits / 8);
+ frames_to_bytes(runtime, s->pcm_buffer_pointer);
remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
frame_step = s->data_block_quadlets - channels;
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index dc632cdc3870..5f2acd35dcb9 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -1913,6 +1913,7 @@ static int snd_asihpi_tuner_band_put(struct snd_kcontrol *kcontrol,
struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol);
*/
u32 h_control = kcontrol->private_value;
+ unsigned int idx;
u16 band;
u16 tuner_bands[HPI_TUNER_BAND_LAST];
u32 num_bands = 0;
@@ -1920,7 +1921,10 @@ static int snd_asihpi_tuner_band_put(struct snd_kcontrol *kcontrol,
num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands,
HPI_TUNER_BAND_LAST);
- band = tuner_bands[ucontrol->value.enumerated.item[0]];
+ idx = ucontrol->value.enumerated.item[0];
+ if (idx >= ARRAY_SIZE(tuner_bands))
+ idx = ARRAY_SIZE(tuner_bands) - 1;
+ band = tuner_bands[idx];
hpi_handle_error(hpi_tuner_set_band(h_control, band));
return 1;
@@ -2383,7 +2387,8 @@ static int snd_asihpi_clksrc_put(struct snd_kcontrol *kcontrol,
struct snd_card_asihpi *asihpi =
(struct snd_card_asihpi *)(kcontrol->private_data);
struct clk_cache *clkcache = &asihpi->cc;
- int change, item;
+ unsigned int item;
+ int change;
u32 h_control = kcontrol->private_value;
change = 1;
diff --git a/sound/pci/au88x0/au88x0_synth.c b/sound/pci/au88x0/au88x0_synth.c
index 8bef47311e45..922a84bba2ef 100644
--- a/sound/pci/au88x0/au88x0_synth.c
+++ b/sound/pci/au88x0/au88x0_synth.c
@@ -219,7 +219,6 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt,
*/
hwwrite(vortex->mmio, WT_RUN(wt), val);
return 0xc;
- break;
case 1: /* param 0 */
/*
printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
@@ -227,7 +226,6 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt,
*/
hwwrite(vortex->mmio, WT_PARM(wt, 0), val);
return 0xc;
- break;
case 2: /* param 1 */
/*
printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
@@ -235,7 +233,6 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt,
*/
hwwrite(vortex->mmio, WT_PARM(wt, 1), val);
return 0xc;
- break;
case 3: /* param 2 */
/*
printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
@@ -243,7 +240,6 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt,
*/
hwwrite(vortex->mmio, WT_PARM(wt, 2), val);
return 0xc;
- break;
case 4: /* param 3 */
/*
printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
@@ -251,7 +247,6 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt,
*/
hwwrite(vortex->mmio, WT_PARM(wt, 3), val);
return 0xc;
- break;
case 6: /* mute */
/*
printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
@@ -259,20 +254,17 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt,
*/
hwwrite(vortex->mmio, WT_MUTE(wt), val);
return 0xc;
- break;
case 0xb:
- { /* delay */
- /*
- printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
- WT_DELAY(wt,0), (int)val);
- */
- hwwrite(vortex->mmio, WT_DELAY(wt, 3), val);
- hwwrite(vortex->mmio, WT_DELAY(wt, 2), val);
- hwwrite(vortex->mmio, WT_DELAY(wt, 1), val);
- hwwrite(vortex->mmio, WT_DELAY(wt, 0), val);
- return 0xc;
- }
- break;
+ /* delay */
+ /*
+ printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
+ WT_DELAY(wt,0), (int)val);
+ */
+ hwwrite(vortex->mmio, WT_DELAY(wt, 3), val);
+ hwwrite(vortex->mmio, WT_DELAY(wt, 2), val);
+ hwwrite(vortex->mmio, WT_DELAY(wt, 1), val);
+ hwwrite(vortex->mmio, WT_DELAY(wt, 0), val);
+ return 0xc;
/* Global WT block parameters */
case 5: /* sramp */
ecx = WT_SRAMP(wt);
@@ -291,7 +283,6 @@ vortex_wt_SetReg(vortex_t * vortex, unsigned char reg, int wt,
break;
default:
return 0;
- break;
}
/*
printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", ecx, (int)val);
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index c8e121611593..1aef7128f7ca 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -715,14 +715,14 @@ snd_azf3328_mixer_ac97_read(struct snd_ac97 *ac97, unsigned short reg_ac97)
const struct snd_azf3328 *chip = ac97->private_data;
unsigned short reg_azf = snd_azf3328_mixer_ac97_map_reg_idx(reg_ac97);
unsigned short reg_val = 0;
- bool unsupported = 0;
+ bool unsupported = false;
snd_azf3328_dbgmixer(
"snd_azf3328_mixer_ac97_read reg_ac97 %u\n",
reg_ac97
);
if (reg_azf & AZF_AC97_REG_UNSUPPORTED)
- unsupported = 1;
+ unsupported = true;
else {
if (reg_azf & AZF_AC97_REG_REAL_IO_READ)
reg_val = snd_azf3328_mixer_inw(chip,
@@ -759,7 +759,7 @@ snd_azf3328_mixer_ac97_read(struct snd_ac97 *ac97, unsigned short reg_ac97)
reg_val = azf_emulated_ac97_vendor_id & 0xffff;
break;
default:
- unsupported = 1;
+ unsupported = true;
break;
}
}
@@ -776,14 +776,14 @@ snd_azf3328_mixer_ac97_write(struct snd_ac97 *ac97,
{
const struct snd_azf3328 *chip = ac97->private_data;
unsigned short reg_azf = snd_azf3328_mixer_ac97_map_reg_idx(reg_ac97);
- bool unsupported = 0;
+ bool unsupported = false;
snd_azf3328_dbgmixer(
"snd_azf3328_mixer_ac97_write reg_ac97 %u val %u\n",
reg_ac97, val
);
if (reg_azf & AZF_AC97_REG_UNSUPPORTED)
- unsupported = 1;
+ unsupported = true;
else {
if (reg_azf & AZF_AC97_REG_REAL_IO_WRITE)
snd_azf3328_mixer_outw(
@@ -808,7 +808,7 @@ snd_azf3328_mixer_ac97_write(struct snd_ac97 *ac97,
*/
break;
default:
- unsupported = 1;
+ unsupported = true;
break;
}
}
@@ -1559,7 +1559,7 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
struct snd_azf3328_codec_data *codec = runtime->private_data;
int result = 0;
u16 flags1;
- bool previously_muted = 0;
+ bool previously_muted = false;
bool is_main_mixer_playback_codec = (AZF_CODEC_PLAYBACK == codec->type);
snd_azf3328_dbgcalls("snd_azf3328_pcm_trigger cmd %d\n", cmd);
diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c
index 0c00eb4088ef..84f86bf63b8f 100644
--- a/sound/pci/ctxfi/ctdaio.c
+++ b/sound/pci/ctxfi/ctdaio.c
@@ -33,7 +33,7 @@ struct daio_rsc_idx {
unsigned short right;
};
-struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = {
+static struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = {
[LINEO1] = {.left = 0x00, .right = 0x01},
[LINEO2] = {.left = 0x18, .right = 0x19},
[LINEO3] = {.left = 0x08, .right = 0x09},
@@ -44,7 +44,7 @@ struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = {
[SPDIFI1] = {.left = 0x95, .right = 0x9d},
};
-struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = {
+static struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = {
[LINEO1] = {.left = 0x40, .right = 0x41},
[LINEO2] = {.left = 0x60, .right = 0x61},
[LINEO3] = {.left = 0x50, .right = 0x51},
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 6e9876f27d95..54d14793725a 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -759,7 +759,7 @@ struct ca0132_spec {
/*
* CA0132 codec access
*/
-unsigned int codec_send_command(struct hda_codec *codec, hda_nid_t nid,
+static unsigned int codec_send_command(struct hda_codec *codec, hda_nid_t nid,
unsigned int verb, unsigned int parm, unsigned int *res)
{
unsigned int response;
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 3d8cd04455a6..7ea0245fc6bd 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1149,32 +1149,43 @@ static int hdmi_choose_cvt(struct hda_codec *codec,
}
static void haswell_config_cvts(struct hda_codec *codec,
- int pin_id, int mux_id)
+ hda_nid_t pin_nid, int mux_idx)
{
struct hdmi_spec *spec = codec->spec;
- struct hdmi_spec_per_pin *per_pin;
- int pin_idx, mux_idx;
- int curr;
- int err;
+ hda_nid_t nid, end_nid;
+ int cvt_idx, curr;
+ struct hdmi_spec_per_cvt *per_cvt;
- for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
- per_pin = get_pin(spec, pin_idx);
+ /* configure all pins, including "no physical connection" ones */
+ end_nid = codec->start_nid + codec->num_nodes;
+ for (nid = codec->start_nid; nid < end_nid; nid++) {
+ unsigned int wid_caps = get_wcaps(codec, nid);
+ unsigned int wid_type = get_wcaps_type(wid_caps);
- if (pin_idx == pin_id)
+ if (wid_type != AC_WID_PIN)
continue;
- curr = snd_hda_codec_read(codec, per_pin->pin_nid, 0,
+ if (nid == pin_nid)
+ continue;
+
+ curr = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_CONNECT_SEL, 0);
+ if (curr != mux_idx)
+ continue;
- /* Choose another unused converter */
- if (curr == mux_id) {
- err = hdmi_choose_cvt(codec, pin_idx, NULL, &mux_idx);
- if (err < 0)
- return;
- snd_printdd("HDMI: choose converter %d for pin %d\n", mux_idx, pin_idx);
- snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
+ /* choose an unassigned converter. The conveters in the
+ * connection list are in the same order as in the codec.
+ */
+ for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) {
+ per_cvt = get_cvt(spec, cvt_idx);
+ if (!per_cvt->assigned) {
+ snd_printdd("choose cvt %d for pin nid %d\n",
+ cvt_idx, nid);
+ snd_hda_codec_write_cache(codec, nid, 0,
AC_VERB_SET_CONNECT_SEL,
- mux_idx);
+ cvt_idx);
+ break;
+ }
}
}
}
@@ -1216,7 +1227,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
/* configure unused pins to choose other converters */
if (is_haswell(codec))
- haswell_config_cvts(codec, pin_idx, mux_idx);
+ haswell_config_cvts(codec, per_pin->pin_nid, mux_idx);
snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid);
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 3cde55b753e2..2907e68150cb 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -3996,7 +3996,6 @@ static int hdspm_tco_sync_check(struct hdspm *hdspm)
return 1;
}
return 0;
- break;
case AES32:
status = hdspm_read(hdspm, HDSPM_statusRegister);
if (status & HDSPM_tcoLockAes) {
@@ -4006,9 +4005,6 @@ static int hdspm_tco_sync_check(struct hdspm *hdspm)
return 1;
}
return 0;
-
- break;
-
case RayDAT:
case AIO:
status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
@@ -4018,7 +4014,6 @@ static int hdspm_tco_sync_check(struct hdspm *hdspm)
if (status & 0x4000000)
return 1; /* Lock */
return 0; /* No signal */
- break;
default:
break;
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 61a64d281905..8b9e70105dd2 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,5 +1,5 @@
snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
-snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o
+snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o soc-devres.o
ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
snd-soc-core-objs += soc-generic-dmaengine-pcm.o
diff --git a/sound/soc/blackfin/bf6xx-i2s.c b/sound/soc/blackfin/bf6xx-i2s.c
index c02405cc007d..5810a0603f2f 100644
--- a/sound/soc/blackfin/bf6xx-i2s.c
+++ b/sound/soc/blackfin/bf6xx-i2s.c
@@ -88,6 +88,7 @@ static int bfin_i2s_hw_params(struct snd_pcm_substream *substream,
case SNDRV_PCM_FORMAT_S8:
param.spctl |= 0x70;
sport->wdsize = 1;
+ break;
case SNDRV_PCM_FORMAT_S16_LE:
param.spctl |= 0xf0;
sport->wdsize = 2;
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
index 8af04343cc1a..75d0ad5d2dcb 100644
--- a/sound/soc/codecs/88pm860x-codec.c
+++ b/sound/soc/codecs/88pm860x-codec.c
@@ -16,6 +16,7 @@
#include <linux/mfd/88pm860x.h>
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/regmap.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -140,6 +141,7 @@ struct pm860x_priv {
unsigned int filter;
struct snd_soc_codec *codec;
struct i2c_client *i2c;
+ struct regmap *regmap;
struct pm860x_chip *chip;
struct pm860x_det det;
@@ -269,48 +271,6 @@ static struct st_gain st_table[] = {
{ -86, 29, 0}, { -56, 30, 0}, { -28, 31, 0}, { 0, 0, 0},
};
-static int pm860x_volatile(unsigned int reg)
-{
- BUG_ON(reg >= REG_CACHE_SIZE);
-
- switch (reg) {
- case PM860X_AUDIO_SUPPLIES_2:
- return 1;
- }
-
- return 0;
-}
-
-static unsigned int pm860x_read_reg_cache(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- unsigned char *cache = codec->reg_cache;
-
- BUG_ON(reg >= REG_CACHE_SIZE);
-
- if (pm860x_volatile(reg))
- return cache[reg];
-
- reg += REG_CACHE_BASE;
-
- return pm860x_reg_read(codec->control_data, reg);
-}
-
-static int pm860x_write_reg_cache(struct snd_soc_codec *codec,
- unsigned int reg, unsigned int value)
-{
- unsigned char *cache = codec->reg_cache;
-
- BUG_ON(reg >= REG_CACHE_SIZE);
-
- if (!pm860x_volatile(reg))
- cache[reg] = (unsigned char)value;
-
- reg += REG_CACHE_BASE;
-
- return pm860x_reg_write(codec->control_data, reg, value);
-}
-
static int snd_soc_get_volsw_2r_st(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -349,6 +309,9 @@ static int snd_soc_put_volsw_2r_st(struct snd_kcontrol *kcontrol,
val = ucontrol->value.integer.value[0];
val2 = ucontrol->value.integer.value[1];
+ if (val >= ARRAY_SIZE(st_table) || val2 >= ARRAY_SIZE(st_table))
+ return -EINVAL;
+
err = snd_soc_update_bits(codec, reg, 0x3f, st_table[val].m);
if (err < 0)
return err;
@@ -1166,6 +1129,7 @@ static int pm860x_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
static int pm860x_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
+ struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
int data;
switch (level) {
@@ -1179,17 +1143,17 @@ static int pm860x_set_bias_level(struct snd_soc_codec *codec,
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
/* Enable Audio PLL & Audio section */
data = AUDIO_PLL | AUDIO_SECTION_ON;
- pm860x_reg_write(codec->control_data, REG_MISC2, data);
+ pm860x_reg_write(pm860x->i2c, REG_MISC2, data);
udelay(300);
data = AUDIO_PLL | AUDIO_SECTION_RESET
| AUDIO_SECTION_ON;
- pm860x_reg_write(codec->control_data, REG_MISC2, data);
+ pm860x_reg_write(pm860x->i2c, REG_MISC2, data);
}
break;
case SND_SOC_BIAS_OFF:
data = AUDIO_PLL | AUDIO_SECTION_RESET | AUDIO_SECTION_ON;
- pm860x_set_bits(codec->control_data, REG_MISC2, data, 0);
+ pm860x_set_bits(pm860x->i2c, REG_MISC2, data, 0);
break;
}
codec->dapm.bias_level = level;
@@ -1319,17 +1283,17 @@ int pm860x_hs_jack_detect(struct snd_soc_codec *codec,
pm860x->det.lo_shrt = lo_shrt;
if (det & SND_JACK_HEADPHONE)
- pm860x_set_bits(codec->control_data, REG_HS_DET,
+ pm860x_set_bits(pm860x->i2c, REG_HS_DET,
EN_HS_DET, EN_HS_DET);
/* headset short detect */
if (hs_shrt) {
data = CLR_SHORT_HS2 | CLR_SHORT_HS1;
- pm860x_set_bits(codec->control_data, REG_SHORTS, data, data);
+ pm860x_set_bits(pm860x->i2c, REG_SHORTS, data, data);
}
/* Lineout short detect */
if (lo_shrt) {
data = CLR_SHORT_LO2 | CLR_SHORT_LO1;
- pm860x_set_bits(codec->control_data, REG_SHORTS, data, data);
+ pm860x_set_bits(pm860x->i2c, REG_SHORTS, data, data);
}
/* sync status */
@@ -1347,7 +1311,7 @@ int pm860x_mic_jack_detect(struct snd_soc_codec *codec,
pm860x->det.mic_det = det;
if (det & SND_JACK_MICROPHONE)
- pm860x_set_bits(codec->control_data, REG_MIC_DET,
+ pm860x_set_bits(pm860x->i2c, REG_MIC_DET,
MICDET_MASK, MICDET_MASK);
/* sync status */
@@ -1363,7 +1327,7 @@ static int pm860x_probe(struct snd_soc_codec *codec)
pm860x->codec = codec;
- codec->control_data = pm860x->i2c;
+ codec->control_data = pm860x->regmap;
for (i = 0; i < 4; i++) {
ret = request_threaded_irq(pm860x->irq[i], NULL,
@@ -1377,14 +1341,6 @@ static int pm860x_probe(struct snd_soc_codec *codec)
pm860x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- ret = pm860x_bulk_read(codec->control_data, REG_CACHE_BASE,
- REG_CACHE_SIZE, codec->reg_cache);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to fill register cache: %d\n",
- ret);
- goto out;
- }
-
return 0;
out:
@@ -1407,10 +1363,6 @@ static int pm860x_remove(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_pm860x = {
.probe = pm860x_probe,
.remove = pm860x_remove,
- .read = pm860x_read_reg_cache,
- .write = pm860x_write_reg_cache,
- .reg_cache_size = REG_CACHE_SIZE,
- .reg_word_size = sizeof(u8),
.set_bias_level = pm860x_set_bias_level,
.controls = pm860x_snd_controls,
@@ -1436,6 +1388,8 @@ static int pm860x_codec_probe(struct platform_device *pdev)
pm860x->chip = chip;
pm860x->i2c = (chip->id == CHIP_PM8607) ? chip->client
: chip->companion;
+ pm860x->regmap = (chip->id == CHIP_PM8607) ? chip->regmap
+ : chip->regmap_companion;
platform_set_drvdata(pdev, pm860x);
for (i = 0; i < 4; i++) {
diff --git a/sound/soc/codecs/88pm860x-codec.h b/sound/soc/codecs/88pm860x-codec.h
index 3364ba4a3607..f7282f4f4a79 100644
--- a/sound/soc/codecs/88pm860x-codec.h
+++ b/sound/soc/codecs/88pm860x-codec.h
@@ -12,67 +12,66 @@
#ifndef __88PM860X_H
#define __88PM860X_H
-/* The offset of these registers are 0xb0 */
-#define PM860X_PCM_IFACE_1 0x00
-#define PM860X_PCM_IFACE_2 0x01
-#define PM860X_PCM_IFACE_3 0x02
-#define PM860X_PCM_RATE 0x03
-#define PM860X_EC_PATH 0x04
-#define PM860X_SIDETONE_L_GAIN 0x05
-#define PM860X_SIDETONE_R_GAIN 0x06
-#define PM860X_SIDETONE_SHIFT 0x07
-#define PM860X_ADC_OFFSET_1 0x08
-#define PM860X_ADC_OFFSET_2 0x09
-#define PM860X_DMIC_DELAY 0x0a
+#define PM860X_PCM_IFACE_1 0xb0
+#define PM860X_PCM_IFACE_2 0xb1
+#define PM860X_PCM_IFACE_3 0xb2
+#define PM860X_PCM_RATE 0xb3
+#define PM860X_EC_PATH 0xb4
+#define PM860X_SIDETONE_L_GAIN 0xb5
+#define PM860X_SIDETONE_R_GAIN 0xb6
+#define PM860X_SIDETONE_SHIFT 0xb7
+#define PM860X_ADC_OFFSET_1 0xb8
+#define PM860X_ADC_OFFSET_2 0xb9
+#define PM860X_DMIC_DELAY 0xba
-#define PM860X_I2S_IFACE_1 0x0b
-#define PM860X_I2S_IFACE_2 0x0c
-#define PM860X_I2S_IFACE_3 0x0d
-#define PM860X_I2S_IFACE_4 0x0e
-#define PM860X_EQUALIZER_N0_1 0x0f
-#define PM860X_EQUALIZER_N0_2 0x10
-#define PM860X_EQUALIZER_N1_1 0x11
-#define PM860X_EQUALIZER_N1_2 0x12
-#define PM860X_EQUALIZER_D1_1 0x13
-#define PM860X_EQUALIZER_D1_2 0x14
-#define PM860X_LOFI_GAIN_LEFT 0x15
-#define PM860X_LOFI_GAIN_RIGHT 0x16
-#define PM860X_HIFIL_GAIN_LEFT 0x17
-#define PM860X_HIFIL_GAIN_RIGHT 0x18
-#define PM860X_HIFIR_GAIN_LEFT 0x19
-#define PM860X_HIFIR_GAIN_RIGHT 0x1a
-#define PM860X_DAC_OFFSET 0x1b
-#define PM860X_OFFSET_LEFT_1 0x1c
-#define PM860X_OFFSET_LEFT_2 0x1d
-#define PM860X_OFFSET_RIGHT_1 0x1e
-#define PM860X_OFFSET_RIGHT_2 0x1f
-#define PM860X_ADC_ANA_1 0x20
-#define PM860X_ADC_ANA_2 0x21
-#define PM860X_ADC_ANA_3 0x22
-#define PM860X_ADC_ANA_4 0x23
-#define PM860X_ANA_TO_ANA 0x24
-#define PM860X_HS1_CTRL 0x25
-#define PM860X_HS2_CTRL 0x26
-#define PM860X_LO1_CTRL 0x27
-#define PM860X_LO2_CTRL 0x28
-#define PM860X_EAR_CTRL_1 0x29
-#define PM860X_EAR_CTRL_2 0x2a
-#define PM860X_AUDIO_SUPPLIES_1 0x2b
-#define PM860X_AUDIO_SUPPLIES_2 0x2c
-#define PM860X_ADC_EN_1 0x2d
-#define PM860X_ADC_EN_2 0x2e
-#define PM860X_DAC_EN_1 0x2f
-#define PM860X_DAC_EN_2 0x31
-#define PM860X_AUDIO_CAL_1 0x32
-#define PM860X_AUDIO_CAL_2 0x33
-#define PM860X_AUDIO_CAL_3 0x34
-#define PM860X_AUDIO_CAL_4 0x35
-#define PM860X_AUDIO_CAL_5 0x36
-#define PM860X_ANA_INPUT_SEL_1 0x37
-#define PM860X_ANA_INPUT_SEL_2 0x38
+#define PM860X_I2S_IFACE_1 0xbb
+#define PM860X_I2S_IFACE_2 0xbc
+#define PM860X_I2S_IFACE_3 0xbd
+#define PM860X_I2S_IFACE_4 0xbe
+#define PM860X_EQUALIZER_N0_1 0xbf
+#define PM860X_EQUALIZER_N0_2 0xc0
+#define PM860X_EQUALIZER_N1_1 0xc1
+#define PM860X_EQUALIZER_N1_2 0xc2
+#define PM860X_EQUALIZER_D1_1 0xc3
+#define PM860X_EQUALIZER_D1_2 0xc4
+#define PM860X_LOFI_GAIN_LEFT 0xc5
+#define PM860X_LOFI_GAIN_RIGHT 0xc6
+#define PM860X_HIFIL_GAIN_LEFT 0xc7
+#define PM860X_HIFIL_GAIN_RIGHT 0xc8
+#define PM860X_HIFIR_GAIN_LEFT 0xc9
+#define PM860X_HIFIR_GAIN_RIGHT 0xca
+#define PM860X_DAC_OFFSET 0xcb
+#define PM860X_OFFSET_LEFT_1 0xcc
+#define PM860X_OFFSET_LEFT_2 0xcd
+#define PM860X_OFFSET_RIGHT_1 0xce
+#define PM860X_OFFSET_RIGHT_2 0xcf
+#define PM860X_ADC_ANA_1 0xd0
+#define PM860X_ADC_ANA_2 0xd1
+#define PM860X_ADC_ANA_3 0xd2
+#define PM860X_ADC_ANA_4 0xd3
+#define PM860X_ANA_TO_ANA 0xd4
+#define PM860X_HS1_CTRL 0xd5
+#define PM860X_HS2_CTRL 0xd6
+#define PM860X_LO1_CTRL 0xd7
+#define PM860X_LO2_CTRL 0xd8
+#define PM860X_EAR_CTRL_1 0xd9
+#define PM860X_EAR_CTRL_2 0xda
+#define PM860X_AUDIO_SUPPLIES_1 0xdb
+#define PM860X_AUDIO_SUPPLIES_2 0xdc
+#define PM860X_ADC_EN_1 0xdd
+#define PM860X_ADC_EN_2 0xde
+#define PM860X_DAC_EN_1 0xdf
+#define PM860X_DAC_EN_2 0xe1
+#define PM860X_AUDIO_CAL_1 0xe2
+#define PM860X_AUDIO_CAL_2 0xe3
+#define PM860X_AUDIO_CAL_3 0xe4
+#define PM860X_AUDIO_CAL_4 0xe5
+#define PM860X_AUDIO_CAL_5 0xe6
+#define PM860X_ANA_INPUT_SEL_1 0xe7
+#define PM860X_ANA_INPUT_SEL_2 0xe8
-#define PM860X_PCM_IFACE_4 0x39
-#define PM860X_I2S_IFACE_5 0x3a
+#define PM860X_PCM_IFACE_4 0xe9
+#define PM860X_I2S_IFACE_5 0xea
#define PM860X_SHORTS 0x3b
#define PM860X_PLL_ADJ_1 0x3c
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
index b8ba0adacfce..a0394a8f2257 100644
--- a/sound/soc/codecs/ab8500-codec.c
+++ b/sound/soc/codecs/ab8500-codec.c
@@ -126,6 +126,8 @@ struct ab8500_codec_drvdata_dbg {
/* Private data for AB8500 device-driver */
struct ab8500_codec_drvdata {
+ struct regmap *regmap;
+
/* Sidetone */
long *sid_fir_values;
enum sid_state sid_status;
@@ -166,49 +168,35 @@ static inline const char *amic_type_str(enum amic_type type)
*/
/* Read a register from the audio-bank of AB8500 */
-static unsigned int ab8500_codec_read_reg(struct snd_soc_codec *codec,
- unsigned int reg)
+static int ab8500_codec_read_reg(void *context, unsigned int reg,
+ unsigned int *value)
{
+ struct device *dev = context;
int status;
- unsigned int value = 0;
u8 value8;
- status = abx500_get_register_interruptible(codec->dev, AB8500_AUDIO,
- reg, &value8);
- if (status < 0) {
- dev_err(codec->dev,
- "%s: ERROR: Register (0x%02x:0x%02x) read failed (%d).\n",
- __func__, (u8)AB8500_AUDIO, (u8)reg, status);
- } else {
- dev_dbg(codec->dev,
- "%s: Read 0x%02x from register 0x%02x:0x%02x\n",
- __func__, value8, (u8)AB8500_AUDIO, (u8)reg);
- value = (unsigned int)value8;
- }
+ status = abx500_get_register_interruptible(dev, AB8500_AUDIO,
+ reg, &value8);
+ *value = (unsigned int)value8;
- return value;
+ return status;
}
/* Write to a register in the audio-bank of AB8500 */
-static int ab8500_codec_write_reg(struct snd_soc_codec *codec,
- unsigned int reg, unsigned int value)
+static int ab8500_codec_write_reg(void *context, unsigned int reg,
+ unsigned int value)
{
- int status;
-
- status = abx500_set_register_interruptible(codec->dev, AB8500_AUDIO,
- reg, value);
- if (status < 0)
- dev_err(codec->dev,
- "%s: ERROR: Register (%02x:%02x) write failed (%d).\n",
- __func__, (u8)AB8500_AUDIO, (u8)reg, status);
- else
- dev_dbg(codec->dev,
- "%s: Wrote 0x%02x into register %02x:%02x\n",
- __func__, (u8)value, (u8)AB8500_AUDIO, (u8)reg);
+ struct device *dev = context;
- return status;
+ return abx500_set_register_interruptible(dev, AB8500_AUDIO,
+ reg, value);
}
+static const struct regmap_config ab8500_codec_regmap = {
+ .reg_read = ab8500_codec_read_reg,
+ .reg_write = ab8500_codec_write_reg,
+};
+
/*
* Controls - DAPM
*/
@@ -1225,13 +1213,18 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol,
struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
struct device *dev = codec->dev;
bool apply_fir, apply_iir;
- int req, status;
+ unsigned int req;
+ int status;
dev_dbg(dev, "%s: Enter.\n", __func__);
mutex_lock(&drvdata->anc_lock);
req = ucontrol->value.integer.value[0];
+ if (req >= ARRAY_SIZE(enum_anc_state)) {
+ status = -EINVAL;
+ goto cleanup;
+ }
if (req != ANC_APPLY_FIR_IIR && req != ANC_APPLY_FIR &&
req != ANC_APPLY_IIR) {
dev_err(dev, "%s: ERROR: Unsupported status to set '%s'!\n",
@@ -2480,9 +2473,13 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec)
dev_dbg(dev, "%s: Enter.\n", __func__);
+ snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
+
/* Setup AB8500 according to board-settings */
pdata = dev_get_platdata(dev->parent);
+ codec->control_data = drvdata->regmap;
+
if (np) {
if (!pdata)
pdata = devm_kzalloc(dev,
@@ -2527,12 +2524,10 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec)
}
/* Override HW-defaults */
- ab8500_codec_write_reg(codec,
- AB8500_ANACONF5,
- BIT(AB8500_ANACONF5_HSAUTOEN));
- ab8500_codec_write_reg(codec,
- AB8500_SHORTCIRCONF,
- BIT(AB8500_SHORTCIRCONF_HSZCDDIS));
+ snd_soc_write(codec, AB8500_ANACONF5,
+ BIT(AB8500_ANACONF5_HSAUTOEN));
+ snd_soc_write(codec, AB8500_SHORTCIRCONF,
+ BIT(AB8500_SHORTCIRCONF_HSZCDDIS));
/* Add filter controls */
status = snd_soc_add_codec_controls(codec, ab8500_filter_controls,
@@ -2562,9 +2557,6 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver ab8500_codec_driver = {
.probe = ab8500_codec_probe,
- .read = ab8500_codec_read_reg,
- .write = ab8500_codec_write_reg,
- .reg_word_size = sizeof(u8),
.controls = ab8500_ctrls,
.num_controls = ARRAY_SIZE(ab8500_ctrls),
.dapm_widgets = ab8500_dapm_widgets,
@@ -2587,6 +2579,15 @@ static int ab8500_codec_driver_probe(struct platform_device *pdev)
drvdata->anc_status = ANC_UNCONFIGURED;
dev_set_drvdata(&pdev->dev, drvdata);
+ drvdata->regmap = devm_regmap_init(&pdev->dev, NULL, &pdev->dev,
+ &ab8500_codec_regmap);
+ if (IS_ERR(drvdata->regmap)) {
+ status = PTR_ERR(drvdata->regmap);
+ dev_err(&pdev->dev, "%s: Failed to allocate regmap: %d\n",
+ __func__, status);
+ return status;
+ }
+
dev_dbg(&pdev->dev, "%s: Register codec.\n", __func__);
status = snd_soc_register_codec(&pdev->dev, &ab8500_codec_driver,
ab8500_codec_dai,
@@ -2601,7 +2602,7 @@ static int ab8500_codec_driver_probe(struct platform_device *pdev)
static int ab8500_codec_driver_remove(struct platform_device *pdev)
{
- dev_info(&pdev->dev, "%s Enter.\n", __func__);
+ dev_dbg(&pdev->dev, "%s Enter.\n", __func__);
snd_soc_unregister_codec(&pdev->dev);
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index 71059c07ae7b..b4819dcd4f4d 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -45,8 +45,6 @@
#define AK4104_TX_TXE (1 << 0)
#define AK4104_TX_V (1 << 1)
-#define DRV_NAME "ak4104-codec"
-
struct ak4104_private {
struct regmap *regmap;
};
@@ -291,12 +289,19 @@ static const struct of_device_id ak4104_of_match[] = {
};
MODULE_DEVICE_TABLE(of, ak4104_of_match);
+static const struct spi_device_id ak4104_id_table[] = {
+ { "ak4104", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, ak4104_id_table);
+
static struct spi_driver ak4104_spi_driver = {
.driver = {
- .name = DRV_NAME,
+ .name = "ak4104",
.owner = THIS_MODULE,
.of_match_table = ak4104_of_match,
},
+ .id_table = ak4104_id_table,
.probe = ak4104_spi_probe,
.remove = ak4104_spi_remove,
};
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 2d0378709702..21c35ed778cc 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -352,7 +352,6 @@ static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
*/
default:
return -EINVAL;
- break;
}
snd_soc_update_bits(codec, MD_CTL1, DIF_MASK, data);
@@ -405,7 +404,6 @@ static int ak4642_dai_hw_params(struct snd_pcm_substream *substream,
break;
default:
return -EINVAL;
- break;
}
snd_soc_update_bits(codec, MD_CTL2, FS_MASK, rate);
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index 657808ba1418..6f05b17d1965 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -1477,21 +1477,25 @@ static void arizona_enable_fll(struct arizona_fll *fll,
{
struct arizona *arizona = fll->arizona;
int ret;
+ bool use_sync = false;
/*
* If we have both REFCLK and SYNCCLK then enable both,
* otherwise apply the SYNCCLK settings to REFCLK.
*/
- if (fll->ref_src >= 0 && fll->ref_src != fll->sync_src) {
+ if (fll->ref_src >= 0 && fll->ref_freq &&
+ fll->ref_src != fll->sync_src) {
regmap_update_bits(arizona->regmap, fll->base + 5,
ARIZONA_FLL1_OUTDIV_MASK,
ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
arizona_apply_fll(arizona, fll->base, ref, fll->ref_src,
false);
- if (fll->sync_src >= 0)
+ if (fll->sync_src >= 0) {
arizona_apply_fll(arizona, fll->base + 0x10, sync,
fll->sync_src, true);
+ use_sync = true;
+ }
} else if (fll->sync_src >= 0) {
regmap_update_bits(arizona->regmap, fll->base + 5,
ARIZONA_FLL1_OUTDIV_MASK,
@@ -1511,7 +1515,7 @@ static void arizona_enable_fll(struct arizona_fll *fll,
* Increase the bandwidth if we're not using a low frequency
* sync source.
*/
- if (fll->sync_src >= 0 && fll->sync_freq > 100000)
+ if (use_sync && fll->sync_freq > 100000)
regmap_update_bits(arizona->regmap, fll->base + 0x17,
ARIZONA_FLL1_SYNC_BW, 0);
else
@@ -1526,8 +1530,7 @@ static void arizona_enable_fll(struct arizona_fll *fll,
regmap_update_bits(arizona->regmap, fll->base + 1,
ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
- if (fll->ref_src >= 0 && fll->sync_src >= 0 &&
- fll->ref_src != fll->sync_src)
+ if (use_sync)
regmap_update_bits(arizona->regmap, fll->base + 0x11,
ARIZONA_FLL1_SYNC_ENA,
ARIZONA_FLL1_SYNC_ENA);
@@ -1561,10 +1564,12 @@ int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
if (fll->ref_src == source && fll->ref_freq == Fref)
return 0;
- if (fll->fout && Fref > 0) {
- ret = arizona_calc_fll(fll, &ref, Fref, fll->fout);
- if (ret != 0)
- return ret;
+ if (fll->fout) {
+ if (Fref > 0) {
+ ret = arizona_calc_fll(fll, &ref, Fref, fll->fout);
+ if (ret != 0)
+ return ret;
+ }
if (fll->sync_src >= 0) {
ret = arizona_calc_fll(fll, &sync, fll->sync_freq,
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
index 23316c887b19..43737a27d79c 100644
--- a/sound/soc/codecs/cq93vc.c
+++ b/sound/soc/codecs/cq93vc.c
@@ -38,24 +38,6 @@
#include <sound/soc.h>
#include <sound/initval.h>
-static inline unsigned int cq93vc_read(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- struct davinci_vc *davinci_vc = codec->control_data;
-
- return readl(davinci_vc->base + reg);
-}
-
-static inline int cq93vc_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- struct davinci_vc *davinci_vc = codec->control_data;
-
- writel(value, davinci_vc->base + reg);
-
- return 0;
-}
-
static const struct snd_kcontrol_new cq93vc_snd_controls[] = {
SOC_SINGLE("PGA Capture Volume", DAVINCI_VC_REG05, 0, 0x03, 0),
SOC_SINGLE("Mono DAC Playback Volume", DAVINCI_VC_REG09, 0, 0x3f, 0),
@@ -64,13 +46,15 @@ static const struct snd_kcontrol_new cq93vc_snd_controls[] = {
static int cq93vc_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
- u8 reg = cq93vc_read(codec, DAVINCI_VC_REG09) & ~DAVINCI_VC_REG09_MUTE;
+ u8 reg;
if (mute)
- cq93vc_write(codec, DAVINCI_VC_REG09,
- reg | DAVINCI_VC_REG09_MUTE);
+ reg = DAVINCI_VC_REG09_MUTE;
else
- cq93vc_write(codec, DAVINCI_VC_REG09, reg);
+ reg = 0;
+
+ snd_soc_update_bits(codec, DAVINCI_VC_REG09, DAVINCI_VC_REG09_MUTE,
+ reg);
return 0;
}
@@ -79,7 +63,7 @@ static int cq93vc_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = codec_dai->codec;
- struct davinci_vc *davinci_vc = codec->control_data;
+ struct davinci_vc *davinci_vc = codec->dev->platform_data;
switch (freq) {
case 22579200:
@@ -97,18 +81,18 @@ static int cq93vc_set_bias_level(struct snd_soc_codec *codec,
{
switch (level) {
case SND_SOC_BIAS_ON:
- cq93vc_write(codec, DAVINCI_VC_REG12,
+ snd_soc_write(codec, DAVINCI_VC_REG12,
DAVINCI_VC_REG12_POWER_ALL_ON);
break;
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY:
- cq93vc_write(codec, DAVINCI_VC_REG12,
+ snd_soc_write(codec, DAVINCI_VC_REG12,
DAVINCI_VC_REG12_POWER_ALL_OFF);
break;
case SND_SOC_BIAS_OFF:
/* force all power off */
- cq93vc_write(codec, DAVINCI_VC_REG12,
+ snd_soc_write(codec, DAVINCI_VC_REG12,
DAVINCI_VC_REG12_POWER_ALL_OFF);
break;
}
@@ -154,11 +138,9 @@ static int cq93vc_probe(struct snd_soc_codec *codec)
struct davinci_vc *davinci_vc = codec->dev->platform_data;
davinci_vc->cq93vc.codec = codec;
- codec->control_data = davinci_vc;
+ codec->control_data = davinci_vc->regmap;
- /* Set controls */
- snd_soc_add_codec_controls(codec, cq93vc_snd_controls,
- ARRAY_SIZE(cq93vc_snd_controls));
+ snd_soc_codec_set_cache_io(codec, 32, 32, SND_SOC_REGMAP);
/* Off, with power on */
cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -174,12 +156,12 @@ static int cq93vc_remove(struct snd_soc_codec *codec)
}
static struct snd_soc_codec_driver soc_codec_dev_cq93vc = {
- .read = cq93vc_read,
- .write = cq93vc_write,
.set_bias_level = cq93vc_set_bias_level,
.probe = cq93vc_probe,
.remove = cq93vc_remove,
.resume = cq93vc_resume,
+ .controls = cq93vc_snd_controls,
+ .num_controls = ARRAY_SIZE(cq93vc_snd_controls),
};
static int cq93vc_platform_probe(struct platform_device *pdev)
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index 566a367c94fa..66ceee22fdad 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -15,6 +15,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -38,294 +39,223 @@ struct max98088_cdata {
};
struct max98088_priv {
- enum max98088_type devtype;
- struct max98088_pdata *pdata;
- unsigned int sysclk;
- struct max98088_cdata dai[2];
- int eq_textcnt;
- const char **eq_texts;
- struct soc_enum eq_enum;
- u8 ina_state;
- u8 inb_state;
- unsigned int ex_mode;
- unsigned int digmic;
- unsigned int mic1pre;
- unsigned int mic2pre;
- unsigned int extmic_mode;
+ struct regmap *regmap;
+ enum max98088_type devtype;
+ struct max98088_pdata *pdata;
+ unsigned int sysclk;
+ struct max98088_cdata dai[2];
+ int eq_textcnt;
+ const char **eq_texts;
+ struct soc_enum eq_enum;
+ u8 ina_state;
+ u8 inb_state;
+ unsigned int ex_mode;
+ unsigned int digmic;
+ unsigned int mic1pre;
+ unsigned int mic2pre;
+ unsigned int extmic_mode;
};
-static const u8 max98088_reg[M98088_REG_CNT] = {
- 0x00, /* 00 IRQ status */
- 0x00, /* 01 MIC status */
- 0x00, /* 02 jack status */
- 0x00, /* 03 battery voltage */
- 0x00, /* 04 */
- 0x00, /* 05 */
- 0x00, /* 06 */
- 0x00, /* 07 */
- 0x00, /* 08 */
- 0x00, /* 09 */
- 0x00, /* 0A */
- 0x00, /* 0B */
- 0x00, /* 0C */
- 0x00, /* 0D */
- 0x00, /* 0E */
- 0x00, /* 0F interrupt enable */
-
- 0x00, /* 10 master clock */
- 0x00, /* 11 DAI1 clock mode */
- 0x00, /* 12 DAI1 clock control */
- 0x00, /* 13 DAI1 clock control */
- 0x00, /* 14 DAI1 format */
- 0x00, /* 15 DAI1 clock */
- 0x00, /* 16 DAI1 config */
- 0x00, /* 17 DAI1 TDM */
- 0x00, /* 18 DAI1 filters */
- 0x00, /* 19 DAI2 clock mode */
- 0x00, /* 1A DAI2 clock control */
- 0x00, /* 1B DAI2 clock control */
- 0x00, /* 1C DAI2 format */
- 0x00, /* 1D DAI2 clock */
- 0x00, /* 1E DAI2 config */
- 0x00, /* 1F DAI2 TDM */
-
- 0x00, /* 20 DAI2 filters */
- 0x00, /* 21 data config */
- 0x00, /* 22 DAC mixer */
- 0x00, /* 23 left ADC mixer */
- 0x00, /* 24 right ADC mixer */
- 0x00, /* 25 left HP mixer */
- 0x00, /* 26 right HP mixer */
- 0x00, /* 27 HP control */
- 0x00, /* 28 left REC mixer */
- 0x00, /* 29 right REC mixer */
- 0x00, /* 2A REC control */
- 0x00, /* 2B left SPK mixer */
- 0x00, /* 2C right SPK mixer */
- 0x00, /* 2D SPK control */
- 0x00, /* 2E sidetone */
- 0x00, /* 2F DAI1 playback level */
-
- 0x00, /* 30 DAI1 playback level */
- 0x00, /* 31 DAI2 playback level */
- 0x00, /* 32 DAI2 playbakc level */
- 0x00, /* 33 left ADC level */
- 0x00, /* 34 right ADC level */
- 0x00, /* 35 MIC1 level */
- 0x00, /* 36 MIC2 level */
- 0x00, /* 37 INA level */
- 0x00, /* 38 INB level */
- 0x00, /* 39 left HP volume */
- 0x00, /* 3A right HP volume */
- 0x00, /* 3B left REC volume */
- 0x00, /* 3C right REC volume */
- 0x00, /* 3D left SPK volume */
- 0x00, /* 3E right SPK volume */
- 0x00, /* 3F MIC config */
-
- 0x00, /* 40 MIC threshold */
- 0x00, /* 41 excursion limiter filter */
- 0x00, /* 42 excursion limiter threshold */
- 0x00, /* 43 ALC */
- 0x00, /* 44 power limiter threshold */
- 0x00, /* 45 power limiter config */
- 0x00, /* 46 distortion limiter config */
- 0x00, /* 47 audio input */
- 0x00, /* 48 microphone */
- 0x00, /* 49 level control */
- 0x00, /* 4A bypass switches */
- 0x00, /* 4B jack detect */
- 0x00, /* 4C input enable */
- 0x00, /* 4D output enable */
- 0xF0, /* 4E bias control */
- 0x00, /* 4F DAC power */
-
- 0x0F, /* 50 DAC power */
- 0x00, /* 51 system */
- 0x00, /* 52 DAI1 EQ1 */
- 0x00, /* 53 DAI1 EQ1 */
- 0x00, /* 54 DAI1 EQ1 */
- 0x00, /* 55 DAI1 EQ1 */
- 0x00, /* 56 DAI1 EQ1 */
- 0x00, /* 57 DAI1 EQ1 */
- 0x00, /* 58 DAI1 EQ1 */
- 0x00, /* 59 DAI1 EQ1 */
- 0x00, /* 5A DAI1 EQ1 */
- 0x00, /* 5B DAI1 EQ1 */
- 0x00, /* 5C DAI1 EQ2 */
- 0x00, /* 5D DAI1 EQ2 */
- 0x00, /* 5E DAI1 EQ2 */
- 0x00, /* 5F DAI1 EQ2 */
-
- 0x00, /* 60 DAI1 EQ2 */
- 0x00, /* 61 DAI1 EQ2 */
- 0x00, /* 62 DAI1 EQ2 */
- 0x00, /* 63 DAI1 EQ2 */
- 0x00, /* 64 DAI1 EQ2 */
- 0x00, /* 65 DAI1 EQ2 */
- 0x00, /* 66 DAI1 EQ3 */
- 0x00, /* 67 DAI1 EQ3 */
- 0x00, /* 68 DAI1 EQ3 */
- 0x00, /* 69 DAI1 EQ3 */
- 0x00, /* 6A DAI1 EQ3 */
- 0x00, /* 6B DAI1 EQ3 */
- 0x00, /* 6C DAI1 EQ3 */
- 0x00, /* 6D DAI1 EQ3 */
- 0x00, /* 6E DAI1 EQ3 */
- 0x00, /* 6F DAI1 EQ3 */
-
- 0x00, /* 70 DAI1 EQ4 */
- 0x00, /* 71 DAI1 EQ4 */
- 0x00, /* 72 DAI1 EQ4 */
- 0x00, /* 73 DAI1 EQ4 */
- 0x00, /* 74 DAI1 EQ4 */
- 0x00, /* 75 DAI1 EQ4 */
- 0x00, /* 76 DAI1 EQ4 */
- 0x00, /* 77 DAI1 EQ4 */
- 0x00, /* 78 DAI1 EQ4 */
- 0x00, /* 79 DAI1 EQ4 */
- 0x00, /* 7A DAI1 EQ5 */
- 0x00, /* 7B DAI1 EQ5 */
- 0x00, /* 7C DAI1 EQ5 */
- 0x00, /* 7D DAI1 EQ5 */
- 0x00, /* 7E DAI1 EQ5 */
- 0x00, /* 7F DAI1 EQ5 */
-
- 0x00, /* 80 DAI1 EQ5 */
- 0x00, /* 81 DAI1 EQ5 */
- 0x00, /* 82 DAI1 EQ5 */
- 0x00, /* 83 DAI1 EQ5 */
- 0x00, /* 84 DAI2 EQ1 */
- 0x00, /* 85 DAI2 EQ1 */
- 0x00, /* 86 DAI2 EQ1 */
- 0x00, /* 87 DAI2 EQ1 */
- 0x00, /* 88 DAI2 EQ1 */
- 0x00, /* 89 DAI2 EQ1 */
- 0x00, /* 8A DAI2 EQ1 */
- 0x00, /* 8B DAI2 EQ1 */
- 0x00, /* 8C DAI2 EQ1 */
- 0x00, /* 8D DAI2 EQ1 */
- 0x00, /* 8E DAI2 EQ2 */
- 0x00, /* 8F DAI2 EQ2 */
-
- 0x00, /* 90 DAI2 EQ2 */
- 0x00, /* 91 DAI2 EQ2 */
- 0x00, /* 92 DAI2 EQ2 */
- 0x00, /* 93 DAI2 EQ2 */
- 0x00, /* 94 DAI2 EQ2 */
- 0x00, /* 95 DAI2 EQ2 */
- 0x00, /* 96 DAI2 EQ2 */
- 0x00, /* 97 DAI2 EQ2 */
- 0x00, /* 98 DAI2 EQ3 */
- 0x00, /* 99 DAI2 EQ3 */
- 0x00, /* 9A DAI2 EQ3 */
- 0x00, /* 9B DAI2 EQ3 */
- 0x00, /* 9C DAI2 EQ3 */
- 0x00, /* 9D DAI2 EQ3 */
- 0x00, /* 9E DAI2 EQ3 */
- 0x00, /* 9F DAI2 EQ3 */
-
- 0x00, /* A0 DAI2 EQ3 */
- 0x00, /* A1 DAI2 EQ3 */
- 0x00, /* A2 DAI2 EQ4 */
- 0x00, /* A3 DAI2 EQ4 */
- 0x00, /* A4 DAI2 EQ4 */
- 0x00, /* A5 DAI2 EQ4 */
- 0x00, /* A6 DAI2 EQ4 */
- 0x00, /* A7 DAI2 EQ4 */
- 0x00, /* A8 DAI2 EQ4 */
- 0x00, /* A9 DAI2 EQ4 */
- 0x00, /* AA DAI2 EQ4 */
- 0x00, /* AB DAI2 EQ4 */
- 0x00, /* AC DAI2 EQ5 */
- 0x00, /* AD DAI2 EQ5 */
- 0x00, /* AE DAI2 EQ5 */
- 0x00, /* AF DAI2 EQ5 */
-
- 0x00, /* B0 DAI2 EQ5 */
- 0x00, /* B1 DAI2 EQ5 */
- 0x00, /* B2 DAI2 EQ5 */
- 0x00, /* B3 DAI2 EQ5 */
- 0x00, /* B4 DAI2 EQ5 */
- 0x00, /* B5 DAI2 EQ5 */
- 0x00, /* B6 DAI1 biquad */
- 0x00, /* B7 DAI1 biquad */
- 0x00, /* B8 DAI1 biquad */
- 0x00, /* B9 DAI1 biquad */
- 0x00, /* BA DAI1 biquad */
- 0x00, /* BB DAI1 biquad */
- 0x00, /* BC DAI1 biquad */
- 0x00, /* BD DAI1 biquad */
- 0x00, /* BE DAI1 biquad */
- 0x00, /* BF DAI1 biquad */
-
- 0x00, /* C0 DAI2 biquad */
- 0x00, /* C1 DAI2 biquad */
- 0x00, /* C2 DAI2 biquad */
- 0x00, /* C3 DAI2 biquad */
- 0x00, /* C4 DAI2 biquad */
- 0x00, /* C5 DAI2 biquad */
- 0x00, /* C6 DAI2 biquad */
- 0x00, /* C7 DAI2 biquad */
- 0x00, /* C8 DAI2 biquad */
- 0x00, /* C9 DAI2 biquad */
- 0x00, /* CA */
- 0x00, /* CB */
- 0x00, /* CC */
- 0x00, /* CD */
- 0x00, /* CE */
- 0x00, /* CF */
-
- 0x00, /* D0 */
- 0x00, /* D1 */
- 0x00, /* D2 */
- 0x00, /* D3 */
- 0x00, /* D4 */
- 0x00, /* D5 */
- 0x00, /* D6 */
- 0x00, /* D7 */
- 0x00, /* D8 */
- 0x00, /* D9 */
- 0x00, /* DA */
- 0x70, /* DB */
- 0x00, /* DC */
- 0x00, /* DD */
- 0x00, /* DE */
- 0x00, /* DF */
-
- 0x00, /* E0 */
- 0x00, /* E1 */
- 0x00, /* E2 */
- 0x00, /* E3 */
- 0x00, /* E4 */
- 0x00, /* E5 */
- 0x00, /* E6 */
- 0x00, /* E7 */
- 0x00, /* E8 */
- 0x00, /* E9 */
- 0x00, /* EA */
- 0x00, /* EB */
- 0x00, /* EC */
- 0x00, /* ED */
- 0x00, /* EE */
- 0x00, /* EF */
-
- 0x00, /* F0 */
- 0x00, /* F1 */
- 0x00, /* F2 */
- 0x00, /* F3 */
- 0x00, /* F4 */
- 0x00, /* F5 */
- 0x00, /* F6 */
- 0x00, /* F7 */
- 0x00, /* F8 */
- 0x00, /* F9 */
- 0x00, /* FA */
- 0x00, /* FB */
- 0x00, /* FC */
- 0x00, /* FD */
- 0x00, /* FE */
- 0x00, /* FF */
+static const struct reg_default max98088_reg[] = {
+ { 0xf, 0x00 }, /* 0F interrupt enable */
+
+ { 0x10, 0x00 }, /* 10 master clock */
+ { 0x11, 0x00 }, /* 11 DAI1 clock mode */
+ { 0x12, 0x00 }, /* 12 DAI1 clock control */
+ { 0x13, 0x00 }, /* 13 DAI1 clock control */
+ { 0x14, 0x00 }, /* 14 DAI1 format */
+ { 0x15, 0x00 }, /* 15 DAI1 clock */
+ { 0x16, 0x00 }, /* 16 DAI1 config */
+ { 0x17, 0x00 }, /* 17 DAI1 TDM */
+ { 0x18, 0x00 }, /* 18 DAI1 filters */
+ { 0x19, 0x00 }, /* 19 DAI2 clock mode */
+ { 0x1a, 0x00 }, /* 1A DAI2 clock control */
+ { 0x1b, 0x00 }, /* 1B DAI2 clock control */
+ { 0x1c, 0x00 }, /* 1C DAI2 format */
+ { 0x1d, 0x00 }, /* 1D DAI2 clock */
+ { 0x1e, 0x00 }, /* 1E DAI2 config */
+ { 0x1f, 0x00 }, /* 1F DAI2 TDM */
+
+ { 0x20, 0x00 }, /* 20 DAI2 filters */
+ { 0x21, 0x00 }, /* 21 data config */
+ { 0x22, 0x00 }, /* 22 DAC mixer */
+ { 0x23, 0x00 }, /* 23 left ADC mixer */
+ { 0x24, 0x00 }, /* 24 right ADC mixer */
+ { 0x25, 0x00 }, /* 25 left HP mixer */
+ { 0x26, 0x00 }, /* 26 right HP mixer */
+ { 0x27, 0x00 }, /* 27 HP control */
+ { 0x28, 0x00 }, /* 28 left REC mixer */
+ { 0x29, 0x00 }, /* 29 right REC mixer */
+ { 0x2a, 0x00 }, /* 2A REC control */
+ { 0x2b, 0x00 }, /* 2B left SPK mixer */
+ { 0x2c, 0x00 }, /* 2C right SPK mixer */
+ { 0x2d, 0x00 }, /* 2D SPK control */
+ { 0x2e, 0x00 }, /* 2E sidetone */
+ { 0x2f, 0x00 }, /* 2F DAI1 playback level */
+
+ { 0x30, 0x00 }, /* 30 DAI1 playback level */
+ { 0x31, 0x00 }, /* 31 DAI2 playback level */
+ { 0x32, 0x00 }, /* 32 DAI2 playbakc level */
+ { 0x33, 0x00 }, /* 33 left ADC level */
+ { 0x34, 0x00 }, /* 34 right ADC level */
+ { 0x35, 0x00 }, /* 35 MIC1 level */
+ { 0x36, 0x00 }, /* 36 MIC2 level */
+ { 0x37, 0x00 }, /* 37 INA level */
+ { 0x38, 0x00 }, /* 38 INB level */
+ { 0x39, 0x00 }, /* 39 left HP volume */
+ { 0x3a, 0x00 }, /* 3A right HP volume */
+ { 0x3b, 0x00 }, /* 3B left REC volume */
+ { 0x3c, 0x00 }, /* 3C right REC volume */
+ { 0x3d, 0x00 }, /* 3D left SPK volume */
+ { 0x3e, 0x00 }, /* 3E right SPK volume */
+ { 0x3f, 0x00 }, /* 3F MIC config */
+
+ { 0x40, 0x00 }, /* 40 MIC threshold */
+ { 0x41, 0x00 }, /* 41 excursion limiter filter */
+ { 0x42, 0x00 }, /* 42 excursion limiter threshold */
+ { 0x43, 0x00 }, /* 43 ALC */
+ { 0x44, 0x00 }, /* 44 power limiter threshold */
+ { 0x45, 0x00 }, /* 45 power limiter config */
+ { 0x46, 0x00 }, /* 46 distortion limiter config */
+ { 0x47, 0x00 }, /* 47 audio input */
+ { 0x48, 0x00 }, /* 48 microphone */
+ { 0x49, 0x00 }, /* 49 level control */
+ { 0x4a, 0x00 }, /* 4A bypass switches */
+ { 0x4b, 0x00 }, /* 4B jack detect */
+ { 0x4c, 0x00 }, /* 4C input enable */
+ { 0x4d, 0x00 }, /* 4D output enable */
+ { 0x4e, 0xF0 }, /* 4E bias control */
+ { 0x4f, 0x00 }, /* 4F DAC power */
+
+ { 0x50, 0x0F }, /* 50 DAC power */
+ { 0x51, 0x00 }, /* 51 system */
+ { 0x52, 0x00 }, /* 52 DAI1 EQ1 */
+ { 0x53, 0x00 }, /* 53 DAI1 EQ1 */
+ { 0x54, 0x00 }, /* 54 DAI1 EQ1 */
+ { 0x55, 0x00 }, /* 55 DAI1 EQ1 */
+ { 0x56, 0x00 }, /* 56 DAI1 EQ1 */
+ { 0x57, 0x00 }, /* 57 DAI1 EQ1 */
+ { 0x58, 0x00 }, /* 58 DAI1 EQ1 */
+ { 0x59, 0x00 }, /* 59 DAI1 EQ1 */
+ { 0x5a, 0x00 }, /* 5A DAI1 EQ1 */
+ { 0x5b, 0x00 }, /* 5B DAI1 EQ1 */
+ { 0x5c, 0x00 }, /* 5C DAI1 EQ2 */
+ { 0x5d, 0x00 }, /* 5D DAI1 EQ2 */
+ { 0x5e, 0x00 }, /* 5E DAI1 EQ2 */
+ { 0x5f, 0x00 }, /* 5F DAI1 EQ2 */
+
+ { 0x60, 0x00 }, /* 60 DAI1 EQ2 */
+ { 0x61, 0x00 }, /* 61 DAI1 EQ2 */
+ { 0x62, 0x00 }, /* 62 DAI1 EQ2 */
+ { 0x63, 0x00 }, /* 63 DAI1 EQ2 */
+ { 0x64, 0x00 }, /* 64 DAI1 EQ2 */
+ { 0x65, 0x00 }, /* 65 DAI1 EQ2 */
+ { 0x66, 0x00 }, /* 66 DAI1 EQ3 */
+ { 0x67, 0x00 }, /* 67 DAI1 EQ3 */
+ { 0x68, 0x00 }, /* 68 DAI1 EQ3 */
+ { 0x69, 0x00 }, /* 69 DAI1 EQ3 */
+ { 0x6a, 0x00 }, /* 6A DAI1 EQ3 */
+ { 0x6b, 0x00 }, /* 6B DAI1 EQ3 */
+ { 0x6c, 0x00 }, /* 6C DAI1 EQ3 */
+ { 0x6d, 0x00 }, /* 6D DAI1 EQ3 */
+ { 0x6e, 0x00 }, /* 6E DAI1 EQ3 */
+ { 0x6f, 0x00 }, /* 6F DAI1 EQ3 */
+
+ { 0x70, 0x00 }, /* 70 DAI1 EQ4 */
+ { 0x71, 0x00 }, /* 71 DAI1 EQ4 */
+ { 0x72, 0x00 }, /* 72 DAI1 EQ4 */
+ { 0x73, 0x00 }, /* 73 DAI1 EQ4 */
+ { 0x74, 0x00 }, /* 74 DAI1 EQ4 */
+ { 0x75, 0x00 }, /* 75 DAI1 EQ4 */
+ { 0x76, 0x00 }, /* 76 DAI1 EQ4 */
+ { 0x77, 0x00 }, /* 77 DAI1 EQ4 */
+ { 0x78, 0x00 }, /* 78 DAI1 EQ4 */
+ { 0x79, 0x00 }, /* 79 DAI1 EQ4 */
+ { 0x7a, 0x00 }, /* 7A DAI1 EQ5 */
+ { 0x7b, 0x00 }, /* 7B DAI1 EQ5 */
+ { 0x7c, 0x00 }, /* 7C DAI1 EQ5 */
+ { 0x7d, 0x00 }, /* 7D DAI1 EQ5 */
+ { 0x7e, 0x00 }, /* 7E DAI1 EQ5 */
+ { 0x7f, 0x00 }, /* 7F DAI1 EQ5 */
+
+ { 0x80, 0x00 }, /* 80 DAI1 EQ5 */
+ { 0x81, 0x00 }, /* 81 DAI1 EQ5 */
+ { 0x82, 0x00 }, /* 82 DAI1 EQ5 */
+ { 0x83, 0x00 }, /* 83 DAI1 EQ5 */
+ { 0x84, 0x00 }, /* 84 DAI2 EQ1 */
+ { 0x85, 0x00 }, /* 85 DAI2 EQ1 */
+ { 0x86, 0x00 }, /* 86 DAI2 EQ1 */
+ { 0x87, 0x00 }, /* 87 DAI2 EQ1 */
+ { 0x88, 0x00 }, /* 88 DAI2 EQ1 */
+ { 0x89, 0x00 }, /* 89 DAI2 EQ1 */
+ { 0x8a, 0x00 }, /* 8A DAI2 EQ1 */
+ { 0x8b, 0x00 }, /* 8B DAI2 EQ1 */
+ { 0x8c, 0x00 }, /* 8C DAI2 EQ1 */
+ { 0x8d, 0x00 }, /* 8D DAI2 EQ1 */
+ { 0x8e, 0x00 }, /* 8E DAI2 EQ2 */
+ { 0x8f, 0x00 }, /* 8F DAI2 EQ2 */
+
+ { 0x90, 0x00 }, /* 90 DAI2 EQ2 */
+ { 0x91, 0x00 }, /* 91 DAI2 EQ2 */
+ { 0x92, 0x00 }, /* 92 DAI2 EQ2 */
+ { 0x93, 0x00 }, /* 93 DAI2 EQ2 */
+ { 0x94, 0x00 }, /* 94 DAI2 EQ2 */
+ { 0x95, 0x00 }, /* 95 DAI2 EQ2 */
+ { 0x96, 0x00 }, /* 96 DAI2 EQ2 */
+ { 0x97, 0x00 }, /* 97 DAI2 EQ2 */
+ { 0x98, 0x00 }, /* 98 DAI2 EQ3 */
+ { 0x99, 0x00 }, /* 99 DAI2 EQ3 */
+ { 0x9a, 0x00 }, /* 9A DAI2 EQ3 */
+ { 0x9b, 0x00 }, /* 9B DAI2 EQ3 */
+ { 0x9c, 0x00 }, /* 9C DAI2 EQ3 */
+ { 0x9d, 0x00 }, /* 9D DAI2 EQ3 */
+ { 0x9e, 0x00 }, /* 9E DAI2 EQ3 */
+ { 0x9f, 0x00 }, /* 9F DAI2 EQ3 */
+
+ { 0xa0, 0x00 }, /* A0 DAI2 EQ3 */
+ { 0xa1, 0x00 }, /* A1 DAI2 EQ3 */
+ { 0xa2, 0x00 }, /* A2 DAI2 EQ4 */
+ { 0xa3, 0x00 }, /* A3 DAI2 EQ4 */
+ { 0xa4, 0x00 }, /* A4 DAI2 EQ4 */
+ { 0xa5, 0x00 }, /* A5 DAI2 EQ4 */
+ { 0xa6, 0x00 }, /* A6 DAI2 EQ4 */
+ { 0xa7, 0x00 }, /* A7 DAI2 EQ4 */
+ { 0xa8, 0x00 }, /* A8 DAI2 EQ4 */
+ { 0xa9, 0x00 }, /* A9 DAI2 EQ4 */
+ { 0xaa, 0x00 }, /* AA DAI2 EQ4 */
+ { 0xab, 0x00 }, /* AB DAI2 EQ4 */
+ { 0xac, 0x00 }, /* AC DAI2 EQ5 */
+ { 0xad, 0x00 }, /* AD DAI2 EQ5 */
+ { 0xae, 0x00 }, /* AE DAI2 EQ5 */
+ { 0xaf, 0x00 }, /* AF DAI2 EQ5 */
+
+ { 0xb0, 0x00 }, /* B0 DAI2 EQ5 */
+ { 0xb1, 0x00 }, /* B1 DAI2 EQ5 */
+ { 0xb2, 0x00 }, /* B2 DAI2 EQ5 */
+ { 0xb3, 0x00 }, /* B3 DAI2 EQ5 */
+ { 0xb4, 0x00 }, /* B4 DAI2 EQ5 */
+ { 0xb5, 0x00 }, /* B5 DAI2 EQ5 */
+ { 0xb6, 0x00 }, /* B6 DAI1 biquad */
+ { 0xb7, 0x00 }, /* B7 DAI1 biquad */
+ { 0xb8 ,0x00 }, /* B8 DAI1 biquad */
+ { 0xb9, 0x00 }, /* B9 DAI1 biquad */
+ { 0xba, 0x00 }, /* BA DAI1 biquad */
+ { 0xbb, 0x00 }, /* BB DAI1 biquad */
+ { 0xbc, 0x00 }, /* BC DAI1 biquad */
+ { 0xbd, 0x00 }, /* BD DAI1 biquad */
+ { 0xbe, 0x00 }, /* BE DAI1 biquad */
+ { 0xbf, 0x00 }, /* BF DAI1 biquad */
+
+ { 0xc0, 0x00 }, /* C0 DAI2 biquad */
+ { 0xc1, 0x00 }, /* C1 DAI2 biquad */
+ { 0xc2, 0x00 }, /* C2 DAI2 biquad */
+ { 0xc3, 0x00 }, /* C3 DAI2 biquad */
+ { 0xc4, 0x00 }, /* C4 DAI2 biquad */
+ { 0xc5, 0x00 }, /* C5 DAI2 biquad */
+ { 0xc6, 0x00 }, /* C6 DAI2 biquad */
+ { 0xc7, 0x00 }, /* C7 DAI2 biquad */
+ { 0xc8, 0x00 }, /* C8 DAI2 biquad */
+ { 0xc9, 0x00 }, /* C9 DAI2 biquad */
};
static struct {
@@ -606,11 +536,28 @@ static struct {
{ 0xFF, 0x00, 1 }, /* FF */
};
-static int max98088_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool max98088_readable_register(struct device *dev, unsigned int reg)
+{
+ return max98088_access[reg].readable;
+}
+
+static bool max98088_volatile_register(struct device *dev, unsigned int reg)
{
return max98088_access[reg].vol;
}
+static const struct regmap_config max98088_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .readable_reg = max98088_readable_register,
+ .volatile_reg = max98088_volatile_register,
+ .max_register = 0xff,
+
+ .reg_defaults = max98088_reg,
+ .num_reg_defaults = ARRAY_SIZE(max98088_reg),
+ .cache_type = REGCACHE_RBTREE,
+};
/*
* Load equalizer DSP coefficient configurations registers
@@ -1610,58 +1557,34 @@ static int max98088_dai2_digital_mute(struct snd_soc_dai *codec_dai, int mute)
return 0;
}
-static void max98088_sync_cache(struct snd_soc_codec *codec)
-{
- u8 *reg_cache = codec->reg_cache;
- int i;
-
- if (!codec->cache_sync)
- return;
-
- codec->cache_only = 0;
-
- /* write back cached values if they're writeable and
- * different from the hardware default.
- */
- for (i = 1; i < codec->driver->reg_cache_size; i++) {
- if (!max98088_access[i].writable)
- continue;
-
- if (reg_cache[i] == max98088_reg[i])
- continue;
-
- snd_soc_write(codec, i, reg_cache[i]);
- }
-
- codec->cache_sync = 0;
-}
-
static int max98088_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- switch (level) {
- case SND_SOC_BIAS_ON:
- break;
-
- case SND_SOC_BIAS_PREPARE:
- break;
-
- case SND_SOC_BIAS_STANDBY:
- if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
- max98088_sync_cache(codec);
-
- snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
- M98088_MBEN, M98088_MBEN);
- break;
-
- case SND_SOC_BIAS_OFF:
- snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
- M98088_MBEN, 0);
- codec->cache_sync = 1;
- break;
- }
- codec->dapm.bias_level = level;
- return 0;
+ struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+
+ case SND_SOC_BIAS_PREPARE:
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
+ regcache_sync(max98088->regmap);
+
+ snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
+ M98088_MBEN, M98088_MBEN);
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
+ M98088_MBEN, 0);
+ regcache_mark_dirty(max98088->regmap);
+ break;
+ }
+ codec->dapm.bias_level = level;
+ return 0;
}
#define MAX98088_RATES SNDRV_PCM_RATE_8000_96000
@@ -1988,9 +1911,9 @@ static int max98088_probe(struct snd_soc_codec *codec)
struct max98088_cdata *cdata;
int ret = 0;
- codec->cache_sync = 1;
+ regcache_mark_dirty(max98088->regmap);
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -2048,9 +1971,6 @@ static int max98088_probe(struct snd_soc_codec *codec)
max98088_handle_pdata(codec);
- snd_soc_add_codec_controls(codec, max98088_snd_controls,
- ARRAY_SIZE(max98088_snd_controls));
-
err_access:
return ret;
}
@@ -2066,15 +1986,13 @@ static int max98088_remove(struct snd_soc_codec *codec)
}
static struct snd_soc_codec_driver soc_codec_dev_max98088 = {
- .probe = max98088_probe,
- .remove = max98088_remove,
- .suspend = max98088_suspend,
- .resume = max98088_resume,
- .set_bias_level = max98088_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(max98088_reg),
- .reg_word_size = sizeof(u8),
- .reg_cache_default = max98088_reg,
- .volatile_register = max98088_volatile_register,
+ .probe = max98088_probe,
+ .remove = max98088_remove,
+ .suspend = max98088_suspend,
+ .resume = max98088_resume,
+ .set_bias_level = max98088_set_bias_level,
+ .controls = max98088_snd_controls,
+ .num_controls = ARRAY_SIZE(max98088_snd_controls),
.dapm_widgets = max98088_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(max98088_dapm_widgets),
.dapm_routes = max98088_audio_map,
@@ -2082,7 +2000,7 @@ static struct snd_soc_codec_driver soc_codec_dev_max98088 = {
};
static int max98088_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+ const struct i2c_device_id *id)
{
struct max98088_priv *max98088;
int ret;
@@ -2092,6 +2010,10 @@ static int max98088_i2c_probe(struct i2c_client *i2c,
if (max98088 == NULL)
return -ENOMEM;
+ max98088->regmap = devm_regmap_init_i2c(i2c, &max98088_regmap);
+ if (IS_ERR(max98088->regmap))
+ return PTR_ERR(max98088->regmap);
+
max98088->devtype = id->driver_data;
i2c_set_clientdata(i2c, max98088);
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 41cdd1642970..8fb072455802 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -39,6 +39,7 @@ struct max98095_cdata {
};
struct max98095_priv {
+ struct regmap *regmap;
enum max98095_type devtype;
struct max98095_pdata *pdata;
unsigned int sysclk;
@@ -56,263 +57,145 @@ struct max98095_priv {
struct snd_soc_jack *mic_jack;
};
-static const u8 max98095_reg_def[M98095_REG_CNT] = {
- 0x00, /* 00 */
- 0x00, /* 01 */
- 0x00, /* 02 */
- 0x00, /* 03 */
- 0x00, /* 04 */
- 0x00, /* 05 */
- 0x00, /* 06 */
- 0x00, /* 07 */
- 0x00, /* 08 */
- 0x00, /* 09 */
- 0x00, /* 0A */
- 0x00, /* 0B */
- 0x00, /* 0C */
- 0x00, /* 0D */
- 0x00, /* 0E */
- 0x00, /* 0F */
- 0x00, /* 10 */
- 0x00, /* 11 */
- 0x00, /* 12 */
- 0x00, /* 13 */
- 0x00, /* 14 */
- 0x00, /* 15 */
- 0x00, /* 16 */
- 0x00, /* 17 */
- 0x00, /* 18 */
- 0x00, /* 19 */
- 0x00, /* 1A */
- 0x00, /* 1B */
- 0x00, /* 1C */
- 0x00, /* 1D */
- 0x00, /* 1E */
- 0x00, /* 1F */
- 0x00, /* 20 */
- 0x00, /* 21 */
- 0x00, /* 22 */
- 0x00, /* 23 */
- 0x00, /* 24 */
- 0x00, /* 25 */
- 0x00, /* 26 */
- 0x00, /* 27 */
- 0x00, /* 28 */
- 0x00, /* 29 */
- 0x00, /* 2A */
- 0x00, /* 2B */
- 0x00, /* 2C */
- 0x00, /* 2D */
- 0x00, /* 2E */
- 0x00, /* 2F */
- 0x00, /* 30 */
- 0x00, /* 31 */
- 0x00, /* 32 */
- 0x00, /* 33 */
- 0x00, /* 34 */
- 0x00, /* 35 */
- 0x00, /* 36 */
- 0x00, /* 37 */
- 0x00, /* 38 */
- 0x00, /* 39 */
- 0x00, /* 3A */
- 0x00, /* 3B */
- 0x00, /* 3C */
- 0x00, /* 3D */
- 0x00, /* 3E */
- 0x00, /* 3F */
- 0x00, /* 40 */
- 0x00, /* 41 */
- 0x00, /* 42 */
- 0x00, /* 43 */
- 0x00, /* 44 */
- 0x00, /* 45 */
- 0x00, /* 46 */
- 0x00, /* 47 */
- 0x00, /* 48 */
- 0x00, /* 49 */
- 0x00, /* 4A */
- 0x00, /* 4B */
- 0x00, /* 4C */
- 0x00, /* 4D */
- 0x00, /* 4E */
- 0x00, /* 4F */
- 0x00, /* 50 */
- 0x00, /* 51 */
- 0x00, /* 52 */
- 0x00, /* 53 */
- 0x00, /* 54 */
- 0x00, /* 55 */
- 0x00, /* 56 */
- 0x00, /* 57 */
- 0x00, /* 58 */
- 0x00, /* 59 */
- 0x00, /* 5A */
- 0x00, /* 5B */
- 0x00, /* 5C */
- 0x00, /* 5D */
- 0x00, /* 5E */
- 0x00, /* 5F */
- 0x00, /* 60 */
- 0x00, /* 61 */
- 0x00, /* 62 */
- 0x00, /* 63 */
- 0x00, /* 64 */
- 0x00, /* 65 */
- 0x00, /* 66 */
- 0x00, /* 67 */
- 0x00, /* 68 */
- 0x00, /* 69 */
- 0x00, /* 6A */
- 0x00, /* 6B */
- 0x00, /* 6C */
- 0x00, /* 6D */
- 0x00, /* 6E */
- 0x00, /* 6F */
- 0x00, /* 70 */
- 0x00, /* 71 */
- 0x00, /* 72 */
- 0x00, /* 73 */
- 0x00, /* 74 */
- 0x00, /* 75 */
- 0x00, /* 76 */
- 0x00, /* 77 */
- 0x00, /* 78 */
- 0x00, /* 79 */
- 0x00, /* 7A */
- 0x00, /* 7B */
- 0x00, /* 7C */
- 0x00, /* 7D */
- 0x00, /* 7E */
- 0x00, /* 7F */
- 0x00, /* 80 */
- 0x00, /* 81 */
- 0x00, /* 82 */
- 0x00, /* 83 */
- 0x00, /* 84 */
- 0x00, /* 85 */
- 0x00, /* 86 */
- 0x00, /* 87 */
- 0x00, /* 88 */
- 0x00, /* 89 */
- 0x00, /* 8A */
- 0x00, /* 8B */
- 0x00, /* 8C */
- 0x00, /* 8D */
- 0x00, /* 8E */
- 0x00, /* 8F */
- 0x00, /* 90 */
- 0x00, /* 91 */
- 0x30, /* 92 */
- 0xF0, /* 93 */
- 0x00, /* 94 */
- 0x00, /* 95 */
- 0x3F, /* 96 */
- 0x00, /* 97 */
- 0x00, /* 98 */
- 0x00, /* 99 */
- 0x00, /* 9A */
- 0x00, /* 9B */
- 0x00, /* 9C */
- 0x00, /* 9D */
- 0x00, /* 9E */
- 0x00, /* 9F */
- 0x00, /* A0 */
- 0x00, /* A1 */
- 0x00, /* A2 */
- 0x00, /* A3 */
- 0x00, /* A4 */
- 0x00, /* A5 */
- 0x00, /* A6 */
- 0x00, /* A7 */
- 0x00, /* A8 */
- 0x00, /* A9 */
- 0x00, /* AA */
- 0x00, /* AB */
- 0x00, /* AC */
- 0x00, /* AD */
- 0x00, /* AE */
- 0x00, /* AF */
- 0x00, /* B0 */
- 0x00, /* B1 */
- 0x00, /* B2 */
- 0x00, /* B3 */
- 0x00, /* B4 */
- 0x00, /* B5 */
- 0x00, /* B6 */
- 0x00, /* B7 */
- 0x00, /* B8 */
- 0x00, /* B9 */
- 0x00, /* BA */
- 0x00, /* BB */
- 0x00, /* BC */
- 0x00, /* BD */
- 0x00, /* BE */
- 0x00, /* BF */
- 0x00, /* C0 */
- 0x00, /* C1 */
- 0x00, /* C2 */
- 0x00, /* C3 */
- 0x00, /* C4 */
- 0x00, /* C5 */
- 0x00, /* C6 */
- 0x00, /* C7 */
- 0x00, /* C8 */
- 0x00, /* C9 */
- 0x00, /* CA */
- 0x00, /* CB */
- 0x00, /* CC */
- 0x00, /* CD */
- 0x00, /* CE */
- 0x00, /* CF */
- 0x00, /* D0 */
- 0x00, /* D1 */
- 0x00, /* D2 */
- 0x00, /* D3 */
- 0x00, /* D4 */
- 0x00, /* D5 */
- 0x00, /* D6 */
- 0x00, /* D7 */
- 0x00, /* D8 */
- 0x00, /* D9 */
- 0x00, /* DA */
- 0x00, /* DB */
- 0x00, /* DC */
- 0x00, /* DD */
- 0x00, /* DE */
- 0x00, /* DF */
- 0x00, /* E0 */
- 0x00, /* E1 */
- 0x00, /* E2 */
- 0x00, /* E3 */
- 0x00, /* E4 */
- 0x00, /* E5 */
- 0x00, /* E6 */
- 0x00, /* E7 */
- 0x00, /* E8 */
- 0x00, /* E9 */
- 0x00, /* EA */
- 0x00, /* EB */
- 0x00, /* EC */
- 0x00, /* ED */
- 0x00, /* EE */
- 0x00, /* EF */
- 0x00, /* F0 */
- 0x00, /* F1 */
- 0x00, /* F2 */
- 0x00, /* F3 */
- 0x00, /* F4 */
- 0x00, /* F5 */
- 0x00, /* F6 */
- 0x00, /* F7 */
- 0x00, /* F8 */
- 0x00, /* F9 */
- 0x00, /* FA */
- 0x00, /* FB */
- 0x00, /* FC */
- 0x00, /* FD */
- 0x00, /* FE */
- 0x00, /* FF */
+static const struct reg_default max98095_reg_def[] = {
+ { 0xf, 0x00 }, /* 0F */
+ { 0x10, 0x00 }, /* 10 */
+ { 0x11, 0x00 }, /* 11 */
+ { 0x12, 0x00 }, /* 12 */
+ { 0x13, 0x00 }, /* 13 */
+ { 0x14, 0x00 }, /* 14 */
+ { 0x15, 0x00 }, /* 15 */
+ { 0x16, 0x00 }, /* 16 */
+ { 0x17, 0x00 }, /* 17 */
+ { 0x18, 0x00 }, /* 18 */
+ { 0x19, 0x00 }, /* 19 */
+ { 0x1a, 0x00 }, /* 1A */
+ { 0x1b, 0x00 }, /* 1B */
+ { 0x1c, 0x00 }, /* 1C */
+ { 0x1d, 0x00 }, /* 1D */
+ { 0x1e, 0x00 }, /* 1E */
+ { 0x1f, 0x00 }, /* 1F */
+ { 0x20, 0x00 }, /* 20 */
+ { 0x21, 0x00 }, /* 21 */
+ { 0x22, 0x00 }, /* 22 */
+ { 0x23, 0x00 }, /* 23 */
+ { 0x24, 0x00 }, /* 24 */
+ { 0x25, 0x00 }, /* 25 */
+ { 0x26, 0x00 }, /* 26 */
+ { 0x27, 0x00 }, /* 27 */
+ { 0x28, 0x00 }, /* 28 */
+ { 0x29, 0x00 }, /* 29 */
+ { 0x2a, 0x00 }, /* 2A */
+ { 0x2b, 0x00 }, /* 2B */
+ { 0x2c, 0x00 }, /* 2C */
+ { 0x2d, 0x00 }, /* 2D */
+ { 0x2e, 0x00 }, /* 2E */
+ { 0x2f, 0x00 }, /* 2F */
+ { 0x30, 0x00 }, /* 30 */
+ { 0x31, 0x00 }, /* 31 */
+ { 0x32, 0x00 }, /* 32 */
+ { 0x33, 0x00 }, /* 33 */
+ { 0x34, 0x00 }, /* 34 */
+ { 0x35, 0x00 }, /* 35 */
+ { 0x36, 0x00 }, /* 36 */
+ { 0x37, 0x00 }, /* 37 */
+ { 0x38, 0x00 }, /* 38 */
+ { 0x39, 0x00 }, /* 39 */
+ { 0x3a, 0x00 }, /* 3A */
+ { 0x3b, 0x00 }, /* 3B */
+ { 0x3c, 0x00 }, /* 3C */
+ { 0x3d, 0x00 }, /* 3D */
+ { 0x3e, 0x00 }, /* 3E */
+ { 0x3f, 0x00 }, /* 3F */
+ { 0x40, 0x00 }, /* 40 */
+ { 0x41, 0x00 }, /* 41 */
+ { 0x42, 0x00 }, /* 42 */
+ { 0x43, 0x00 }, /* 43 */
+ { 0x44, 0x00 }, /* 44 */
+ { 0x45, 0x00 }, /* 45 */
+ { 0x46, 0x00 }, /* 46 */
+ { 0x47, 0x00 }, /* 47 */
+ { 0x48, 0x00 }, /* 48 */
+ { 0x49, 0x00 }, /* 49 */
+ { 0x4a, 0x00 }, /* 4A */
+ { 0x4b, 0x00 }, /* 4B */
+ { 0x4c, 0x00 }, /* 4C */
+ { 0x4d, 0x00 }, /* 4D */
+ { 0x4e, 0x00 }, /* 4E */
+ { 0x4f, 0x00 }, /* 4F */
+ { 0x50, 0x00 }, /* 50 */
+ { 0x51, 0x00 }, /* 51 */
+ { 0x52, 0x00 }, /* 52 */
+ { 0x53, 0x00 }, /* 53 */
+ { 0x54, 0x00 }, /* 54 */
+ { 0x55, 0x00 }, /* 55 */
+ { 0x56, 0x00 }, /* 56 */
+ { 0x57, 0x00 }, /* 57 */
+ { 0x58, 0x00 }, /* 58 */
+ { 0x59, 0x00 }, /* 59 */
+ { 0x5a, 0x00 }, /* 5A */
+ { 0x5b, 0x00 }, /* 5B */
+ { 0x5c, 0x00 }, /* 5C */
+ { 0x5d, 0x00 }, /* 5D */
+ { 0x5e, 0x00 }, /* 5E */
+ { 0x5f, 0x00 }, /* 5F */
+ { 0x60, 0x00 }, /* 60 */
+ { 0x61, 0x00 }, /* 61 */
+ { 0x62, 0x00 }, /* 62 */
+ { 0x63, 0x00 }, /* 63 */
+ { 0x64, 0x00 }, /* 64 */
+ { 0x65, 0x00 }, /* 65 */
+ { 0x66, 0x00 }, /* 66 */
+ { 0x67, 0x00 }, /* 67 */
+ { 0x68, 0x00 }, /* 68 */
+ { 0x69, 0x00 }, /* 69 */
+ { 0x6a, 0x00 }, /* 6A */
+ { 0x6b, 0x00 }, /* 6B */
+ { 0x6c, 0x00 }, /* 6C */
+ { 0x6d, 0x00 }, /* 6D */
+ { 0x6e, 0x00 }, /* 6E */
+ { 0x6f, 0x00 }, /* 6F */
+ { 0x70, 0x00 }, /* 70 */
+ { 0x71, 0x00 }, /* 71 */
+ { 0x72, 0x00 }, /* 72 */
+ { 0x73, 0x00 }, /* 73 */
+ { 0x74, 0x00 }, /* 74 */
+ { 0x75, 0x00 }, /* 75 */
+ { 0x76, 0x00 }, /* 76 */
+ { 0x77, 0x00 }, /* 77 */
+ { 0x78, 0x00 }, /* 78 */
+ { 0x79, 0x00 }, /* 79 */
+ { 0x7a, 0x00 }, /* 7A */
+ { 0x7b, 0x00 }, /* 7B */
+ { 0x7c, 0x00 }, /* 7C */
+ { 0x7d, 0x00 }, /* 7D */
+ { 0x7e, 0x00 }, /* 7E */
+ { 0x7f, 0x00 }, /* 7F */
+ { 0x80, 0x00 }, /* 80 */
+ { 0x81, 0x00 }, /* 81 */
+ { 0x82, 0x00 }, /* 82 */
+ { 0x83, 0x00 }, /* 83 */
+ { 0x84, 0x00 }, /* 84 */
+ { 0x85, 0x00 }, /* 85 */
+ { 0x86, 0x00 }, /* 86 */
+ { 0x87, 0x00 }, /* 87 */
+ { 0x88, 0x00 }, /* 88 */
+ { 0x89, 0x00 }, /* 89 */
+ { 0x8a, 0x00 }, /* 8A */
+ { 0x8b, 0x00 }, /* 8B */
+ { 0x8c, 0x00 }, /* 8C */
+ { 0x8d, 0x00 }, /* 8D */
+ { 0x8e, 0x00 }, /* 8E */
+ { 0x8f, 0x00 }, /* 8F */
+ { 0x90, 0x00 }, /* 90 */
+ { 0x91, 0x00 }, /* 91 */
+ { 0x92, 0x30 }, /* 92 */
+ { 0x93, 0xF0 }, /* 93 */
+ { 0x94, 0x00 }, /* 94 */
+ { 0x95, 0x00 }, /* 95 */
+ { 0x96, 0x3F }, /* 96 */
+ { 0x97, 0x00 }, /* 97 */
+ { 0xff, 0x00 }, /* FF */
};
static struct {
@@ -577,14 +460,14 @@ static struct {
{ 0xFF, 0x00 }, /* FF */
};
-static int max98095_readable(struct snd_soc_codec *codec, unsigned int reg)
+static bool max98095_readable(struct device *dev, unsigned int reg)
{
if (reg >= M98095_REG_CNT)
return 0;
return max98095_access[reg].readable != 0;
}
-static int max98095_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static bool max98095_volatile(struct device *dev, unsigned int reg)
{
if (reg > M98095_REG_MAX_CACHED)
return 1;
@@ -611,22 +494,18 @@ static int max98095_volatile(struct snd_soc_codec *codec, unsigned int reg)
return 0;
}
-/*
- * Filter coefficients are in a separate register segment
- * and they share the address space of the normal registers.
- * The coefficient registers do not need or share the cache.
- */
-static int max98095_hw_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- int ret;
+static const struct regmap_config max98095_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
- codec->cache_bypass = 1;
- ret = snd_soc_write(codec, reg, value);
- codec->cache_bypass = 0;
+ .reg_defaults = max98095_reg_def,
+ .num_reg_defaults = ARRAY_SIZE(max98095_reg_def),
+ .max_register = M98095_0FF_REV_ID,
+ .cache_type = REGCACHE_RBTREE,
- return ret ? -EIO : 0;
-}
+ .readable_reg = max98095_readable,
+ .volatile_reg = max98095_volatile,
+};
/*
* Load equalizer DSP coefficient configurations registers
@@ -648,8 +527,8 @@ static void m98095_eq_band(struct snd_soc_codec *codec, unsigned int dai,
/* Step through the registers and coefs */
for (i = 0; i < M98095_COEFS_PER_BAND; i++) {
- max98095_hw_write(codec, eq_reg++, M98095_BYTE1(coefs[i]));
- max98095_hw_write(codec, eq_reg++, M98095_BYTE0(coefs[i]));
+ snd_soc_write(codec, eq_reg++, M98095_BYTE1(coefs[i]));
+ snd_soc_write(codec, eq_reg++, M98095_BYTE0(coefs[i]));
}
}
@@ -673,8 +552,8 @@ static void m98095_biquad_band(struct snd_soc_codec *codec, unsigned int dai,
/* Step through the registers and coefs */
for (i = 0; i < M98095_COEFS_PER_BAND; i++) {
- max98095_hw_write(codec, bq_reg++, M98095_BYTE1(coefs[i]));
- max98095_hw_write(codec, bq_reg++, M98095_BYTE0(coefs[i]));
+ snd_soc_write(codec, bq_reg++, M98095_BYTE1(coefs[i]));
+ snd_soc_write(codec, bq_reg++, M98095_BYTE0(coefs[i]));
}
}
@@ -1285,14 +1164,6 @@ static const struct snd_soc_dapm_route max98095_audio_map[] = {
{"MIC2 Input", NULL, "MIC2"},
};
-static int max98095_add_widgets(struct snd_soc_codec *codec)
-{
- snd_soc_add_codec_controls(codec, max98095_snd_controls,
- ARRAY_SIZE(max98095_snd_controls));
-
- return 0;
-}
-
/* codec mclk clock divider coefficients */
static const struct {
u32 rate;
@@ -1748,6 +1619,7 @@ static int max98095_dai3_set_fmt(struct snd_soc_dai *codec_dai,
static int max98095_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
+ struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
int ret;
switch (level) {
@@ -1759,7 +1631,7 @@ static int max98095_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
- ret = snd_soc_cache_sync(codec);
+ ret = regcache_sync(max98095->regmap);
if (ret != 0) {
dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
@@ -1774,7 +1646,7 @@ static int max98095_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_OFF:
snd_soc_update_bits(codec, M98095_090_PWR_EN_IN,
M98095_MBEN, 0);
- codec->cache_sync = 1;
+ regcache_mark_dirty(max98095->regmap);
break;
}
codec->dapm.bias_level = level;
@@ -1863,7 +1735,7 @@ static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol,
struct max98095_pdata *pdata = max98095->pdata;
int channel = max98095_get_eq_channel(kcontrol->id.name);
struct max98095_cdata *cdata;
- int sel = ucontrol->value.integer.value[0];
+ unsigned int sel = ucontrol->value.integer.value[0];
struct max98095_eq_cfg *coef_set;
int fs, best, best_val, i;
int regmask, regsave;
@@ -2016,7 +1888,7 @@ static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol,
struct max98095_pdata *pdata = max98095->pdata;
int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
struct max98095_cdata *cdata;
- int sel = ucontrol->value.integer.value[0];
+ unsigned int sel = ucontrol->value.integer.value[0];
struct max98095_biquad_cfg *coef_set;
int fs, best, best_val, i;
int regmask, regsave;
@@ -2341,7 +2213,7 @@ static int max98095_reset(struct snd_soc_codec *codec)
/* Reset to hardware default for registers, as there is not
* a soft reset hardware control register */
for (i = M98095_010_HOST_INT_CFG; i < M98095_REG_MAX_CACHED; i++) {
- ret = snd_soc_write(codec, i, max98095_reg_def[i]);
+ ret = snd_soc_write(codec, i, snd_soc_read(codec, i));
if (ret < 0) {
dev_err(codec->dev, "Failed to reset: %d\n", ret);
return ret;
@@ -2358,7 +2230,7 @@ static int max98095_probe(struct snd_soc_codec *codec)
struct i2c_client *client;
int ret = 0;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -2447,8 +2319,6 @@ static int max98095_probe(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, M98095_097_PWR_SYS, M98095_SHDNRUN,
M98095_SHDNRUN);
- max98095_add_widgets(codec);
-
return 0;
err_irq:
@@ -2480,11 +2350,8 @@ static struct snd_soc_codec_driver soc_codec_dev_max98095 = {
.suspend = max98095_suspend,
.resume = max98095_resume,
.set_bias_level = max98095_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(max98095_reg_def),
- .reg_word_size = sizeof(u8),
- .reg_cache_default = max98095_reg_def,
- .readable_register = max98095_readable,
- .volatile_register = max98095_volatile,
+ .controls = max98095_snd_controls,
+ .num_controls = ARRAY_SIZE(max98095_snd_controls),
.dapm_widgets = max98095_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(max98095_dapm_widgets),
.dapm_routes = max98095_audio_map,
@@ -2502,6 +2369,13 @@ static int max98095_i2c_probe(struct i2c_client *i2c,
if (max98095 == NULL)
return -ENOMEM;
+ max98095->regmap = devm_regmap_init_i2c(i2c, &max98095_regmap);
+ if (IS_ERR(max98095->regmap)) {
+ ret = PTR_ERR(max98095->regmap);
+ dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+ return ret;
+ }
+
max98095->devtype = id->driver_data;
i2c_set_clientdata(i2c, max98095);
max98095->pdata = i2c->dev.platform_data;
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c
index 58c38a5b481c..c5dd61785f8d 100644
--- a/sound/soc/codecs/max9850.c
+++ b/sound/soc/codecs/max9850.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -27,18 +28,26 @@
#include "max9850.h"
struct max9850_priv {
+ struct regmap *regmap;
unsigned int sysclk;
};
/* max9850 register cache */
-static const u8 max9850_reg[MAX9850_CACHEREGNUM] = {
- 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+static const struct reg_default max9850_reg[] = {
+ { 2, 0x0c },
+ { 3, 0x00 },
+ { 4, 0x00 },
+ { 5, 0x00 },
+ { 6, 0x00 },
+ { 7, 0x00 },
+ { 8, 0x00 },
+ { 9, 0x00 },
+ { 10, 0x00 },
};
/* these registers are not used at the moment but provided for the sake of
* completeness */
-static int max9850_volatile_register(struct snd_soc_codec *codec,
- unsigned int reg)
+static bool max9850_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case MAX9850_STATUSA:
@@ -49,6 +58,15 @@ static int max9850_volatile_register(struct snd_soc_codec *codec,
}
}
+static const struct regmap_config max9850_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = MAX9850_DIGITAL_AUDIO,
+ .volatile_reg = max9850_volatile_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+
static const unsigned int max9850_tlv[] = {
TLV_DB_RANGE_HEAD(4),
0x18, 0x1f, TLV_DB_SCALE_ITEM(-7450, 400, 0),
@@ -225,6 +243,7 @@ static int max9850_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
static int max9850_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
+ struct max9850_priv *max9850 = snd_soc_codec_get_drvdata(codec);
int ret;
switch (level) {
@@ -234,7 +253,7 @@ static int max9850_set_bias_level(struct snd_soc_codec *codec,
break;
case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
- ret = snd_soc_cache_sync(codec);
+ ret = regcache_sync(max9850->regmap);
if (ret) {
dev_err(codec->dev,
"Failed to sync cache: %d\n", ret);
@@ -295,7 +314,7 @@ static int max9850_probe(struct snd_soc_codec *codec)
{
int ret;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -316,10 +335,6 @@ static struct snd_soc_codec_driver soc_codec_dev_max9850 = {
.suspend = max9850_suspend,
.resume = max9850_resume,
.set_bias_level = max9850_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(max9850_reg),
- .reg_word_size = sizeof(u8),
- .reg_cache_default = max9850_reg,
- .volatile_register = max9850_volatile_register,
.controls = max9850_controls,
.num_controls = ARRAY_SIZE(max9850_controls),
@@ -340,6 +355,10 @@ static int max9850_i2c_probe(struct i2c_client *i2c,
if (max9850 == NULL)
return -ENOMEM;
+ max9850->regmap = devm_regmap_init_i2c(i2c, &max9850_regmap);
+ if (IS_ERR(max9850->regmap))
+ return PTR_ERR(max9850->regmap);
+
i2c_set_clientdata(i2c, max9850);
ret = snd_soc_register_codec(&i2c->dev,
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c
index ea141e1d6f28..eedbf05b8e96 100644
--- a/sound/soc/codecs/mc13783.c
+++ b/sound/soc/codecs/mc13783.c
@@ -30,16 +30,10 @@
#include <sound/soc.h>
#include <sound/initval.h>
#include <sound/soc-dapm.h>
+#include <linux/regmap.h>
#include "mc13783.h"
-#define MC13783_AUDIO_RX0 36
-#define MC13783_AUDIO_RX1 37
-#define MC13783_AUDIO_TX 38
-#define MC13783_SSI_NETWORK 39
-#define MC13783_AUDIO_CODEC 40
-#define MC13783_AUDIO_DAC 41
-
#define AUDIO_RX0_ALSPEN (1 << 5)
#define AUDIO_RX0_ALSPSEL (1 << 7)
#define AUDIO_RX0_ADDCDC (1 << 21)
@@ -95,45 +89,12 @@
struct mc13783_priv {
struct mc13xxx *mc13xxx;
+ struct regmap *regmap;
enum mc13783_ssi_port adc_ssi_port;
enum mc13783_ssi_port dac_ssi_port;
};
-static unsigned int mc13783_read(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
- unsigned int value = 0;
-
- mc13xxx_lock(priv->mc13xxx);
-
- mc13xxx_reg_read(priv->mc13xxx, reg, &value);
-
- mc13xxx_unlock(priv->mc13xxx);
-
- return value;
-}
-
-static int mc13783_write(struct snd_soc_codec *codec,
- unsigned int reg, unsigned int value)
-{
- struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
- int ret;
-
- mc13xxx_lock(priv->mc13xxx);
-
- ret = mc13xxx_reg_write(priv->mc13xxx, reg, value);
-
- /* include errata fix for spi audio problems */
- if (reg == MC13783_AUDIO_CODEC || reg == MC13783_AUDIO_DAC)
- ret = mc13xxx_reg_write(priv->mc13xxx, reg, value);
-
- mc13xxx_unlock(priv->mc13xxx);
-
- return ret;
-}
-
/* Mapping between sample rates and register value */
static unsigned int mc13783_rates[] = {
8000, 11025, 12000, 16000,
@@ -587,8 +548,14 @@ static struct snd_kcontrol_new mc13783_control_list[] = {
static int mc13783_probe(struct snd_soc_codec *codec)
{
struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
+ int ret;
- mc13xxx_lock(priv->mc13xxx);
+ codec->control_data = dev_get_regmap(codec->dev->parent, NULL);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 24, SND_SOC_REGMAP);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
/* these are the reset values */
mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_RX0, 0x25893);
@@ -612,8 +579,6 @@ static int mc13783_probe(struct snd_soc_codec *codec)
mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC,
0, AUDIO_SSI_SEL);
- mc13xxx_unlock(priv->mc13xxx);
-
return 0;
}
@@ -621,13 +586,9 @@ static int mc13783_remove(struct snd_soc_codec *codec)
{
struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
- mc13xxx_lock(priv->mc13xxx);
-
/* Make sure VAUDIOON is off */
mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_RX0, 0x3, 0);
- mc13xxx_unlock(priv->mc13xxx);
-
return 0;
}
@@ -717,8 +678,6 @@ static struct snd_soc_dai_driver mc13783_dai_sync[] = {
static struct snd_soc_codec_driver soc_codec_dev_mc13783 = {
.probe = mc13783_probe,
.remove = mc13783_remove,
- .read = mc13783_read,
- .write = mc13783_write,
.controls = mc13783_control_list,
.num_controls = ARRAY_SIZE(mc13783_control_list),
.dapm_widgets = mc13783_dapm_widgets,
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index c26a8f814b18..641eeeb00c5c 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -21,6 +21,7 @@
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
+#include <linux/acpi.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -926,7 +927,7 @@ static int rt5640_set_dmic2_event(struct snd_soc_dapm_widget *w,
return 0;
}
-void hp_amp_power_on(struct snd_soc_codec *codec)
+static void hp_amp_power_on(struct snd_soc_codec *codec)
{
struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
@@ -1609,7 +1610,8 @@ static int rt5640_hw_params(struct snd_pcm_substream *substream,
rt5640->lrck[dai->id] = params_rate(params);
pre_div = get_clk_info(rt5640->sysclk, rt5640->lrck[dai->id]);
if (pre_div < 0) {
- dev_err(codec->dev, "Unsupported clock setting\n");
+ dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n",
+ rt5640->lrck[dai->id], dai->id);
return -EINVAL;
}
frame_size = snd_soc_params_to_frame_size(params);
@@ -2080,6 +2082,14 @@ static const struct i2c_device_id rt5640_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id);
+#ifdef CONFIG_ACPI
+static struct acpi_device_id rt5640_acpi_match[] = {
+ { "INT33CA", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, rt5640_acpi_match);
+#endif
+
static int rt5640_parse_dt(struct rt5640_priv *rt5640, struct device_node *np)
{
rt5640->pdata.in1_diff = of_property_read_bool(np,
@@ -2199,6 +2209,7 @@ static struct i2c_driver rt5640_i2c_driver = {
.driver = {
.name = "rt5640",
.owner = THIS_MODULE,
+ .acpi_match_table = ACPI_PTR(rt5640_acpi_match),
},
.probe = rt5640_i2c_probe,
.remove = rt5640_i2c_remove,
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index dba26e63844e..13045f2af4d3 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -164,30 +164,28 @@ static unsigned int sn95031_get_mic_bias(struct snd_soc_codec *codec)
}
/*end - adc helper functions */
-static inline unsigned int sn95031_read(struct snd_soc_codec *codec,
- unsigned int reg)
+static int sn95031_read(void *ctx, unsigned int reg, unsigned int *val)
{
u8 value = 0;
int ret;
ret = intel_scu_ipc_ioread8(reg, &value);
- if (ret)
- pr_err("read of %x failed, err %d\n", reg, ret);
- return value;
+ if (ret == 0)
+ *val = value;
+ return ret;
}
-static inline int sn95031_write(struct snd_soc_codec *codec,
- unsigned int reg, unsigned int value)
+static int sn95031_write(void *ctx, unsigned int reg, unsigned int value)
{
- int ret;
-
- ret = intel_scu_ipc_iowrite8(reg, value);
- if (ret)
- pr_err("write of %x failed, err %d\n", reg, ret);
- return ret;
+ return intel_scu_ipc_iowrite8(reg, value);
}
+static const struct regmap_config sn95031_regmap = {
+ .reg_read = sn95031_read,
+ .reg_write = sn95031_write,
+};
+
static int sn95031_set_vaud_bias(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
@@ -827,6 +825,8 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
{
pr_debug("codec_probe called\n");
+ snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
+
/* PCM interface config
* This sets the pcm rx slot conguration to max 6 slots
* for max 4 dais (2 stereo and 2 mono)
@@ -886,8 +886,6 @@ static int sn95031_codec_remove(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver sn95031_codec = {
.probe = sn95031_codec_probe,
.remove = sn95031_codec_remove,
- .read = sn95031_read,
- .write = sn95031_write,
.set_bias_level = sn95031_set_vaud_bias,
.idle_bias_off = true,
.dapm_widgets = sn95031_dapm_widgets,
@@ -898,7 +896,14 @@ static struct snd_soc_codec_driver sn95031_codec = {
static int sn95031_device_probe(struct platform_device *pdev)
{
+ struct regmap *regmap;
+
pr_debug("codec device probe called for %s\n", dev_name(&pdev->dev));
+
+ regmap = devm_regmap_init(&pdev->dev, NULL, NULL, &sn95031_regmap);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
return snd_soc_register_codec(&pdev->dev, &sn95031_codec,
sn95031_dais, ARRAY_SIZE(sn95031_dais));
}
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 31762ebdd774..5d430cc56f51 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -24,6 +24,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -37,11 +38,27 @@
/*
* AIC23 register cache
*/
-static const u16 tlv320aic23_reg[] = {
- 0x0097, 0x0097, 0x00F9, 0x00F9, /* 0 */
- 0x001A, 0x0004, 0x0007, 0x0001, /* 4 */
- 0x0020, 0x0000, 0x0000, 0x0000, /* 8 */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 12 */
+static const struct reg_default tlv320aic23_reg[] = {
+ { 0, 0x0097 },
+ { 1, 0x0097 },
+ { 2, 0x00F9 },
+ { 3, 0x00F9 },
+ { 4, 0x001A },
+ { 5, 0x0004 },
+ { 6, 0x0007 },
+ { 7, 0x0001 },
+ { 8, 0x0020 },
+ { 9, 0x0000 },
+};
+
+static const struct regmap_config tlv320aic23_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+
+ .max_register = TLV320AIC23_RESET,
+ .reg_defaults = tlv320aic23_reg,
+ .num_reg_defaults = ARRAY_SIZE(tlv320aic23_reg),
+ .cache_type = REGCACHE_RBTREE,
};
static const char *rec_src_text[] = { "Line", "Mic" };
@@ -171,7 +188,7 @@ static const struct snd_soc_dapm_route tlv320aic23_intercon[] = {
/* AIC23 driver data */
struct aic23 {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
int mclk;
int requested_adc;
int requested_dac;
@@ -532,7 +549,9 @@ static int tlv320aic23_suspend(struct snd_soc_codec *codec)
static int tlv320aic23_resume(struct snd_soc_codec *codec)
{
- snd_soc_cache_sync(codec);
+ struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
+ regcache_mark_dirty(aic23->regmap);
+ regcache_sync(aic23->regmap);
tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
@@ -540,10 +559,9 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec)
static int tlv320aic23_probe(struct snd_soc_codec *codec)
{
- struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
int ret;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, aic23->control_type);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -552,16 +570,6 @@ static int tlv320aic23_probe(struct snd_soc_codec *codec)
/* Reset codec */
snd_soc_write(codec, TLV320AIC23_RESET, 0);
- /* Write the register default value to cache for reserved registers,
- * so the write to the these registers are suppressed by the cache
- * restore code when it skips writes of default registers.
- */
- snd_soc_cache_write(codec, 0x0A, 0);
- snd_soc_cache_write(codec, 0x0B, 0);
- snd_soc_cache_write(codec, 0x0C, 0);
- snd_soc_cache_write(codec, 0x0D, 0);
- snd_soc_cache_write(codec, 0x0E, 0);
-
/* power on device */
tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -586,9 +594,6 @@ static int tlv320aic23_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x1);
- snd_soc_add_codec_controls(codec, tlv320aic23_snd_controls,
- ARRAY_SIZE(tlv320aic23_snd_controls));
-
return 0;
}
@@ -599,21 +604,19 @@ static int tlv320aic23_remove(struct snd_soc_codec *codec)
}
static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
- .reg_cache_size = ARRAY_SIZE(tlv320aic23_reg),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = tlv320aic23_reg,
.probe = tlv320aic23_probe,
.remove = tlv320aic23_remove,
.suspend = tlv320aic23_suspend,
.resume = tlv320aic23_resume,
.set_bias_level = tlv320aic23_set_bias_level,
+ .controls = tlv320aic23_snd_controls,
+ .num_controls = ARRAY_SIZE(tlv320aic23_snd_controls),
.dapm_widgets = tlv320aic23_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
.dapm_routes = tlv320aic23_intercon,
.num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon),
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
/*
* If the i2c layer weren't so broken, we could pass this kind of data
* around
@@ -631,8 +634,11 @@ static int tlv320aic23_codec_probe(struct i2c_client *i2c,
if (aic23 == NULL)
return -ENOMEM;
+ aic23->regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap);
+ if (IS_ERR(aic23->regmap))
+ return PTR_ERR(aic23->regmap);
+
i2c_set_clientdata(i2c, aic23);
- aic23->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1);
@@ -660,29 +666,7 @@ static struct i2c_driver tlv320aic23_i2c_driver = {
.id_table = tlv320aic23_id,
};
-#endif
-
-static int __init tlv320aic23_modinit(void)
-{
- int ret;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- ret = i2c_add_driver(&tlv320aic23_i2c_driver);
- if (ret != 0) {
- printk(KERN_ERR "Failed to register TLV320AIC23 I2C driver: %d\n",
- ret);
- }
-#endif
- return ret;
-}
-module_init(tlv320aic23_modinit);
-
-static void __exit tlv320aic23_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- i2c_del_driver(&tlv320aic23_i2c_driver);
-#endif
-}
-module_exit(tlv320aic23_exit);
+module_i2c_driver(tlv320aic23_i2c_driver);
MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver");
MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index 7b8f3d965f43..94a658fa6d97 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -29,6 +29,7 @@ MODULE_LICENSE("GPL");
/* AIC26 driver private data */
struct aic26 {
struct spi_device *spi;
+ struct regmap *regmap;
struct snd_soc_codec *codec;
int master;
int datfm;
@@ -40,85 +41,6 @@ struct aic26 {
int keyclick_len;
};
-/* ---------------------------------------------------------------------
- * Register access routines
- */
-static unsigned int aic26_reg_read(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
- u16 *cache = codec->reg_cache;
- u16 cmd, value;
- u8 buffer[2];
- int rc;
-
- if (reg >= AIC26_NUM_REGS) {
- WARN_ON_ONCE(1);
- return 0;
- }
-
- /* Do SPI transfer; first 16bits are command; remaining is
- * register contents */
- cmd = AIC26_READ_COMMAND_WORD(reg);
- buffer[0] = (cmd >> 8) & 0xff;
- buffer[1] = cmd & 0xff;
- rc = spi_write_then_read(aic26->spi, buffer, 2, buffer, 2);
- if (rc) {
- dev_err(&aic26->spi->dev, "AIC26 reg read error\n");
- return -EIO;
- }
- value = (buffer[0] << 8) | buffer[1];
-
- /* Update the cache before returning with the value */
- cache[reg] = value;
- return value;
-}
-
-static unsigned int aic26_reg_read_cache(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- u16 *cache = codec->reg_cache;
-
- if (reg >= AIC26_NUM_REGS) {
- WARN_ON_ONCE(1);
- return 0;
- }
-
- return cache[reg];
-}
-
-static int aic26_reg_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
- u16 *cache = codec->reg_cache;
- u16 cmd;
- u8 buffer[4];
- int rc;
-
- if (reg >= AIC26_NUM_REGS) {
- WARN_ON_ONCE(1);
- return -EINVAL;
- }
-
- /* Do SPI transfer; first 16bits are command; remaining is data
- * to write into register */
- cmd = AIC26_WRITE_COMMAND_WORD(reg);
- buffer[0] = (cmd >> 8) & 0xff;
- buffer[1] = cmd & 0xff;
- buffer[2] = value >> 8;
- buffer[3] = value;
- rc = spi_write(aic26->spi, buffer, 4);
- if (rc) {
- dev_err(&aic26->spi->dev, "AIC26 reg read error\n");
- return -EIO;
- }
-
- /* update cache before returning */
- cache[reg] = value;
- return 0;
-}
-
static const struct snd_soc_dapm_widget tlv320aic26_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("MICIN"),
SND_SOC_DAPM_INPUT("AUX"),
@@ -195,19 +117,15 @@ static int aic26_hw_params(struct snd_pcm_substream *substream,
snd_soc_write(codec, AIC26_REG_PLL_PROG2, reg);
/* Audio Control 3 (master mode, fsref rate) */
- reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL3);
- reg &= ~0xf800;
if (aic26->master)
- reg |= 0x0800;
+ reg = 0x0800;
if (fsref == 48000)
- reg |= 0x2000;
- snd_soc_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
+ reg = 0x2000;
+ snd_soc_update_bits(codec, AIC26_REG_AUDIO_CTRL3, 0xf800, reg);
/* Audio Control 1 (FSref divisor) */
- reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL1);
- reg &= ~0x0fff;
- reg |= wlen | aic26->datfm | (divisor << 3) | divisor;
- snd_soc_write(codec, AIC26_REG_AUDIO_CTRL1, reg);
+ reg = wlen | aic26->datfm | (divisor << 3) | divisor;
+ snd_soc_update_bits(codec, AIC26_REG_AUDIO_CTRL1, 0xfff, reg);
return 0;
}
@@ -219,16 +137,16 @@ static int aic26_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
- u16 reg = aic26_reg_read_cache(codec, AIC26_REG_DAC_GAIN);
+ u16 reg;
dev_dbg(&aic26->spi->dev, "aic26_mute(dai=%p, mute=%i)\n",
dai, mute);
if (mute)
- reg |= 0x8080;
+ reg = 0x8080;
else
- reg &= ~0x8080;
- snd_soc_write(codec, AIC26_REG_DAC_GAIN, reg);
+ reg = 0;
+ snd_soc_update_bits(codec, AIC26_REG_DAC_GAIN, 0x8000, reg);
return 0;
}
@@ -346,7 +264,7 @@ static ssize_t aic26_keyclick_show(struct device *dev,
struct aic26 *aic26 = dev_get_drvdata(dev);
int val, amp, freq, len;
- val = aic26_reg_read_cache(aic26->codec, AIC26_REG_AUDIO_CTRL2);
+ val = snd_soc_read(aic26->codec, AIC26_REG_AUDIO_CTRL2);
amp = (val >> 12) & 0x7;
freq = (125 << ((val >> 8) & 0x7)) >> 1;
len = 2 * (1 + ((val >> 4) & 0xf));
@@ -360,11 +278,9 @@ static ssize_t aic26_keyclick_set(struct device *dev,
const char *buf, size_t count)
{
struct aic26 *aic26 = dev_get_drvdata(dev);
- int val;
- val = aic26_reg_read_cache(aic26->codec, AIC26_REG_AUDIO_CTRL2);
- val |= 0x8000;
- snd_soc_write(aic26->codec, AIC26_REG_AUDIO_CTRL2, val);
+ snd_soc_update_bits(aic26->codec, AIC26_REG_AUDIO_CTRL2,
+ 0x8000, 0x800);
return count;
}
@@ -377,7 +293,9 @@ static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set);
static int aic26_probe(struct snd_soc_codec *codec)
{
struct aic26 *aic26 = dev_get_drvdata(codec->dev);
- int ret, err, i, reg;
+ int ret, reg;
+
+ snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
aic26->codec = codec;
@@ -393,37 +311,30 @@ static int aic26_probe(struct snd_soc_codec *codec)
reg |= 0x0800; /* set master mode */
snd_soc_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
- /* Fill register cache */
- for (i = 0; i < codec->driver->reg_cache_size; i++)
- snd_soc_read(codec, i);
-
/* Register the sysfs files for debugging */
/* Create SysFS files */
ret = device_create_file(codec->dev, &dev_attr_keyclick);
if (ret)
dev_info(codec->dev, "error creating sysfs files\n");
- /* register controls */
- dev_dbg(codec->dev, "Registering controls\n");
- err = snd_soc_add_codec_controls(codec, aic26_snd_controls,
- ARRAY_SIZE(aic26_snd_controls));
- WARN_ON(err < 0);
-
return 0;
}
static struct snd_soc_codec_driver aic26_soc_codec_dev = {
.probe = aic26_probe,
- .read = aic26_reg_read,
- .write = aic26_reg_write,
- .reg_cache_size = AIC26_NUM_REGS,
- .reg_word_size = sizeof(u16),
+ .controls = aic26_snd_controls,
+ .num_controls = ARRAY_SIZE(aic26_snd_controls),
.dapm_widgets = tlv320aic26_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(tlv320aic26_dapm_widgets),
.dapm_routes = tlv320aic26_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(tlv320aic26_dapm_routes),
};
+static const struct regmap_config aic26_regmap = {
+ .reg_bits = 16,
+ .val_bits = 16,
+};
+
/* ---------------------------------------------------------------------
* SPI device portion of driver: probe and release routines and SPI
* driver registration.
@@ -440,6 +351,10 @@ static int aic26_spi_probe(struct spi_device *spi)
if (!aic26)
return -ENOMEM;
+ aic26->regmap = devm_regmap_init_spi(spi, &aic26_regmap);
+ if (IS_ERR(aic26->regmap))
+ return PTR_ERR(aic26->regmap);
+
/* Initialize the driver data */
aic26->spi = spi;
dev_set_drvdata(&spi->dev, aic26);
diff --git a/sound/soc/codecs/tlv320aic26.h b/sound/soc/codecs/tlv320aic26.h
index 67f19c3bebe6..629b85e75409 100644
--- a/sound/soc/codecs/tlv320aic26.h
+++ b/sound/soc/codecs/tlv320aic26.h
@@ -9,10 +9,7 @@
#define _TLV320AIC16_H_
/* AIC26 Registers */
-#define AIC26_READ_COMMAND_WORD(addr) ((1 << 15) | (addr << 5))
-#define AIC26_WRITE_COMMAND_WORD(addr) ((0 << 15) | (addr << 5))
-#define AIC26_PAGE_ADDR(page, offset) ((page << 6) | offset)
-#define AIC26_NUM_REGS AIC26_PAGE_ADDR(3, 0)
+#define AIC26_PAGE_ADDR(page, offset) ((page << 11) | offset << 5)
/* Page 0: Auxiliary data registers */
#define AIC26_REG_BAT1 AIC26_PAGE_ADDR(0, 0x05)
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 2ed57d4aa445..18cdcca9014c 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -60,9 +60,8 @@ struct aic32x4_rate_divs {
};
struct aic32x4_priv {
+ struct regmap *regmap;
u32 sysclk;
- u8 page_no;
- void *control_data;
u32 power_cfg;
u32 micpga_routing;
bool swapdacs;
@@ -262,67 +261,25 @@ static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = {
{"Right ADC", NULL, "Right Input Mixer"},
};
-static inline int aic32x4_change_page(struct snd_soc_codec *codec,
- unsigned int new_page)
-{
- struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
- u8 data[2];
- int ret;
-
- data[0] = 0x00;
- data[1] = new_page & 0xff;
-
- ret = codec->hw_write(codec->control_data, data, 2);
- if (ret == 2) {
- aic32x4->page_no = new_page;
- return 0;
- } else {
- return ret;
- }
-}
-
-static int aic32x4_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int val)
-{
- struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
- unsigned int page = reg / 128;
- unsigned int fixed_reg = reg % 128;
- u8 data[2];
- int ret;
-
- /* A write to AIC32X4_PSEL is really a non-explicit page change */
- if (reg == AIC32X4_PSEL)
- return aic32x4_change_page(codec, val);
-
- if (aic32x4->page_no != page) {
- ret = aic32x4_change_page(codec, page);
- if (ret != 0)
- return ret;
- }
-
- data[0] = fixed_reg & 0xff;
- data[1] = val & 0xff;
-
- if (codec->hw_write(codec->control_data, data, 2) == 2)
- return 0;
- else
- return -EIO;
-}
+static const struct regmap_range_cfg aic32x4_regmap_pages[] = {
+ {
+ .selector_reg = 0,
+ .selector_mask = 0xff,
+ .window_start = 0,
+ .window_len = 128,
+ .range_min = AIC32X4_PAGE1,
+ .range_max = AIC32X4_PAGE1 + 127,
+ },
+};
-static unsigned int aic32x4_read(struct snd_soc_codec *codec, unsigned int reg)
-{
- struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
- unsigned int page = reg / 128;
- unsigned int fixed_reg = reg % 128;
- int ret;
+static const struct regmap_config aic32x4_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
- if (aic32x4->page_no != page) {
- ret = aic32x4_change_page(codec, page);
- if (ret != 0)
- return ret;
- }
- return i2c_smbus_read_byte_data(codec->control_data, fixed_reg & 0xff);
-}
+ .max_register = AIC32X4_RMICPGAVOL,
+ .ranges = aic32x4_regmap_pages,
+ .num_ranges = ARRAY_SIZE(aic32x4_regmap_pages),
+};
static inline int aic32x4_get_divs(int mclk, int rate)
{
@@ -617,16 +574,10 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
{
struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
u32 tmp_reg;
- int ret;
- codec->hw_write = (hw_write_t) i2c_master_send;
- codec->control_data = aic32x4->control_data;
+ snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
if (aic32x4->rstn_gpio >= 0) {
- ret = devm_gpio_request_one(codec->dev, aic32x4->rstn_gpio,
- GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");
- if (ret != 0)
- return ret;
ndelay(10);
gpio_set_value(aic32x4->rstn_gpio, 1);
}
@@ -692,8 +643,6 @@ static int aic32x4_remove(struct snd_soc_codec *codec)
}
static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = {
- .read = aic32x4_read,
- .write = aic32x4_write,
.probe = aic32x4_probe,
.remove = aic32x4_remove,
.suspend = aic32x4_suspend,
@@ -720,7 +669,10 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c,
if (aic32x4 == NULL)
return -ENOMEM;
- aic32x4->control_data = i2c;
+ aic32x4->regmap = devm_regmap_init_i2c(i2c, &aic32x4_regmap);
+ if (IS_ERR(aic32x4->regmap))
+ return PTR_ERR(aic32x4->regmap);
+
i2c_set_clientdata(i2c, aic32x4);
if (pdata) {
@@ -735,6 +687,13 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c,
aic32x4->rstn_gpio = -1;
}
+ if (aic32x4->rstn_gpio >= 0) {
+ ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio,
+ GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");
+ if (ret != 0)
+ return ret;
+ }
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_aic32x4, &aic32x4_dai, 1);
return ret;
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 6e3f269243e0..892c108ca67a 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -72,9 +72,9 @@ struct aic3x_disable_nb {
/* codec private data */
struct aic3x_priv {
struct snd_soc_codec *codec;
+ struct regmap *regmap;
struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES];
struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES];
- enum snd_soc_control_type control_type;
struct aic3x_setup_data *setup;
unsigned int sysclk;
struct list_head list;
@@ -90,41 +90,45 @@ struct aic3x_priv {
enum aic3x_micbias_voltage micbias_vg;
};
-/*
- * AIC3X register cache
- * We can't read the AIC3X register space when we are
- * using 2 wire for device control, so we cache them instead.
- * There is no point in caching the reset register
- */
-static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
- 0x00, 0x00, 0x00, 0x10, /* 0 */
- 0x04, 0x00, 0x00, 0x00, /* 4 */
- 0x00, 0x00, 0x00, 0x01, /* 8 */
- 0x00, 0x00, 0x00, 0x80, /* 12 */
- 0x80, 0xff, 0xff, 0x78, /* 16 */
- 0x78, 0x78, 0x78, 0x78, /* 20 */
- 0x78, 0x00, 0x00, 0xfe, /* 24 */
- 0x00, 0x00, 0xfe, 0x00, /* 28 */
- 0x18, 0x18, 0x00, 0x00, /* 32 */
- 0x00, 0x00, 0x00, 0x00, /* 36 */
- 0x00, 0x00, 0x00, 0x80, /* 40 */
- 0x80, 0x00, 0x00, 0x00, /* 44 */
- 0x00, 0x00, 0x00, 0x04, /* 48 */
- 0x00, 0x00, 0x00, 0x00, /* 52 */
- 0x00, 0x00, 0x04, 0x00, /* 56 */
- 0x00, 0x00, 0x00, 0x00, /* 60 */
- 0x00, 0x04, 0x00, 0x00, /* 64 */
- 0x00, 0x00, 0x00, 0x00, /* 68 */
- 0x04, 0x00, 0x00, 0x00, /* 72 */
- 0x00, 0x00, 0x00, 0x00, /* 76 */
- 0x00, 0x00, 0x00, 0x00, /* 80 */
- 0x00, 0x00, 0x00, 0x00, /* 84 */
- 0x00, 0x00, 0x00, 0x00, /* 88 */
- 0x00, 0x00, 0x00, 0x00, /* 92 */
- 0x00, 0x00, 0x00, 0x00, /* 96 */
- 0x00, 0x00, 0x02, 0x00, /* 100 */
- 0x00, 0x00, 0x00, 0x00, /* 104 */
- 0x00, 0x00, /* 108 */
+static const struct reg_default aic3x_reg[] = {
+ { 0, 0x00 }, { 1, 0x00 }, { 2, 0x00 }, { 3, 0x10 },
+ { 4, 0x04 }, { 5, 0x00 }, { 6, 0x00 }, { 7, 0x00 },
+ { 8, 0x00 }, { 9, 0x00 }, { 10, 0x00 }, { 11, 0x01 },
+ { 12, 0x00 }, { 13, 0x00 }, { 14, 0x00 }, { 15, 0x80 },
+ { 16, 0x80 }, { 17, 0xff }, { 18, 0xff }, { 19, 0x78 },
+ { 20, 0x78 }, { 21, 0x78 }, { 22, 0x78 }, { 23, 0x78 },
+ { 24, 0x78 }, { 25, 0x00 }, { 26, 0x00 }, { 27, 0xfe },
+ { 28, 0x00 }, { 29, 0x00 }, { 30, 0xfe }, { 31, 0x00 },
+ { 32, 0x18 }, { 33, 0x18 }, { 34, 0x00 }, { 35, 0x00 },
+ { 36, 0x00 }, { 37, 0x00 }, { 38, 0x00 }, { 39, 0x00 },
+ { 40, 0x00 }, { 41, 0x00 }, { 42, 0x00 }, { 43, 0x80 },
+ { 44, 0x80 }, { 45, 0x00 }, { 46, 0x00 }, { 47, 0x00 },
+ { 48, 0x00 }, { 49, 0x00 }, { 50, 0x00 }, { 51, 0x04 },
+ { 52, 0x00 }, { 53, 0x00 }, { 54, 0x00 }, { 55, 0x00 },
+ { 56, 0x00 }, { 57, 0x00 }, { 58, 0x04 }, { 59, 0x00 },
+ { 60, 0x00 }, { 61, 0x00 }, { 62, 0x00 }, { 63, 0x00 },
+ { 64, 0x00 }, { 65, 0x04 }, { 66, 0x00 }, { 67, 0x00 },
+ { 68, 0x00 }, { 69, 0x00 }, { 70, 0x00 }, { 71, 0x00 },
+ { 72, 0x04 }, { 73, 0x00 }, { 74, 0x00 }, { 75, 0x00 },
+ { 76, 0x00 }, { 77, 0x00 }, { 78, 0x00 }, { 79, 0x00 },
+ { 80, 0x00 }, { 81, 0x00 }, { 82, 0x00 }, { 83, 0x00 },
+ { 84, 0x00 }, { 85, 0x00 }, { 86, 0x00 }, { 87, 0x00 },
+ { 88, 0x00 }, { 89, 0x00 }, { 90, 0x00 }, { 91, 0x00 },
+ { 92, 0x00 }, { 93, 0x00 }, { 94, 0x00 }, { 95, 0x00 },
+ { 96, 0x00 }, { 97, 0x00 }, { 98, 0x00 }, { 99, 0x00 },
+ { 100, 0x00 }, { 101, 0x00 }, { 102, 0x02 }, { 103, 0x00 },
+ { 104, 0x00 }, { 105, 0x00 }, { 106, 0x00 }, { 107, 0x00 },
+ { 108, 0x00 }, { 109, 0x00 },
+};
+
+static const struct regmap_config aic3x_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = DAC_ICC_ADJ,
+ .reg_defaults = aic3x_reg,
+ .num_reg_defaults = ARRAY_SIZE(aic3x_reg),
+ .cache_type = REGCACHE_RBTREE,
};
#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
@@ -824,12 +828,6 @@ static int aic3x_add_widgets(struct snd_soc_codec *codec)
struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
- snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets,
- ARRAY_SIZE(aic3x_dapm_widgets));
-
- /* set up audio path interconnects */
- snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
-
if (aic3x->model == AIC3X_MODEL_3007) {
snd_soc_dapm_new_controls(dapm, aic3007_dapm_widgets,
ARRAY_SIZE(aic3007_dapm_widgets));
@@ -1078,29 +1076,6 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
return 0;
}
-static int aic3x_init_3007(struct snd_soc_codec *codec)
-{
- u8 tmp1, tmp2, *cache = codec->reg_cache;
-
- /*
- * There is no need to cache writes to undocumented page 0xD but
- * respective page 0 register cache entries must be preserved
- */
- tmp1 = cache[0xD];
- tmp2 = cache[0x8];
- /* Class-D speaker driver init; datasheet p. 46 */
- snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x0D);
- snd_soc_write(codec, 0xD, 0x0D);
- snd_soc_write(codec, 0x8, 0x5C);
- snd_soc_write(codec, 0x8, 0x5D);
- snd_soc_write(codec, 0x8, 0x5C);
- snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x00);
- cache[0xD] = tmp1;
- cache[0x8] = tmp2;
-
- return 0;
-}
-
static int aic3x_regulator_event(struct notifier_block *nb,
unsigned long event, void *data)
{
@@ -1115,7 +1090,7 @@ static int aic3x_regulator_event(struct notifier_block *nb,
*/
if (gpio_is_valid(aic3x->gpio_reset))
gpio_set_value(aic3x->gpio_reset, 0);
- aic3x->codec->cache_sync = 1;
+ regcache_mark_dirty(aic3x->regmap);
}
return 0;
@@ -1124,8 +1099,7 @@ static int aic3x_regulator_event(struct notifier_block *nb,
static int aic3x_set_power(struct snd_soc_codec *codec, int power)
{
struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
- int i, ret;
- u8 *cache = codec->reg_cache;
+ int ret;
if (power) {
ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
@@ -1133,12 +1107,6 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
if (ret)
goto out;
aic3x->power = 1;
- /*
- * Reset release and cache sync is necessary only if some
- * supply was off or if there were cached writes
- */
- if (!codec->cache_sync)
- goto out;
if (gpio_is_valid(aic3x->gpio_reset)) {
udelay(1);
@@ -1146,12 +1114,8 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
}
/* Sync reg_cache with the hardware */
- codec->cache_only = 0;
- for (i = AIC3X_SAMPLE_RATE_SEL_REG; i < ARRAY_SIZE(aic3x_reg); i++)
- snd_soc_write(codec, i, cache[i]);
- if (aic3x->model == AIC3X_MODEL_3007)
- aic3x_init_3007(codec);
- codec->cache_sync = 0;
+ regcache_cache_only(aic3x->regmap, false);
+ regcache_sync(aic3x->regmap);
} else {
/*
* Do soft reset to this codec instance in order to clear
@@ -1159,10 +1123,10 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
* remain on
*/
snd_soc_write(codec, AIC3X_RESET, SOFT_RESET);
- codec->cache_sync = 1;
+ regcache_mark_dirty(aic3x->regmap);
aic3x->power = 0;
/* HW writes are needless when bias is off */
- codec->cache_only = 1;
+ regcache_cache_only(aic3x->regmap, true);
ret = regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies),
aic3x->supplies);
}
@@ -1317,7 +1281,6 @@ static int aic3x_init(struct snd_soc_codec *codec)
snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
if (aic3x->model == AIC3X_MODEL_3007) {
- aic3x_init_3007(codec);
snd_soc_write(codec, CLASSD_CTRL, 0);
}
@@ -1345,29 +1308,12 @@ static int aic3x_probe(struct snd_soc_codec *codec)
INIT_LIST_HEAD(&aic3x->list);
aic3x->codec = codec;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
- if (gpio_is_valid(aic3x->gpio_reset) &&
- !aic3x_is_shared_reset(aic3x)) {
- ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset");
- if (ret != 0)
- goto err_gpio;
- gpio_direction_output(aic3x->gpio_reset, 0);
- }
-
- for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
- aic3x->supplies[i].supply = aic3x_supply_names[i];
-
- ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies),
- aic3x->supplies);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
- goto err_get;
- }
for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) {
aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event;
aic3x->disable_nb[i].aic3x = aic3x;
@@ -1381,7 +1327,7 @@ static int aic3x_probe(struct snd_soc_codec *codec)
}
}
- codec->cache_only = 1;
+ regcache_mark_dirty(aic3x->regmap);
aic3x_init(codec);
if (aic3x->setup) {
@@ -1392,8 +1338,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
(aic3x->setup->gpio_func[1] & 0xf) << 4);
}
- snd_soc_add_codec_controls(codec, aic3x_snd_controls,
- ARRAY_SIZE(aic3x_snd_controls));
if (aic3x->model == AIC3X_MODEL_3007)
snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
@@ -1424,12 +1368,6 @@ err_notif:
while (i--)
regulator_unregister_notifier(aic3x->supplies[i].consumer,
&aic3x->disable_nb[i].nb);
- regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
-err_get:
- if (gpio_is_valid(aic3x->gpio_reset) &&
- !aic3x_is_shared_reset(aic3x))
- gpio_free(aic3x->gpio_reset);
-err_gpio:
return ret;
}
@@ -1440,15 +1378,9 @@ static int aic3x_remove(struct snd_soc_codec *codec)
aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
list_del(&aic3x->list);
- if (gpio_is_valid(aic3x->gpio_reset) &&
- !aic3x_is_shared_reset(aic3x)) {
- gpio_set_value(aic3x->gpio_reset, 0);
- gpio_free(aic3x->gpio_reset);
- }
for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
regulator_unregister_notifier(aic3x->supplies[i].consumer,
&aic3x->disable_nb[i].nb);
- regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
return 0;
}
@@ -1456,13 +1388,16 @@ static int aic3x_remove(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
.set_bias_level = aic3x_set_bias_level,
.idle_bias_off = true,
- .reg_cache_size = ARRAY_SIZE(aic3x_reg),
- .reg_word_size = sizeof(u8),
- .reg_cache_default = aic3x_reg,
.probe = aic3x_probe,
.remove = aic3x_remove,
.suspend = aic3x_suspend,
.resume = aic3x_resume,
+ .controls = aic3x_snd_controls,
+ .num_controls = ARRAY_SIZE(aic3x_snd_controls),
+ .dapm_widgets = aic3x_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets),
+ .dapm_routes = intercon,
+ .num_dapm_routes = ARRAY_SIZE(intercon),
};
/*
@@ -1479,6 +1414,16 @@ static const struct i2c_device_id aic3x_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
+static const struct reg_default aic3007_class_d[] = {
+ /* Class-D speaker driver init; datasheet p. 46 */
+ { AIC3X_PAGE_SELECT, 0x0D },
+ { 0xD, 0x0D },
+ { 0x8, 0x5C },
+ { 0x8, 0x5D },
+ { 0x8, 0x5C },
+ { AIC3X_PAGE_SELECT, 0x00 },
+};
+
/*
* If the i2c layer weren't so broken, we could pass this kind of data
* around
@@ -1490,7 +1435,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
struct aic3x_priv *aic3x;
struct aic3x_setup_data *ai3x_setup;
struct device_node *np = i2c->dev.of_node;
- int ret;
+ int ret, i;
u32 value;
aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL);
@@ -1499,7 +1444,13 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
return -ENOMEM;
}
- aic3x->control_type = SND_SOC_I2C;
+ aic3x->regmap = devm_regmap_init_i2c(i2c, &aic3x_regmap);
+ if (IS_ERR(aic3x->regmap)) {
+ ret = PTR_ERR(aic3x->regmap);
+ return ret;
+ }
+
+ regcache_cache_only(aic3x->regmap, true);
i2c_set_clientdata(i2c, aic3x);
if (pdata) {
@@ -1551,14 +1502,54 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
aic3x->model = id->driver_data;
+ if (gpio_is_valid(aic3x->gpio_reset) &&
+ !aic3x_is_shared_reset(aic3x)) {
+ ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset");
+ if (ret != 0)
+ goto err;
+ gpio_direction_output(aic3x->gpio_reset, 0);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
+ aic3x->supplies[i].supply = aic3x_supply_names[i];
+
+ ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(aic3x->supplies),
+ aic3x->supplies);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
+ goto err_gpio;
+ }
+
+ if (aic3x->model == AIC3X_MODEL_3007) {
+ ret = regmap_register_patch(aic3x->regmap, aic3007_class_d,
+ ARRAY_SIZE(aic3007_class_d));
+ if (ret != 0)
+ dev_err(&i2c->dev, "Failed to init class D: %d\n",
+ ret);
+ }
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_aic3x, &aic3x_dai, 1);
return ret;
+
+err_gpio:
+ if (gpio_is_valid(aic3x->gpio_reset) &&
+ !aic3x_is_shared_reset(aic3x))
+ gpio_free(aic3x->gpio_reset);
+err:
+ return ret;
}
static int aic3x_i2c_remove(struct i2c_client *client)
{
+ struct aic3x_priv *aic3x = i2c_get_clientdata(client);
+
snd_soc_unregister_codec(&client->dev);
+ if (gpio_is_valid(aic3x->gpio_reset) &&
+ !aic3x_is_shared_reset(aic3x)) {
+ gpio_set_value(aic3x->gpio_reset, 0);
+ gpio_free(aic3x->gpio_reset);
+ }
return 0;
}
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 3c79dbb6c323..35059a242fa4 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -246,7 +246,7 @@ static bool twl6040_is_path_unmuted(struct snd_soc_codec *codec,
return priv->dl2_unmuted;
default:
return 1;
- };
+ }
}
/*
@@ -1100,7 +1100,7 @@ static void twl6040_mute_path(struct snd_soc_codec *codec, enum twl6040_dai_id i
break;
default:
break;
- };
+ }
}
static int twl6040_digital_mute(struct snd_soc_dai *dai, int mute)
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index d2a092850283..48dc7d2fee36 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -32,13 +32,6 @@
#include "wm8400.h"
-/* Fake register for internal state */
-#define WM8400_INTDRIVBITS (WM8400_REGISTER_COUNT + 1)
-#define WM8400_INMIXL_PWR 0
-#define WM8400_AINLMUX_PWR 1
-#define WM8400_INMIXR_PWR 2
-#define WM8400_AINRMUX_PWR 3
-
static struct regulator_bulk_data power[] = {
{
.supply = "I2S1VDD",
@@ -74,32 +67,6 @@ struct wm8400_priv {
int fll_in, fll_out;
};
-static inline unsigned int wm8400_read(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- struct wm8400_priv *wm8400 = snd_soc_codec_get_drvdata(codec);
-
- if (reg == WM8400_INTDRIVBITS)
- return wm8400->fake_register;
- else
- return wm8400_reg_read(wm8400->wm8400, reg);
-}
-
-/*
- * write to the wm8400 register space
- */
-static int wm8400_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- struct wm8400_priv *wm8400 = snd_soc_codec_get_drvdata(codec);
-
- if (reg == WM8400_INTDRIVBITS) {
- wm8400->fake_register = value;
- return 0;
- } else
- return wm8400_set_bits(wm8400->wm8400, reg, 0xffff, value);
-}
-
static void wm8400_codec_reset(struct snd_soc_codec *codec)
{
struct wm8400_priv *wm8400 = snd_soc_codec_get_drvdata(codec);
@@ -352,32 +319,6 @@ SOC_SINGLE("RIN34 Mute Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME,
* _DAPM_ Controls
*/
-static int inmixer_event (struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- u16 reg, fakepower;
-
- reg = snd_soc_read(w->codec, WM8400_POWER_MANAGEMENT_2);
- fakepower = snd_soc_read(w->codec, WM8400_INTDRIVBITS);
-
- if (fakepower & ((1 << WM8400_INMIXL_PWR) |
- (1 << WM8400_AINLMUX_PWR))) {
- reg |= WM8400_AINL_ENA;
- } else {
- reg &= ~WM8400_AINL_ENA;
- }
-
- if (fakepower & ((1 << WM8400_INMIXR_PWR) |
- (1 << WM8400_AINRMUX_PWR))) {
- reg |= WM8400_AINR_ENA;
- } else {
- reg &= ~WM8400_AINR_ENA;
- }
- snd_soc_write(w->codec, WM8400_POWER_MANAGEMENT_2, reg);
-
- return 0;
-}
-
static int outmixer_event (struct snd_soc_dapm_widget *w,
struct snd_kcontrol * kcontrol, int event)
{
@@ -658,27 +599,26 @@ SND_SOC_DAPM_MIXER("RIN34 PGA", WM8400_POWER_MANAGEMENT_2,
0, &wm8400_dapm_rin34_pga_controls[0],
ARRAY_SIZE(wm8400_dapm_rin34_pga_controls)),
+SND_SOC_DAPM_SUPPLY("INL", WM8400_POWER_MANAGEMENT_2, WM8400_AINL_ENA_SHIFT,
+ 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("INR", WM8400_POWER_MANAGEMENT_2, WM8400_AINR_ENA_SHIFT,
+ 0, NULL, 0),
+
/* INMIXL */
-SND_SOC_DAPM_MIXER_E("INMIXL", WM8400_INTDRIVBITS, WM8400_INMIXL_PWR, 0,
+SND_SOC_DAPM_MIXER("INMIXL", SND_SOC_NOPM, 0, 0,
&wm8400_dapm_inmixl_controls[0],
- ARRAY_SIZE(wm8400_dapm_inmixl_controls),
- inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ ARRAY_SIZE(wm8400_dapm_inmixl_controls)),
/* AINLMUX */
-SND_SOC_DAPM_MUX_E("AILNMUX", WM8400_INTDRIVBITS, WM8400_AINLMUX_PWR, 0,
- &wm8400_dapm_ainlmux_controls, inmixer_event,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_MUX("AILNMUX", SND_SOC_NOPM, 0, 0, &wm8400_dapm_ainlmux_controls),
/* INMIXR */
-SND_SOC_DAPM_MIXER_E("INMIXR", WM8400_INTDRIVBITS, WM8400_INMIXR_PWR, 0,
+SND_SOC_DAPM_MIXER("INMIXR", SND_SOC_NOPM, 0, 0,
&wm8400_dapm_inmixr_controls[0],
- ARRAY_SIZE(wm8400_dapm_inmixr_controls),
- inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ ARRAY_SIZE(wm8400_dapm_inmixr_controls)),
/* AINRMUX */
-SND_SOC_DAPM_MUX_E("AIRNMUX", WM8400_INTDRIVBITS, WM8400_AINRMUX_PWR, 0,
- &wm8400_dapm_ainrmux_controls, inmixer_event,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_MUX("AIRNMUX", SND_SOC_NOPM, 0, 0, &wm8400_dapm_ainrmux_controls),
/* Output Side */
/* DACs */
@@ -789,11 +729,13 @@ static const struct snd_soc_dapm_route wm8400_dapm_routes[] = {
{"LIN34 PGA", "LIN3 Switch", "LIN3"},
{"LIN34 PGA", "LIN4 Switch", "LIN4/RXN"},
/* INMIXL */
+ {"INMIXL", NULL, "INL"},
{"INMIXL", "Record Left Volume", "LOMIX"},
{"INMIXL", "LIN2 Volume", "LIN2"},
{"INMIXL", "LINPGA12 Switch", "LIN12 PGA"},
{"INMIXL", "LINPGA34 Switch", "LIN34 PGA"},
/* AILNMUX */
+ {"AILNMUX", NULL, "INL"},
{"AILNMUX", "INMIXL Mix", "INMIXL"},
{"AILNMUX", "DIFFINL Mix", "LIN12 PGA"},
{"AILNMUX", "DIFFINL Mix", "LIN34 PGA"},
@@ -808,12 +750,14 @@ static const struct snd_soc_dapm_route wm8400_dapm_routes[] = {
/* RIN34 PGA */
{"RIN34 PGA", "RIN3 Switch", "RIN3"},
{"RIN34 PGA", "RIN4 Switch", "RIN4/RXP"},
- /* INMIXL */
+ /* INMIXR */
+ {"INMIXR", NULL, "INR"},
{"INMIXR", "Record Right Volume", "ROMIX"},
{"INMIXR", "RIN2 Volume", "RIN2"},
{"INMIXR", "RINPGA12 Switch", "RIN12 PGA"},
{"INMIXR", "RINPGA34 Switch", "RIN34 PGA"},
/* AIRNMUX */
+ {"AIRNMUX", NULL, "INR"},
{"AIRNMUX", "INMIXR Mix", "INMIXR"},
{"AIRNMUX", "DIFFINR Mix", "RIN12 PGA"},
{"AIRNMUX", "DIFFINR Mix", "RIN34 PGA"},
@@ -1365,9 +1309,12 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec)
return -ENOMEM;
snd_soc_codec_set_drvdata(codec, priv);
- codec->control_data = priv->wm8400 = wm8400;
+ priv->wm8400 = wm8400;
+ codec->control_data = wm8400->regmap;
priv->codec = codec;
+ snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
+
ret = devm_regulator_bulk_get(wm8400->dev,
ARRAY_SIZE(power), &power[0]);
if (ret != 0) {
@@ -1414,8 +1361,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8400 = {
.remove = wm8400_codec_remove,
.suspend = wm8400_suspend,
.resume = wm8400_resume,
- .read = snd_soc_read,
- .write = wm8400_write,
.set_bias_level = wm8400_set_bias_level,
.controls = wm8400_snd_controls,
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index fd7c45b9ed5a..2f8161c1d5f0 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -27,6 +27,10 @@
#include "davinci-i2s.h"
#include "davinci-mcasp.h"
+struct snd_soc_card_drvdata_davinci {
+ unsigned sysclk;
+};
+
#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
static int evm_hw_params(struct snd_pcm_substream *substream,
@@ -35,27 +39,11 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_card *soc_card = codec->card;
int ret = 0;
- unsigned sysclk;
-
- /* ASP1 on DM355 EVM is clocked by an external oscillator */
- if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm() ||
- machine_is_davinci_dm365_evm())
- sysclk = 27000000;
-
- /* ASP0 in DM6446 EVM is clocked by U55, as configured by
- * board-dm644x-evm.c using GPIOs from U18. There are six
- * options; here we "know" we use a 48 KHz sample rate.
- */
- else if (machine_is_davinci_evm())
- sysclk = 12288000;
-
- else if (machine_is_davinci_da830_evm() ||
- machine_is_davinci_da850_evm())
- sysclk = 24576000;
-
- else
- return -EINVAL;
+ unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *)
+ snd_soc_card_get_drvdata(soc_card))->sysclk;
/* set codec DAI configuration */
ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT);
@@ -243,35 +231,65 @@ static struct snd_soc_dai_link da850_evm_dai = {
};
/* davinci dm6446 evm audio machine driver */
+/*
+ * ASP0 in DM6446 EVM is clocked by U55, as configured by
+ * board-dm644x-evm.c using GPIOs from U18. There are six
+ * options; here we "know" we use a 48 KHz sample rate.
+ */
+static struct snd_soc_card_drvdata_davinci dm6446_snd_soc_card_drvdata = {
+ .sysclk = 12288000,
+};
+
static struct snd_soc_card dm6446_snd_soc_card_evm = {
.name = "DaVinci DM6446 EVM",
.owner = THIS_MODULE,
.dai_link = &dm6446_evm_dai,
.num_links = 1,
+ .drvdata = &dm6446_snd_soc_card_drvdata,
};
/* davinci dm355 evm audio machine driver */
+/* ASP1 on DM355 EVM is clocked by an external oscillator */
+static struct snd_soc_card_drvdata_davinci dm355_snd_soc_card_drvdata = {
+ .sysclk = 27000000,
+};
+
static struct snd_soc_card dm355_snd_soc_card_evm = {
.name = "DaVinci DM355 EVM",
.owner = THIS_MODULE,
.dai_link = &dm355_evm_dai,
.num_links = 1,
+ .drvdata = &dm355_snd_soc_card_drvdata,
};
/* davinci dm365 evm audio machine driver */
+static struct snd_soc_card_drvdata_davinci dm365_snd_soc_card_drvdata = {
+ .sysclk = 27000000,
+};
+
static struct snd_soc_card dm365_snd_soc_card_evm = {
.name = "DaVinci DM365 EVM",
.owner = THIS_MODULE,
.dai_link = &dm365_evm_dai,
.num_links = 1,
+ .drvdata = &dm365_snd_soc_card_drvdata,
};
/* davinci dm6467 evm audio machine driver */
+static struct snd_soc_card_drvdata_davinci dm6467_snd_soc_card_drvdata = {
+ .sysclk = 27000000,
+};
+
static struct snd_soc_card dm6467_snd_soc_card_evm = {
.name = "DaVinci DM6467 EVM",
.owner = THIS_MODULE,
.dai_link = dm6467_evm_dai,
.num_links = ARRAY_SIZE(dm6467_evm_dai),
+ .drvdata = &dm6467_snd_soc_card_drvdata,
+};
+
+static struct snd_soc_card_drvdata_davinci da830_snd_soc_card_drvdata = {
+ .sysclk = 24576000,
};
static struct snd_soc_card da830_snd_soc_card = {
@@ -279,6 +297,11 @@ static struct snd_soc_card da830_snd_soc_card = {
.owner = THIS_MODULE,
.dai_link = &da830_evm_dai,
.num_links = 1,
+ .drvdata = &da830_snd_soc_card_drvdata,
+};
+
+static struct snd_soc_card_drvdata_davinci da850_snd_soc_card_drvdata = {
+ .sysclk = 24576000,
};
static struct snd_soc_card da850_snd_soc_card = {
@@ -286,6 +309,7 @@ static struct snd_soc_card da850_snd_soc_card = {
.owner = THIS_MODULE,
.dai_link = &da850_evm_dai,
.num_links = 1,
+ .drvdata = &da850_snd_soc_card_drvdata,
};
static struct platform_device *evm_snd_device;
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 3920c3e849ce..ff1f34766ee3 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -963,7 +963,7 @@ static bool fsl_spdif_readable_reg(struct device *dev, unsigned int reg)
return true;
default:
return false;
- };
+ }
}
static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg)
@@ -982,7 +982,7 @@ static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg)
return true;
default:
return false;
- };
+ }
}
static const struct regmap_config fsl_spdif_regmap_config = {
@@ -1172,23 +1172,16 @@ static int fsl_spdif_probe(struct platform_device *pdev)
/* Register with ASoC */
dev_set_drvdata(&pdev->dev, spdif_priv);
- ret = snd_soc_register_component(&pdev->dev, &fsl_spdif_component,
- &spdif_priv->cpu_dai_drv, 1);
+ ret = devm_snd_soc_register_component(&pdev->dev, &fsl_spdif_component,
+ &spdif_priv->cpu_dai_drv, 1);
if (ret) {
dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
return ret;
}
ret = imx_pcm_dma_init(pdev);
- if (ret) {
+ if (ret)
dev_err(&pdev->dev, "imx_pcm_dma_init failed: %d\n", ret);
- goto error_component;
- }
-
- return ret;
-
-error_component:
- snd_soc_unregister_component(&pdev->dev);
return ret;
}
@@ -1196,7 +1189,6 @@ error_component:
static int fsl_spdif_remove(struct platform_device *pdev)
{
imx_pcm_dma_exit(pdev);
- snd_soc_unregister_component(&pdev->dev);
return 0;
}
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index c6b743978d5e..35e277379b86 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -469,19 +469,12 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
* parameters, then the second stream may be
* constrained to the wrong sample rate or size.
*/
- if (!first_runtime->sample_bits) {
- dev_err(substream->pcm->card->dev,
- "set sample size in %s stream first\n",
- substream->stream ==
- SNDRV_PCM_STREAM_PLAYBACK
- ? "capture" : "playback");
- return -EAGAIN;
- }
-
- snd_pcm_hw_constraint_minmax(substream->runtime,
- SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+ if (first_runtime->sample_bits) {
+ snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
first_runtime->sample_bits,
first_runtime->sample_bits);
+ }
}
ssi_private->second_stream = substream;
@@ -748,7 +741,7 @@ static void fsl_ssi_ac97_init(void)
fsl_ssi_setup(fsl_ac97_data);
}
-void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
unsigned short val)
{
struct ccsr_ssi *ssi = fsl_ac97_data->ssi;
@@ -770,7 +763,7 @@ void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
udelay(100);
}
-unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97,
+static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97,
unsigned short reg)
{
struct ccsr_ssi *ssi = fsl_ac97_data->ssi;
@@ -936,7 +929,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
ssi_private->ssi_phys = res.start;
ssi_private->irq = irq_of_parse_and_map(np, 0);
- if (ssi_private->irq == NO_IRQ) {
+ if (!ssi_private->irq) {
dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
return -ENXIO;
}
@@ -1135,7 +1128,6 @@ static int fsl_ssi_remove(struct platform_device *pdev)
if (ssi_private->ssi_on_imx)
imx_pcm_dma_exit(pdev);
snd_soc_unregister_component(&pdev->dev);
- dev_set_drvdata(&pdev->dev, NULL);
device_remove_file(&pdev->dev, &ssi_private->dev_attr);
if (ssi_private->ssi_on_imx)
clk_disable_unprepare(ssi_private->clk);
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c
index 46c5b4fdfc52..6f4bdc89ae3c 100644
--- a/sound/soc/fsl/imx-sgtl5000.c
+++ b/sound/soc/fsl/imx-sgtl5000.c
@@ -62,7 +62,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
struct device_node *ssi_np, *codec_np;
struct platform_device *ssi_pdev;
struct i2c_client *codec_dev;
- struct imx_sgtl5000_data *data;
+ struct imx_sgtl5000_data *data = NULL;
int int_port, ext_port;
int ret;
@@ -128,7 +128,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
goto fail;
}
- data->codec_clk = devm_clk_get(&codec_dev->dev, NULL);
+ data->codec_clk = clk_get(&codec_dev->dev, NULL);
if (IS_ERR(data->codec_clk)) {
ret = PTR_ERR(data->codec_clk);
goto fail;
@@ -159,7 +159,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
data->card.dapm_widgets = imx_sgtl5000_dapm_widgets;
data->card.num_dapm_widgets = ARRAY_SIZE(imx_sgtl5000_dapm_widgets);
- ret = snd_soc_register_card(&data->card);
+ ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
goto fail;
@@ -172,6 +172,8 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
return 0;
fail:
+ if (data && !IS_ERR(data->codec_clk))
+ clk_put(data->codec_clk);
if (ssi_np)
of_node_put(ssi_np);
if (codec_np)
@@ -184,7 +186,7 @@ static int imx_sgtl5000_remove(struct platform_device *pdev)
{
struct imx_sgtl5000_data *data = platform_get_drvdata(pdev);
- snd_soc_unregister_card(&data->card);
+ clk_put(data->codec_clk);
return 0;
}
@@ -202,7 +204,6 @@ static struct platform_driver imx_sgtl5000_driver = {
.of_match_table = imx_sgtl5000_dt_ids,
},
.probe = imx_sgtl5000_probe,
- .remove = imx_sgtl5000_remove,
};
module_platform_driver(imx_sgtl5000_driver);
diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c
index 816013b0ebba..8499d5292f08 100644
--- a/sound/soc/fsl/imx-spdif.c
+++ b/sound/soc/fsl/imx-spdif.c
@@ -87,7 +87,7 @@ static int imx_spdif_audio_probe(struct platform_device *pdev)
if (ret)
goto error_dir;
- ret = snd_soc_register_card(&data->card);
+ ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed: %d\n", ret);
goto error_dir;
@@ -119,8 +119,6 @@ static int imx_spdif_audio_remove(struct platform_device *pdev)
if (data->txdev)
platform_device_unregister(data->txdev);
- snd_soc_unregister_card(&data->card);
-
return 0;
}
diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c
index 722afe69169e..6c6066618f3b 100644
--- a/sound/soc/fsl/imx-wm8962.c
+++ b/sound/soc/fsl/imx-wm8962.c
@@ -266,7 +266,7 @@ static int imx_wm8962_probe(struct platform_device *pdev)
data->card.late_probe = imx_wm8962_late_probe;
data->card.set_bias_level = imx_wm8962_set_bias_level;
- ret = snd_soc_register_card(&data->card);
+ ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
goto clk_fail;
@@ -296,7 +296,6 @@ static int imx_wm8962_remove(struct platform_device *pdev)
if (!IS_ERR(data->codec_clk))
clk_disable_unprepare(data->codec_clk);
- snd_soc_unregister_card(&data->card);
return 0;
}
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index b238434f92b0..0c85c4e1a1ae 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -29,9 +29,7 @@
#define KIRKWOOD_FORMATS \
(SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE | \
- SNDRV_PCM_FMTBIT_S32_LE | \
- SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | \
- SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE)
+ SNDRV_PCM_FMTBIT_S32_LE)
static struct kirkwood_dma_data *kirkwood_priv(struct snd_pcm_substream *subs)
{
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c
index ee363845759e..d3d4c32434f7 100644
--- a/sound/soc/mid-x86/mfld_machine.c
+++ b/sound/soc/mid-x86/mfld_machine.c
@@ -400,7 +400,7 @@ static int snd_mfld_mc_probe(struct platform_device *pdev)
}
/* register the soc card */
snd_soc_card_mfld.dev = &pdev->dev;
- ret_val = snd_soc_register_card(&snd_soc_card_mfld);
+ ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_mfld);
if (ret_val) {
pr_debug("snd_soc_register_card failed %d\n", ret_val);
return ret_val;
@@ -410,20 +410,12 @@ static int snd_mfld_mc_probe(struct platform_device *pdev)
return 0;
}
-static int snd_mfld_mc_remove(struct platform_device *pdev)
-{
- pr_debug("snd_mfld_mc_remove called\n");
- snd_soc_unregister_card(&snd_soc_card_mfld);
- return 0;
-}
-
static struct platform_driver snd_mfld_mc_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "msic_audio",
},
.probe = snd_mfld_mc_probe,
- .remove = snd_mfld_mc_remove,
};
module_platform_driver(snd_mfld_mc_driver);
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index b56b8a0e8deb..14152f6f70dd 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -768,8 +768,8 @@ static int mxs_saif_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "failed to init clocks\n");
}
- ret = snd_soc_register_component(&pdev->dev, &mxs_saif_component,
- &mxs_saif_dai, 1);
+ ret = devm_snd_soc_register_component(&pdev->dev, &mxs_saif_component,
+ &mxs_saif_dai, 1);
if (ret) {
dev_err(&pdev->dev, "register DAI failed\n");
return ret;
@@ -778,21 +778,15 @@ static int mxs_saif_probe(struct platform_device *pdev)
ret = mxs_pcm_platform_register(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
- goto failed_pdev_alloc;
+ return ret;
}
return 0;
-
-failed_pdev_alloc:
- snd_soc_unregister_component(&pdev->dev);
-
- return ret;
}
static int mxs_saif_remove(struct platform_device *pdev)
{
mxs_pcm_platform_unregister(&pdev->dev);
- snd_soc_unregister_component(&pdev->dev);
return 0;
}
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c
index 4bb273786ff3..61822cc53bd3 100644
--- a/sound/soc/mxs/mxs-sgtl5000.c
+++ b/sound/soc/mxs/mxs-sgtl5000.c
@@ -122,14 +122,12 @@ static struct snd_soc_card mxs_sgtl5000 = {
.num_links = ARRAY_SIZE(mxs_sgtl5000_dai),
};
-static int mxs_sgtl5000_probe_dt(struct platform_device *pdev)
+static int mxs_sgtl5000_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &mxs_sgtl5000;
+ int ret, i;
struct device_node *np = pdev->dev.of_node;
struct device_node *saif_np[2], *codec_np;
- int i;
-
- if (!np)
- return 1; /* no device tree */
saif_np[0] = of_parse_phandle(np, "saif-controllers", 0);
saif_np[1] = of_parse_phandle(np, "saif-controllers", 1);
@@ -152,18 +150,6 @@ static int mxs_sgtl5000_probe_dt(struct platform_device *pdev)
of_node_put(saif_np[0]);
of_node_put(saif_np[1]);
- return 0;
-}
-
-static int mxs_sgtl5000_probe(struct platform_device *pdev)
-{
- struct snd_soc_card *card = &mxs_sgtl5000;
- int ret;
-
- ret = mxs_sgtl5000_probe_dt(pdev);
- if (ret < 0)
- return ret;
-
/*
* Set an init clock(11.28Mhz) for sgtl5000 initialization(i2c r/w).
* The Sgtl5000 sysclk is derived from saif0 mclk and it's range
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index 90d2a7cd2563..cd9ee167959d 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -490,14 +490,9 @@ static int asoc_mcpdm_probe(struct platform_device *pdev)
mcpdm->dev = &pdev->dev;
- return snd_soc_register_component(&pdev->dev, &omap_mcpdm_component,
- &omap_mcpdm_dai, 1);
-}
-
-static int asoc_mcpdm_remove(struct platform_device *pdev)
-{
- snd_soc_unregister_component(&pdev->dev);
- return 0;
+ return devm_snd_soc_register_component(&pdev->dev,
+ &omap_mcpdm_component,
+ &omap_mcpdm_dai, 1);
}
static const struct of_device_id omap_mcpdm_of_match[] = {
@@ -514,7 +509,6 @@ static struct platform_driver asoc_mcpdm_driver = {
},
.probe = asoc_mcpdm_probe,
- .remove = asoc_mcpdm_remove,
};
module_platform_driver(asoc_mcpdm_driver);
diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c
index 2a9324f794d8..6a8d6b5f160d 100644
--- a/sound/soc/omap/omap-twl4030.c
+++ b/sound/soc/omap/omap-twl4030.c
@@ -338,9 +338,9 @@ static int omap_twl4030_probe(struct platform_device *pdev)
}
snd_soc_card_set_drvdata(card, priv);
- ret = snd_soc_register_card(card);
+ ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) {
- dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ dev_err(&pdev->dev, "devm_snd_soc_register_card() failed: %d\n",
ret);
return ret;
}
@@ -357,7 +357,6 @@ static int omap_twl4030_remove(struct platform_device *pdev)
snd_soc_jack_free_gpios(&priv->hs_jack,
ARRAY_SIZE(hs_jack_gpios),
hs_jack_gpios);
- snd_soc_unregister_card(card);
return 0;
}
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
index 41752a5fe3b0..5bf5f1f7cac5 100644
--- a/sound/soc/pxa/mmp-sspa.c
+++ b/sound/soc/pxa/mmp-sspa.c
@@ -455,8 +455,8 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev)
priv->dai_fmt = (unsigned int) -1;
platform_set_drvdata(pdev, priv);
- return snd_soc_register_component(&pdev->dev, &mmp_sspa_component,
- &mmp_sspa_dai, 1);
+ return devm_snd_soc_register_component(&pdev->dev, &mmp_sspa_component,
+ &mmp_sspa_dai, 1);
}
static int asoc_mmp_sspa_remove(struct platform_device *pdev)
@@ -466,7 +466,6 @@ static int asoc_mmp_sspa_remove(struct platform_device *pdev)
clk_disable(priv->audio_clk);
clk_put(priv->audio_clk);
clk_put(priv->sysclk);
- snd_soc_unregister_component(&pdev->dev);
return 0;
}
diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c
index 29e246803626..84f5d8b76679 100644
--- a/sound/soc/samsung/bells.c
+++ b/sound/soc/samsung/bells.c
@@ -356,6 +356,7 @@ static struct snd_soc_dapm_widget bells_widgets[] = {
static struct snd_soc_dapm_route bells_routes[] = {
{ "Sub CLK_SYS", NULL, "OPCLK" },
+ { "CLKIN", NULL, "OPCLK" },
{ "DMIC", NULL, "MICBIAS2" },
{ "IN2L", NULL, "DMIC" },
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index b302f3b7a587..32956df8f50c 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -1060,7 +1060,7 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
i2s->i2s_dai_drv.ops = &samsung_i2s_dai_ops;
i2s->i2s_dai_drv.suspend = i2s_suspend;
i2s->i2s_dai_drv.resume = i2s_resume;
- i2s->i2s_dai_drv.playback.channels_min = 2;
+ i2s->i2s_dai_drv.playback.channels_min = 1;
i2s->i2s_dai_drv.playback.channels_max = 2;
i2s->i2s_dai_drv.playback.rates = SAMSUNG_I2S_RATES;
i2s->i2s_dai_drv.playback.formats = SAMSUNG_I2S_FMTS;
@@ -1143,9 +1143,9 @@ static int samsung_i2s_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Unable to get drvdata\n");
return -EFAULT;
}
- snd_soc_register_component(&sec_dai->pdev->dev,
- &samsung_i2s_component,
- &sec_dai->i2s_dai_drv, 1);
+ devm_snd_soc_register_component(&sec_dai->pdev->dev,
+ &samsung_i2s_component,
+ &sec_dai->i2s_dai_drv, 1);
samsung_asoc_dma_platform_register(&pdev->dev);
return 0;
}
@@ -1258,8 +1258,9 @@ static int samsung_i2s_probe(struct platform_device *pdev)
goto err;
}
- snd_soc_register_component(&pri_dai->pdev->dev, &samsung_i2s_component,
- &pri_dai->i2s_dai_drv, 1);
+ devm_snd_soc_register_component(&pri_dai->pdev->dev,
+ &samsung_i2s_component,
+ &pri_dai->i2s_dai_drv, 1);
pm_runtime_enable(&pdev->dev);
@@ -1294,7 +1295,6 @@ static int samsung_i2s_remove(struct platform_device *pdev)
i2s->sec_dai = NULL;
samsung_asoc_dma_platform_unregister(&pdev->dev);
- snd_soc_unregister_component(&pdev->dev);
return 0;
}
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c
index 5fd7a05a9b9e..831972d24fb9 100644
--- a/sound/soc/samsung/smdk_wm8994.c
+++ b/sound/soc/samsung/smdk_wm8994.c
@@ -193,7 +193,7 @@ static int smdk_audio_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, board);
- ret = snd_soc_register_card(card);
+ ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret)
dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret);
@@ -201,15 +201,6 @@ static int smdk_audio_probe(struct platform_device *pdev)
return ret;
}
-static int smdk_audio_remove(struct platform_device *pdev)
-{
- struct snd_soc_card *card = platform_get_drvdata(pdev);
-
- snd_soc_unregister_card(card);
-
- return 0;
-}
-
static struct platform_driver smdk_audio_driver = {
.driver = {
.name = "smdk-audio-wm8894",
@@ -217,7 +208,6 @@ static struct platform_driver smdk_audio_driver = {
.of_match_table = of_match_ptr(samsung_wm8994_of_match),
},
.probe = smdk_audio_probe,
- .remove = smdk_audio_remove,
};
module_platform_driver(smdk_audio_driver);
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
index d80deb7ccf13..9430097979a5 100644
--- a/sound/soc/sh/rcar/adg.c
+++ b/sound/soc/sh/rcar/adg.c
@@ -8,7 +8,6 @@
* for more details.
*/
#include <linux/sh_clk.h>
-#include <mach/clock.h>
#include "rsnd.h"
#define CLKA 0
@@ -22,6 +21,7 @@ struct rsnd_adg {
int rate_of_441khz_div_6;
int rate_of_48khz_div_6;
+ u32 ckr;
};
#define for_each_rsnd_clk(pos, adg, i) \
@@ -116,6 +116,11 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate)
found_clock:
+ /* see rsnd_adg_ssi_clk_init() */
+ rsnd_mod_bset(mod, SSICKR, 0x00FF0000, adg->ckr);
+ rsnd_mod_write(mod, BRRA, 0x00000002); /* 1/6 */
+ rsnd_mod_write(mod, BRRB, 0x00000002); /* 1/6 */
+
/*
* This "mod" = "ssi" here.
* we can get "ssi id" from mod
@@ -182,9 +187,7 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
}
}
- rsnd_priv_bset(priv, SSICKR, 0x00FF0000, ckr);
- rsnd_priv_write(priv, BRRA, 0x00000002); /* 1/6 */
- rsnd_priv_write(priv, BRRB, 0x00000002); /* 1/6 */
+ adg->ckr = ckr;
}
int rsnd_adg_probe(struct platform_device *pdev,
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index a35706028514..fc83f0f2aead 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -106,51 +106,6 @@
(!(priv->info->func) ? -ENODEV : \
priv->info->func(param))
-
-/*
- * basic function
- */
-u32 rsnd_read(struct rsnd_priv *priv,
- struct rsnd_mod *mod, enum rsnd_reg reg)
-{
- void __iomem *base = rsnd_gen_reg_get(priv, mod, reg);
-
- BUG_ON(!base);
-
- return ioread32(base);
-}
-
-void rsnd_write(struct rsnd_priv *priv,
- struct rsnd_mod *mod,
- enum rsnd_reg reg, u32 data)
-{
- void __iomem *base = rsnd_gen_reg_get(priv, mod, reg);
- struct device *dev = rsnd_priv_to_dev(priv);
-
- BUG_ON(!base);
-
- dev_dbg(dev, "w %p : %08x\n", base, data);
-
- iowrite32(data, base);
-}
-
-void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
- enum rsnd_reg reg, u32 mask, u32 data)
-{
- void __iomem *base = rsnd_gen_reg_get(priv, mod, reg);
- struct device *dev = rsnd_priv_to_dev(priv);
- u32 val;
-
- BUG_ON(!base);
-
- val = ioread32(base);
- val &= ~mask;
- val |= data & mask;
- iowrite32(val, base);
-
- dev_dbg(dev, "s %p : %08x\n", base, val);
-}
-
/*
* rsnd_mod functions
*/
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
index babb203b43b7..61212ee97c28 100644
--- a/sound/soc/sh/rcar/gen.c
+++ b/sound/soc/sh/rcar/gen.c
@@ -11,6 +11,11 @@
#include "rsnd.h"
struct rsnd_gen_ops {
+ int (*probe)(struct platform_device *pdev,
+ struct rcar_snd_info *info,
+ struct rsnd_priv *priv);
+ void (*remove)(struct platform_device *pdev,
+ struct rsnd_priv *priv);
int (*path_init)(struct rsnd_priv *priv,
struct rsnd_dai *rdai,
struct rsnd_dai_stream *io);
@@ -19,21 +24,97 @@ struct rsnd_gen_ops {
struct rsnd_dai_stream *io);
};
-struct rsnd_gen_reg_map {
- int index; /* -1 : not supported */
- u32 offset_id; /* offset of ssi0, ssi1, ssi2... */
- u32 offset_adr; /* offset of SSICR, SSISR, ... */
-};
-
struct rsnd_gen {
void __iomem *base[RSND_BASE_MAX];
- struct rsnd_gen_reg_map reg_map[RSND_REG_MAX];
struct rsnd_gen_ops *ops;
+
+ struct regmap *regmap;
+ struct regmap_field *regs[RSND_REG_MAX];
};
#define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen)
+#define RSND_REG_SET(gen, id, reg_id, offset, _id_offset, _id_size) \
+ [id] = { \
+ .reg = (unsigned int)gen->base[reg_id] + offset, \
+ .lsb = 0, \
+ .msb = 31, \
+ .id_size = _id_size, \
+ .id_offset = _id_offset, \
+ }
+
+/*
+ * basic function
+ */
+static int rsnd_regmap_write32(void *context, const void *_data, size_t count)
+{
+ struct rsnd_priv *priv = context;
+ struct device *dev = rsnd_priv_to_dev(priv);
+ u32 *data = (u32 *)_data;
+ u32 val = data[1];
+ void __iomem *reg = (void *)data[0];
+
+ iowrite32(val, reg);
+
+ dev_dbg(dev, "w %p : %08x\n", reg, val);
+
+ return 0;
+}
+
+static int rsnd_regmap_read32(void *context,
+ const void *_data, size_t reg_size,
+ void *_val, size_t val_size)
+{
+ struct rsnd_priv *priv = context;
+ struct device *dev = rsnd_priv_to_dev(priv);
+ u32 *data = (u32 *)_data;
+ u32 *val = (u32 *)_val;
+ void __iomem *reg = (void *)data[0];
+
+ *val = ioread32(reg);
+
+ dev_dbg(dev, "r %p : %08x\n", reg, *val);
+
+ return 0;
+}
+
+static struct regmap_bus rsnd_regmap_bus = {
+ .write = rsnd_regmap_write32,
+ .read = rsnd_regmap_read32,
+ .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+ .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+u32 rsnd_read(struct rsnd_priv *priv,
+ struct rsnd_mod *mod, enum rsnd_reg reg)
+{
+ struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
+ u32 val;
+
+ regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val);
+
+ return val;
+}
+
+void rsnd_write(struct rsnd_priv *priv,
+ struct rsnd_mod *mod,
+ enum rsnd_reg reg, u32 data)
+{
+ struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
+
+ regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data);
+}
+
+void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
+ enum rsnd_reg reg, u32 mask, u32 data)
+{
+ struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
+
+ regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod),
+ mask, data);
+}
+
/*
* Gen2
* will be filled in the future
@@ -98,44 +179,64 @@ static int rsnd_gen1_path_exit(struct rsnd_priv *priv,
return ret;
}
-static struct rsnd_gen_ops rsnd_gen1_ops = {
- .path_init = rsnd_gen1_path_init,
- .path_exit = rsnd_gen1_path_exit,
-};
+/* single address mapping */
+#define RSND_GEN1_S_REG(gen, reg, id, offset) \
+ RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9)
-#define RSND_GEN1_REG_MAP(g, s, i, oi, oa) \
- do { \
- (g)->reg_map[RSND_REG_##i].index = RSND_GEN1_##s; \
- (g)->reg_map[RSND_REG_##i].offset_id = oi; \
- (g)->reg_map[RSND_REG_##i].offset_adr = oa; \
- } while (0)
+/* multi address mapping */
+#define RSND_GEN1_M_REG(gen, reg, id, offset, _id_offset) \
+ RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, _id_offset, 9)
-static void rsnd_gen1_reg_map_init(struct rsnd_gen *gen)
+static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen)
{
- RSND_GEN1_REG_MAP(gen, SRU, SRC_ROUTE_SEL, 0x0, 0x00);
- RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL0, 0x0, 0x08);
- RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL1, 0x0, 0x0c);
- RSND_GEN1_REG_MAP(gen, SRU, SRC_TMG_SEL2, 0x0, 0x10);
- RSND_GEN1_REG_MAP(gen, SRU, SRC_CTRL, 0x0, 0xc0);
- RSND_GEN1_REG_MAP(gen, SRU, SSI_MODE0, 0x0, 0xD0);
- RSND_GEN1_REG_MAP(gen, SRU, SSI_MODE1, 0x0, 0xD4);
- RSND_GEN1_REG_MAP(gen, SRU, BUSIF_MODE, 0x4, 0x20);
- RSND_GEN1_REG_MAP(gen, SRU, BUSIF_ADINR, 0x40, 0x214);
-
- RSND_GEN1_REG_MAP(gen, ADG, BRRA, 0x0, 0x00);
- RSND_GEN1_REG_MAP(gen, ADG, BRRB, 0x0, 0x04);
- RSND_GEN1_REG_MAP(gen, ADG, SSICKR, 0x0, 0x08);
- RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL0, 0x0, 0x0c);
- RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL1, 0x0, 0x10);
- RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL3, 0x0, 0x18);
- RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL4, 0x0, 0x1c);
- RSND_GEN1_REG_MAP(gen, ADG, AUDIO_CLK_SEL5, 0x0, 0x20);
-
- RSND_GEN1_REG_MAP(gen, SSI, SSICR, 0x40, 0x00);
- RSND_GEN1_REG_MAP(gen, SSI, SSISR, 0x40, 0x04);
- RSND_GEN1_REG_MAP(gen, SSI, SSITDR, 0x40, 0x08);
- RSND_GEN1_REG_MAP(gen, SSI, SSIRDR, 0x40, 0x0c);
- RSND_GEN1_REG_MAP(gen, SSI, SSIWSR, 0x40, 0x20);
+ int i;
+ struct device *dev = rsnd_priv_to_dev(priv);
+ struct regmap_config regc;
+ struct reg_field regf[RSND_REG_MAX] = {
+ RSND_GEN1_S_REG(gen, SRU, SRC_ROUTE_SEL, 0x00),
+ RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL0, 0x08),
+ RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL1, 0x0c),
+ RSND_GEN1_S_REG(gen, SRU, SRC_TMG_SEL2, 0x10),
+ RSND_GEN1_S_REG(gen, SRU, SRC_CTRL, 0xc0),
+ RSND_GEN1_S_REG(gen, SRU, SSI_MODE0, 0xD0),
+ RSND_GEN1_S_REG(gen, SRU, SSI_MODE1, 0xD4),
+ RSND_GEN1_M_REG(gen, SRU, BUSIF_MODE, 0x20, 0x4),
+ RSND_GEN1_M_REG(gen, SRU, BUSIF_ADINR, 0x214, 0x40),
+
+ RSND_GEN1_S_REG(gen, ADG, BRRA, 0x00),
+ RSND_GEN1_S_REG(gen, ADG, BRRB, 0x04),
+ RSND_GEN1_S_REG(gen, ADG, SSICKR, 0x08),
+ RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c),
+ RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10),
+ RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL3, 0x18),
+ RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL4, 0x1c),
+ RSND_GEN1_S_REG(gen, ADG, AUDIO_CLK_SEL5, 0x20),
+
+ RSND_GEN1_M_REG(gen, SSI, SSICR, 0x00, 0x40),
+ RSND_GEN1_M_REG(gen, SSI, SSISR, 0x04, 0x40),
+ RSND_GEN1_M_REG(gen, SSI, SSITDR, 0x08, 0x40),
+ RSND_GEN1_M_REG(gen, SSI, SSIRDR, 0x0c, 0x40),
+ RSND_GEN1_M_REG(gen, SSI, SSIWSR, 0x20, 0x40),
+ };
+
+ memset(&regc, 0, sizeof(regc));
+ regc.reg_bits = 32;
+ regc.val_bits = 32;
+
+ gen->regmap = devm_regmap_init(dev, &rsnd_regmap_bus, priv, &regc);
+ if (IS_ERR(gen->regmap)) {
+ dev_err(dev, "regmap error %ld\n", PTR_ERR(gen->regmap));
+ return PTR_ERR(gen->regmap);
+ }
+
+ for (i = 0; i < RSND_REG_MAX; i++) {
+ gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]);
+ if (IS_ERR(gen->regs[i]))
+ return PTR_ERR(gen->regs[i]);
+
+ }
+
+ return 0;
}
static int rsnd_gen1_probe(struct platform_device *pdev,
@@ -147,6 +248,7 @@ static int rsnd_gen1_probe(struct platform_device *pdev,
struct resource *sru_res;
struct resource *adg_res;
struct resource *ssi_res;
+ int ret;
/*
* map address
@@ -163,8 +265,9 @@ static int rsnd_gen1_probe(struct platform_device *pdev,
IS_ERR(gen->base[RSND_GEN1_SSI]))
return -ENODEV;
- gen->ops = &rsnd_gen1_ops;
- rsnd_gen1_reg_map_init(gen);
+ ret = rsnd_gen1_regmap_init(priv, gen);
+ if (ret < 0)
+ return ret;
dev_dbg(dev, "Gen1 device probed\n");
dev_dbg(dev, "SRU : %08x => %p\n", sru_res->start,
@@ -183,6 +286,13 @@ static void rsnd_gen1_remove(struct platform_device *pdev,
{
}
+static struct rsnd_gen_ops rsnd_gen1_ops = {
+ .probe = rsnd_gen1_probe,
+ .remove = rsnd_gen1_remove,
+ .path_init = rsnd_gen1_path_init,
+ .path_exit = rsnd_gen1_path_exit,
+};
+
/*
* Gen
*/
@@ -204,46 +314,12 @@ int rsnd_gen_path_exit(struct rsnd_priv *priv,
return gen->ops->path_exit(priv, rdai, io);
}
-void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
- struct rsnd_mod *mod,
- enum rsnd_reg reg)
-{
- struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
- struct device *dev = rsnd_priv_to_dev(priv);
- int index;
- u32 offset_id, offset_adr;
-
- if (reg >= RSND_REG_MAX) {
- dev_err(dev, "rsnd_reg reg error\n");
- return NULL;
- }
-
- index = gen->reg_map[reg].index;
- offset_id = gen->reg_map[reg].offset_id;
- offset_adr = gen->reg_map[reg].offset_adr;
-
- if (index < 0) {
- dev_err(dev, "unsupported reg access %d\n", reg);
- return NULL;
- }
-
- if (offset_id && mod)
- offset_id *= rsnd_mod_id(mod);
-
- /*
- * index/offset were set on gen1/gen2
- */
-
- return gen->base[index] + offset_id + offset_adr;
-}
-
int rsnd_gen_probe(struct platform_device *pdev,
struct rcar_snd_info *info,
struct rsnd_priv *priv)
{
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_gen *gen;
- int i;
gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL);
if (!gen) {
@@ -251,30 +327,23 @@ int rsnd_gen_probe(struct platform_device *pdev,
return -ENOMEM;
}
- priv->gen = gen;
-
- /*
- * see
- * rsnd_reg_get()
- * rsnd_gen_probe()
- */
- for (i = 0; i < RSND_REG_MAX; i++)
- gen->reg_map[i].index = -1;
-
- /*
- * init each module
- */
if (rsnd_is_gen1(priv))
- return rsnd_gen1_probe(pdev, info, priv);
+ gen->ops = &rsnd_gen1_ops;
- dev_err(dev, "unknown generation R-Car sound device\n");
+ if (!gen->ops) {
+ dev_err(dev, "unknown generation R-Car sound device\n");
+ return -ENODEV;
+ }
- return -ENODEV;
+ priv->gen = gen;
+
+ return gen->ops->probe(pdev, info, priv);
}
void rsnd_gen_remove(struct platform_device *pdev,
struct rsnd_priv *priv)
{
- if (rsnd_is_gen1(priv))
- rsnd_gen1_remove(pdev, priv);
+ struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
+
+ gen->ops->remove(pdev, priv);
}
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index 9cc6986a8cfb..3868aaf41cc4 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -78,10 +78,6 @@ struct rsnd_dai_stream;
#define rsnd_mod_bset(m, r, s, d) \
rsnd_bset(rsnd_mod_to_priv(m), m, RSND_REG_##r, s, d)
-#define rsnd_priv_read(p, r) rsnd_read(p, NULL, RSND_REG_##r)
-#define rsnd_priv_write(p, r, d) rsnd_write(p, NULL, RSND_REG_##r, d)
-#define rsnd_priv_bset(p, r, s, d) rsnd_bset(p, NULL, RSND_REG_##r, s, d)
-
u32 rsnd_read(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg);
void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod,
enum rsnd_reg reg, u32 data);
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index e72f55428f0b..1b6663f45b34 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -11,12 +11,9 @@
* option) any later version.
*/
-#include <linux/i2c.h>
-#include <linux/spi/spi.h>
#include <sound/soc.h>
-#include <linux/bitmap.h>
-#include <linux/rbtree.h>
#include <linux/export.h>
+#include <linux/slab.h>
#include <trace/events/asoc.h>
@@ -66,126 +63,42 @@ static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx,
return -1;
}
-static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
+int snd_soc_cache_init(struct snd_soc_codec *codec)
{
- int i;
- int ret;
- const struct snd_soc_codec_driver *codec_drv;
- unsigned int val;
+ const struct snd_soc_codec_driver *codec_drv = codec->driver;
+ size_t reg_size;
- codec_drv = codec->driver;
- for (i = 0; i < codec_drv->reg_cache_size; ++i) {
- ret = snd_soc_cache_read(codec, i, &val);
- if (ret)
- return ret;
- if (codec->reg_def_copy)
- if (snd_soc_get_cache_val(codec->reg_def_copy,
- i, codec_drv->reg_word_size) == val)
- continue;
+ reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
- WARN_ON(!snd_soc_codec_writable_register(codec, i));
-
- ret = snd_soc_write(codec, i, val);
- if (ret)
- return ret;
- dev_dbg(codec->dev, "ASoC: Synced register %#x, value = %#x\n",
- i, val);
- }
- return 0;
-}
-
-static int snd_soc_flat_cache_write(struct snd_soc_codec *codec,
- unsigned int reg, unsigned int value)
-{
- snd_soc_set_cache_val(codec->reg_cache, reg, value,
- codec->driver->reg_word_size);
- return 0;
-}
-
-static int snd_soc_flat_cache_read(struct snd_soc_codec *codec,
- unsigned int reg, unsigned int *value)
-{
- *value = snd_soc_get_cache_val(codec->reg_cache, reg,
- codec->driver->reg_word_size);
- return 0;
-}
+ mutex_init(&codec->cache_rw_mutex);
-static int snd_soc_flat_cache_exit(struct snd_soc_codec *codec)
-{
- if (!codec->reg_cache)
- return 0;
- kfree(codec->reg_cache);
- codec->reg_cache = NULL;
- return 0;
-}
+ dev_dbg(codec->dev, "ASoC: Initializing cache for %s codec\n",
+ codec->name);
-static int snd_soc_flat_cache_init(struct snd_soc_codec *codec)
-{
- if (codec->reg_def_copy)
- codec->reg_cache = kmemdup(codec->reg_def_copy,
- codec->reg_size, GFP_KERNEL);
+ if (codec_drv->reg_cache_default)
+ codec->reg_cache = kmemdup(codec_drv->reg_cache_default,
+ reg_size, GFP_KERNEL);
else
- codec->reg_cache = kzalloc(codec->reg_size, GFP_KERNEL);
+ codec->reg_cache = kzalloc(reg_size, GFP_KERNEL);
if (!codec->reg_cache)
return -ENOMEM;
return 0;
}
-/* an array of all supported compression types */
-static const struct snd_soc_cache_ops cache_types[] = {
- /* Flat *must* be the first entry for fallback */
- {
- .id = SND_SOC_FLAT_COMPRESSION,
- .name = "flat",
- .init = snd_soc_flat_cache_init,
- .exit = snd_soc_flat_cache_exit,
- .read = snd_soc_flat_cache_read,
- .write = snd_soc_flat_cache_write,
- .sync = snd_soc_flat_cache_sync
- },
-};
-
-int snd_soc_cache_init(struct snd_soc_codec *codec)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(cache_types); ++i)
- if (cache_types[i].id == codec->compress_type)
- break;
-
- /* Fall back to flat compression */
- if (i == ARRAY_SIZE(cache_types)) {
- dev_warn(codec->dev, "ASoC: Could not match compress type: %d\n",
- codec->compress_type);
- i = 0;
- }
-
- mutex_init(&codec->cache_rw_mutex);
- codec->cache_ops = &cache_types[i];
-
- if (codec->cache_ops->init) {
- if (codec->cache_ops->name)
- dev_dbg(codec->dev, "ASoC: Initializing %s cache for %s codec\n",
- codec->cache_ops->name, codec->name);
- return codec->cache_ops->init(codec);
- }
- return -ENOSYS;
-}
-
/*
* NOTE: keep in mind that this function might be called
* multiple times.
*/
int snd_soc_cache_exit(struct snd_soc_codec *codec)
{
- if (codec->cache_ops && codec->cache_ops->exit) {
- if (codec->cache_ops->name)
- dev_dbg(codec->dev, "ASoC: Destroying %s cache for %s codec\n",
- codec->cache_ops->name, codec->name);
- return codec->cache_ops->exit(codec);
- }
- return -ENOSYS;
+ dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n",
+ codec->name);
+ if (!codec->reg_cache)
+ return 0;
+ kfree(codec->reg_cache);
+ codec->reg_cache = NULL;
+ return 0;
}
/**
@@ -198,18 +111,15 @@ int snd_soc_cache_exit(struct snd_soc_codec *codec)
int snd_soc_cache_read(struct snd_soc_codec *codec,
unsigned int reg, unsigned int *value)
{
- int ret;
+ if (!value)
+ return -EINVAL;
mutex_lock(&codec->cache_rw_mutex);
-
- if (value && codec->cache_ops && codec->cache_ops->read) {
- ret = codec->cache_ops->read(codec, reg, value);
- mutex_unlock(&codec->cache_rw_mutex);
- return ret;
- }
-
+ *value = snd_soc_get_cache_val(codec->reg_cache, reg,
+ codec->driver->reg_word_size);
mutex_unlock(&codec->cache_rw_mutex);
- return -ENOSYS;
+
+ return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_cache_read);
@@ -223,20 +133,42 @@ EXPORT_SYMBOL_GPL(snd_soc_cache_read);
int snd_soc_cache_write(struct snd_soc_codec *codec,
unsigned int reg, unsigned int value)
{
+ mutex_lock(&codec->cache_rw_mutex);
+ snd_soc_set_cache_val(codec->reg_cache, reg, value,
+ codec->driver->reg_word_size);
+ mutex_unlock(&codec->cache_rw_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_cache_write);
+
+static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
+{
+ int i;
int ret;
+ const struct snd_soc_codec_driver *codec_drv;
+ unsigned int val;
- mutex_lock(&codec->cache_rw_mutex);
+ codec_drv = codec->driver;
+ for (i = 0; i < codec_drv->reg_cache_size; ++i) {
+ ret = snd_soc_cache_read(codec, i, &val);
+ if (ret)
+ return ret;
+ if (codec_drv->reg_cache_default)
+ if (snd_soc_get_cache_val(codec_drv->reg_cache_default,
+ i, codec_drv->reg_word_size) == val)
+ continue;
- if (codec->cache_ops && codec->cache_ops->write) {
- ret = codec->cache_ops->write(codec, reg, value);
- mutex_unlock(&codec->cache_rw_mutex);
- return ret;
- }
+ WARN_ON(!snd_soc_codec_writable_register(codec, i));
- mutex_unlock(&codec->cache_rw_mutex);
- return -ENOSYS;
+ ret = snd_soc_write(codec, i, val);
+ if (ret)
+ return ret;
+ dev_dbg(codec->dev, "ASoC: Synced register %#x, value = %#x\n",
+ i, val);
+ }
+ return 0;
}
-EXPORT_SYMBOL_GPL(snd_soc_cache_write);
/**
* snd_soc_cache_sync: Sync the register cache with the hardware.
@@ -249,92 +181,19 @@ EXPORT_SYMBOL_GPL(snd_soc_cache_write);
*/
int snd_soc_cache_sync(struct snd_soc_codec *codec)
{
+ const char *name = "flat";
int ret;
- const char *name;
- if (!codec->cache_sync) {
+ if (!codec->cache_sync)
return 0;
- }
-
- if (!codec->cache_ops || !codec->cache_ops->sync)
- return -ENOSYS;
- if (codec->cache_ops->name)
- name = codec->cache_ops->name;
- else
- name = "unknown";
-
- if (codec->cache_ops->name)
- dev_dbg(codec->dev, "ASoC: Syncing %s cache for %s codec\n",
- codec->cache_ops->name, codec->name);
+ dev_dbg(codec->dev, "ASoC: Syncing cache for %s codec\n",
+ codec->name);
trace_snd_soc_cache_sync(codec, name, "start");
- ret = codec->cache_ops->sync(codec);
+ ret = snd_soc_flat_cache_sync(codec);
if (!ret)
codec->cache_sync = 0;
trace_snd_soc_cache_sync(codec, name, "end");
return ret;
}
EXPORT_SYMBOL_GPL(snd_soc_cache_sync);
-
-static int snd_soc_get_reg_access_index(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- const struct snd_soc_codec_driver *codec_drv;
- unsigned int min, max, index;
-
- codec_drv = codec->driver;
- min = 0;
- max = codec_drv->reg_access_size - 1;
- do {
- index = (min + max) / 2;
- if (codec_drv->reg_access_default[index].reg == reg)
- return index;
- if (codec_drv->reg_access_default[index].reg < reg)
- min = index + 1;
- else
- max = index;
- } while (min <= max);
- return -1;
-}
-
-int snd_soc_default_volatile_register(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- int index;
-
- if (reg >= codec->driver->reg_cache_size)
- return 1;
- index = snd_soc_get_reg_access_index(codec, reg);
- if (index < 0)
- return 0;
- return codec->driver->reg_access_default[index].vol;
-}
-EXPORT_SYMBOL_GPL(snd_soc_default_volatile_register);
-
-int snd_soc_default_readable_register(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- int index;
-
- if (reg >= codec->driver->reg_cache_size)
- return 1;
- index = snd_soc_get_reg_access_index(codec, reg);
- if (index < 0)
- return 0;
- return codec->driver->reg_access_default[index].read;
-}
-EXPORT_SYMBOL_GPL(snd_soc_default_readable_register);
-
-int snd_soc_default_writable_register(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- int index;
-
- if (reg >= codec->driver->reg_cache_size)
- return 1;
- index = snd_soc_get_reg_access_index(codec, reg);
- if (index < 0)
- return 0;
- return codec->driver->reg_access_default[index].write;
-}
-EXPORT_SYMBOL_GPL(snd_soc_default_writable_register);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 4d0561312f3b..4280c70ba0ee 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1380,7 +1380,6 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
return -ENODEV;
list_add(&cpu_dai->dapm.list, &card->dapm_list);
- snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai);
}
if (cpu_dai->driver->probe) {
@@ -1590,17 +1589,13 @@ static void soc_remove_aux_dev(struct snd_soc_card *card, int num)
soc_remove_codec(codec);
}
-static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
- enum snd_soc_compress_type compress_type)
+static int snd_soc_init_codec_cache(struct snd_soc_codec *codec)
{
int ret;
if (codec->cache_init)
return 0;
- /* override the compress_type if necessary */
- if (compress_type && codec->compress_type != compress_type)
- codec->compress_type = compress_type;
ret = snd_soc_cache_init(codec);
if (ret < 0) {
dev_err(codec->dev,
@@ -1615,8 +1610,6 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
static int snd_soc_instantiate_card(struct snd_soc_card *card)
{
struct snd_soc_codec *codec;
- struct snd_soc_codec_conf *codec_conf;
- enum snd_soc_compress_type compress_type;
struct snd_soc_dai_link *dai_link;
int ret, i, order, dai_fmt;
@@ -1640,19 +1633,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
list_for_each_entry(codec, &codec_list, list) {
if (codec->cache_init)
continue;
- /* by default we don't override the compress_type */
- compress_type = 0;
- /* check to see if we need to override the compress_type */
- for (i = 0; i < card->num_configs; ++i) {
- codec_conf = &card->codec_conf[i];
- if (!strcmp(codec->name, codec_conf->dev_name)) {
- compress_type = codec_conf->compress_type;
- if (compress_type && compress_type
- != codec->compress_type)
- break;
- }
- }
- ret = snd_soc_init_codec_cache(codec, compress_type);
+ ret = snd_soc_init_codec_cache(codec);
if (ret < 0)
goto base_error;
}
@@ -2298,13 +2279,6 @@ unsigned int snd_soc_write(struct snd_soc_codec *codec,
}
EXPORT_SYMBOL_GPL(snd_soc_write);
-unsigned int snd_soc_bulk_write_raw(struct snd_soc_codec *codec,
- unsigned int reg, const void *data, size_t len)
-{
- return codec->bulk_write_raw(codec, reg, data, len);
-}
-EXPORT_SYMBOL_GPL(snd_soc_bulk_write_raw);
-
/**
* snd_soc_update_bits - update codec register bits
* @codec: audio codec
@@ -3577,6 +3551,22 @@ int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll);
/**
+ * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio.
+ * @dai: DAI
+ * @ratio Ratio of BCLK to Sample rate.
+ *
+ * Configures the DAI for a preset BCLK to sample rate ratio.
+ */
+int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
+{
+ if (dai->driver && dai->driver->ops->set_bclk_ratio)
+ return dai->driver->ops->set_bclk_ratio(dai, ratio);
+ else
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio);
+
+/**
* snd_soc_dai_set_fmt - configure DAI hardware audio format.
* @dai: DAI
* @fmt: SND_SOC_DAIFMT_ format value.
@@ -4021,6 +4011,112 @@ static void snd_soc_unregister_dais(struct device *dev, size_t count)
}
/**
+ * snd_soc_register_component - Register a component with the ASoC core
+ *
+ */
+static int
+__snd_soc_register_component(struct device *dev,
+ struct snd_soc_component *cmpnt,
+ const struct snd_soc_component_driver *cmpnt_drv,
+ struct snd_soc_dai_driver *dai_drv,
+ int num_dai, bool allow_single_dai)
+{
+ int ret;
+
+ dev_dbg(dev, "component register %s\n", dev_name(dev));
+
+ if (!cmpnt) {
+ dev_err(dev, "ASoC: Failed to connecting component\n");
+ return -ENOMEM;
+ }
+
+ cmpnt->name = fmt_single_name(dev, &cmpnt->id);
+ if (!cmpnt->name) {
+ dev_err(dev, "ASoC: Failed to simplifying name\n");
+ return -ENOMEM;
+ }
+
+ cmpnt->dev = dev;
+ cmpnt->driver = cmpnt_drv;
+ cmpnt->num_dai = num_dai;
+
+ /*
+ * snd_soc_register_dai() uses fmt_single_name(), and
+ * snd_soc_register_dais() uses fmt_multiple_name()
+ * for dai->name which is used for name based matching
+ *
+ * this function is used from cpu/codec.
+ * allow_single_dai flag can ignore "codec" driver reworking
+ * since it had been used snd_soc_register_dais(),
+ */
+ if ((1 == num_dai) && allow_single_dai)
+ ret = snd_soc_register_dai(dev, dai_drv);
+ else
+ ret = snd_soc_register_dais(dev, dai_drv, num_dai);
+ if (ret < 0) {
+ dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
+ goto error_component_name;
+ }
+
+ mutex_lock(&client_mutex);
+ list_add(&cmpnt->list, &component_list);
+ mutex_unlock(&client_mutex);
+
+ dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name);
+
+ return ret;
+
+error_component_name:
+ kfree(cmpnt->name);
+
+ return ret;
+}
+
+int snd_soc_register_component(struct device *dev,
+ const struct snd_soc_component_driver *cmpnt_drv,
+ struct snd_soc_dai_driver *dai_drv,
+ int num_dai)
+{
+ struct snd_soc_component *cmpnt;
+
+ cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL);
+ if (!cmpnt) {
+ dev_err(dev, "ASoC: Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ return __snd_soc_register_component(dev, cmpnt, cmpnt_drv,
+ dai_drv, num_dai, true);
+}
+EXPORT_SYMBOL_GPL(snd_soc_register_component);
+
+/**
+ * snd_soc_unregister_component - Unregister a component from the ASoC core
+ *
+ */
+void snd_soc_unregister_component(struct device *dev)
+{
+ struct snd_soc_component *cmpnt;
+
+ list_for_each_entry(cmpnt, &component_list, list) {
+ if (dev == cmpnt->dev)
+ goto found;
+ }
+ return;
+
+found:
+ snd_soc_unregister_dais(dev, cmpnt->num_dai);
+
+ mutex_lock(&client_mutex);
+ list_del(&cmpnt->list);
+ mutex_unlock(&client_mutex);
+
+ dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name);
+ kfree(cmpnt->name);
+}
+EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
+
+/**
* snd_soc_add_platform - Add a platform to the ASoC core
* @dev: The parent device for the platform
* @platform: The platform to add
@@ -4166,7 +4262,6 @@ int snd_soc_register_codec(struct device *dev,
struct snd_soc_dai_driver *dai_drv,
int num_dai)
{
- size_t reg_size;
struct snd_soc_codec *codec;
int ret, i;
@@ -4183,11 +4278,6 @@ int snd_soc_register_codec(struct device *dev,
goto fail_codec;
}
- if (codec_drv->compress_type)
- codec->compress_type = codec_drv->compress_type;
- else
- codec->compress_type = SND_SOC_FLAT_COMPRESSION;
-
codec->write = codec_drv->write;
codec->read = codec_drv->read;
codec->volatile_register = codec_drv->volatile_register;
@@ -4204,35 +4294,6 @@ int snd_soc_register_codec(struct device *dev,
codec->num_dai = num_dai;
mutex_init(&codec->mutex);
- /* allocate CODEC register cache */
- if (codec_drv->reg_cache_size && codec_drv->reg_word_size) {
- reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
- codec->reg_size = reg_size;
- /* it is necessary to make a copy of the default register cache
- * because in the case of using a compression type that requires
- * the default register cache to be marked as the
- * kernel might have freed the array by the time we initialize
- * the cache.
- */
- if (codec_drv->reg_cache_default) {
- codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default,
- reg_size, GFP_KERNEL);
- if (!codec->reg_def_copy) {
- ret = -ENOMEM;
- goto fail_codec_name;
- }
- }
- }
-
- if (codec_drv->reg_access_size && codec_drv->reg_access_default) {
- if (!codec->volatile_register)
- codec->volatile_register = snd_soc_default_volatile_register;
- if (!codec->readable_register)
- codec->readable_register = snd_soc_default_readable_register;
- if (!codec->writable_register)
- codec->writable_register = snd_soc_default_writable_register;
- }
-
for (i = 0; i < num_dai; i++) {
fixup_codec_formats(&dai_drv[i].playback);
fixup_codec_formats(&dai_drv[i].capture);
@@ -4242,10 +4303,12 @@ int snd_soc_register_codec(struct device *dev,
list_add(&codec->list, &codec_list);
mutex_unlock(&client_mutex);
- /* register any DAIs */
- ret = snd_soc_register_dais(dev, dai_drv, num_dai);
+ /* register component */
+ ret = __snd_soc_register_component(dev, &codec->component,
+ &codec_drv->component_driver,
+ dai_drv, num_dai, false);
if (ret < 0) {
- dev_err(codec->dev, "ASoC: Failed to regster DAIs: %d\n", ret);
+ dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret);
goto fail_codec_name;
}
@@ -4280,7 +4343,7 @@ void snd_soc_unregister_codec(struct device *dev)
return;
found:
- snd_soc_unregister_dais(dev, codec->num_dai);
+ snd_soc_unregister_component(dev);
mutex_lock(&client_mutex);
list_del(&codec->list);
@@ -4289,98 +4352,11 @@ found:
dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", codec->name);
snd_soc_cache_exit(codec);
- kfree(codec->reg_def_copy);
kfree(codec->name);
kfree(codec);
}
EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
-
-/**
- * snd_soc_register_component - Register a component with the ASoC core
- *
- */
-int snd_soc_register_component(struct device *dev,
- const struct snd_soc_component_driver *cmpnt_drv,
- struct snd_soc_dai_driver *dai_drv,
- int num_dai)
-{
- struct snd_soc_component *cmpnt;
- int ret;
-
- dev_dbg(dev, "component register %s\n", dev_name(dev));
-
- cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL);
- if (!cmpnt) {
- dev_err(dev, "ASoC: Failed to allocate memory\n");
- return -ENOMEM;
- }
-
- cmpnt->name = fmt_single_name(dev, &cmpnt->id);
- if (!cmpnt->name) {
- dev_err(dev, "ASoC: Failed to simplifying name\n");
- return -ENOMEM;
- }
-
- cmpnt->dev = dev;
- cmpnt->driver = cmpnt_drv;
- cmpnt->num_dai = num_dai;
-
- /*
- * snd_soc_register_dai() uses fmt_single_name(), and
- * snd_soc_register_dais() uses fmt_multiple_name()
- * for dai->name which is used for name based matching
- */
- if (1 == num_dai)
- ret = snd_soc_register_dai(dev, dai_drv);
- else
- ret = snd_soc_register_dais(dev, dai_drv, num_dai);
- if (ret < 0) {
- dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
- goto error_component_name;
- }
-
- mutex_lock(&client_mutex);
- list_add(&cmpnt->list, &component_list);
- mutex_unlock(&client_mutex);
-
- dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name);
-
- return ret;
-
-error_component_name:
- kfree(cmpnt->name);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(snd_soc_register_component);
-
-/**
- * snd_soc_unregister_component - Unregister a component from the ASoC core
- *
- */
-void snd_soc_unregister_component(struct device *dev)
-{
- struct snd_soc_component *cmpnt;
-
- list_for_each_entry(cmpnt, &component_list, list) {
- if (dev == cmpnt->dev)
- goto found;
- }
- return;
-
-found:
- snd_soc_unregister_dais(dev, cmpnt->num_dai);
-
- mutex_lock(&client_mutex);
- list_del(&cmpnt->list);
- mutex_unlock(&client_mutex);
-
- dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name);
- kfree(cmpnt->name);
-}
-EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
-
/* Retrieve a card's name from device tree */
int snd_soc_of_parse_card_name(struct snd_soc_card *card,
const char *propname)
@@ -4568,6 +4544,41 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
}
EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt);
+int snd_soc_of_get_dai_name(struct device_node *of_node,
+ const char **dai_name)
+{
+ struct snd_soc_component *pos;
+ struct of_phandle_args args;
+ int ret;
+
+ ret = of_parse_phandle_with_args(of_node, "sound-dai",
+ "#sound-dai-cells", 0, &args);
+ if (ret)
+ return ret;
+
+ ret = -EPROBE_DEFER;
+
+ mutex_lock(&client_mutex);
+ list_for_each_entry(pos, &component_list, list) {
+ if (pos->dev->of_node != args.np)
+ continue;
+
+ if (!pos->driver->of_xlate_dai_name) {
+ ret = -ENOSYS;
+ break;
+ }
+
+ ret = pos->driver->of_xlate_dai_name(pos, &args, dai_name);
+ break;
+ }
+ mutex_unlock(&client_mutex);
+
+ of_node_put(args.np);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_name);
+
static int __init snd_soc_init(void)
{
#ifdef CONFIG_DEBUG_FS
diff --git a/sound/soc/soc-devres.c b/sound/soc/soc-devres.c
new file mode 100644
index 000000000000..b1d732255c02
--- /dev/null
+++ b/sound/soc/soc-devres.c
@@ -0,0 +1,86 @@
+/*
+ * soc-devres.c -- ALSA SoC Audio Layer devres functions
+ *
+ * Copyright (C) 2013 Linaro Ltd
+ *
+ * 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 <linux/module.h>
+#include <linux/moduleparam.h>
+#include <sound/soc.h>
+
+static void devm_component_release(struct device *dev, void *res)
+{
+ snd_soc_unregister_component(*(struct device **)res);
+}
+
+/**
+ * devm_snd_soc_register_component - resource managed component registration
+ * @dev: Device used to manage component
+ * @cmpnt_drv: Component driver
+ * @dai_drv: DAI driver
+ * @num_dai: Number of DAIs to register
+ *
+ * Register a component with automatic unregistration when the device is
+ * unregistered.
+ */
+int devm_snd_soc_register_component(struct device *dev,
+ const struct snd_soc_component_driver *cmpnt_drv,
+ struct snd_soc_dai_driver *dai_drv, int num_dai)
+{
+ struct device **ptr;
+ int ret;
+
+ ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return -ENOMEM;
+
+ ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai);
+ if (ret == 0) {
+ *ptr = dev;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(devm_snd_soc_register_component);
+
+static void devm_card_release(struct device *dev, void *res)
+{
+ snd_soc_unregister_card(*(struct snd_soc_card **)res);
+}
+
+/**
+ * devm_snd_soc_register_card - resource managed card registration
+ * @dev: Device used to manage card
+ * @card: Card to register
+ *
+ * Register a card with automatic unregistration when the device is
+ * unregistered.
+ */
+int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
+{
+ struct device **ptr;
+ int ret;
+
+ ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return -ENOMEM;
+
+ ret = snd_soc_register_card(card);
+ if (ret == 0) {
+ *ptr = dev;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(devm_snd_soc_register_card);
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index 122c0c18b9dd..4f11d23f2062 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -65,31 +65,6 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
return val;
}
-/* Primitive bulk write support for soc-cache. The data pointed to by
- * `data' needs to already be in the form the hardware expects. Any
- * data written through this function will not go through the cache as
- * it only handles writing to volatile or out of bounds registers.
- *
- * This is currently only supported for devices using the regmap API
- * wrappers.
- */
-static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec,
- unsigned int reg,
- const void *data, size_t len)
-{
- /* To ensure that we don't get out of sync with the cache, check
- * whether the base register is volatile or if we've directly asked
- * to bypass the cache. Out of bounds registers are considered
- * volatile.
- */
- if (!codec->cache_bypass
- && !snd_soc_codec_volatile_register(codec, reg)
- && reg < codec->driver->reg_cache_size)
- return -EINVAL;
-
- return regmap_raw_write(codec->control_data, reg, data, len);
-}
-
/**
* snd_soc_codec_set_cache_io: Set up standard I/O functions.
*
@@ -119,7 +94,6 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
memset(&config, 0, sizeof(config));
codec->write = hw_write;
codec->read = hw_read;
- codec->bulk_write_raw = snd_soc_hw_bulk_write_raw;
config.reg_bits = addr_bits;
config.val_bits = data_bits;
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
index 29b211e9c060..5e633659c1b3 100644
--- a/sound/soc/soc-utils.c
+++ b/sound/soc/soc-utils.c
@@ -75,7 +75,11 @@ static const struct snd_pcm_hardware dummy_dma_hardware = {
static int dummy_dma_open(struct snd_pcm_substream *substream)
{
- snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware);
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+ /* BE's dont need dummy params */
+ if (!rtd->dai_link->no_pcm)
+ snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware);
return 0;
}
diff --git a/sound/soc/spear/spdif_in.c b/sound/soc/spear/spdif_in.c
index 63acfeb4b69d..21a8c954af1c 100644
--- a/sound/soc/spear/spdif_in.c
+++ b/sound/soc/spear/spdif_in.c
@@ -257,20 +257,12 @@ static int spdif_in_probe(struct platform_device *pdev)
return ret;
}
- return snd_soc_register_component(&pdev->dev, &spdif_in_component,
- &spdif_in_dai, 1);
-}
-
-static int spdif_in_remove(struct platform_device *pdev)
-{
- snd_soc_unregister_component(&pdev->dev);
-
- return 0;
+ return devm_snd_soc_register_component(&pdev->dev, &spdif_in_component,
+ &spdif_in_dai, 1);
}
static struct platform_driver spdif_in_driver = {
.probe = spdif_in_probe,
- .remove = spdif_in_remove,
.driver = {
.name = "spdif-in",
.owner = THIS_MODULE,
diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c
index 2fdf68c98d22..b6ef6f78dc78 100644
--- a/sound/soc/spear/spdif_out.c
+++ b/sound/soc/spear/spdif_out.c
@@ -280,7 +280,6 @@ static int spdif_out_probe(struct platform_device *pdev)
struct spdif_out_dev *host;
struct spear_spdif_platform_data *pdata;
struct resource *res;
- int ret;
host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
if (!host) {
@@ -307,16 +306,8 @@ static int spdif_out_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, host);
- ret = snd_soc_register_component(&pdev->dev, &spdif_out_component,
- &spdif_out_dai, 1);
- return ret;
-}
-
-static int spdif_out_remove(struct platform_device *pdev)
-{
- snd_soc_unregister_component(&pdev->dev);
-
- return 0;
+ return devm_snd_soc_register_component(&pdev->dev, &spdif_out_component,
+ &spdif_out_dai, 1);
}
#ifdef CONFIG_PM
@@ -357,7 +348,6 @@ static SIMPLE_DEV_PM_OPS(spdif_out_dev_pm_ops, spdif_out_suspend, \
static struct platform_driver spdif_out_driver = {
.probe = spdif_out_probe,
- .remove = spdif_out_remove,
.driver = {
.name = "spdif-out",
.owner = THIS_MODULE,
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 64952e2d3ed1..d1f54dfe41d5 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -79,7 +79,6 @@ static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card *
/* Vendor/product IDs for this card */
static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
-static int nrpacks = 8; /* max. number of packets per urb */
static int device_setup[SNDRV_CARDS]; /* device parameter for this card */
static bool ignore_ctl_error;
static bool autoclock = true;
@@ -94,8 +93,6 @@ module_param_array(vid, int, NULL, 0444);
MODULE_PARM_DESC(vid, "Vendor ID for the USB audio device.");
module_param_array(pid, int, NULL, 0444);
MODULE_PARM_DESC(pid, "Product ID for the USB audio device.");
-module_param(nrpacks, int, 0644);
-MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB.");
module_param_array(device_setup, int, NULL, 0444);
MODULE_PARM_DESC(device_setup, "Specific device setup (if needed).");
module_param(ignore_ctl_error, bool, 0444);
@@ -374,7 +371,6 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
chip->dev = dev;
chip->card = card;
chip->setup = device_setup[idx];
- chip->nrpacks = nrpacks;
chip->autoclock = autoclock;
chip->probing = 1;
@@ -756,10 +752,6 @@ static struct usb_driver usb_audio_driver = {
static int __init snd_usb_audio_init(void)
{
- if (nrpacks < 1 || nrpacks > MAX_PACKS) {
- printk(KERN_WARNING "invalid nrpacks value.\n");
- return -EINVAL;
- }
return usb_register(&usb_audio_driver);
}
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 5ecacaa90b53..ca98a9b915c9 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -2,11 +2,11 @@
#define __USBAUDIO_CARD_H
#define MAX_NR_RATES 1024
-#define MAX_PACKS 20
+#define MAX_PACKS 6 /* per URB */
#define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */
-#define MAX_URBS 8
+#define MAX_URBS 12
#define SYNC_URBS 4 /* always four urbs for sync */
-#define MAX_QUEUE 24 /* try not to exceed this queue length, in ms */
+#define MAX_QUEUE 18 /* try not to exceed this queue length, in ms */
struct audioformat {
struct list_head list;
@@ -87,6 +87,7 @@ struct snd_usb_endpoint {
unsigned int phase; /* phase accumulator */
unsigned int maxpacksize; /* max packet size in bytes */
unsigned int maxframesize; /* max packet size in frames */
+ unsigned int max_urb_frames; /* max URB size in frames */
unsigned int curpacksize; /* current packet size in bytes (for capture) */
unsigned int curframesize; /* current packet size in frames (for capture) */
unsigned int syncmaxsize; /* sync endpoint packet size */
@@ -116,6 +117,8 @@ struct snd_usb_substream {
unsigned int channels_max; /* max channels in the all audiofmts */
unsigned int cur_rate; /* current rate (for hw_params callback) */
unsigned int period_bytes; /* current period bytes (for hw_params callback) */
+ unsigned int period_frames; /* current frames per period */
+ unsigned int buffer_periods; /* current periods per buffer */
unsigned int altset_idx; /* USB data format: index of alternate setting */
unsigned int txfr_quirk:1; /* allow sub-frame alignment */
unsigned int fmt_type; /* USB audio format type (1-3) */
@@ -125,6 +128,7 @@ struct snd_usb_substream {
unsigned int hwptr_done; /* processed byte position in the buffer */
unsigned int transfer_done; /* processed frames since last period update */
+ unsigned int frame_limit; /* limits number of packets in URB */
/* data and sync endpoints for this stream */
unsigned int ep_num; /* the endpoint number */
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 93e970f2b3c0..21dc6422d747 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -574,11 +574,14 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
snd_pcm_format_t pcm_format,
unsigned int channels,
unsigned int period_bytes,
+ unsigned int frames_per_period,
+ unsigned int periods_per_buffer,
struct audioformat *fmt,
struct snd_usb_endpoint *sync_ep)
{
- unsigned int maxsize, i, urb_packs, total_packs, packs_per_ms;
- int is_playback = usb_pipeout(ep->pipe);
+ unsigned int maxsize, minsize, packs_per_ms, max_packs_per_urb;
+ unsigned int max_packs_per_period, urbs_per_period, urb_packs;
+ unsigned int max_urbs, i;
int frame_bits = snd_pcm_format_physical_width(pcm_format) * channels;
if (pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && fmt->dsd_dop) {
@@ -611,58 +614,67 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
else
ep->curpacksize = maxsize;
- if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL)
+ if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL) {
packs_per_ms = 8 >> ep->datainterval;
- else
- packs_per_ms = 1;
-
- if (is_playback && !snd_usb_endpoint_implicit_feedback_sink(ep)) {
- urb_packs = max(ep->chip->nrpacks, 1);
- urb_packs = min(urb_packs, (unsigned int) MAX_PACKS);
+ max_packs_per_urb = MAX_PACKS_HS;
} else {
- urb_packs = 1;
+ packs_per_ms = 1;
+ max_packs_per_urb = MAX_PACKS;
}
+ if (sync_ep && !snd_usb_endpoint_implicit_feedback_sink(ep))
+ max_packs_per_urb = min(max_packs_per_urb,
+ 1U << sync_ep->syncinterval);
+ max_packs_per_urb = max(1u, max_packs_per_urb >> ep->datainterval);
- urb_packs *= packs_per_ms;
+ /*
+ * Capture endpoints need to use small URBs because there's no way
+ * to tell in advance where the next period will end, and we don't
+ * want the next URB to complete much after the period ends.
+ *
+ * Playback endpoints with implicit sync much use the same parameters
+ * as their corresponding capture endpoint.
+ */
+ if (usb_pipein(ep->pipe) ||
+ snd_usb_endpoint_implicit_feedback_sink(ep)) {
- if (sync_ep && !snd_usb_endpoint_implicit_feedback_sink(ep))
- urb_packs = min(urb_packs, 1U << sync_ep->syncinterval);
+ /* make capture URBs <= 1 ms and smaller than a period */
+ urb_packs = min(max_packs_per_urb, packs_per_ms);
+ while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
+ urb_packs >>= 1;
+ ep->nurbs = MAX_URBS;
- /* decide how many packets to be used */
- if (is_playback && !snd_usb_endpoint_implicit_feedback_sink(ep)) {
- unsigned int minsize, maxpacks;
+ /*
+ * Playback endpoints without implicit sync are adjusted so that
+ * a period fits as evenly as possible in the smallest number of
+ * URBs. The total number of URBs is adjusted to the size of the
+ * ALSA buffer, subject to the MAX_URBS and MAX_QUEUE limits.
+ */
+ } else {
/* determine how small a packet can be */
- minsize = (ep->freqn >> (16 - ep->datainterval))
- * (frame_bits >> 3);
+ minsize = (ep->freqn >> (16 - ep->datainterval)) *
+ (frame_bits >> 3);
/* with sync from device, assume it can be 12% lower */
if (sync_ep)
minsize -= minsize >> 3;
minsize = max(minsize, 1u);
- total_packs = (period_bytes + minsize - 1) / minsize;
- /* we need at least two URBs for queueing */
- if (total_packs < 2) {
- total_packs = 2;
- } else {
- /* and we don't want too long a queue either */
- maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2);
- total_packs = min(total_packs, maxpacks);
- }
- } else {
- while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
- urb_packs >>= 1;
- total_packs = MAX_URBS * urb_packs;
- }
- ep->nurbs = (total_packs + urb_packs - 1) / urb_packs;
- if (ep->nurbs > MAX_URBS) {
- /* too much... */
- ep->nurbs = MAX_URBS;
- total_packs = MAX_URBS * urb_packs;
- } else if (ep->nurbs < 2) {
- /* too little - we need at least two packets
- * to ensure contiguous playback/capture
- */
- ep->nurbs = 2;
+ /* how many packets will contain an entire ALSA period? */
+ max_packs_per_period = DIV_ROUND_UP(period_bytes, minsize);
+
+ /* how many URBs will contain a period? */
+ urbs_per_period = DIV_ROUND_UP(max_packs_per_period,
+ max_packs_per_urb);
+ /* how many packets are needed in each URB? */
+ urb_packs = DIV_ROUND_UP(max_packs_per_period, urbs_per_period);
+
+ /* limit the number of frames in a single URB */
+ ep->max_urb_frames = DIV_ROUND_UP(frames_per_period,
+ urbs_per_period);
+
+ /* try to use enough URBs to contain an entire ALSA buffer */
+ max_urbs = min((unsigned) MAX_URBS,
+ MAX_QUEUE * packs_per_ms / urb_packs);
+ ep->nurbs = min(max_urbs, urbs_per_period * periods_per_buffer);
}
/* allocate and initialize data urbs */
@@ -670,8 +682,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
struct snd_urb_ctx *u = &ep->urb[i];
u->index = i;
u->ep = ep;
- u->packets = (i + 1) * total_packs / ep->nurbs
- - i * total_packs / ep->nurbs;
+ u->packets = urb_packs;
u->buffer_size = maxsize * u->packets;
if (fmt->fmt_type == UAC_FORMAT_TYPE_II)
@@ -748,6 +759,8 @@ out_of_memory:
* @pcm_format: the audio fomat.
* @channels: the number of audio channels.
* @period_bytes: the number of bytes in one alsa period.
+ * @period_frames: the number of frames in one alsa period.
+ * @buffer_periods: the number of periods in one alsa buffer.
* @rate: the frame rate.
* @fmt: the USB audio format information
* @sync_ep: the sync endpoint to use, if any
@@ -760,6 +773,8 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
snd_pcm_format_t pcm_format,
unsigned int channels,
unsigned int period_bytes,
+ unsigned int period_frames,
+ unsigned int buffer_periods,
unsigned int rate,
struct audioformat *fmt,
struct snd_usb_endpoint *sync_ep)
@@ -793,7 +808,8 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
switch (ep->type) {
case SND_USB_ENDPOINT_TYPE_DATA:
err = data_ep_set_params(ep, pcm_format, channels,
- period_bytes, fmt, sync_ep);
+ period_bytes, period_frames,
+ buffer_periods, fmt, sync_ep);
break;
case SND_USB_ENDPOINT_TYPE_SYNC:
err = sync_ep_set_params(ep, fmt);
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 2287adf5ca59..3bd02f0d226c 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -12,6 +12,8 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
snd_pcm_format_t pcm_format,
unsigned int channels,
unsigned int period_bytes,
+ unsigned int period_frames,
+ unsigned int buffer_periods,
unsigned int rate,
struct audioformat *fmt,
struct snd_usb_endpoint *sync_ep);
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 95558ef4a7a0..44b0ba4feab3 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1151,14 +1151,14 @@ static void check_no_speaker_on_headset(struct snd_kcontrol *kctl,
const char *names_to_check[] = {
"Headset", "headset", "Headphone", "headphone", NULL};
const char **s;
- bool found = 0;
+ bool found = false;
if (strcmp("Speaker", kctl->id.name))
return;
for (s = names_to_check; *s; s++)
if (strstr(card->shortname, *s)) {
- found = 1;
+ found = true;
break;
}
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index b375d58871e7..19e79953f2e3 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -595,6 +595,7 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs)
subs->pcm_format,
subs->channels,
subs->period_bytes,
+ 0, 0,
subs->cur_rate,
subs->cur_audiofmt,
NULL);
@@ -631,6 +632,7 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs)
subs->pcm_format,
sync_fp->channels,
sync_period_bytes,
+ 0, 0,
subs->cur_rate,
sync_fp,
NULL);
@@ -653,6 +655,8 @@ static int configure_endpoint(struct snd_usb_substream *subs)
subs->pcm_format,
subs->channels,
subs->period_bytes,
+ subs->period_frames,
+ subs->buffer_periods,
subs->cur_rate,
subs->cur_audiofmt,
subs->sync_endpoint);
@@ -689,6 +693,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
subs->pcm_format = params_format(hw_params);
subs->period_bytes = params_period_bytes(hw_params);
+ subs->period_frames = params_period_size(hw_params);
+ subs->buffer_periods = params_periods(hw_params);
subs->channels = params_channels(hw_params);
subs->cur_rate = params_rate(hw_params);
@@ -1363,6 +1369,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
frames = 0;
urb->number_of_packets = 0;
spin_lock_irqsave(&subs->lock, flags);
+ subs->frame_limit += ep->max_urb_frames;
for (i = 0; i < ctx->packets; i++) {
if (ctx->packet_size[i])
counts = ctx->packet_size[i];
@@ -1377,6 +1384,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
subs->transfer_done += counts;
if (subs->transfer_done >= runtime->period_size) {
subs->transfer_done -= runtime->period_size;
+ subs->frame_limit = 0;
period_elapsed = 1;
if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
if (subs->transfer_done > 0) {
@@ -1399,8 +1407,10 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
break;
}
}
- if (period_elapsed &&
- !snd_usb_endpoint_implicit_feedback_sink(subs->data_endpoint)) /* finish at the period boundary */
+ /* finish at the period boundary or after enough frames */
+ if ((period_elapsed ||
+ subs->transfer_done >= subs->frame_limit) &&
+ !snd_usb_endpoint_implicit_feedback_sink(ep))
break;
}
bytes = frames * ep->stride;
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index caabe9b3af49..5d2fe0530745 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -55,7 +55,6 @@ struct snd_usb_audio {
struct list_head mixer_list; /* list of mixer interfaces */
int setup; /* from the 'device_setup' module param */
- int nrpacks; /* from the 'nrpacks' module param */
bool autoclock; /* from the 'autoclock' module param */
struct usb_host_interface *ctrl_intf; /* the audio control interface */
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 8fd9ec66121c..b8d6d541d854 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -89,6 +89,7 @@ static char *processor_arch;
static char *os_build;
static char *os_version;
static char *lic_version = "Unknown version";
+static char full_domain_name[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
static struct utsname uts_buf;
/*
@@ -1367,7 +1368,7 @@ setval_error:
}
-static int
+static void
kvp_get_domain_name(char *buffer, int length)
{
struct addrinfo hints, *info ;
@@ -1381,12 +1382,12 @@ kvp_get_domain_name(char *buffer, int length)
error = getaddrinfo(buffer, NULL, &hints, &info);
if (error != 0) {
- strcpy(buffer, "getaddrinfo failed\n");
- return error;
+ snprintf(buffer, length, "getaddrinfo failed: 0x%x %s",
+ error, gai_strerror(error));
+ return;
}
- strcpy(buffer, info->ai_canonname);
+ snprintf(buffer, length, "%s", info->ai_canonname);
freeaddrinfo(info);
- return error;
}
static int
@@ -1433,7 +1434,6 @@ int main(void)
int pool;
char *if_name;
struct hv_kvp_ipaddr_value *kvp_ip_val;
- char *kvp_send_buffer;
char *kvp_recv_buffer;
size_t kvp_recv_buffer_len;
@@ -1442,17 +1442,21 @@ int main(void)
openlog("KVP", 0, LOG_USER);
syslog(LOG_INFO, "KVP starting; pid is:%d", getpid());
- kvp_recv_buffer_len = NLMSG_HDRLEN + sizeof(struct cn_msg) + sizeof(struct hv_kvp_msg);
- kvp_send_buffer = calloc(1, kvp_recv_buffer_len);
+ kvp_recv_buffer_len = NLMSG_LENGTH(0) + sizeof(struct cn_msg) + sizeof(struct hv_kvp_msg);
kvp_recv_buffer = calloc(1, kvp_recv_buffer_len);
- if (!(kvp_send_buffer && kvp_recv_buffer)) {
- syslog(LOG_ERR, "Failed to allocate netlink buffers");
+ if (!kvp_recv_buffer) {
+ syslog(LOG_ERR, "Failed to allocate netlink buffer");
exit(EXIT_FAILURE);
}
/*
* Retrieve OS release information.
*/
kvp_get_os_info();
+ /*
+ * Cache Fully Qualified Domain Name because getaddrinfo takes an
+ * unpredictable amount of time to finish.
+ */
+ kvp_get_domain_name(full_domain_name, sizeof(full_domain_name));
if (kvp_file_init()) {
syslog(LOG_ERR, "Failed to initialize the pools");
@@ -1488,7 +1492,7 @@ int main(void)
/*
* Register ourselves with the kernel.
*/
- message = (struct cn_msg *)kvp_send_buffer;
+ message = (struct cn_msg *)kvp_recv_buffer;
message->id.idx = CN_KVP_IDX;
message->id.val = CN_KVP_VAL;
@@ -1671,8 +1675,7 @@ int main(void)
switch (hv_msg->body.kvp_enum_data.index) {
case FullyQualifiedDomainName:
- kvp_get_domain_name(key_value,
- HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
+ strcpy(key_value, full_domain_name);
strcpy(key_name, "FullyQualifiedDomainName");
break;
case IntegrationServicesVersion:
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
index 8611962c672c..8bcb04096eb2 100644
--- a/tools/hv/hv_vss_daemon.c
+++ b/tools/hv/hv_vss_daemon.c
@@ -140,7 +140,6 @@ int main(void)
struct cn_msg *incoming_cn_msg;
int op;
struct hv_vss_msg *vss_msg;
- char *vss_send_buffer;
char *vss_recv_buffer;
size_t vss_recv_buffer_len;
@@ -150,10 +149,9 @@ int main(void)
openlog("Hyper-V VSS", 0, LOG_USER);
syslog(LOG_INFO, "VSS starting; pid is:%d", getpid());
- vss_recv_buffer_len = NLMSG_HDRLEN + sizeof(struct cn_msg) + sizeof(struct hv_vss_msg);
- vss_send_buffer = calloc(1, vss_recv_buffer_len);
+ vss_recv_buffer_len = NLMSG_LENGTH(0) + sizeof(struct cn_msg) + sizeof(struct hv_vss_msg);
vss_recv_buffer = calloc(1, vss_recv_buffer_len);
- if (!(vss_send_buffer && vss_recv_buffer)) {
+ if (!vss_recv_buffer) {
syslog(LOG_ERR, "Failed to allocate netlink buffers");
exit(EXIT_FAILURE);
}
@@ -185,7 +183,7 @@ int main(void)
/*
* Register ourselves with the kernel.
*/
- message = (struct cn_msg *)vss_send_buffer;
+ message = (struct cn_msg *)vss_recv_buffer;
message->id.idx = CN_VSS_IDX;
message->id.val = CN_VSS_VAL;
message->ack = 0;
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index c2dff9cb1f2c..9b5f077fee5b 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -101,7 +101,7 @@ static int setup_cpunode_map(void)
dir1 = opendir(PATH_SYS_NODE);
if (!dir1)
- return -1;
+ return 0;
while ((dent1 = readdir(dir1)) != NULL) {
if (dent1->d_type != DT_DIR ||
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index fd4853404727..71aa3e35406b 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1055,6 +1055,7 @@ static int trace__replay(struct trace *trace)
trace->tool.sample = trace__process_sample;
trace->tool.mmap = perf_event__process_mmap;
+ trace->tool.mmap2 = perf_event__process_mmap2;
trace->tool.comm = perf_event__process_comm;
trace->tool.exit = perf_event__process_exit;
trace->tool.fork = perf_event__process_fork;
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 346ee929d250..5f6f9b3271bb 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -87,7 +87,7 @@ CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -std=gnu99
-EXTLIBS = -lelf -lpthread -lrt -lm
+EXTLIBS = -lelf -lpthread -lrt -lm -ldl
ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y)
CFLAGS += -fstack-protector-all
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 933d14f287ca..6188d2876a71 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -792,7 +792,7 @@ static int machine__create_modules(struct machine *machine)
modules = path;
}
- if (symbol__restricted_filename(path, "/proc/modules"))
+ if (symbol__restricted_filename(modules, "/proc/modules"))
return -1;
file = fopen(modules, "r");
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 20c7299a9d4e..371476cb8ddc 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -118,7 +118,6 @@ static const Dwfl_Callbacks offline_callbacks = {
static int debuginfo__init_offline_dwarf(struct debuginfo *self,
const char *path)
{
- Dwfl_Module *mod;
int fd;
fd = open(path, O_RDONLY);
@@ -129,11 +128,11 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *self,
if (!self->dwfl)
goto error;
- mod = dwfl_report_offline(self->dwfl, "", "", fd);
- if (!mod)
+ self->mod = dwfl_report_offline(self->dwfl, "", "", fd);
+ if (!self->mod)
goto error;
- self->dbg = dwfl_module_getdwarf(mod, &self->bias);
+ self->dbg = dwfl_module_getdwarf(self->mod, &self->bias);
if (!self->dbg)
goto error;
@@ -676,37 +675,42 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
}
/* Convert subprogram DIE to trace point */
-static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
- bool retprobe, struct probe_trace_point *tp)
+static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
+ Dwarf_Addr paddr, bool retprobe,
+ struct probe_trace_point *tp)
{
Dwarf_Addr eaddr, highaddr;
- const char *name;
-
- /* Copy the name of probe point */
- name = dwarf_diename(sp_die);
- if (name) {
- if (dwarf_entrypc(sp_die, &eaddr) != 0) {
- pr_warning("Failed to get entry address of %s\n",
- dwarf_diename(sp_die));
- return -ENOENT;
- }
- if (dwarf_highpc(sp_die, &highaddr) != 0) {
- pr_warning("Failed to get end address of %s\n",
- dwarf_diename(sp_die));
- return -ENOENT;
- }
- if (paddr > highaddr) {
- pr_warning("Offset specified is greater than size of %s\n",
- dwarf_diename(sp_die));
- return -EINVAL;
- }
- tp->symbol = strdup(name);
- if (tp->symbol == NULL)
- return -ENOMEM;
- tp->offset = (unsigned long)(paddr - eaddr);
- } else
- /* This function has no name. */
- tp->offset = (unsigned long)paddr;
+ GElf_Sym sym;
+ const char *symbol;
+
+ /* Verify the address is correct */
+ if (dwarf_entrypc(sp_die, &eaddr) != 0) {
+ pr_warning("Failed to get entry address of %s\n",
+ dwarf_diename(sp_die));
+ return -ENOENT;
+ }
+ if (dwarf_highpc(sp_die, &highaddr) != 0) {
+ pr_warning("Failed to get end address of %s\n",
+ dwarf_diename(sp_die));
+ return -ENOENT;
+ }
+ if (paddr > highaddr) {
+ pr_warning("Offset specified is greater than size of %s\n",
+ dwarf_diename(sp_die));
+ return -EINVAL;
+ }
+
+ /* Get an appropriate symbol from symtab */
+ symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
+ if (!symbol) {
+ pr_warning("Failed to find symbol at 0x%lx\n",
+ (unsigned long)paddr);
+ return -ENOENT;
+ }
+ tp->offset = (unsigned long)(paddr - sym.st_value);
+ tp->symbol = strdup(symbol);
+ if (!tp->symbol)
+ return -ENOMEM;
/* Return probe must be on the head of a subprogram */
if (retprobe) {
@@ -1149,7 +1153,7 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
tev = &tf->tevs[tf->ntevs++];
/* Trace point should be converted from subprogram DIE */
- ret = convert_to_trace_point(&pf->sp_die, pf->addr,
+ ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr,
pf->pev->point.retprobe, &tev->point);
if (ret < 0)
return ret;
@@ -1181,7 +1185,7 @@ int debuginfo__find_trace_events(struct debuginfo *self,
{
struct trace_event_finder tf = {
.pf = {.pev = pev, .callback = add_probe_trace_event},
- .max_tevs = max_tevs};
+ .mod = self->mod, .max_tevs = max_tevs};
int ret;
/* Allocate result tevs array */
@@ -1250,7 +1254,7 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
vl = &af->vls[af->nvls++];
/* Trace point should be converted from subprogram DIE */
- ret = convert_to_trace_point(&pf->sp_die, pf->addr,
+ ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr,
pf->pev->point.retprobe, &vl->point);
if (ret < 0)
return ret;
@@ -1289,6 +1293,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *self,
{
struct available_var_finder af = {
.pf = {.pev = pev, .callback = add_available_vars},
+ .mod = self->mod,
.max_vls = max_vls, .externs = externs};
int ret;
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 17e94d0c36f9..3b7d63018960 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -23,6 +23,7 @@ static inline int is_c_varname(const char *name)
/* debug information structure */
struct debuginfo {
Dwarf *dbg;
+ Dwfl_Module *mod;
Dwfl *dwfl;
Dwarf_Addr bias;
};
@@ -77,6 +78,7 @@ struct probe_finder {
struct trace_event_finder {
struct probe_finder pf;
+ Dwfl_Module *mod; /* For solving symbols */
struct probe_trace_event *tevs; /* Found trace events */
int ntevs; /* Number of trace events */
int max_tevs; /* Max number of trace events */
@@ -84,6 +86,7 @@ struct trace_event_finder {
struct available_var_finder {
struct probe_finder pf;
+ Dwfl_Module *mod; /* For solving symbols */
struct variable_list *vls; /* Found variable lists */
int nvls; /* Number of variable lists */
int max_vls; /* Max no. of variable lists */
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index a9c829be5216..d2a888e2e058 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -928,8 +928,33 @@ int dso__load_sym(struct dso *dso, struct map *map,
* to it...
*/
if (symbol_conf.demangle) {
- demangled = bfd_demangle(NULL, elf_name,
+ /*
+ * The demangler doesn't deal with cloned functions.
+ * XXXX.clone.NUM or similar
+ * Strip the dot part and readd it later.
+ */
+ char *p = (char *)elf_name, *dot;
+ dot = strchr(elf_name, '.');
+ if (dot) {
+ p = strdup(elf_name);
+ if (!p)
+ goto new_symbol;
+ dot = strchr(p, '.');
+ *dot = 0;
+ }
+
+ demangled = bfd_demangle(NULL, p,
DMGL_PARAMS | DMGL_ANSI);
+ if (dot)
+ *dot = '.';
+ if (demangled && dot) {
+ demangled = realloc(demangled, strlen(demangled) + strlen(dot) + 1);
+ if (!demangled)
+ goto new_symbol;
+ strcpy(demangled + (dot - p), dot);
+ }
+ if (p != elf_name)
+ free(p);
if (demangled != NULL)
elf_name = demangled;
}
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index fe702076ca46..2bb8bf506681 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -2,7 +2,7 @@
* turbostat -- show CPU frequency and C-state residency
* on modern Intel turbo-capable processors.
*
- * Copyright (c) 2012 Intel Corporation.
+ * Copyright (c) 2013 Intel Corporation.
* Len Brown <len.brown@intel.com>
*
* This program is free software; you can redistribute it and/or modify it
@@ -47,6 +47,8 @@ unsigned int skip_c1;
unsigned int do_nhm_cstates;
unsigned int do_snb_cstates;
unsigned int do_c8_c9_c10;
+unsigned int do_slm_cstates;
+unsigned int use_c1_residency_msr;
unsigned int has_aperf;
unsigned int has_epb;
unsigned int units = 1000000000; /* Ghz etc */
@@ -81,6 +83,8 @@ double rapl_joule_counter_range;
#define RAPL_DRAM (1 << 3)
#define RAPL_PKG_PERF_STATUS (1 << 4)
#define RAPL_DRAM_PERF_STATUS (1 << 5)
+#define RAPL_PKG_POWER_INFO (1 << 6)
+#define RAPL_CORE_POLICY (1 << 7)
#define TJMAX_DEFAULT 100
#define MAX(a, b) ((a) > (b) ? (a) : (b))
@@ -96,7 +100,7 @@ struct thread_data {
unsigned long long tsc;
unsigned long long aperf;
unsigned long long mperf;
- unsigned long long c1; /* derived */
+ unsigned long long c1;
unsigned long long extra_msr64;
unsigned long long extra_delta64;
unsigned long long extra_msr32;
@@ -266,7 +270,7 @@ void print_header(void)
outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset64);
if (do_nhm_cstates)
outp += sprintf(outp, " %%c1");
- if (do_nhm_cstates)
+ if (do_nhm_cstates && !do_slm_cstates)
outp += sprintf(outp, " %%c3");
if (do_nhm_cstates)
outp += sprintf(outp, " %%c6");
@@ -280,9 +284,9 @@ void print_header(void)
if (do_snb_cstates)
outp += sprintf(outp, " %%pc2");
- if (do_nhm_cstates)
+ if (do_nhm_cstates && !do_slm_cstates)
outp += sprintf(outp, " %%pc3");
- if (do_nhm_cstates)
+ if (do_nhm_cstates && !do_slm_cstates)
outp += sprintf(outp, " %%pc6");
if (do_snb_cstates)
outp += sprintf(outp, " %%pc7");
@@ -480,7 +484,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
goto done;
- if (do_nhm_cstates)
+ if (do_nhm_cstates && !do_slm_cstates)
outp += sprintf(outp, " %6.2f", 100.0 * c->c3/t->tsc);
if (do_nhm_cstates)
outp += sprintf(outp, " %6.2f", 100.0 * c->c6/t->tsc);
@@ -499,9 +503,9 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (do_snb_cstates)
outp += sprintf(outp, " %6.2f", 100.0 * p->pc2/t->tsc);
- if (do_nhm_cstates)
+ if (do_nhm_cstates && !do_slm_cstates)
outp += sprintf(outp, " %6.2f", 100.0 * p->pc3/t->tsc);
- if (do_nhm_cstates)
+ if (do_nhm_cstates && !do_slm_cstates)
outp += sprintf(outp, " %6.2f", 100.0 * p->pc6/t->tsc);
if (do_snb_cstates)
outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc);
@@ -648,17 +652,24 @@ delta_thread(struct thread_data *new, struct thread_data *old,
}
- /*
- * As counter collection is not atomic,
- * it is possible for mperf's non-halted cycles + idle states
- * to exceed TSC's all cycles: show c1 = 0% in that case.
- */
- if ((old->mperf + core_delta->c3 + core_delta->c6 + core_delta->c7) > old->tsc)
- old->c1 = 0;
- else {
- /* normal case, derive c1 */
- old->c1 = old->tsc - old->mperf - core_delta->c3
+ if (use_c1_residency_msr) {
+ /*
+ * Some models have a dedicated C1 residency MSR,
+ * which should be more accurate than the derivation below.
+ */
+ } else {
+ /*
+ * As counter collection is not atomic,
+ * it is possible for mperf's non-halted cycles + idle states
+ * to exceed TSC's all cycles: show c1 = 0% in that case.
+ */
+ if ((old->mperf + core_delta->c3 + core_delta->c6 + core_delta->c7) > old->tsc)
+ old->c1 = 0;
+ else {
+ /* normal case, derive c1 */
+ old->c1 = old->tsc - old->mperf - core_delta->c3
- core_delta->c6 - core_delta->c7;
+ }
}
if (old->mperf == 0) {
@@ -872,13 +883,21 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, extra_msr_offset64, &t->extra_msr64))
return -5;
+ if (use_c1_residency_msr) {
+ if (get_msr(cpu, MSR_CORE_C1_RES, &t->c1))
+ return -6;
+ }
+
/* collect core counters only for 1st thread in core */
if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
return 0;
- if (do_nhm_cstates) {
+ if (do_nhm_cstates && !do_slm_cstates) {
if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3))
return -6;
+ }
+
+ if (do_nhm_cstates) {
if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6))
return -7;
}
@@ -898,7 +917,7 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
return 0;
- if (do_nhm_cstates) {
+ if (do_nhm_cstates && !do_slm_cstates) {
if (get_msr(cpu, MSR_PKG_C3_RESIDENCY, &p->pc3))
return -9;
if (get_msr(cpu, MSR_PKG_C6_RESIDENCY, &p->pc6))
@@ -1046,25 +1065,28 @@ print_nhm_turbo_ratio_limits:
switch(msr & 0x7) {
case 0:
- fprintf(stderr, "pc0");
+ fprintf(stderr, do_slm_cstates ? "no pkg states" : "pc0");
break;
case 1:
- fprintf(stderr, do_snb_cstates ? "pc2" : "pc0");
+ fprintf(stderr, do_slm_cstates ? "no pkg states" : do_snb_cstates ? "pc2" : "pc0");
break;
case 2:
- fprintf(stderr, do_snb_cstates ? "pc6-noret" : "pc3");
+ fprintf(stderr, do_slm_cstates ? "invalid" : do_snb_cstates ? "pc6-noret" : "pc3");
break;
case 3:
- fprintf(stderr, "pc6");
+ fprintf(stderr, do_slm_cstates ? "invalid" : "pc6");
break;
case 4:
- fprintf(stderr, "pc7");
+ fprintf(stderr, do_slm_cstates ? "pc4" : "pc7");
break;
case 5:
- fprintf(stderr, do_snb_cstates ? "pc7s" : "invalid");
+ fprintf(stderr, do_slm_cstates ? "invalid" : do_snb_cstates ? "pc7s" : "invalid");
+ break;
+ case 6:
+ fprintf(stderr, do_slm_cstates ? "pc6" : "invalid");
break;
case 7:
- fprintf(stderr, "unlimited");
+ fprintf(stderr, do_slm_cstates ? "pc7" : "unlimited");
break;
default:
fprintf(stderr, "invalid");
@@ -1460,6 +1482,7 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
case 0x3F: /* HSW */
case 0x45: /* HSW */
case 0x46: /* HSW */
+ case 0x4D: /* AVN */
return 1;
case 0x2E: /* Nehalem-EX Xeon - Beckton */
case 0x2F: /* Westmere-EX Xeon - Eagleton */
@@ -1555,11 +1578,14 @@ void rapl_probe(unsigned int family, unsigned int model)
case 0x3F: /* HSW */
case 0x45: /* HSW */
case 0x46: /* HSW */
- do_rapl = RAPL_PKG | RAPL_CORES | RAPL_GFX;
+ do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO;
break;
case 0x2D:
case 0x3E:
- do_rapl = RAPL_PKG | RAPL_CORES | RAPL_DRAM | RAPL_PKG_PERF_STATUS | RAPL_DRAM_PERF_STATUS;
+ do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_PKG_PERF_STATUS | RAPL_DRAM_PERF_STATUS | RAPL_PKG_POWER_INFO;
+ break;
+ case 0x4D: /* AVN */
+ do_rapl = RAPL_PKG | RAPL_CORES ;
break;
default:
return;
@@ -1573,17 +1599,18 @@ void rapl_probe(unsigned int family, unsigned int model)
rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F));
rapl_time_units = 1.0 / (1 << (msr >> 16 & 0xF));
- /* get TDP to determine energy counter range */
- if (get_msr(0, MSR_PKG_POWER_INFO, &msr))
- return;
+ if (do_rapl & RAPL_PKG_POWER_INFO) {
+ /* get TDP to determine energy counter range */
+ if (get_msr(0, MSR_PKG_POWER_INFO, &msr))
+ return;
- tdp = ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units;
+ tdp = ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units;
- rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
-
- if (verbose)
- fprintf(stderr, "RAPL: %.0f sec. Joule Counter Range\n", rapl_joule_counter_range);
+ rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
+ if (verbose)
+ fprintf(stderr, "RAPL: %.0f sec. Joule Counter Range\n", rapl_joule_counter_range);
+ }
return;
}
@@ -1702,7 +1729,8 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
"(%f Watts, %f Joules, %f sec.)\n", cpu, msr,
local_rapl_power_units, local_rapl_energy_units, local_rapl_time_units);
}
- if (do_rapl & RAPL_PKG) {
+ if (do_rapl & RAPL_PKG_POWER_INFO) {
+
if (get_msr(cpu, MSR_PKG_POWER_INFO, &msr))
return -5;
@@ -1714,6 +1742,9 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units,
((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units);
+ }
+ if (do_rapl & RAPL_PKG) {
+
if (get_msr(cpu, MSR_PKG_POWER_LIMIT, &msr))
return -9;
@@ -1749,12 +1780,16 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
print_power_limit_msr(cpu, msr, "DRAM Limit");
}
- if (do_rapl & RAPL_CORES) {
+ if (do_rapl & RAPL_CORE_POLICY) {
if (verbose) {
if (get_msr(cpu, MSR_PP0_POLICY, &msr))
return -7;
fprintf(stderr, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF);
+ }
+ }
+ if (do_rapl & RAPL_CORES) {
+ if (verbose) {
if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr))
return -9;
@@ -1813,10 +1848,47 @@ int has_c8_c9_c10(unsigned int family, unsigned int model)
}
+int is_slm(unsigned int family, unsigned int model)
+{
+ if (!genuine_intel)
+ return 0;
+ switch (model) {
+ case 0x4D: /* AVN */
+ return 1;
+ }
+ return 0;
+}
+
+#define SLM_BCLK_FREQS 5
+double slm_freq_table[SLM_BCLK_FREQS] = { 83.3, 100.0, 133.3, 116.7, 80.0};
+
+double slm_bclk(void)
+{
+ unsigned long long msr = 3;
+ unsigned int i;
+ double freq;
+
+ if (get_msr(0, MSR_FSB_FREQ, &msr))
+ fprintf(stderr, "SLM BCLK: unknown\n");
+
+ i = msr & 0xf;
+ if (i >= SLM_BCLK_FREQS) {
+ fprintf(stderr, "SLM BCLK[%d] invalid\n", i);
+ msr = 3;
+ }
+ freq = slm_freq_table[i];
+
+ fprintf(stderr, "SLM BCLK: %.1f Mhz\n", freq);
+
+ return freq;
+}
+
double discover_bclk(unsigned int family, unsigned int model)
{
if (is_snb(family, model))
return 100.00;
+ else if (is_slm(family, model))
+ return slm_bclk();
else
return 133.33;
}
@@ -1873,7 +1945,7 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk
fprintf(stderr, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n",
cpu, msr, target_c_local);
- if (target_c_local < 85 || target_c_local > 120)
+ if (target_c_local < 85 || target_c_local > 127)
goto guess;
tcc_activation_temp = target_c_local;
@@ -1970,6 +2042,7 @@ void check_cpuid()
do_smi = do_nhm_cstates;
do_snb_cstates = is_snb(family, model);
do_c8_c9_c10 = has_c8_c9_c10(family, model);
+ do_slm_cstates = is_slm(family, model);
bclk = discover_bclk(family, model);
do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model);
@@ -2331,7 +2404,7 @@ int main(int argc, char **argv)
cmdline(argc, argv);
if (verbose)
- fprintf(stderr, "turbostat v3.4 April 17, 2013"
+ fprintf(stderr, "turbostat v3.5 April 26, 2013"
" - Len Brown <lenb@kernel.org>\n");
turbostat_init();
diff --git a/tools/testing/ktest/examples/crosstests.conf b/tools/testing/ktest/examples/crosstests.conf
index 46736604c26c..a1203148dfa1 100644
--- a/tools/testing/ktest/examples/crosstests.conf
+++ b/tools/testing/ktest/examples/crosstests.conf
@@ -133,12 +133,6 @@ CROSS = frv-linux
ARCH = frv
GCC_VER = 4.5.1
-# h8300 - failed make defconfig??
-TEST_START IF ${RUN} == h8300 || ${DO_FAILED}
-CROSS = h8300-elf
-ARCH = h8300
-GCC_VER = 4.5.1
-
# m68k fails with error?
TEST_START IF ${RUN} == m68k || ${DO_DEFAULT}
CROSS = m68k-linux
diff --git a/virt/kvm/async_pf.c b/virt/kvm/async_pf.c
index 8a39dda7a325..b197950ac4d5 100644
--- a/virt/kvm/async_pf.c
+++ b/virt/kvm/async_pf.c
@@ -75,7 +75,6 @@ static void async_pf_execute(struct work_struct *work)
spin_lock(&vcpu->async_pf.lock);
list_add_tail(&apf->link, &vcpu->async_pf.done);
apf->page = page;
- apf->done = true;
spin_unlock(&vcpu->async_pf.lock);
/*
@@ -99,9 +98,8 @@ void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu)
struct kvm_async_pf *work =
list_entry(vcpu->async_pf.queue.next,
typeof(*work), queue);
- cancel_work_sync(&work->work);
list_del(&work->queue);
- if (!work->done) { /* work was canceled */
+ if (cancel_work_sync(&work->work)) {
mmdrop(work->mm);
kvm_put_kvm(vcpu->kvm); /* == work->vcpu->kvm */
kmem_cache_free(async_pf_cache, work);
@@ -166,7 +164,6 @@ int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn,
return 0;
work->page = NULL;
- work->done = false;
work->vcpu = vcpu;
work->gva = gva;
work->addr = gfn_to_hva(vcpu->kvm, gfn);